dante-editor 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/dante.js +1 -0
- data/app/assets/javascripts/dante/behaviors/image.js.coffee +235 -3
- data/app/assets/javascripts/dante/behaviors/paste.js.coffee +64 -0
- data/app/assets/javascripts/dante/editor.js.coffee +44 -191
- data/app/assets/javascripts/dante/popover.js.coffee +1 -1
- data/app/assets/javascripts/dante/tooltip_widgets/uploader.js.coffee +7 -2
- data/bower.json +1 -1
- data/dist/js/dante-editor.js +357 -199
- data/lib/dante-editor/version.rb +1 -1
- data/source/partials/_readme.markdown +15 -10
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b896bd119ce66604964b20e7e45e6d7547e26022
|
4
|
+
data.tar.gz: 4675935e48ee846eccbf5ba67f5c961d9343635b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 011a522973ef58cc5e486d70779f52dc876b65c3cb64478634e8b6fc6584a424dcab24b9c274390af0390e7f8c72cd72a3a99b9466c1eb5825b3c3653ad7918f
|
7
|
+
data.tar.gz: d994b05d927cb2059506b0d251252dc9dcf90b7413f6e677b1714697af3fecf8310ae9575403ae7e879ae120c2c9b4c0c42efdb5d8a8645a302e5a3501ef03b4
|
data/README.md
CHANGED
@@ -94,7 +94,7 @@ Until now I´ve been able to implement the following features:
|
|
94
94
|
#### Uploader:
|
95
95
|
+ **upload_url:** default: /uploads.json
|
96
96
|
+ **upload_callback** default: empty, allows optional way to handle the server response when image is uploaded This is useful when you don't have control on the backend response.
|
97
|
-
|
97
|
+
+ **image_delete_callback**: default: none, returns the image data before deletion. use this if you want to destroy image from the server.
|
98
98
|
#### Embed tool:
|
99
99
|
+ **oembed_url:** default: http://api.embed.ly/1/oembed?url="
|
100
100
|
+ **extract_url:** default: http://api.embed.ly/1/extract?url="
|
@@ -2,6 +2,16 @@ utils = Dante.utils
|
|
2
2
|
|
3
3
|
class Dante.View.Behavior.Image extends Dante.View.Behavior
|
4
4
|
|
5
|
+
# TODO. dry up this!, call constants from @editor
|
6
|
+
BACKSPACE = 8
|
7
|
+
TAB = 9
|
8
|
+
ENTER = 13
|
9
|
+
SPACEBAR = 32
|
10
|
+
LEFTARROW = 37
|
11
|
+
UPARROW = 38
|
12
|
+
RIGHTARROW = 39
|
13
|
+
DOWNARROW = 40
|
14
|
+
|
5
15
|
events:
|
6
16
|
"click .graf--figure .aspectRatioPlaceholder" : "handleGrafFigureSelectImg"
|
7
17
|
"click .graf--figure figcaption" : "handleGrafFigureSelectCaption"
|
@@ -27,17 +37,24 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
27
37
|
target = $(ev.currentTarget)
|
28
38
|
@editor.pop_over_align.positionPopOver(target)
|
29
39
|
|
40
|
+
placeHolderDiv: (target)->
|
41
|
+
target.find(".aspectRatioPlaceholder")
|
42
|
+
|
30
43
|
handleGrafFigureSelectCaption: (ev)->
|
31
44
|
utils.log "FIGCAPTION"
|
32
45
|
element = ev.currentTarget
|
33
46
|
$(element).parent(".graf--figure").removeClass("is-mediaFocused")
|
47
|
+
@editor.pop_over_align.hide()
|
34
48
|
|
35
49
|
handleGrafCaptionTyping: (ev)->
|
50
|
+
@editor.pop_over_align.hide()
|
51
|
+
|
52
|
+
node = $(@editor.getNode())
|
53
|
+
|
36
54
|
if _.isEmpty(utils.getNode().textContent.trim())
|
37
|
-
$(
|
55
|
+
$(node).addClass("is-defaultValue")
|
38
56
|
else
|
39
|
-
$(
|
40
|
-
|
57
|
+
$(node).removeClass("is-defaultValue")
|
41
58
|
|
42
59
|
#TODO: this is from embed! move this to embed behavior
|
43
60
|
handleGrafFigureSelectIframe: (ev)->
|
@@ -54,3 +71,218 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
54
71
|
@iframeSelected = null
|
55
72
|
$(element).removeClass("is-selected is-mediaFocused")
|
56
73
|
|
74
|
+
handleKeyDown: (e, parent)->
|
75
|
+
|
76
|
+
if _.contains([UPARROW, DOWNARROW], e.which)
|
77
|
+
utils.log e.which
|
78
|
+
@handleArrowForKeyDown(e)
|
79
|
+
|
80
|
+
if (e.which is BACKSPACE)
|
81
|
+
|
82
|
+
# without selection but with target active
|
83
|
+
if $(e.target).hasClass("graf--figure")
|
84
|
+
e.preventDefault()
|
85
|
+
|
86
|
+
# call callback for image delete
|
87
|
+
if @editor.image_delete_callback
|
88
|
+
@editor.image_delete_callback( $(".is-selected").find("img").data() )
|
89
|
+
|
90
|
+
utils.log("Replacing selected node")
|
91
|
+
@editor.replaceWith("p", $(".is-selected"))
|
92
|
+
@editor.setRangeAt($(".is-selected")[0])
|
93
|
+
@editor.pop_over_align.hide()
|
94
|
+
utils.log("Focus on the previous graf")
|
95
|
+
@editor.continue = false
|
96
|
+
return false
|
97
|
+
|
98
|
+
#select an image if backspacing into it from a paragraph
|
99
|
+
if(parent.hasClass("graf--p") && @editor.isFirstChar() )
|
100
|
+
if(parent.prev().hasClass("graf--figure") && @editor.getSelectedText().length == 0)
|
101
|
+
e.preventDefault()
|
102
|
+
parent.prev().find("img").click()
|
103
|
+
@editor.pop_over_align.positionPopOver(parent.prev())
|
104
|
+
utils.log("Focus on the previous image")
|
105
|
+
@editor.continue = false
|
106
|
+
return false
|
107
|
+
|
108
|
+
# supress del into & delete embed if empty content found on delete key
|
109
|
+
if parent.hasClass("graf--mixtapeEmbed") or parent.hasClass("graf--iframe")
|
110
|
+
if _.isEmpty parent.text().trim() or @isFirstChar()
|
111
|
+
utils.log("Check for inmediate deletion on empty embed text")
|
112
|
+
@editor.inmediateDeletion = @editor.isSelectingAll(anchor_node)
|
113
|
+
@editor.handleInmediateDeletion(parent) if @editor.inmediateDeletion
|
114
|
+
e.preventDefault()
|
115
|
+
@editor.continue = false
|
116
|
+
return false
|
117
|
+
|
118
|
+
# TODO: supress del when the prev el is embed and current_node is at first char
|
119
|
+
if parent.prev().hasClass("graf--mixtapeEmbed")
|
120
|
+
if @editor.isFirstChar() && !_.isEmpty( parent.text().trim() )
|
121
|
+
@editor.continue = false
|
122
|
+
return false
|
123
|
+
|
124
|
+
# when user types over a selected image (graf--figure)
|
125
|
+
# unselect image , and set range on caption
|
126
|
+
if _.isUndefined(parent) or parent.length is 0 && $(".is-selected").hasClass("is-mediaFocused")
|
127
|
+
# will remove default value on typing
|
128
|
+
node = $(".is-selected").find("figcaption")
|
129
|
+
node.find(".defaultValue").remove()
|
130
|
+
|
131
|
+
@editor.setRangeAt node[0]
|
132
|
+
$(".is-selected").removeClass("is-mediaFocused")
|
133
|
+
@editor.pop_over_align.hide()
|
134
|
+
#@editor.continue = false
|
135
|
+
return false
|
136
|
+
|
137
|
+
# handleKeyUp: (e, parent)->
|
138
|
+
|
139
|
+
#handle arrow direction from keyDown.
|
140
|
+
handleArrowForKeyDown: (ev)=>
|
141
|
+
caret_node = @editor.getNode()
|
142
|
+
current_node = $(caret_node)
|
143
|
+
utils.log(ev)
|
144
|
+
ev_type = ev.originalEvent.key || ev.originalEvent.keyIdentifier
|
145
|
+
|
146
|
+
utils.log("ENTER ARROW for key #{ev_type}")
|
147
|
+
|
148
|
+
|
149
|
+
#handle keys for image figure
|
150
|
+
|
151
|
+
switch ev_type
|
152
|
+
|
153
|
+
when "ArrowDown", "Down"
|
154
|
+
# when graff-image selected but none selection is found
|
155
|
+
if _.isUndefined(current_node) or !current_node.exists()
|
156
|
+
if $(".is-selected").exists()
|
157
|
+
current_node = $(".is-selected")
|
158
|
+
|
159
|
+
next_node = current_node.next()
|
160
|
+
|
161
|
+
utils.log "NEXT NODE IS #{next_node.attr('class')}"
|
162
|
+
utils.log "CURRENT NODE IS #{current_node.attr('class')}"
|
163
|
+
|
164
|
+
return unless $(current_node).hasClass("graf")
|
165
|
+
return unless current_node.hasClass("graf--figure") or $(current_node).editableCaretOnLastLine()
|
166
|
+
|
167
|
+
utils.log "ENTER ARROW PASSED RETURNS"
|
168
|
+
|
169
|
+
#if next element is embed select & focus it
|
170
|
+
if next_node.hasClass("graf--figure") && caret_node
|
171
|
+
n = next_node.find(".imageCaption")
|
172
|
+
@editor.scrollTo(n)
|
173
|
+
utils.log "1 down"
|
174
|
+
utils.log n[0]
|
175
|
+
@editor.skip_keyup = true
|
176
|
+
@editor.selection().removeAllRanges()
|
177
|
+
@editor.markAsSelected(next_node)
|
178
|
+
next_node.addClass("is-mediaFocused is-selected")
|
179
|
+
|
180
|
+
#@editor.setRangeAt $(".is-selected").find("figcaption")[0]
|
181
|
+
@editor.pop_over_align.positionPopOver(@placeHolderDiv(next_node))
|
182
|
+
@editor.continue = false
|
183
|
+
|
184
|
+
return false
|
185
|
+
|
186
|
+
else if next_node.prev().hasClass("graf--figure")
|
187
|
+
@editor.pop_over_align.hide()
|
188
|
+
|
189
|
+
#if current node is embed
|
190
|
+
else if next_node.hasClass("graf--mixtapeEmbed")
|
191
|
+
n = current_node.next(".graf--mixtapeEmbed")
|
192
|
+
num = n[0].childNodes.length
|
193
|
+
@editor.setRangeAt n[0], num
|
194
|
+
#@editor.scrollTo(n)
|
195
|
+
utils.log "2 down"
|
196
|
+
@editor.continue = false
|
197
|
+
return false
|
198
|
+
|
199
|
+
if current_node.hasClass("graf--figure") && next_node.hasClass("graf")
|
200
|
+
@editor.scrollTo(next_node)
|
201
|
+
utils.log "3 down, from figure to next graf"
|
202
|
+
@editor.skip_keyup = true
|
203
|
+
@editor.markAsSelected(next_node)
|
204
|
+
@editor.setRangeAt next_node[0]
|
205
|
+
@editor.continue = false
|
206
|
+
|
207
|
+
return false
|
208
|
+
|
209
|
+
when "ArrowUp", "Up"
|
210
|
+
prev_node = current_node.prev()
|
211
|
+
utils.log "PREV NODE IS #{prev_node.attr('class')} #{prev_node.attr('name')}"
|
212
|
+
utils.log "CURRENT NODE IS up #{current_node.attr('class')}"
|
213
|
+
|
214
|
+
# will handle up when figure is selected
|
215
|
+
if prev_node.length is 0 && $(ev.target).hasClass("graf--figure")
|
216
|
+
n = $(ev.target).prev(".graf")
|
217
|
+
#num = n[0].childNodes.length
|
218
|
+
#@editor.setRangeAt n[0], num
|
219
|
+
@editor.continue = false
|
220
|
+
@editor.markAsSelected(n[0])
|
221
|
+
@editor.pop_over_align.hide()
|
222
|
+
return false
|
223
|
+
|
224
|
+
else if prev_node.length > 0 && $(".graf--figure.is-mediaFocused").length > 0
|
225
|
+
# do our best to detect up arrow from selected
|
226
|
+
n = $(".graf--figure.is-mediaFocused").prev(".graf")
|
227
|
+
#num = n[0].childNodes.length
|
228
|
+
#@editor.setRangeAt n[0], num
|
229
|
+
@editor.continue = false
|
230
|
+
@editor.markAsSelected(n[0])
|
231
|
+
@editor.pop_over_align.hide()
|
232
|
+
return false
|
233
|
+
|
234
|
+
return unless $(current_node).hasClass("graf")
|
235
|
+
return unless $(current_node).editableCaretOnFirstLine()
|
236
|
+
|
237
|
+
utils.log "ENTER ARROW PASSED RETURNS"
|
238
|
+
|
239
|
+
if prev_node.hasClass("graf--figure")
|
240
|
+
utils.log "1 up"
|
241
|
+
n = prev_node.find(".imageCaption")
|
242
|
+
@editor.scrollTo(n)
|
243
|
+
@editor.skip_keyup = true
|
244
|
+
@editor.selection().removeAllRanges()
|
245
|
+
@editor.markAsSelected(prev_node)
|
246
|
+
|
247
|
+
#TODO: to function
|
248
|
+
# @editor.setRangeAt $(".is-selected").find("figcaption")[0]
|
249
|
+
prev_node.addClass("is-mediaFocused")
|
250
|
+
@editor.pop_over_align.positionPopOver(@placeHolderDiv(prev_node))
|
251
|
+
|
252
|
+
@editor.continue = false
|
253
|
+
|
254
|
+
return false
|
255
|
+
|
256
|
+
else if prev_node.hasClass("graf--mixtapeEmbed")
|
257
|
+
n = current_node.prev(".graf--mixtapeEmbed")
|
258
|
+
num = n[0].childNodes.length
|
259
|
+
@editor.setRangeAt n[0], num
|
260
|
+
#@editor.scrollTo(n)
|
261
|
+
utils.log "2 up"
|
262
|
+
@editor.continue = false
|
263
|
+
return false
|
264
|
+
|
265
|
+
if current_node.hasClass("graf--figure") && prev_node.hasClass("graf")
|
266
|
+
@editor.setRangeAt prev_node[0]
|
267
|
+
#@editor.scrollTo(prev_node)
|
268
|
+
utils.log "3 up"
|
269
|
+
@editor.continue = false
|
270
|
+
return false
|
271
|
+
|
272
|
+
else if prev_node.hasClass("graf")
|
273
|
+
n = current_node.prev(".graf")
|
274
|
+
num = n[0].childNodes.length
|
275
|
+
#@editor.scrollTo(n)
|
276
|
+
utils.log "4 up"
|
277
|
+
@editor.skip_keyup = true
|
278
|
+
@editor.markAsSelected(prev_node)
|
279
|
+
# @editor.continue = false
|
280
|
+
return false
|
281
|
+
|
282
|
+
|
283
|
+
#handle arrow direction from keyUp.
|
284
|
+
handleArrowForKeyUp: (ev)=>
|
285
|
+
current_node = $(@editor.editor.getNode())
|
286
|
+
if current_node.length > 0
|
287
|
+
@editor.markAsSelected( current_node )
|
288
|
+
@editor.displayTooltipAt( current_node )
|
@@ -0,0 +1,64 @@
|
|
1
|
+
utils = Dante.utils
|
2
|
+
|
3
|
+
class Dante.View.Behavior.Paste extends Dante.View.Behavior
|
4
|
+
|
5
|
+
#events:
|
6
|
+
# "paste" : "handlePaste"
|
7
|
+
|
8
|
+
initialize: (opts={})->
|
9
|
+
@editor = opts.current_editor
|
10
|
+
|
11
|
+
#detects html data , creates a hidden node to paste ,
|
12
|
+
#then clean up the content and copies to currentNode, very clever uh?
|
13
|
+
handlePaste: (ev, parent)=>
|
14
|
+
|
15
|
+
utils.log("pasted!")
|
16
|
+
|
17
|
+
pastedText = undefined
|
18
|
+
if (window.clipboardData && window.clipboardData.getData) #IE
|
19
|
+
pastedText = window.clipboardData.getData('Text')
|
20
|
+
else if (ev.originalEvent.clipboardData && ev.originalEvent.clipboardData.getData)
|
21
|
+
cbd = ev.originalEvent.clipboardData
|
22
|
+
pastedText = if _.isEmpty(cbd.getData('text/html')) then cbd.getData('text/plain') else cbd.getData('text/html')
|
23
|
+
|
24
|
+
utils.log("Process and handle text...")
|
25
|
+
#detect if is html
|
26
|
+
if pastedText.match(/<\/*[a-z][^>]+?>/gi)
|
27
|
+
utils.log("HTML DETECTED ON PASTE")
|
28
|
+
pastedText = pastedText.replace(/&.*;/g, "")
|
29
|
+
|
30
|
+
#convert pasted divs in p before copy contents into div
|
31
|
+
pastedText = pastedText.replace(/<div>([\w\W]*?)<\/div>/gi, '<p>$1</p>')
|
32
|
+
|
33
|
+
#create the placeholder element and assign pasted content
|
34
|
+
document.body.appendChild( $("<div id='#{@editor.paste_element_id.replace('#', '')}' class='dante-paste'></div>")[0] )
|
35
|
+
|
36
|
+
$(@editor.paste_element_id).html("<span>#{pastedText}</span>")
|
37
|
+
|
38
|
+
#clean pasted content
|
39
|
+
@editor.setupElementsClasses $(@editor.paste_element_id), (e)=>
|
40
|
+
# e is the target object which is cleaned
|
41
|
+
nodes = $(e.html()).insertAfter($(parent))
|
42
|
+
#remove paste div since we wont use it until the next paste
|
43
|
+
e.remove()
|
44
|
+
#set caret on newly created node
|
45
|
+
last_node = nodes.last()[0]
|
46
|
+
num = last_node.childNodes.length
|
47
|
+
@editor.setRangeAt(last_node, num)
|
48
|
+
|
49
|
+
#select new node
|
50
|
+
new_node = $(@editor.getNode())
|
51
|
+
@editor.markAsSelected(new_node)
|
52
|
+
@editor.displayTooltipAt($(@editor.el).find(".is-selected"))
|
53
|
+
|
54
|
+
# wrap new images
|
55
|
+
@editor.handleUnwrappedImages(nodes)
|
56
|
+
|
57
|
+
#scroll to element top
|
58
|
+
top = new_node.offset().top
|
59
|
+
$('html, body').animate
|
60
|
+
scrollTop: top
|
61
|
+
, 20
|
62
|
+
|
63
|
+
@editor.continue = false
|
64
|
+
return false # Prevent the default handler from running.
|
@@ -38,6 +38,8 @@ class Dante.Editor extends Dante.View
|
|
38
38
|
|
39
39
|
@upload_url = opts.upload_url || "/uploads.json"
|
40
40
|
@upload_callback = opts.upload_callback
|
41
|
+
@image_delete_callback = opts.image_delete_callback
|
42
|
+
|
41
43
|
@oembed_url = opts.oembed_url || "http://api.embed.ly/1/oembed?key=#{opts.api_key}&url="
|
42
44
|
@extract_url = opts.extract_url || "http://api.embed.ly/1/extract?key=#{opts.api_key}&url="
|
43
45
|
@default_loading_placeholder = opts.default_loading_placeholder || Dante.defaults.image_placeholder
|
@@ -60,7 +62,7 @@ class Dante.Editor extends Dante.View
|
|
60
62
|
@suggest_resource_handler = opts.suggest_resource_handler || null
|
61
63
|
|
62
64
|
opts.base_widgets ||= ["uploader", "embed", "embed_extract"]
|
63
|
-
opts.base_behaviors ||= ["save", "image","list", "suggest"]
|
65
|
+
opts.base_behaviors ||= ["save", "image", "paste", "list", "suggest"]
|
64
66
|
|
65
67
|
@widgets = []
|
66
68
|
@behaviors = []
|
@@ -94,13 +96,17 @@ class Dante.Editor extends Dante.View
|
|
94
96
|
@save_behavior = new Dante.View.Behavior.Save(current_editor: @, el: @el)
|
95
97
|
@behaviors.push @save_behavior
|
96
98
|
|
99
|
+
if base_behaviors.indexOf("paste") >= 0
|
100
|
+
@paste_behavior = new Dante.View.Behavior.Paste(current_editor: @, el: @el)
|
101
|
+
@behaviors.push @paste_behavior
|
102
|
+
|
97
103
|
if base_behaviors.indexOf("image") >= 0
|
98
|
-
@
|
99
|
-
@behaviors.push @
|
104
|
+
@image_behavior = new Dante.View.Behavior.Image(current_editor: @, el: @el)
|
105
|
+
@behaviors.push @image_behavior
|
100
106
|
|
101
107
|
if base_behaviors.indexOf("list") >= 0
|
102
|
-
@
|
103
|
-
@behaviors.push @
|
108
|
+
@list_behavior = new Dante.View.Behavior.List(current_editor: @, el: @el)
|
109
|
+
@behaviors.push @list_behavior
|
104
110
|
|
105
111
|
#add extra behaviors
|
106
112
|
if opts.extra_behaviors
|
@@ -217,6 +223,7 @@ class Dante.Editor extends Dante.View
|
|
217
223
|
|
218
224
|
getSelectionStart: ->
|
219
225
|
node = document.getSelection().anchorNode
|
226
|
+
return if node is null
|
220
227
|
if node.nodeType == 3 then node.parentNode else node
|
221
228
|
|
222
229
|
getRange: () ->
|
@@ -386,111 +393,12 @@ class Dante.Editor extends Dante.View
|
|
386
393
|
, 20
|
387
394
|
|
388
395
|
#handle arrow direction from keyUp.
|
389
|
-
|
396
|
+
handleArrowForKeyUp: (ev)=>
|
390
397
|
current_node = $(@getNode())
|
391
398
|
if current_node.length > 0
|
392
399
|
@markAsSelected( current_node )
|
393
400
|
@displayTooltipAt( current_node )
|
394
401
|
|
395
|
-
#handle arrow direction from keyDown.
|
396
|
-
handleArrowForKeyDown: (ev)=>
|
397
|
-
caret_node = @getNode()
|
398
|
-
current_node = $(caret_node)
|
399
|
-
utils.log(ev)
|
400
|
-
ev_type = ev.originalEvent.key || ev.originalEvent.keyIdentifier
|
401
|
-
|
402
|
-
utils.log("ENTER ARROW for key #{ev_type}")
|
403
|
-
|
404
|
-
#handle keys for image figure
|
405
|
-
switch ev_type
|
406
|
-
|
407
|
-
when "Down"
|
408
|
-
#when graff-image selected but none selection is found
|
409
|
-
if _.isUndefined(current_node) or !current_node.exists()
|
410
|
-
if $(".is-selected").exists()
|
411
|
-
current_node = $(".is-selected")
|
412
|
-
|
413
|
-
next_node = current_node.next()
|
414
|
-
|
415
|
-
utils.log "NEXT NODE IS #{next_node.attr('class')}"
|
416
|
-
utils.log "CURRENT NODE IS #{current_node.attr('class')}"
|
417
|
-
|
418
|
-
return unless $(current_node).hasClass("graf")
|
419
|
-
return unless current_node.hasClass("graf--figure") or $(current_node).editableCaretOnLastLine()
|
420
|
-
|
421
|
-
utils.log "ENTER ARROW PASSED RETURNS"
|
422
|
-
|
423
|
-
#if next element is embed select & focus it
|
424
|
-
if next_node.hasClass("graf--figure") && caret_node
|
425
|
-
n = next_node.find(".imageCaption")
|
426
|
-
@scrollTo(n)
|
427
|
-
utils.log "1 down"
|
428
|
-
utils.log n[0]
|
429
|
-
@skip_keyup = true
|
430
|
-
@selection().removeAllRanges()
|
431
|
-
@markAsSelected(next_node)
|
432
|
-
next_node.addClass("is-mediaFocused is-selected")
|
433
|
-
return false
|
434
|
-
#if current node is embed
|
435
|
-
else if next_node.hasClass("graf--mixtapeEmbed")
|
436
|
-
n = current_node.next(".graf--mixtapeEmbed")
|
437
|
-
num = n[0].childNodes.length
|
438
|
-
@setRangeAt n[0], num
|
439
|
-
@scrollTo(n)
|
440
|
-
utils.log "2 down"
|
441
|
-
return false
|
442
|
-
|
443
|
-
if current_node.hasClass("graf--figure") && next_node.hasClass("graf")
|
444
|
-
@scrollTo(next_node)
|
445
|
-
utils.log "3 down, from figure to next graf"
|
446
|
-
#@skip_keyup = true
|
447
|
-
@markAsSelected(next_node)
|
448
|
-
@setRangeAt next_node[0]
|
449
|
-
return false
|
450
|
-
|
451
|
-
when "Up"
|
452
|
-
prev_node = current_node.prev()
|
453
|
-
utils.log "PREV NODE IS #{prev_node.attr('class')} #{prev_node.attr('name')}"
|
454
|
-
utils.log "CURRENT NODE IS up #{current_node.attr('class')}"
|
455
|
-
|
456
|
-
return unless $(current_node).hasClass("graf")
|
457
|
-
return unless $(current_node).editableCaretOnFirstLine()
|
458
|
-
|
459
|
-
utils.log "ENTER ARROW PASSED RETURNS"
|
460
|
-
|
461
|
-
if prev_node.hasClass("graf--figure")
|
462
|
-
utils.log "1 up"
|
463
|
-
n = prev_node.find(".imageCaption")
|
464
|
-
@scrollTo(n)
|
465
|
-
@skip_keyup = true
|
466
|
-
@selection().removeAllRanges()
|
467
|
-
@markAsSelected(prev_node)
|
468
|
-
prev_node.addClass("is-mediaFocused")
|
469
|
-
return false
|
470
|
-
|
471
|
-
else if prev_node.hasClass("graf--mixtapeEmbed")
|
472
|
-
n = current_node.prev(".graf--mixtapeEmbed")
|
473
|
-
num = n[0].childNodes.length
|
474
|
-
@setRangeAt n[0], num
|
475
|
-
@scrollTo(n)
|
476
|
-
utils.log "2 up"
|
477
|
-
return false
|
478
|
-
|
479
|
-
if current_node.hasClass("graf--figure") && prev_node.hasClass("graf")
|
480
|
-
@setRangeAt prev_node[0]
|
481
|
-
@scrollTo(prev_node)
|
482
|
-
utils.log "3 up"
|
483
|
-
return false
|
484
|
-
|
485
|
-
else if prev_node.hasClass("graf")
|
486
|
-
n = current_node.prev(".graf")
|
487
|
-
num = n[0].childNodes.length
|
488
|
-
@scrollTo(n)
|
489
|
-
utils.log "4 up"
|
490
|
-
@skip_keyup = true
|
491
|
-
@markAsSelected(prev_node)
|
492
|
-
return false
|
493
|
-
|
494
402
|
#parse text for initial mess
|
495
403
|
parseInitialMess: ()->
|
496
404
|
@setupElementsClasses $(@el).find('.section-inner') , (e)=>
|
@@ -505,56 +413,17 @@ class Dante.Editor extends Dante.View
|
|
505
413
|
|
506
414
|
#detects html data , creates a hidden node to paste ,
|
507
415
|
#then clean up the content and copies to currentNode, very clever uh?
|
508
|
-
handlePaste: (
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
if (window.clipboardData && window.clipboardData.getData) #IE
|
514
|
-
pastedText = window.clipboardData.getData('Text')
|
515
|
-
else if (ev.originalEvent.clipboardData && ev.originalEvent.clipboardData.getData)
|
516
|
-
cbd = ev.originalEvent.clipboardData
|
517
|
-
pastedText = if _.isEmpty(cbd.getData('text/html')) then cbd.getData('text/plain') else cbd.getData('text/html')
|
518
|
-
|
519
|
-
utils.log("Process and handle text...")
|
520
|
-
#detect if is html
|
521
|
-
if pastedText.match(/<\/*[a-z][^>]+?>/gi)
|
522
|
-
utils.log("HTML DETECTED ON PASTE")
|
523
|
-
pastedText = pastedText.replace(/&.*;/g, "")
|
524
|
-
|
525
|
-
#convert pasted divs in p before copy contents into div
|
526
|
-
pastedText = pastedText.replace(/<div>([\w\W]*?)<\/div>/gi, '<p>$1</p>')
|
527
|
-
|
528
|
-
#create the placeholder element and assign pasted content
|
529
|
-
document.body.appendChild( $("<div id='#{@paste_element_id.replace('#', '')}' class='dante-paste'></div>")[0] )
|
530
|
-
$(@paste_element_id).html("<span>#{pastedText}</span>")
|
531
|
-
|
532
|
-
#clean pasted content
|
533
|
-
|
534
|
-
@setupElementsClasses $(@paste_element_id), (e)=>
|
535
|
-
# e is the target object which is cleaned
|
536
|
-
nodes = $(e.html()).insertAfter($(@aa))
|
537
|
-
#remove paste div since we wont use it until the next paste
|
538
|
-
e.remove()
|
539
|
-
#set caret on newly created node
|
540
|
-
last_node = nodes.last()[0]
|
541
|
-
num = last_node.childNodes.length
|
542
|
-
@setRangeAt(last_node, num)
|
543
|
-
#select new node
|
544
|
-
new_node = $(@getNode())
|
545
|
-
@markAsSelected(new_node)
|
546
|
-
@displayTooltipAt($(@el).find(".is-selected"))
|
547
|
-
|
548
|
-
@handleUnwrappedImages(nodes)
|
549
|
-
|
550
|
-
#scroll to element top
|
551
|
-
top = new_node.offset().top
|
552
|
-
$('html, body').animate
|
553
|
-
scrollTop: top
|
554
|
-
, 20
|
416
|
+
handlePaste: (e)=>
|
417
|
+
@continue = true
|
418
|
+
#handle paste for each widget
|
419
|
+
utils.log("HANDLING PASTE");
|
420
|
+
parent = @getNode()
|
555
421
|
|
422
|
+
_.each @behaviors, (b)=>
|
423
|
+
if b.handlePaste
|
424
|
+
b.handlePaste(e, parent);
|
556
425
|
|
557
|
-
|
426
|
+
return false unless @continue
|
558
427
|
|
559
428
|
handleUnwrappedImages: (elements)->
|
560
429
|
# http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata
|
@@ -658,6 +527,8 @@ class Dante.Editor extends Dante.View
|
|
658
527
|
handleKeyDown: (e)->
|
659
528
|
utils.log "KEYDOWN"
|
660
529
|
|
530
|
+
@continue = true
|
531
|
+
|
661
532
|
anchor_node = @getNode() #current node on which cursor is positioned
|
662
533
|
parent = $(anchor_node)
|
663
534
|
|
@@ -670,6 +541,8 @@ class Dante.Editor extends Dante.View
|
|
670
541
|
if b.handleKeyDown
|
671
542
|
b.handleKeyDown(e, parent);
|
672
543
|
|
544
|
+
return false unless @continue
|
545
|
+
|
673
546
|
if e.which is TAB
|
674
547
|
@handleTab(anchor_node)
|
675
548
|
return false
|
@@ -682,7 +555,7 @@ class Dante.Editor extends Dante.View
|
|
682
555
|
utils.log @isLastChar()
|
683
556
|
|
684
557
|
#handle keydowns for each widget
|
685
|
-
utils.log("HANDLING WIDGET
|
558
|
+
utils.log("HANDLING WIDGET ENTER");
|
686
559
|
_.each @widgets, (w)=>
|
687
560
|
if w.handleEnterKey
|
688
561
|
w.handleEnterKey(e, parent);
|
@@ -761,11 +634,11 @@ class Dante.Editor extends Dante.View
|
|
761
634
|
return false;
|
762
635
|
|
763
636
|
#select an image if backspacing into it from a paragraph
|
764
|
-
if($(anchor_node).hasClass("graf--p") && @isFirstChar() )
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
637
|
+
#if($(anchor_node).hasClass("graf--p") && @isFirstChar() )
|
638
|
+
# if($(anchor_node).prev().hasClass("graf--figure") && @getSelectedText().length == 0)
|
639
|
+
# e.preventDefault();
|
640
|
+
# $(anchor_node).prev().find("img").click();
|
641
|
+
# utils.log("Focus on the previous image");
|
769
642
|
|
770
643
|
if $(utils_anchor_node).hasClass("section-content") || $(utils_anchor_node).hasClass("graf--first")
|
771
644
|
utils.log "SECTION DETECTED FROM KEYDOWN #{_.isEmpty($(utils_anchor_node).text())}"
|
@@ -775,41 +648,17 @@ class Dante.Editor extends Dante.View
|
|
775
648
|
# @displayEmptyPlaceholder()
|
776
649
|
utils.log("TextNode detected from Down!")
|
777
650
|
#return false
|
778
|
-
|
779
|
-
# supress del into & delete embed if empty content found on delete key
|
780
|
-
if $(anchor_node).hasClass("graf--mixtapeEmbed") or $(anchor_node).hasClass("graf--iframe")
|
781
|
-
if _.isEmpty $(anchor_node).text().trim() or @isFirstChar()
|
782
|
-
utils.log("Check for inmediate deletion on empty embed text")
|
783
|
-
@inmediateDeletion = @isSelectingAll(anchor_node)
|
784
|
-
@handleInmediateDeletion($(anchor_node)) if @inmediateDeletion
|
785
|
-
return false
|
786
|
-
|
787
|
-
# TODO: supress del when the prev el is embed and current_node is at first char
|
788
|
-
if $(anchor_node).prev().hasClass("graf--mixtapeEmbed")
|
789
|
-
return false if @isFirstChar() && !_.isEmpty( $(anchor_node).text().trim() )
|
790
|
-
|
791
|
-
#arrows key
|
792
|
-
#up & down
|
793
|
-
if _.contains([UPARROW, DOWNARROW], e.which)
|
794
|
-
utils.log e.which
|
795
|
-
@handleArrowForKeyDown(e)
|
796
|
-
#return false
|
797
|
-
|
651
|
+
|
798
652
|
#hides tooltip if anchor_node text is empty
|
799
653
|
if anchor_node
|
800
654
|
unless _.isEmpty($(anchor_node).text())
|
801
655
|
@tooltip_view.hide()
|
802
656
|
$(anchor_node).removeClass("graf--empty")
|
803
657
|
|
804
|
-
#when user types over a selected image (graf--figure)
|
805
|
-
#unselect image , and set range on caption
|
806
|
-
if _.isUndefined(anchor_node) && $(".is-selected").hasClass("is-mediaFocused")
|
807
|
-
@setRangeAt $(".is-selected").find("figcaption")[0]
|
808
|
-
$(".is-selected").removeClass("is-mediaFocused")
|
809
|
-
return false
|
810
|
-
|
811
658
|
handleKeyUp: (e , node)->
|
812
659
|
|
660
|
+
@continue = true
|
661
|
+
|
813
662
|
if @skip_keyup
|
814
663
|
@skip_keyup = null
|
815
664
|
utils.log "SKIP KEYUP"
|
@@ -830,6 +679,8 @@ class Dante.Editor extends Dante.View
|
|
830
679
|
if b.handleKeyUp
|
831
680
|
b.handleKeyUp(e)
|
832
681
|
|
682
|
+
return false unless @continue
|
683
|
+
|
833
684
|
if (e.which == BACKSPACE)
|
834
685
|
|
835
686
|
#if detect all text deleted , re render
|
@@ -872,7 +723,7 @@ class Dante.Editor extends Dante.View
|
|
872
723
|
|
873
724
|
#arrows key
|
874
725
|
if _.contains([LEFTARROW, UPARROW, RIGHTARROW, DOWNARROW], e.which)
|
875
|
-
@
|
726
|
+
@handleArrowForKeyUp(e)
|
876
727
|
#return false
|
877
728
|
|
878
729
|
handleKeyPress: (e, node)->
|
@@ -915,13 +766,15 @@ class Dante.Editor extends Dante.View
|
|
915
766
|
|
916
767
|
#mark the current row as selected
|
917
768
|
markAsSelected: (element)->
|
918
|
-
utils.log
|
769
|
+
utils.log "MARK AS SELECTED"
|
770
|
+
|
919
771
|
return if _.isUndefined element
|
920
772
|
|
921
773
|
$(@el).find(".is-selected").removeClass("is-mediaFocused is-selected")
|
774
|
+
|
922
775
|
$(element).addClass("is-selected")
|
923
776
|
|
924
|
-
|
777
|
+
#$(element).find(".defaultValue").remove()
|
925
778
|
#set reached top if element is first!
|
926
779
|
if $(element).hasClass("graf--first")
|
927
780
|
@reachedTop = true
|
@@ -997,7 +850,7 @@ class Dante.Editor extends Dante.View
|
|
997
850
|
@cleanContents(element)
|
998
851
|
@wrapTextNodes(element)
|
999
852
|
#setup classes
|
1000
|
-
_.each
|
853
|
+
_.each element.children(), (n)=>
|
1001
854
|
name = $(n).prop("tagName").toLowerCase()
|
1002
855
|
n = @addClassesToElement(n)
|
1003
856
|
@setElementName(n)
|
@@ -1114,7 +967,7 @@ class Dante.Editor extends Dante.View
|
|
1114
967
|
|
1115
968
|
setupFirstAndLast: ()=>
|
1116
969
|
childs = $(@el).find(".section-inner").children()
|
1117
|
-
childs.removeClass("graf--last
|
970
|
+
childs.removeClass("graf--last, graf--first")
|
1118
971
|
childs.first().addClass("graf--first")
|
1119
972
|
childs.last().addClass("graf--last")
|
1120
973
|
|