locomotivecms 3.0.0.rc2 → 3.0.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/README.md +2 -1
  4. data/app/api/locomotive/api/entities/site_entity.rb +8 -0
  5. data/app/api/locomotive/api/exception_rescuers.rb +1 -1
  6. data/app/api/locomotive/api/forms/content_entry_form.rb +4 -3
  7. data/app/api/locomotive/api/helpers/params_helper.rb +21 -3
  8. data/app/api/locomotive/api/resources/current_site_resource.rb +1 -1
  9. data/app/api/locomotive/api/resources/site_resource.rb +2 -2
  10. data/app/assets/images/locomotive/deadend.png +0 -0
  11. data/app/assets/javascripts/locomotive/not_logged_in.js.coffee +1 -1
  12. data/app/assets/javascripts/locomotive/utils/core_ext.js +1 -1
  13. data/app/assets/javascripts/locomotive/utils/wysihtml5.js.coffee +43 -17
  14. data/app/assets/javascripts/locomotive/views/application_view.js.coffee +5 -1
  15. data/app/assets/javascripts/locomotive/views/editable_elements/edit_view.js.coffee +47 -0
  16. data/app/assets/javascripts/locomotive/views/editable_elements/iframe_view.js.coffee +59 -0
  17. data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +19 -92
  18. data/app/assets/javascripts/locomotive/views/editable_elements/page_view.js.coffee +81 -0
  19. data/app/assets/javascripts/locomotive/views/editable_elements/text_highlighter_view.js.coffee +76 -0
  20. data/app/assets/javascripts/locomotive/views/inputs/rte/edit_table_view.js.coffee +35 -0
  21. data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +14 -10
  22. data/app/assets/javascripts/locomotive/views/inputs/rte/link_view.js.coffee +25 -15
  23. data/app/assets/javascripts/locomotive/views/inputs/rte/table_view.js.coffee +82 -0
  24. data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +64 -23
  25. data/app/assets/javascripts/locomotive/views/inputs/text_view.js.coffee +11 -6
  26. data/app/assets/javascripts/locomotive.js +2 -2
  27. data/app/assets/stylesheets/locomotive/application.scss +1 -3
  28. data/app/assets/stylesheets/locomotive/base/_form.scss +2 -1
  29. data/app/assets/stylesheets/locomotive/base/_typography.scss +3 -2
  30. data/app/assets/stylesheets/locomotive/base/form/_base.scss +5 -0
  31. data/app/assets/stylesheets/locomotive/base/form/_rte.scss +42 -0
  32. data/app/assets/stylesheets/locomotive/error.scss +1 -1
  33. data/app/assets/stylesheets/locomotive/globals/_mixins.scss +41 -48
  34. data/app/assets/stylesheets/locomotive/globals/_variables.scss +202 -121
  35. data/app/assets/stylesheets/locomotive/layouts/_not_logged_in.scss +8 -9
  36. data/app/assets/stylesheets/locomotive/live_editing_error.scss +19 -0
  37. data/app/assets/stylesheets/locomotive/live_editing_iframe.scss +84 -0
  38. data/app/assets/stylesheets/locomotive/unauthorized/_forms.scss +63 -0
  39. data/app/assets/stylesheets/locomotive/unauthorized/_keyframes.scss +31 -0
  40. data/app/assets/stylesheets/locomotive/unauthorized/_notify.scss +85 -0
  41. data/app/assets/stylesheets/locomotive/unauthorized/_public.scss +129 -0
  42. data/app/assets/stylesheets/locomotive/unauthorized/_type.scss +14 -0
  43. data/app/assets/stylesheets/locomotive/unauthorized/_variables.scss +54 -0
  44. data/app/assets/stylesheets/locomotive/unauthorized.scss +34 -0
  45. data/app/helpers/locomotive/dashboard_helper.rb +1 -1
  46. data/app/inputs/locomotive/rte_input.rb +12 -0
  47. data/app/models/locomotive/concerns/page/editable_elements.rb +0 -2
  48. data/app/models/locomotive/editable_element.rb +1 -1
  49. data/app/services/locomotive/content_asset_service.rb +1 -1
  50. data/app/services/locomotive/page_parsing_service.rb +4 -2
  51. data/app/views/locomotive/editable_elements/index.html.slim +1 -1
  52. data/app/views/locomotive/layouts/not_logged_in.html.slim +13 -9
  53. data/app/views/locomotive/passwords/edit.html.slim +13 -13
  54. data/app/views/locomotive/passwords/new.html.slim +14 -11
  55. data/app/views/locomotive/registrations/new.html.slim +14 -13
  56. data/app/views/locomotive/sessions/new.html.slim +14 -13
  57. data/app/views/locomotive/shared/rte/_markdown_toolbar.html.slim +0 -30
  58. data/app/views/locomotive/shared/rte/_table_popover.html.slim +17 -0
  59. data/app/views/locomotive/shared/rte/_toolbar.html.slim +48 -11
  60. data/config/initializers/simple_form.rb +2 -0
  61. data/config/locales/carrierwave.lt.yml +4 -0
  62. data/config/locales/carrierwave.nl.yml +4 -0
  63. data/config/locales/carrierwave.ru.yml +4 -0
  64. data/config/locales/default.nl.yml +13 -0
  65. data/config/locales/devise.nl.yml +61 -0
  66. data/config/locales/en.yml +28 -10
  67. data/config/locales/flash.nl.yml +79 -0
  68. data/config/locales/inputs.lt.yml +18 -0
  69. data/config/locales/inputs.nl.yml +18 -0
  70. data/config/locales/mongoid.nl.yml +47 -0
  71. data/config/locales/nl.yml +316 -0
  72. data/config/locales/simple_form.en.yml +6 -0
  73. data/config/locales/simple_form.nl.yml +148 -0
  74. data/lib/locomotive/carrierwave/asset.rb +5 -1
  75. data/lib/locomotive/dependencies.rb +0 -1
  76. data/lib/locomotive/engine.rb +7 -1
  77. data/lib/locomotive/middlewares/site.rb +14 -2
  78. data/lib/locomotive/mongoid/patches.rb +29 -0
  79. data/lib/locomotive/steam/middlewares/catch_error.rb +78 -0
  80. data/lib/locomotive/steam/middlewares/wysihtml_css.rb +32 -0
  81. data/lib/locomotive/steam_adaptor.rb +4 -7
  82. data/lib/locomotive/version.rb +1 -1
  83. data/spec/requests/locomotive/steam/cache_spec.rb +3 -3
  84. data/spec/requests/locomotive/steam/wysihtml_css_spec.rb +42 -0
  85. data/spec/requests/site_spec.rb +13 -2
  86. data/spec/support/features/session_helpers.rb +3 -3
  87. data/vendor/assets/components/locomotive/backbone/backbone.js +1894 -0
  88. data/vendor/assets/components/locomotive/underscore/underscore.js +1548 -0
  89. data/vendor/assets/components/locomotive_sources/backbone/LICENSE +22 -0
  90. data/vendor/assets/components/locomotive_sources/backbone/backbone-min.js +2 -0
  91. data/vendor/assets/components/locomotive_sources/backbone/backbone-min.map +1 -0
  92. data/vendor/assets/components/locomotive_sources/backbone/backbone.js +1894 -0
  93. data/vendor/assets/components/locomotive_sources/backbone/bower.json +8 -0
  94. data/vendor/assets/components/locomotive_sources/underscore/LICENSE +23 -0
  95. data/vendor/assets/components/locomotive_sources/underscore/README.md +22 -0
  96. data/vendor/assets/components/locomotive_sources/underscore/bower.json +7 -0
  97. data/vendor/assets/components/locomotive_sources/underscore/underscore-min.js +6 -0
  98. data/vendor/assets/components/locomotive_sources/underscore/underscore-min.map +1 -0
  99. data/vendor/assets/components/locomotive_sources/underscore/underscore.js +1548 -0
  100. data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced.js +22 -48
  101. data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced_unwrap.js +13 -12
  102. data/vendor/assets/javascripts/locomotive/wysihtml5x-toolbar.js +7324 -3862
  103. data/vendor/assets/stylesheets/locomotive/wysihtml5_editor.css +27 -1
  104. metadata +53 -28
  105. data/app/assets/stylesheets/locomotive/globals/_all.scss +0 -3
  106. data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +0 -841
  107. data/app/assets/stylesheets/locomotive/globals/_colors.scss +0 -1
  108. data/app/assets/stylesheets/locomotive/globals/_nprogress.scss +0 -3
  109. data/app/assets/stylesheets/locomotive/not_logged_in.scss +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5fcc2bd87ac0d01a19c8ea5f798ff338f1eb8fc
