mercury-rails 0.2.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. data/app/controllers/{images_controller.rb → mercury/images_controller.rb} +3 -3
  2. data/app/controllers/mercury_controller.rb +13 -3
  3. data/app/models/{image.rb → mercury/image.rb} +3 -1
  4. data/app/views/layouts/mercury.html.erb +14 -6
  5. data/app/views/mercury/lightviews/about.html +7 -3
  6. data/app/views/mercury/modals/character.html +2 -2
  7. data/app/views/mercury/modals/htmleditor.html +2 -2
  8. data/app/views/mercury/modals/link.html +3 -3
  9. data/app/views/mercury/modals/media.html +3 -3
  10. data/app/views/mercury/modals/table.html +3 -3
  11. data/app/views/mercury/panels/snippets.html +1 -1
  12. data/app/views/mercury/selects/formatblock.html +9 -9
  13. data/app/views/mercury/snippets/example/options.html.erb +27 -16
  14. data/config/engine.rb +35 -0
  15. data/db/migrate/{20110526035601_create_images.rb → 20110526035601_create_mercury_images.rb} +2 -2
  16. data/features/loading/loading.feature +1 -1
  17. data/features/loading/navigating.feature +1 -1
  18. data/features/loading/user_interface.feature +2 -2
  19. data/features/regions/editable/basic_editing.feature +8 -8
  20. data/features/regions/editable/inserting_snippets.feature +4 -5
  21. data/features/regions/editable/inserting_tables.feature +9 -9
  22. data/features/step_definitions/mercury_steps.rb +20 -23
  23. data/features/step_definitions/web_steps.rb +5 -5
  24. data/features/support/mercury_selectors.rb +1 -0
  25. data/lib/generators/mercury/install/install_generator.rb +24 -3
  26. data/lib/generators/mercury/install/templates/mongoid_paperclip_image.rb +17 -0
  27. data/lib/mercury-rails.rb +0 -1
  28. data/lib/mercury/authentication.rb +8 -0
  29. data/spec/javascripts/mercury/dialog_spec.js.coffee +28 -21
  30. data/spec/javascripts/mercury/dialogs/backcolor_spec.js.coffee +0 -2
  31. data/spec/javascripts/mercury/dialogs/forecolor_spec.js.coffee +0 -2
  32. data/spec/javascripts/mercury/dialogs/formatblock_spec.js.coffee +0 -2
  33. data/spec/javascripts/mercury/dialogs/snippetpanel_spec.js.coffee +0 -2
  34. data/spec/javascripts/mercury/dialogs/style_spec.js.coffee +0 -2
  35. data/spec/javascripts/mercury/history_buffer_spec.js.coffee +0 -2
  36. data/spec/javascripts/mercury/lightview_spec.js.coffee +42 -21
  37. data/spec/javascripts/mercury/mercury_spec.js.coffee +87 -7
  38. data/spec/javascripts/mercury/modal_spec.js.coffee +53 -23
  39. data/spec/javascripts/mercury/modals/htmleditor_spec.js.coffee +0 -2
  40. data/spec/javascripts/mercury/modals/insertcharacter_spec.js.coffee +2 -3
  41. data/spec/javascripts/mercury/modals/insertlink_spec.js.coffee +0 -2
  42. data/spec/javascripts/mercury/modals/insertmedia_spec.js.coffee +2 -2
  43. data/spec/javascripts/mercury/modals/insertsnippet_spec.js.coffee +0 -2
  44. data/spec/javascripts/mercury/modals/inserttable_spec.js.coffee +2 -4
  45. data/spec/javascripts/mercury/native_extensions_spec.js.coffee +20 -2
  46. data/spec/javascripts/mercury/page_editor_spec.js.coffee +130 -35
  47. data/spec/javascripts/mercury/palette_spec.js.coffee +4 -6
  48. data/spec/javascripts/mercury/panel_spec.js.coffee +44 -6
  49. data/spec/javascripts/mercury/region_spec.js.coffee +42 -8
  50. data/spec/javascripts/mercury/regions/editable_spec.js.coffee +0 -2
  51. data/spec/javascripts/mercury/regions/markupable_spec.js.coffee +0 -2
  52. data/spec/javascripts/mercury/regions/snippetable_spec.js.coffee +3 -5
  53. data/spec/javascripts/mercury/select_spec.js.coffee +4 -6
  54. data/spec/javascripts/mercury/snippet_spec.js.coffee +3 -4
  55. data/spec/javascripts/mercury/snippet_toolbar_spec.js.coffee +2 -4
  56. data/spec/javascripts/mercury/statusbar_spec.js.coffee +0 -2
  57. data/spec/javascripts/mercury/table_editor_spec.js.coffee +2 -4
  58. data/spec/javascripts/mercury/toolbar.button_group_spec.js.coffee +0 -2
  59. data/spec/javascripts/mercury/toolbar.button_spec.js.coffee +34 -15
  60. data/spec/javascripts/mercury/toolbar.expander_spec.js.coffee +0 -2
  61. data/spec/javascripts/mercury/toolbar_spec.js.coffee +41 -26
  62. data/spec/javascripts/mercury/tooltip_spec.js.coffee +3 -5
  63. data/spec/javascripts/mercury/uploader_spec.js.coffee +8 -14
  64. data/spec/javascripts/spec_helper.js +1 -0
  65. data/spec/javascripts/templates/mercury/page_editor.html +1 -0
  66. data/spec/javascripts/templates/mercury/region.html +2 -2
  67. data/vendor/assets/images/mercury/missing-image.png +0 -0
  68. data/vendor/assets/javascripts/mercury.js +218 -112
  69. data/vendor/assets/javascripts/mercury/dependencies/{jquery-1.6.js → jquery-1.7.js} +2030 -1595
  70. data/vendor/assets/javascripts/mercury/dependencies/jquery.additions.js +55 -0
  71. data/vendor/assets/javascripts/mercury/dialog.js.coffee +7 -5
  72. data/vendor/assets/javascripts/mercury/dialogs/backcolor.js.coffee +1 -1
  73. data/vendor/assets/javascripts/mercury/dialogs/forecolor.js.coffee +1 -1
  74. data/vendor/assets/javascripts/mercury/dialogs/formatblock.js.coffee +1 -1
  75. data/vendor/assets/javascripts/mercury/dialogs/{objectspanel.js.coffee → snippetpanel.js.coffee} +2 -2
  76. data/vendor/assets/javascripts/mercury/dialogs/style.js.coffee +1 -1
  77. data/vendor/assets/javascripts/mercury/finalize.js.coffee +3 -0
  78. data/vendor/assets/javascripts/mercury/lightview.js.coffee +76 -30
  79. data/vendor/assets/javascripts/mercury/locales/da.locale.js.coffee +211 -0
  80. data/vendor/assets/javascripts/mercury/locales/de.locale.js.coffee +206 -0
  81. data/vendor/assets/javascripts/mercury/locales/es.locale.js.coffee +211 -0
  82. data/vendor/assets/javascripts/mercury/locales/example.local.js.coffee +211 -0
  83. data/vendor/assets/javascripts/mercury/locales/fr.locale.js.coffee +211 -0
  84. data/vendor/assets/javascripts/mercury/locales/it.locale.js.coffee +208 -0
  85. data/vendor/assets/javascripts/mercury/locales/ko.local.js.coffee +206 -0
  86. data/vendor/assets/javascripts/mercury/locales/nl.locale.js.coffee +206 -0
  87. data/vendor/assets/javascripts/mercury/locales/pt.locale.js.coffee +211 -0
  88. data/vendor/assets/javascripts/mercury/locales/sv.local.js.coffee +209 -0
  89. data/vendor/assets/javascripts/mercury/locales/swedish_chef.locale.js.coffee +213 -0
  90. data/vendor/assets/javascripts/mercury/mercury.js.coffee +62 -17
  91. data/vendor/assets/javascripts/mercury/modal.js.coffee +34 -21
  92. data/vendor/assets/javascripts/mercury/modals/htmleditor.js.coffee +1 -2
  93. data/vendor/assets/javascripts/mercury/modals/insertcharacter.js.coffee +3 -3
  94. data/vendor/assets/javascripts/mercury/modals/insertlink.js.coffee +4 -4
  95. data/vendor/assets/javascripts/mercury/modals/insertmedia.js.coffee +10 -9
  96. data/vendor/assets/javascripts/mercury/modals/insertsnippet.js.coffee +1 -1
  97. data/vendor/assets/javascripts/mercury/modals/inserttable.js.coffee +8 -9
  98. data/vendor/assets/javascripts/mercury/native_extensions.js.coffee +26 -8
  99. data/vendor/assets/javascripts/mercury/page_editor.js.coffee +68 -46
  100. data/vendor/assets/javascripts/mercury/palette.js.coffee +1 -1
  101. data/vendor/assets/javascripts/mercury/panel.js.coffee +25 -7
  102. data/vendor/assets/javascripts/mercury/plugins/save_as_xml/mercury/page_editor.js.coffee +1 -0
  103. data/vendor/assets/javascripts/mercury/region.js.coffee +21 -17
  104. data/vendor/assets/javascripts/mercury/regions/editable.js.coffee +47 -35
  105. data/vendor/assets/javascripts/mercury/regions/markupable.js.coffee +43 -36
  106. data/vendor/assets/javascripts/mercury/regions/snippetable.js.coffee +22 -24
  107. data/vendor/assets/javascripts/mercury/select.js.coffee +3 -2
  108. data/vendor/assets/javascripts/mercury/snippet.js.coffee +2 -1
  109. data/vendor/assets/javascripts/mercury/snippet_toolbar.js.coffee +10 -7
  110. data/vendor/assets/javascripts/mercury/statusbar.js.coffee +4 -4
  111. data/vendor/assets/javascripts/mercury/table_editor.js.coffee +1 -3
  112. data/vendor/assets/javascripts/mercury/toolbar.button.js.coffee +42 -20
  113. data/vendor/assets/javascripts/mercury/toolbar.button_group.js.coffee +3 -3
  114. data/vendor/assets/javascripts/mercury/toolbar.expander.js.coffee +2 -2
  115. data/vendor/assets/javascripts/mercury/toolbar.js.coffee +8 -6
  116. data/vendor/assets/javascripts/mercury/tooltip.js.coffee +13 -9
  117. data/vendor/assets/javascripts/mercury/uploader.js.coffee +22 -16
  118. data/vendor/assets/javascripts/mercury_loader.js +2 -0
  119. data/vendor/assets/javascripts/mercury_overrides.js +6 -0
  120. data/vendor/assets/stylesheets/mercury/all_images.css.erb +89 -0
  121. data/vendor/assets/stylesheets/mercury/dialog.css +13 -4
  122. data/vendor/assets/stylesheets/mercury/lightview.css +66 -15
  123. data/vendor/assets/stylesheets/mercury/mercury.css +12 -7
  124. data/vendor/assets/stylesheets/mercury/modal.css +9 -5
  125. data/vendor/assets/stylesheets/mercury/toolbar.css +3 -29
  126. metadata +266 -144
  127. data/POST_INSTALL +0 -15
  128. data/README.md +0 -299
  129. data/VERSION +0 -1
  130. data/annotated_source.template +0 -57
  131. data/config/routes.rb +0 -15
  132. data/mercury-rails.gemspec +0 -288
  133. data/spec/javascripts/responses/blank.html +0 -1
  134. data/vendor/assets/javascripts/mercury/lightviews/imageprocessor.js.coffee +0 -2
