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
@@ -7,6 +7,7 @@ class Mercury.PageEditor extends Mercury.PageEditor
7
7
  return
8
8
  method = 'PUT' if @options.saveMethod == 'PUT'
9
9
  jQuery.ajax url, {
10
+ headers: Mercury.ajaxHeaders()
10
11
  type: method || 'POST'
11
12
  dataType: 'xml'
12
13
  data: data
@@ -6,11 +6,12 @@ class @Mercury.Region
6
6
  Mercury.log("building #{@type}", @element, @options)
7
7
 
8
8
  @document = @window.document
9
- @name = @element.attr('id')
9
+ @name = @element.attr(Mercury.config.regions.identifier)
10
10
  @history = new Mercury.HistoryBuffer()
11
11
  @build()
12
12
  @bindEvents()
13
13
  @pushHistory()
14
+ @element.data('region', @)
14
15
 
15
16
 
16
17
  build: ->
@@ -20,28 +21,24 @@ class @Mercury.Region
20
21
 
21
22
 
22
23
  bindEvents: ->
23
- Mercury.bind 'mode', (event, options) =>
24
- @togglePreview() if options.mode == 'preview'
24
+ Mercury.on 'mode', (event, options) => @togglePreview() if options.mode == 'preview'
25
25
 
26
- Mercury.bind 'focus:frame', =>
27
- return if @previewing
28
- return unless Mercury.region == @
26
+ Mercury.on 'focus:frame', =>
27
+ return if @previewing || Mercury.region != @
29
28
  @focus()
30
29
 
31
- Mercury.bind 'action', (event, options) =>
32
- return if @previewing
33
- return unless Mercury.region == @
30
+ Mercury.on 'action', (event, options) =>
31
+ return if @previewing || Mercury.region != @
34
32
  @execCommand(options.action, options) if options.action
35
33
 
36
- @element.mousemove (event) =>
37
- return if @previewing
38
- return unless Mercury.region == @
34
+ @element.on 'mousemove', (event) =>
35
+ return if @previewing || Mercury.region != @
39
36
  snippet = jQuery(event.target).closest('.mercury-snippet')
40
37
  if snippet.length
41
38
  @snippet = snippet
42
39
  Mercury.trigger('show:toolbar', {type: 'snippet', snippet: @snippet})
43
40
 
44
- @element.mouseout (event) =>
41
+ @element.on 'mouseout', =>
45
42
  return if @previewing
46
43
  Mercury.trigger('hide:toolbar', {type: 'snippet', immediately: false})
47
44
 
@@ -55,7 +52,7 @@ class @Mercury.Region
55
52
  container.html(@element.html().replace(/^\s+|\s+$/g, ''))
56
53
 
57
54
  # replace snippet contents to be an identifier
58
- if filterSnippets then for snippet, index in container.find('.mercury-snippet')
55
+ if filterSnippets then for snippet in container.find('.mercury-snippet')
59
56
  snippet = jQuery(snippet)
60
57
  snippet.attr({contenteditable: null, 'data-version': null})
61
58
  snippet.html("[#{snippet.data('snippet')}]")
@@ -66,11 +63,11 @@ class @Mercury.Region
66
63
  togglePreview: ->
67
64
  if @previewing
68
65
  @previewing = false
69
- @element.addClass(Mercury.config.regionClass).removeClass("#{Mercury.config.regionClass}-preview")
66
+ @element.addClass(Mercury.config.regions.className).removeClass("#{Mercury.config.regions.className}-preview")
70
67
  @focus() if Mercury.region == @
71
68
  else
72
69
  @previewing = true
73
- @element.addClass("#{Mercury.config.regionClass}-preview").removeClass(Mercury.config.regionClass)
70
+ @element.addClass("#{Mercury.config.regions.className}-preview").removeClass(Mercury.config.regions.className)
74
71
  Mercury.trigger('region:blurred', {region: @})
75
72
 
76
73
 
@@ -79,7 +76,7 @@ class @Mercury.Region
79
76
  @pushHistory() unless action == 'redo'
80
77
 
81
78
  Mercury.log('execCommand', action, options.value)
82
- Mercury.changes = true
79
+ Mercury.changes = true unless options.already_handled
83
80
 
84
81
 
85
82
  pushHistory: ->
@@ -95,9 +92,16 @@ class @Mercury.Region
95
92
  return snippets
96
93
 
97
94
 
95
+ dataAttributes: ->
96
+ data = {}
97
+ data[attr] = @element.attr('data-' + attr) for attr in Mercury.config.regions.dataAttributes
98
+ return data
99
+
100
+
98
101
  serialize: ->
99
102
  return {
100
103
  type: @type
104
+ data: @dataAttributes()
101
105
  value: @content(null, true)
102
106
  snippets: @snippets()
103
107
  }
@@ -1,4 +1,8 @@
1
1
  class @Mercury.Regions.Editable extends Mercury.Region
2
+ # No IE support yet because it doesn't follow the W3C standards for HTML5 contentEditable (aka designMode).
3
+ @supported: document.designMode && !jQuery.browser.konqueror && !jQuery.browser.msie
4
+ @supportedText: "Chrome 10+, Firefox 4+, Safari 5+"
5
+
2
6
  type = 'editable'
3
7
 
4
8
  constructor: (@element, @window, @options = {}) ->
@@ -41,15 +45,14 @@ class @Mercury.Regions.Editable extends Mercury.Region
41
45
  bindEvents: ->
42
46
  super
43
47
 
44
- Mercury.bind 'region:update', =>
45
- return if @previewing
46
- return unless Mercury.region == @
47
- setTimeout((=> @selection().forceSelection(@element.get(0))), 1)
48
+ Mercury.on 'region:update', =>
49
+ return if @previewing || Mercury.region != @
50
+ setTimeout(1, => @selection().forceSelection(@element.get(0)))
48
51
  currentElement = @currentElement()
49
52
  if currentElement.length
50
53
  # setup the table editor if we're inside a table
51
54
  table = currentElement.closest('table', @element)
52
- Mercury.tableEditor(table, currentElement.closest('tr, td'), ' ') if table.length
55
+ Mercury.tableEditor(table, currentElement.closest('tr, td'), '<br/>') if table.length
53
56
  # display a tooltip if we're in an anchor
54
57
  anchor = currentElement.closest('a', @element)
55
58
  if anchor.length && anchor.attr('href')
@@ -57,25 +60,25 @@ class @Mercury.Regions.Editable extends Mercury.Region
57
60
  else
58
61
  Mercury.tooltip.hide()
59
62
 
60
- @element.bind 'dragenter', (event) =>
63
+ @element.on 'dragenter', (event) =>
61
64
  return if @previewing
62
65
  event.preventDefault() unless Mercury.snippet
63
66
  event.originalEvent.dataTransfer.dropEffect = 'copy'
64
67
 
65
- @element.bind 'dragover', (event) =>
68
+ @element.on 'dragover', (event) =>
66
69
  return if @previewing
67
70
  event.preventDefault() unless Mercury.snippet
68
71
  event.originalEvent.dataTransfer.dropEffect = 'copy'
69
72
  if jQuery.browser.webkit
70
73
  clearTimeout(@dropTimeout)
71
- @dropTimeout = setTimeout((=> @element.trigger('possible:drop')), 10)
74
+ @dropTimeout = setTimeout(10, => @element.trigger('possible:drop'))
72
75
 
73
- @element.bind 'drop', (event) =>
76
+ @element.on 'drop', (event) =>
74
77
  return if @previewing
75
78
 
76
79
  # handle dropping snippets
77
80
  clearTimeout(@dropTimeout)
78
- @dropTimeout = setTimeout((=> @element.trigger('possible:drop')), 1)
81
+ @dropTimeout = setTimeout(1, => @element.trigger('possible:drop'))
79
82
 
80
83
  # handle any files that were dropped
81
84
  return unless event.originalEvent.dataTransfer.files.length
@@ -88,7 +91,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
88
91
  # isn't handled (eg, putting the image where it was dropped,) so to allow the browser to do it's thing, and also do
89
92
  # our thing we have this little hack. *sigh*
90
93
  # read: http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
91
- @element.bind 'possible:drop', =>
94
+ @element.on 'possible:drop', =>
92
95
  return if @previewing
93
96
  if snippet = @element.find('img[data-snippet]').get(0)
94
97
  @focus()
@@ -97,11 +100,11 @@ class @Mercury.Regions.Editable extends Mercury.Region
97
100
 
98
101
  # custom paste handling: we have to do some hackery to get the pasted content since it's not exposed normally
99
102
  # through a clipboard in firefox (heaven forbid), and to keep the behavior across all browsers, we manually detect
100
- # what was pasted by running a quick diff, removing it by calling undo, making our adjustments, and then putting the
101
- # content back. This is possible, so it doesn't make sense why it wouldn't be exposed in a sensible way. *sigh*
102
- @element.bind 'paste', (event) =>
103
- return if @previewing
104
- return unless Mercury.region == @
103
+ # what was pasted by focusing a different (hidden) region, letting it paste there, making our adjustments, and then
104
+ # inserting the content where it was intended. This is possible, so it doesn't make sense why it wouldn't be
105
+ # exposed in a sensible way. *sigh*
106
+ @element.on 'paste', (event) =>
107
+ return if @previewing || Mercury.region != @
105
108
  if @specialContainer
106
109
  event.preventDefault()
107
110
  return
@@ -109,35 +112,34 @@ class @Mercury.Regions.Editable extends Mercury.Region
109
112
  Mercury.changes = true
110
113
  @handlePaste(event.originalEvent)
111
114
 
112
- @element.focus =>
115
+ @element.on 'focus', =>
113
116
  return if @previewing
114
117
  Mercury.region = @
115
- setTimeout((=> @selection().forceSelection(@element.get(0))), 1)
118
+ setTimeout(1, => @selection().forceSelection(@element.get(0)))
116
119
  Mercury.trigger('region:focused', {region: @})
117
120
 
118
- @element.blur =>
121
+ @element.on 'blur', =>
119
122
  return if @previewing
120
123
  Mercury.trigger('region:blurred', {region: @})
121
124
  Mercury.tooltip.hide()
122
125
 
123
- @element.click (event) =>
124
- jQuery(event.target).closest('a').attr('target', '_top') if @previewing
126
+ @element.on 'click', (event) =>
127
+ jQuery(event.target).closest('a').attr('target', '_parent') if @previewing
125
128
 
126
- @element.dblclick (event) =>
129
+ @element.on 'dblclick', (event) =>
127
130
  return if @previewing
128
131
  image = jQuery(event.target).closest('img', @element)
129
132
  if image.length
130
133
  @selection().selectNode(image.get(0), true)
131
134
  Mercury.trigger('button', {action: 'insertMedia'})
132
135
 
133
- @element.mouseup =>
136
+ @element.on 'mouseup', =>
134
137
  return if @previewing
135
138
  @pushHistory()
136
139
  Mercury.trigger('region:update', {region: @})
137
140
 
138
- @element.keydown (event) =>
141
+ @element.on 'keydown', (event) =>
139
142
  return if @previewing
140
- Mercury.changes = true
141
143
  switch event.keyCode
142
144
  when 90 # undo / redo
143
145
  return unless event.metaKey
@@ -166,7 +168,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
166
168
  else if container.parents('ul, ol').length > 1
167
169
  @execCommand('outdent')
168
170
  else
169
- @execCommand('insertHTML', {value: '&nbsp; '})
171
+ @execCommand('insertHTML', {value: '&nbsp;&nbsp;'})
170
172
 
171
173
  if event.metaKey
172
174
  switch event.keyCode
@@ -184,15 +186,21 @@ class @Mercury.Regions.Editable extends Mercury.Region
184
186
 
185
187
  @pushHistory(event.keyCode)
186
188
 
187
- @element.keyup =>
189
+ @element.on 'keyup', =>
188
190
  return if @previewing
189
191
  Mercury.trigger('region:update', {region: @})
192
+ Mercury.changes = true
190
193
 
191
194
 
192
195
  focus: ->
193
196
  if Mercury.region != @
194
- @element.focus()
195
- selection = @selection().selection.collapseToStart()
197
+ setTimeout(10, => @element.focus())
198
+ try
199
+ @selection().selection.collapseToStart()
200
+ catch e
201
+ # intentially do nothing
202
+ else
203
+ setTimeout(10, => @element.focus())
196
204
 
197
205
  Mercury.trigger('region:focused', {region: @})
198
206
  Mercury.trigger('region:update', {region: @})
@@ -278,9 +286,12 @@ class @Mercury.Regions.Editable extends Mercury.Region
278
286
  @document.execCommand(action, false, options.value)
279
287
  catch error
280
288
  # mozilla: indenting when there's no br tag handles strangely
281
- # todo: mozilla: trying to justify the first line of any contentEditable fails
289
+ # mozilla: trying to justify the first line of any contentEditable fails
282
290
  @element.prev().remove() if action == 'indent' && @element.prev() != sibling
283
291
 
292
+ # handle any broken images by replacing the source with an alert image
293
+ @element.find('img').one 'error', -> jQuery(@).attr({src: '/assets/mercury/missing-image.png', title: 'Image not found'})
294
+
284
295
 
285
296
  pushHistory: (keyCode) ->
286
297
  # when pressing return, delete or backspace it should push to the history
@@ -297,7 +308,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
297
308
  @history.push(@content(null, false, true))
298
309
  else if keyCode
299
310
  # set a timeout for pushing to the history
300
- @historyTimeout = setTimeout((=> @history.push(@content(null, false, true))), waitTime * 1000)
311
+ @historyTimeout = setTimeout(waitTime * 1000, => @history.push(@content(null, false, true)))
301
312
  else
302
313
  # push to the history immediately
303
314
  @history.push(@content(null, false, true))
@@ -331,7 +342,6 @@ class @Mercury.Regions.Editable extends Mercury.Region
331
342
  event.preventDefault()
332
343
  return
333
344
  else
334
- console.debug('testing')
335
345
  # get current selection & range
336
346
  selection = @selection()
337
347
  selection.placeMarker()
@@ -354,7 +364,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
354
364
 
355
365
  sanitize: (sanitizer) ->
356
366
  # always remove nested regions
357
- sanitizer.find(".#{Mercury.config.regionClass}").remove()
367
+ sanitizer.find(".#{Mercury.config.regions.className}").remove()
358
368
 
359
369
  if Mercury.config.pasting.sanitize
360
370
  switch Mercury.config.pasting.sanitize
@@ -369,8 +379,8 @@ class @Mercury.Regions.Editable extends Mercury.Region
369
379
  for allowedTag, allowedAttributes of Mercury.config.pasting.whitelist
370
380
  if element.tagName.toLowerCase() == allowedTag.toLowerCase()
371
381
  allowed = true
372
- for attr, index in element.attributes
373
- jQuery(element).attr(attr.name, null) if attr && allowedAttributes.indexOf(attr.name) == -1
382
+ for attr in jQuery(element.attributes)
383
+ jQuery(element).removeAttr(attr.name) unless attr.name in allowedAttributes
374
384
  break
375
385
  jQuery(element).replaceWith(jQuery(element).contents()) unless allowed
376
386
  content = sanitizer.html()
@@ -426,6 +436,8 @@ class @Mercury.Regions.Editable extends Mercury.Region
426
436
 
427
437
  insertImage: (selection, options) -> @execCommand('insertHTML', {value: jQuery('<img/>', options.value)})
428
438
 
439
+ insertTable: (selection, options) -> @execCommand('insertHTML', {value: options.value})
440
+
429
441
  insertLink: (selection, options) ->
430
442
  anchor = jQuery("<#{options.value.tagName}>", @document).attr(options.value.attrs).html(options.value.content)
431
443
  selection.insertNode(anchor)
@@ -4,6 +4,9 @@
4
4
  # nice if we could activate the bold button for instance.
5
5
 
6
6
  class @Mercury.Regions.Markupable extends Mercury.Region
7
+ @supported: document.getElementById
8
+ @supportedText: "IE 7+, Chrome 10+, Firefox 4+, Safari 5+, Opera 8+"
9
+
7
10
  type = 'markupable'
8
11
 
9
12
  constructor: (@element, @window, @options = {}) ->
@@ -17,54 +20,46 @@ class @Mercury.Regions.Markupable extends Mercury.Region
17
20
  height = @element.height()
18
21
 
19
22
  value = @element.html().replace(/^\s+|\s+$/g, '').replace('&gt;', '>')
23
+ @element.removeClass(Mercury.config.regions.className)
20
24
  @textarea = jQuery('<textarea>', @document).val(value)
21
25
  @textarea.attr('class', @element.attr('class')).addClass('mercury-textarea')
22
- @textarea.css({border: 0, background: 'transparent', display: 'block', width: width, height: height, fontFamily: '"Courier New", Courier, monospace', fontSize: '14px'})
26
+ @textarea.css({border: 0, background: 'transparent', display: 'block', 'overflow-y': 'hidden', width: width, height: height, fontFamily: '"Courier New", Courier, monospace'})
27
+ @element.addClass(Mercury.config.regions.className)
23
28
  @element.empty().append(@textarea)
24
- @element.removeClass(Mercury.config.regionClass)
25
29
 
26
30
  @previewElement = jQuery('<div>', @document)
27
31
  @element.append(@previewElement)
32
+ @container = @element
33
+ @container.data('region', @)
28
34
  @element = @textarea
29
35
  @resize()
30
36
 
31
37
 
32
- focus: ->
33
- @element.focus()
34
-
35
-
36
38
  bindEvents: ->
37
- Mercury.bind 'mode', (event, options) =>
38
- @togglePreview() if options.mode == 'preview'
39
+ Mercury.on 'mode', (event, options) => @togglePreview() if options.mode == 'preview'
40
+ Mercury.on 'focus:frame', => @focus() if !@previewing && Mercury.region == @
39
41
 
40
- Mercury.bind 'focus:frame', =>
41
- return if @previewing
42
- return unless Mercury.region == @
43
- @focus()
44
-
45
- Mercury.bind 'action', (event, options) =>
46
- return if @previewing
47
- return unless Mercury.region == @
42
+ Mercury.on 'action', (event, options) =>
43
+ return if @previewing || Mercury.region != @
48
44
  @execCommand(options.action, options) if options.action
49
45
 
50
- Mercury.bind 'unfocus:regions', (event) =>
51
- return if @previewing
52
- return unless Mercury.region == @
46
+ Mercury.on 'unfocus:regions', =>
47
+ return if @previewing || Mercury.region != @
53
48
  @element.blur()
54
- @element.removeClass('focus')
49
+ @container.removeClass('focus')
55
50
  Mercury.trigger('region:blurred', {region: @})
56
51
 
57
- @element.bind 'dragenter', (event) =>
52
+ @element.on 'dragenter', (event) =>
58
53
  return if @previewing
59
54
  event.preventDefault()
60
55
  event.originalEvent.dataTransfer.dropEffect = 'copy'
61
56
 
62
- @element.bind 'dragover', (event) =>
57
+ @element.on 'dragover', (event) =>
63
58
  return if @previewing
64
59
  event.preventDefault()
65
60
  event.originalEvent.dataTransfer.dropEffect = 'copy'
66
61
 
67
- @element.bind 'drop', (event) =>
62
+ @element.on 'drop', (event) =>
68
63
  return if @previewing
69
64
 
70
65
  # handle dropping snippets
@@ -79,15 +74,14 @@ class @Mercury.Regions.Markupable extends Mercury.Region
79
74
  @focus()
80
75
  Mercury.uploader(event.originalEvent.dataTransfer.files[0])
81
76
 
82
- @element.focus =>
77
+ @element.on 'focus', =>
83
78
  return if @previewing
84
79
  Mercury.region = @
85
- @element.addClass('focus')
80
+ @container.addClass('focus')
86
81
  Mercury.trigger('region:focused', {region: @})
87
82
 
88
- @element.keydown (event) =>
83
+ @element.on 'keydown', (event) =>
89
84
  return if @previewing
90
- Mercury.changes = true
91
85
  @resize()
92
86
  switch event.keyCode
93
87
  when 90 # undo / redo
@@ -133,17 +127,23 @@ class @Mercury.Regions.Markupable extends Mercury.Region
133
127
 
134
128
  @pushHistory(event.keyCode)
135
129
 
136
- @element.keyup =>
130
+ @element.on 'keyup', =>
137
131
  return if @previewing
132
+ Mercury.changes = true
133
+ @resize()
138
134
  Mercury.trigger('region:update', {region: @})
139
135
 
140
- @element.mouseup =>
136
+ @element.on 'mouseup', =>
141
137
  return if @previewing
142
138
  @focus()
143
139
  Mercury.trigger('region:focused', {region: @})
144
140
 
145
- @previewElement.click (event) =>
146
- $(event.target).closest('a').attr('target', '_top') if @previewing
141
+ @previewElement.on 'click', (event) =>
142
+ $(event.target).closest('a').attr('target', '_parent') if @previewing
143
+
144
+
145
+ focus: ->
146
+ @element.focus()
147
147
 
148
148
 
149
149
  content: (value = null, filterSnippets = true) ->
@@ -163,14 +163,19 @@ class @Mercury.Regions.Markupable extends Mercury.Region
163
163
 
164
164
  togglePreview: ->
165
165
  if @previewing
166
+ @previewing = false
167
+ @container.addClass(Mercury.config.regions.className).removeClass("#{Mercury.config.regions.className}-preview")
166
168
  @previewElement.hide()
167
169
  @element.show()
170
+ @focus() if Mercury.region == @
168
171
  else
172
+ @previewing = true
173
+ @container.addClass("#{Mercury.config.regions.className}-preview").removeClass(Mercury.config.regions.className)
169
174
  value = @converter.makeHtml(@element.val())
170
175
  @previewElement.html(value)
171
176
  @previewElement.show()
172
177
  @element.hide()
173
- super
178
+ Mercury.trigger('region:blurred', {region: @})
174
179
 
175
180
 
176
181
  execCommand: (action, options = {}) ->
@@ -195,7 +200,7 @@ class @Mercury.Regions.Markupable extends Mercury.Region
195
200
  @history.push(@contentAndSelection())
196
201
  else if keyCode
197
202
  # set a timeout for pushing to the history
198
- @historyTimeout = setTimeout((=> @history.push(@contentAndSelection())), waitTime * 1000)
203
+ @historyTimeout = setTimeout(waitTime * 1000, => @history.push(@contentAndSelection()))
199
204
  else
200
205
  # push to the history immediately
201
206
  @history.push(@contentAndSelection())
@@ -208,9 +213,8 @@ class @Mercury.Regions.Markupable extends Mercury.Region
208
213
 
209
214
 
210
215
  resize: ->
211
- # todo: get this working if possible, and it seems to be useful
212
- # adjustedHeight = Math.max(@textarea.get(0).scrollHeight, @textarea.get(0).clientHeight)
213
- # @textarea.height(adjustedHeight) if adjustedHeight >= @textarea.get(0).clientHeight
216
+ @element.css({height: @element.get(0).scrollHeight - 100})
217
+ @element.css({height: @element.get(0).scrollHeight});
214
218
 
215
219
 
216
220
  snippets: ->
@@ -231,6 +235,9 @@ class @Mercury.Regions.Markupable extends Mercury.Region
231
235
  insertImage: (selection, options) ->
232
236
  selection.replace('![add alt text](' + encodeURI(options.value.src) + ')', true)
233
237
 
238
+ insertTable: (selection, options) ->
239
+ selection.replace(options.value.replace(/<br>|<br\/>/ig, ''), false, true)
240
+
234
241
  insertLink: (selection, options) ->
235
242
  selection.replace("[#{options.value.content}](#{options.value.attrs.href} 'optional title')", true)
236
243