PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/app/django/timetables/static/js/view/student/modules.js

https://bitbucket.org/td324/timetables-prototype-caret
JavaScript | 286 lines | 236 code | 47 blank | 3 comment | 25 complexity | fd59ad599c52ab15b30d2911a2acf4b7 MD5 | raw file
  1. define([
  2. "jquery",
  3. "underscore",
  4. "backbone",
  5. "util/underscore-mixins"
  6. ], function ($, _, Backbone) {
  7. "use strict";
  8. var ModulesList = Backbone.View.extend({
  9. initialize: function (opts) {
  10. if (opts.thingPath) {
  11. this.thingPath = opts.thingPath;
  12. } else {
  13. throw new Error("Please provide a thingpath for the modules list to work.");
  14. }
  15. if (opts.crsfToken) {
  16. this.crsfToken = opts.crsfToken;
  17. } else {
  18. throw new Error("Please provide a crsfToken for modules list to work.");
  19. }
  20. _.bindAll(this, "updateList");
  21. },
  22. events: {
  23. "click a.js-more" : "moreClickHandler",
  24. "click a.js-less" : "lessClickHandler",
  25. "click a.js-btn-add, a.js-btn-remove" : "moduleButtonClickHandler"
  26. },
  27. associate: function ($source, add) {
  28. var self = this;
  29. var sourcepath = this.thingPath;
  30. var crsf = this.crsfToken;
  31. var postdata = {};
  32. if ( add ) {
  33. postdata.t = $source.attr("data-fullpath");
  34. postdata.es = $source.attr("data-eventsourceid");
  35. postdata.e = $source.attr("data-eventid");
  36. } else {
  37. postdata.td = $source.attr("data-fullpath");
  38. postdata.esd = $source.attr("data-eventsourceid");
  39. postdata.ed = $source.attr("data-eventid");
  40. }
  41. postdata.csrfmiddlewaretoken = crsf;
  42. $.post(sourcepath+".link", postdata, function() {
  43. self.updateButtonStates($source);
  44. _.dispatchEvent(self, "timetableUpdated");
  45. }).error(function(response, status, error) {
  46. console.log("Status code is "+response.status+" error:"+error);
  47. if ( response.status === 403 ) {
  48. $("#signinModal").modal("show");
  49. } else {
  50. $("#errorModal").modal("show");
  51. }
  52. });
  53. },
  54. updateButtonStates: function ($source) {
  55. if ($source.is(".js-btn-module-level")) {
  56. this.toggleButtonState($source.parent().parent().find("a.btn"), $source.is(".js-btn-add"));
  57. } else {
  58. this.toggleButtonState($source, $source.is(".js-btn-add"));
  59. if ($source.parent().parent().is(".courseMoreInfo")) {
  60. if ($source.parent().parent().find(".js-btn-add").length <= 0) {
  61. this.toggleButtonState($source.parent().parent().parent().find(".js-btn-add.js-btn-module-level"), true);
  62. } else {
  63. this.toggleButtonState($source.parent().parent().parent().find(".js-btn-remove.js-btn-module-level"), false);
  64. }
  65. }
  66. }
  67. },
  68. toggleButtonState: function ($btn, fromAdd) {
  69. if (fromAdd === true) {
  70. $btn.removeClass("js-btn-add btn-success").addClass("js-btn-remove btn-danger").text("Remove");
  71. } else {
  72. $btn.removeClass("js-btn-remove btn-danger").addClass("js-btn-add btn-success").text("Add");
  73. }
  74. },
  75. moduleButtonClickHandler: function (event) {
  76. var $target = $(event.currentTarget);
  77. if ($target.is(".js-btn-module-level")) {
  78. this.associate($target.parent().parent().find("a.btn"), $target.is(".js-btn-add"));
  79. } else {
  80. this.associate($target, $target.is(".js-btn-add"));
  81. }
  82. return false;
  83. },
  84. updatePersonalTimetable: function (postData, callback) {
  85. var self = this;
  86. postData.crsfmiddlewatetoken = this.crsfToken;
  87. $.ajax({
  88. type: "POST",
  89. data: postData,
  90. url: self.thingPath + ".link",
  91. success: function () {
  92. if (typeof callback === "function") {
  93. callback.call();
  94. }
  95. console.log("Timetable update success:", arguments);
  96. },
  97. error: function () {
  98. if (typeof callback === "function") {
  99. callback.call();
  100. }
  101. console.log("Timetable update error:", arguments);
  102. }
  103. });
  104. this.trigger("timetableUpdated");
  105. },
  106. lessClickHandler: function (event) {
  107. var $target = $(event.currentTarget);
  108. $target.removeClass("js-less").addClass("js-more");
  109. $target.text("more");
  110. //$(".courseMoreInfo", $target.parent().parent()).stop().slideUp("fast");
  111. $(".courseMoreInfo", $target.parent().parent()).slideUp("fast");
  112. return false;
  113. },
  114. moreClickHandler: function (event) {
  115. var $target = $(event.currentTarget);
  116. $target.removeClass("js-more").addClass("js-less");
  117. $target.text("show less");
  118. //$(".courseMoreInfo", $target.parent().parent()).stop().hide().slideDown("fast");
  119. $(".courseMoreInfo", $target.parent().parent()).slideDown("fast");
  120. return false;
  121. },
  122. updateList: function (fullpath) {
  123. var self = this;
  124. $.ajax({
  125. url: "/" + fullpath + ".children.html?t=" + encodeURIComponent(self.thingPath),
  126. type: "GET",
  127. success: function (data) {
  128. var modulesFound = self.$(".js-modules-list").empty().append(data).find("> li").length,
  129. modulesFoundText = "Found " + modulesFound + " modules";
  130. if (modulesFound === 1) {
  131. modulesFoundText = "Found 1 module";
  132. }
  133. self.updateModulesFoundText(modulesFoundText);
  134. },
  135. error: function () {
  136. //TODO handle errors in the modules panel
  137. console.log(arguments);
  138. self.$(".js-modules-list").empty();
  139. }
  140. });
  141. },
  142. updateModulesFoundText: function (to) {
  143. this.$(".js-modules-found h3").text(to);
  144. },
  145. setHeight: function (height) {
  146. this.$el.height(height);
  147. }
  148. });
  149. var ModulesSelector = Backbone.View.extend({
  150. initialize: function () {
  151. this.$moduleSelect = this.$(".js-module-select");
  152. this.$partSelect = this.$(".js-part-select");
  153. },
  154. events: {
  155. "change .js-module-select" : "moduleChangedHandler",
  156. "change .js-part-select" : "partChangedHandler"
  157. },
  158. moduleChangedHandler: function () {
  159. var selectedOption = this.$moduleSelect.find("option:selected");
  160. this.renderPartsSelect(selectedOption.data("levels"));
  161. this.partChangedHandler();
  162. },
  163. partChangedHandler: function () {
  164. this.trigger("partChanged", this.$partSelect.val());
  165. },
  166. renderPartsSelect: function (levels) {
  167. var i;
  168. $("option:not(:disabled)", this.$partSelect).remove();
  169. for (i = 0; i < levels.length; i += 1) {
  170. this.$partSelect.append(this.htmlForLevel(levels[i]));
  171. }
  172. },
  173. getSelectedModuleOptionFromFullpath: function (fullpath) {
  174. return $(_.filter($("option", this.$moduleSelect), function (option) {
  175. return _.any($(option).data("levels"), function (levelObj) {
  176. return levelObj.fullpath === fullpath;
  177. });
  178. }));
  179. },
  180. setSelectsFromFullpath: function (fullpath) {
  181. if (this.$partSelect.val() !== fullpath) {
  182. var $selectedOption = this.getSelectedModuleOptionFromFullpath(fullpath);
  183. this.$moduleSelect.val($selectedOption.val());
  184. this.renderPartsSelect($selectedOption.data("levels"));
  185. this.$partSelect.val(fullpath);
  186. }
  187. },
  188. htmlForLevel: function (levelData) {
  189. var $option = $("<option />");
  190. $option.attr("value", levelData.fullpath);
  191. $option.text(levelData.level_name);
  192. return $option;
  193. }
  194. });
  195. var ListView = Backbone.View.extend({
  196. initialize: function (opts) {
  197. if (!opts.thingPath) {
  198. throw new Error("ListView needs a thingpath to work correctly");
  199. } else {
  200. this.thingPath = opts.thingPath;
  201. }
  202. },
  203. setActiveDate: function (activeDate) {
  204. if (this.activeDate !== activeDate) {
  205. this.activeDate = activeDate;
  206. this.render();
  207. }
  208. },
  209. show: function () {
  210. this.$el.show();
  211. },
  212. hide: function () {
  213. this.$el.hide();
  214. },
  215. render: function () {
  216. var self = this;
  217. $.ajax({
  218. url: self.thingPath + ".callist.html",
  219. type: "GET",
  220. data: {
  221. "y": self.activeDate.getFullYear(),
  222. "m" : self.activeDate.getMonth() + 1
  223. },
  224. success: function (response) {
  225. self.$el.empty().append(response);
  226. },
  227. error: function () {
  228. console.log("list view data not fetched");
  229. console.log(arguments);
  230. }
  231. });
  232. }
  233. });
  234. return {
  235. ModulesList: ModulesList,
  236. ModulesSelector: ModulesSelector,
  237. ListView: ListView
  238. };
  239. });