@@ -1,4 +1,4 @@
1
1
  @Mercury.modalHandlers.insertCharacter = ->
2
- @element.find('.character').click ->
3
- Mercury.trigger('action', {action: 'insertHTML', value: "&#{jQuery(@).attr('data-entity')};"})
4
- Mercury.modal.hide()
2
+ @element.find('.character').on 'click', (event) =>
3
+ Mercury.trigger('action', {action: 'insertHTML', value: "&#{jQuery(event.target).attr('data-entity')};"})
4
+ @hide()
@@ -1,13 +1,13 @@
1
1
  @Mercury.modalHandlers.insertLink = ->
2
2
  # make the inputs work with the radio buttons
3
- @element.find('label input').click (event) ->
3
+ @element.find('label input').on 'click', ->
4
4
  jQuery(@).closest('label').next('.selectable').focus()
5
5
 
6
- @element.find('.selectable').focus ->
6
+ @element.find('.selectable').on 'focus', ->
7
7
  jQuery(@).prev('label').find('input[type=radio]').prop("checked", true)
8
8
 
9
9
  # show/hide the link target options on target change
10
- @element.find('#link_target').change =>
10
+ @element.find('#link_target').on 'change', =>
11
11
  @element.find(".link-target-options").hide()
12
12
  @element.find("##{@element.find('#link_target').val()}_options").show()
