character_editor 0.0.9 → 0.1.2
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 -1
- data/app/assets/javascripts/character_editor/insert/_insert.coffee +97 -0
- data/app/assets/javascripts/character_editor/toolbar/_templates.coffee +14 -13
- data/app/assets/javascripts/character_editor/toolbar/_toolbar.coffee +2 -2
- data/app/assets/javascripts/character_editor.coffee +19 -1
- data/app/assets/stylesheets/character_editor.scss +22 -2
- data/lib/character_editor/version.rb +1 -1
- data/vendor/assets/javascripts/keypress.js +1063 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a28ae915e435aff9c7c4b42efa95dcbddd8e2b55
|
4
|
+
data.tar.gz: 567065cb629ca416769396e391657318295d41f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d00e2832a413ae65a4d3feaea248d8f4485b2e7ebd3e0265f2419a5e4d6df2734d68f66dcf0ef50c40a7959f080a77847bd75645fbc4966d4dd76e0df6b9e22
|
7
|
+
data.tar.gz: 67543b68ee242101e2f8d06d3fa3d5e9b3c30e3627547092451782f47d0d7057a6aca4e796d4c9bead7e7d024f73b6fabe1856067bf9642bff98fad994d3e44a
|
data/README.md
CHANGED
@@ -5,7 +5,12 @@ Based on [MediumEditor](https://github.com/daviferreira/medium-editor) — Mediu
|
|
5
5
|
## TODO:
|
6
6
|
- fix copy/paste in the editor (test Safari/Chrome/FF, might be related to span issue)
|
7
7
|
- pre tag is not removed when unset
|
8
|
-
-
|
8
|
+
- buttons for image settings
|
9
|
+
- fix placeholder
|
10
|
+
- fix insert image after pre
|
11
|
+
- figure out default buttons
|
12
|
+
- hotkeys
|
13
|
+
- improve toolbar performance (no DOM changes)
|
9
14
|
|
10
15
|
### Span Issue: happens only in Chrome
|
11
16
|
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#= require_self
|
2
|
+
|
3
|
+
window.delay = (ms, fnc) -> setTimeout(fnc, ms)
|
4
|
+
|
5
|
+
@CharacterEditor.Insert =
|
6
|
+
init: (options, elem) ->
|
7
|
+
@options = $.extend({}, @options, options)
|
8
|
+
|
9
|
+
@$elem = $("<div id=character_editor_insert_button class='character-editor-insert'><i class='chr-icon icon-plus-alt'></i></div>")
|
10
|
+
$(@options.viewSelector).append(@$elem)
|
11
|
+
|
12
|
+
@_build()
|
13
|
+
@_bind()
|
14
|
+
@
|
15
|
+
|
16
|
+
options: {}
|
17
|
+
|
18
|
+
_build: ->
|
19
|
+
|
20
|
+
_hide: ->
|
21
|
+
delay 50, => if not @stayVisible then @$elem.removeClass('visible')
|
22
|
+
|
23
|
+
_show: ($editorElement, offsetY=0) ->
|
24
|
+
# TODO: it looks like we don't need live recalculations, rather can have just a table of positions
|
25
|
+
delay 50, =>
|
26
|
+
if @stayVisible
|
27
|
+
offsetX = -($(@options.viewSelector).offset().left - $editorElement.offset().left) - 5 # '+' moves to the right
|
28
|
+
offsetY += Math.floor($editorElement.offset().top + $(@options.viewSelector).scrollTop() - $(@options.viewSelector).offset().top)
|
29
|
+
@$elem.css({ top: offsetY, 'margin-left': offsetX }).addClass('visible')
|
30
|
+
|
31
|
+
_bind: ->
|
32
|
+
@_bindOnHover()
|
33
|
+
@_bindImage()
|
34
|
+
|
35
|
+
_bindOnHover: ->
|
36
|
+
@$elem.on 'mouseenter', (e) => @stayVisible = true
|
37
|
+
@$elem.on 'mouseleave', (e) => @stayVisible = false ; @_hide()
|
38
|
+
@_bindMousemove()
|
39
|
+
#$(document).on 'mouseleave', '.character-editor-insert-enabled', => @stayVisible = false ; @_hide()
|
40
|
+
|
41
|
+
_bindMousemove: ->
|
42
|
+
$(document).on 'mousemove', '.character-editor-insert-enabled', (e) =>
|
43
|
+
# TODO: block this while scrolling is not stopped
|
44
|
+
$editorElement = $(e.currentTarget)
|
45
|
+
currentEditor = $editorElement.data('editor')
|
46
|
+
|
47
|
+
if currentEditor.options.disableInsert
|
48
|
+
return
|
49
|
+
|
50
|
+
if e.currentTarget == e.target # no child block is hovered
|
51
|
+
offsetY = 0
|
52
|
+
editorTop = $editorElement.offset().top
|
53
|
+
|
54
|
+
if $editorElement.children().length > 0
|
55
|
+
paddingTop = $editorElement.children().first().offset().top - editorTop
|
56
|
+
else
|
57
|
+
paddingTop = parseInt($editorElement.css('padding-top'))
|
58
|
+
|
59
|
+
if e.offsetY <= paddingTop # beginning of the editor
|
60
|
+
if $editorElement.children().length > 0
|
61
|
+
offsetY = paddingTop - @$elem.height()
|
62
|
+
|
63
|
+
@$insertAfterBlock = false
|
64
|
+
@$activeEditor = $editorElement
|
65
|
+
|
66
|
+
else # cursor in between blocks
|
67
|
+
$editorElement.children().each (i, el) =>
|
68
|
+
$block = $(el)
|
69
|
+
y = $block.offset().top - editorTop + $block.height()
|
70
|
+
|
71
|
+
if y < e.offsetY
|
72
|
+
@$insertAfterBlock = $block
|
73
|
+
offsetY = y
|
74
|
+
|
75
|
+
@stayVisible = true
|
76
|
+
@_show($editorElement, offsetY)
|
77
|
+
|
78
|
+
else
|
79
|
+
@stayVisible = false
|
80
|
+
@_hide()
|
81
|
+
|
82
|
+
_bindImage: ->
|
83
|
+
$('#character_editor_insert_button').on 'click', (e) =>
|
84
|
+
chr.execute 'showImages', true, (images) =>
|
85
|
+
_.each images.reverse(), (model) =>
|
86
|
+
@_insertImage(model.get('image'))
|
87
|
+
|
88
|
+
_insertImage: (data) ->
|
89
|
+
imageUrl = data.image.regular.url
|
90
|
+
$el = $("""<figure class='character-image' contenteditable='false'><img src='#{ imageUrl }'></figure>""")
|
91
|
+
if @$insertAfterBlock then $el.insertAfter(@$insertAfterBlock) else $el.prependTo(@$activeEditor)
|
92
|
+
|
93
|
+
destroy: ->
|
94
|
+
$('#character_editor_insert_button').off 'click'
|
95
|
+
$(document).off 'mousemove', '.character-editor-insert-enabled'
|
96
|
+
@$elem.off 'mouseenter, mouseleave'
|
97
|
+
@$elem.remove()
|
@@ -13,19 +13,19 @@
|
|
13
13
|
|
14
14
|
l =
|
15
15
|
bold: '<i class="fa fa-bold"></i>'
|
16
|
-
italic
|
16
|
+
italic: '<i class="fa fa-italic"></i>'
|
17
17
|
underline: '<i class="fa fa-underline"></i>'
|
18
18
|
strikethrough: '<i class="fa fa-strikethrough"></i>'
|
19
|
-
superscript: '<i class="fa fa-superscript"></i>'
|
20
|
-
subscript: '<i class="fa fa-subscript"></i>'
|
21
19
|
anchor: '<i class="fa fa-link"></i>'
|
22
|
-
image: '<i class="fa fa-picture-o"></i>'
|
23
20
|
quote: '<i class="fa fa-quote-right"></i>'
|
24
21
|
orderedlist: '<i class="fa fa-list-ol"></i>'
|
25
22
|
unorderedlist: '<i class="fa fa-list-ul"></i>'
|
26
23
|
pre: '<i class="fa fa-code fa-lg"></i>'
|
27
24
|
header1: "<b>#{ options.firstHeader.toUpperCase() }</b>"
|
28
25
|
header2: "<b>#{ options.secondHeader.toUpperCase() }</b>"
|
26
|
+
#image: '<i class="fa fa-picture-o"></i>'
|
27
|
+
#superscript: '<i class="fa fa-superscript"></i>'
|
28
|
+
#subscript: '<i class="fa fa-subscript"></i>'
|
29
29
|
|
30
30
|
templates =
|
31
31
|
bold: "<li><button class='#{classPrefix} #{classPrefix}-bold'
|
@@ -40,18 +40,9 @@
|
|
40
40
|
strikethrough: "<li><button class='#{classPrefix} #{classPrefix}-strikethrough'
|
41
41
|
data-action='strikethrough' data-element='strike'>#{ l.strikethrough }</button></li>"
|
42
42
|
|
43
|
-
superscript: "<li><button class='#{classPrefix} #{classPrefix}-superscript'
|
44
|
-
data-action='superscript' data-element='sup'>#{ l.superscript }</button></li>"
|
45
|
-
|
46
|
-
subscript: "<li><button class='#{classPrefix} #{classPrefix}-subscript'
|
47
|
-
data-action='subscript' data-element='sub'>#{ l.subscript }</button></li>"
|
48
|
-
|
49
43
|
anchor: "<li><button class='#{classPrefix} #{classPrefix}-anchor'
|
50
44
|
data-action='anchor' data-element='a'>#{ l.anchor }</button></li>"
|
51
45
|
|
52
|
-
image: "<li><button class='#{classPrefix} #{classPrefix}-image'
|
53
|
-
data-action='image' data-element='img'>#{ l.image }</button></li>"
|
54
|
-
|
55
46
|
quote: "<li><button class='#{classPrefix} #{classPrefix}-quote'
|
56
47
|
data-action='append-blockquote' data-element='blockquote'>#{ l.quote }</button></li>"
|
57
48
|
|
@@ -69,4 +60,14 @@
|
|
69
60
|
|
70
61
|
header2: "<li><button class='#{classPrefix} #{classPrefix}-header2'
|
71
62
|
data-action='append-#{ options.secondHeader }' data-element='#{ options.secondHeader }'>#{ l.header2 }</button></li>"
|
63
|
+
|
64
|
+
# image: "<li><button class='#{classPrefix} #{classPrefix}-image'
|
65
|
+
# data-action='image' data-element='img'>#{ l.image }</button></li>"
|
66
|
+
|
67
|
+
# superscript: "<li><button class='#{classPrefix} #{classPrefix}-superscript'
|
68
|
+
# data-action='superscript' data-element='sup'>#{ l.superscript }</button></li>"
|
69
|
+
|
70
|
+
# subscript: "<li><button class='#{classPrefix} #{classPrefix}-subscript'
|
71
|
+
# data-action='subscript' data-element='sub'>#{ l.subscript }</button></li>"
|
72
|
+
|
72
73
|
return templates
|
@@ -53,7 +53,7 @@
|
|
53
53
|
|
54
54
|
@$toolbarButtons.show()
|
55
55
|
|
56
|
-
@$anchorInput.css('width', @$elem.width() - 40
|
56
|
+
@$anchorInput.css('width', @$elem.width() - 40) # TODO: remove build in themes values
|
57
57
|
|
58
58
|
@keepToolbarVisible = false
|
59
59
|
|
@@ -102,9 +102,9 @@
|
|
102
102
|
if !@options.allowMultiParagraphSelection and hasMultiParagraphs
|
103
103
|
return @_hide()
|
104
104
|
|
105
|
-
@_setButtonStates()
|
106
105
|
@_show()
|
107
106
|
@_setPosition()
|
107
|
+
@_setButtonStates()
|
108
108
|
|
109
109
|
_setButtonStates: ->
|
110
110
|
$buttons = @$elem.find('button')
|
@@ -10,9 +10,11 @@
|
|
10
10
|
|
11
11
|
###
|
12
12
|
|
13
|
+
#= require keypress
|
13
14
|
#= require_self
|
14
15
|
#= require character_editor/_selection
|
15
16
|
#= require character_editor/toolbar/_toolbar
|
17
|
+
#= require character_editor/insert/_insert
|
16
18
|
|
17
19
|
# Object - an object representing a concept that you want
|
18
20
|
# to model (e.g. a car)
|
@@ -26,6 +28,7 @@
|
|
26
28
|
diffTop: -10
|
27
29
|
disableReturn: false
|
28
30
|
disableToolbar: false
|
31
|
+
disableInsert: false
|
29
32
|
forcePlainText: true
|
30
33
|
placeholder: 'Type your text...'
|
31
34
|
targetBlank: false
|
@@ -33,7 +36,7 @@
|
|
33
36
|
secondHeader: 'h3'
|
34
37
|
tabSpaces: ' '
|
35
38
|
viewSelector: 'body'
|
36
|
-
parentElements: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre']
|
39
|
+
parentElements: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre', 'ul', 'ol']
|
37
40
|
|
38
41
|
_dataOptions: ->
|
39
42
|
result = {}
|
@@ -81,6 +84,16 @@
|
|
81
84
|
if not @options.disableToolbar
|
82
85
|
@_addToolbar()
|
83
86
|
|
87
|
+
if not @options.disableInsert
|
88
|
+
@$elem.addClass 'character-editor-insert-enabled'
|
89
|
+
@_addInsert()
|
90
|
+
|
91
|
+
_addInsert: ->
|
92
|
+
@insert = window.characterEditorInsert
|
93
|
+
if not @insert
|
94
|
+
@insert = Object.create(CharacterEditor.Insert).init(@options)
|
95
|
+
window.characterEditorInsert = @insert
|
96
|
+
|
84
97
|
_addToolbar: ->
|
85
98
|
@toolbar = window.characterEditorToolbar
|
86
99
|
if not @toolbar
|
@@ -171,6 +184,11 @@
|
|
171
184
|
delete @toolbar
|
172
185
|
delete window.characterEditorToolbar
|
173
186
|
|
187
|
+
if @insert
|
188
|
+
@insert.destroy()
|
189
|
+
delete @insert
|
190
|
+
delete window.characterEditorInsert
|
191
|
+
|
174
192
|
# Object.create support test, and fallback for browsers without it
|
175
193
|
if typeof Object.create isnt "function"
|
176
194
|
Object.create = (o) ->
|
@@ -10,6 +10,26 @@ $button_size: 40px;
|
|
10
10
|
.character-editor {
|
11
11
|
&:focus { outline: 0;
|
12
12
|
}
|
13
|
+
&.character-editor-insert-enabled { padding: 20px 0;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
.character-editor-insert { position: absolute;
|
18
|
+
width: 20px;
|
19
|
+
height: 20px;
|
20
|
+
left: 0px;
|
21
|
+
top: 0px;
|
22
|
+
visibility: hidden;
|
23
|
+
cursor: pointer;
|
24
|
+
box-sizing: border-box;
|
25
|
+
z-index: 1;
|
26
|
+
i { width: 16px;
|
27
|
+
height: 16px;
|
28
|
+
margin-left: 2px;
|
29
|
+
margin-top: 2px;
|
30
|
+
}
|
31
|
+
&.visible { visibility: visible;
|
32
|
+
}
|
13
33
|
}
|
14
34
|
|
15
35
|
.character-editor-placeholder { position: relative;
|
@@ -53,7 +73,7 @@ $button_size: 40px;
|
|
53
73
|
cursor: pointer;
|
54
74
|
font-size: 14px;
|
55
75
|
text-decoration: none;
|
56
|
-
&:hover { background-color: $border_color;
|
76
|
+
&:hover { //background-color: $border_color;
|
57
77
|
color: #fff;
|
58
78
|
}
|
59
79
|
&:focus { outline: none;
|
@@ -75,7 +95,7 @@ $button_size: 40px;
|
|
75
95
|
}
|
76
96
|
input[type='text'] { display: inline;
|
77
97
|
padding: 6px;
|
78
|
-
height: $button_size
|
98
|
+
height: $button_size;
|
79
99
|
background-color: $bgcolor!important;
|
80
100
|
color: $link_color;
|
81
101
|
border: none;
|