PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/static/js/controllers/placescontroller.js

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