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

/pancake-web/pancake/web/static/js/controllers/placescontroller.js

https://bitbucket.org/mozillapancake/pancake
JavaScript | 194 lines | 129 code | 35 blank | 30 comment | 7 complexity | 8bbdfa8d026b1ecca5dfc6e7413c3fca MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, MIT, Apache-2.0
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. define([
  5. 'config',
  6. 'underscore',
  7. 'backbone',
  8. 'lib/promise',
  9. 'lib/routecontroller',
  10. 'views/stackplacesview',
  11. 'models/sitemodel',
  12. 'lib/bridge',
  13. 'lib/assert',
  14. 'logger',
  15. 'lib/errors'
  16. ], function(
  17. config,
  18. util,
  19. Backbone,
  20. Promise,
  21. RouteController,
  22. PlacesView,
  23. SiteModel,
  24. Bridge,
  25. assert,
  26. logger,
  27. errors
  28. ) {
  29. var bridge = new Bridge();
  30. var onPlaceVisit = function (view, model, e) {
  31. e.preventDefault();
  32. bridge.showViewer();
  33. };
  34. var PlacesController = RouteController.extend({
  35. enter: function(options) {
  36. util.extend(this, options || {});
  37. if(!this.bridge) {
  38. this.bridge = bridge;
  39. }
  40. if(this.pageState){
  41. this.bridge.stateModel = this.pageState;
  42. }
  43. this.watch('view:stacklist', this.bridge, 'onReturnToStackList');
  44. return this;
  45. },
  46. exit: function(){
  47. // stop noticing when stacks are added/removed
  48. // stop noticing when an individual stack is changed
  49. var unwatches = this._watches,
  50. handle = null;
  51. while((handle = unwatches.shift())){
  52. handle();
  53. }
  54. },
  55. // I am not keen on having the `stack_id` be implicit, but I'll make
  56. // the method name abundantly clear and call it good for now. -GB.
  57. createPlaceInActiveStack: function (placeData) {
  58. var stack_id = this.pageState.get('stack_id');
  59. return this.createPlace(stack_id, placeData);
  60. },
  61. // Call this controller action to add a new place to a currently existing
  62. // stack.
  63. createPlace: function (stack_id, placeData) {
  64. var stackCollection = this.pageState.stacksCollection;
  65. assert.contains(
  66. placeData,
  67. ['place_url', 'place_title']
  68. ).orThrow(
  69. errors.KeysMissingError,
  70. "placescontroller: Data given to createPlace is missing required properties"
  71. );
  72. Promise.when(stackCollection.fetchStack(stack_id), function (stackModel) {
  73. // we don't have the place_id we need until lattice responds to the link request...
  74. stackModel.link(placeData);
  75. });
  76. return this;
  77. },
  78. changeStack: function (stack_id) {
  79. var pageState = this.pageState;
  80. var stackCollection = pageState.stacksCollection;
  81. pageState.set({ stack_id: stack_id });
  82. // return a promise, as fetchStack can be async
  83. return Promise.whenPromise(stackCollection.fetchStack(stack_id), function (stack) {
  84. stackCollection.put(stack, { at: 0 });
  85. // Set this stackModel as active in the collection
  86. // (selects this stack, de-selects all other stacks).
  87. // TODO: this should happen outside of the setTimeout, however,
  88. // if we do this now, the stack view does not get rendered as
  89. // selected properly even when the model is selected. Check when
  90. // `render` method is called.
  91. stackCollection.selectStack(stack.id);
  92. var msg = util.extend(stack.toJSON(), { origin: config.appName });
  93. bridge.changeStack(msg);
  94. return stack;
  95. });
  96. },
  97. viewPlaces: function (stack_id, place_id) {
  98. var appView = this.appView;
  99. var self = this;
  100. var placesPromise = new Promise();
  101. this.changeStack(stack_id).then(function (stack) {
  102. var places = stack.places();
  103. // Default to stack's active `place_id` if not found.
  104. place_id = place_id || stack.get('place_id');
  105. // Replace previously-displayed view.
  106. appView.widget('#pane--places', self.placesView(stack));
  107. // If places have not yet been loaded for this stack, load them.
  108. // Semi-magical place fetching behavior to work around
  109. // <https://bugzilla.mozilla.org/show_bug.cgi?id=755146#c5>
  110. var placesReady = places.loaded ? places : places.fetch({ diff: true });
  111. Promise.when(placesReady, function (places) {
  112. placesPromise.resolve(places);
  113. var msg = util.extend(stack.toJSON(), { origin: config.appName });
  114. bridge
  115. .viewPlaces(msg)
  116. .showViewer();
  117. appView.activateChild('#pane--places');
  118. // Place should exist in collection at this point, since we fetched
  119. // all places.
  120. places
  121. .changePlace(place_id)
  122. .selectPlace(place_id);
  123. }, util.bind(placesPromise.reject, placesPromise));
  124. });
  125. return placesPromise;
  126. },
  127. // Create or return a memoized placesView for a given stack.
  128. placesView: function (stack) {
  129. var placesView = this.placesView = this.placesView || {};
  130. return (placesView[stack.id] = placesView[stack.id] || this.createPlacesView(
  131. stack
  132. ));
  133. },
  134. // Create a placesView for a given stackModel.
  135. // Configures event handlers, etc.
  136. createPlacesView: function (stack) {
  137. var appView = this.appView;
  138. var placesView = new PlacesView({
  139. model: stack,
  140. collection: stack.places(),
  141. bridge: this.bridge
  142. });
  143. // Recalculate mask height after adding places.
  144. var refitMask = function (collection) {
  145. var active = appView.activePane;
  146. if (active === '#pane--places') appView.fitMaskTo('#pane--places');
  147. };
  148. placesView.collection.bind('add', refitMask).bind('remove', refitMask);
  149. // Bind additional logic to visit events for this view.
  150. placesView.bind('visit', onPlaceVisit);
  151. return placesView;
  152. },
  153. onReturnToStackList: function(){
  154. this.pageState.navigate('stacks/active', true);
  155. }
  156. });
  157. // module return is an instance
  158. return new PlacesController();
  159. });