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.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/README.md +2 -1
- data/app/api/locomotive/api/entities/site_entity.rb +8 -0
- data/app/api/locomotive/api/exception_rescuers.rb +1 -1
- data/app/api/locomotive/api/forms/content_entry_form.rb +4 -3
- data/app/api/locomotive/api/helpers/params_helper.rb +21 -3
- data/app/api/locomotive/api/resources/current_site_resource.rb +1 -1
- data/app/api/locomotive/api/resources/site_resource.rb +2 -2
- data/app/assets/images/locomotive/deadend.png +0 -0
- data/app/assets/javascripts/locomotive/not_logged_in.js.coffee +1 -1
- data/app/assets/javascripts/locomotive/utils/core_ext.js +1 -1
- data/app/assets/javascripts/locomotive/utils/wysihtml5.js.coffee +43 -17
- data/app/assets/javascripts/locomotive/views/application_view.js.coffee +5 -1
- data/app/assets/javascripts/locomotive/views/editable_elements/edit_view.js.coffee +47 -0
- data/app/assets/javascripts/locomotive/views/editable_elements/iframe_view.js.coffee +59 -0
- data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +19 -92
- data/app/assets/javascripts/locomotive/views/editable_elements/page_view.js.coffee +81 -0
- data/app/assets/javascripts/locomotive/views/editable_elements/text_highlighter_view.js.coffee +76 -0
- data/app/assets/javascripts/locomotive/views/inputs/rte/edit_table_view.js.coffee +35 -0
- data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +14 -10
- data/app/assets/javascripts/locomotive/views/inputs/rte/link_view.js.coffee +25 -15
- data/app/assets/javascripts/locomotive/views/inputs/rte/table_view.js.coffee +82 -0
- data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +64 -23
- data/app/assets/javascripts/locomotive/views/inputs/text_view.js.coffee +11 -6
- data/app/assets/javascripts/locomotive.js +2 -2
- data/app/assets/stylesheets/locomotive/application.scss +1 -3
- data/app/assets/stylesheets/locomotive/base/_form.scss +2 -1
- data/app/assets/stylesheets/locomotive/base/_typography.scss +3 -2
- data/app/assets/stylesheets/locomotive/base/form/_base.scss +5 -0
- data/app/assets/stylesheets/locomotive/base/form/_rte.scss +42 -0
- data/app/assets/stylesheets/locomotive/error.scss +1 -1
- data/app/assets/stylesheets/locomotive/globals/_mixins.scss +41 -48
- data/app/assets/stylesheets/locomotive/globals/_variables.scss +202 -121
- data/app/assets/stylesheets/locomotive/layouts/_not_logged_in.scss +8 -9
- data/app/assets/stylesheets/locomotive/live_editing_error.scss +19 -0
- data/app/assets/stylesheets/locomotive/live_editing_iframe.scss +84 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_forms.scss +63 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_keyframes.scss +31 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_notify.scss +85 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_public.scss +129 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_type.scss +14 -0
- data/app/assets/stylesheets/locomotive/unauthorized/_variables.scss +54 -0
- data/app/assets/stylesheets/locomotive/unauthorized.scss +34 -0
- data/app/helpers/locomotive/dashboard_helper.rb +1 -1
- data/app/inputs/locomotive/rte_input.rb +12 -0
- data/app/models/locomotive/concerns/page/editable_elements.rb +0 -2
- data/app/models/locomotive/editable_element.rb +1 -1
- data/app/services/locomotive/content_asset_service.rb +1 -1
- data/app/services/locomotive/page_parsing_service.rb +4 -2
- data/app/views/locomotive/editable_elements/index.html.slim +1 -1
- data/app/views/locomotive/layouts/not_logged_in.html.slim +13 -9
- data/app/views/locomotive/passwords/edit.html.slim +13 -13
- data/app/views/locomotive/passwords/new.html.slim +14 -11
- data/app/views/locomotive/registrations/new.html.slim +14 -13
- data/app/views/locomotive/sessions/new.html.slim +14 -13
- data/app/views/locomotive/shared/rte/_markdown_toolbar.html.slim +0 -30
- data/app/views/locomotive/shared/rte/_table_popover.html.slim +17 -0
- data/app/views/locomotive/shared/rte/_toolbar.html.slim +48 -11
- data/config/initializers/simple_form.rb +2 -0
- data/config/locales/carrierwave.lt.yml +4 -0
- data/config/locales/carrierwave.nl.yml +4 -0
- data/config/locales/carrierwave.ru.yml +4 -0
- data/config/locales/default.nl.yml +13 -0
- data/config/locales/devise.nl.yml +61 -0
- data/config/locales/en.yml +28 -10
- data/config/locales/flash.nl.yml +79 -0
- data/config/locales/inputs.lt.yml +18 -0
- data/config/locales/inputs.nl.yml +18 -0
- data/config/locales/mongoid.nl.yml +47 -0
- data/config/locales/nl.yml +316 -0
- data/config/locales/simple_form.en.yml +6 -0
- data/config/locales/simple_form.nl.yml +148 -0
- data/lib/locomotive/carrierwave/asset.rb +5 -1
- data/lib/locomotive/dependencies.rb +0 -1
- data/lib/locomotive/engine.rb +7 -1
- data/lib/locomotive/middlewares/site.rb +14 -2
- data/lib/locomotive/mongoid/patches.rb +29 -0
- data/lib/locomotive/steam/middlewares/catch_error.rb +78 -0
- data/lib/locomotive/steam/middlewares/wysihtml_css.rb +32 -0
- data/lib/locomotive/steam_adaptor.rb +4 -7
- data/lib/locomotive/version.rb +1 -1
- data/spec/requests/locomotive/steam/cache_spec.rb +3 -3
- data/spec/requests/locomotive/steam/wysihtml_css_spec.rb +42 -0
- data/spec/requests/site_spec.rb +13 -2
- data/spec/support/features/session_helpers.rb +3 -3
- data/vendor/assets/components/locomotive/backbone/backbone.js +1894 -0
- data/vendor/assets/components/locomotive/underscore/underscore.js +1548 -0
- data/vendor/assets/components/locomotive_sources/backbone/LICENSE +22 -0
- data/vendor/assets/components/locomotive_sources/backbone/backbone-min.js +2 -0
- data/vendor/assets/components/locomotive_sources/backbone/backbone-min.map +1 -0
- data/vendor/assets/components/locomotive_sources/backbone/backbone.js +1894 -0
- data/vendor/assets/components/locomotive_sources/backbone/bower.json +8 -0
- data/vendor/assets/components/locomotive_sources/underscore/LICENSE +23 -0
- data/vendor/assets/components/locomotive_sources/underscore/README.md +22 -0
- data/vendor/assets/components/locomotive_sources/underscore/bower.json +7 -0
- data/vendor/assets/components/locomotive_sources/underscore/underscore-min.js +6 -0
- data/vendor/assets/components/locomotive_sources/underscore/underscore-min.map +1 -0
- data/vendor/assets/components/locomotive_sources/underscore/underscore.js +1548 -0
- data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced.js +22 -48
- data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced_unwrap.js +13 -12
- data/vendor/assets/javascripts/locomotive/wysihtml5x-toolbar.js +7324 -3862
- data/vendor/assets/stylesheets/locomotive/wysihtml5_editor.css +27 -1
- metadata +53 -28
- data/app/assets/stylesheets/locomotive/globals/_all.scss +0 -3
- data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +0 -841
- data/app/assets/stylesheets/locomotive/globals/_colors.scss +0 -1
- data/app/assets/stylesheets/locomotive/globals/_nprogress.scss +0 -3
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: adb0a5ebc0f40fc62072340ff10f15d6029d14bb
|
|
4
|
+
data.tar.gz: c7d3971de7bd5e22fc8d32b94445e3c6ff96f2cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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: '../
|
|
25
|
-
# gem 'locomotivecms_steam', github: 'locomotivecms/steam', ref: '
|
|
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
|
|
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 + "\"
|
|
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
|
|
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
|
-
#
|
|
13
|
+
# Examples:
|
|
14
14
|
#
|
|
15
15
|
# permitted_params_from_policy(current_site, :site)
|
|
16
16
|
#
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
|
Binary file
|
|
@@ -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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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.
|
|
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', =>
|
|
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
|
-
@
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
@tokens = [
|
|
15
|
+
PubSub.subscribe 'editable_elements.highlighted_text', @shrink_preview
|
|
16
|
+
]
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
@
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
@
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
|
|
96
|
-
|
|
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
|
-
$(@
|
|
103
|
-
@
|
|
104
|
-
@
|
|
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
|
-
@
|
|
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'
|