dante-editor 0.0.10 → 0.0.11

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/app/assets/javascripts/dante.js +4 -0
  4. data/app/assets/javascripts/dante/editor.js.coffee +56 -25
  5. data/app/assets/javascripts/dante/tooltip.js.coffee +14 -304
  6. data/app/assets/javascripts/dante/tooltip_widget.js.coffee +10 -0
  7. data/app/assets/javascripts/dante/tooltip_widgets/embed.js.coffee +60 -0
  8. data/app/assets/javascripts/dante/tooltip_widgets/extract.js.coffee +64 -0
  9. data/app/assets/javascripts/dante/tooltip_widgets/uploader.js.coffee +224 -0
  10. data/app/assets/javascripts/dante/view.js.coffee +46 -1
  11. data/app/assets/stylesheets/{dante.css.scss → dante.scss} +0 -0
  12. data/bower.json +1 -1
  13. data/config.rb +2 -2
  14. data/dist/{0.0.10/css → css}/dante-editor.css +0 -0
  15. data/dist/{0.0.10/fonts → fonts}/dante/dante.eot +0 -0
  16. data/dist/{0.0.10/fonts → fonts}/dante/dante.svg +0 -0
  17. data/dist/{0.0.10/fonts → fonts}/dante/dante.ttf +0 -0
  18. data/dist/{0.0.10/fonts → fonts}/dante/dante.woff +0 -0
  19. data/dist/{0.0.10/fonts → fonts}/dante/fontello.eot +0 -0
  20. data/dist/{0.0.10/fonts → fonts}/dante/fontello.svg +0 -0
  21. data/dist/{0.0.10/fonts → fonts}/dante/fontello.ttf +0 -0
  22. data/dist/{0.0.10/fonts → fonts}/dante/fontello.woff +0 -0
  23. data/dist/{0.0.10/images → images}/dante/media-loading-placeholder.png +0 -0
  24. data/dist/{0.0.10/js → js}/dante-editor.js +355 -138
  25. data/lib/dante-editor/version.rb +1 -1
  26. data/source/assets/javascripts/examples/custom_toolbar.js.coffee +30 -0
  27. data/source/custom_toolbar.erb +29 -0
  28. data/source/layouts/layout.erb +1 -1
  29. metadata +20 -47
  30. data/dist/0.0.7/css/dante-editor.css +0 -1077
  31. data/dist/0.0.7/fonts/dante/dante.eot +0 -0
  32. data/dist/0.0.7/fonts/dante/dante.svg +0 -14
  33. data/dist/0.0.7/fonts/dante/dante.ttf +0 -0
  34. data/dist/0.0.7/fonts/dante/dante.woff +0 -0
  35. data/dist/0.0.7/fonts/dante/fontello.eot +0 -0
  36. data/dist/0.0.7/fonts/dante/fontello.svg +0 -36
  37. data/dist/0.0.7/fonts/dante/fontello.ttf +0 -0
  38. data/dist/0.0.7/fonts/dante/fontello.woff +0 -0
  39. data/dist/0.0.7/images/dante/media-loading-placeholder.png +0 -0
  40. data/dist/0.0.7/js/dante-editor.js +0 -2610
  41. data/dist/0.0.8/css/dante-editor.css +0 -1116
  42. data/dist/0.0.8/fonts/dante/dante.eot +0 -0
  43. data/dist/0.0.8/fonts/dante/dante.svg +0 -14
  44. data/dist/0.0.8/fonts/dante/dante.ttf +0 -0
  45. data/dist/0.0.8/fonts/dante/dante.woff +0 -0
  46. data/dist/0.0.8/fonts/dante/fontello.eot +0 -0
  47. data/dist/0.0.8/fonts/dante/fontello.svg +0 -36
  48. data/dist/0.0.8/fonts/dante/fontello.ttf +0 -0
  49. data/dist/0.0.8/fonts/dante/fontello.woff +0 -0
  50. data/dist/0.0.8/images/dante/media-loading-placeholder.png +0 -0
  51. data/dist/0.0.8/js/dante-editor.js +0 -2532
  52. data/dist/0.0.9/css/dante-editor.css +0 -1116
  53. data/dist/0.0.9/fonts/dante/dante.eot +0 -0
  54. data/dist/0.0.9/fonts/dante/dante.svg +0 -14
  55. data/dist/0.0.9/fonts/dante/dante.ttf +0 -0
  56. data/dist/0.0.9/fonts/dante/dante.woff +0 -0
  57. data/dist/0.0.9/fonts/dante/fontello.eot +0 -0
  58. data/dist/0.0.9/fonts/dante/fontello.svg +0 -36
  59. data/dist/0.0.9/fonts/dante/fontello.ttf +0 -0
  60. data/dist/0.0.9/fonts/dante/fontello.woff +0 -0
  61. data/dist/0.0.9/images/dante/media-loading-placeholder.png +0 -0
  62. data/dist/0.0.9/js/dante-editor.js +0 -2575
