mercury-rails 0.1.1 → 0.1.2
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.
- data/README.rdoc +81 -50
- data/VERSION +1 -1
- data/app/assets/javascripts/mercury/dialog.js.coffee +4 -4
- data/app/assets/javascripts/mercury/dialogs/backcolor.js.coffee +3 -3
- data/app/assets/javascripts/mercury/dialogs/forecolor.js.coffee +3 -3
- data/app/assets/javascripts/mercury/dialogs/formatblock.js.coffee +1 -1
- data/app/assets/javascripts/mercury/dialogs/objectspanel.js.coffee +3 -3
- data/app/assets/javascripts/mercury/dialogs/style.js.coffee +1 -1
- data/app/assets/javascripts/mercury/history_buffer.js.coffee +2 -2
- data/app/assets/javascripts/mercury/mercury.js.coffee +47 -54
- data/app/assets/javascripts/mercury/modal.js.coffee +13 -13
- data/app/assets/javascripts/mercury/modals/htmleditor.js.coffee +2 -2
- data/app/assets/javascripts/mercury/modals/insertcharacter.js.coffee +2 -2
- data/app/assets/javascripts/mercury/modals/insertlink.js.coffee +7 -7
- data/app/assets/javascripts/mercury/modals/insertmedia.js.coffee +5 -5
- data/app/assets/javascripts/mercury/modals/insertsnippet.js.coffee +2 -2
- data/app/assets/javascripts/mercury/modals/inserttable.js.coffee +14 -15
- data/app/assets/javascripts/mercury/native_extensions.js.coffee +2 -1
- data/app/assets/javascripts/mercury/page_editor.js.coffee +27 -27
- data/app/assets/javascripts/mercury/palette.js.coffee +6 -6
- data/app/assets/javascripts/mercury/panel.js.coffee +4 -4
- data/app/assets/javascripts/mercury/region.js.coffee +9 -9
- data/app/assets/javascripts/mercury/regions/editable.js.coffee +71 -71
- data/app/assets/javascripts/mercury/regions/markupable.js.coffee +51 -42
- data/app/assets/javascripts/mercury/regions/snippetable.js.coffee +7 -8
- data/app/assets/javascripts/mercury/select.js.coffee +8 -8
- data/app/assets/javascripts/mercury/snippet.js.coffee +6 -6
- data/app/assets/javascripts/mercury/snippet_toolbar.js.coffee +7 -7
- data/app/assets/javascripts/mercury/statusbar.js.coffee +7 -3
- data/app/assets/javascripts/mercury/table_editor.js.coffee +24 -24
- data/app/assets/javascripts/mercury/toolbar.button.js.coffee +20 -21
- data/app/assets/javascripts/mercury/toolbar.button_group.js.coffee +2 -2
- data/app/assets/javascripts/mercury/toolbar.expander.js.coffee +9 -9
- data/app/assets/javascripts/mercury/toolbar.js.coffee +12 -13
- data/app/assets/javascripts/mercury/tooltip.js.coffee +7 -7
- data/app/assets/javascripts/mercury/uploader.js.coffee +12 -13
- data/app/assets/javascripts/mercury_loader.js +98 -0
- data/app/assets/stylesheets/mercury/modal.scss +5 -5
- data/app/assets/stylesheets/mercury/toolbar.scss +62 -64
- data/app/views/layouts/mercury.html.haml +0 -4
- data/app/views/mercury/modals/character.html.haml +1 -1
- data/app/views/mercury/modals/htmleditor.html.haml +1 -1
- data/app/views/mercury/modals/table.html.haml +10 -10
- data/config/routes.rb +2 -2
- data/mercury-rails.gemspec +17 -20
- data/spec/javascripts/mercury/dialogs/backcolor_spec.js.coffee +3 -3
- data/spec/javascripts/mercury/dialogs/forecolor_spec.js.coffee +3 -3
- data/spec/javascripts/mercury/dialogs/objectspanel_spec.js.coffee +3 -3
- data/spec/javascripts/mercury/modals/htmleditor_spec.js.coffee +4 -4
- data/spec/javascripts/mercury/modals/insertcharacter_spec.js.coffee +2 -2
- data/spec/javascripts/mercury/modals/insertlink_spec.js.coffee +10 -10
- data/spec/javascripts/mercury/modals/insertmedia_spec.js.coffee +7 -7
- data/spec/javascripts/mercury/modals/insertsnippet_spec.js.coffee +4 -4
- data/spec/javascripts/mercury/modals/inserttable_spec.js.coffee +17 -17
- data/spec/javascripts/mercury/page_editor_spec.js.coffee +5 -6
- data/spec/javascripts/mercury/region_spec.js.coffee +5 -5
- data/spec/javascripts/mercury/regions/editable_spec.js.coffee +398 -0
- data/spec/javascripts/mercury/regions/snippetable_spec.js.coffee +18 -14
- data/spec/javascripts/mercury/snippet_spec.js.coffee +1 -1
- data/spec/javascripts/mercury/toolbar.button_spec.js.coffee +16 -16
- data/spec/javascripts/templates/mercury/modals/inserttable.html +11 -11
- data/spec/javascripts/templates/mercury/regions/editable.html +3 -0
- data/spec/javascripts/templates/mercury/toolbar.button.html +8 -8
- data/vendor/assets/javascripts/{jquery-ui-1.8.13.sortable.custom.js → jquery-ui-1.8.13.custom.js} +250 -0
- data/vendor/assets/javascripts/jquery.additions.js +151 -0
- data/vendor/assets/javascripts/showdown.js +1254 -1276
- metadata +26 -29
- data/app/assets/javascripts/mercury/websocket.js.coffee +0 -34
- data/spec/javascripts/mercury/regions/_editable_.js.coffee +0 -0
- data/vendor/assets/javascripts/jquery-ui-1.8.13.custom.min.js +0 -249
- data/vendor/assets/javascripts/jquery.easing.js +0 -173
- data/vendor/assets/javascripts/jquery.json2.js +0 -178
- data/vendor/assets/javascripts/jquery.serialize_object.js +0 -16
- data/vendor/assets/javascripts/jquery.ujs.js +0 -289
@@ -8,14 +8,14 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
8
8
|
|
9
9
|
build: ->
|
10
10
|
# mozilla: set some initial content so everything works correctly
|
11
|
-
@
|
11
|
+
@content(' ') if jQuery.browser.mozilla && @content() == ''
|
12
12
|
|
13
13
|
# set overflow just in case
|
14
14
|
@element.data({originalOverflow: @element.css('overflow')})
|
15
15
|
@element.css({overflow: 'auto'})
|
16
16
|
|
17
17
|
# mozilla: there's some weird behavior when the element isn't a div
|
18
|
-
@specialContainer =
|
18
|
+
@specialContainer = jQuery.browser.mozilla && @element.get(0).tagName != 'DIV'
|
19
19
|
|
20
20
|
# make it editable
|
21
21
|
# gecko: in this makes double clicking in textareas fail: https://bugzilla.mozilla.org/show_bug.cgi?id=490367
|
@@ -24,7 +24,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
24
24
|
# make all snippets not editable, and set their versions to 1
|
25
25
|
for element in @element.find('.mercury-snippet')
|
26
26
|
element.contentEditable = false
|
27
|
-
|
27
|
+
jQuery(element).attr('data-version', '1')
|
28
28
|
|
29
29
|
# add the basic editor settings to the document (only once)
|
30
30
|
unless @document.mercuryEditing
|
@@ -46,7 +46,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
46
46
|
if currentElement.length
|
47
47
|
# setup the table editor if we're inside a table
|
48
48
|
table = currentElement.closest('table', @element)
|
49
|
-
Mercury.tableEditor(table, currentElement) if table.length
|
49
|
+
Mercury.tableEditor(table, currentElement.closest('tr, td')) if table.length
|
50
50
|
# display a tooltip if we're in an anchor
|
51
51
|
anchor = currentElement.closest('a', @element)
|
52
52
|
if anchor.length && anchor.attr('href')
|
@@ -63,7 +63,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
63
63
|
return if @previewing
|
64
64
|
event.preventDefault() if event.shiftKey
|
65
65
|
event.originalEvent.dataTransfer.dropEffect = 'copy'
|
66
|
-
if
|
66
|
+
if jQuery.browser.webkit
|
67
67
|
clearTimeout(@dropTimeout)
|
68
68
|
@dropTimeout = setTimeout((=> @element.trigger('possible:drop')), 10)
|
69
69
|
|
@@ -89,7 +89,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
89
89
|
return if @previewing
|
90
90
|
if snippet = @element.find('img[data-snippet]').get(0)
|
91
91
|
@focus()
|
92
|
-
Mercury.Snippet.displayOptionsFor(
|
92
|
+
Mercury.Snippet.displayOptionsFor(jQuery(snippet).data('snippet'))
|
93
93
|
@document.execCommand('undo', false, null)
|
94
94
|
|
95
95
|
# custom paste handling: we have to do some hackery to get the pasted content since it's not exposed normally
|
@@ -100,9 +100,9 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
100
100
|
return if @previewing
|
101
101
|
return unless Mercury.region == @
|
102
102
|
Mercury.changes = true
|
103
|
-
|
103
|
+
content = @content()
|
104
104
|
event.preventDefault() if @specialContainer
|
105
|
-
setTimeout((=> @handlePaste(
|
105
|
+
setTimeout((=> @handlePaste(content)), 1)
|
106
106
|
|
107
107
|
@element.focus =>
|
108
108
|
return if @previewing
|
@@ -116,14 +116,14 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
116
116
|
Mercury.tooltip.hide()
|
117
117
|
|
118
118
|
@element.click (event) =>
|
119
|
-
|
119
|
+
jQuery(event.target).closest('a').attr('target', '_top') if @previewing
|
120
120
|
|
121
121
|
@element.dblclick (event) =>
|
122
122
|
return if @previewing
|
123
|
-
image =
|
123
|
+
image = jQuery(event.target).closest('img', @element)
|
124
124
|
if image.length
|
125
125
|
@selection().selectNode(image.get(0), true)
|
126
|
-
Mercury.trigger('button', {action: '
|
126
|
+
Mercury.trigger('button', {action: 'insertMedia'})
|
127
127
|
|
128
128
|
@element.mouseup =>
|
129
129
|
return if @previewing
|
@@ -134,7 +134,6 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
134
134
|
return if @previewing
|
135
135
|
Mercury.changes = true
|
136
136
|
switch event.keyCode
|
137
|
-
|
138
137
|
when 90 # undo / redo
|
139
138
|
return unless event.metaKey
|
140
139
|
event.preventDefault()
|
@@ -142,9 +141,9 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
142
141
|
return
|
143
142
|
|
144
143
|
when 13 # enter
|
145
|
-
if
|
144
|
+
if jQuery.browser.webkit && @selection().commonAncestor().closest('li, ul', @element).length == 0
|
146
145
|
event.preventDefault()
|
147
|
-
@document.execCommand('
|
146
|
+
@document.execCommand('insertLineBreak', false, null)
|
148
147
|
else if @specialContainer
|
149
148
|
# mozilla: pressing enter in any elemeny besides a div handles strangely
|
150
149
|
event.preventDefault()
|
@@ -164,7 +163,6 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
164
163
|
|
165
164
|
if event.metaKey
|
166
165
|
switch event.keyCode
|
167
|
-
|
168
166
|
when 66 # b
|
169
167
|
@execCommand('bold')
|
170
168
|
event.preventDefault()
|
@@ -190,16 +188,16 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
190
188
|
Mercury.trigger('region:update', {region: @})
|
191
189
|
|
192
190
|
|
193
|
-
|
191
|
+
content: (value = null, filterSnippets = true, includeMarker = false) ->
|
194
192
|
if value != null
|
195
193
|
# sanitize the html before we insert it
|
196
|
-
container =
|
194
|
+
container = jQuery('<div>').appendTo(@document.createDocumentFragment())
|
197
195
|
container.html(value)
|
198
196
|
|
199
197
|
# fill in the snippet contents
|
200
198
|
for element in container.find('[data-snippet]')
|
201
199
|
element.contentEditable = false
|
202
|
-
element =
|
200
|
+
element = jQuery(element)
|
203
201
|
if snippet = Mercury.Snippet.find(element.data('snippet'))
|
204
202
|
unless element.data('version')
|
205
203
|
try
|
@@ -225,24 +223,24 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
225
223
|
selection.placeMarker()
|
226
224
|
|
227
225
|
# sanitize the html before we return it
|
228
|
-
container =
|
226
|
+
container = jQuery('<div>').appendTo(@document.createDocumentFragment())
|
229
227
|
container.html(@element.html().replace(/^\s+|\s+$/g, ''))
|
230
228
|
|
231
229
|
# replace snippet contents to be an identifier
|
232
230
|
if filterSnippets then for element, index in container.find('[data-snippet]')
|
233
|
-
element =
|
231
|
+
element = jQuery(element)
|
234
232
|
if snippet = Mercury.Snippet.find(element.data("snippet"))
|
235
233
|
snippet.data = element.html()
|
236
234
|
element.html("[#{element.data("snippet")}/#{element.data("version")}]")
|
237
235
|
element.attr({contenteditable: null, 'data-version': null})
|
238
236
|
|
239
237
|
# get the html before removing the markers
|
240
|
-
|
238
|
+
content = container.html()
|
241
239
|
|
242
240
|
# remove the markers from the dom
|
243
241
|
selection.removeMarker() if includeMarker
|
244
242
|
|
245
|
-
return
|
243
|
+
return content
|
246
244
|
|
247
245
|
|
248
246
|
togglePreview: ->
|
@@ -250,7 +248,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
250
248
|
@element.get(0).contentEditable = true
|
251
249
|
@element.css({overflow: 'auto'})
|
252
250
|
else
|
253
|
-
@
|
251
|
+
@content(@content())
|
254
252
|
@element.get(0).contentEditable = false
|
255
253
|
@element.css({overflow: @element.data('originalOverflow')})
|
256
254
|
@element.blur()
|
@@ -265,7 +263,7 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
265
263
|
handler.call(@, @selection(), options)
|
266
264
|
else
|
267
265
|
sibling = @element.get(0).previousSibling if action == 'indent'
|
268
|
-
options.value =
|
266
|
+
options.value = jQuery('<div>').html(options.value).html() if action == 'insertHTML' && options.value && options.value.get
|
269
267
|
try
|
270
268
|
@document.execCommand(action, false, options.value)
|
271
269
|
catch error
|
@@ -285,13 +283,13 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
285
283
|
|
286
284
|
# if the key code was return, delete, or backspace store now -- unless it was the same as last time
|
287
285
|
if knownKeyCode >= 0 && knownKeyCode != @lastKnownKeyCode # || !keyCode
|
288
|
-
@history.push(@
|
286
|
+
@history.push(@content(null, false, true))
|
289
287
|
else if keyCode
|
290
288
|
# set a timeout for pushing to the history
|
291
|
-
@historyTimeout = setTimeout((=> @history.push(@
|
289
|
+
@historyTimeout = setTimeout((=> @history.push(@content(null, false, true))), waitTime * 1000)
|
292
290
|
else
|
293
291
|
# push to the history immediately
|
294
|
-
@history.push(@
|
292
|
+
@history.push(@content(null, false, true))
|
295
293
|
|
296
294
|
@lastKnownKeyCode = knownKeyCode
|
297
295
|
|
@@ -315,33 +313,33 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
315
313
|
return element
|
316
314
|
|
317
315
|
|
318
|
-
handlePaste: (
|
319
|
-
|
316
|
+
handlePaste: (prePasteContent) ->
|
317
|
+
prePasteContent = prePasteContent.replace(/^\<br\>/, '')
|
320
318
|
|
321
319
|
# remove any regions that might have been pasted
|
322
320
|
@element.find('.mercury-region').remove()
|
323
321
|
|
324
322
|
# handle pasting from ms office etc
|
325
|
-
|
326
|
-
if
|
323
|
+
content = @content()
|
324
|
+
if content.indexOf('<!--StartFragment-->') > -1 || content.indexOf('="mso-') > -1 || content.indexOf('<o:') > -1 || content.indexOf('="Mso') > -1
|
327
325
|
# clean out all the tags from the pasted contents
|
328
|
-
cleaned =
|
326
|
+
cleaned = prePasteContent.singleDiff(@content()).sanitizeHTML()
|
329
327
|
try
|
330
328
|
# try to undo and put the cleaned html where the selection was
|
331
329
|
@document.execCommand('undo', false, null)
|
332
330
|
@execCommand('insertHTML', {value: cleaned})
|
333
331
|
catch error
|
334
332
|
# remove the pasted html and load up the cleaned contents into a modal
|
335
|
-
@
|
333
|
+
@content(prePasteContent)
|
336
334
|
Mercury.modal '/mercury/modals/sanitizer', {
|
337
335
|
title: 'HTML Sanitizer (Starring Clippy)',
|
338
336
|
afterLoad: -> @element.find('textarea').val(cleaned.replace(/<br\/>/g, '\n'))
|
339
337
|
}
|
340
338
|
else if Mercury.config.cleanStylesOnPaste
|
341
339
|
# strip styles
|
342
|
-
pasted =
|
340
|
+
pasted = prePasteContent.singleDiff(@content())
|
343
341
|
|
344
|
-
container =
|
342
|
+
container = jQuery('<div>').appendTo(@document.createDocumentFragment()).html(pasted)
|
345
343
|
container.find('[style]').attr({style: null})
|
346
344
|
|
347
345
|
@document.execCommand('undo', false, null)
|
@@ -350,64 +348,64 @@ class @Mercury.Regions.Editable extends Mercury.Region
|
|
350
348
|
|
351
349
|
# Custom actions (eg. things that execCommand doesn't do, or doesn't do well)
|
352
350
|
@actions: {
|
353
|
-
|
351
|
+
insertRowBefore: -> Mercury.tableEditor.addRow('before')
|
354
352
|
|
355
|
-
|
353
|
+
insertRowAfter: -> Mercury.tableEditor.addRow('after')
|
356
354
|
|
357
|
-
|
355
|
+
insertColumnBefore: -> Mercury.tableEditor.addColumn('before')
|
358
356
|
|
359
|
-
|
357
|
+
insertColumnAfter: -> Mercury.tableEditor.addColumn('after')
|
360
358
|
|
361
|
-
|
359
|
+
deleteColumn: -> Mercury.tableEditor.removeColumn()
|
362
360
|
|
363
|
-
|
361
|
+
deleteRow: -> Mercury.tableEditor.removeRow()
|
364
362
|
|
365
|
-
|
363
|
+
increaseColspan: -> Mercury.tableEditor.increaseColspan()
|
366
364
|
|
367
|
-
|
365
|
+
decreaseColspan: -> Mercury.tableEditor.decreaseColspan()
|
368
366
|
|
369
|
-
|
367
|
+
increaseRowspan: -> Mercury.tableEditor.increaseRowspan()
|
370
368
|
|
371
|
-
|
369
|
+
decreaseRowspan: -> Mercury.tableEditor.decreaseRowspan()
|
372
370
|
|
373
|
-
undo: -> @
|
371
|
+
undo: -> @content(@history.undo())
|
374
372
|
|
375
|
-
redo: -> @
|
373
|
+
redo: -> @content(@history.redo())
|
376
374
|
|
377
|
-
|
375
|
+
removeFormatting: (selection) -> selection.insertTextNode(selection.textContent())
|
378
376
|
|
379
|
-
|
377
|
+
backColor: (selection, options) -> selection.wrap("<span style=\"background-color:#{options.value.toHex()}\">", true)
|
380
378
|
|
381
379
|
overline: (selection) -> selection.wrap('<span style="text-decoration:overline">', true)
|
382
380
|
|
383
381
|
style: (selection, options) -> selection.wrap("<span class=\"#{options.value}\">", true)
|
384
382
|
|
385
|
-
replaceHTML: (selection, options) -> @
|
383
|
+
replaceHTML: (selection, options) -> @content(options.value)
|
386
384
|
|
387
|
-
insertImage: (selection, options) -> @execCommand('insertHTML', {value:
|
385
|
+
insertImage: (selection, options) -> @execCommand('insertHTML', {value: jQuery('<img/>', options.value)})
|
388
386
|
|
389
387
|
insertLink: (selection, options) ->
|
390
|
-
anchor =
|
388
|
+
anchor = jQuery("<#{options.value.tagName}>").attr(options.value.attrs).html(options.value.content)
|
391
389
|
selection.insertNode(anchor)
|
392
390
|
|
393
391
|
replaceLink: (selection, options) ->
|
394
|
-
anchor =
|
392
|
+
anchor = jQuery("<#{options.value.tagName}>").attr(options.value.attrs).html(options.value.content)
|
395
393
|
selection.selectNode(options.node)
|
396
|
-
html =
|
397
|
-
selection.replace(
|
394
|
+
html = jQuery('<div>').html(selection.content()).find('a').html()
|
395
|
+
selection.replace(jQuery(anchor, selection.context).html(html))
|
398
396
|
|
399
|
-
|
397
|
+
insertSnippet: (selection, options) ->
|
400
398
|
snippet = options.value
|
401
399
|
if (existing = @element.find("[data-snippet=#{snippet.identity}]")).length
|
402
400
|
selection.selectNode(existing.get(0))
|
403
401
|
selection.insertNode(snippet.getHTML(@document))
|
404
402
|
|
405
|
-
|
403
|
+
editSnippet: ->
|
406
404
|
return unless @snippet
|
407
405
|
snippet = Mercury.Snippet.find(@snippet.data('snippet'))
|
408
406
|
snippet.displayOptions()
|
409
407
|
|
410
|
-
|
408
|
+
removeSnippet: ->
|
411
409
|
@snippet.remove() if @snippet
|
412
410
|
Mercury.trigger('hide:toolbar', {type: 'snippet', immediately: true})
|
413
411
|
}
|
@@ -427,11 +425,11 @@ class Mercury.Regions.Editable.Selection
|
|
427
425
|
return null unless @range
|
428
426
|
ancestor = @range.commonAncestorContainer
|
429
427
|
ancestor = ancestor.parentNode if ancestor.nodeType == 3 && onlyTag
|
430
|
-
return
|
428
|
+
return jQuery(ancestor)
|
431
429
|
|
432
430
|
|
433
431
|
wrap: (element, replace = false) ->
|
434
|
-
element =
|
432
|
+
element = jQuery(element, @context).html(@fragment)
|
435
433
|
@replace(element) if replace
|
436
434
|
return element
|
437
435
|
|
@@ -446,24 +444,26 @@ class Mercury.Regions.Editable.Selection
|
|
446
444
|
|
447
445
|
is: (elementType) ->
|
448
446
|
content = @content()
|
449
|
-
return
|
447
|
+
return jQuery(content.firstChild) if content.childNodes.length == 1 && jQuery(content.firstChild).is(elementType)
|
450
448
|
return false
|
451
449
|
|
452
450
|
|
453
451
|
forceSelection: (element) ->
|
454
|
-
return unless
|
452
|
+
return unless jQuery.browser.webkit
|
455
453
|
range = @context.createRange()
|
456
454
|
|
455
|
+
# todo: the \00 thing breaks when using uglifier, and is escapped to "0".. it's been fixed, but isn't available yet
|
456
|
+
# https://github.com/lautis/uglifier/issues/11
|
457
457
|
if @range
|
458
458
|
if @commonAncestor(true).closest('.mercury-snippet').length
|
459
|
-
lastChild = @context.createTextNode('
|
459
|
+
lastChild = @context.createTextNode(' ') #\00
|
460
460
|
element.appendChild(lastChild)
|
461
461
|
else
|
462
462
|
if element.lastChild && element.lastChild.nodeType == 3 && element.lastChild.textContent.replace(/^[\s+|\n+]|[\s+|\n+]$/, '') == ''
|
463
463
|
lastChild = element.lastChild
|
464
|
-
element.lastChild.textContent = '
|
464
|
+
element.lastChild.textContent = ' ' #\00
|
465
465
|
else
|
466
|
-
lastChild = @context.createTextNode('
|
466
|
+
lastChild = @context.createTextNode(' ') #\00
|
467
467
|
element.appendChild(lastChild)
|
468
468
|
|
469
469
|
if lastChild
|
@@ -489,8 +489,8 @@ class Mercury.Regions.Editable.Selection
|
|
489
489
|
placeMarker: ->
|
490
490
|
return unless @range
|
491
491
|
|
492
|
-
@startMarker =
|
493
|
-
@endMarker =
|
492
|
+
@startMarker = jQuery('<em class="mercury-marker"/>', @context).get(0)
|
493
|
+
@endMarker = jQuery('<em class="mercury-marker"/>', @context).get(0)
|
494
494
|
|
495
495
|
# put a single marker (the end)
|
496
496
|
rangeEnd = @range.cloneRange()
|
@@ -508,8 +508,8 @@ class Mercury.Regions.Editable.Selection
|
|
508
508
|
|
509
509
|
|
510
510
|
removeMarker: ->
|
511
|
-
|
512
|
-
|
511
|
+
jQuery(@startMarker).remove()
|
512
|
+
jQuery(@endMarker).remove()
|
513
513
|
|
514
514
|
|
515
515
|
insertTextNode: (string) ->
|
@@ -522,7 +522,7 @@ class Mercury.Regions.Editable.Selection
|
|
522
522
|
|
523
523
|
insertNode: (element) ->
|
524
524
|
element = element.get(0) if element.get
|
525
|
-
element =
|
525
|
+
element = jQuery(element, @context).get(0) if jQuery.type(element) == 'string'
|
526
526
|
|
527
527
|
@range.deleteContents()
|
528
528
|
@range.insertNode(element)
|
@@ -538,7 +538,7 @@ class Mercury.Regions.Editable.Selection
|
|
538
538
|
|
539
539
|
replace: (element) ->
|
540
540
|
element = element.get(0) if element.get
|
541
|
-
element =
|
541
|
+
element = jQuery(element, @context).get(0) if jQuery.type(element) == 'string'
|
542
542
|
|
543
543
|
@range.deleteContents()
|
544
544
|
@range.insertNode(element)
|
@@ -18,16 +18,19 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
18
18
|
height = @element.height()
|
19
19
|
|
20
20
|
value = @element.html().replace(/^\s+|\s+$/g, '')
|
21
|
-
@textarea =
|
21
|
+
@textarea = jQuery('<textarea>', @document).val(value)
|
22
22
|
@textarea.attr('class', @element.attr('class')).addClass('mercury-textarea')
|
23
23
|
@textarea.css({border: 0, background: 'transparent', display: 'block', width: width, height: height, fontFamily: '"Courier New", Courier, monospace', fontSize: '14px'})
|
24
24
|
@element.after(@textarea)
|
25
25
|
@element.hide()
|
26
26
|
@resize()
|
27
27
|
|
28
|
+
@previewElement = @element
|
29
|
+
@element = @textarea
|
30
|
+
|
28
31
|
|
29
32
|
focus: ->
|
30
|
-
@
|
33
|
+
@element.focus()
|
31
34
|
|
32
35
|
|
33
36
|
bindEvents: ->
|
@@ -44,17 +47,24 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
44
47
|
return unless Mercury.region == @
|
45
48
|
@execCommand(options.action, options) if options.action
|
46
49
|
|
47
|
-
|
50
|
+
Mercury.bind 'unfocus:regions', (event) =>
|
51
|
+
return if @previewing
|
52
|
+
if Mercury.region == @
|
53
|
+
@element.blur()
|
54
|
+
@element.removeClass('focus')
|
55
|
+
Mercury.trigger('region:blurred', {region: @})
|
56
|
+
|
57
|
+
@element.bind 'dragenter', (event) =>
|
48
58
|
return if @previewing
|
49
59
|
event.preventDefault()
|
50
60
|
event.originalEvent.dataTransfer.dropEffect = 'copy'
|
51
61
|
|
52
|
-
@
|
62
|
+
@element.bind 'dragover', (event) =>
|
53
63
|
return if @previewing
|
54
64
|
event.preventDefault()
|
55
65
|
event.originalEvent.dataTransfer.dropEffect = 'copy'
|
56
66
|
|
57
|
-
@
|
67
|
+
@element.bind 'drop', (event) =>
|
58
68
|
return if @previewing
|
59
69
|
|
60
70
|
# handle dropping snippets
|
@@ -69,26 +79,20 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
69
79
|
@focus()
|
70
80
|
Mercury.uploader(event.originalEvent.dataTransfer.files[0])
|
71
81
|
|
72
|
-
@
|
82
|
+
@element.focus =>
|
73
83
|
return if @previewing
|
74
84
|
Mercury.region = @
|
75
|
-
@
|
85
|
+
@element.addClass('focus')
|
76
86
|
Mercury.trigger('region:focused', {region: @})
|
77
87
|
|
78
|
-
@
|
79
|
-
return if @previewing
|
80
|
-
@textarea.removeClass('focus')
|
81
|
-
Mercury.trigger('region:blurred', {region: @})
|
82
|
-
|
83
|
-
@textarea.keydown (event) =>
|
88
|
+
@element.keydown (event) =>
|
84
89
|
return if @previewing
|
85
90
|
Mercury.changes = true
|
86
91
|
@resize()
|
87
92
|
switch event.keyCode
|
88
|
-
|
89
93
|
when 13 # enter or return
|
90
94
|
selection = @selection()
|
91
|
-
text = @
|
95
|
+
text = @element.val()
|
92
96
|
start = text.lastIndexOf('\n', selection.start)
|
93
97
|
end = text.indexOf('\n', selection.end)
|
94
98
|
end = text.length if end < start
|
@@ -98,9 +102,7 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
98
102
|
event.preventDefault()
|
99
103
|
if /\d/.test(text[start + 1])
|
100
104
|
lineText = text.substring(start, end)
|
101
|
-
console.debug(lineText)
|
102
105
|
if /(\d+)\./.test(lineText)
|
103
|
-
console.debug(2)
|
104
106
|
number = parseInt(RegExp.$1)
|
105
107
|
selection.replace("\n#{number += 1}. ", false, true)
|
106
108
|
event.preventDefault()
|
@@ -113,7 +115,6 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
113
115
|
|
114
116
|
if event.metaKey
|
115
117
|
switch event.keyCode
|
116
|
-
|
117
118
|
when 66 # b
|
118
119
|
@execCommand('bold')
|
119
120
|
event.preventDefault()
|
@@ -128,34 +129,41 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
128
129
|
|
129
130
|
@pushHistory(event.keyCode)
|
130
131
|
|
131
|
-
@
|
132
|
+
@element.keyup =>
|
132
133
|
return if @previewing
|
133
134
|
Mercury.trigger('region:update', {region: @})
|
134
135
|
|
135
|
-
@element.
|
136
|
+
@element.mouseup =>
|
137
|
+
return if @previewing
|
138
|
+
@focus()
|
139
|
+
Mercury.trigger('region:focused', {region: @})
|
140
|
+
|
141
|
+
@previewElement.click (event) =>
|
136
142
|
$(event.target).closest('a').attr('target', '_top') if @previewing
|
137
143
|
|
138
144
|
|
139
|
-
|
145
|
+
content: (value = null, filterSnippets = true) ->
|
140
146
|
if value != null
|
141
147
|
if $.type(value) == 'string'
|
142
|
-
@
|
148
|
+
@element.val(value)
|
149
|
+
if jQuery.type(value) == 'string'
|
150
|
+
@element.val(value)
|
143
151
|
else
|
144
|
-
@
|
152
|
+
@element.val(value.html)
|
145
153
|
@selection().select(value.selection.start, value.selection.end)
|
146
154
|
else
|
147
|
-
return @
|
155
|
+
return @element.val()
|
148
156
|
|
149
157
|
|
150
158
|
togglePreview: ->
|
151
159
|
if @previewing
|
152
|
-
@
|
153
|
-
@textarea.show()
|
154
|
-
else
|
155
|
-
value = @converter.makeHtml(@textarea.val())
|
156
|
-
@element.html(value)
|
160
|
+
@previewElement.hide()
|
157
161
|
@element.show()
|
158
|
-
|
162
|
+
else
|
163
|
+
value = @converter.makeHtml(@element.val())
|
164
|
+
@previewElement.html(value)
|
165
|
+
@previewElement.show()
|
166
|
+
@element.hide()
|
159
167
|
super
|
160
168
|
|
161
169
|
|
@@ -167,7 +175,7 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
167
175
|
|
168
176
|
|
169
177
|
htmlAndSelection: ->
|
170
|
-
return {html: @
|
178
|
+
return {html: @content(null, false), selection: @selection().serialize()}
|
171
179
|
|
172
180
|
|
173
181
|
pushHistory: (keyCode) ->
|
@@ -194,12 +202,13 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
194
202
|
|
195
203
|
|
196
204
|
selection: ->
|
197
|
-
return new Mercury.Regions.Markupable.Selection(@
|
205
|
+
return new Mercury.Regions.Markupable.Selection(@element)
|
198
206
|
|
199
207
|
|
200
208
|
resize: ->
|
201
|
-
#
|
202
|
-
#
|
209
|
+
# todo: get this working if possible, and it seems to be useful
|
210
|
+
# adjustedHeight = Math.max(@textarea.get(0).scrollHeight, @textarea.get(0).clientHeight)
|
211
|
+
# @textarea.height(adjustedHeight) if adjustedHeight >= @textarea.get(0).clientHeight
|
203
212
|
|
204
213
|
|
205
214
|
snippets: ->
|
@@ -208,13 +217,13 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
208
217
|
# Actions
|
209
218
|
@actions: {
|
210
219
|
|
211
|
-
undo: -> @
|
220
|
+
undo: -> @content(@history.undo())
|
212
221
|
|
213
|
-
redo: -> @
|
222
|
+
redo: -> @content(@history.redo())
|
214
223
|
|
215
224
|
insertHTML: (selection, options) ->
|
216
225
|
if options.value.get && element = options.value.get(0)
|
217
|
-
options.value =
|
226
|
+
options.value = jQuery('<div>').html(element).html()
|
218
227
|
selection.replace(options.value, false, true)
|
219
228
|
|
220
229
|
insertImage: (selection, options) ->
|
@@ -223,9 +232,9 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
223
232
|
insertLink: (selection, options) ->
|
224
233
|
selection.replace("[#{options.value.content}](#{options.value.attrs.href} 'optional title')", true)
|
225
234
|
|
226
|
-
|
235
|
+
insertUnorderedList: (selection) -> selection.addList('unordered')
|
227
236
|
|
228
|
-
|
237
|
+
insertOrderedList: (selection) -> selection.addList('ordered')
|
229
238
|
|
230
239
|
style: (selection, options) -> selection.wrap("<span class=\"#{options.value}\">", '</span>')
|
231
240
|
|
@@ -261,9 +270,9 @@ class @Mercury.Regions.Markupable extends Mercury.Region
|
|
261
270
|
outdent: (selection) ->
|
262
271
|
selection.unWrapLine('> ', '', false, true)
|
263
272
|
|
264
|
-
|
273
|
+
horizontalRule: (selection) -> selection.replace('\n- - -\n')
|
265
274
|
|
266
|
-
|
275
|
+
insertSnippet: (selection, options) ->
|
267
276
|
snippet = options.value
|
268
277
|
selection.replace(snippet.getText())
|
269
278
|
|
@@ -377,4 +386,4 @@ class Mercury.Regions.Markupable.Selection
|
|
377
386
|
|
378
387
|
|
379
388
|
textContent: ->
|
380
|
-
return @text
|
389
|
+
return @text
|