spontaneous 0.2.0.beta5 → 0.2.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +39 -0
  4. data/Gemfile +2 -0
  5. data/Readme.markdown +4 -4
  6. data/application/css/core.css.scss +144 -43
  7. data/application/css/definitions.css.scss +50 -16
  8. data/application/css/dialogue.css.scss +5 -2
  9. data/application/css/editing.css.scss +7 -7
  10. data/application/css/font.css.scss +1 -1
  11. data/application/css/meta.css.scss +6 -6
  12. data/application/css/popover.css.scss +6 -6
  13. data/application/css/top.css.scss +8 -1
  14. data/application/js/add_alias_dialogue.js +137 -36
  15. data/application/js/add_home_dialogue.js +10 -10
  16. data/application/js/ajax.js +26 -26
  17. data/application/js/authentication.js +2 -2
  18. data/application/js/box.js +21 -10
  19. data/application/js/box_container.js +13 -7
  20. data/application/js/compatibility.js +19 -17
  21. data/application/js/conflicted_field_dialogue.js +5 -5
  22. data/application/js/content.js +22 -16
  23. data/application/js/content_area.js +62 -33
  24. data/application/js/dialogue.js +16 -16
  25. data/application/js/dom.js +9 -10
  26. data/application/js/edit_panel.js +25 -20
  27. data/application/js/editing.js +21 -8
  28. data/application/js/entry.js +1 -1
  29. data/application/js/extensions.js +11 -11
  30. data/application/js/field/boolean.js +6 -6
  31. data/application/js/field/date.js +1 -1
  32. data/application/js/field/file.js +17 -17
  33. data/application/js/field/image.js +27 -27
  34. data/application/js/field/markdown.js +72 -71
  35. data/application/js/field/select.js +9 -9
  36. data/application/js/field/string.js +3 -3
  37. data/application/js/field/webvideo.js +2 -2
  38. data/application/js/field_preview.js +3 -0
  39. data/application/js/init.js +3 -2
  40. data/application/js/jquery-selection-position.js +13 -13
  41. data/application/js/location.js +17 -12
  42. data/application/js/login.js +2 -2
  43. data/application/js/meta_view/user_admin.js +101 -101
  44. data/application/js/metadata.js +1 -1
  45. data/application/js/page.js +2 -2
  46. data/application/js/page_browser.js +13 -13
  47. data/application/js/page_entry.js +1 -1
  48. data/application/js/panel/root_menu.js +10 -10
  49. data/application/js/popover.js +6 -5
  50. data/application/js/popover_view.js +5 -5
  51. data/application/js/preview.js +10 -4
  52. data/application/js/progress.js +6 -6
  53. data/application/js/properties.js +35 -6
  54. data/application/js/publish.js +43 -43
  55. data/application/js/require.js +14 -14
  56. data/application/js/services.js +3 -3
  57. data/application/js/sharded_upload.js +9 -8
  58. data/application/js/side_bar.js +5 -5
  59. data/application/js/state.js +2 -2
  60. data/application/js/status_bar.js +6 -6
  61. data/application/js/top_bar.js +97 -65
  62. data/application/js/types.js +9 -6
  63. data/application/js/upload.js +4 -4
  64. data/application/js/upload_manager.js +21 -21
  65. data/application/js/user.js +1 -1
  66. data/application/js/vendor/jquery.velocity.min.js +7 -0
  67. data/application/js/views.js +32 -8
  68. data/application/js/views/box_view.js +51 -31
  69. data/application/js/views/page_piece_view.js +17 -15
  70. data/application/js/views/page_view.js +54 -43
  71. data/application/js/views/piece_view.js +44 -37
  72. data/application/static/font/fontawesome-webfont-4f0022f25672c7f501c339cbf98d9117.ttf +0 -0
  73. data/application/views/index.erb +1 -0
  74. data/db/migrations/20130114120000_create_revision_tables.rb +2 -1
  75. data/db/migrations/20130813111009_increase_path_length.rb +11 -2
  76. data/db/migrations/20140506171823_add_index_to_target_id.rb +11 -0
  77. data/db/migrations/20140514090204_add_content_hash.rb +59 -0
  78. data/db/migrations/20140519150253_add_content_hash_timestamp.rb +20 -0
  79. data/lib/spontaneous.rb +0 -1
  80. data/lib/spontaneous/asset/environment.rb +77 -15
  81. data/lib/spontaneous/box.rb +21 -0
  82. data/lib/spontaneous/capistrano/deploy.rb +1 -1
  83. data/lib/spontaneous/capistrano/sync.rb +8 -7
  84. data/lib/spontaneous/change.rb +4 -2
  85. data/lib/spontaneous/cli/fields.rb +7 -3
  86. data/lib/spontaneous/cli/generate.rb +2 -0
  87. data/lib/spontaneous/cli/init.rb +24 -93
  88. data/lib/spontaneous/cli/init/db.rb +94 -0
  89. data/lib/spontaneous/cli/init/mysql.rb +17 -0
  90. data/lib/spontaneous/cli/init/postgresql.rb +33 -0
  91. data/lib/spontaneous/cli/init/sqlite.rb +14 -0
  92. data/lib/spontaneous/cli/site.rb +45 -20
  93. data/lib/spontaneous/collections/box_set.rb +3 -0
  94. data/lib/spontaneous/collections/entry_set.rb +43 -4
  95. data/lib/spontaneous/collections/field_set.rb +14 -2
  96. data/lib/spontaneous/data_mapper.rb +40 -7
  97. data/lib/spontaneous/data_mapper/content_model.rb +1 -1
  98. data/lib/spontaneous/data_mapper/content_model/associations.rb +63 -12
  99. data/lib/spontaneous/data_mapper/content_model/timestamps.rb +9 -14
  100. data/lib/spontaneous/data_mapper/content_table.rb +4 -2
  101. data/lib/spontaneous/data_mapper/dataset.rb +31 -2
  102. data/lib/spontaneous/data_mapper/scope.rb +37 -20
  103. data/lib/spontaneous/errors.rb +6 -0
  104. data/lib/spontaneous/facet.rb +20 -10
  105. data/lib/spontaneous/field/base.rb +8 -1
  106. data/lib/spontaneous/field/file.rb +28 -3
  107. data/lib/spontaneous/field/image.rb +2 -0
  108. data/lib/spontaneous/field/update.rb +6 -0
  109. data/lib/spontaneous/field/webvideo/vimeo.rb +6 -1
  110. data/lib/spontaneous/field/webvideo/vine.rb +1 -1
  111. data/lib/spontaneous/field/webvideo/youtube.rb +1 -1
  112. data/lib/spontaneous/generators/site.rb +6 -4
  113. data/lib/spontaneous/generators/site/.gitignore +1 -0
  114. data/lib/spontaneous/generators/site/Gemfile.tt +3 -3
  115. data/lib/spontaneous/generators/site/config/{indexes.rb.tt → initializers/indexes.rb.tt} +0 -0
  116. data/lib/spontaneous/generators/site/config/initializers/publishing.rb.tt +78 -0
  117. data/lib/spontaneous/generators/site/{config/database.yml.tt → db/mysql2.yml.tt} +7 -6
  118. data/lib/spontaneous/generators/site/db/postgres.yml.tt +25 -0
  119. data/lib/spontaneous/generators/site/db/sqlite3.yml.tt +18 -0
  120. data/lib/spontaneous/generators/site/public/humans.txt.tt +14 -0
  121. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +51 -0
  122. data/lib/spontaneous/loader.rb +1 -1
  123. data/lib/spontaneous/logger.rb +1 -1
  124. data/lib/spontaneous/media/image/optimizer.rb +1 -1
  125. data/lib/spontaneous/media/image/processor.rb +11 -2
  126. data/lib/spontaneous/media/image/renderable.rb +2 -0
  127. data/lib/spontaneous/model.rb +3 -0
  128. data/lib/spontaneous/model/box/allowed_types.rb +17 -4
  129. data/lib/spontaneous/model/core.rb +36 -3
  130. data/lib/spontaneous/model/core/aliases.rb +5 -2
  131. data/lib/spontaneous/model/core/boxes.rb +6 -0
  132. data/lib/spontaneous/model/core/cascading_change.rb +38 -0
  133. data/lib/spontaneous/model/core/content_hash.rb +171 -0
  134. data/lib/spontaneous/model/core/entries.rb +0 -19
  135. data/lib/spontaneous/model/core/fields.rb +11 -0
  136. data/lib/spontaneous/model/core/modifications.rb +22 -21
  137. data/lib/spontaneous/model/core/render.rb +3 -0
  138. data/lib/spontaneous/model/core/serialisation.rb +18 -17
  139. data/lib/spontaneous/model/page.rb +35 -8
  140. data/lib/spontaneous/model/page/page_tree.rb +20 -8
  141. data/lib/spontaneous/model/page/paths.rb +79 -50
  142. data/lib/spontaneous/model/page/singleton.rb +71 -0
  143. data/lib/spontaneous/model/page/site_map.rb +2 -1
  144. data/lib/spontaneous/model/page/site_timestamps.rb +2 -2
  145. data/lib/spontaneous/model/piece.rb +10 -0
  146. data/lib/spontaneous/output/context.rb +13 -6
  147. data/lib/spontaneous/output/format.rb +30 -5
  148. data/lib/spontaneous/output/helpers/script_helper.rb +8 -0
  149. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +7 -0
  150. data/lib/spontaneous/output/renderable.rb +16 -0
  151. data/lib/spontaneous/output/store.rb +1 -1
  152. data/lib/spontaneous/output/template/renderer.rb +2 -2
  153. data/lib/spontaneous/page_piece.rb +25 -1
  154. data/lib/spontaneous/prototypes/box_prototype.rb +13 -0
  155. data/lib/spontaneous/prototypes/field_prototype.rb +7 -4
  156. data/lib/spontaneous/publishing.rb +10 -5
  157. data/lib/spontaneous/publishing/immediate.rb +32 -349
  158. data/lib/spontaneous/publishing/pipeline.rb +43 -0
  159. data/lib/spontaneous/publishing/progress.rb +186 -0
  160. data/lib/spontaneous/publishing/publish.rb +107 -0
  161. data/lib/spontaneous/publishing/rerender.rb +17 -0
  162. data/lib/spontaneous/publishing/revision.rb +53 -18
  163. data/lib/spontaneous/publishing/simultaneous.rb +1 -1
  164. data/lib/spontaneous/publishing/steps.rb +154 -0
  165. data/lib/spontaneous/publishing/steps/activate_revision.rb +45 -0
  166. data/lib/spontaneous/publishing/steps/archive_old_revisions.rb +22 -0
  167. data/lib/spontaneous/publishing/steps/base_step.rb +49 -0
  168. data/lib/spontaneous/publishing/steps/copy_static_files.rb +74 -0
  169. data/lib/spontaneous/publishing/steps/create_revision_directory.rb +24 -0
  170. data/lib/spontaneous/publishing/steps/generate_rackup_file.rb +51 -0
  171. data/lib/spontaneous/publishing/steps/generate_search_indexes.rb +24 -0
  172. data/lib/spontaneous/publishing/steps/render_revision.rb +69 -0
  173. data/lib/spontaneous/publishing/steps/write_revision_file.rb +43 -0
  174. data/lib/spontaneous/rack/back.rb +3 -1
  175. data/lib/spontaneous/rack/back/alias.rb +9 -8
  176. data/lib/spontaneous/rack/front.rb +1 -1
  177. data/lib/spontaneous/rack/middleware.rb +7 -4
  178. data/lib/spontaneous/rack/middleware/transaction.rb +14 -0
  179. data/lib/spontaneous/rack/page_controller.rb +23 -8
  180. data/lib/spontaneous/revision.rb +5 -10
  181. data/lib/spontaneous/schema.rb +5 -0
  182. data/lib/spontaneous/server.rb +3 -1
  183. data/lib/spontaneous/site.rb +17 -10
  184. data/lib/spontaneous/site/publishing.rb +25 -3
  185. data/lib/spontaneous/site/state.rb +7 -3
  186. data/lib/spontaneous/tasks/database.rake +5 -10
  187. data/lib/spontaneous/utils/database/mysql_dumper.rb +5 -1
  188. data/lib/spontaneous/version.rb +1 -1
  189. data/spontaneous.gemspec +4 -3
  190. data/test/fixtures/example_application/config/initializers/initializer1.rb +1 -0
  191. data/test/fixtures/example_application/config/initializers/initializer2.rb +1 -0
  192. data/test/fixtures/example_application/config/initializers/publishing.rb +13 -0
  193. data/test/fixtures/search/config/{indexes.rb → initializers/indexes.rb} +0 -0
  194. data/test/fixtures/serialisation/root_hash.yaml.erb +10 -4
  195. data/test/functional/test_application.rb +10 -0
  196. data/test/functional/test_back.rb +23 -5
  197. data/test/functional/test_cli.rb +98 -34
  198. data/test/functional/test_front.rb +7 -3
  199. data/test/test_helper.rb +35 -28
  200. data/test/unit/test_alias.rb +20 -3
  201. data/test/unit/test_assets.rb +58 -30
  202. data/test/unit/test_changesets.rb +20 -12
  203. data/test/unit/test_content_hash.rb +496 -0
  204. data/test/unit/test_context.rb +28 -1
  205. data/test/unit/test_controllers.rb +96 -61
  206. data/test/unit/test_crypt.rb +1 -8
  207. data/test/unit/test_datamapper.rb +95 -19
  208. data/test/unit/test_features.rb +1 -4
  209. data/test/unit/test_fields.rb +61 -12
  210. data/test/unit/test_generators.rb +39 -2
  211. data/test/unit/test_images.rb +3 -1
  212. data/test/unit/test_modifications.rb +224 -219
  213. data/test/unit/test_output_store.rb +10 -0
  214. data/test/unit/{test_formats.rb → test_outputs.rb} +75 -6
  215. data/test/unit/test_page.rb +61 -15
  216. data/test/unit/test_plugins.rb +2 -42
  217. data/test/unit/test_publishing_pipeline.rb +1050 -0
  218. data/test/unit/test_render.rb +30 -0
  219. data/test/unit/test_revisions.rb +110 -2
  220. data/test/unit/test_schema.rb +4 -0
  221. data/test/unit/test_search.rb +1 -1
  222. data/test/unit/test_serialisation.rb +6 -1
  223. data/test/unit/test_singletons.rb +159 -0
  224. data/test/unit/test_site.rb +71 -44
  225. metadata +140 -86
  226. data/application/static/font/fontawesome-webfont-1c66a4738b40ef0f6b1abca0ba9a796d.ttf +0 -0
  227. data/test/unit/test_publishing.rb +0 -330
