PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/javascript/profile-package/profile-goals.js

https://bitbucket.org/pandapanda/debastabiilne
JavaScript | 209 lines | 168 code | 26 blank | 15 comment | 25 complexity | 8cf46c529071dd5f9b6ab1c2040b10c3 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, CC-BY-3.0, GPL-3.0
  1. var GoalProfileView = Backbone.View.extend({
  2. template: Templates.get("profile.profile-goals"),
  3. needsRerender: true,
  4. initialize: function() {
  5. this.model.bind("change", this.render, this);
  6. this.model.bind("reset", this.render, this);
  7. this.model.bind("remove", this.render, this);
  8. this.model.bind("add", this.render, this);
  9. // only hookup event handlers if the view allows edits
  10. if (this.options.readonly) {
  11. return;
  12. }
  13. $(this.el)
  14. // edit titles
  15. .delegate("input.goal-title", "focusout", $.proxy(this.changeTitle, this))
  16. .delegate("input.goal-title", "keypress", $.proxy(function(e) {
  17. if (e.which == "13") { // enter
  18. e.preventDefault();
  19. this.changeTitle(e);
  20. $(e.target).blur();
  21. }
  22. }, this))
  23. .delegate("input.goal-title", "keyup", $.proxy(function(e) {
  24. if (e.which == "27") { // escape
  25. e.preventDefault();
  26. // restore old title
  27. var jel = $(e.target);
  28. var goal = this.model.get(jel.closest(".goal").data("id"));
  29. jel.val(goal.get("title"));
  30. jel.blur();
  31. }
  32. }, this))
  33. // show abandon button on hover
  34. .delegate(".goal", "mouseenter mouseleave", function(e) {
  35. var el = $(e.currentTarget);
  36. if (e.type == "mouseenter") {
  37. el.find(".goal-description .summary-light").hide();
  38. el.find(".goal-description .goal-controls").show();
  39. } else {
  40. el.find(".goal-description .goal-controls").hide();
  41. el.find(".goal-description .summary-light").show();
  42. }
  43. })
  44. // respond to abandon button
  45. .delegate(".abandon", "click", $.proxy(this.abandon, this));
  46. },
  47. changeTitle: function(e, options) {
  48. var jel = $(e.target);
  49. var goal = this.model.get(jel.closest(".goal").data("id"));
  50. var newTitle = jel.val();
  51. if (newTitle !== goal.get("title")) {
  52. goal.save({title: newTitle});
  53. }
  54. },
  55. show: function() {
  56. // render if necessary
  57. if (this.needsRerender) {
  58. this.render();
  59. }
  60. return $(this.el).show();
  61. },
  62. hide: function() {
  63. $(this.el).hide();
  64. },
  65. render: function() {
  66. var jel = $(this.el);
  67. // delay rendering until the view is actually visible
  68. this.needsRerender = false;
  69. var json = _.pluck(this.model.models, "attributes");
  70. jel.html(this.template({
  71. goals: json,
  72. isCurrent: (this.options.type == "current"),
  73. isCompleted: (this.options.type == "completed"),
  74. isAbandoned: (this.options.type == "abandoned"),
  75. readonly: this.options.readonly,
  76. colors: this.options.colors
  77. }));
  78. // attach a NewGoalView to the new goals html
  79. var newGoalEl = this.$(".goalpicker");
  80. if (newGoalEl.length > 0) {
  81. this.newGoalsView = new NewGoalView({
  82. el: newGoalEl,
  83. model: this.model
  84. });
  85. }
  86. Profile.AddObjectiveHover(jel);
  87. return jel;
  88. },
  89. abandon: function(evt) {
  90. var goalEl = $(evt.target).closest(".goal");
  91. var goal = this.model.get(goalEl.data("id"));
  92. if (!goal) {
  93. // haven't yet received a reponse from the server after creating the
  94. // goal. Shouldn't happen too often, so just show a message.
  95. alert("Please wait a few seconds and try again. If this is the second time you've seen this message, reload the page");
  96. return;
  97. }
  98. if (confirm("Abandoning a goal is permanent and cannot be undone. Do you really want to abandon this goal?")) {
  99. // move the model to the abandoned collection
  100. this.model.remove(goal);
  101. goal.set({"abandoned": true});
  102. AbandonedGoalBook.add(goal);
  103. // persist to server
  104. goal.save().fail(function() {
  105. KAConsole.log("Warning: failed to abandon goal", goal);
  106. AbandonedGoalBook.remove(goal);
  107. this.model.add(goal);
  108. });
  109. }
  110. }
  111. });
  112. var GoalProfileViewsCollection = {
  113. views: {},
  114. render: function(data) {
  115. var viewingOwnGoals = Profile.profile.get("isSelf"),
  116. current_goals = [],
  117. completed_goals = [],
  118. abandoned_goals = [];
  119. $.each(data, function(idx, goal) {
  120. if (goal.completed) {
  121. if (goal.abandoned) {
  122. abandoned_goals.push(goal);
  123. } else {
  124. completed_goals.push(goal);
  125. }
  126. } else {
  127. current_goals.push(goal);
  128. }
  129. });
  130. if (viewingOwnGoals) {
  131. GoalBook.reset(current_goals);
  132. } else {
  133. CurrentGoalBook = new GoalCollection(current_goals);
  134. }
  135. CompletedGoalBook = new GoalCollection(completed_goals);
  136. AbandonedGoalBook = new GoalCollection(abandoned_goals);
  137. $("#profile-goals-content").html('<div id="current-goals-list"></div><div id="completed-goals-list"></div><div id="abandoned-goals-list"></div>');
  138. this.views.current = new GoalProfileView({
  139. el: "#current-goals-list",
  140. model: viewingOwnGoals ? GoalBook : CurrentGoalBook,
  141. type: "current",
  142. readonly: !viewingOwnGoals
  143. });
  144. this.views.completed = new GoalProfileView({
  145. el: "#completed-goals-list",
  146. model: CompletedGoalBook,
  147. type: "completed",
  148. readonly: true
  149. });
  150. this.views.abandoned = new GoalProfileView({
  151. el: "#abandoned-goals-list",
  152. model: AbandonedGoalBook,
  153. type: "abandoned",
  154. readonly: true
  155. });
  156. if (viewingOwnGoals) {
  157. $(".new-goal").addClass("green").removeClass("disabled").click(function(e) {
  158. e.preventDefault();
  159. window.newGoalDialog.show();
  160. });
  161. }
  162. // Because we wait for a response from /api/v1/user/goals to render the collection,
  163. // a view can be selected by the user before they exist (either by
  164. // navigating directly to /profile/username/goals/abandoned or clicking quickly).
  165. var jel = $("#tab-content-goals .graph-picker .type"),
  166. selectedType = "current";
  167. $.each(this.views, function(index, view) {
  168. if (jel.filter("." + view.options.type).hasClass("selected")) {
  169. selectedType = view.options.type;
  170. return false;
  171. }
  172. });
  173. this.showGoalType(selectedType);
  174. },
  175. showGoalType: function(type) {
  176. var view = this.views[type];
  177. if (view) {
  178. view.show().siblings().hide();
  179. }
  180. $(".graph-picker").find("." + type).addClass("selected")
  181. .siblings().removeClass("selected");
  182. }
  183. };