13
13
  @resize(true)
@@ -59,7 +59,7 @@
59
59
  @element.find('#link_text').val(selection.textContent()) if selection.textContent
60
60
 
61
61
  # build the link on form submission
62
- @element.find('form').submit (event) =>
62
+ @element.find('form').on 'submit', (event) =>
63
63
  event.preventDefault()
64
64
 
65
65
  content = @element.find('#link_text').val()
@@ -1,9 +1,9 @@
1
1
  @Mercury.modalHandlers.insertMedia = ->
2
2
  # make the inputs work with the radio buttons, and options
3
- @element.find('label input').click (event) ->
3
+ @element.find('label input').on 'click', ->
4
4
  jQuery(@).closest('label').next('.selectable').focus()
5
5
 
6
- @element.find('.selectable').focus (event) =>
6
+ @element.find('.selectable').on 'focus', (event) =>
7
7
  element = jQuery(event.target)
8
8
  element.prev('label').find('input[type=radio]').prop("checked", true)
9
9
 
@@ -19,6 +19,7 @@
19
19
  if selection.is && image = selection.is('img')
20
20
  @element.find('#media_image_url').val(image.attr('src'))
21
21
  @element.find('#media_image_alignment').val(image.attr('align'))
22
+ setTimeout 300, => @element.find('#media_image_url').focus()
22
23
 
