dante-editor-seo 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +40 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +140 -0
  7. data/Procfile +1 -0
  8. data/README.md +187 -0
  9. data/ROADMAP.md +10 -0
  10. data/TODO.md +30 -0
  11. data/app/assets/fonts/dante/dante.eot +0 -0
  12. data/app/assets/fonts/dante/dante.svg +14 -0
  13. data/app/assets/fonts/dante/dante.ttf +0 -0
  14. data/app/assets/fonts/dante/dante.woff +0 -0
  15. data/app/assets/fonts/dante/fontello.eot +0 -0
  16. data/app/assets/fonts/dante/fontello.svg +36 -0
  17. data/app/assets/fonts/dante/fontello.ttf +0 -0
  18. data/app/assets/fonts/dante/fontello.woff +0 -0
  19. data/app/assets/images/dante/media-loading-placeholder.png +0 -0
  20. data/app/assets/javascripts/dante/dante.js.coffee.erb +10 -0
  21. data/app/assets/javascripts/dante/editor.js.coffee +1250 -0
  22. data/app/assets/javascripts/dante/menu.js.coffee +216 -0
  23. data/app/assets/javascripts/dante/popover.js.coffee +75 -0
  24. data/app/assets/javascripts/dante/tooltip.js.coffee +82 -0
  25. data/app/assets/javascripts/dante/tooltip_widget.js.coffee +10 -0
  26. data/app/assets/javascripts/dante/tooltip_widgets/embed.js.coffee +60 -0
  27. data/app/assets/javascripts/dante/tooltip_widgets/extract.js.coffee +64 -0
  28. data/app/assets/javascripts/dante/tooltip_widgets/uploader.js.coffee +248 -0
  29. data/app/assets/javascripts/dante/utils.js.coffee +235 -0
  30. data/app/assets/javascripts/dante/view.js.coffee +101 -0
  31. data/app/assets/javascripts/dante.js +12 -0
  32. data/app/assets/stylesheets/dante/_animations.scss +54 -0
  33. data/app/assets/stylesheets/dante/_caption.scss +52 -0
  34. data/app/assets/stylesheets/dante/_debug.scss +11 -0
  35. data/app/assets/stylesheets/dante/_fonts.scss +17 -0
  36. data/app/assets/stylesheets/dante/_graf.scss +238 -0
  37. data/app/assets/stylesheets/dante/_icons.scss +57 -0
  38. data/app/assets/stylesheets/dante/_media.scss +39 -0
  39. data/app/assets/stylesheets/dante/_menu.scss +153 -0
  40. data/app/assets/stylesheets/dante/_needsorder.scss +209 -0
  41. data/app/assets/stylesheets/dante/_popover.scss +134 -0
  42. data/app/assets/stylesheets/dante/_post.scss +69 -0
  43. data/app/assets/stylesheets/dante/_scaffold.scss +20 -0
  44. data/app/assets/stylesheets/dante/_tooltip.scss +131 -0
  45. data/app/assets/stylesheets/dante/_utilities.scss +55 -0
  46. data/app/assets/stylesheets/dante/_variables.scss +46 -0
  47. data/app/assets/stylesheets/dante.scss +18 -0
  48. data/bower.json +44 -0
  49. data/config.rb +86 -0
  50. data/config.ru +42 -0
  51. data/dante-editor.gemspec +19 -0
  52. data/dist/css/dante-editor.css +1116 -0
  53. data/dist/fonts/dante/dante.eot +0 -0
  54. data/dist/fonts/dante/dante.svg +14 -0
  55. data/dist/fonts/dante/dante.ttf +0 -0
  56. data/dist/fonts/dante/dante.woff +0 -0
  57. data/dist/fonts/dante/fontello.eot +0 -0
  58. data/dist/fonts/dante/fontello.svg +36 -0
  59. data/dist/fonts/dante/fontello.ttf +0 -0
  60. data/dist/fonts/dante/fontello.woff +0 -0
  61. data/dist/images/dante/media-loading-placeholder.png +0 -0
  62. data/dist/js/dante-editor.js +2878 -0
  63. data/lib/dante-editor/rails.rb +4 -0
  64. data/lib/dante-editor/version.rb +5 -0
  65. data/lib/dante-editor.rb +5 -0
  66. data/license.md +22 -0
  67. data/rakefile +2 -0
  68. data/source/assets/images/dante-editor-logo.png +0 -0
  69. data/source/assets/images/github-logo.png +0 -0
  70. data/source/assets/javascripts/all.js +3 -0
  71. data/source/assets/javascripts/dante-editor.js +1 -0
  72. data/source/assets/javascripts/deps.js +4 -0
  73. data/source/assets/javascripts/examples/custom_toolbar.js.coffee +30 -0
  74. data/source/assets/javascripts/spec.js +2 -0
  75. data/source/assets/javascripts/specs/cleaner.js.coffee +8 -0
  76. data/source/assets/javascripts/specs/dante_view.js.coffee +74 -0
  77. data/source/assets/javascripts/specs/editor.js.coffee +78 -0
  78. data/source/assets/stylesheets/_layout.scss +51 -0
  79. data/source/assets/stylesheets/_scaffold.scss +8 -0
  80. data/source/assets/stylesheets/_tooltips.scss +216 -0
  81. data/source/assets/stylesheets/all.css.scss +5 -0
  82. data/source/assets/stylesheets/dante-editor.css.scss +1 -0
  83. data/source/assets/stylesheets/normalize.css +375 -0
  84. data/source/custom_toolbar.erb +29 -0
  85. data/source/embeds.html.erb +27 -0
  86. data/source/icons/dante.json +143 -0
  87. data/source/icons/embed.svg +13 -0
  88. data/source/icons/image.svg +13 -0
  89. data/source/icons/plus.svg +13 -0
  90. data/source/icons/video.svg +13 -0
  91. data/source/index.html.erb +18 -0
  92. data/source/layouts/layout.erb +26 -0
  93. data/source/layouts/spec.html.erb +22 -0
  94. data/source/lists.html.erb +18 -0
  95. data/source/partials/_content.erb +6 -0
  96. data/source/partials/_example_1.erb +45 -0
  97. data/source/partials/_example_2.erb +32 -0
  98. data/source/partials/_example_3.erb +4 -0
  99. data/source/partials/_lists.erb +13 -0
  100. data/source/partials/_readme.markdown +24 -0
  101. data/source/partials/test/_example_1.erb +39 -0
  102. data/source/tests/dante_view.html.erb +11 -0
  103. data/source/tests/index.html.erb +39 -0
  104. data/tmp/.gitkeep +0 -0
  105. metadata +151 -0
