dante-editor 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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")