23
24
  # if we're editing an iframe (assume it's a video for now)
24
25
  if selection.is && iframe = selection.is('iframe')
@@ -28,18 +29,18 @@
28
29
  @element.find('#media_youtube_url').val("http://youtu.be/#{src.match(/\/embed\/(\w+)/)[1]}")
29
30
  @element.find('#media_youtube_width').val(iframe.width())
30
31
  @element.find('#media_youtube_height').val(iframe.height())
31
- @element.find('#media_youtube_url').focus()
32
+ setTimeout 300, => @element.find('#media_youtube_url').focus()
32
33
  else if src.indexOf('http://player.vimeo.com') > -1
33
34
  # it's a vimeo video
34
35
  @element.find('#media_vimeo_url').val("http://vimeo.com/#{src.match(/\/video\/(\w+)/)[1]}")
35
36
  @element.find('#media_vimeo_width').val(iframe.width())
36
37
  @element.find('#media_vimeo_height').val(iframe.height())
37
- @element.find('#media_vimeo_url').focus()
38
+ setTimeout 300, => @element.find('#media_vimeo_url').focus()
39
+
38
40
 
39
41
  # build the image or youtube embed on form submission
40
- @element.find('form').submit (event) =>
42
+ @element.find('form').on 'submit', (event) =>
41
43
  event.preventDefault()
42
-
43
44
  type = @element.find('input[name=media_type]:checked').val()
44
45
 
45
46
  switch type
@@ -51,7 +52,7 @@
51
52
  when 'youtube_url'
52
53
  url = @element.find('#media_youtube_url').val()
53
54
  unless /^http:\/\/youtu.be\//.test(url)
54
- alert('Error: The provided youtube share url was invalid.')
55
+ Mercury.notify('Error: The provided youtube share url was invalid.')
55
56
  return
56
57
  code = url.replace('http://youtu.be/', '')
