spontaneous 0.2.0.beta1 → 0.2.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (335) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.locat +42 -0
  4. data/.travis/gemfiles/Gemfile.empty +7 -0
  5. data/.travis.yml +18 -0
  6. data/Gemfile +12 -8
  7. data/LICENSE +1 -1
  8. data/Rakefile +15 -157
  9. data/Readme.markdown +1 -1
  10. data/application/css/core.css.scss +22 -146
  11. data/application/css/definitions.css.scss +7 -3
  12. data/application/css/dialogue.css.scss +26 -1
  13. data/application/css/editing.css.scss +70 -28
  14. data/application/css/font.css.scss +1 -1
  15. data/application/css/popover.css.scss +2 -0
  16. data/application/css/top.css.scss +231 -0
  17. data/application/js/add_alias_dialogue.js +1 -1
  18. data/application/js/add_home_dialogue.js +1 -1
  19. data/application/js/ajax.js +61 -31
  20. data/application/js/box.js +4 -4
  21. data/application/js/conflicted_field_dialogue.js +1 -1
  22. data/application/js/content.js +5 -5
  23. data/application/js/dom.js +5 -0
  24. data/application/js/edit_panel.js +1 -0
  25. data/application/js/editing.js +1 -1
  26. data/application/js/extensions.js +8 -0
  27. data/application/js/field/boolean.js +31 -0
  28. data/application/js/field/file.js +32 -4
  29. data/application/js/field/image.js +24 -9
  30. data/application/js/field/markdown.js +87 -59
  31. data/application/js/field/select.js +1 -1
  32. data/application/js/field/webvideo.js +6 -1
  33. data/application/js/init.js +2 -2
  34. data/application/js/jquery-selection-position.js +130 -0
  35. data/application/js/location.js +4 -25
  36. data/application/js/meta_view/user_admin.js +2 -2
  37. data/application/js/metadata.js +2 -2
  38. data/application/js/page_browser.js +1 -1
  39. data/application/js/panel/root_menu.js +0 -1
  40. data/application/js/popover.js +27 -12
  41. data/application/js/popover_view.js +20 -4
  42. data/application/js/preview.js +31 -16
  43. data/application/js/progress.js +22 -21
  44. data/application/js/publish.js +18 -7
  45. data/application/js/sharded_upload.js +9 -6
  46. data/application/js/spontaneous.js +3 -1
  47. data/application/js/top_bar.js +264 -173
  48. data/application/js/upload.js +12 -5
  49. data/application/js/upload_manager.js +4 -3
  50. data/application/js/user.js +1 -2
  51. data/application/js/views/box_view.js +1 -1
  52. data/application/js/views/page_view.js +16 -5
  53. data/application/js/views/piece_view.js +5 -4
  54. data/application/static/font/fontawesome-webfont-1c66a4738b40ef0f6b1abca0ba9a796d.ttf +0 -0
  55. data/application/views/index.erb +6 -14
  56. data/application/views/login.erb +6 -25
  57. data/application/views/schema_modification_error.html.erb +3 -7
  58. data/db/migrations/20130114120000_create_revision_tables.rb +2 -2
  59. data/db/migrations/20130813111009_increase_path_length.rb +14 -0
  60. data/gem-public_cert.pem +20 -0
  61. data/lib/spontaneous/asset/app_compiler.rb +44 -0
  62. data/lib/spontaneous/asset/environment.rb +225 -0
  63. data/lib/spontaneous/asset.rb +2 -67
  64. data/lib/spontaneous/box.rb +0 -1
  65. data/lib/spontaneous/capistrano/deploy.rb +2 -2
  66. data/lib/spontaneous/capistrano/sync.rb +1 -1
  67. data/lib/spontaneous/cli/init.rb +36 -13
  68. data/lib/spontaneous/cli/server.rb +0 -1
  69. data/lib/spontaneous/cli/site.rb +2 -1
  70. data/lib/spontaneous/cli.rb +3 -1
  71. data/lib/spontaneous/collections/entry_set.rb +4 -12
  72. data/lib/spontaneous/collections/hash_with_fallback.rb +20 -0
  73. data/lib/spontaneous/collections/prototype_set.rb +6 -5
  74. data/lib/spontaneous/crypt.rb +2 -2
  75. data/lib/spontaneous/data_mapper/content_model/associations.rb +115 -63
  76. data/lib/spontaneous/data_mapper.rb +1 -1
  77. data/lib/spontaneous/errors.rb +6 -0
  78. data/lib/spontaneous/extensions/object_space.rb +6 -0
  79. data/lib/spontaneous/facet.rb +1 -0
  80. data/lib/spontaneous/field/base.rb +86 -13
  81. data/lib/spontaneous/field/boolean.rb +65 -0
  82. data/lib/spontaneous/field/file.rb +17 -6
  83. data/lib/spontaneous/field/html.rb +13 -0
  84. data/lib/spontaneous/field/image/size.rb +76 -0
  85. data/lib/spontaneous/field/image.rb +99 -414
  86. data/lib/spontaneous/field/tags.rb +36 -0
  87. data/lib/spontaneous/field/update.rb +1 -1
  88. data/lib/spontaneous/field/webvideo/fallback.rb +41 -0
  89. data/lib/spontaneous/field/webvideo/vimeo.rb +113 -0
  90. data/lib/spontaneous/field/webvideo/vine.rb +94 -0
  91. data/lib/spontaneous/field/webvideo/youtube.rb +133 -0
  92. data/lib/spontaneous/field/webvideo.rb +100 -250
  93. data/lib/spontaneous/field.rb +1 -1
  94. data/lib/spontaneous/generators/site/Gemfile.tt +5 -14
  95. data/lib/spontaneous/generators/site/assets/README.md +20 -0
  96. data/lib/spontaneous/generators/site/assets/css/site.scss +8 -0
  97. data/lib/spontaneous/generators/site/assets/js/site.js +6 -0
  98. data/lib/spontaneous/generators/site/config/deploy.rb.tt +9 -0
  99. data/lib/spontaneous/generators/site/config/user_levels.yml +14 -3
  100. data/lib/spontaneous/generators/site/public/README.md +12 -0
  101. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +2 -2
  102. data/lib/spontaneous/generators/site.rb +77 -35
  103. data/lib/spontaneous/layout.rb +6 -7
  104. data/lib/spontaneous/loader.rb +21 -13
  105. data/lib/spontaneous/media/file.rb +22 -9
  106. data/lib/spontaneous/media/image/attributes.rb +33 -0
  107. data/lib/spontaneous/media/image/format/gif.rb +4 -0
  108. data/lib/spontaneous/media/image/format/jpg.rb +17 -0
  109. data/lib/spontaneous/media/image/format/png.rb +4 -0
  110. data/lib/spontaneous/media/image/format/webp.rb +26 -0
  111. data/lib/spontaneous/media/image/format.rb +79 -0
  112. data/lib/spontaneous/media/image/optimizer.rb +69 -0
  113. data/lib/spontaneous/media/image/processor.rb +17 -0
  114. data/lib/spontaneous/media/image/renderable.rb +52 -0
  115. data/lib/spontaneous/media/image/skeptick.rb +70 -0
  116. data/lib/spontaneous/media/image.rb +50 -0
  117. data/lib/spontaneous/media/temp_file.rb +4 -0
  118. data/lib/spontaneous/media.rb +1 -0
  119. data/lib/spontaneous/model/core/aliases.rb +14 -8
  120. data/lib/spontaneous/model/core/boxes.rb +5 -2
  121. data/lib/spontaneous/model/core/entries.rb +4 -0
  122. data/lib/spontaneous/model/core/entry.rb +1 -0
  123. data/lib/spontaneous/model/core/fields.rb +5 -2
  124. data/lib/spontaneous/model/core/locks.rb +16 -0
  125. data/lib/spontaneous/model/core/media.rb +1 -15
  126. data/lib/spontaneous/model/core.rb +31 -1
  127. data/lib/spontaneous/model/page/controllers.rb +2 -2
  128. data/lib/spontaneous/model/page/formats.rb +1 -4
  129. data/lib/spontaneous/model/page/layouts.rb +6 -2
  130. data/lib/spontaneous/model/page/locks.rb +8 -2
  131. data/lib/spontaneous/model/page/page_tree.rb +2 -2
  132. data/lib/spontaneous/model/page/paths.rb +74 -9
  133. data/lib/spontaneous/model/page.rb +11 -3
  134. data/lib/spontaneous/model.rb +6 -6
  135. data/lib/spontaneous/output/context/render_cache.rb +23 -0
  136. data/lib/spontaneous/output/context.rb +56 -30
  137. data/lib/spontaneous/output/helpers/script_helper.rb +9 -53
  138. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +8 -40
  139. data/lib/spontaneous/output/template/renderer.rb +17 -5
  140. data/lib/spontaneous/output.rb +0 -1
  141. data/lib/spontaneous/paths.rb +6 -2
  142. data/lib/spontaneous/permissions/access_key.rb +18 -0
  143. data/lib/spontaneous/permissions/user.rb +1 -1
  144. data/lib/spontaneous/permissions.rb +4 -1
  145. data/lib/spontaneous/plugins/application/state.rb +19 -12
  146. data/lib/spontaneous/prototypes/field_prototype.rb +14 -8
  147. data/lib/spontaneous/published_revision.rb +7 -0
  148. data/lib/spontaneous/publishing/immediate.rb +43 -34
  149. data/lib/spontaneous/publishing/revision.rb +9 -6
  150. data/lib/spontaneous/rack/asset_server.rb +20 -0
  151. data/lib/spontaneous/rack/back/alias.rb +46 -0
  152. data/lib/spontaneous/rack/back/application_assets.rb +28 -0
  153. data/lib/spontaneous/rack/back/base.rb +34 -0
  154. data/lib/spontaneous/rack/back/changes.rb +19 -0
  155. data/lib/spontaneous/rack/back/content.rb +54 -0
  156. data/lib/spontaneous/rack/back/events.rb +38 -0
  157. data/lib/spontaneous/rack/back/field.rb +37 -0
  158. data/lib/spontaneous/rack/back/file.rb +118 -0
  159. data/lib/spontaneous/rack/back/helpers.rb +71 -0
  160. data/lib/spontaneous/rack/back/index.rb +16 -0
  161. data/lib/spontaneous/rack/back/login.rb +47 -0
  162. data/lib/spontaneous/rack/back/map.rb +24 -0
  163. data/lib/spontaneous/rack/back/page.rb +46 -0
  164. data/lib/spontaneous/rack/back/preview.rb +43 -0
  165. data/lib/spontaneous/rack/back/schema.rb +30 -0
  166. data/lib/spontaneous/rack/back/site.rb +25 -0
  167. data/lib/spontaneous/rack/back/site_assets.rb +13 -0
  168. data/lib/spontaneous/rack/back/unsupported_browser.rb +7 -0
  169. data/lib/spontaneous/rack/{user_admin.rb → back/user_admin.rb} +2 -5
  170. data/lib/spontaneous/rack/back.rb +85 -764
  171. data/lib/spontaneous/rack/cacheable_file.rb +3 -3
  172. data/lib/spontaneous/rack/front.rb +16 -9
  173. data/lib/spontaneous/rack/middleware/authenticate.rb +65 -0
  174. data/lib/spontaneous/rack/middleware/csrf.rb +66 -0
  175. data/lib/spontaneous/rack/middleware/reloader.rb +52 -0
  176. data/lib/spontaneous/rack/middleware/scope.rb +60 -0
  177. data/lib/spontaneous/rack/middleware.rb +6 -0
  178. data/lib/spontaneous/rack/page_controller.rb +18 -5
  179. data/lib/spontaneous/rack/public.rb +17 -11
  180. data/lib/spontaneous/rack.rb +34 -24
  181. data/lib/spontaneous/revision.rb +29 -2
  182. data/lib/spontaneous/schema/uid.rb +4 -3
  183. data/lib/spontaneous/schema/uid_map.rb +5 -24
  184. data/lib/spontaneous/schema.rb +1 -0
  185. data/lib/spontaneous/search/database.rb +8 -0
  186. data/lib/spontaneous/search/field.rb +1 -1
  187. data/lib/spontaneous/search/index.rb +3 -5
  188. data/lib/spontaneous/server.rb +1 -1
  189. data/lib/spontaneous/simultaneous.rb +1 -1
  190. data/lib/spontaneous/site/features.rb +4 -5
  191. data/lib/spontaneous/site/helpers.rb +22 -5
  192. data/lib/spontaneous/site/instance.rb +2 -2
  193. data/lib/spontaneous/site/selectors.rb +22 -3
  194. data/lib/spontaneous/storage/cloud.rb +13 -9
  195. data/lib/spontaneous/storage/local.rb +11 -6
  196. data/lib/spontaneous/style.rb +40 -23
  197. data/lib/spontaneous/utils/database/mysql_dumper.rb +1 -1
  198. data/lib/spontaneous/utils/smush_it.rb +1 -1
  199. data/lib/spontaneous/version.rb +1 -1
  200. data/lib/spontaneous.rb +35 -33
  201. data/spontaneous.gemspec +53 -787
  202. data/test/experimental/test_crypt.rb +56 -56
  203. data/test/experimental/test_features.rb +16 -27
  204. data/test/fixtures/assets/public1/css/data.css.scss +3 -0
  205. data/test/fixtures/assets/public1/css/image1.css.scss +4 -0
  206. data/test/fixtures/assets/public1/css/import.css.scss +1 -0
  207. data/test/fixtures/assets/public1/css/urlhash.css.scss +3 -0
  208. data/test/fixtures/assets/public1/js/a.js +1 -1
  209. data/test/fixtures/assets/public1/js/all.js +4 -0
  210. data/test/fixtures/assets/public1/js/{m.coffee → m.js.coffee} +1 -0
  211. data/test/fixtures/assets/public1/x.js +1 -0
  212. data/test/fixtures/assets/public2/css/all.css +4 -0
  213. data/test/fixtures/assets/public2/css/missing.css.scss +3 -0
  214. data/test/fixtures/assets/public2/i/y.png +0 -0
  215. data/test/fixtures/assets/public2/js/b.js +1 -1
  216. data/test/fixtures/assets/public2/js/c.js +1 -1
  217. data/test/fixtures/images/size.extended.webp +0 -0
  218. data/test/fixtures/images/size.lossless.webp +0 -0
  219. data/test/fixtures/images/size.lossy.webp +0 -0
  220. data/test/fixtures/schema/before.yml +4 -4
  221. data/test/fixtures/schema/schema.yml +1 -1
  222. data/test/fixtures/templates/aliases/aaa.html.cut +0 -0
  223. data/test/fixtures/templates/extended/partial_with_renderer.html.cut +1 -0
  224. data/test/fixtures/templates/extended/with_includes_and_renderer.html.cut +2 -0
  225. data/test/functional/test_application.rb +108 -106
  226. data/test/functional/test_back.rb +924 -930
  227. data/test/functional/test_front.rb +285 -238
  228. data/test/functional/test_user_manager.rb +75 -100
  229. data/test/integration/test_installation.rb +1 -1
  230. data/test/support/matchers.rb +12 -0
  231. data/test/support/minitest.rb +121 -0
  232. data/test/support/rack.rb +45 -0
  233. data/test/support/test_start_finish.rb +103 -0
  234. data/test/test_helper.rb +21 -68
  235. data/test/test_integration_helper.rb +1 -3
  236. data/test/unit/test_alias.rb +432 -408
  237. data/test/unit/test_asset_bundler.rb +58 -58
  238. data/test/unit/test_assets.rb +485 -155
  239. data/test/unit/test_async.rb +16 -37
  240. data/test/unit/test_authentication.rb +425 -457
  241. data/test/unit/test_boxes.rb +191 -191
  242. data/test/unit/test_changesets.rb +244 -254
  243. data/test/unit/test_config.rb +128 -142
  244. data/test/unit/test_content.rb +313 -359
  245. data/test/unit/test_content_inheritance.rb +29 -30
  246. data/test/unit/test_datamapper.rb +1205 -1080
  247. data/test/unit/test_datamapper_content.rb +49 -51
  248. data/test/unit/test_extensions.rb +23 -23
  249. data/test/unit/test_fields.rb +1488 -1180
  250. data/test/unit/test_formats.rb +158 -158
  251. data/test/unit/test_generators.rb +98 -40
  252. data/test/unit/test_helpers.rb +73 -76
  253. data/test/unit/test_image_size.rb +53 -22
  254. data/test/unit/test_images.rb +164 -165
  255. data/test/unit/test_layouts.rb +133 -122
  256. data/test/unit/test_logger.rb +14 -17
  257. data/test/unit/test_media.rb +69 -84
  258. data/test/unit/test_modifications.rb +513 -525
  259. data/test/unit/test_page.rb +462 -361
  260. data/test/unit/test_permissions.rb +379 -364
  261. data/test/unit/test_piece.rb +67 -75
  262. data/test/unit/test_plugins.rb +82 -89
  263. data/test/unit/test_prototype_set.rb +215 -216
  264. data/test/unit/test_prototypes.rb +114 -124
  265. data/test/unit/test_publishing.rb +252 -289
  266. data/test/unit/test_render.rb +167 -115
  267. data/test/unit/test_revisions.rb +436 -444
  268. data/test/unit/test_schema.rb +339 -309
  269. data/test/unit/test_search.rb +577 -574
  270. data/test/unit/test_serialisation.rb +136 -147
  271. data/test/unit/test_site.rb +252 -227
  272. data/test/unit/test_skeptick.rb +130 -0
  273. data/test/unit/test_storage.rb +46 -40
  274. data/test/unit/test_structure.rb +57 -66
  275. data/test/unit/test_styles.rb +104 -104
  276. data/test/unit/test_templates.rb +72 -57
  277. data/test/unit/test_type_hierarchy.rb +15 -16
  278. data/test/unit/test_visibility.rb +239 -257
  279. metadata +455 -326
  280. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +0 -283
  281. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +0 -30
  282. data/application/js/vendor/JS.Class-2.1.5/README +0 -30
  283. data/application/js/vendor/JS.Class-2.1.5/min/command.js +0 -1
  284. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +0 -1
  285. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +0 -1
  286. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +0 -1
  287. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +0 -1
  288. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +0 -1
  289. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +0 -1
  290. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +0 -1
  291. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +0 -1
  292. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +0 -1
  293. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +0 -1
  294. data/application/js/vendor/JS.Class-2.1.5/min/package.js +0 -1
  295. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +0 -1
  296. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +0 -1
  297. data/application/js/vendor/JS.Class-2.1.5/min/set.js +0 -1
  298. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +0 -1
  299. data/application/js/vendor/JS.Class-2.1.5/min/state.js +0 -1
  300. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +0 -16
  301. data/application/js/vendor/jquery-1.6.2.min.js +0 -18
  302. data/application/js/vendor/jquery-ui-1.8.16.custom.min.js +0 -791
  303. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +0 -415
  304. data/application/static/font/fontawesome-webfont-5c5c21100a346972a82c34c5e96ffcfe.ttf +0 -0
  305. data/application/static/select-arrow-6e7dd3745b00e934b0d7a3250c46558b.png +0 -0
  306. data/bin/limit-upload +0 -5
  307. data/bin/unlimit-upload +0 -3
  308. data/lib/spontaneous/asset/file.rb +0 -25
  309. data/lib/spontaneous/asset/source.rb +0 -28
  310. data/lib/spontaneous/image_size.rb +0 -123
  311. data/lib/spontaneous/output/assets/compression.rb +0 -58
  312. data/lib/spontaneous/output/assets.rb +0 -32
  313. data/lib/spontaneous/rack/around_back.rb +0 -20
  314. data/lib/spontaneous/rack/around_front.rb +0 -27
  315. data/lib/spontaneous/rack/around_preview.rb +0 -22
  316. data/lib/spontaneous/rack/assets.rb +0 -126
  317. data/lib/spontaneous/rack/authentication.rb +0 -20
  318. data/lib/spontaneous/rack/cookie_authentication.rb +0 -38
  319. data/lib/spontaneous/rack/helpers.rb +0 -52
  320. data/lib/spontaneous/rack/http.rb +0 -18
  321. data/lib/spontaneous/rack/media.rb +0 -30
  322. data/lib/spontaneous/rack/query_authentication.rb +0 -35
  323. data/lib/spontaneous/rack/reloader.rb +0 -45
  324. data/lib/spontaneous/rack/user_helpers.rb +0 -28
  325. /data/{README → application/js/field/markdown/text_command.js} +0 -0
  326. /data/application/js/vendor/{JS.Class-2.1.5/min/core.js → js.class-2.1.5.min.js} +0 -0
  327. /data/test/fixtures/assets/public1/css/{a.scss → a.css.scss} +0 -0
  328. /data/{lib/spontaneous/generators/site/public/css/site.scss → test/fixtures/assets/public1/x.css} +0 -0
  329. /data/{lib/spontaneous/generators/site/public/js/.empty_directory → test/fixtures/assets/public1/x.png} +0 -0
  330. /data/test/fixtures/assets/public2/css/{b.scss → b.css.scss} +0 -0
  331. /data/test/fixtures/assets/public2/js/{n.coffee → n.js.coffee} +0 -0
  332. /data/test/fixtures/back/{public → assets}/css/sass_include.scss +0 -0
  333. /data/test/fixtures/back/{public → assets}/css/sass_template.scss +0 -0
  334. /data/test/fixtures/back/{public → assets}/js/coffeescript.coffee +0 -0
  335. /data/{lib/spontaneous/generators/site/public/js/site.js → test/fixtures/templates/aliases/aa_alias.html.cut} +0 -0