@@ -11,8 +11,8 @@ Spontaneous.Field.String = (function($, S) {
11
11
  },
12
12
  panel: function() {
13
13
  var labels = dom.div('.string-field-conflict.labels.differences'), outer = dom.div(), diff_outer = dom.div('.string-field-conflict.changes.differences'), local_diff = dom.div('.original.diff'), computed_diff = dom.div('.final.diff');
14
- var local_diff_label = dom.div('.diff').text("Changes made by other person");
15
- var final_diff_label = dom.div('.diff').text("Their changes merged with yours");
14
+ var local_diff_label = dom.div('.diff').text('Changes made by other person');
15
+ var final_diff_label = dom.div('.diff').text('Their changes merged with yours');
16
16
  var server_change = this.diff(this.values.local_original, this.values.server_original);
17
17
  var local_change = this.diff(this.values.local_original, this.values.local_edited);
18
18
  var merge = this.differ.patch_apply(local_change.patches, this.values.server_original);
@@ -129,7 +129,7 @@ Spontaneous.Field.String = (function($, S) {
129
129
  return this.title;
130
130
  },
131
131
  generate_input: function() {
132
- return dom.input(dom.id(this.css_id()), {'type':'text', 'name':this.form_name(), 'value':this.unprocessed_value()})
132
+ return dom.input(dom.id(this.css_id()), {'type':'text', 'name':this.form_name(), 'value':this.unprocessed_value()});
133
133
  },
134
134
  input: function() {
135
135
  if (!this._input) {
@@ -16,11 +16,11 @@ Spontaneous.Field.WebVideo = (function($, S) {
16
16
  // at the same time I want to replace an immediately inserted video player with an
17
17
  // image + play button to reduce the impact of multiple videos on the cms ui load time
18
18
  var value = this.get('value').replace(/autoplay=1/, '')
19
- , iframe = dom.iframe({src:value, frameborder: 0, border: 0}).css({position: "absolute", top:0, left:0, height: "100%", width: "100%"});
19
+ , iframe = dom.iframe({src:value, frameborder: 0, border: 0}).css({position: 'absolute', top:0, left:0, height: '100%', width: '100%'});
20
20
  if (!value) { // don't fill up the page with empty iframes...
21
21
  return dom.div();
22
22
  }
23
- return dom.div().css({width: "100%", position: "relative", "padding-bottom":"56.25%", height: 0}).append(iframe)
23
+ return dom.div().css({width: '100%', position: 'relative', 'padding-bottom':'56.25%', height: 0}).append(iframe);
24
24
  }
25
25
  });
26
26
 
@@ -55,6 +55,9 @@ Spontaneous.FieldPreview = (function($, S) {
55
55
  }
56
56
  });
57
57
  return wrapper;
58
+ },
59
+ unload: function() {
60
+ // keep compatibility with the view api
58
61
  }
59
62
  });
