dante-editor 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/app/assets/javascripts/dante.js +7 -6
- data/app/assets/javascripts/dante/article.js.coffee +56 -0
- data/app/assets/javascripts/dante/behaviors/image.js.coffee +9 -9
- data/app/assets/javascripts/dante/behaviors/list.js.coffee +2 -2
- data/app/assets/javascripts/dante/behaviors/paste.js.coffee +3 -0
- data/app/assets/javascripts/dante/dante.js.coffee.erb +2 -0
- data/app/assets/javascripts/dante/editor.js.coffee +71 -40
- data/app/assets/javascripts/dante/popovers/anchor.js.coffee +82 -0
- data/app/assets/javascripts/dante/popovers/card.js.coffee +103 -0
- data/app/assets/javascripts/dante/popovers/image.js.coffee +112 -0
- data/app/assets/javascripts/dante/popovers/typeahead.js.coffee +125 -0
- data/app/assets/javascripts/dante/tooltip_widgets/embed.js.coffee +3 -3
- data/app/assets/javascripts/dante/tooltip_widgets/extract.js.coffee +12 -3
- data/app/assets/javascripts/dante/tooltip_widgets/uploader.js.coffee +1 -1
- data/bower.json +1 -1
- data/dist/js/dante-editor.js +608 -455
- data/lib/dante-editor/version.rb +1 -1
- data/source/non_editable.erb +45 -0
- data/source/partials/_existing_content.erb +35 -0
- metadata +9 -3
- data/app/assets/javascripts/dante/popover.js.coffee +0 -424
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5f8c0fc81095096da19c3e387d79bedab7a3ec3
|
4
|
+
data.tar.gz: f11b2bc0404231a18de30c42b59169ae674db5af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61923bfbcb46e98d3314997362b4f13a3041a60e34b8dc97b4ab4c91c8f436a7a7e1c76c751fa3d55148cfe30746c6fd4be68fa7d5479a73f89145ebe03169a4
|
7
|
+
data.tar.gz: 3bca3b2e85212118e3f6dcb114fa7ed75cca273cc58d75f9cdd1f7843837dd507a69446e679792d696340796071b022e82ba8bfeab6535813f824f473984bc56
|
data/README.md
CHANGED
@@ -92,13 +92,19 @@ Until now I´ve been able to implement the following features:
|
|
92
92
|
+ **store_interval:** default: 1500 (1.5 secs), used when store_url is present.
|
93
93
|
|
94
94
|
#### Uploader:
|
95
|
+
|
95
96
|
+ **upload_url:** default: /uploads.json
|
96
97
|
+ **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
98
|
+ **image_delete_callback**: default: none, returns the image data before deletion. use this if you want to destroy image from the server.
|
99
|
+
+ **image_caption_placeholder** default: "Type caption for image (optional)"
|
100
|
+
|
101
|
+
|
98
102
|
#### Embed tool:
|
103
|
+
|
99
104
|
+ **oembed_url:** default: http://api.embed.ly/1/oembed?url="
|
100
105
|
+ **extract_url:** default: http://api.embed.ly/1/extract?url="
|
101
106
|
+ **embed_placeholder** default: 'Paste a YouTube, Vine, Vimeo, or other video link, and press Enter'
|
107
|
+
+ **embed_caption_placeholder** default: "Type caption for embed (optional)"
|
102
108
|
+ **extract_placeholder** default: 'Paste a link to embed content from another site (e.g. Twitter) and press Enter'
|
103
109
|
|
104
110
|
#### Suggest Behavior (new!)
|
@@ -3,16 +3,17 @@
|
|
3
3
|
//= require dante/utils
|
4
4
|
//= require dante/view
|
5
5
|
//= require dante/editor
|
6
|
+
|
7
|
+
//= require dante/article
|
8
|
+
|
6
9
|
//= require dante/behavior
|
7
|
-
//=
|
8
|
-
|
9
|
-
//= require dante/behaviors/image
|
10
|
-
//= require dante/behaviors/list
|
11
|
-
//= require dante/behaviors/save
|
10
|
+
//= require_tree ./dante/behaviors
|
11
|
+
|
12
12
|
//= require dante/tooltip_widget
|
13
13
|
//= require dante/tooltip_widgets/uploader
|
14
14
|
//= require dante/tooltip_widgets/embed
|
15
15
|
//= require dante/tooltip_widgets/extract
|
16
16
|
//= require dante/tooltip
|
17
|
-
|
17
|
+
|
18
|
+
//= require_tree ./dante/popovers
|
18
19
|
//= require dante/menu
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class Dante.Article extends Dante.View
|
2
|
+
|
3
|
+
el: "body"
|
4
|
+
|
5
|
+
events:
|
6
|
+
# TODO: this events should be in tooltip class
|
7
|
+
"mouseover .markup--anchor" : "displayPopOver"
|
8
|
+
"mouseout .markup--anchor" : "hidePopOver"
|
9
|
+
|
10
|
+
initialize: (opts={})->
|
11
|
+
@options = opts
|
12
|
+
@popovers = []
|
13
|
+
opts.base_popovers ||= ["anchor", "card"]
|
14
|
+
|
15
|
+
start: ()=>
|
16
|
+
@render()
|
17
|
+
@appendMenus()
|
18
|
+
|
19
|
+
appendMenus: ->
|
20
|
+
@intializePopOvers(@options)
|
21
|
+
@removeEditables()
|
22
|
+
|
23
|
+
render: ->
|
24
|
+
|
25
|
+
removeEditables: ->
|
26
|
+
$(@el).find("[contenteditable]").removeAttr("contenteditable")
|
27
|
+
|
28
|
+
intializePopOvers: (opts)->
|
29
|
+
|
30
|
+
base_popovers = opts.base_popovers
|
31
|
+
self = @
|
32
|
+
|
33
|
+
if base_popovers.indexOf("anchor") >= 0
|
34
|
+
@pop_over = new Dante.Editor.PopOver(editor: @)
|
35
|
+
@popovers.push @pop_over
|
36
|
+
|
37
|
+
if base_popovers.indexOf("card") >= 0
|
38
|
+
@pop_over_card = new Dante.Editor.PopOverCard(editor: @)
|
39
|
+
@popovers.push @pop_over_card
|
40
|
+
|
41
|
+
# add extra widgets
|
42
|
+
if opts.extra_popovers
|
43
|
+
_.each opts.extra_popovers, (w)=>
|
44
|
+
if !w.current_editor
|
45
|
+
w.current_editor = self
|
46
|
+
@popovers.push w
|
47
|
+
|
48
|
+
# render and hide
|
49
|
+
@popovers.forEach (p)->
|
50
|
+
p.render().hide()
|
51
|
+
|
52
|
+
displayPopOver: (ev)->
|
53
|
+
@pop_over.displayAt(ev)
|
54
|
+
|
55
|
+
hidePopOver: (ev)->
|
56
|
+
@pop_over.hide(ev)
|
@@ -85,11 +85,11 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
85
85
|
|
86
86
|
# call callback for image delete
|
87
87
|
if @editor.image_delete_callback
|
88
|
-
@editor.image_delete_callback(
|
88
|
+
@editor.image_delete_callback( @editor.findSelected().find("img").data() )
|
89
89
|
|
90
90
|
utils.log("Replacing selected node")
|
91
|
-
@editor.replaceWith("p",
|
92
|
-
@editor.setRangeAt(
|
91
|
+
@editor.replaceWith("p", @editor.findSelected())
|
92
|
+
@editor.setRangeAt(@editor.findSelected()[0])
|
93
93
|
@editor.pop_over_align.hide()
|
94
94
|
utils.log("Focus on the previous graf")
|
95
95
|
@editor.continue = false
|
@@ -123,13 +123,13 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
123
123
|
|
124
124
|
# when user types over a selected image (graf--figure)
|
125
125
|
# unselect image , and set range on caption
|
126
|
-
if _.isUndefined(parent) or parent.length is 0 &&
|
126
|
+
if _.isUndefined(parent) or parent.length is 0 && @editor.findSelected().hasClass("is-mediaFocused")
|
127
127
|
# will remove default value on typing
|
128
|
-
node =
|
128
|
+
node = @editor.findSelected().find("figcaption")
|
129
129
|
node.find(".defaultValue").remove()
|
130
130
|
|
131
131
|
@editor.setRangeAt node[0]
|
132
|
-
|
132
|
+
@editor.findSelected().removeClass("is-mediaFocused")
|
133
133
|
@editor.pop_over_align.hide()
|
134
134
|
#@editor.continue = false
|
135
135
|
return false
|
@@ -153,8 +153,8 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
153
153
|
when "ArrowDown", "Down"
|
154
154
|
# when graff-image selected but none selection is found
|
155
155
|
if _.isUndefined(current_node) or !current_node.exists()
|
156
|
-
if
|
157
|
-
current_node =
|
156
|
+
if @editor.findSelected().exists()
|
157
|
+
current_node = @editor.findSelected()
|
158
158
|
|
159
159
|
next_node = current_node.next()
|
160
160
|
|
@@ -274,7 +274,7 @@ class Dante.View.Behavior.Image extends Dante.View.Behavior
|
|
274
274
|
num = n[0].childNodes.length
|
275
275
|
#@editor.scrollTo(n)
|
276
276
|
utils.log "4 up"
|
277
|
-
@editor.skip_keyup = true
|
277
|
+
# @editor.skip_keyup = true
|
278
278
|
@editor.markAsSelected(prev_node)
|
279
279
|
# @editor.continue = false
|
280
280
|
return false
|
@@ -60,7 +60,7 @@ class Dante.View.Behavior.List extends Dante.View.Behavior
|
|
60
60
|
|
61
61
|
@editor.addClassesToElement($list[0])
|
62
62
|
@editor.replaceWith("li", $paragraph)
|
63
|
-
$li =
|
63
|
+
$li = @editor.findSelected()
|
64
64
|
|
65
65
|
@editor.setElementName($li[0])
|
66
66
|
|
@@ -141,7 +141,7 @@ class Dante.View.Behavior.List extends Dante.View.Behavior
|
|
141
141
|
$list.before($li)
|
142
142
|
content = $li.html()
|
143
143
|
@editor.replaceWith("p", $li)
|
144
|
-
$paragraph =
|
144
|
+
$paragraph = @editor.findSelected()
|
145
145
|
$paragraph.removeClass("graf--empty").html(content).attr("name", utils.generateUniqueName());
|
146
146
|
|
147
147
|
if($list.children().length is 0)
|
@@ -13,6 +13,9 @@ class Dante.View.Behavior.Paste extends Dante.View.Behavior
|
|
13
13
|
handlePaste: (ev, parent)=>
|
14
14
|
|
15
15
|
utils.log("pasted!")
|
16
|
+
|
17
|
+
# hide default value if it's any
|
18
|
+
@editor.hidePlaceholder($(parent))
|
16
19
|
|
17
20
|
pastedText = undefined
|
18
21
|
if (window.clipboardData && window.clipboardData.getData) #IE
|
@@ -39,11 +39,13 @@ class Dante.Editor extends Dante.View
|
|
39
39
|
@upload_url = opts.upload_url || "/uploads.json"
|
40
40
|
@upload_callback = opts.upload_callback
|
41
41
|
@image_delete_callback = opts.image_delete_callback
|
42
|
+
@image_caption_placeholder = opts.image_caption_placeholder || "Type caption for image (optional)"
|
42
43
|
|
43
44
|
@oembed_url = opts.oembed_url || "http://api.embed.ly/1/oembed?key=#{opts.api_key}&url="
|
44
45
|
@extract_url = opts.extract_url || "http://api.embed.ly/1/extract?key=#{opts.api_key}&url="
|
45
46
|
@default_loading_placeholder = opts.default_loading_placeholder || Dante.defaults.image_placeholder
|
46
|
-
|
47
|
+
@embed_caption_placeholder = opts.embed_caption_placeholder || "Type caption for embed (optional)"
|
48
|
+
|
47
49
|
@store_url = opts.store_url
|
48
50
|
@store_method = opts.store_method || "POST"
|
49
51
|
@store_success_handler = opts.store_success_handler
|
@@ -63,9 +65,11 @@ class Dante.Editor extends Dante.View
|
|
63
65
|
|
64
66
|
opts.base_widgets ||= ["uploader", "embed", "embed_extract"]
|
65
67
|
opts.base_behaviors ||= ["save", "image", "paste", "list", "suggest"]
|
68
|
+
opts.base_popovers ||= ["anchor", "typeahead", "card", "align"]
|
66
69
|
|
67
70
|
@widgets = []
|
68
71
|
@behaviors = []
|
72
|
+
@popovers = []
|
69
73
|
|
70
74
|
window.debugMode = opts.debug || false
|
71
75
|
|
@@ -73,8 +77,7 @@ class Dante.Editor extends Dante.View
|
|
73
77
|
|
74
78
|
titleplaceholder = opts.title_placeholder || 'Title'
|
75
79
|
@title_placeholder = "<span class='defaultValue defaultValue--root'>#{titleplaceholder}</span><br>"
|
76
|
-
title
|
77
|
-
@title = title
|
80
|
+
@title = opts.title || ''
|
78
81
|
bodyplaceholder = opts.body_placeholder || 'Tell your story…'
|
79
82
|
@body_placeholder = "<span class='defaultValue defaultValue--root'>#{bodyplaceholder}</span><br>"
|
80
83
|
embedplaceholder = opts.embed_placeholder || 'Paste a YouTube, Vine, Vimeo, or other video link, and press Enter'
|
@@ -108,7 +111,7 @@ class Dante.Editor extends Dante.View
|
|
108
111
|
@list_behavior = new Dante.View.Behavior.List(current_editor: @, el: @el)
|
109
112
|
@behaviors.push @list_behavior
|
110
113
|
|
111
|
-
#add extra behaviors
|
114
|
+
# add extra behaviors
|
112
115
|
if opts.extra_behaviors
|
113
116
|
_.each opts.extra_behaviors, (w)=>
|
114
117
|
if !w.current_editor
|
@@ -116,8 +119,8 @@ class Dante.Editor extends Dante.View
|
|
116
119
|
@behaviors.push w
|
117
120
|
|
118
121
|
initializeWidgets: (opts)->
|
119
|
-
#TODO: this could be a hash to access widgets without var
|
120
|
-
#Base widgets
|
122
|
+
# TODO: this could be a hash to access widgets without var
|
123
|
+
# Base widgets
|
121
124
|
base_widgets = opts.base_widgets
|
122
125
|
self = @
|
123
126
|
|
@@ -133,13 +136,45 @@ class Dante.Editor extends Dante.View
|
|
133
136
|
@embed_extract_widget = new Dante.View.TooltipWidget.EmbedExtract(current_editor: @)
|
134
137
|
@widgets.push @embed_extract_widget
|
135
138
|
|
136
|
-
#add extra widgets
|
139
|
+
# add extra widgets
|
137
140
|
if opts.extra_tooltip_widgets
|
138
141
|
_.each opts.extra_tooltip_widgets, (w)=>
|
139
142
|
if !w.current_editor
|
140
143
|
w.current_editor = self
|
141
144
|
@widgets.push w
|
142
145
|
|
146
|
+
intializePopOvers: (opts)->
|
147
|
+
|
148
|
+
base_popovers = opts.base_popovers
|
149
|
+
self = @
|
150
|
+
|
151
|
+
if base_popovers.indexOf("anchor") >= 0
|
152
|
+
@pop_over = new Dante.Editor.PopOver(editor: @)
|
153
|
+
@pop_over.render().hide()
|
154
|
+
|
155
|
+
if base_popovers.indexOf("typeahead") >= 0
|
156
|
+
@pop_over_typeahead = new Dante.Editor.PopOverTypeAhead(editor: @)
|
157
|
+
@popovers.push @pop_over_typeahead
|
158
|
+
|
159
|
+
if base_popovers.indexOf("card") >= 0
|
160
|
+
@pop_over_card = new Dante.Editor.PopOverCard(editor: @)
|
161
|
+
@popovers.push @pop_over_card
|
162
|
+
|
163
|
+
if base_popovers.indexOf("align") >= 0
|
164
|
+
@pop_over_align = new Dante.Editor.ImageTooltip(editor: @)
|
165
|
+
@popovers.push @pop_over_align
|
166
|
+
|
167
|
+
# add extra widgets
|
168
|
+
if opts.extra_popovers
|
169
|
+
_.each opts.extra_popovers, (w)=>
|
170
|
+
if !w.current_editor
|
171
|
+
w.current_editor = self
|
172
|
+
@popovers.push w
|
173
|
+
|
174
|
+
# render and hide
|
175
|
+
@popovers.forEach (p)->
|
176
|
+
p.render().hide()
|
177
|
+
|
143
178
|
getContent: ()->
|
144
179
|
$(@el).find(".section-inner").html()
|
145
180
|
|
@@ -170,18 +205,8 @@ class Dante.Editor extends Dante.View
|
|
170
205
|
$("<div class='inlineTooltip'></div>").insertAfter(@el)
|
171
206
|
@editor_menu = new Dante.Editor.Menu(editor: @)
|
172
207
|
@tooltip_view = new @tooltip_class(editor: @ , widgets: @widgets)
|
173
|
-
@pop_over = new Dante.Editor.PopOver(editor: @)
|
174
|
-
@pop_over.render().hide()
|
175
208
|
|
176
|
-
|
177
|
-
@pop_over_typeahead = new Dante.Editor.PopOverTypeAhead(editor: @)
|
178
|
-
@pop_over_typeahead.render().hide()
|
179
|
-
|
180
|
-
@pop_over_card = new Dante.Editor.PopOverCard(editor: @)
|
181
|
-
@pop_over_card.render().hide()
|
182
|
-
|
183
|
-
@pop_over_align = new Dante.Editor.ImageTooltip(editor: @)
|
184
|
-
@pop_over_align.render().hide()
|
209
|
+
@intializePopOvers(@editor_options)
|
185
210
|
|
186
211
|
@tooltip_view.render().hide()
|
187
212
|
|
@@ -488,7 +513,7 @@ class Dante.Editor extends Dante.View
|
|
488
513
|
else if !prev
|
489
514
|
@.setRangeAt(@.$el.find(".section-inner p")[0])
|
490
515
|
|
491
|
-
@displayTooltipAt(
|
516
|
+
@displayTooltipAt(@findSelected())
|
492
517
|
|
493
518
|
#used when all the content is removed, then it re render
|
494
519
|
handleCompleteDeletion: (element)->
|
@@ -525,6 +550,7 @@ class Dante.Editor extends Dante.View
|
|
525
550
|
@scrollTo $(next)
|
526
551
|
|
527
552
|
handleKeyDown: (e)->
|
553
|
+
|
528
554
|
utils.log "KEYDOWN"
|
529
555
|
|
530
556
|
@continue = true
|
@@ -536,12 +562,6 @@ class Dante.Editor extends Dante.View
|
|
536
562
|
|
537
563
|
#handle keyups for each widget
|
538
564
|
utils.log("HANDLING Behavior KEYDOWN");
|
539
|
-
|
540
|
-
_.each @behaviors, (b)=>
|
541
|
-
if b.handleKeyDown
|
542
|
-
b.handleKeyDown(e, parent);
|
543
|
-
|
544
|
-
return false unless @continue
|
545
565
|
|
546
566
|
if e.which is TAB
|
547
567
|
@handleTab(anchor_node)
|
@@ -550,7 +570,7 @@ class Dante.Editor extends Dante.View
|
|
550
570
|
if e.which is ENTER
|
551
571
|
|
552
572
|
#removes previous selected nodes
|
553
|
-
|
573
|
+
@findSelected().removeClass("is-selected")
|
554
574
|
|
555
575
|
utils.log @isLastChar()
|
556
576
|
|
@@ -569,9 +589,9 @@ class Dante.Editor extends Dante.View
|
|
569
589
|
if parent.hasClass("graf--iframe") or parent.hasClass("graf--figure")
|
570
590
|
if @isLastChar()
|
571
591
|
@handleLineBreakWith("p", parent)
|
572
|
-
@setRangeAtText(
|
592
|
+
@setRangeAtText(@findSelected()[0])
|
573
593
|
|
574
|
-
|
594
|
+
@findSelected().trigger("mouseup") #is not making any change
|
575
595
|
return false
|
576
596
|
else
|
577
597
|
return false
|
@@ -603,7 +623,7 @@ class Dante.Editor extends Dante.View
|
|
603
623
|
$(node).append("<br>")
|
604
624
|
|
605
625
|
# shows tooltip
|
606
|
-
@displayTooltipAt(
|
626
|
+
@displayTooltipAt(@findSelected())
|
607
627
|
, 2
|
608
628
|
|
609
629
|
# delete key
|
@@ -651,10 +671,16 @@ class Dante.Editor extends Dante.View
|
|
651
671
|
|
652
672
|
#hides tooltip if anchor_node text is empty
|
653
673
|
if anchor_node
|
654
|
-
|
674
|
+
if !_.isEmpty($(anchor_node).text())
|
655
675
|
@tooltip_view.hide()
|
656
676
|
$(anchor_node).removeClass("graf--empty")
|
657
677
|
|
678
|
+
_.each @behaviors, (b)=>
|
679
|
+
if b.handleKeyDown
|
680
|
+
b.handleKeyDown(e, parent);
|
681
|
+
|
682
|
+
return false unless @continue
|
683
|
+
|
658
684
|
handleKeyUp: (e , node)->
|
659
685
|
|
660
686
|
@continue = true
|
@@ -673,14 +699,6 @@ class Dante.Editor extends Dante.View
|
|
673
699
|
|
674
700
|
@handleTextSelection(anchor_node)
|
675
701
|
|
676
|
-
# handle keyups for each widget
|
677
|
-
utils.log("HANDLING Behavior KEYUPS");
|
678
|
-
_.each @behaviors, (b)=>
|
679
|
-
if b.handleKeyUp
|
680
|
-
b.handleKeyUp(e)
|
681
|
-
|
682
|
-
return false unless @continue
|
683
|
-
|
684
702
|
if (e.which == BACKSPACE)
|
685
703
|
|
686
704
|
#if detect all text deleted , re render
|
@@ -726,10 +744,21 @@ class Dante.Editor extends Dante.View
|
|
726
744
|
@handleArrowForKeyUp(e)
|
727
745
|
#return false
|
728
746
|
|
747
|
+
# handle keyups for each widget
|
748
|
+
utils.log("HANDLING Behavior KEYUPS");
|
749
|
+
_.each @behaviors, (b)=>
|
750
|
+
if b.handleKeyUp
|
751
|
+
b.handleKeyUp(e)
|
752
|
+
|
753
|
+
return false unless @continue
|
754
|
+
|
729
755
|
handleKeyPress: (e, node)->
|
730
756
|
anchor_node = @getNode()
|
731
757
|
parent = $(anchor_node)
|
732
|
-
|
758
|
+
|
759
|
+
@hidePlaceholder(parent)
|
760
|
+
|
761
|
+
# handle keyups for each widget
|
733
762
|
utils.log("HANDLING Behavior KEYPRESS");
|
734
763
|
_.each @behaviors, (b)=>
|
735
764
|
if b.handleKeyPress
|
@@ -770,7 +799,7 @@ class Dante.Editor extends Dante.View
|
|
770
799
|
|
771
800
|
return if _.isUndefined element
|
772
801
|
|
773
|
-
|
802
|
+
@findSelected().removeClass("is-mediaFocused is-selected")
|
774
803
|
|
775
804
|
$(element).addClass("is-selected")
|
776
805
|
|
@@ -990,3 +1019,5 @@ class Dante.Editor extends Dante.View
|
|
990
1019
|
$(span).replaceWith($(span).html()) for span in $spans when not $(span).hasClass("defaultValue")
|
991
1020
|
$item
|
992
1021
|
|
1022
|
+
findSelected: ->
|
1023
|
+
$(@el).find(".is-selected")
|