4
- data.tar.gz: b189780fd9fbc5c04631715245fa79a068d355f9
3
+ metadata.gz: adb0a5ebc0f40fc62072340ff10f15d6029d14bb
4
+ data.tar.gz: c7d3971de7bd5e22fc8d32b94445e3c6ff96f2cc
5
5
  SHA512:
6
- metadata.gz: 0b3a1a9f8d51163f4c16999f78e02d9cbcde1b00875bbb8694be328d50d2afcece5af4f8eb087b6ebb0d0bae1322770f363a5100d99acd8785f148c86334762c
7
- data.tar.gz: a48ea5fc1565b9a175ae2b3e515644fed3dd15664961c75a37ab152630108cd3052db6f50bd867f21381d6601ad2dfde8420d8180f3e57d25dcc99a0e72a8231
6
+ metadata.gz: 470554e8983fb56b3d2e88bc02dd1276b21baa7153dc9afcd8c98b29e4b4ea9ecb3cbe1eef5bba2df822da81024ac1682ec29eec4c157dd4337709bcf9499ea3
7
+ data.tar.gz: e38ef2a4463cd47412a61cc2843242e843db154d8e78f0e58486939535e6318b70453c0763fb5bd6c1eaf0884bca322f65cb35730513fd2180cf4421a732fa27
data/Gemfile CHANGED
@@ -21,8 +21,8 @@ group :development do
21
21
  # gem 'custom_fields', path: '../gems/custom_fields' # for Developers