@@ -0,0 +1,10 @@
1
+ class Dante.View.TooltipWidget extends Dante.View
2
+
3
+ initialize: (opts={})->
4
+ @icon = opts.icon
5
+ @title = opts.title
6
+ @actionEvent = opts.title
7
+
8
+ hide: ()=>
9
+ @.current_editor.tooltip_view.hide()
10
+
@@ -0,0 +1,60 @@
1
+ utils = Dante.utils
2
+
3
+ class Dante.View.TooltipWidget.Embed extends Dante.View.TooltipWidget
4
+
5
+ initialize: (opts={})->
6
+ @icon = opts.icon || "icon-video"
7
+ @title = opts.title || "Add a video"
8
+ @action = opts.action || "embed"
9
+ @current_editor = opts.current_editor
10
+
11
+ handleClick: (ev)->
12
+ @displayEmbedPlaceHolder(ev)
13
+
14
+ handleEnterKey: (ev, $node)->
15
+ if $node.hasClass("is-embedable")
16
+ @getEmbedFromNode($node);
17
+
18
+ embedTemplate: ()->
19
+ "<figure contenteditable='false' class='graf--figure graf--iframe graf--first' name='504e' tabindex='0'>
20
+ <div class='iframeContainer'>
21
+ <iframe frameborder='0' width='700' height='393' data-media-id='' src='' data-height='480' data-width='854'>
22
+ </iframe>
23
+ </div>
24
+ <figcaption contenteditable='true' data-default-value='Type caption for embed (optional)' class='imageCaption'>
25
+ <a rel='nofollow' class='markup--anchor markup--figure-anchor' data-href='' href='' target='_blank'>
26
+
27
+ </a>
28
+ </figcaption>
29
+ </figure>"
30
+
31
+ displayEmbedPlaceHolder: ()->
32
+ ph = @current_editor.embed_placeholder
33
+ @node = @current_editor.getNode()
34
+ $(@node).html(ph).addClass("is-embedable")
35
+
36
+ @current_editor.setRangeAt(@node)
37
+ @hide()
38
+ false
39
+
40
+ getEmbedFromNode: (node)=>
41
+ @node = $(node)
42
+ @node_name = @node.attr("name")
43
+ @node.addClass("spinner")
44
+
45
+ $.getJSON("#{@current_editor.oembed_url}#{$(@node).text()}")
46
+ .success (data)=>
47
+ @node = $("[name=#{@node_name}]")
48
+ iframe_src = $(data.html).prop("src")
49
+ tmpl = $(@embedTemplate())
50
+ tmpl.attr("name", @node.attr("name"))
51
+ $(@node).replaceWith(tmpl)
52
+ replaced_node = $(".graf--iframe[name=#{@node.attr("name")}]")
53
+ replaced_node.find("iframe").attr("src", iframe_src)
54
+ url = data.url || data.author_url
55
+ utils.log "URL IS #{url}"
56
+ replaced_node.find(".markup--anchor").attr("href", url ).text(url)
57
+ @hide()
58
+ .error (res)=>
59
+ @node.removeClass("spinner")
60
+
@@ -0,0 +1,64 @@
1
+ utils = Dante.utils
2
+
3
+ class Dante.View.TooltipWidget.EmbedExtract extends Dante.View.TooltipWidget
4
+
5
+ initialize: (opts={})->
6
+ @icon = opts.icon || "icon-embed"
7
+ @title = opts.title || "Add an embed"
8
+ @action = opts.action || "embed-extract"
9
+ @current_editor = opts.current_editor
10
+
11
+ handleClick: (ev)->
12
+ @displayExtractPlaceHolder(ev)
13
+
14
+ handleEnterKey: (ev, $node)->
15
+ if $node.hasClass("is-extractable")
16
+ @getExtractFromNode($node)
17
+
18
+ extractTemplate: ()->
19
+ "<div class='graf graf--mixtapeEmbed is-selected' name=''>
20
+ <a target='_blank' data-media-id='' class='js-mixtapeImage mixtapeImage mixtapeImage--empty u-ignoreBlock' href=''>
21
+ </a>
22
+ <a data-tooltip-type='link' data-tooltip-position='bottom' data-tooltip='' title='' class='markup--anchor markup--mixtapeEmbed-anchor' data-href='' href='' target='_blank'>
23
+ <strong class='markup--strong markup--mixtapeEmbed-strong'></strong>
24
+ <em class='markup--em markup--mixtapeEmbed-em'></em>
25
+ </a>
26
+ </div>"
27
+
28
+ displayExtractPlaceHolder: ()->
29
+ ph = @current_editor.extract_placeholder
30
+ @node = @current_editor.getNode()
31
+ $(@node).html(ph).addClass("is-extractable")
32
+
33
+ @current_editor.setRangeAt(@node)
34
+ @hide()
35
+ false
36
+
37
+ getExtractFromNode: (node)=>
38
+ @node = $(node)
39
+ @node_name = @node.attr("name")
40
+ @node.addClass("spinner")
41
+
42
+ $.getJSON("#{@current_editor.extract_url}#{$(@node).text()}")
43
+ .success (data)=>
44
+ @node = $("[name=#{@node_name}]")
45
+ iframe_src = $(data.html).prop("src")
46
+ tmpl = $(@extractTemplate())
47
+ tmpl.attr("name", @node.attr("name"))
48
+ $(@node).replaceWith(tmpl)
49
+ replaced_node = $(".graf--mixtapeEmbed[name=#{@node.attr("name")}]")
50
+ replaced_node.find("strong").text(data.title)
51
+ replaced_node.find("em").text(data.description)
52
+ replaced_node.append(data.provider_url)
53
+ replaced_node.find(".markup--anchor").attr("href", data.url )
54
+ unless _.isEmpty data.images
55
+ image_node = replaced_node.find(".mixtapeImage")
56
+ image_node.css("background-image", "url(#{data.images[0].url})")
57
+ image_node.removeClass("mixtapeImage--empty u-ignoreBlock")
58
+ @hide()
59
+ .error (data)=>
60
+ @node.removeClass("spinner")
61
+
62
+ getExtract: (url)=>
63
+ $.getJSON("#{@current_editor.extract_url}#{url}").done (data)->
64
+ utils.log(data)
@@ -0,0 +1,224 @@
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)->
167
+ formData = new FormData()
168
+ formData.append('file', file)
169
+ return formData
170
+
171
+ uploadFiles: (files)=>
172
+ acceptedTypes =
173
+ "image/png": true
174
+ "image/jpeg": true
175
+ "image/gif": true
176
+
177
+ i = 0
178
+ while i < files.length
179
+ file = files[i]
180
+ if acceptedTypes[file.type] is true
181
+ $(@placeholder).append "<progress class=\"progress\" min=\"0\" max=\"100\" value=\"0\">0</progress>"
182
+ @displayAndUploadImages(file)
183
+ i++
184
+
185
+ uploadFile: (file, node)=>
186
+ n = node
187
+ handleUp = (jqxhr)=>
188
+ @uploadCompleted jqxhr, n
189
+
190
+ $.ajax
191
+ type: "post"
192
+ url: @current_editor.upload_url
193
+ xhr: =>
194
+ xhr = new XMLHttpRequest()
195
+ xhr.upload.onprogress = @updateProgressBar
196
+ xhr
197
+ cache: false
198
+ contentType: false
199
+
200
+ success: (response) =>
201
+ response = @current_editor.upload_callback(response) if @current_editor.upload_callback
202
+ handleUp(response)
203
+ return
204
+ error: (jqxhr)=>
205
+ utils.log("ERROR: got error uploading file #{jqxhr.responseText}")
206
+
207
+ processData: false
208
+ data: @formatData(file)
209
+
210
+ updateProgressBar: (e)=>
211
+ $progress = $('.progress:first', this.$el)
212
+ complete = ""
213
+
214
+ if (e.lengthComputable)
215
+ complete = e.loaded / e.total * 100
216
+ complete = complete ? complete : 0
217
+ #$progress.attr('value', complete)
218
+ #$progress.html(complete)
219
+ utils.log "complete"
220
+ utils.log complete
221
+
222
+ uploadCompleted: (url, node)=>
223
+ node.find("img").attr("src", url)
224
+ #return false
@@ -53,4 +53,49 @@ class Dante.View
53
53
 
54
54
  _setElement: (el)->
55
55
  @.$el = if el instanceof $ then el else $(el)
56
- @.el = @.$el[0]
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
data/bower.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name" : "dante",
3
3
  "description": "Just another Medium editor clone.",
4
4
  "homepage": "michelson.github.io/Dante/",
5
- "version" : "0.0.10",
5
+ "version" : "0.0.11",
6
6
  "keywords": [
7
7
  "css",
8
8
  "sass",
data/config.rb CHANGED
@@ -7,8 +7,8 @@ class DistBuilder < Middleman::Extension
7
7
 
8
8
  app.after_build do |builder|
9
9
  app.config[:dist_dir] = "dist"
10
-
11
- base_dist_path = File.join(app.config[:dist_dir], DanteEditor::VERSION)
10
+ FileUtils.rm_rf Dir.glob("#{app.config[:dist_dir]}/*")
11
+ base_dist_path = app.config[:dist_dir]
12
12
  dist_fonts_path = File.join(base_dist_path, "fonts", "dante")
13
13
  dist_images_path = File.join(base_dist_path, "images", "dante")
14
14
  dist_js_path = File.join(base_dist_path, "js")