57
58
  value = jQuery('<iframe>', {
@@ -66,14 +67,14 @@
66
67
  when 'vimeo_url'
67
68
  url = @element.find('#media_vimeo_url').val()
68
69
  unless /^http:\/\/vimeo.com\//.test(url)
69
- alert('Error: The provided vimeo url was invalid.')
70
+ Mercury.notify('Error: The provided vimeo url was invalid.')
70
71
  return
71
72
  code = url.replace('http://vimeo.com/', '')
72
73
  value = jQuery('<iframe>', {
73
74
  width: @element.find('#media_vimeo_width').val() || 400,
74
75
  height: @element.find('#media_vimeo_height').val() || 225,
75
76
  src: "http://player.vimeo.com/video/#{code}?title=1&byline=1&portrait=0&color=ffffff",
76
- frameborder: 0,
77
+ frameborder: 0
77
78
  })
78
79
  Mercury.trigger('action', {action: 'insertHTML', value: value})
79
80
 
@@ -1,5 +1,5 @@
1
1
  @Mercury.modalHandlers.insertSnippet = ->
2
- @element.find('form').submit (event) =>
2
+ @element.find('form').on 'submit', (event) =>
3
3
  event.preventDefault()
4
4
  serializedForm = @element.find('form').serializeObject()
5
5
  if Mercury.snippet
@@ -2,7 +2,7 @@
2
2
  table = @element.find('#table_display table')
3
3
 
4
4
  # make td's selectable
5
- table.click (event) =>
5
+ table.on 'click', (event) =>
6
6
  cell = jQuery(event.target)
7
7
  table = cell.closest('table')
8
8
  table.find('.selected').removeAttr('class')
@@ -15,7 +15,7 @@
15
15
  Mercury.tableEditor(table, firstCell, '&nbsp;')
16
16
 
17
17
  # make the buttons work
18
- @element.find('input.action').click (event) =>
18
+ @element.find('input.action').on 'click', (event) =>
19
19
  action = jQuery(event.target).attr('name')
20
20
  switch action
21
21
  when 'insertRowBefore' then Mercury.tableEditor.addRow('before')
@@ -30,26 +30,25 @@
30
30
  when 'decreaseRowspan' then Mercury.tableEditor.decreaseRowspan()
31
31
 
32
32
  # set the alignment
33
- @element.find('#table_alignment').change =>
33
+ @element.find('#table_alignment').on 'change', =>
34
34
  table.attr({align: @element.find('#table_alignment').val()})
35
35
 
36
36
  # set the border
37
- @element.find('#table_border').keyup =>
37
+ @element.find('#table_border').on 'keyup', =>
38
38
  table.attr({border: parseInt(@element.find('#table_border').val())})
39
39
 
40
40
  # set the cellspacing
41
- @element.find('#table_spacing').keyup =>
41
+ @element.find('#table_spacing').on 'keyup', =>
42
42
  table.attr({cellspacing: parseInt(@element.find('#table_spacing').val())})
43
43
 
44
44
  # build the table on form submission
45
- @element.find('form').submit (event) =>
45
+ @element.find('form').on 'submit', (event) =>
46
46
  event.preventDefault()
47
47
  table.find('.selected').removeAttr('class')
48
- table.find('td, th').html('&nbsp;')
48
+ table.find('td, th').html('<br/>')
49
49
 
50
50
  html = jQuery('<div>').html(table).html()
51
51
  value = html.replace(/^\s+|\n/gm, '').replace(/(<\/.*?>|<table.*?>|<tbody>|<tr>)/g, '$1\n')
52
52
 
53
- Mercury.trigger('action', {action: 'insertHTML', value: value})
53
+ Mercury.trigger('action', {action: 'insertTable', value: value})
54
54
  @hide()
55
-
@@ -3,18 +3,36 @@ String::titleize = ->
3
3
 
4
4
 
5
5
  String::toHex = ->
6
- # todo: we should handle alpha as well
7
6
  return @ if @[0] == '#'
8
- @replace /rgba?\((\d+)[\s|\,]?\s(\d+)[\s|\,]?\s(\d+)\)/gi, (a, r, g, b) ->
7
+ @replace /rgb(a)?\(([0-9|%]+)[\s|,]?\s?([0-9|%]+)[\s|,]?\s?([0-9|%]+)[\s|,]?\s?([0-9|.|%]+\s?)?\)/gi, (x, alpha, r, g, b, a) ->
9
8
  "##{parseInt(r).toHex()}#{parseInt(g).toHex()}#{parseInt(b).toHex()}"
10
9
 
11
10
 
12
- String::sanitizeHTML = ->
13
- element = jQuery('<div>').html(@.toString())
14
- element.find('style').remove()
15
- content = element.text()
16
- content = content.replace(/\n+/g, '<br/>').replace(/.*<!--.*-->/g, '').replace(/^(<br\/>)+|(<br\/>\s*)+$/g, '')
17
- return content
11
+ String::regExpEscape = ->
12
+ specials = ['/','.','*','+','?','|','(',')','[',']','{','}','\\']
13
+ escaped = new RegExp('(\\' + specials.join('|\\') + ')', 'g')
14
+ return @replace(escaped, '\\$1')
15
+
16
+
17
+ String::printf = ->
18
+ chunks = @split('%')
19
+ result = chunks[0]
20
+ re = /^([sdf])([\s\S%]*)$/
21
+ offset = 0
22
+ for chunk, index in chunks
23
+ p = re.exec(chunk)
24
+ if index == 0 || !p || arguments[index] == null
25
+ if index > 1
26
+ offset += 2
27
+ result += "%#{chunk}"
28
+ continue
29
+ arg = arguments[(index - 1) - offset]
30
+ switch p[1]
31
+ when 's' then result += arg
32
+ when 'd', 'i' then result += parseInt(arg.toString(), 10)
33
+ when 'f' then result += parseFloat(arg)
34
+ result += p[2]
35
+ return result
18
36
 
19
37
 
20
38
  Number::toHex = ->
@@ -6,10 +6,9 @@ class @Mercury.PageEditor
6
6
  # saveMethod: 'POST', or 'PUT', create or update actions on save (defaults to POST)
7
7
  # visible: boolean, if the interface should start visible or not (defaults to true)
8
8
  constructor: (@saveUrl = null, @options = {}) ->
9
- throw "Mercury.PageEditor is unsupported in this client. Supported browsers are chrome 10+, firefix 4+, and safari 5+." unless Mercury.supported
10
- throw "Mercury.PageEditor can only be instantiated once." if window.mercuryInstance
9
+ throw Mercury.I18n('Mercury.PageEditor can only be instantiated once.') if window.mercuryInstance
11
10
 
12
- @options.visible = true unless @options.visible == false
11
+ @options.visible = true unless (@options.visible == false || @options.visible == 'no')
13
12
  @visible = @options.visible
14
13
 
15
14
  window.mercuryInstance = @
@@ -24,26 +23,24 @@ class @Mercury.PageEditor
24
23
  @iframe = jQuery('<iframe>', {id: 'mercury_iframe', class: 'mercury-iframe', seamless: 'true', frameborder: '0', src: 'about:blank'})
25
24
  @iframe.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
26
25
 
27
- @iframe.load => @initializeFrame()
28
- @iframe.get(0).contentWindow.document.location.href = @iframeSrc()
29
-
30
26
  @toolbar = new Mercury.Toolbar(@options)
31
27
  @statusbar = new Mercury.Statusbar(@options)
28
+ @resize()
29
+
30
+ @iframe.on 'load', => @initializeFrame()
31
+ @iframe.get(0).contentWindow.document.location.href = @iframeSrc(null, true)
32
32
 
33
33
 
34
34
  initializeFrame: ->
35
35
  try
36
36
  return if @iframe.data('loaded')
37
37
  @iframe.data('loaded', true)
38
- alert("Opera isn't a fully supported browser, your results may not be optimal.") if jQuery.browser.opera
38
+ Mercury.notify("Opera isn't a fully supported browser, your results may not be optimal.") if jQuery.browser.opera
39
39
  @document = jQuery(@iframe.get(0).contentWindow.document)
40
- stylesToInject = Mercury.config.injectedStyles.replace(/{{regionClass}}/g, Mercury.config.regionClass)
40
+ stylesToInject = Mercury.config.injectedStyles.replace(/{{regionClass}}/g, Mercury.config.regions.className)
41
41
  jQuery("<style mercury-styles=\"true\">").html(stylesToInject).appendTo(@document.find('head'))
42
42
 
43
- # jquery: make jQuery evaluate scripts within the context of the iframe window -- note that this means that we
44
- # can't use eval in mercury (eg. script tags in ajax responses) because it will eval in the wrong context (you can
45
- # use top.Mercury though, if you keep it in mind)
46
- # todo: look into `context` options for ajax as an alternative
43
+ # jquery: make jQuery evaluate scripts within the context of the iframe window
47
44
  iframeWindow = @iframe.get(0).contentWindow
48
45
  jQuery.globalEval = (data) -> (iframeWindow.execScript || (data) -> iframeWindow["eval"].call(iframeWindow, data))(data) if (data && /\S/.test(data))
49
46
 
@@ -61,11 +58,12 @@ class @Mercury.PageEditor
61
58
 
62
59
  @iframe.css({visibility: 'visible'})
63
60
  catch error
64
- alert("Mercury.PageEditor failed to load: #{error}\n\nPlease try refreshing.")
61
+ Mercury.notify('Mercury.PageEditor failed to load: %s\n\nPlease try refreshing.', error)
65
62
 
66
63
 
67
64
  initializeRegions: ->
68
- @buildRegion(jQuery(region)) for region in jQuery(".#{Mercury.config.regionClass}", @document)
65
+ @regions = []
66
+ @buildRegion(jQuery(region)) for region in jQuery(".#{Mercury.config.regions.className}", @document)
69
67
  return unless @options.visible
70
68
  for region in @regions
71
69
  if region.focus
@@ -74,16 +72,21 @@ class @Mercury.PageEditor
74
72
 
75
73
 
76
74
  buildRegion: (region) ->
77
- try
78
- type = region.data('type').titleize()
79
- @regions.push(new Mercury.Regions[type](region, @iframe.get(0).contentWindow))
80
- catch error
81
- alert(error) if Mercury.debug
82
- alert("Region type is malformed, no data-type provided, or \"#{type}\" is unknown.")
75
+ if region.data('region')
76
+ region = region.data('region')
77
+ else
78
+ type = (region.data('type') || 'unknown').titleize()
79
+ throw Mercury.I18n('Region type is malformed, no data-type provided, or "%s" is unknown for the "%s" region.', type, region.attr('id') || 'unknown') if type == 'Unknown' || !Mercury.Regions[type]
80
+ if !Mercury.Regions[type].supported
81
+ Mercury.notify('Mercury.Regions.%s is unsupported in this client. Supported browsers are %s.', type, Mercury.Regions[type].supportedText)
82
+ return false
83
+ region = new Mercury.Regions[type](region, @iframe.get(0).contentWindow)
84
+ region.togglePreview() if @previewing
85
+ @regions.push(region)
83
86
 
84
87
 
85
88
  finalizeInterface: ->
86
- @santizerElement = jQuery('<div>', {id: 'mercury_sanitizer', contenteditable: 'true', style: 'position:fixed;width:100px;height:100px;top:-100px;left:-100px;opacity:0'})
89
+ @santizerElement = jQuery('<div>', {id: 'mercury_sanitizer', contenteditable: 'true', style: 'position:fixed;width:100px;height:100px;top:0;left:-100px;opacity:0;overflow:hidden'})
87
90
  @santizerElement.appendTo(@options.appendTo ? @document.find('body'))
88
91
 
89
92
  @snippetToolbar = new Mercury.SnippetToolbar(@document)
@@ -93,26 +96,44 @@ class @Mercury.PageEditor
93
96
 
94
97
 
95
98
  bindEvents: ->
96
- Mercury.bind 'initialize:frame', => setTimeout(@initializeFrame, 1000)
97
- Mercury.bind 'focus:frame', => @iframe.focus()
98
- Mercury.bind 'focus:window', => setTimeout((=> @focusableElement.focus()), 10)
99
+ Mercury.on 'initialize:frame', => setTimeout(100, @initializeFrame)
100
+ Mercury.on 'focus:frame', => @iframe.focus()
101
+ Mercury.on 'focus:window', => setTimeout(10, => @focusableElement.focus())
102
+ Mercury.on 'toggle:interface', => @toggleInterface()
103
+ Mercury.on 'reinitialize', => @initializeRegions()
104
+ Mercury.on 'mode', (event, options) => @previewing = !@previewing if options.mode == 'preview'
105
+ Mercury.on 'action', (event, options) =>
106
+ action = Mercury.config.globalBehaviors[options.action] || @[options.action]
107
+ return unless typeof(action) == 'function'
108
+ options.already_handled = true
109
+ action.call(@, options)
110
+
111
+ @document.on 'mousedown', (event) ->
112
+ Mercury.trigger('hide:dialogs')
113
+ if Mercury.region
114
+ Mercury.trigger('unfocus:regions') unless jQuery(event.target).closest(".#{Mercury.config.regions.className}").get(0) == Mercury.region.element.get(0)
99
115
 
100
- Mercury.bind 'toggle:interface', => @toggleInterface()
116
+ jQuery(window).on 'resize', =>
117
+ @resize()
101
118
 
102
- Mercury.bind 'action', (event, options) =>
103
- @save() if options.action == 'save'
119
+ jQuery(@document).bind 'keydown', (event) =>
120
+ return unless event.ctrlKey || event.metaKey
121
+ if (event.keyCode == 83) # meta+S
122
+ Mercury.trigger('action', {action: 'save'})
123
+ event.preventDefault()
104
124
 
105
- @document.mousedown (event) ->
106
- Mercury.trigger('hide:dialogs')
107
- if Mercury.region
108
- Mercury.trigger('unfocus:regions') unless jQuery(event.target).closest(".#{Mercury.config.regionClass}").get(0) == Mercury.region.element.get(0)
125
+ jQuery(window).bind 'keydown', (event) =>
126
+ return unless event.ctrlKey || event.metaKey
127
+ if (event.keyCode == 83) # meta+S
128
+ Mercury.trigger('action', {action: 'save'})
129
+ event.preventDefault()
109
130
 
110
- jQuery(window).resize => @resize()
111
131
  window.onbeforeunload = @beforeUnload
112
132
 
113
133
 
114
134
  toggleInterface: ->
115
135
  if @visible
136
+ Mercury.trigger('mode', {mode: 'preview'}) if @previewing
116
137
  @visible = false
117
138
  @toolbar.hide()
118
139
  @statusbar.hide()
@@ -140,8 +161,13 @@ class @Mercury.PageEditor
140
161
  Mercury.trigger('resize')
141
162
 
142
163
 
143
- iframeSrc: (url = null) ->
144
- (url ? window.location.href).replace(/([http|https]:\/\/.[^\/]*)\/editor\/?(.*)/i, "$1/$2")
164
+ iframeSrc: (url = null, params = false) ->
165
+ url = (url ? window.location.href).replace(Mercury.config.editorUrlRegEx ?= /([http|https]:\/\/.[^\/]*)\/editor\/?(.*)/i, "$1/$2")
166
+ url = url.replace(/[\?|\&]mercury_frame=true/gi, '')
167
+ if params
168
+ return "#{url}#{if url.indexOf('?') > -1 then '&' else '?'}mercury_frame=true"
169
+ else
170
+ return url
145
171
 
146
172
 
147
173
  hijackLinksAndForms: ->
@@ -151,13 +177,13 @@ class @Mercury.PageEditor
151
177
  if jQuery(element).hasClass(classname)
152
178
  ignored = true
153
179
  continue
154
- if !ignored && (element.target == '' || element.target == '_self') && !jQuery(element).closest(".#{Mercury.config.regionClass}").length
155
- jQuery(element).attr('target', '_top')
180
+ if !ignored && (element.target == '' || element.target == '_self') && !jQuery(element).closest(".#{Mercury.config.regions.className}").length
181
+ jQuery(element).attr('target', '_parent')
156
182
 
157
183
 
158
184
  beforeUnload: ->
159
185
  if Mercury.changes && !Mercury.silent
160
- return "You have unsaved changes. Are you sure you want to leave without saving them first?"
186
+ return Mercury.I18n('You have unsaved changes. Are you sure you want to leave without saving them first?')
161
187
  return null
162
188
 
163
189
 
@@ -167,30 +193,26 @@ class @Mercury.PageEditor
167
193
  return null
168
194
 
169
195
 
170
- save: ->
196
+ save: (callback) ->
171
197
  url = @saveUrl ? Mercury.saveURL ? @iframeSrc()
172
198
  data = @serialize()
173
199
  Mercury.log('saving', data)
174
200
  data = jQuery.toJSON(data) unless @options.saveStyle == 'form'
175
201
  method = 'PUT' if @options.saveMethod == 'PUT'
176
202
  jQuery.ajax url, {
203
+ headers: Mercury.ajaxHeaders()
177
204
  type: method || 'POST'
178
205
  dataType: @options.saveDataType || 'json'
179
- headers: @saveHeaders()
180
206
  data: {content: data, _method: method}
181
207
  success: =>
182
208
  Mercury.changes = false
209
+ Mercury.trigger('saved')
210
+ callback() if typeof(callback) == 'function'
183
211
  error: =>
184
- alert("Mercury was unable to save to the url: #{url}")
212
+ Mercury.notify('Mercury was unable to save to the url: %s', url)
185
213
  }
186
214
 
187
215
 
188
- saveHeaders: ->
189
- headers = {}
190
- headers[Mercury.config.csrfHeader] = Mercury.csrfToken
191
- return headers
192
-
193
-
194
216
  serialize: ->
195
217
  serialized = {}
196
218
  serialized[region.name] = region.serialize() for region in @regions
@@ -10,7 +10,7 @@ class @Mercury.Palette extends Mercury.Dialog
10
10
 
11
11
 
12
12
  bindEvents: ->
13
- Mercury.bind 'hide:dialogs', (event, dialog) => @hide() unless dialog == @
13
+ Mercury.on 'hide:dialogs', (event, dialog) => @hide() unless dialog == @
14
14
  super
15
15
 
16
16
 
@@ -6,20 +6,34 @@ class @Mercury.Panel extends Mercury.Dialog
6
6
 
7
7
  build: ->
8
8
  @element = jQuery('<div>', {class: 'mercury-panel loading', style: 'display:none;'})
9
- @titleElement = jQuery("<h1>#{@options.title}</h1>").appendTo(@element)
9
+ @titleElement = jQuery("<h1>#{Mercury.I18n(@options.title)}</h1>").appendTo(@element)
10
10
  @paneElement = jQuery('<div>', {class: 'mercury-panel-pane'}).appendTo(@element)
11
11
 
12
+ if @options.closeButton
13
+ jQuery('<a/>', {class: 'mercury-panel-close'}).appendTo(@titleElement).css({opacity: 0})
14
+
12
15
  @element.appendTo(jQuery(@options.appendTo).get(0) ? 'body')
13
16
 
14
17
 
15
18
  bindEvents: ->
16
- Mercury.bind 'resize', => @position(@visible)
17
- Mercury.bind 'hide:panels', (event, panel) =>
18
- unless panel == @
19
- @button.removeClass('pressed')
20
- @hide()
19
+ Mercury.on 'resize', => @position(@visible)
20
+
21
+ Mercury.on 'hide:panels', (event, panel) =>
22
+ return if panel == @
23
+ @button.removeClass('pressed')
24
+ @hide()
25
+
26
+ @titleElement.find('.mercury-panel-close').on 'click', (event) ->
27
+ event.preventDefault()
28
+ Mercury.trigger('hide:panels')
21
29
 
22
- @element.mousedown (event) -> event.stopPropagation()
30
+ @element.on 'mousedown', (event) ->
31
+ event.stopPropagation()
32
+
33
+ @element.on 'ajax:beforeSend', (event, xhr, options) =>
34
+ options.success = (content) =>
35
+ @loadContent(content)
36
+ @resize()
23
37
 
24
38
  super
25
39
 
@@ -30,6 +44,7 @@ class @Mercury.Panel extends Mercury.Dialog
30
44
 
31
45
 
32
46
  resize: ->
47
+ @titleElement.find('.mercury-panel-close').css({opacity: 0})
33
48
  @paneElement.css({display: 'none'})
34
49
  preWidth = @element.width()
35
50
 
@@ -39,6 +54,8 @@ class @Mercury.Panel extends Mercury.Dialog
39
54
  @paneElement.css({visibility: 'visible', display: 'none'})
40
55
  position = @element.offset()
41
56
  @element.animate {left: position.left - (postWidth - preWidth), width: postWidth}, 200, 'easeInOutSine', =>
57
+ @titleElement.find('.mercury-panel-close').animate({opacity: 1}, 100)
58
+
42
59
  @paneElement.css({display: 'block', width: postWidth})
43
60
  @makeDraggable()
44
61
 
@@ -77,6 +94,7 @@ class @Mercury.Panel extends Mercury.Dialog
77
94
  @element.removeClass('loading')
78
95
  @paneElement.css({visibility: 'hidden'})
79
96
  @paneElement.html(data)
97
+ @paneElement.localize(Mercury.locale()) if Mercury.config.localization.enabled
80
98
 
81
99
 
82
100
  makeDraggable: ->