60
63
  return FieldPreview;
@@ -9,9 +9,10 @@ Spontaneous.Init = (function($, S) {
9
9
 
10
10
  location.watch('location', top_bar.location_changed.bind(top_bar));
11
11
  location.watch('location', content_area.location_changed.bind(content_area));
12
+ location.watch('loading_location', content_area.location_loading.bind(content_area));
12
13
 
13
- top_bar.watch('mode', content_area.display.bind(content_area));
14
- top_bar.watch('mode', location.view_mode_changed.bind(location));
14
+ top_bar.watch('mode', content_area.display.bind(content_area));
15
+ top_bar.watch('mode', location.view_mode_changed.bind(location));
15
16
 
16
17
  S.Editing.watch('page', location.page_loaded.bind(location));
17
18
  S.Editing.watch('path', location.path_changed.bind(location));
@@ -7,7 +7,7 @@
7
7
  * @author Bevis Zhao (i@bevis.me, http://bevis.me)
8
8
  */
9
9
  (function($) {
10
- "use strict";
10
+ 'use strict';
11
11
 
12
12
  var calculator = {
13
13
  // key styles
@@ -26,7 +26,7 @@ specificStyle: {
26
26
  'overflow-y': 'auto'
27
27
  },
28
28
 
29
- simulator : $('<div id="textarea_simulator"/>').css({
29
+ simulator: $('<div id="textarea_simulator"/>').css({
30
30
  position: 'absolute',
31
31
  top: 0,
32
32
  left: 0,
@@ -53,7 +53,7 @@ visibility: 'hidden'
53
53
  selectStart = element.selectionStart,
54
54
  selectEnd = element.selectionEnd;
55
55
 
56
- if (selectEnd === selectStart) { return false; };
56
+ if (selectEnd === selectStart) { return false; }
57
57
 
58
58
  var beforeText = value.substring(0, selectStart),
59
59
  selectedText = value.substring(selectStart, selectEnd),
@@ -69,7 +69,7 @@ visibility: 'hidden'
69
69
 
70
70
  return {
71
71
  top: focusOffset.top - simulatorOffset.top - element.scrollTop,
72
- left: focus[0].offsetLeft - cal.simulator[0].offsetLeft - element.scrollLeft,
72
+ left: focus[0].offsetLeft - cal.simulator[0].offsetLeft - element.scrollLeft,
73
73
  width: focus.width(),
74
74
  height: focus.height()
75
75
  };
@@ -87,22 +87,22 @@ var showPopup = function(textarea, popup, offsetCalculator) {
87
87
 
88
88
  // In order to use the size of the popup in the positioning calculations
89
89
  // it needs to be visible in the dom.
90
- popup.css("visibility", "hidden").show();
90
+ popup.css('visibility', 'hidden').show();
91
91
  var place = offsetCalculator(pos);
92
- popup.hide().css("visibility", "visible");
92
+ popup.css({opacity: 0}).css('visibility', 'visible');
93
93
  if (top >= position.top && top < bottom) {
94
94
  popup.css({
95
95
  left: place.left,
96
96
  top: place.top
97
- }).fadeIn(100)
97
+ }).velocity({opacity: 1}, {duration: 100});
98
98
  } else {
99
- popup.fadeOut(100);
99
+ popup.velocity('fadeOut', 100);
100
100
  }
101
101
  return true;
102
- }
102
+ };
103
103
  $.fn.extend({
104
104
  getComputedStyle: function(styleName) {
105
- if (this.length == 0) return;
105
+ if (this.length === 0) { return; }
106
106
  var self = this[0], result = this.css(styleName);
107
107
  result = result || ($.browser.msie ? self.currentStyle[styleName]: document.defaultView.getComputedStyle(self, null)[styleName]);
108
108
  return result;
@@ -118,11 +118,11 @@ showSelectionPopup: function(popup, offsetCalculator) {
118
118
  var callback = function() {
119
119
  var selected = showPopup(self, popup, offsetCalculator);
120
120
  if (!selected) {
121
- self.unbind("scroll.popup").unbind("mouseup.popup");
121
+ self.unbind('scroll.popup').unbind('mouseup.popup');
122
122
  }
123
123
  };
124
- self.bind("scroll.popup", callback);
125
- self.bind("mouseup.popup", callback.delay(1));
124
+ self.bind('scroll.popup', callback);
125
+ self.bind('mouseup.popup', callback.delay(1));
126
126
  callback();
127
127
  }
128
128
  });
@@ -19,8 +19,8 @@ Spontaneous.Location = (function($, S) {
19
19
  },
20
20
  restore: function() {
21
21
  if (this.mode) {
22
- Spontaneous.Location.view_mode_changed(this.mode)
23
- Spontaneous.TopBar.set_mode(this.mode)
22
+ Spontaneous.Location.view_mode_changed(this.mode);
23
+ Spontaneous.TopBar.set_mode(this.mode);
24
24
  }
25
25
  if (this.page_id) {
26
26
  Spontaneous.Location.load_id(this.page_id);
@@ -32,29 +32,29 @@ Spontaneous.Location = (function($, S) {
32
32
  return '#/'+(this.page_id || '') + (this.mode ? ('@' + this.mode) : '');
33
33
  },
34
34
  to_path: function() {
35
- return [ajax.namespace, (this.page_id || ''), this.mode].join("/")
35
+ return [ajax.namespace, (this.page_id || ''), this.mode].join('/');
36
36
  },
37
37
  to_obj: function() {
38
38
  return {
39
39
  page_id: this.page_id,
40
40
  mode: this.mode
41
- }
41
+ };
42
42
  }
43
43
  });
44
44
 
45
45
  State.extend({
46
46
  // currently just produces some kind of loop
47
47
  popstate: function(event) {
48
- State.restore(event)
48
+ State.restore(event);
49
49
  return false;
50
50
  },
51
51
  restore: function(event) {
52
- var state = new State(window.location.pathname)
52
+ var state = new State(window.location.pathname);
53
53
  state.restore();
54
54
  },
55
55
 
56
56
  page: function(location, mode) {
57
- var s = new State
57
+ var s = new State();
58
58
  s.page_id = location.id;
59
59
  s.mode = mode;
60
60
  window.history.replaceState(s.to_obj(), ''+s.page_id, s.to_path());
@@ -94,6 +94,7 @@ Spontaneous.Location = (function($, S) {
94
94
  this.set('path', location.path);
95
95
  this.update_state(location, this.get('view_mode'));
96
96
  }
97
+ this.set('loading_location', null);
97
98
  },
98
99
  update_state: function(location, mode) {
99
100
  State.page(location, mode);
@@ -112,14 +113,14 @@ Spontaneous.Location = (function($, S) {
112
113
  },
113
114
  url: function() {
114
115
  var l = this.location();
115
- return (l ? l.url : "/about");
116
+ return (l ? l.url : '/about');
116
117
  },
117
118
  location: function() {
118
119
  return this.get('location');
119
120
  },
120
121
  update: function(location) {
121
122
  this.set('location', location);
122
- this.path_from_url(location.url)
123
+ this.path_from_url(location.url);
123
124
  },
124
125
  current_path: function() {
125
126
  return this.path_from_url(this.url());
@@ -128,13 +129,13 @@ Spontaneous.Location = (function($, S) {
128
129
  if (this.location() && path === this.location().path) {
129
130
  return this.location();
130
131
  }
131
- this.retrieve('/map/path'+path, this.location_loaded.bind(this));
132
+ this.retrieve_with_progress('/map/path'+path, this.location_loaded.bind(this));
132
133
  },
133
134
  find_id: function(id) {
134
135
  if (this.location() && id === this.location().id) {
135
136
  return this.location();
136
137
  }
137
- this.retrieve('/map/'+id, this.location_loaded.bind(this));
138
+ this.retrieve_with_progress('/map/'+id, this.location_loaded.bind(this));
138
139
  },
139
140
  path_from_url: function(url) {
140
141
  var map = this.get('map'),
@@ -142,7 +143,7 @@ Spontaneous.Location = (function($, S) {
142
143
  path = [], i, ii,
143
144
  parts = url.split('/').slice(1), position = 0;
144
145
  // add root to path
145
- path.push({selected:0, pages:[ map ], root:true});;
146
+ path.push({selected:0, pages:[map], root:true});
146
147
  while (position < parts.length) {
147
148
  for (i = 0, ii = children.length; i < ii; i++) {
148
149
  var child = children[i], slug = child.url.split('/').slice(-1)[0];
@@ -156,6 +157,10 @@ Spontaneous.Location = (function($, S) {
156
157
  }
157
158
  return path;
158
159
  },
160
+ retrieve_with_progress: function(url, callback) {
161
+ this.set('loading_location', url);
162
+ return this.retrieve(url, callback);
163
+ },
159
164
  retrieve: function(url, callback) {
160
165
  ajax.get(url, {}, callback, {ifModified: true, cache: true});
161
166
  },
@@ -31,7 +31,7 @@
31
31
  var $this = $(this);
32
32
  $.ajax({
33
33
  url: $this.attr('action'),
34
- type: "POST",
34
+ type: 'POST',
35
35
  data:$this.serialize(),
36
36
  success: function(data) {
37
37
  if (data.key) {
@@ -44,7 +44,7 @@
44
44
  $('#failed-name').text($('#user-login').val());
45
45
  $(this).fadeIn();
46
46
  });
47
- $("#error-message:hidden").slideDown(200);
47
+ $('#error-message:hidden').slideDown(200);
48
48
  },
49
49
  dataType: 'json'
50
50
  });
@@ -27,10 +27,10 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
27
27
  var levels = this.levels;
28
28
  var nonePosition = function() {
29
29
  for (var i = 0, ii = levels.length; i < ii; i++) {
30
- if (levels[i].levelName() === "none") {
30
+ if (levels[i].levelName() === 'none') {
31
31
  return i;
32
32
  }
33
- };
33
+ }
34
34
  }();
35
35
  return levels[nonePosition + 1];
36
36
  };
@@ -43,17 +43,17 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
43
43
  element: function(cancelCallback) {
44
44
  var self = this;
45
45
  var levels = Level.levels;
46
- var currentLevel = Level.get(this.user.get("level")) || Level.defaultLevel();
47
- var outer = dom.div(".level-select");
48
- var input = dom.input({type: "hidden", name: Input.inputName(this.name), value: currentLevel.levelName()});
49
- var select = dom.div(".select").hide();
50
- var value = dom.div(".level-value").text(currentLevel.title());
46
+ var currentLevel = Level.get(this.user.get('level')) || Level.defaultLevel();
47
+ var outer = dom.div('.level-select');
48
+ var input = dom.input({type: 'hidden', name: Input.inputName(this.name), value: currentLevel.levelName()});
49
+ var select = dom.div('.select').hide();
50
+ var value = dom.div('.level-value').text(currentLevel.title());
51
51
  levels.forEach(function(level) {
52
- var row = dom.div(".level").addClass("level-" + level.levelName());
53
- row.append(dom.span(".level-name").text(level.title()));
54
- row.append(dom.span(".level-publish").text("Publish").addClass(""+level.canPublish()));
55
- row.append(dom.span(".level-admin").text("Admin").addClass(""+level.isAdmin()));
56
- row.data("level", level);
52
+ var row = dom.div('.level').addClass('level-' + level.levelName());
53
+ row.append(dom.span('.level-name').text(level.title()));
54
+ row.append(dom.span('.level-publish').text('Publish').addClass(''+level.canPublish()));
55
+ row.append(dom.span('.level-admin').text('Admin').addClass(''+level.isAdmin()));
56
+ row.data('level', level);
57
57
  row.click(function() {
58
58
  self.choose(level);
59
59
  return false;
@@ -75,12 +75,12 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
75
75
  var pulldown = this.pulldown;
76
76
  pulldown.fadeIn(100);
77
77
  var level = this.currentLevel();
78
- var options = pulldown.find(".level");
78
+ var options = pulldown.find('.level');
79
79
  var levelDiv = options.filter(function(div) {
80
- return $(this).data("level").levelName() == level.levelName();
80
+ return $(this).data('level').levelName() == level.levelName();
81
81
  })[0];
82
82
  var pos = $(levelDiv).position();
83
- pulldown.css("top", dom.px(-pos.top));
83
+ pulldown.css('top', dom.px(-pos.top));
84
84
  },
85
85
 
86
86
  choose: function(level) {
@@ -89,7 +89,7 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
89
89
 
90
90
  this.close();
91
91
  },
92
- close: function( ) {
92
+ close: function() {
93
93
  this.pulldown.fadeOut(100);
94
94
  },
95
95
  activate: function() {
@@ -113,21 +113,21 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
113
113
  this.value = value;
114
114
  },
115
115
  element: function(cancelCallback) {
116
- var type = (this.name === "email" ? "email" : "text");
116
+ var type = (this.name === 'email' ? 'email' : 'text');
117
117
  var input = dom.input({
118
118
  name: this.inputName(),
119
119
  value: this.value,
120
120
  type: type
121
121
  }).focus(function() {
122
- $(this).parents("p").addClass("focus");
122
+ $(this).parents('p').addClass('focus');
123
123
  }).blur(function() {
124
- $(this).parents("p").removeClass("focus");
124
+ $(this).parents('p').removeClass('focus');
125
125
  }).keydown(function(event) {
126
126
  if (event.keyCode === 27) { cancelCallback(); }
127
127
  });
128
128
  // TODO: catch RETURN and ESCAPE
129
129
  return input;
130
- }.cache("input"),
130
+ }.cache('input'),
131
131
  inputName: function() { return Input.inputName(this.name); },
132
132
  isModified: function() {
133
133
  // TODO: compare current value of input against original value
@@ -136,12 +136,12 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
136
136
  showError: function(errors) {
137
137
  var error = errors[0]
138
138
  , element = this.element()
139
- , errorWrap = dom.div(".error").append(dom.span().text(error)).hide();
139
+ , errorWrap = dom.div('.error').append(dom.span().text(error)).hide();
140
140
  element.after(errorWrap);
141
141
  errorWrap.fadeIn(300);
142
142
  },
143
143
  hideError: function() {
144
- var error = this.element().next(".error");
144
+ var error = this.element().next('.error');
145
145
  error.fadeOut(100, function() {
146
146
  error.remove();
147
147
  });
@@ -149,71 +149,71 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
149
149
  });
150
150
 
151
151
  Input.inputName = function(name) {
152
- return "user[" + name + "]";
152
+ return 'user[' + name + ']';
153
153
  };
154
154
 
155
155
  var responseCallback = function(complete, successCallback, failCallback) {
156
- var isFunction = function(f) { return (typeof f === "function"); }
156
+ var isFunction = function(f) { return (typeof f === 'function'); };
157
157
  return function(result, status) {
158
- if (status === "success") {
158
+ if (status === 'success') {
159
159
  if (isFunction(complete)) { complete(result); }
160
160
  if (isFunction(successCallback)) { successCallback(result); }
161
161
  } else {
162
162
  if (isFunction(failCallback)) { failCallback(result); }
163
163
  }
164
- }
164
+ };
165
165
  };
166
166
 
167
167
  var UserController = {
168
- save: function(user, params, successCallback, failCallback) {
169
- var url = ["/users", user.get("id")].join("/");
168
+ save: function(user, params, successCallback, failCallback) {
169
+ var url = ['/users', user.get('id')].join('/');
170
170
  ajax.put(url, params, responseCallback(function(result) {
171
171
  user.update(result);
172
172
  }, successCallback, failCallback));
173
173
  },
174
174
  create: function(user, params, successCallback, failCallback) {
175
- var url = "/users";
175
+ var url = '/users';
176
176
  ajax.post(url, params, responseCallback(function(result) {
177
177
  user.update(result);
178
178
  }, successCallback, failCallback));
179
179
  },
180
180
  delete: function(user, successCallback, failCallback) {
181
- var url = ["/users", user.get("id")].join("/");
181
+ var url = ['/users', user.get('id')].join('/');
182
182
  ajax.del(url, {}, responseCallback(function(result) {
183
183
 
184
184
  }, successCallback, failCallback));
185
185
  },
186
186
  enable: function(user, enabled, successCallback, failCallback) {
187
- var action = (enabled ? "enable" : "disable")
188
- , url = ["/users", action, user.get("id")].join("/");
187
+ var action = (enabled ? 'enable' : 'disable')
188
+ , url = ['/users', action, user.get('id')].join('/');
189
189
  ajax.put(url, {}, responseCallback(function(result) {
190
- user.set("disabled", !enabled);
190
+ user.set('disabled', !enabled);
191
191
  }, successCallback, failCallback));
192
192
  },
193
193
  logout: function(user, successCallback, failCallback) {
194
- var url = ["/users", "keys", user.get("id")].join("/");
194
+ var url = ['/users', 'keys', user.get('id')].join('/');
195
195
  ajax.del(url, {}, responseCallback(function(result) {
196
196
 
197
197
  },successCallback, failCallback));
198
- },
198
+ }
199
199
  };
200
200
 
201
201
  var EditUserView = new JS.Class({
202
202
  initialize: function(parent, user) {
203
203
  this.parent = parent;
204
- this.user = user;
204
+ this.user = user;
205
205
  },
206
206
  titleText: function() {
207
- return "Editing User “" + this.user.get("name") + "";
207
+ return 'Editing User “' + this.user.get('name') + '';
208
208
  },
209
209
  view: function() {
210
210
  var self = this;
211
211
  var user = this.user;
212
212
  var wrap = dom.div();
213
- var form = dom.form({method: "post", action: ajax.request_url("/users/"+ user.get("id"))})
213
+ var form = dom.form({method: 'post', action: ajax.request_url('/users/'+ user.get('id'))});
214
214
  var inputs = {};
215
215
  var p, label, input, value;
216
- var titleBar = dom.div(".title").append(dom.span().text(this.titleText()));
216
+ var titleBar = dom.div('.title').append(dom.span().text(this.titleText()));
217
217
 
218
218
  form.append(self.aboveUserAttributes());
219
219
 
@@ -221,10 +221,10 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
221
221
  self.parent.closeUser();
222
222
  };
223
223
  self.editableAttributes().forEach(function(name) {
224
- p = dom.p()
224
+ p = dom.p();
225
225
  label = dom.label().text(name);
226
226
  input = self.inputForAttribute(name);
227
- value = dom.div(".value").append(input.element(cancel));
227
+ value = dom.div('.value').append(input.element(cancel));
228
228
  p.append(label, value);
229
229
  form.append(p);
230
230
  inputs[name] = input;
@@ -241,14 +241,14 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
241
241
  self.save(form, saveComplete, saveFail);
242
242
  return false;
243
243
  };
244
- var cancelBtn = dom.a(".button.cancel").text("Cancel").click(cancel);
245
- var saveBtn = dom.button(".button", {type: "submit"}).text(self.saveButtonText()).click(performSave);
246
- p.append(cancelBtn, dom.div(".gap"), saveBtn);
244
+ var cancelBtn = dom.a('.button.cancel').text('Cancel').click(cancel);
245
+ var saveBtn = dom.button('.button', {type: 'submit'}).text(self.saveButtonText()).click(performSave);
246
+ p.append(cancelBtn, dom.div('.gap'), saveBtn);
247
247
  form.append(p);
248
248
  form.submit(performSave);
249
249
  this.inputs = inputs;
250
250
  form.find('input[type="text"]:first').focus().select();
251
- wrap.append(titleBar, form)
251
+ wrap.append(titleBar, form);
252
252
  return wrap;
253
253
  },
254
254
  verificationErrors: function(errors) {
@@ -258,42 +258,42 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
258
258
  });
259
259
  },
260
260
  saveButtonText: function() {
261
- return "Save";
261
+ return 'Save';
262
262
  },
263
263
  inputForAttribute: function(name) {
264
- if (name === "level") {
264
+ if (name === 'level') {
265
265
  return new LevelSelect(name, this.user);
266
266
  }
267
267
  return new Input(name, this.user.get(name));
268
268
  },
269
269
  editableAttributes: function() {
270
- return ["login", "name", "email", "level"];
270
+ return ['login', 'name', 'email', 'level'];
271
271
  },
272
272
  aboveUserAttributes: function() {
273
273
  var self = this;
274
- var user = this.user
275
- var admin = dom.div(".admin");
276
- p = dom.p(".enabled");
277
- label = dom.label().text("Enabled");
278
- var checkbox = dom.input({type:"checkbox", checked: (!user.get("disabled"))}).click(function() {
279
- var enabled = $(this).attr("checked") === "checked";
274
+ var user = this.user;
275
+ var admin = dom.div('.admin');
276
+ p = dom.p('.enabled');
277
+ label = dom.label().text('Enabled');
278
+ var checkbox = dom.input({type:'checkbox', checked: (!user.get('disabled'))}).click(function() {
279
+ var enabled = $(this).attr('checked') === 'checked';
280
280
  UserController.enable(user, enabled);
281
281
  return false;
282
282
  });
283
- user.watch("disabled", function(disabled) {
284
- checkbox.attr("checked", !disabled);
283
+ user.watch('disabled', function(disabled) {
284
+ checkbox.attr('checked', !disabled);
285
285
  });
286
286
  label.append(checkbox);
287
287
  p.append(label);
288
288
  admin.append(p);
289
289
 
290
- admin.append(dom.p(".gap"));
291
- p = dom.p(".log-off");
292
- var btn = dom.a(".button.log-out").text("Log "+user.get("login")+" Out").click(function() {
290
+ admin.append(dom.p('.gap'));
291
+ p = dom.p('.log-off');
292
+ var btn = dom.a('.button.log-out').text('Log '+user.get('login')+' Out').click(function() {
293
293
  var $this = $(this);
294
- $this.addClass("pending");
294
+ $this.addClass('pending');
295
295
  UserController.logout(user, function() {
296
- $this.removeClass("pending").addClass("complete").text("Logged Out");
296
+ $this.removeClass('pending').addClass('complete').text('Logged Out');
297
297
  });
298
298
  });
299
299
  p.append(btn);
@@ -324,32 +324,32 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
324
324
  },
325
325
  save: function(form, successCallback, failCallback) {
326
326
  var self = this
327
- , params = self.serialiseForm(form)
327
+ , params = self.serialiseForm(form);
328
328
  UserController.save(self.user, params, successCallback, failCallback);
329
329
  }
330
330
  });
331
331
 
332
332
  var CreateUserView = new JS.Class(EditUserView, {
333
333
  titleText: function() {
334
- return "Create User";
334
+ return 'Create User';
335
335
  },
336
336
  aboveUserAttributes: function() {
337
- return "";
337
+ return '';
338
338
  },
339
339
  belowUserAttributes: function() {
340
- return "";
340
+ return '';
341
341
  },
342
342
  editableAttributes: function() {
343
- return ["login", "name", "email", "password", "level"];
343
+ return ['login', 'name', 'email', 'password', 'level'];
344
344
  },
345
345
  saveButtonText: function() {
346
- return "Create";
346
+ return 'Create';
347
347
  },
348
348
  save: function(form, successCallback, failCallback) {
349
349
  var self = this
350
- , params = self.serialiseForm(form)
350
+ , params = self.serialiseForm(form)
351
351
  , callback = function(params) {
352
- if (typeof successCallback === "function") {
352
+ if (typeof successCallback === 'function') {
353
353
  successCallback(params);
354
354
  }
355
355
  self.parent.addUser(self.user);
@@ -371,7 +371,7 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
371
371
  $.each(attributes, function(key, val) {
372
372
  self.set(key, val);
373
373
  });
374
- },
374
+ }
375
375
  });
376
376
 
377
377
  var UserAdmin = new JS.Class({
@@ -385,15 +385,15 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
385
385
  return;
386
386
  }
387
387
  var self = this;
388
- var outer = dom.div("#user-admin-container");
389
- var title = dom.div(".title.main").append(dom.span().text("CMS Users"));
390
- var contents = dom.div(".contents");
391
- var edit = dom.div(".edit").hide();
392
- var done = dom.a(".button.done").text("Done").click(function() {
388
+ var outer = dom.div('#user-admin-container');
389
+ var title = dom.div('.title.main').append(dom.span().text('CMS Users'));
390
+ var contents = dom.div('.contents');
391
+ var edit = dom.div('.edit').hide();
392
+ var done = dom.a('.button.done').text('Done').click(function() {
393
393
  self.close();
394
394
  });
395
- var addWrapper = dom.div(".add-user")
396
- var addButton = dom.a(".button.add").text("Create User").click(function() {
395
+ var addWrapper = dom.div('.add-user');
396
+ var addButton = dom.a('.button.add').text('Create User').click(function() {
397
397
  self.createUser();
398
398
  });
399
399
  addWrapper.append(addButton);
@@ -404,8 +404,8 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
404
404
  this.titleContainer = title;
405
405
  this.contentsContainer = contents;
406
406
  this.editContainer = edit;
407
- container.append(outer)
408
- ajax.get("/users", this.ready.bind(this));
407
+ container.append(outer);
408
+ ajax.get('/users', this.ready.bind(this));
409
409
  },
410
410
  createUser: function() {
411
411
  var user = new User(this, {});
@@ -434,11 +434,11 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
434
434
  },
435
435
  listEntry: function(user) {
436
436
  var self = this;
437
- var row = dom.div(".user");
438
- row.attr("id", "user-admin-" + user.get("id"));
439
- var cells = ["name", "level"].map(function(attr) {
437
+ var row = dom.div('.user');
438
+ row.attr('id', 'user-admin-' + user.get('id'));
439
+ var cells = ['name', 'level'].map(function(attr) {
440
440
  var div = dom.div().addClass(attr).text(user.get(attr)).click(function() {
441
- self.editUser(user)
441
+ self.editUser(user);
442
442
  return false;
443
443
  });
444
444
  user.watch(attr, function(newValue) {
@@ -448,19 +448,19 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
448
448
  });
449
449
  var disabledState = function(disabled) {
450
450
  if (disabled) {
451
- row.addClass("disabled");
451
+ row.addClass('disabled');
452
452
  } else {
453
- row.removeClass("disabled");
453
+ row.removeClass('disabled');
454
454
  }
455
455
  };
456
- user.watch("disabled", disabledState);
457
- disabledState(user.get("disabled"));
458
- var del = dom.div(".delete").click(function() {
456
+ user.watch('disabled', disabledState);
457
+ disabledState(user.get('disabled'));
458
+ var del = dom.div('.delete').click(function() {
459
459
  self.confirmDeleteUser(user);
460
460
  return false;
461
461
  });
462
462
  cells.push(del);
463
- row.append.apply(row, cells)
463
+ row.append.apply(row, cells);
464
464
  return row;
465
465
  },
466
466
  animationDuration: 300,
@@ -472,19 +472,19 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
472
472
  var animationDuration = self.animationDuration;
473
473
  var edit = this.editContainer.empty();
474
474
  var list = this.contentsContainer;
475
- var back = dom.div(".back");
475
+ var back = dom.div('.back');
476
476
  edit.append(back, viewInstance.view());
477
- edit.css({ left: "100%", opacity: 0 }).show();
478
- list.animate({ opacity: 0.2 }, animationDuration);
479
- edit.animate({ left: "48px", opacity: 1 }, animationDuration, "swing")
477
+ edit.css({ left: '100%', opacity: 0 }).show();
478
+ list.velocity({ opacity: 0.2 }, animationDuration);
479
+ edit.velocity({ left: '48px', opacity: 1 }, animationDuration, 'swing');
480
480
  viewInstance.activate();
481
481
  },
482
482
  closeUser: function() {
483
483
  var animationDuration = this.animationDuration;
484
484
  var edit = this.editContainer.empty();
485
485
  var list = this.contentsContainer;
486
- list.animate({ opacity: 1 }, animationDuration);
487
- edit.animate({ left: "100%", opacity: 0 }, animationDuration, function() {
486
+ list.velocity({ opacity: 1 }, animationDuration);
487
+ edit.velocity({ left: '100%', opacity: 0 }, animationDuration, function() {
488
488
  edit.empty().hide();
489
489
  });
490
490
  },
@@ -492,9 +492,9 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
492
492
  var dialogue = Spontaneous.Popover.open(event, new ConfirmDeletePopup(this, user));
493
493
  },
494
494
  deleteUser: function(user) {
495
- var url = ["/users", user.get("id")].join("/");
495
+ var url = ['/users', user.get('id')].join('/');
496
496
  ajax.del(url, {}, function(result, status) {
497
- if (status === "success") {
497
+ if (status === 'success') {
498
498
  user.listEntry.disappear();
499
499
  }
500
500
  });
@@ -513,7 +513,7 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
513
513
  // return 208;
514
514
  // },
515
515
  title: function() {
516
- return "Delete user “" + (this.user.get("login")) + "";
516
+ return 'Delete user “' + (this.user.get('login')) + '';
517
517
  },
518
518
  position_from_event: function(target) {
519
519
  var pos = this.position_from_element(target);
@@ -527,13 +527,13 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
527
527
  return false;
528
528
  });
529
529
 
530
- var ok = dom.a('.ok').text("Delete").click(function() {
530
+ var ok = dom.a('.ok').text('Delete').click(function() {
531
531
  self.close();
532
532
  __entry.deleteUser(self.user);
533
533
  return false;
534
534
  });
535
- var cancel = dom.a('.cancel').text("Cancel");
536
- w.append(cancel, ok)
535
+ var cancel = dom.a('.cancel').text('Cancel');
536
+ w.append(cancel, ok);
537
537
  return w;
538
538
  }
539
539
  });