22
22
  # gem 'custom_fields', github: 'locomotivecms/custom_fields', ref: '15cceb66ed'
23
23
 
24
- # gem 'locomotivecms_steam', path: '../in_progress/steam', require: false
25
- # gem 'locomotivecms_steam', github: 'locomotivecms/steam', ref: 'c1d1120', require: false
24
+ # gem 'locomotivecms_steam', path: '../gems/steam', require: false
25
+ # gem 'locomotivecms_steam', github: 'locomotivecms/steam', ref: 'c9cb7f6', require: false
26
26
 
27
27
  # gem 'locomotive_liquid', path: '../gems/liquid' # for Developers
28
28
  # gem 'locomotivecms_solid', path: '../gems/solid' # for Developers
data/README.md CHANGED
@@ -65,9 +65,10 @@ Here is our Transifex portal page: [https://www.transifex.com/locomotive/locomot
65
65
 
66
66
  Locomotive is an open source project, we encourage contributions. If you have found a bug and want to contribute a fix, or have a new feature you would like to add, follow the steps below to get your patch into the project:
67
67
 
68
- - Install ruby and mongoDB
68
+ - Install ruby, mongoDB and phantomjs
69
69
  - Clone the project <code>git clone git@github.com:locomotivecms/engine.git</code>
70
70
  - Setup a virtual host entry for <code>test.example.com</code> to point to localhost
71
+ - Start mongodb if it is not already running
71
72
  - Run the tests <code>bundle exec rake</code>
72
73
  - Write your failing tests
73
74
  - Make the tests pass
@@ -31,6 +31,14 @@ module Locomotive
31
31
  Locomotive::Dragonfly.resize_url site.picture.url, '100x100#'
32
32
  end
33
33
 
34
+ expose :preview_url do |site, opts|
35
+ Locomotive::Engine.routes.url_helpers.preview_url(site, host: opts[:env]['HTTP_HOST'])
36
+ end
37
+
38
+ expose :sign_in_url do |site, opts|
39
+ Locomotive::Engine.routes.url_helpers.new_locomotive_account_session_url(host: opts[:env]['HTTP_HOST'])
40
+ end
41
+
34
42
  end
35
43
 
36
44
  end
@@ -8,7 +8,7 @@ module Locomotive
8
8
  included do
9
9
 
10
10
  rescue_from :all do |e|
11
- Rails.logger.error "[API]" + e.message + "\"" + e.backtrace.join("\n")
11
+ Rails.logger.error "[API] " + e.message + "\n\t" + e.backtrace.join("\n\t")
12
12
 
13
13
  error_response(message: { error: e.message }, status: 500)
14
14
  end
@@ -26,12 +26,13 @@ module Locomotive
26
26
 
27
27
  def set_many_to_many(field, value)
28
28
  if value.blank?
29
- dynamic_attributes[:"#{field.name}_ids"] = [] # reset it
29
+ dynamic_attributes[:"#{field.name.singularize}_ids"] = [] # reset it
30
30
  else
31
- dynamic_attributes[:"#{field.name}_ids"] = fetch_entry_ids(field.class_name, value).sort do |a, b|
31
+ dynamic_attributes[:"#{field.name.singularize}_ids"] = fetch_entry_ids(field.class_name, value).sort do |a, b|
32
+ # keep the original order
32
33
  (value.index(a.first.to_s) || value.index(a.last)) <=>
33
34
  (value.index(b.first.to_s) || value.index(b.last))
34
- end # keep the original order
35
+ end.map(&:first)
35
36
  end
36
37
  end
37
38
 
@@ -10,16 +10,34 @@ module Locomotive
10
10
  # Much safer than permitted_params because it also uses the current policy
11
11
  # (Pundit) to filter the parameters.
12
12
  #
13
- # Example:
13
+ # Examples:
14
14
  #
15
15
  # permitted_params_from_policy(current_site, :site)
16
16
  #
17
- def permitted_params_from_policy(object_or_class, key)
18
- _params = permitted_params[key]
17
+ # If we want to deal with ActionDispatch::Http::UploadedFile instances
18
+ # instead of hashes (which would break the permitted attributes policy).
19
+ #
20
+ # permitted_params_from_policy(current_site, :site, [:picture])
21
+ #
22
+ def permitted_params_from_policy(object_or_class, key, file_inputs = nil)
23
+ _params = permitted_params[key]
24
+
25
+ build_uploaded_files_from_params!(_params, file_inputs) if file_inputs
26
+
19
27
  _attributes = policy(object_or_class).permitted_attributes
20
28
  ::ActionController::Parameters.new(_params).permit(*_attributes)
21
29
  end
22
30
 
31
+ def build_uploaded_files_from_params!(hash, list)
32
+ list.each do |name|
33
+ file_hash = hash[name]
34
+
35
+ next unless file_hash.try(:has_key?, :tempfile)
36
+
37
+ hash[name] = ActionDispatch::Http::UploadedFile.new(file_hash)
38
+ end
39
+ end
40
+
23
41
  end
24
42
 
25
43
  end
@@ -46,7 +46,7 @@ module Locomotive
46
46
  put do
47
47
  authorize current_site, :update?
48
48
 
49
- current_site_form = Forms::SiteForm.new(permitted_params_from_policy(current_site, :site))
49
+ current_site_form = Forms::SiteForm.new(permitted_params_from_policy(current_site, :site, [:picture]))
50
50
  service.update(current_site, current_site_form.serializable_hash)
51
51
 
52
52
  present current_site, with: entity_klass
@@ -71,7 +71,7 @@ module Locomotive
71
71
  post do
72
72
  authorize Site, :create?
73
73
 
74
- site_form = Forms::SiteForm.new(permitted_params_from_policy(Locomotive::Site, :site))
74
+ site_form = Forms::SiteForm.new(permitted_params_from_policy(Locomotive::Site, :site, [:picture]))
75
75
  site = service.create!(site_form.serializable_hash)
76
76
 
77
77
  present site, with: entity_klass
@@ -98,7 +98,7 @@ module Locomotive
98
98
  site = load_site
99
99
  authorize site, :update?
100
100
 
101
- site_form = Forms::SiteForm.new(permitted_params_from_policy(site, :site))
101
+ site_form = Forms::SiteForm.new(permitted_params_from_policy(site, :site, [:picture]))
102
102
  site.assign_attributes(site_form.serializable_hash)
103
103
  site.save!
104
104
 
@@ -1,6 +1,6 @@
1
1
  #= require jquery
2
2
  #= require_self
3
- #= require underscore
3
+ #= require underscore/underscore
4
4
  #= require locomotive/bootstrap-notify
5
5
  #= require ./utils/notify
6
6
 
@@ -60,7 +60,7 @@
60
60
  doc.body.appendChild(script);
61
61
  }