@@ -0,0 +1,31 @@
1
+ Spontaneous.Field.Boolean = (function($, S) {
2
+ var dom = S.Dom;
3
+ var BooleanField = new JS.Class(Spontaneous.Field.String, {
4
+ edit: function() {
5
+ var self = this
6
+ , w = dom.div(dom.id(self.css_id()))
7
+ , input = self.input() // ensure we have created the radio inputs $on & $off
8
+ , labels = self.type.labels
9
+ , label = function(label, radio) { return dom.label().text(label).prepend(radio); }
10
+ ;
11
+ w.append(label(labels['true'], self.$on), label(labels['false'], self.$off));
12
+ return w;
13
+ },
14
+ generate_input: function() {
15
+ var self = this
16
+ , checked = (this.get('unprocessed_value') == 'true')
17
+ , click = function() { self.editor.field_focus(self.input()); }
18
+ , on = dom.radio({'name':this.form_name(), 'value': 'true', 'checked': checked})
19
+ , off = dom.radio({'name':this.form_name(), 'value': 'false', 'checked': !checked})
20
+ ;
21
+ self.$on = on;
22
+ self.$off = off;
23
+ return $(on).add(off).click(click);
24
+ },
25
+ edited_value: function() {
26
+ return this.input().filter(':checked').val();
27
+ }
28
+ });
29
+ return BooleanField;
30
+ })(jQuery, Spontaneous);
31
+
@@ -4,11 +4,40 @@ Spontaneous.Field.File = (function($, S) {
4
4
  var FileField = new JS.Class(Spontaneous.Field.String, {
5
5
  selected_files: false,
6
6
 
7
+ currentValue: function() {
8
+ var pending, v = this.get('value');
9
+ if ((pending = v['__pending__'])) {
10
+ return pending['value'];
11
+ }
12
+ return v;
13
+ },
14
+
15
+ currentFilename: function() {
16
+ return this.currentValue()['filename'];
17
+ },
18
+
19
+ currentFilesize: function() {
20
+ return this.currentValue()['filesize'];
21
+ },
22
+
23
+ currentEditValue: function() {
24
+ var value, pending, ui, v = this.get('value');
25
+ if ((pending = v['__pending__'])) {
26
+ return pending['value'];
27
+ }
28
+ value = v['original'];
29
+ if ((ui = v['__ui__'])) {
30
+ value['path'] = value['src'];
31
+ value['src'] = ui['src'];
32
+ }
33
+ return value;
34
+ },
35
+
7
36
  preview: function() {
8
37
  Spontaneous.UploadManager.register(this);
9
38
  var self = this
10
- , value = this.get('value')
11
- , filename = this.filename(value);
39
+ , value = this.currentValue()
40
+ , filename = this.currentFilename();
12
41
  var wrap = dom.div('.file-field');
13
42
  var dropper = dom.div('.file-drop');
14
43
 
@@ -61,7 +90,7 @@ Spontaneous.Field.File = (function($, S) {
61
90
  }
62
91
  };
63
92
  if (value) {
64
- set_info(value.html, this.filename(value), value.filesize);
93
+ set_info(value.html, this.currentFilename(), this.currentFilesize());
65
94
  }
66
95
 
67
96
  dropper.append(this.progress_bar().parent());
@@ -237,7 +266,6 @@ Spontaneous.Field.File = (function($, S) {
237
266
  this.processed_value();
238
267
  },
239
268
  set_edited_value: function(value) {
240
- console.log('set_edited_value', value, this.edited_value(), this.original_value())
241
269
  if (value === this.edited_value()) {
242
270
  // do nothing
243
271
  } else {
@@ -1,5 +1,6 @@
1
1
  // console.log('Loading ImageField...')
2
2
  Spontaneous.Field.Image = (function($, S) {
3
+ "use strict";
3
4
  var dom = S.Dom;
4
5
  var ImageFieldConflictView = new JS.Class(S.Field.String.ConflictView, {
5
6
 
@@ -58,13 +59,31 @@ Spontaneous.Field.Image = (function($, S) {
58
59
  },
59
60
 
60
61
  currentValue: function() {
61
- var v = this.get('value');
62
+ var pending, v = this.get('value');
62
63
  if ((pending = v['__pending__'])) {
64
+ pending['path'] = pending['src'];
63
65
  return pending['value'];
64
66
  }
65
67
  return v['__ui__'] || v['original'];
66
68
  },
67
69
 
70
+ currentEditValue: function() {
71
+ var value, pending, ui, v = this.get('value');
72
+ if ((pending = v['__pending__'])) {
73
+ return pending['value'];
74
+ }
75
+ value = v['original'];
76
+ if ((ui = v['__ui__'])) {
77
+ value['path'] = value['src'];
78
+ value['src'] = ui['src'];
79
+ }
80
+ return value;
81
+ },
82
+
83
+ currentFilename: function() {
84
+ var v = this.currentValue();
85
+ return v['filename'];
86
+ },
68
87
  /*
69
88
  * HACK: The async nature of image updates means that the version setting
70
89
  * may be out of date not because of the actions of another, but because
@@ -80,7 +99,7 @@ Spontaneous.Field.Image = (function($, S) {
80
99
  * weird problems with simultaneous updates.
81
100
  */
82
101
  version: function() {
83
- var value = this.get("value");
102
+ var pending, value = this.get("value");
84
103
  if ((pending = value["__pending__"])) {
85
104
  return pending["version"];
86
105
  }
@@ -245,7 +264,7 @@ Spontaneous.Field.Image = (function($, S) {
245
264
  },
246
265
  edit: function() {
247
266
  var wrap = dom.div({'style':'position:relative;'}),
248
- value = this.currentValue(),
267
+ value = this.currentEditValue(),
249
268
  src = value.src,
250
269
  img = dom.img({'src':src}),
251
270
  info, sizes, filename_info, filesize_info, dimensions_info;
@@ -350,8 +369,8 @@ Spontaneous.Field.Image = (function($, S) {
350
369
  wrap.append(img, actions, info);
351
370
 
352
371
  if (value) {
353
- var s = value.src.split('/'), filename = s[s.length - 1];
354
- set_info(filename, value.filesize, value.width, value.height);
372
+ // var s = value.path.split('/'), filename = s[s.length - 1];
373
+ set_info(this.currentFilename(), value.filesize, value.width, value.height);
355
374
  }
356
375
  this.preview_img = img;
357
376
  return wrap;
@@ -370,10 +389,6 @@ Spontaneous.Field.Image = (function($, S) {
370
389
  this.input = this.generate_input();
371
390
  return this.input;
372
391
  },
373
-
374
- edited_value: function() {
375
- return this.input.val();
376
- },
377
392
  cancel_edit: function() {
378
393
  this.image.attr('src', this.currentValue().src);
379
394
  },
@@ -447,7 +447,8 @@ Spontaneous.Field.Markdown = (function($, S) {
447
447
  },
448
448
  page_selected: function(page) {
449
449
  this.url_input.val(page.path);
450
- }
450
+ },
451
+ scroll: true
451
452
  });
452
453
 
453
454
  var PageSelector = new JS.Class({
@@ -502,38 +503,25 @@ Spontaneous.Field.Markdown = (function($, S) {
502
503
  state = this.fix_selection_whitespace(state)
503
504
  var selected = state.selection, m, n, start = state.start, end = state.end;
504
505
 
505
- // cursor is either in the [] or in the ()
506
- // first test for being in []
507
- m = /(\[[^\]]*)$/.exec(state.before);
508
- if (m) {
509
- n = /^(.*\]\(.+?\))/.exec(state.after);
510
- if (n) {
511
- start -= m[1].length;
512
- selected += m[1];
513
- end += n[1].length;
514
- selected += n[1];
515
- }
516
- }
517
- // now test for being in the ()
518
- m = /(\[.+?\]\([^\)]*)$/.exec(state.before);
519
- if (m) {
520
- n = /^(.*?\))/.exec(state.after);
521
- if (n) {
522
- start -= m[1].length;
523
- selected += m[1];
524
- end += n[1].length;
525
- selected += n[1];
526
- }
527
- }
528
- // finally check for being exactly between the two
529
- m = /(\[.+?\])$/.exec(state.before);
530
- if (m) {
531
- n = /^(\(.+?\))/.exec(state.after);
532
- if (n) {
533
- start -= m[1].length;
534
- selected += m[1];
535
- end += n[1].length;
536
- selected += n[1];
506
+ var linkExp = /(\[[^\]]*?\]\([^\ ]*?\))/g;
507
+ var text = this.input.val(), cursor = start, match = 0;
508
+ // First look at all the text before and move the cursor past any links.
509
+ // This stops us expanding backwards to grab any link found in the text before
510
+ // the selection start.
511
+ do {
512
+ if ((m = linkExp.exec(state.before))) { match = linkExp.lastIndex; }
513
+ } while (m && (linkExp.lastIndex < cursor));
514
+
515
+ // now we've established where the last whole link lives, and can stop ourselves
516
+ // including it in the search, we can look backwards
517
+ // until we find the start of any link that's around the current selection.
518
+ while ((cursor >= match) && (text[cursor] !== "[")) { cursor--; }
519
+
520
+ if (text[cursor] === "[") {
521
+ if (m = linkExp.exec(text.substr(cursor))) {
522
+ start = cursor;
523
+ end = cursor + m[1].length;
524
+ selected = m[1];
537
525
  }
538
526
  }
539
527
  return {selection:selected, start:start, end:end};
@@ -637,45 +625,86 @@ Spontaneous.Field.Markdown = (function($, S) {
637
625
  this.callSuper();
638
626
  },
639
627
  toolbar: function() {
640
- if (!this._toolbar) {
641
- this._wrapper = dom.div([dom.id('editor-'+this.css_id()), '.markdown-editor']);
642
- // $(dom.div, {'class':'markdown-editor', 'id':'editor-'+this.css_id()});
643
- this._toolbar = dom.div('.md-toolbar');
644
- this.commands = [];
645
- var input = this.input();
646
- for (var i = 0, c = this.actions, ii = c.length; i < ii; i++) {
628
+ var self = this;
629
+ if (!self._toolbar) {
630
+ self._wrapper = dom.div([dom.id('editor-'+self.css_id()), '.markdown-editor']);
631
+ self._wrapper.append(self.popupToolbar());
632
+ }
633
+ return self._wrapper;
634
+ },
635
+ popupToolbar: function() {
636
+ var self = this;
637
+ if (!self._popupToolbar) {
638
+ var toolbar = dom.div('.md-toolbar');
639
+ var arrow = dom.div(".arrow");
640
+ toolbar.append(arrow);
641
+ self.commands = [];
642
+ var input = self.input();
643
+ for (var i = 0, c = self.actions, ii = c.length; i < ii; i++) {
647
644
  var cmd_class = c[i], cmd = new cmd_class(input);
648
- this.commands.push(cmd);
649
- this._toolbar.append(cmd.button());
645
+ self.commands.push(cmd);
646
+ toolbar.append(cmd.button());
650
647
  }
651
- this._wrapper.append(this._toolbar);
652
- // input.css('height', '');
648
+ toolbar.hide();
649
+ self._popupToolbar = toolbar;
653
650
  }
654
- return this._wrapper;
651
+ return self._popupToolbar;
655
652
  },
656
653
  edit: function() {
657
- this.expanded = false;
658
- var input = this.input();
659
- input.unbind('select.markdown').unbind('click.markdown').unbind('keyup.markdown');
660
- input.bind('select.markdown', this.on_select.bind(this))
661
- input.bind('click.markdown', this.on_select.bind(this))
662
- input.bind('keyup.markdown', this.on_select.bind(this))
654
+ var self = this, input = self.input();
655
+ self.expanded = false;
656
+ // clear previously assigned bindings
657
+ input.unbind('select.markdown');
658
+ input.bind('select.markdown', self.on_select.bind(self))
659
+ // input.bind('click.markdown', self.on_select.bind(self))
660
+ // input.bind('keyup.markdown', self.on_select.bind(self))
663
661
  return input;
664
662
  },
665
663
  close_edit: function() {
666
- this._input = null;
667
- this._toolbar = null;
668
- this.commands = [];
669
- this.expanded = false;
670
- this.callSuper();
664
+ var self = this;
665
+ self._input = null;
666
+ self._toolbar = null;
667
+ self._popupToolbar = null;
668
+ self.commands = [];
669
+ self.expanded = false;
670
+ self.callSuper();
671
671
  },
672
672
  // iterates through all the buttons and lets them highlight themselves depending on the
673
673
  // currently selected text
674
674
  on_select: function(event) {
675
- var state = TextCommand.get_state(this.input());
675
+ var input = this.input(), toolbar = this.popupToolbar(), state = TextCommand.get_state(input);
676
676
  $.each(this.commands, function() {
677
677
  this.respond_to_selection(state);
678
678
  });
679
+ input.showSelectionPopup(toolbar, function(position) {
680
+ var tools = {width: toolbar.width(), height: toolbar.height()},
681
+ text = { width: input.width(), height: input.height()};
682
+ // console.log("position", position, tools, text);
683
+ var place = {
684
+ left: position.left,
685
+ // 5 is half the height of the arrow
686
+ // 7 is the padding of the field
687
+ top: position.top + 7 - 5 - tools.height
688
+ };
689
+ var dx = 0;
690
+ var arrow = toolbar.find(".arrow"),
691
+ arrowLeft = (position.width / 2) - 5;
692
+ // if the selection is narrow the arrow can peek over the left
693
+ // of the toolbar. This shifts everything over and keeps it neat.
694
+ if (position.width < 40) {
695
+ place.left = place.left - 15;
696
+ arrowLeft += 15;
697
+ }
698
+ if ((place.left + tools.width) > (text.width)) {
699
+ dx = ((place.left + tools.width) - (text.width + 20));
700
+ place.left = place.left - dx;
701
+ arrowLeft += dx;
702
+ }
703
+
704
+ arrowLeft = Math.min(toolbar.width() - 30, arrowLeft);
705
+ arrow.css("left", dom.px(arrowLeft));
706
+ return place;
707
+ });
679
708
  }
680
709
  });
681
710
 
@@ -688,9 +717,8 @@ Spontaneous.Field.Markdown = (function($, S) {
688
717
  H1: H1,
689
718
  H2: H2,
690
719
  Link: Link
691
-
692
-
693
720
  });
721
+
694
722
  return MarkdownField;
695
723
  })(jQuery, Spontaneous);
696
724
 
@@ -25,7 +25,7 @@ Spontaneous.Field.Select = (function($, S) {
25
25
  },
26
26
 
27
27
  optionsURL: function() {
28
- return ["/options", this.type.schema_id, this.content.id()].join("/");
28
+ return ["/field/options", this.type.schema_id, this.content.id()].join("/");
29
29
  },
30
30
 
31
31
  append_select: function(wrapper, option_list) {
@@ -10,7 +10,12 @@ Spontaneous.Field.WebVideo = (function($, S) {
10
10
  // return this.get_input();
11
11
  // }
12
12
  preview: function() {
13
- var value = this.get('value')
13
+ // oh god. I need to have a UI only version of the player code which disables autoplay etc
14
+ // at the moment the value passed to the ui is the same as the one used for templates
15
+ // which, in the case of autoplay, is wildly inappropriate
16
+ // at the same time I want to replace an immediately inserted video player with an
17
+ // image + play button to reduce the impact of multiple videos on the cms ui load time
18
+ var value = this.get('value').replace(/autoplay=1/, '')
14
19
  , iframe = dom.iframe({src:value, frameborder: 0, border: 0}).css({position: "absolute", top:0, left:0, height: "100%", width: "100%"});
15
20
  if (!value) { // don't fill up the page with empty iframes...
16
21
  return dom.div();
@@ -20,9 +20,9 @@ Spontaneous.Init = (function($, S) {
20
20
  b.append(content_area.init());
21
21
  b.append(S.StatusBar.init());
22
22
 
23
- S.Metadata.load(function() {
23
+ S.Metadata.load(function(metadata) {
24
24
  location.init(function() {
25
- top_bar.init();
25
+ top_bar.init(metadata);
26
26
  });
27
27
  });
28
28
  };
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Based on an original plugin "jquery-caret-position-getter"
3
+ *
4
+ * https://github.com/beviz/jquery-caret-position-getter
5
+ *
6
+ * @license under Apache license
7
+ * @author Bevis Zhao (i@bevis.me, http://bevis.me)
8
+ */
9
+ (function($) {
10
+ "use strict";
11
+
12
+ var calculator = {
13
+ // key styles
14
+ primaryStyles: ['fontFamily', 'fontSize', 'fontWeight', 'fontVariant',
15
+ 'fontStyle', 'paddingLeft', 'paddingTop', 'paddingBottom', 'paddingRight',
16
+ 'marginLeft', 'marginTop', 'marginBottom', 'marginRight', 'borderLeftColor',
17
+ 'borderTopColor', 'borderBottomColor', 'borderRightColor', 'borderLeftStyle',
18
+ 'borderTopStyle', 'borderBottomStyle', 'borderRightStyle', 'borderLeftWidth',
19
+ 'borderTopWidth', 'borderBottomWidth', 'borderRightWidth', 'line-height',
20
+ 'outline'],
21
+
22
+ specificStyle: {
23
+ 'white-space': 'pre-wrap',
24
+ 'word-wrap': 'normal',
25
+ 'overflow-x': 'hidden',
26
+ 'overflow-y': 'auto'
27
+ },
28
+
29
+ simulator : $('<div id="textarea_simulator"/>').css({
30
+ position: 'absolute',
31
+ top: 0,
32
+ left: 0,
33
+ visibility: 'hidden'
34
+ }).appendTo(document.body),
35
+
36
+ // calculate position
37
+ getSelectionPosition: function() {
38
+ var cal = calculator, self = this, element = self[0], elementOffset = self.offset();
39
+
40
+ cal.simulator.empty();
41
+ // clone primary styles to imitate textarea
42
+ $.each(cal.primaryStyles, function(index, styleName) {
43
+ self.cloneStyle(cal.simulator, styleName);
44
+ });
45
+
46
+ // caculate width and height
47
+ cal.simulator.css($.extend({
48
+ 'width': self.width(),
49
+ 'height': self.height()
50
+ }, cal.specificStyle));
51
+
52
+ var value = self.val(),
53
+ selectStart = element.selectionStart,
54
+ selectEnd = element.selectionEnd;
55
+
56
+ if (selectEnd === selectStart) { return false; };
57
+
58
+ var beforeText = value.substring(0, selectStart),
59
+ selectedText = value.substring(selectStart, selectEnd),
60
+ afterText = value.substring(selectEnd);
61
+
62
+ var before = $('<span class="before"/>').html(beforeText),
63
+ focus = $('<span class="focus"/>').html(selectedText),
64
+ after = $('<span class="after"/>').html(afterText);
65
+
66
+ cal.simulator.append(before, focus, after);
67
+
68
+ var focusOffset = focus.offset(), simulatorOffset = cal.simulator.offset();
69
+
70
+ return {
71
+ top: focusOffset.top - simulatorOffset.top - element.scrollTop,
72
+ left: focus[0].offsetLeft - cal.simulator[0].offsetLeft - element.scrollLeft,
73
+ width: focus.width(),
74
+ height: focus.height()
75
+ };
76
+ }
77
+ };
78
+
79
+ var showPopup = function(textarea, popup, offsetCalculator) {
80
+ var pos = calculator.getSelectionPosition.call(textarea);
81
+ if (pos === false) {
82
+ popup.hide();
83
+ return false;
84
+ }
85
+ var position = textarea.position(), height = textarea.height(),
86
+ top = position.top + pos.top, bottom = position.top + height;
87
+
88
+ // In order to use the size of the popup in the positioning calculations
89
+ // it needs to be visible in the dom.
90
+ popup.css("visibility", "hidden").show();
91
+ var place = offsetCalculator(pos);
92
+ popup.hide().css("visibility", "visible");
93
+ if (top >= position.top && top < bottom) {
94
+ popup.css({
95
+ left: place.left,
96
+ top: place.top
97
+ }).fadeIn(100)
98
+ } else {
99
+ popup.fadeOut(100);
100
+ }
101
+ return true;
102
+ }
103
+ $.fn.extend({
104
+ getComputedStyle: function(styleName) {
105
+ if (this.length == 0) return;
106
+ var self = this[0], result = this.css(styleName);
107
+ result = result || ($.browser.msie ? self.currentStyle[styleName]: document.defaultView.getComputedStyle(self, null)[styleName]);
108
+ return result;
109
+ },
110
+ cloneStyle: function(target, styleName) {
111
+ var styleVal = this.getComputedStyle(styleName);
112
+ if (!!styleVal) {
113
+ $(target).css(styleName, styleVal);
114
+ }
115
+ },
116
+ showSelectionPopup: function(popup, offsetCalculator) {
117
+ var self = $(this);
118
+ var callback = function() {
119
+ var selected = showPopup(self, popup, offsetCalculator);
120
+ if (!selected) {
121
+ self.unbind("scroll.popup").unbind("mouseup.popup");
122
+ }
123
+ };
124
+ self.bind("scroll.popup", callback);
125
+ self.bind("mouseup.popup", callback.delay(1));
126
+ callback();
127
+ }
128
+ });
129
+ }(jQuery));
130
+
@@ -83,7 +83,8 @@ Spontaneous.Location = (function($, S) {
83
83
  },
84
84
  load_map: function() {
85
85
  },
86
- location_loaded: function(location, xhr) {
86
+ location_loaded: function(location, status, xhr) {
87
+ S.Popover.close();
87
88
  if (xhr.status === 406) { // Code returned if site is missing a root page
88
89
  var d = new Spontaneous.AddHomeDialogue(Spontaneous.Types.get('types'));
89
90
  d.open();
@@ -127,7 +128,7 @@ Spontaneous.Location = (function($, S) {
127
128
  if (this.location() && path === this.location().path) {
128
129
  return this.location();
129
130
  }
130
- this.retrieve('/location'+path, this.location_loaded.bind(this));
131
+ this.retrieve('/map/path'+path, this.location_loaded.bind(this));
131
132
  },
132
133
  find_id: function(id) {
133
134
  if (this.location() && id === this.location().id) {
@@ -155,30 +156,8 @@ Spontaneous.Location = (function($, S) {
155
156
  }
156
157
  return path;
157
158
  },
158
- // easier to create my own 304 sensitive ajax request
159
- // than peg on a content cache to jQuery's
160
159
  retrieve: function(url, callback) {
161
- var self = this
162
- , req = new XMLHttpRequest()
163
- , data;
164
- req.open("GET", ajax.request_url(url, true), true)
165
- req.setRequestHeader('If-Modified-Since', self.lastModified(url));
166
- req.onreadystatechange = function(event) {
167
- if (req.readyState === XMLHttpRequest.DONE) {
168
- if (req.status === 200) {
169
- data = jQuery.parseJSON(req.responseText);
170
- self.setLocationCache(url, req.getResponseHeader("Last-Modified"), data)
171
- }
172
- if (req.status === 304) {
173
- data = self.getLocationCache(url)
174
- }
175
- if (req.status === 401) {
176
- S.Ajax.unauthorized();
177
- }
178
- callback(data, req);
179
- }
180
- };
181
- req.send(null);
160
+ ajax.get(url, {}, callback, {ifModified: true, cache: true});
182
161
  },
183
162
  lastModified: function(path) {
184
163
  return (this.locationCache[path] || {}).lastModified;
@@ -515,8 +515,8 @@ Spontaneous.MetaView.UserAdmin = (function($, S){
515
515
  title: function() {
516
516
  return "Delete user “" + (this.user.get("login")) + "”";
517
517
  },
518
- position_from_event: function(event) {
519
- var pos = this.position_from_element(event);
518
+ position_from_event: function(target) {
519
+ var pos = this.position_from_element(target);
520
520
  pos.left += 40;
521
521
  return pos;
522
522
  },
@@ -7,12 +7,12 @@ Spontaneous.Metadata = (function($, S) {
7
7
  S.Types.loaded(metadata.types);
8
8
  S.User.loaded(metadata.user);
9
9
  S.Services.loaded(metadata.services);
10
- if (callback) { callback.call(); };
10
+ if (callback) { callback(metadata); };
11
11
  };
12
12
  };
13
13
  return {
14
14
  load: function(onComplete) {
15
- ajax.get('/metadata', loaded(onComplete));
15
+ ajax.get('/site', loaded(onComplete));
16
16
  }
17
17
  };
18
18
  }(jQuery, Spontaneous));
@@ -52,7 +52,7 @@ Spontaneous.PageBrowser = (function($, S) {
52
52
  get_page_list: function() {
53
53
  var path;
54
54
  if (typeof this.origin === 'string') {
55
- path = '/location' + this.origin;
55
+ path = '/map/path' + this.origin;
56
56
  } else {
57
57
  path = '/map/' + this.origin.id;
58
58
  }
@@ -22,7 +22,6 @@
22
22
  return outer;
23
23
  },
24
24
  after_close: function() {
25
- console.log("root menu after close")
26
25
  if (this.afterCloseCallback && (typeof this.afterCloseCallback === "function")) {
27
26
  this.afterCloseCallback();
28
27
  }