@@ -0,0 +1,248 @@
1
+ utils = Dante.utils
2
+
3
+ class Dante.View.TooltipWidget.Uploader extends Dante.View.TooltipWidget
4
+
5
+ initialize: (opts={})->
6
+ #super
7
+ #@name = "menu-image"
8
+ @icon = opts.icon || "icon-image"
9
+ @title = opts.title || "Add an image"
10
+ @action = opts.action || "menu-image"
11
+ @current_editor = opts.current_editor
12
+
13
+ handleClick: (ev)->
14
+ @imageSelect(ev)
15
+
16
+ insertTemplate: ()->
17
+ "<figure contenteditable='false' class='graf graf--figure is-defaultValue' name='#{utils.generateUniqueName()}' tabindex='0'>
18
+ <div style='' class='aspectRatioPlaceholder is-locked'>
19
+ <div style='padding-bottom: 100%;' class='aspect-ratio-fill'></div>
20
+ <img src='' data-height='' data-width='' data-image-id='' class='graf-image' data-delayed-src=''>
21
+ </div>
22
+ <figcaption contenteditable='true' data-default-value='Type caption for image (optional)' class='imageCaption'>
23
+ <span class='defaultValue'>Type caption for image (optional)</span>
24
+ <br>
25
+ </figcaption>
26
+ </figure>"
27
+
28
+ #UPLOADER
29
+ #replace existing img tag , and wrap it in insertTamplate
30
+ #TODO: take the url and upload it
31
+ uploadExistentImage: (image_element, opts = {})->
32
+
33
+ utils.log ("process image here!")
34
+ tmpl = $(@insertTemplate())
35
+ tmpl.find("img").attr('src', @current_editor.default_loading_placeholder )
36
+ #is a child element or a first level element ?
37
+
38
+ if $(image_element).parents(".graf").length > 0
39
+ #return if its already wrapped in graf--figure
40
+ if $(image_element).parents(".graf").hasClass("graf--figure")
41
+ return
42
+ utils.log "UNO"
43
+ tmpl.insertBefore( $(image_element).parents(".graf") )
44
+ node = @current_editor.getNode()
45
+ if node
46
+ @current_editor.preCleanNode($(node))
47
+ @current_editor.addClassesToElement(node)
48
+ else
49
+ utils.log "DOS"
50
+ img = $(image_element).parentsUntil(".section-inner").first()
51
+ $(img).replaceWith(tmpl)
52
+
53
+ utils.log $("[name='#{tmpl.attr('name')}']").attr("name")
54
+ @replaceImg(image_element, $("[name='#{tmpl.attr('name')}']"))
55
+
56
+ #in case we found that graf--image is nested element, unwrap * nested times
57
+ n = $("[name='#{tmpl.attr('name')}']").parentsUntil(".section-inner").length
58
+ unless n is 0
59
+ for i in [0..n-1] by 1
60
+ $("[name='#{tmpl.attr('name')}']").unwrap()
61
+
62
+ utils.log "FIG"
63
+ #utils.log $("[name='#{tmpl.attr('name')}']").attr("name")
64
+
65
+ replaceImg: (image_element, figure)->
66
+ utils.log figure.attr("name")
67
+ utils.log figure
68
+ $(image_element).remove()
69
+ img = new Image()
70
+ img.src = image_element.src
71
+ self = this
72
+ img.onload = ()->
73
+ utils.log "replace image with loaded info"
74
+ utils.log figure.attr("name")
75
+ utils.log(this.width + 'x' + this.height);
76
+
77
+ ar = self.getAspectRatio(this.width, this.height)
78
+ #debugger
79
+ figure.find(".aspectRatioPlaceholder").css
80
+ 'max-width': ar.width
81
+ 'max-height': ar.height
82
+
83
+ figure.find(".graf-image").attr
84
+ "data-height": this.height
85
+ "data-width": this.width
86
+
87
+ figure.find(".aspect-ratio-fill").css
88
+ "padding-bottom": "#{ar.ratio}%"
89
+
90
+ #TODO: upload file to server
91
+ #@uploadFile file, replaced_node
92
+
93
+ figure.find("img").attr("src", image_element.src)
94
+
95
+ displayAndUploadImages: (file)->
96
+ @displayCachedImage file
97
+
98
+ imageSelect: (ev)->
99
+ $selectFile = $('<input type="file" multiple="multiple">').click()
100
+ self = @
101
+ $selectFile.change ()->
102
+ t = this
103
+ self.uploadFiles(t.files)
104
+
105
+ displayCachedImage: (file)->
106
+ @current_editor.tooltip_view.hide()
107
+
108
+ reader = new FileReader()
109
+ reader.onload = (e)=>
110
+ img = new Image
111
+ img.src = e.target.result
112
+ node = @current_editor.getNode()
113
+ self = this
114
+ img.onload = ()->
115
+ new_tmpl = $(self.insertTemplate())
116
+
117
+ replaced_node = $( new_tmpl ).insertBefore($(node))
118
+
119
+ img_tag = new_tmpl.find('img.graf-image').attr('src', e.target.result)
120
+ img_tag.height = this.height
121
+ img_tag.width = this.width
122
+
123
+ utils.log "UPLOADED SHOW FROM CACHE"
124
+
125
+ ar = self.getAspectRatio(this.width, this.height)
126
+
127
+ replaced_node.find(".aspectRatioPlaceholder").css
128
+ 'max-width': ar.width
129
+ 'max-height': ar.height
130
+
131
+ replaced_node.find(".graf-image").attr
132
+ "data-height": this.height
133
+ "data-width": this.width
134
+
135
+ replaced_node.find(".aspect-ratio-fill").css
136
+ "padding-bottom": "#{ar.ratio}%"
137
+
138
+ self.uploadFile file, replaced_node
139
+
140
+ reader.readAsDataURL(file)
141
+
142
+ getAspectRatio: (w , h)->
143
+ maxWidth = 700
144
+ maxHeight = 700
145
+ ratio = 0
146
+ width = w # Current image width
147
+ height = h # Current image height
148
+
149
+ # Check if the current width is larger than the max
150
+ if width > maxWidth
151
+ ratio = maxWidth / width # get ratio for scaling image
152
+ height = height * ratio # Reset height to match scaled image
153
+ width = width * ratio # Reset width to match scaled image
154
+
155
+ # Check if current height is larger than max
156
+ else if height > maxHeight
157
+ ratio = maxHeight / height # get ratio for scaling image
158
+ width = width * ratio # Reset width to match scaled image
159
+ height = height * ratio # Reset height to match scaled image
160
+
161
+ fill_ratio = height / width * 100
162
+ result = { width: width, height: height, ratio: fill_ratio }
163
+ utils.log result
164
+ result
165
+
166
+ formatData: (file, upload_params)->
167
+ formData = new FormData()
168
+ formData.append('file', file)
169
+ formData.append('upload_params', upload_params)
170
+ return formData
171
+
172
+ uploadFiles: (files)=>
173
+ acceptedTypes =
174
+ "image/png": true
175
+ "image/jpeg": true
176
+ "image/gif": true
177
+
178
+ i = 0
179
+ while i < files.length
180
+ file = files[i]
181
+ if acceptedTypes[file.type] is true
182
+ $(@placeholder).append "<progress class=\"progress\" min=\"0\" max=\"100\" value=\"0\">0</progress>"
183
+ @displayAndUploadImages(file)
184
+ i++
185
+
186
+ uploadFile: (file, node)=>
187
+ n = node
188
+ handleUp = (jqxhr)=>
189
+ @uploadCompleted jqxhr, n
190
+
191
+ $.ajax
192
+ type: "post"
193
+ url: @current_editor.upload_url
194
+ xhr: =>
195
+ xhr = new XMLHttpRequest()
196
+ xhr.upload.onprogress = @updateProgressBar
197
+ xhr
198
+ cache: false
199
+ contentType: false
200
+
201
+ success: (response) =>
202
+ response = @current_editor.upload_callback(response) if @current_editor.upload_callback
203
+ handleUp(response)
204
+ return
205
+ error: (jqxhr)=>
206
+ utils.log("ERROR: got error uploading file #{jqxhr.responseText}")
207
+
208
+ processData: false
209
+ data: @formatData(file, @upload_params)
210
+
211
+ updateProgressBar: (e)=>
212
+ $progress = $('.progress:first', this.$el)
213
+ complete = ""
214
+
215
+ if (e.lengthComputable)
216
+ complete = e.loaded / e.total * 100
217
+ complete = complete ? complete : 0
218
+ #$progress.attr('value', complete)
219
+ #$progress.html(complete)
220
+ utils.log "complete"
221
+ utils.log complete
222
+
223
+ uploadCompleted: (url, node)=>
224
+ node.find("img").attr("src", url)
225
+ #return false
226
+
227
+ ###
228
+ # Handles the behavior of deleting images when using the backspace key
229
+ #
230
+ # @param {Event} e - The backspace event that is being handled
231
+ # @param {Node} node - The node the backspace was used in, assumed to be from te editor's getNode() function
232
+ #
233
+ # @return {Boolean} true if this function handled the backspace event, otherwise false
234
+ ###
235
+ handleBackspaceKey: (e, node) =>
236
+
237
+ #remove graf figure is is selected but not in range (not focus on caption)
238
+ if $(".is-selected").hasClass("graf--figure") && !anchor_node?
239
+ utils.log("Replacing selected node")
240
+ @current_editor.replaceWith("p", $(".is-selected"))
241
+
242
+ e.preventDefault() #without this line, the browser may interpret the backspace as a "go pack a page" command
243
+
244
+ @current_editor.setRangeAt($(".is-selected")[0])
245
+ return true
246
+
247
+ return false
248
+
@@ -0,0 +1,235 @@
1
+ String.prototype.killWhiteSpace = ()->
2
+ this.replace(/\s/g, '')
3
+
4
+ String.prototype.reduceWhiteSpace = ()->
5
+ this.replace(/\s+/g, ' ')
6
+
7
+ utils = {}
8
+ window.Dante.utils = utils
9
+
10
+ utils.log = (message, force) ->
11
+ if (window.debugMode || force)
12
+ #console.log('%cDANTE DEBUGGER: %c' + message, 'font-family:arial,sans-serif;color:#1abf89;line-height:2em;', 'font-family:cursor,monospace;color:#333;');
13
+ #console.log('%cDANTE DEBUGGER: %c', 'font-family:arial,sans-serif;color:#1abf89;line-height:2em;', 'font-family:cursor,monospace;color:#333;');
14
+ console.log( message );
15
+
16
+ utils.getBase64Image = (img) ->
17
+ canvas = document.createElement("canvas")
18
+ canvas.width = img.width
19
+ canvas.height = img.height
20
+ ctx = canvas.getContext("2d")
21
+ ctx.drawImage img, 0, 0
22
+ dataURL = canvas.toDataURL("image/png")
23
+
24
+ # escape data:image prefix
25
+ # dataURL.replace /^data:image\/(png|jpg);base64,/, ""
26
+
27
+ # or just return dataURL
28
+ return dataURL
29
+
30
+ utils.generateUniqueName = ()->
31
+ Math.random().toString(36).slice(8)
32
+
33
+ #http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element
34
+ utils.saveSelection = ()->
35
+ if window.getSelection
36
+ sel = window.getSelection()
37
+ if sel.getRangeAt and sel.rangeCount
38
+ ranges = []
39
+ i = 0
40
+ len = sel.rangeCount
41
+
42
+ while i < len
43
+ ranges.push sel.getRangeAt(i)
44
+ ++i
45
+ return ranges
46
+ else return document.selection.createRange() if document.selection and document.selection.createRange
47
+ null
48
+
49
+ utils.restoreSelection = (savedSel) ->
50
+ if savedSel
51
+ if window.getSelection
52
+ sel = window.getSelection()
53
+ sel.removeAllRanges()
54
+ i = 0
55
+ len = savedSel.length
56
+
57
+ while i < len
58
+ sel.addRange savedSel[i]
59
+ ++i
60
+ else savedSel.select() if document.selection and savedSel.select
61
+ return
62
+
63
+ utils.getNode = ()->
64
+ range = undefined
65
+ sel = undefined
66
+ container = undefined
67
+ if document.selection and document.selection.createRange
68
+
69
+ # IE case
70
+ range = document.selection.createRange()
71
+ range.parentElement()
72
+ else if window.getSelection
73
+ sel = window.getSelection()
74
+ if sel.getRangeAt
75
+ range = sel.getRangeAt(0) if sel.rangeCount > 0
76
+ else
77
+
78
+ # Old WebKit selection object has no getRangeAt, so
79
+ # create a range from other selection properties
80
+ range = document.createRange()
81
+ range.setStart sel.anchorNode, sel.anchorOffset
82
+ range.setEnd sel.focusNode, sel.focusOffset
83
+
84
+ # Handle the case when the selection was selected backwards (from the end to the start in the document)
85
+ if range.collapsed isnt sel.isCollapsed
86
+ range.setStart sel.focusNode, sel.focusOffset
87
+ range.setEnd sel.anchorNode, sel.anchorOffset
88
+ if range
89
+ container = range.commonAncestorContainer
90
+
91
+ # Check if the container is a text node and return its parent if so
92
+ (if container.nodeType is 3 then container.parentNode else container)
93
+
94
+ #http://stackoverflow.com/questions/12603397/calculate-width-height-of-the-selected-text-javascript
95
+ utils.getSelectionDimensions = ->
96
+ sel = document.selection
97
+ range = undefined
98
+ width = 0
99
+ height = 0
100
+ left = 0
101
+ top = 0
102
+ if sel
103
+ unless sel.type is "Control"
104
+ range = sel.createRange()
105
+ width = range.boundingWidth
106
+ height = range.boundingHeight
107
+ else if window.getSelection
108
+ sel = window.getSelection()
109
+ if sel.rangeCount
110
+ range = sel.getRangeAt(0).cloneRange()
111
+ if range.getBoundingClientRect
112
+ rect = range.getBoundingClientRect()
113
+ width = rect.right - rect.left
114
+ height = rect.bottom - rect.top
115
+
116
+ width: width
117
+ height: height
118
+ top: rect.top
119
+ left: rect.left
120
+
121
+ #http://stackoverflow.com/questions/3972014/get-caret-position-in-contenteditable-div
122
+ utils.getCaretPosition = (editableDiv) ->
123
+ caretPos = 0
124
+ containerEl = null
125
+ sel = undefined
126
+ range = undefined
127
+ if window.getSelection
128
+ sel = window.getSelection()
129
+ if sel.rangeCount
130
+ range = sel.getRangeAt(0)
131
+ caretPos = range.endOffset if range.commonAncestorContainer.parentNode is editableDiv
132
+ else if document.selection and document.selection.createRange
133
+ range = document.selection.createRange()
134
+ if range.parentElement() is editableDiv
135
+ tempEl = document.createElement("span")
136
+ editableDiv.insertBefore tempEl, editableDiv.firstChild
137
+ tempRange = range.duplicate()
138
+ tempRange.moveToElementText tempEl
139
+ tempRange.setEndPoint "EndToEnd", range
140
+ caretPos = tempRange.text.length
141
+ caretPos
142
+
143
+ #http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
144
+ utils.isElementInViewport = (el) ->
145
+ #special bonus for those using jQuery
146
+ el = el[0] if typeof jQuery is "function" and el instanceof jQuery
147
+ rect = el.getBoundingClientRect()
148
+ #or $(window).height()
149
+ rect.top >= 0 and rect.left >= 0 and rect.bottom <= (window.innerHeight or document.documentElement.clientHeight) and rect.right <= (window.innerWidth or document.documentElement.clientWidth) #or $(window).width()
150
+
151
+ #http://brianmhunt.github.io/articles/taming-contenteditable/
152
+
153
+ LINE_HEIGHT = 20
154
+
155
+ is_caret_at_start_of_node = (node, range) ->
156
+ # See: http://stackoverflow.com/questions/7451468
157
+ pre_range = document.createRange()
158
+ pre_range.selectNodeContents(node)
159
+ pre_range.setEnd(range.startContainer, range.startOffset)
160
+ return pre_range.toString().trim().length == 0
161
+
162
+ is_caret_at_end_of_node = (node, range) ->
163
+ post_range = document.createRange()
164
+ post_range.selectNodeContents(node)
165
+ post_range.setStart(range.endContainer, range.endOffset)
166
+ return post_range.toString().trim().length == 0
167
+
168
+ $.fn.editableIsCaret = ->
169
+ return window.getSelection().type == 'Caret'
170
+ # alt test:
171
+ # return sel.rangeCount == 1 and sel.getRangeAt(0).collapsed
172
+
173
+ $.fn.editableRange = ->
174
+ # Return the range for the selection
175
+ sel = window.getSelection()
176
+ return unless sel.rangeCount > 0
177
+ return sel.getRangeAt(0)
178
+
179
+ $.fn.editableCaretRange = ->
180
+ return unless @editableIsCaret()
181
+ return @editableRange()
182
+
183
+ $.fn.editableSetRange = (range) ->
184
+ sel = window.getSelection()
185
+ sel.removeAllRanges() if sel.rangeCount > 0
186
+ sel.addRange(range)
187
+
188
+ $.fn.editableFocus = (at_start=true) ->
189
+ return unless @attr('contenteditable')
190
+ sel = window.getSelection()
191
+ sel.removeAllRanges() if sel.rangeCount > 0
192
+ range = document.createRange()
193
+ range.selectNodeContents(@[0])
194
+ range.collapse(at_start)
195
+ sel.addRange(range)
196
+
197
+ $.fn.editableCaretAtStart = ->
198
+ range = @editableRange()
199
+ return false unless range
200
+ return is_caret_at_start_of_node(@[0], range)
201
+
202
+ $.fn.editableCaretAtEnd = ->
203
+ range = @editableRange()
204
+ return false unless range
205
+ return is_caret_at_end_of_node(@[0], range)
206
+
207
+ $.fn.editableCaretOnFirstLine = ->
208
+ range = @editableRange()
209
+ return false unless range
210
+ # At the start of a node, the getClientRects() is [], so we have to
211
+ # use the getBoundingClientRect (which seems to work).
212
+ if is_caret_at_start_of_node(@[0], range)
213
+ return true
214
+ else if is_caret_at_end_of_node(@[0], range)
215
+ ctop = @[0].getBoundingClientRect().bottom - LINE_HEIGHT
216
+ else
217
+ ctop = range.getClientRects()[0].top
218
+ etop = @[0].getBoundingClientRect().top
219
+ return ctop < etop + LINE_HEIGHT
220
+
221
+ $.fn.editableCaretOnLastLine = ->
222
+ range = @editableRange()
223
+ return false unless range
224
+ if is_caret_at_end_of_node(@[0], range)
225
+ return true
226
+ else if is_caret_at_start_of_node(@[0], range)
227
+ # We are on the first line.
228
+ cbtm = @[0].getBoundingClientRect().top + LINE_HEIGHT
229
+ else
230
+ cbtm = range.getClientRects()[0].bottom
231
+ ebtm = @[0].getBoundingClientRect().bottom
232
+ return cbtm > ebtm - LINE_HEIGHT
233
+
234
+ $.fn.exists = ->
235
+ @.length > 0
@@ -0,0 +1,101 @@
1
+ #a very light backbone.view like version
2
+
3
+ class Dante.View
4
+
5
+ constructor: (opts = {})->
6
+ @el = opts.el if opts.el
7
+ @._ensureElement()
8
+ @initialize.apply(@, arguments)
9
+ @._ensureEvents()
10
+
11
+ initialize: (opts={})->
12
+
13
+ events: ->
14
+
15
+ render: ()->
16
+ return @
17
+
18
+ remove: ()->
19
+ @._removeElement()
20
+ @.stopListening()
21
+ return @
22
+
23
+ _removeElement: ()->
24
+ @.$el.remove();
25
+
26
+ setElement: (element)->
27
+ #@.undelegateEvents()
28
+ @._setElement(element)
29
+ #@.delegateEvents()
30
+ return @
31
+
32
+ setEvent: (opts)->
33
+ if !_.isEmpty(opts)
34
+ _.each opts, (f, key)=>
35
+ key_arr = key.split(" ")
36
+
37
+ if _.isFunction(f)
38
+ func = f
39
+ else if _.isString(f)
40
+ func = @[f]
41
+ else
42
+ throw "error event needs a function or string"
43
+
44
+ element = if key_arr.length > 1 then key_arr.splice(1 , 3).join(" ") else null
45
+
46
+ $( @el ).on( key_arr[0], element, _.bind(func, this) )
47
+
48
+ _ensureElement: ()->
49
+ @.setElement(_.result(@, 'el'))
50
+
51
+ _ensureEvents: ()->
52
+ @.setEvent(_.result(@, 'events'))
53
+
54
+ _setElement: (el)->
55
+ @.$el = if el instanceof $ then el else $(el)
56
+ @.el = @.$el[0]
57
+
58
+
59
+ # Helper function to correctly set up the prototype chain, for subclasses.
60
+ # Similar to `goog.inherits`, but uses a hash of prototype properties and
61
+ # class properties to be extended.
62
+
63
+ # This is borrowed from Backbone .extend function
64
+
65
+ extend = (protoProps, staticProps) ->
66
+ parent = this
67
+ child = undefined
68
+ # The constructor function for the new subclass is either defined by you
69
+ # (the "constructor" property in your `extend` definition), or defaulted
70
+ # by us to simply call the parent's constructor.
71
+ if protoProps and _.has(protoProps, 'constructor')
72
+ child = protoProps.constructor
73
+ else
74
+
75
+ child = ->
76
+ parent.apply this, arguments
77
+
78
+ # Add static properties to the constructor function, if supplied.
79
+ _.extend child, parent, staticProps
80
+ # Set the prototype chain to inherit from `parent`, without calling
81
+ # `parent`'s constructor function.
82
+
83
+ Surrogate = ->
84
+ @constructor = child
85
+ return
86
+
87
+ Surrogate.prototype = parent.prototype
88
+ child.prototype = new Surrogate
89
+ # Add prototype properties (instance properties) to the subclass,
90
+ # if supplied.
91
+ if protoProps
92
+ _.extend child.prototype, protoProps
93
+ # Set a convenience property in case the parent's prototype is needed
94
+ # later.
95
+ child.__super__ = parent.prototype
96
+ child
97
+
98
+ #Set up inheritance for the model, collection, router, view and history.
99
+ #Dante.View.extend = utils.extend;
100
+
101
+ Dante.View.extend = extend
@@ -0,0 +1,12 @@
1
+ //Editor components
2
+ //= require dante/dante
3
+ //= require dante/utils
4
+ //= require dante/view
5
+ //= require dante/editor
6
+ //= require dante/tooltip_widget
7
+ //= require dante/tooltip_widgets/uploader
8
+ //= require dante/tooltip_widgets/embed
9
+ //= require dante/tooltip_widgets/extract
10
+ //= require dante/tooltip
11
+ //= require dante/popover
12
+ //= require dante/menu
@@ -0,0 +1,54 @@
1
+ @-webkit-keyframes pop-upwards {
2
+ 0% {
3
+ -webkit-transform: matrix(.97, 0, 0, 1, 0, 12);
4
+ transform: matrix(.97, 0, 0, 1, 0, 12);
5
+ opacity: 0;
6
+ }
7
+ 20% {
8
+ -webkit-transform: matrix(.99, 0, 0, 1, 0, 2);
9
+ transform: matrix(.99, 0, 0, 1, 0, 2);
10
+ opacity: .7;
11
+ }
12
+ 40% {
13
+ -webkit-transform: matrix(1, 0, 0, 1, 0, -1);
14
+ transform: matrix(1, 0, 0, 1, 0, -1);
15
+ opacity: 1;
16
+ }
17
+ 70% {
18
+ -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
19
+ transform: matrix(1, 0, 0, 1, 0, 0);
20
+ opacity: 1;
21
+ }
22
+ 100% {
23
+ -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
24
+ transform: matrix(1, 0, 0, 1, 0, 0);
25
+ opacity: 1;
26
+ }
27
+ }
28
+ @keyframes pop-upward {
29
+ 0% {
30
+ -webkit-transform: matrix(.97, 0, 0, 1, 0, 12);
31
+ transform: matrix(.97, 0, 0, 1, 0, 12);
32
+ opacity: 0;
33
+ }
34
+ 20% {
35
+ -webkit-transform: matrix(.99, 0, 0, 1, 0, 2);
36
+ transform: matrix(.99, 0, 0, 1, 0, 2);
37
+ opacity: .7;
38
+ }
39
+ 40% {
40
+ -webkit-transform: matrix(1, 0, 0, 1, 0, -1);
41
+ transform: matrix(1, 0, 0, 1, 0, -1);
42
+ opacity: 1;
43
+ }
44
+ 70% {
45
+ -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
46
+ transform: matrix(1, 0, 0, 1, 0, 0);
47
+ opacity: 1;
48
+ }
49
+ 100% {
50
+ -webkit-transform: matrix(1, 0, 0, 1, 0, 0);
51
+ transform: matrix(1, 0, 0, 1, 0, 0);
52
+ opacity: 1;
53
+ }
54
+ }
@@ -0,0 +1,52 @@
1
+ .imageCaption {
2
+ & {
3
+ position: absolute;
4
+ left: -172px;
5
+ width: 150px;
6
+ top: 0;
7
+ text-align: right;
8
+ margin-top: 0;
9
+ font-family: "freight-text-pro",Georgia,Cambria,"Times New Roman",Times,serif;
10
+ letter-spacing: 0.01rem;
11
+ font-weight: 400;
12
+ font-style: italic;
13
+ font-size: 14px;
14
+ line-height: 1.4;
15
+ color: rgba(0,0,0,0.6);
16
+ outline: 0;
17
+ z-index: 300;
18
+ }
19
+ &:before {
20
+ width: 25%;
21
+ margin-left: 75%;
22
+ border-top: 1px solid rgba(0,0,0,0.15);
23
+ display: block;
24
+ content: "";
25
+ margin-bottom: 10px;
26
+ }
27
+ }
28
+ @media (max-width: 1200px) {
29
+ .imageCaption,
30
+ .postField--outsetCenterImage > .imageCaption {
31
+ position: relative;
32
+ width: 100%;
33
+ text-align: center;
34
+ left: 0;
35
+ margin-top: 10px;
36
+ }
37
+ .imageCaption:before {
38
+ display: none;
39
+ }
40
+ }
41
+
42
+ figure.is-defaultValue .imageCaption,
43
+ .graf--sectionCaption.is-defaultValue {
44
+ display: none;
45
+ }
46
+
47
+ .graf--figure.is-mediaFocused .imageCaption,
48
+ .graf--figure.is-defaultValue.is-selected .imageCaption,
49
+ section.is-mediaFocused .graf--sectionCaption,
50
+ .graf--sectionCaption.is-defaultValue.is-selected {
51
+ display: block;
52
+ }