PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/javascript/shared-package/topics.js

https://bitbucket.org/lmeius/lehor
JavaScript | 329 lines | 259 code | 56 blank | 14 comment | 20 complexity | 31a59e4e3fec2ce07e567d9960b79509 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, CC-BY-3.0, GPL-3.0
  1. // These models can automatically fetch the tree incrementally
  2. // using API calls during traversal. Note that the fetchByID()
  3. // call may be either synchronous or asynchronous, depending on
  4. // whether the model is already in the cache.
  5. window.TestTopics = function() {
  6. var tree = getDefaultTopicTree();
  7. KAConsole.log("Fetching root...");
  8. tree.fetchByID("root",
  9. function() {
  10. KAConsole.log("Got root. Fetching first child...");
  11. tree.fetchByID(this.get("children")[0].id,
  12. function() {
  13. KAConsole.log("Got child topic:", this);
  14. }
  15. );
  16. }
  17. );
  18. };
  19. // Model for a TopicVersion
  20. (function() {
  21. var topicVersionList = null;
  22. window.TopicVersion = Backbone.Model.extend({
  23. defaults: {
  24. number: 0, // API ID
  25. kind: "TopicVersion",
  26. "default": false, // Is the current default version
  27. edit: false, // Is the current editing version
  28. title: "(untitled version)",
  29. last_edited_by: "",
  30. description: "",
  31. created_on: "",
  32. updated_on: ""
  33. },
  34. idAttribute: "number",
  35. urlRoot: "/api/v1/topicversion",
  36. initialize: function() {
  37. this._topicTree = new TopicTree(this);
  38. },
  39. getTopicTree: function() {
  40. return this._topicTree;
  41. }
  42. });
  43. window.TopicVersionList = IncrementalCollection.extend({
  44. model: TopicVersion,
  45. url: "/api/v1/topicversions/"
  46. });
  47. window.getTopicVersionList = function() {
  48. topicVersionList = topicVersionList || new TopicVersionList();
  49. return topicVersionList;
  50. };
  51. })();
  52. // Model/collection for Topics
  53. (function() {
  54. var defaultTree = null;
  55. window.Topic = Backbone.Model.extend({
  56. defaults: {
  57. // Short version
  58. id: "new_topic", // API ID / slug
  59. title: "New Topic",
  60. standalone_title: "New Topic",
  61. kind: "Topic",
  62. // Long version
  63. description: "",
  64. hide: false,
  65. ka_url: "",
  66. tags: [],
  67. children: []
  68. },
  69. initialize: function() {
  70. },
  71. url: function() {
  72. var versionID = this.collection ? this.collection.getVersionID() : "edit";
  73. return "/api/v1/topicversion/" + versionID + "/topic/" + this.id;
  74. },
  75. getChildren: function() {
  76. var self = this;
  77. return _.map(this.get("children"), function(child) { return self.tree.get(child.id); });
  78. },
  79. addChild: function(child, idx) {
  80. var child_list = this.get("children").slice(0);
  81. child_list.splice(idx, 0, child);
  82. this.set({"children": child_list});
  83. },
  84. removeChild: function(kind, id) {
  85. var ret = null;
  86. var child_list = _.filter(this.get("children"), function(child) {
  87. if (child.kind != kind || child.id != id) {
  88. return true;
  89. }
  90. ret = child;
  91. return false;
  92. });
  93. this.set({"children": child_list});
  94. return ret;
  95. },
  96. updateNode: function() {
  97. var tree = this.tree;
  98. // Insert "placeholder" nodes into tree so we can track changes
  99. _.each(this.get("children"), function(child) {
  100. if (child.kind == "Topic" && !tree.get(child.id)) {
  101. var newNode = new Topic(child);
  102. tree.addNode(newNode);
  103. child.__ptr = newNode;
  104. }
  105. });
  106. // Update child lists
  107. tree.each(function(otherNode) {
  108. var children = _.map(otherNode.get("children"), function(child) {
  109. if (child.__ptr && child.__ptr.__inited) {
  110. return {
  111. kind: child.kind,
  112. __ptr: child.__ptr,
  113. id: child.__ptr.id,
  114. title: child.__ptr.get("title"),
  115. hide: child.__ptr.get("hide")
  116. };
  117. } else {
  118. return child;
  119. }
  120. });
  121. otherNode.set({children: children});
  122. });
  123. }
  124. });
  125. window.TopicTree = IncrementalCollection.extend({
  126. model: Topic,
  127. version: null,
  128. initialize: function(version) {
  129. this.version = version;
  130. },
  131. getRoot: function() {
  132. var ret = this.fetchByID("root");
  133. if (!ret.__inited) {
  134. ret.set({title: "Loading..."});
  135. }
  136. return ret;
  137. },
  138. addNode: function(node) {
  139. KAConsole.log("Adding node to tree: " + node.get("id"));
  140. node.tree = this;
  141. this.add([ node ]);
  142. node.bind("change", node.updateNode, node);
  143. },
  144. getVersionID: function() {
  145. return _.isString(this.version) ? this.version : this.version.get("number");
  146. }
  147. });
  148. var itemIDTable = {
  149. Topic: "id",
  150. Video: "readable_id",
  151. Exercise: "name",
  152. Url: "id"
  153. };
  154. var itemTitleTable = {
  155. Topic: "title",
  156. Video: "title",
  157. Exercise: "display_name",
  158. Url: "title"
  159. };
  160. var itemHideTable = {
  161. Topic: "hide"
  162. };
  163. // Utility class to wrap a Video/Exercise/URL model with accessors for the common fields id/title/etc.
  164. window.TopicChild = function(childModel) {
  165. if (childModel instanceof Backbone.Model) {
  166. this.model = childModel.toJSON();
  167. } else {
  168. this.model = childModel;
  169. }
  170. this.kind = this.model.kind;
  171. this.id = this.model[itemIDTable[this.model.kind]];
  172. this.title = this.model[itemTitleTable[this.model.kind]];
  173. if (itemHideTable[this.model.kind]) {
  174. this.hide = this.model[itemHideTable[this.model.kind]];
  175. } else {
  176. this.hide = false;
  177. }
  178. };
  179. window.getDefaultTopicTree = function() {
  180. defaultTree = defaultTree || new TopicTree("default");
  181. return defaultTree;
  182. };
  183. })();
  184. // Model/collection for Videos
  185. (function() {
  186. var videoList = null;
  187. window.Video = Backbone.Model.extend({
  188. defaults: {
  189. readable_id: "", // API ID / slug
  190. kind: "Video",
  191. title: "",
  192. youtube_id: "",
  193. description: "",
  194. keywords: "",
  195. duration: 0,
  196. views: 0,
  197. date_added: "",
  198. url: "",
  199. ka_url: "",
  200. relative_url: "",
  201. download_urls: null
  202. },
  203. idAttribute: "readable_id",
  204. initialize: function(version) {
  205. this.version = version;
  206. },
  207. urlRoot: "/api/v1/topicversion/edit/videos",
  208. });
  209. window.VideoList = IncrementalCollection.extend({
  210. model: Video
  211. });
  212. window.getVideoList = function() {
  213. videoList = videoList || new VideoList();
  214. return videoList;
  215. };
  216. })();
  217. // Model/collection for Exercises
  218. (function() {
  219. var exerciseList = null;
  220. window.Exercise = Backbone.Model.extend({
  221. defaults: {
  222. name: "new_exercise", // API ID / slug
  223. kind: "Exercise",
  224. display_name: "New Exercise",
  225. short_display_name: "New Ex",
  226. creation_date: "",
  227. h_position: 0,
  228. v_position: 0,
  229. live: false,
  230. summative: false,
  231. num_milestones: 0,
  232. seconds_per_fast_problem: 0,
  233. covers: [],
  234. prerequisites: [],
  235. ka_url: "",
  236. relative_url: "",
  237. description: "",
  238. tags: []
  239. },
  240. idAttribute: "name",
  241. urlRoot: "/api/v1/topicversion/edit/exercises"
  242. });
  243. window.ExerciseList = IncrementalCollection.extend({
  244. model: Exercise
  245. });
  246. window.getExerciseList = function() {
  247. exerciseList = exerciseList || new ExerciseList();
  248. return exerciseList;
  249. };
  250. })();
  251. // Model/collection for URLs
  252. (function() {
  253. var urlList = null;
  254. window.ExternalURL = Backbone.Model.extend({
  255. defaults: {
  256. id: "", // API ID
  257. kind: "Url",
  258. url: "",
  259. title: "New URL",
  260. tags: [],
  261. created_on: "",
  262. updated_on: ""
  263. },
  264. urlRoot: "/api/v1/topicversion/edit/url"
  265. });
  266. window.URLList = IncrementalCollection.extend({
  267. model: ExternalURL
  268. });
  269. window.getUrlList = function() {
  270. urlList = urlList || new URLList();
  271. return urlList;
  272. };
  273. })();