62
62
 
63
- window.addStylesheet = function(doc, src, options) {
63
+ window.addStylesheet = function(doc, src) {
64
64
  var stylesheet = doc.createElement('link');
65
65
  stylesheet.style = 'text/css';
66
66
  stylesheet.href = src;
@@ -1,33 +1,23 @@
1
- # New command: strike
2
- wysihtml5.commands.strike =
3
- exec: (composer, command, param) ->
4
- wysihtml5.commands.formatInline.exec(composer, command, 'strike')
5
-
6
- state: (composer, command) ->
7
- wysihtml5.commands.formatInline.state(composer, command, 'strike')
8
-
9
- # New command: justify full
10
- # https://github.com/xing/wysihtml5/blob/56960b31adc37e07797382d8e8b10109f206b19c/src/commands/justifyFull.js
11
1
  ((wysihtml5) ->
12
- CLASS_NAME = "wysiwyg-text-align-justify"
13
- REG_EXP = /wysiwyg-text-align-[0-9a-z]+/g
14
2
 
15
- wysihtml5.commands.justifyFull =
16
- exec: (composer, command, param) ->
17
- wysihtml5.commands.formatBlock.exec(composer, 'formatBlock', null, CLASS_NAME, REG_EXP)
3
+ # New command: strike
4
+ wysihtml5.commands.strike =
5
+ exec: (composer, command) ->
6
+ wysihtml5.commands.formatInline.exec(composer, command, 'STRIKE')
18
7
 
19
8
  state: (composer, command) ->
20
- wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP)
9
+ wysihtml5.commands.formatInline.state(composer, command, 'STRIKE', null, null)
21
10
 
22
11
  )(wysihtml5)
23
12
 
13
+
24
14
  # New command: insert file
25
15
  ((wysihtml5) ->
26
16
 
27
17
  wysihtml5.commands.insertFile =
28
18
  exec: (composer, command, param) ->
29
19
  # do nothing
30
- console.log "[insertFile] exec(#{command}, #{param})"
20
+ # console.log "[insertFile] exec(#{command}, #{param})"
31
21
 
32
22
  state: (composer, command) ->
33
23
  # console.log "[insertFile] state(#{command})"
@@ -36,4 +26,40 @@ wysihtml5.commands.strike =
36
26
 
37
27
  )(wysihtml5)
38
28
 
29
+ # Replace command: insert table
30
+ ((wysihtml5) ->
31
+
32
+ buildHeader = (cols) ->
33
+ html = '<thead><tr>'
34
+ html += '<th><br></th>' for col in [0...cols]
35
+ html + '</tr></thead>'
36
+
37
+ buildBody = (cols, rows) ->
38
+ html = '<tbody>'
39
+ for row in [0...rows]
40
+ html += '<tr>'
41
+ html += '<td><br></td>' for col in [0...cols]
42
+ html += '</tr>'
43
+ html += '</tbody>'
44
+
45
+ wysihtml5.commands.createTable =
46
+ exec: (composer, command, options) ->
47
+ options = _.extend { cols: 3, rows: 3, class_name: '', head: true }, options
48
+
49
+ cols = parseInt(options.cols, 10)
50
+ rows = parseInt(options.rows, 10)
51
+
52
+ html = "<table class='#{options.class_name}'>"
53
+ html += buildHeader(cols) if options.head
54
+ html += buildBody(cols, rows)
55
+ html += '</table>'
56
+
57
+ composer.commands.exec('insertHTML', html)
58
+
59
+ state: (composer, command) ->
60
+ false
61
+
62
+ )(wysihtml5)
63
+
64
+
39
65
 
@@ -35,10 +35,14 @@ class Locomotive.Views.ApplicationView extends Backbone.View
35
35
  Locomotive.notify couple[1], couple[0]
36
36
 
37
37
  automatic_max_height: ->
38
- $(window).on 'resize', => @set_max_height()
38
+ $(window).on 'resize', =>
39
+ height = @set_max_height()
40
+ PubSub.publish 'application_view.resize', height: height
39
41
 
40
42
  set_max_height: ->
41
43
  max_height = $(window).height()
42
44
  height = max_height - @header_view.height()
43
45
 
44
46
  @$('> .wrapper').height(height)
47
+
48
+ height
@@ -4,6 +4,17 @@ class Locomotive.Views.EditableElements.EditView extends Locomotive.Views.Shared
4
4
 
5
5
  el: '.content > .inner'
6
6
 
7
+ events:
8
+ 'click .form-group.rte label': 'select_editable_text'
9
+ 'click .form-group.text label': 'select_editable_text'
10
+
11
+ initialize: ->
12
+ _.bindAll(@, 'highlight_form_group')
13
+
14
+ @tokens = [
15
+ PubSub.subscribe 'editable_elements.highlighted_text', @highlight_form_group
16
+ ]
17
+
7
18
  render: ->
8
19
  super
9
20
 
@@ -14,12 +25,44 @@ class Locomotive.Views.EditableElements.EditView extends Locomotive.Views.Shared
14
25
  @refresh_inputs $(data)
15
26
 
16
27
  $('.info-row select[name=block]').select2().on 'change', (event) =>
28
+ PubSub.publish 'editable_elements.block_selected', name: event.val
17
29
  @filter_elements_by(event.val)
18
30
 
19
31
  # editable control elements
20
32
  $('.editable-elements .form-group.input.select select').select2().on 'change', (event) =>
21
33
  @need_reload = true
22
34
 
35
+ select_editable_text: (event) ->
36
+ element_id = $(event.target).parents('.form-group').attr('id').replace('editable-text-', '')
37
+ PubSub.publish 'editable_elements.form_group_selected', element_id: element_id
38
+
39
+ highlight_form_group: (msg, data) ->
40
+ $form_group = $(@el).find("#editable-text-#{data.element_id}")
41
+
42
+ return false if $form_group.size() == 0
43
+
44
+ @filter_elements_by('')
45
+
46
+ highlight_effect = =>
47
+ $form_group.clearQueue().queue (next) ->
48
+ $(this).addClass('highlighted')
49
+ next()
50
+ .delay(200).queue (next) ->
51
+ $(this).removeClass('highlighted').find('input[type=text],textarea').trigger('highlight')
52
+ next()
53
+
54
+ # scroll to the form group and then highlight the textarea/input/editor
55
+ $parent = @$('.scrollable')
56
+ offset = $form_group.position().top
57
+
58
+ if offset == 0
59
+ $parent.animate { scrollTop: 0 }, 500, 'swing', highlight_effect
60
+ else if offset < 0 || offset > $parent.height()
61
+ offset = $parent.scrollTop() + offset if offset < 0
62
+ $parent.animate { scrollTop: offset }, 500, 'swing', highlight_effect
63
+ else
64
+ highlight_effect()
65
+
23
66
  refresh_inputs: ($html) ->
24
67
  @inputs = _.map @inputs, (view) =>
25
68
  return view unless view.need_refresh?
@@ -39,3 +82,7 @@ class Locomotive.Views.EditableElements.EditView extends Locomotive.Views.Shared
39
82
  $el.parent().show()
40
83
  else
41
84
  $el.parent().hide()
85
+
86
+ remove: ->
87
+ super
88
+ _.each @tokens, (token) -> PubSub.unsubscribe(token)
@@ -0,0 +1,59 @@
1
+ Locomotive.Views.EditableElements ||= {}
2
+
3
+ class Locomotive.Views.EditableElements.IframeView extends Backbone.View
4
+
5
+ el: '.preview iframe'
6
+
7
+ startup: true
8
+
9
+ initialize: ->
10
+ # shortcut
11
+ @window = $(@el)[0].contentWindow
12
+
13
+ # when the url of the iframe changes, process
14
+ $(@el).load (event) => @on_load(event)
15
+
16
+ reload: ->
17
+ $(@el).attr('src', @preview_url)
18
+
19
+ on_load: (event) ->
20
+ # Able to get the path to the edit form?
21
+ if (path = @edit_view_path())?
22
+ @preview_url = @window.document.location.href
23
+
24
+ if !@startup
25
+ History.replaceState({ live_editing: true, url: @preview_url }, '', path)
26
+ @options.parent_view.replace_edit_view(path)
27
+ else
28
+ @startup = false
29
+
30
+ @build_and_render_page_view()
31
+
32
+ edit_view_path: ->
33
+ # the browser might be unable to load the iframe because of
34
+ # the 'X-Frame-Options' option which is set to 'SAMEORIGIN'.
35
+ try
36
+ $document = $(@window.document)
37
+ return $document.find('meta[name=locomotive-editable-elements-path]').attr('content')
38
+ catch e
39
+ # reload the iframe with the previous url and display an error message
40
+ @reload()
41
+ Locomotive.notify $(@el).data('redirection-error'), 'warning'
42
+ return null
43
+
44
+ build_and_render_page_view: ->
45
+ @page_view.remove() if @page_view?
46
+ @page_view = new Locomotive.Views.EditableElements.PageView
47
+ el: $(@window.document.body)
48
+ parent_view: @
49
+ button_labels:
50
+ edit: $(@el).data('edit-label')
51
+ @page_view.render()
52
+
53
+ # insert the highlighter CSS (path to the CSS in the iframe data)
54
+ window.addStylesheet(@window.document, $(@el).data('style-path'))
55
+
56
+ remove: ->
57
+ super()
58
+ @page_view.remove() if @page_view?
59
+ _.each @tokens, (token) -> PubSub.unsubscribe(token)
@@ -8,108 +8,35 @@ class Locomotive.Views.EditableElements.IndexView extends Backbone.View
8
8
  'click .content .expand-button': 'expand_preview'
9
9
  'click .content .close-button': 'shrink_preview'
10
10
 
11
- expand_preview: (event) ->
12
- $('body').addClass('full-width-preview')
13
-
14
- shrink_preview: (event) ->
15
- $('body').removeClass('full-width-preview')
16
-
17
11
  initialize: ->
18
- _.bindAll(@, 'refresh_elements', 'refresh_image', 'refresh_image_on_remove', 'refresh_text', 'reload_page')
19
-
20
12
  view_options = if $('body').hasClass('live-editing') then {} else { el: '.main' }
21
13
 
22
- @startup = true
23
- @edit_view = new Locomotive.Views.EditableElements.EditView(view_options)
24
- @pubsub_text_token = PubSub.subscribe('inputs.text_changed', @refresh_text)
14
+ @tokens = [
15
+ PubSub.subscribe 'editable_elements.highlighted_text', @shrink_preview
16
+ ]
25
17
 
26
- @pubsub_image_changed_token = PubSub.subscribe('inputs.image_changed', @refresh_image)
27
- @pubsub_image_removed_token = PubSub.subscribe('inputs.image_removed', @refresh_image_on_remove)
28
- @pubsub_pages_sorted_token = PubSub.subscribe('pages.sorted', @reload_page)
29
-
30
- $('.preview iframe').load (event) => @on_iframe_load(event)
18
+ # order is important here
19
+ @views = [
20
+ new Locomotive.Views.EditableElements.EditView(view_options),
21
+ new Locomotive.Views.EditableElements.IframeView(parent_view: @)
22
+ ]
31
23
 
32
24
  render: ->
33
25
  super()
34
- @edit_view.render()
35
-
36
- refresh_elements: (type, view, callback) ->
37
- $parent_view = $(view.el).parent()
38
- element_id = $parent_view.find('input[name*="[id]"]').val()
39
-
40
- $iframe_document = $($('iframe')[0].contentWindow.document)
41
-
42
- callback($iframe_document.find("*[data-element-id=#{element_id}]"), element_id, $iframe_document)
43
-
44
- refresh_image_on_remove: (msg, data) ->
45
- data.url = $(data.view.el).parent().find('input[name*="[default_source_url]"]').val()
46
- @refresh_image(msg, data)
47
-
48
- refresh_image: (msg, data) ->
49
- @refresh_elements 'image', data.view, ($elements, element_id, $iframe_document) ->
50
- current_image_url = data.view.$('input[name*="[content]"]').val()
51
- image_url = data.url || current_image_url
26
+ _.invoke @views, 'render'
52
27
 
53
- if $elements.size() > 0
54
- $elements.each ->
55
- if this.nodeName == 'IMG'
56
- $(this).attr('src', image_url)
57
- else
58
- $(this).css("background-image", "url('" + image_url + "')")
59
- else
60
- # looking for DIVs with background-url property matching the previous image url
61
- $el = $iframe_document.find("*[style*='#{current_image_url}']").attr('data-element-id', element_id)
62
- $el.css("background-image", "url('" + image_url + "')")
63
-
64
- # looking for IMGs with src attribute matching the previous image url
65
- $el = $iframe_document.find("img[src*='#{current_image_url}']").attr('data-element-id', element_id)
66
- $el.attr('src', image_url)
67
-
68
- refresh_text: (msg, data) ->
69
- @refresh_elements 'text', data.view, ($elements) ->
70
- $elements.each -> $(this).html(data.content)
71
-
72
- reload_page: (event) ->
73
- $iframe = $('.preview iframe')
74
- $target_window = $iframe[0].contentWindow
75
- $iframe.attr('src', @preview_url)
76
-
77
- on_iframe_load: (event) ->
78
- $iframe = $('.preview iframe')
79
- $target_window = $iframe[0].contentWindow
80
- editable_elements_path = null
81
-
82
- # unable to display the iframe in the frame because it set 'X-Frame-Options' to 'SAMEORIGIN'
83
- try
84
- $iframe_document = $($target_window.document)
85
- editable_elements_path = $iframe_document.find('meta[name=locomotive-editable-elements-path]').attr('content')
86
- catch e
87
- # reload the iframe with the previous url and display an error message
88
- $iframe.attr('src', @preview_url)
89
- Locomotive.notify $iframe.data('redirection-error'), 'warning'
90
- return
91
-
92
- # store the url
93
- @preview_url = $('.preview iframe')[0].contentWindow.document.location.href
28
+ expand_preview: (event) ->
29
+ $('body').addClass('full-width-preview')
94
30
 
95
- if editable_elements_path? && @startup == false
96
- History.replaceState({ live_editing: true, url: @preview_url }, '', editable_elements_path)
97
- @replace_edit_view(editable_elements_path)
98
- else
99
- @startup = false
31
+ shrink_preview: (event) ->
32
+ $('body').removeClass('full-width-preview')
100
33
 
101
34
  replace_edit_view: (url) ->
102
- $(@edit_view.el).load url, =>
103
- @edit_view.remove()
104
- @edit_view = new Locomotive.Views.EditableElements.EditView()
105
- @edit_view.render()
35
+ $(@views[0].el).load url, =>
36
+ @views[0].remove()
37
+ (@views[0] = new Locomotive.Views.EditableElements.EditView()).render()
106
38
 
107
39
  remove: ->
108
- super
109
-
110
- @edit_view.remove()
111
-
112
- PubSub.unsubscribe(@pubsub_image_changed_token)
113
- PubSub.unsubscribe(@pubsub_image_removed_token)
114
- PubSub.unsubscribe(@pubsub_text_token)
115
- PubSub.unsubscribe(@pubsub_pages_sorted_token)
40
+ super()
41
+ _.each @tokens, (token) -> PubSub.unsubscribe(token)
42
+ _.invoke @views, 'remove'
@@ -0,0 +1,81 @@
1
+ Locomotive.Views.EditableElements ||= {}
2
+
3
+ class Locomotive.Views.EditableElements.PageView extends Backbone.View
4
+
5
+ initialize: ->
6
+ _.bindAll(@, 'refresh_all', 'refresh_text', 'refresh_image', 'refresh_image_on_remove', 'scroll_to_block', 'scroll_to_element')
7
+
8
+ # Global event subscriptions
9
+ @tokens = [
10
+ PubSub.subscribe 'editable_elements.block_selected', @scroll_to_block
11
+ PubSub.subscribe 'editable_elements.form_group_selected', @scroll_to_element
12
+ PubSub.subscribe 'inputs.text_changed', @refresh_text,
13
+ PubSub.subscribe 'inputs.image_changed', @refresh_image,
14
+ PubSub.subscribe 'inputs.image_removed', @refresh_image_on_remove,
15
+ PubSub.subscribe 'pages.sorted', @refresh_all
16
+ ]
17
+
18
+ # create the highlighter view
19
+ @views = [new Locomotive.Views.EditableElements.TextHighLighterView(el: @el, button_labels: @options.button_labels)]
20
+
21
+ render: ->
22
+ # render the highlighter view
23
+ _.invoke @views, 'render'
24
+
25
+ scroll_to_block: (msg, data) ->
26
+ @_scroll_to @$("span.locomotive-block-anchor[data-element-id=\"#{data.name}\"]")
27
+
28
+ scroll_to_element: (msg, data) ->
29
+ @_scroll_to @$("span.locomotive-editable-text[data-element-id=\"#{data.element_id}\"]")
30
+
31
+ _scroll_to: (element) ->
32
+ return false if element.size() == 0
33
+ $(@el).animate({ scrollTop: element.offset().top }, 500)
34
+
35
+ refresh_all: (msg, data) ->
36
+ @options.parent_view.reload()
37
+
38
+ refresh_text: (msg, data) ->
39
+ @refresh_elements 'text', data.view, ($elements) ->
40
+ $elements.each -> $(this).html(data.content)
41
+
42
+ refresh_image_on_remove: (msg, data) ->
43
+ data.url = $(data.view.el).parent().find('input[name*="[default_source_url]"]').val()
44
+ @refresh_image(msg, data)
45
+
46
+ refresh_image: (msg, data) ->
47
+ @refresh_elements 'image', data.view, ($elements, element_id) =>
48
+ current_image_url = data.view.$('input[name*="[content]"]').val()
49
+ image_url = data.url || current_image_url
50
+
51
+ if $elements.size() > 0
52
+ @replace_images($elements, image_url)
53
+ else
54
+ @replace_images_identified_by_url(current_image_url, image_url, element_id)
55
+
56
+ refresh_elements: (type, view, callback) ->
57
+ $form_view = $(view.el).parent()
58
+ element_id = $form_view.find('input[name*="[id]"]').val()
59
+
60
+ callback($(@el).find("*[data-element-id=#{element_id}]"), element_id)
61
+
62
+ replace_images: (images, new_image_url) ->
63
+ images.each ->
64
+ if this.nodeName == 'IMG'
65
+ $(this).attr('src', new_image_url)
66
+ else
67
+ $(this).css("background-image", "url('" + new_image_url + "')")
68
+
69
+ replace_images_identified_by_url: (current_image_url, new_image_url, element_id) ->
70
+ # looking for DIVs with background-url property matching the previous image url
71
+ $el = $(@el).find("*[style*='#{current_image_url}']").attr('data-element-id', element_id)
72
+ $el.css("background-image", "url('" + new_image_url + "')")
73
+
74
+ # looking for IMGs with src attribute matching the previous image url
75
+ $el = $(@el).find("img[src*='#{current_image_url}']").attr('data-element-id', element_id)
76
+ $el.attr('src', new_image_url)
77
+
78
+ remove: ->
79
+ super()
80
+ _.each @tokens, (token) -> PubSub.unsubscribe(token)
81
+ _.invoke @views, 'remove'