dante-editor 0.0.1

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +23 -0
  5. data/Gemfile.lock +146 -0
  6. data/Procfile +1 -0
  7. data/README.md +129 -0
  8. data/TODO.md +45 -0
  9. data/bower.json +10 -0
  10. data/config.rb +82 -0
  11. data/config.ru +31 -0
  12. data/dante-editor.gemspec +19 -0
  13. data/lib/dante-editor.rb +3 -0
  14. data/lib/dante-editor/version.rb +5 -0
  15. data/license.md +22 -0
  16. data/rakefile +2 -0
  17. data/source/assets/fonts/fontello.eot +0 -0
  18. data/source/assets/fonts/fontello.svg +36 -0
  19. data/source/assets/fonts/fontello.ttf +0 -0
  20. data/source/assets/fonts/fontello.woff +0 -0
  21. data/source/assets/images/background.png +0 -0
  22. data/source/assets/images/icon-logo.png +0 -0
  23. data/source/assets/images/icon.png +0 -0
  24. data/source/assets/images/media-loading-placeholder.png +0 -0
  25. data/source/assets/images/middleman.png +0 -0
  26. data/source/assets/javascripts/all.js +3 -0
  27. data/source/assets/javascripts/dante.js +7 -0
  28. data/source/assets/javascripts/dante/dante.js.coffee.erb +7 -0
  29. data/source/assets/javascripts/dante/editor.js.coffee +917 -0
  30. data/source/assets/javascripts/dante/menu.js.coffee +202 -0
  31. data/source/assets/javascripts/dante/tooltip.js.coffee +302 -0
  32. data/source/assets/javascripts/dante/utils.js.coffee +235 -0
  33. data/source/assets/javascripts/dante/view.js.coffee +56 -0
  34. data/source/assets/javascripts/deps.js +4 -0
  35. data/source/assets/javascripts/spec.js +2 -0
  36. data/source/assets/javascripts/specs/cleaner.js.coffee +8 -0
  37. data/source/assets/javascripts/specs/dante_view.js.coffee +74 -0
  38. data/source/assets/javascripts/specs/editor.js.coffee +57 -0
  39. data/source/assets/stylesheets/all.css.scss +4 -0
  40. data/source/assets/stylesheets/dante.css.scss +3 -0
  41. data/source/assets/stylesheets/dante/base.css.scss +57 -0
  42. data/source/assets/stylesheets/dante/editor.css.scss +662 -0
  43. data/source/assets/stylesheets/dante/fonts.css.scss +106 -0
  44. data/source/assets/stylesheets/normalize.css +375 -0
  45. data/source/embeds.html.erb +29 -0
  46. data/source/index.html.erb +28 -0
  47. data/source/layouts/layout.erb +21 -0
  48. data/source/layouts/spec.html.erb +24 -0
  49. data/source/partials/_example_1.erb +30 -0
  50. data/source/partials/_example_2.erb +33 -0
  51. data/source/partials/_example_3.erb +17 -0
  52. data/source/partials/_readme.markdown +78 -0
  53. data/source/partials/test/_example_1.erb +18 -0
  54. data/source/readme.html.erb +28 -0
  55. data/source/tests/dante_view.html.erb +11 -0
  56. data/source/tests/index.html.erb +32 -0
  57. data/tmp/.gitkeep +0 -0
  58. metadata +99 -0
data/config.ru ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'middleman/rack'
3
+
4
+ class UploadServer < Sinatra::Base
5
+
6
+ use Rack::Static, :urls => ["/images"], :root => "tmp"
7
+ # Info
8
+ get "/info" do
9
+ "Dante Upload server, hello!"
10
+ end
11
+
12
+ # Handle POST-request (Receive and save the uploaded file)
13
+ post "/new.?:format?" do
14
+
15
+ name = [Time.now.to_i , params['file'][:filename]].join("-")
16
+ path = File.join(File.dirname(__FILE__), 'tmp/images', name)
17
+ File.open(path, "wb") do |f|
18
+ f.write(params['file'][:tempfile].read)
19
+ end
20
+
21
+ return "/uploads/images/#{name}"
22
+ end
23
+
24
+ end
25
+
26
+
27
+ #Mounts upload server & middleman app
28
+ run Rack::URLMap.new(
29
+ "/" => Middleman.server,
30
+ "/uploads" => UploadServer.new
31
+ )
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dante-editor/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "dante-editor"
8
+ gem.version = DanteEditor::VERSION
9
+ gem.authors = ["Miguel Michelson"]
10
+ gem.email = ["miguelmichelson@gmail.com"]
11
+ gem.description = %q{dante-editor yet another Medium editor clone.}
12
+ gem.summary = %q{dante-editor yet another Medium editor clone.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,3 @@
1
+ require "dante-editor/version"
2
+ module DanteEditor
3
+ end
@@ -0,0 +1,5 @@
1
+ require "dante-editor/version"
2
+
3
+ module DanteEditor
4
+ VERSION = "0.0.1"
5
+ end
data/license.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Miguel Michelson
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'middleman-gh-pages'
2
+ require "bundler/gem_tasks"
Binary file
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Copyright (C) 2012 by original authors @ fontello.com</metadata>
5
+ <defs>
6
+ <font id="fontello" horiz-adv-x="1000" >
7
+ <font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
8
+ <missing-glyph horiz-adv-x="1000" />
9
+ <glyph glyph-name="location" unicode="&#xe815;" d="M429 493q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m143 0q0-61-18-100l-203-432q-9-18-27-29t-38-11-38 11-26 29l-204 432q-18 39-18 100 0 118 84 202t202 84 202-84 84-202z" horiz-adv-x="571.429" />
10
+ <glyph glyph-name="fit" unicode="&#xe80f;" d="M429 314l0-250q0-15-11-25t-25-11-25 11l-80 80-185-185q-6-6-13-6t-13 6l-64 64q-6 6-6 13t6 13l185 185-80 80q-11 11-11 25t11 25 25 11l250 0q15 0 25-11t11-25z m421 375q0-7-6-13l-185-185 80-80q11-11 11-25t-11-25-25-11l-250 0q-15 0-25 11t-11 25l0 250q0 15 11 25t25 11 25-11l80-80 185 185q6 6 13 6t13-6l64-64q6-6 6-13z" horiz-adv-x="857.143" />
11
+ <glyph glyph-name="bold" unicode="&#xe805;" d="M310 1q42-18 78-18 73 0 121 23t68 63q21 39 21 101 0 64-23 100-32 52-79 70-45 18-138 18-41 0-56-6l0-80-1-97 2-151q0-8 7-25z m-8 416q24-4 61-4 98 0 147 36t50 125q0 62-47 104t-142 42q-29 0-73-7 0-25 1-43 4-68 3-156l-1-55q0-24 1-43z m-302-496l1 52q25 5 38 7 43 7 69 17 9 15 12 28 5 37 5 108l-1 277q-3 143-5 225-1 49-6 61-1 2-7 7-10 7-39 8-17 1-64 7l-2 46 145 3 212 7 25 1q3 0 8 0t8 0q1 0 12 0t23 0l41 0q49 0 107-15 24-7 54-22 32-16 57-42t36-58 12-68q0-39-18-71t-53-59q-15-11-84-43 99-23 149-81 51-59 51-132 0-42-16-90-12-35-40-65-37-40-78-60t-113-33q-46-8-110-6l-110 2q-47 1-166-6-18-2-152-6z" horiz-adv-x="785.714" />
12
+ <glyph glyph-name="italic" unicode="&#xe806;" d="M0-77l9 47q2 1 43 11 42 11 65 22 16 21 23 56l15 78 31 150 7 36q4 25 9 47t9 37 7 26 5 17 2 6l16 88 9 35 12 75 4 28 0 21q-23 12-80 16-16 1-21 2l11 57 177-8q22-1 41-1 37 0 119 5 18 1 38 3t20 1q-1-11-3-21-4-16-7-28-31-11-61-17-36-9-56-17-7-17-13-49-5-25-7-46-25-111-37-171l-34-174-21-88-24-131-7-25q-1-4 1-15 36-8 66-12 20-3 37-6-1-16-4-32-4-17-5-23-10 0-13-1-13-1-23-1-5 0-16 2t-81 9l-110 1q-23 1-97-6-41-4-55-5z" horiz-adv-x="571.429" />
13
+ <glyph glyph-name="justifyleft" unicode="&#xe80a;" d="M1000 100l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m-214 214l0-71q0-15-11-25t-25-11l-714 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l714 0q15 0 25-11t11-25z m143 214l0-71q0-15-11-25t-25-11l-857 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l857 0q15 0 25-11t11-25z m-214 214l0-71q0-15-11-25t-25-11l-643 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l643 0q15 0 25-11t11-25z" horiz-adv-x="1000" />
14
+ <glyph glyph-name="justifycenter" unicode="&#xe80b;" d="M1000 100l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m-214 214l0-71q0-15-11-25t-25-11l-500 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l500 0q15 0 25-11t11-25z m143 214l0-71q0-15-11-25t-25-11l-786 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l786 0q15 0 25-11t11-25z m-214 214l0-71q0-15-11-25t-25-11l-357 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l357 0q15 0 25-11t11-25z" horiz-adv-x="1000" />
15
+ <glyph glyph-name="justifyright" unicode="&#xe80c;" d="M1000 100l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-714 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l714 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-857 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l857 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-643 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l643 0q15 0 25-11t11-25z" horiz-adv-x="1000" />
16
+ <glyph glyph-name="justifyfull" unicode="&#xe80d;" d="M1000 100l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z m0 214l0-71q0-15-11-25t-25-11l-929 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l929 0q15 0 25-11t11-25z" horiz-adv-x="1000" />
17
+ <glyph glyph-name="outdent" unicode="&#xe800;" d="M214 546l0-321q0-7-5-13t-13-5q-8 0-13 5l-161 161q-5 5-5 13t5 13l161 161q5 5 13 5 7 0 13-5t5-13z m786-429l0-107q0-7-5-13t-13-5l-964 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l964 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-607 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l607 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-607 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l607 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-964 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l964 0q7 0 13-5t5-13z" horiz-adv-x="1000" />
18
+ <glyph glyph-name="indent" unicode="&#xe801;" d="M196 386q0-8-5-13l-161-161q-5-5-13-5-7 0-13 5t-5 13l0 321q0 7 5 13t13 5q8 0 13-5l161-161q5-5 5-13z m804-268l0-107q0-7-5-13t-13-5l-964 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l964 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-607 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l607 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-607 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l607 0q7 0 13-5t5-13z m0 214l0-107q0-7-5-13t-13-5l-964 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l964 0q7 0 13-5t5-13z" horiz-adv-x="1000" />
19
+ <glyph glyph-name="mode" unicode="&#xe813;" d="M429 46l0 607q-83 0-152-41t-110-110-41-152 41-152 110-110 152-41z m429 304q0-117-57-215t-156-156-215-57-215 57-156 156-57 215 57 215 156 156 215 57 215-57 156-156 57-215z" horiz-adv-x="857.143" />
20
+ <glyph glyph-name="fullscreen" unicode="&#xe80e;" d="M716 548l-198-198 198-198 80 80q16 17 39 8 22-9 22-33l0-250q0-15-11-25t-25-11l-250 0q-23 0-33 22-9 22 8 39l80 80-198 198-198-198 80-80q17-17 8-39t-33-22l-250 0q-15 0-25 11t-11 25l0 250q0 23 22 33 22 9 39-8l80-80 198 198-198 198-80-80q-11-11-25-11-7 0-13 3-22 9-22 33l0 250q0 15 11 25t25 11l250 0q23 0 33-22 9-22-8-39l-80-80 198-198 198 198-80 80q-17 17-8 39t33 22l250 0q15 0 25-11t11-25l0-250q0-23-22-33-7-3-14-3-15 0-25 11z" horiz-adv-x="857.143" />
21
+ <glyph glyph-name="insertunorderedlist" unicode="&#xe802;" d="M214 64q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m0 286q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l679 0q7 0 13-5t5-13z m-786 518q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l679 0q7 0 13-5t5-13z m0 286l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l679 0q7 0 13-5t5-13z" horiz-adv-x="1000" />
22
+ <glyph glyph-name="insertorderedlist" unicode="&#xe803;" d="M213-54q0-45-30-70t-76-26q-59 0-96 37l32 49q27-25 59-25 16 0 28 8t12 24q0 36-59 31l-15 31q4 6 18 24t24 30 21 21l0 1q-9 0-27-1t-27-1l0-30-59 0 0 85 186 0 0-49-53-64q28-7 45-27t17-49z m1 350l0-89-202 0q-3 20-3 30 0 28 13 52t32 38 37 27 32 24 13 25q0 14-8 21t-22 8q-26 0-45-32l-47 33q13 28 40 44t59 16q41 0 69-23t28-63q0-28-19-51t-42-36-42-28-20-29l71 0 0 33 59 0z m786-178l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 8 5 13t13 5l679 0q7 0 13-5t5-13z m-786 502l0-55-187 0 0 55 60 0q0 23 0 68t0 68l0 7-1 0q-4-9-28-30l-40 42 76 71 59 0 0-225 60 0z m786-216l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 8 5 13t13 5l679 0q7 0 13-5t5-13z m0 286l0-107q0-7-5-13t-13-5l-679 0q-7 0-13 5t-5 13l0 107q0 7 5 13t13 5l679 0q7 0 13-5t5-13z" horiz-adv-x="1000" />
23
+ <glyph glyph-name="strikethrough" unicode="&#xe807;" d="M982 350q8 0 13-5t5-13l0-36q0-8-5-13t-13-5l-964 0q-8 0-13 5t-5 13l0 36q0 8 5 13t13 5l964 0z m-713 36q-16 20-28 45-27 54-27 105 0 101 75 172 74 71 219 71 28 0 93-11 37-7 99-27 6-21 12-66 8-69 8-102 0-10-3-25l-7-2-47 3-8 1q-28 83-57 114-49 51-117 51-64 0-102-33-37-32-37-81 0-41 37-78t156-72q39-11 97-37 32-16 53-29l-415 0z m283-143l229 0q4-22 4-51 0-62-23-118-13-31-40-58-21-20-61-45-45-27-85-37-45-12-113-12-64 0-109 13l-78 22q-32 9-40 16-4 4-4 12l0 7q0 60-1 87-1 17 0 38l1 21 0 25 57 1q8-19 17-40t13-31 7-15q20-32 45-52 24-20 59-32 33-12 74-12 36 0 78 15 43 15 68 48 26 34 26 72 0 47-45 88-19 16-76 40z" horiz-adv-x="1000" />
24
+ <glyph glyph-name="underline" unicode="&#xe804;" d="M27 726q-21 1-25 2l-2 49q7 1 22 1 33 0 62-2 74-4 93-4 48 0 94 2 65 2 81 3 31 0 48 1l-1-8 1-36 0-5q-33-5-69-5-33 0-44-14-7-8-7-74 0-7 0-18t0-14l1-128 8-156q3-69 28-113 20-33 54-51 49-26 99-26 58 0 107 16 31 10 55 28 27 20 36 36 20 31 30 64 12 41 12 128 0 44-2 71t-6 68-8 89l-2 33q-3 37-13 49-19 20-43 19l-56-1-8 2 1 48 47 0 114-6q42-2 109 6l10-1q3-21 3-28 0-4-2-17-25-7-47-7-41-6-44-9-8-8-8-23 0-4 1-15t1-17q4-11 12-221 3-109-8-170-8-42-23-68-21-36-62-69-42-32-102-50-61-18-142-18-93 0-158 26-66 26-100 68t-46 109q-9 45-9 132l0 186q0 105-9 119-14 20-82 22z m830-786l0 36q0 8-5 13t-13 5l-821 0q-8 0-13-5t-5-13l0-36q0-8 5-13t13-5l821 0q8 0 13 5t5 13z" horiz-adv-x="857.143" />
25
+ <glyph glyph-name="blockquote" unicode="&#xe814;" d="M429 671l0-393q0-58-23-111t-61-91-91-61-111-23l-36 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l36 0q59 0 101 42t42 101l0 18q0 22-16 38t-38 16l-125 0q-45 0-76 31t-31 76l0 214q0 45 31 76t76 31l214 0q45 0 76-31t31-76z m500 0l0-393q0-58-23-111t-61-91-91-61-111-23l-36 0q-15 0-25 11t-11 25l0 71q0 15 11 25t25 11l36 0q59 0 101 42t42 101l0 18q0 22-16 38t-38 16l-125 0q-45 0-76 31t-31 76l0 214q0 45 31 76t76 31l214 0q45 0 76-31t31-76z" horiz-adv-x="928.571" />
26
+ <glyph glyph-name="undo" unicode="&#xe817;" d="M1000 225q0-93-71-252-2-4-6-13t-8-17-7-12q-7-9-16-9-8 0-13 6t-5 14q0 5 1 15t1 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3l-125 0 0-143q0-15-11-25t-25-11-25 11l-286 286q-11 11-11 25t11 25l286 286q11 11 25 11t25-11 11-25l0-143 125 0q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
27
+ <glyph glyph-name="code" unicode="&#xe816;" d="M344 69l-28-28q-6-6-13-6t-13 6l-260 260q-6 6-6 13t6 13l260 260q6 6 13 6t13-6l28-28q6-6 6-13t-6-13l-219-219 219-219q6-6 6-13t-6-13z m330 595l-208-720q-2-7-9-11t-13-1l-35 9q-7 2-11 9t-1 14l208 720q2 7 9 11t13 1l35-9q7-2 11-9t1-14z m367-363l-260-260q-6-6-13-6t-13 6l-28 28q-6 6-6 13t6 13l219 219-219 219q-6 6-6 13t6 13l28 28q6 6 13 6t13-6l260-260q6-6 6-13t-6-13z" horiz-adv-x="1071.429" />
28
+ <glyph glyph-name="unlink" unicode="&#xe811;" d="M245 141l-143-143q-6-5-13-5t-13 5q-5 6-5 13t5 13l143 143q6 5 13 5t13-5q5-6 5-13t-5-13z m94-23l0-179q0-8-5-13t-13-5-13 5-5 13l0 179q0 8 5 13t13 5 13-5 5-13z m-125 125q0-8-5-13t-13-5l-179 0q-8 0-13 5t-5 13 5 13 13 5l179 0q8 0 13-5t5-13z m705-71q0-67-47-113l-82-81q-46-46-113-46-68 0-114 47l-186 187q-12 12-23 31l133 10 152-153q15-15 38-15t38 15l82 81q16 16 16 37 0 22-16 38l-153 153 10 133q20-12 31-23l187-187q47-48 47-114z m-344 404l-133-10-152 153q-16 16-38 16t-38-15l-82-81q-16-16-16-37 0-22 16-38l153-153-10-134q-20 12-31 23l-187 187q-47 48-47 114 0 67 47 113l82 81q46 46 113 46 68 0 114-47l186-187q12-12 23-31z m353-47q0-8-5-13t-13-5l-179 0q-8 0-13 5t-5 13 5 13 13 5l179 0q8 0 13-5t5-13z m-304 304l0-179q0-8-5-13t-13-5-13 5-5 13l0 179q0 8 5 13t13 5 13-5 5-13z m227-84l-143-143q-6-5-13-5t-13 5q-5 6-5 13t5 13l143 143q6 5 13 5t13-5q5-6 5-13t-5-13z" horiz-adv-x="928.571" />
29
+ <glyph glyph-name="superscript" unicode="&#xe808;" d="M501 86l0-93-138 0-89 141-13 23q-4 5-6 12l-2 0-5-12q-6-11-14-25l-86-140-144 0 0 93 71 0 110 162-103 152-76 0 0 94 154 0 78-127q1-2 13-23 4-5 6-12l2 0q2 5 6 12l14 23 78 127 143 0 0-94-70 0-103-149 114-165 61 0z m355 379l0-115-287 0-2 15q-2 16-2 26 0 36 15 65t36 48 47 36 47 30 36 30 15 36q0 21-16 35t-39 14q-28 0-54-22-8-6-20-21l-59 51q15 21 35 37 46 36 105 36 61 0 99-33t38-88q0-31-14-57t-35-43-45-33-46-28-37-29-17-35l129 0 0 45 70 0z" horiz-adv-x="857.143" />
30
+ <glyph glyph-name="subscript" unicode="&#xe809;" d="M501 86l0-93-138 0-89 141-13 23q-4 5-6 12l-2 0-5-12q-6-11-14-25l-86-140-144 0 0 93 71 0 110 162-103 152-76 0 0 94 154 0 78-127q1-2 13-23 4-5 6-12l2 0q2 5 6 12l14 23 78 127 143 0 0-94-70 0-103-149 114-165 61 0z m357-121l0-115-287 0-2 15q-2 25-2 26 0 36 15 65t36 48 47 36 47 30 36 30 15 36q0 21-16 35t-39 14q-28 0-54-22-8-6-20-21l-59 51q15 21 35 37 45 36 105 36 61 0 99-33t38-88q0-37-19-66t-47-48-56-35-49-35-23-41l129 0 0 45 70 0z" horiz-adv-x="857.143" />
31
+ <glyph glyph-name="inserthorizontalrule" unicode="&#xe818;" d="M214 439l0-107q0-22-16-38t-38-16l-107 0q-22 0-38 16t-16 38l0 107q0 22 16 38t38 16l107 0q22 0 38-16t16-38z m286 0l0-107q0-22-16-38t-38-16l-107 0q-22 0-38 16t-16 38l0 107q0 22 16 38t38 16l107 0q22 0 38-16t16-38z m286 0l0-107q0-22-16-38t-38-16l-107 0q-22 0-38 16t-16 38l0 107q0 22 16 38t38 16l107 0q22 0 38-16t16-38z" horiz-adv-x="785.714" />
32
+ <glyph glyph-name="pin" unicode="&#xe812;" d="M268 368l0 250q0 8-5 13t-13 5-13-5-5-13l0-250q0-8 5-13t13-5 13 5 5 13z m375-196q0-15-11-25t-25-11l-239 0-28-270q-1-7-6-11t-11-5l-1 0q-15 0-18 15l-42 271-225 0q-15 0-25 11t-11 25q0 69 44 124t99 55l0 286q-29 0-50 21t-21 50 21 50 50 21l357 0q29 0 50-21t21-50-21-50-50-21l0-286q55 0 99-55t44-124z" horiz-adv-x="642.857" />
33
+ <glyph glyph-name="createlink" unicode="&#xe810;" d="M812 171q0 22-16 38l-116 116q-16 16-38 16-23 0-40-18 2-2 11-10t12-12 8-11 7-14 2-15q0-22-16-38t-38-16q-8 0-15 2t-14 7-11 8-12 12-10 11q-18-17-18-41 0-22 16-38l115-116q15-15 38-15 22 0 38 15l82 81q16 16 16 37z m-392 393q0 22-16 38l-115 116q-16 16-38 16t-38-15l-82-81q-16-16-16-37 0-22 16-38l116-116q15-15 38-15t40 17q-2 2-11 10t-12 12-8 11-7 14-2 15q0 22 16 38t38 16q8 0 15-2t14-7 11-8 12-12 10-11q18 17 18 41z m499-393q0-67-47-113l-82-81q-46-46-113-46-68 0-114 47l-115 116q-46 46-46 113 0 69 49 117l-49 49q-48-49-116-49-67 0-114 47l-116 116q-47 47-47 114t47 113l82 81q46 46 113 46 68 0 114-47l115-116q46-46 46-113 0-69-49-117l49-49q48 49 116 49 67 0 114-47l116-116q47-47 47-114z" horiz-adv-x="928.571" />
34
+ </font>
35
+ </defs>
36
+ </svg>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ // Main dependencies
2
+ //= require deps
3
+ //= require dante
@@ -0,0 +1,7 @@
1
+ //Editor components
2
+ //= require dante/dante
3
+ //= require dante/utils
4
+ //= require dante/view
5
+ //= require dante/editor
6
+ //= require dante/tooltip
7
+ //= require dante/menu
@@ -0,0 +1,7 @@
1
+ window.Dante = {
2
+ Editor: {
3
+ ToolTip: {}
4
+ Menu: {}
5
+ }
6
+ version: "<%= DanteEditor::VERSION %>"
7
+ }
@@ -0,0 +1,917 @@
1
+
2
+ selected_menu = false
3
+ utils = Dante.utils
4
+
5
+ class Dante.Editor extends Dante.View
6
+ #el: "#editor"
7
+
8
+ events:
9
+ "blur" : "handleBlur"
10
+ "mouseup" : "handleMouseUp"
11
+ "keydown" : "handleKeyDown"
12
+ "keyup" : "handleKeyUp"
13
+ "paste" : "handlePaste"
14
+ "click .graf--figure" : "handleGrafFigureSelect"
15
+
16
+ initialize: (opts = {})=>
17
+ @editor_options = opts
18
+ #globals for selected text and node
19
+ @initial_html = $(@el).html()
20
+ @current_range = null
21
+ @current_node = null
22
+ @el = opts.el || "#editor"
23
+ window.debugMode = opts.debug || false
24
+ $(@el).addClass("debug") if window.debugMode
25
+ @upload_url = opts.upload_url || "/uploads.json"
26
+ @oembed_url = opts.oembed_url || "http://api.embed.ly/1/oembed?url="
27
+ @extract_url = opts.extract_url || "http://api.embed.ly/1/extract?key=86c28a410a104c8bb58848733c82f840&url="
28
+ @default_loading_placeholder = opts.default_loading_placeholder || "/images/media-loading-placeholder.png"
29
+ @store_url = opts.store_url
30
+ if (localStorage.getItem('contenteditable'))
31
+ $(@el).html localStorage.getItem('contenteditable')
32
+
33
+ @store()
34
+
35
+ @title_placeholder = "<span class='defaultValue defaultValue--root'>Title…</span><br>"
36
+ @body_placeholder = "<span class='defaultValue defaultValue--root'>Tell your story…</span><br>"
37
+ @embed_placeholder = "<span class='defaultValue defaultValue--prompt'>Paste a YouTube, Vine, Vimeo, or other video link, and press Enter</span><br>"
38
+ @extract_placeholder = "<span class='defaultValue defaultValue--prompt'>Paste a link to embed content from another site (e.g. Twitter) and press Enter</span><br>"
39
+
40
+ store: ()->
41
+ #localStorage.setItem("contenteditable", $(@el).html() )
42
+ return unless @store_url
43
+ setTimeout ()=>
44
+ @checkforStore()
45
+ , 15000
46
+
47
+ checkforStore: ()->
48
+ if @content is @getContent()
49
+ utils.log "content not changed skip store"
50
+ @store()
51
+ else
52
+ utils.log "content changed! update"
53
+ @content = @getContent()
54
+ $.ajax
55
+ url: @store_url
56
+ method: "post"
57
+ data: @getContent()
58
+ success: (res)->
59
+ utils.log "store!"
60
+ utils.log res
61
+ complete: (jxhr) =>
62
+ @store()
63
+
64
+ getContent: ()->
65
+ $(@el).find(".section-inner").html()
66
+
67
+ template: ()=>
68
+ "<section class='section--first section--last'>
69
+
70
+ <div class='section-divider layoutSingleColumn'>
71
+ <hr class='section-divider'>
72
+ </div>
73
+
74
+ <div class='section-content'>
75
+ <div class='section-inner'>
76
+ <p class='graf graf--h3'>#{@title_placeholder}</p>
77
+ <p class='graf graf--p'>#{@body_placeholder}<p>
78
+ </div>
79
+ </div>
80
+
81
+ </section>"
82
+
83
+ baseParagraphTmpl: ()->
84
+ "<p class='graf--p' name='#{utils.generateUniqueName()}'><br></p>"
85
+
86
+ appendMenus: ()=>
87
+ $("<div id='dante-menu' class='dante-menu' style='opacity: 0;'></div>").insertAfter(@el)
88
+ $("<div class='inlineTooltip2 button-scalableGroup'></div>").insertAfter(@el)
89
+ @editor_menu = new Dante.Editor.Menu(editor: @)
90
+ @tooltip_view = new Dante.Editor.Tooltip(editor: @)
91
+ @tooltip_view.render()
92
+
93
+ appendInitialContent: ()=>
94
+ $(@el).find(".section-inner").html(@initial_html)
95
+
96
+ start: ()=>
97
+ @render()
98
+ $(@el).attr("contenteditable", "true")
99
+ $(@el).addClass("postField--body")
100
+ $(@el).wrap("<div class='notesSource'></div>")
101
+ @appendMenus()
102
+ @appendInitialContent() unless _.isEmpty @initial_html.trim()
103
+ @setupElementsClasses()
104
+
105
+ restart: ()=>
106
+ @render()
107
+
108
+ render: ()=>
109
+ @template()
110
+ $(@el).html @template()
111
+
112
+ getSelectedText: () ->
113
+ text = ""
114
+ if typeof window.getSelection != "undefined"
115
+ text = window.getSelection().toString()
116
+ else if typeof document.selection != "undefined" && document.selection.type == "Text"
117
+ text = document.selection.createRange().text
118
+ text
119
+
120
+ selection: ()=>
121
+ selection
122
+ if (window.getSelection)
123
+ selection = window.getSelection()
124
+ else if (document.selection && document.selection.type != "Control")
125
+ selection = document.selection
126
+
127
+ getRange: () ->
128
+ editor = $(@el)[0]
129
+ range = selection && selection.rangeCount && selection.getRangeAt(0)
130
+ range = document.createRange() if (!range)
131
+ if !editor.contains(range.commonAncestorContainer)
132
+ range.selectNodeContents(editor)
133
+ range.collapse(false)
134
+ range
135
+
136
+ setRange: (range)->
137
+ range = range || this.current_range
138
+ if !range
139
+ range = this.getRange()
140
+ range.collapse(false); # set to end
141
+
142
+ @selection().removeAllRanges()
143
+ @selection().addRange(range)
144
+ @
145
+
146
+ getCharacterPrecedingCaret: ->
147
+ precedingChar = ""
148
+ sel = undefined
149
+ range = undefined
150
+ precedingRange = undefined
151
+ if window.getSelection
152
+ sel = window.getSelection()
153
+ if sel.rangeCount > 0
154
+ range = sel.getRangeAt(0).cloneRange()
155
+ range.collapse true
156
+ range.setStart @getNode(), 0
157
+ precedingChar = range.toString().slice(0)
158
+ else if (sel = document.selection) and sel.type isnt "Control"
159
+ range = sel.createRange()
160
+ precedingRange = range.duplicate()
161
+ precedingRange.moveToElementText containerEl
162
+ precedingRange.setEndPoint "EndToStart", range
163
+ precedingChar = precedingRange.text.slice(0)
164
+ precedingChar
165
+
166
+ isLastChar: ()->
167
+ #utils.log "#{$(@getNode()).text().trim().length} | #{@getCharacterPrecedingCaret().trim().length}"
168
+ $(@getNode()).text().trim().length is @getCharacterPrecedingCaret().trim().length
169
+
170
+ isFirstChar: ()->
171
+ @getCharacterPrecedingCaret().trim().length is 0
172
+
173
+ isSelectingAll: (element)->
174
+ a = @getSelectedText().killWhiteSpace().length
175
+ b = $(element).text().killWhiteSpace().length
176
+ a is b
177
+
178
+ #set focus and caret position on element
179
+ setRangeAt: (element, int=0)->
180
+ range = document.createRange()
181
+ sel = window.getSelection()
182
+ #node = element.firstChild;
183
+ range.setStart(element, int); #DANGER this is supported by IE 9
184
+ #range.setStartAfter(element)
185
+ #range.setEnd(element, int);
186
+ range.collapse(true)
187
+ sel.removeAllRanges()
188
+ sel.addRange(range)
189
+ #@el.focus()
190
+ element.focus()
191
+
192
+ #set focus and caret position on element
193
+ setRangeAtText: (element, int=0)->
194
+ range = document.createRange()
195
+ sel = window.getSelection()
196
+ node = element.firstChild;
197
+ range.setStart(node, 0); #DANGER this is supported by IE 9
198
+ range.setEnd(node, 0);
199
+ range.collapse(true)
200
+ sel.removeAllRanges()
201
+ sel.addRange(range)
202
+ element.focus()
203
+
204
+ focus: (focusStart) ->
205
+ @.setRange() if (!focusStart)
206
+ $(@el).focus()
207
+ @
208
+
209
+ #NOT USED
210
+ focusNode: (node, range)->
211
+ range.setStartAfter(node)
212
+ range.setEndBefore(node)
213
+ range.collapse(false)
214
+ @.setRange(range)
215
+
216
+ #get the element that wraps Caret position while is inside section
217
+ getNode: ()->
218
+ node = undefined
219
+ root = $(@el).find(".section-inner")[0]
220
+ return if @selection().rangeCount < 1
221
+ range = @selection().getRangeAt(0)
222
+ node = range.commonAncestorContainer
223
+ return null if not node or node is root
224
+ node = node.parentNode while node and (node.nodeType isnt 1) and (node.parentNode isnt root)
225
+ node = node.parentNode while node and (node.parentNode isnt root)
226
+ (if root && root.contains(node) then node else null)
227
+
228
+ displayMenu: (sel)->
229
+ setTimeout ()=>
230
+ @editor_menu.render()
231
+ pos = utils.getSelectionDimensions()
232
+ @relocateMenu(pos)
233
+ @editor_menu.show()
234
+ , 10
235
+
236
+ #get text of selected and displays menu
237
+ handleTextSelection: (anchor_node)->
238
+ @editor_menu.hide()
239
+ text = @getSelectedText()
240
+ unless _.isEmpty text.trim()
241
+ #@current_range = @getRange()
242
+ @current_node = anchor_node
243
+ @.displayMenu()
244
+
245
+ relocateMenu: (position)->
246
+ padd = @editor_menu.$el.width() / 2
247
+ top = position.top + $(window).scrollTop() - 43
248
+ l = position.left + (position.width / 2) - padd
249
+ @editor_menu.$el.offset({left: l , top: top })
250
+
251
+ hidePlaceholder: (element)->
252
+ $(element).find("span.defaultValue").remove().html("<br>")
253
+
254
+ displayEmptyPlaceholder: (element)->
255
+ $(".graf--first").html(@title_placeholder)
256
+ $(".graf--last").html(@body_placeholder)
257
+
258
+ handleGrafFigureSelect: (ev)->
259
+ element = ev.currentTarget
260
+ @markAsSelected( element )
261
+ @setRangeAt( $(element).find('.imageCaption')[0] )
262
+
263
+ handleBlur: (ev)=>
264
+ #hide menu only if is not in use
265
+ setTimeout ()=>
266
+ @editor_menu.hide() unless selected_menu
267
+ , 200
268
+ false
269
+
270
+ handleMouseUp: (ev)=>
271
+ utils.log "MOUSE UP"
272
+ anchor_node = @getNode()
273
+ utils.log anchor_node
274
+ utils.log ev.currentTarget
275
+ return if _.isNull(anchor_node)
276
+ @handleTextSelection(anchor_node)
277
+ @hidePlaceholder(anchor_node)
278
+ @markAsSelected( anchor_node )
279
+ @displayTooltipAt( anchor_node )
280
+
281
+ scrollTo: (node)->
282
+ return if utils.isElementInViewport($(node))
283
+
284
+ top = node.offset().top
285
+ #scroll to element top
286
+ $('html, body').animate
287
+ scrollTop: top
288
+ , 20
289
+
290
+ #handle arrow direction from keyUp.
291
+ handleArrow: (ev)=>
292
+ current_node = $(@getNode())
293
+ if current_node
294
+ @markAsSelected( current_node )
295
+ @displayTooltipAt( current_node )
296
+
297
+ #handle arrow direction from keyDown.
298
+ handleArrowForKeyDown: (ev)=>
299
+ current_node = $(@getNode())
300
+ utils.log(ev)
301
+ ev_type = ev.originalEvent.key || ev.originalEvent.keyIdentifier
302
+
303
+ utils.log("ENTER ARROW for key #{ev_type}")
304
+
305
+ #handle keys for image figure
306
+ switch ev_type
307
+
308
+ when "Down"
309
+ next_node = current_node.next()
310
+ utils.log "NEXT NODE IS #{next_node.attr('class')}"
311
+ utils.log "CURRENT NODE IS #{current_node.attr('class')}"
312
+
313
+ return unless $(current_node).hasClass("graf")
314
+ return unless $(current_node).editableCaretOnLastLine()
315
+
316
+ utils.log "ENTER ARROW PASSED RETURNS"
317
+
318
+ #if next element is embed select & focus it
319
+ if next_node.hasClass("graf--figure")
320
+ n = next_node.find(".imageCaption")
321
+ @setRangeAt n[0]
322
+ @scrollTo(n)
323
+ utils.log "1 down"
324
+ utils.log n[0]
325
+ next_node.addClass("is-mediaFocused is-selected")
326
+ return false
327
+ #if current node is embed
328
+ else if next_node.hasClass("graf--mixtapeEmbed")
329
+ n = current_node.next(".graf--mixtapeEmbed")
330
+ num = n[0].childNodes.length
331
+ @setRangeAt n[0], num
332
+ @scrollTo(n)
333
+ utils.log "2 down"
334
+ return false
335
+
336
+ if current_node.hasClass("graf--figure") && next_node.hasClass("graf")
337
+ @setRangeAt next_node[0]
338
+ @scrollTo(next_node)
339
+ utils.log "3 down"
340
+ return false
341
+
342
+ ###
343
+ else if next_node.hasClass("graf")
344
+ n = current_node.next(".graf")
345
+ @setRangeAt n[0]
346
+ @scrollTo(n)
347
+ false
348
+ ###
349
+
350
+ when "Up"
351
+ prev_node = current_node.prev()
352
+ utils.log "PREV NODE IS #{prev_node.attr('class')}"
353
+ utils.log "CURRENT NODE IS up #{current_node.attr('class')}"
354
+
355
+ return unless $(current_node).hasClass("graf")
356
+ return unless $(current_node).editableCaretOnFirstLine()
357
+
358
+ utils.log "ENTER ARROW PASSED RETURNS"
359
+
360
+ if prev_node.hasClass("graf--figure")
361
+ utils.log "1 up"
362
+ n = prev_node.find(".imageCaption")
363
+ @setRangeAt n[0]
364
+ @scrollTo(n)
365
+ prev_node.addClass("is-mediaFocused is-selected")
366
+ return false
367
+
368
+ else if prev_node.hasClass("graf--mixtapeEmbed")
369
+ n = current_node.prev(".graf--mixtapeEmbed")
370
+ num = n[0].childNodes.length
371
+ @setRangeAt n[0], num
372
+ @scrollTo(n)
373
+ utils.log "2 up"
374
+ return false
375
+
376
+ if current_node.hasClass("graf--figure") && prev_node.hasClass("graf")
377
+ @setRangeAt prev_node[0]
378
+ @scrollTo(prev_node)
379
+ utils.log "3 up"
380
+ return false
381
+
382
+ else if prev_node.hasClass("graf")
383
+ n = current_node.prev(".graf")
384
+ num = n[0].childNodes.length
385
+ @setRangeAt n[0], num
386
+ @scrollTo(n)
387
+ utils.log "4 up"
388
+ return false
389
+
390
+ utils.log "noting"
391
+
392
+ #detects html data , creates a hidden node to paste ,
393
+ #then clean up the content and copies to currentNode, very clever uh?
394
+ handlePaste: (ev)=>
395
+ utils.log("pasted!")
396
+ @aa = @getNode()
397
+
398
+ pastedText = undefined
399
+ if (window.clipboardData && window.clipboardData.getData) #IE
400
+ pastedText = window.clipboardData.getData('Text')
401
+ else if (ev.originalEvent.clipboardData && ev.originalEvent.clipboardData.getData)
402
+ cbd = ev.originalEvent.clipboardData
403
+ pastedText = if _.isEmpty(cbd.getData('text/html')) then cbd.getData('text/plain') else cbd.getData('text/html')
404
+
405
+ #alert(pastedText) # Process and handle text...
406
+ #detect if is html
407
+ if pastedText.match(/<\/*[a-z][^>]+?>/gi)
408
+ utils.log("HTML DETECTED ON PASTE")
409
+ $(pastedText)
410
+
411
+ document.body.appendChild($("<div id='paste'></div>")[0])
412
+ $("#paste").html(pastedText)
413
+ @setupElementsClasses $("#paste"), ()=>
414
+ nodes = $($("#paste").html()).insertAfter($(@aa))
415
+ $("#paste").remove()
416
+ #set caret on newly created node
417
+ last_node = nodes.last()[0]
418
+ num = last_node.childNodes.length
419
+ @setRangeAt(last_node, num)
420
+ new_node = $(@getNode())
421
+ top = new_node.offset().top
422
+ @markAsSelected(new_node)
423
+ @displayTooltipAt($(@el).find(".is-selected"))
424
+ #scroll to element top
425
+ @handleUnwrappedImages(nodes)
426
+ $('html, body').animate
427
+ scrollTop: top
428
+ , 200
429
+
430
+ return false # Prevent the default handler from running.
431
+
432
+ handleUnwrappedImages: (elements)->
433
+ #http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata
434
+ _.each elements.find("img"), (image)=>
435
+ utils.log ("process image here!")
436
+ @tooltip_view.uploadExistentImage(image)
437
+
438
+ #TODO: remove this, not used
439
+ handleInmediateDeletion: (element)->
440
+ @inmediateDeletion = false
441
+ new_node = $( @baseParagraphTmpl() ).insertBefore( $(element) )
442
+ new_node.addClass("is-selected")
443
+ @setRangeAt($(element).prev()[0])
444
+ $(element).remove()
445
+
446
+ #TODO: not used anymore, remove this
447
+ #when found that the current node is text node
448
+ #create a new <p> and focus
449
+ handleUnwrappedNode: (element)->
450
+ tmpl = $(@baseParagraphTmpl())
451
+ @setElementName(tmpl)
452
+ $(element).wrap(tmpl)
453
+ new_node = $("[name='#{tmpl.attr('name')}']")
454
+ new_node.addClass("is-selected")
455
+ @setRangeAt(new_node[0])
456
+ return false
457
+
458
+ ###
459
+ This is a rare hack only for FF (I hope),
460
+ when there is no range it creates a new element as a placeholder,
461
+ then finds previous element from that placeholder,
462
+ then it focus the prev and removes the placeholder.
463
+ a nasty nasty one...
464
+ ###
465
+ handleNullAnchor: ()->
466
+ utils.log "WARNING! this is an empty node"
467
+ sel = @selection();
468
+
469
+ if (sel.isCollapsed && sel.rangeCount > 0)
470
+ range = sel.getRangeAt(0)
471
+ span = $( @baseParagraphTmpl())[0]
472
+ range.insertNode(span)
473
+ range.setStart(span, 0)
474
+ range.setEnd(span, 0)
475
+ sel.removeAllRanges()
476
+ sel.addRange(range)
477
+
478
+ node = $(range.commonAncestorContainer)
479
+ prev = node.prev()
480
+ num = prev[0].childNodes.length
481
+ utils.log prev
482
+ if prev.hasClass("graf")
483
+ @setRangeAt(prev[0], num)
484
+ node.remove()
485
+ @markAsSelected(@getNode())
486
+ else if prev.hasClass("graf--mixtapeEmbed")
487
+ @setRangeAt(prev[0], num)
488
+ node.remove()
489
+ @markAsSelected(@getNode())
490
+ else if !prev
491
+ @.setRangeAt(@.$el.find(".section-inner p")[0])
492
+
493
+ @displayTooltipAt($(@el).find(".is-selected"))
494
+
495
+ #used when all the content is removed, then it re render
496
+ handleCompleteDeletion: (element)->
497
+ if _.isEmpty( $(element).text().trim() )
498
+ utils.log "HANDLE COMPLETE DELETION"
499
+ @selection().removeAllRanges()
500
+ @render()
501
+
502
+ setTimeout =>
503
+ @setRangeAt($(@el).find(".section-inner p")[0])
504
+ , 20
505
+ @completeDeletion = true
506
+
507
+ #handles tab navigation
508
+ handleTab: (anchor_node)->
509
+ utils.log "HANDLE TAB"
510
+ classes = ".graf, .graf--mixtapeEmbed, .graf--figure, .graf--figure"
511
+ next = $(anchor_node).next(classes)
512
+
513
+ if $(next).hasClass("graf--figure")
514
+ next = $(next).find("figcaption")
515
+ @setRangeAt next[0]
516
+ @markAsSelected $(next).parent(".graf--figure")
517
+ @displayTooltipAt next
518
+ @scrollTo $(next)
519
+ return false
520
+
521
+ if _.isEmpty(next) or _.isUndefined(next[0])
522
+ next = $(".graf:first")
523
+
524
+ @setRangeAt next[0]
525
+ @markAsSelected next
526
+ @displayTooltipAt next
527
+ @scrollTo $(next)
528
+
529
+ handleKeyDown: (e)->
530
+ utils.log "KEYDOWN"
531
+
532
+ anchor_node = @getNode() #current node on which cursor is positioned
533
+
534
+ @markAsSelected( anchor_node ) if anchor_node
535
+
536
+ if e.which is 9
537
+
538
+ @handleTab(anchor_node)
539
+ return false
540
+
541
+ if e.which == 13
542
+
543
+ #removes previous selected nodes
544
+ $(@el).find(".is-selected").removeClass("is-selected")
545
+
546
+ parent = $(anchor_node)
547
+
548
+ utils.log @isLastChar()
549
+
550
+ #embeds or extracts
551
+ if parent.hasClass("is-embedable")
552
+ @tooltip_view.getEmbedFromNode($(anchor_node))
553
+ else if parent.hasClass("is-extractable")
554
+ @tooltip_view.getExtractFromNode($(anchor_node))
555
+
556
+
557
+ #supress linebreak into embed page text unless last char
558
+ if parent.hasClass("graf--mixtapeEmbed") or parent.hasClass("graf--iframe") or parent.hasClass("graf--figure")
559
+ utils.log("supress linebreak from embed !(last char)")
560
+ return false unless @isLastChar()
561
+
562
+ #supress linebreak or create new <p> into embed caption unless last char el
563
+ if parent.hasClass("graf--iframe") or parent.hasClass("graf--figure")
564
+ if @isLastChar()
565
+ @handleLineBreakWith("p", parent)
566
+ @setRangeAtText($(".is-selected")[0])
567
+
568
+ $(".is-selected").trigger("mouseup") #is not making any change
569
+ return false
570
+ else
571
+ return false
572
+
573
+ @tooltip_view.cleanOperationClasses($(anchor_node))
574
+
575
+
576
+ if (anchor_node && @editor_menu.lineBreakReg.test(anchor_node.nodeName))
577
+ #new paragraph if it the last character
578
+ if @isLastChar()
579
+ utils.log "new paragraph if it the last character"
580
+ e.preventDefault()
581
+ @handleLineBreakWith("p", parent)
582
+
583
+ setTimeout ()=>
584
+ node = @getNode()
585
+ @markAsSelected( @getNode() ) #if anchor_node
586
+ @setupFirstAndLast()
587
+ #set name on new element
588
+ @setElementName($(node))
589
+
590
+ #empty childs if text is empty
591
+ if _.isEmpty $(node).text().trim()
592
+ _.each $(node).children(), (n)->
593
+ $(n).remove()
594
+ $(node).append("<br>")
595
+
596
+ #shows tooltip
597
+ @displayTooltipAt($(@el).find(".is-selected"))
598
+ , 2
599
+
600
+
601
+ #delete key
602
+ if (e.which == 8)
603
+ @tooltip_view.hide()
604
+ utils.log("removing from down")
605
+ utils.log "REACHED TOP" if @reachedTop
606
+ return false if @prevented or @reachedTop && @isFirstChar()
607
+ #return false if !anchor_node or anchor_node.nodeType is 3
608
+ utils.log("pass initial validations")
609
+ anchor_node = @getNode()
610
+ utils.log "anchor_node"
611
+ utils.log anchor_node
612
+ utils.log "UTILS anchor_node"
613
+ utils_anchor_node = utils.getNode()
614
+ utils.log utils_anchor_node
615
+
616
+ if $(utils_anchor_node).hasClass("section-content") || $(utils_anchor_node).hasClass("graf--first")
617
+ utils.log "SECTION DETECTED FROM KEYDOWN #{_.isEmpty($(utils_anchor_node).text())}"
618
+ return false if _.isEmpty($(utils_anchor_node).text())
619
+
620
+ if anchor_node && anchor_node.nodeType is 3
621
+ #@displayEmptyPlaceholder()
622
+ utils.log("TextNode detected from Down!")
623
+ #return false
624
+
625
+ #supress del into embed if first char or delete if empty content
626
+ if $(anchor_node).hasClass("graf--mixtapeEmbed") or $(anchor_node).hasClass("graf--iframe")
627
+ if _.isEmpty $(anchor_node).text().trim()
628
+ utils.log "EMPTY CHAR"
629
+ return false
630
+ else
631
+ if @isFirstChar()
632
+ utils.log "FIRST CHAR"
633
+ @inmediateDeletion = true if @isSelectingAll(anchor_node)
634
+ return false
635
+
636
+ #TODO: supress del when the prev el is embed and current_node is at first char
637
+ if $(anchor_node).prev().hasClass("graf--mixtapeEmbed")
638
+ return false if @isFirstChar() && !_.isEmpty( $(anchor_node).text().trim() )
639
+
640
+ #arrows key
641
+ #if _.contains([37,38,39,40], e.which)
642
+ #up & down
643
+ if _.contains([38, 40], e.which)
644
+ utils.log e.which
645
+ @handleArrowForKeyDown(e)
646
+ #return false
647
+
648
+ handleKeyUp: (e , node)->
649
+ utils.log "KEYUP"
650
+
651
+ @editor_menu.hide() #hides menu just in case
652
+ @reachedTop = false
653
+ anchor_node = @getNode() #current node on which cursor is positioned
654
+ utils_anchor_node = utils.getNode()
655
+
656
+ @handleTextSelection(anchor_node)
657
+
658
+ if (e.which == 8)
659
+
660
+ #if detect all text deleted , re render
661
+ if $(utils_anchor_node).hasClass("postField--body")
662
+ utils.log "ALL GONE from UP"
663
+ @handleCompleteDeletion($(@el))
664
+ if @completeDeletion
665
+ @completeDeletion = false
666
+ return false
667
+
668
+ if $(utils_anchor_node).hasClass("section-content") || $(utils_anchor_node).hasClass("graf--first")
669
+ utils.log "SECTION DETECTED FROM KEYUP #{_.isEmpty($(utils_anchor_node).text())}"
670
+ return false if _.isEmpty($(utils_anchor_node).text())
671
+
672
+ if _.isNull(anchor_node)
673
+ @handleNullAnchor()
674
+ return false
675
+
676
+ if $(anchor_node).hasClass("graf--first")
677
+ utils.log "THE FIRST ONE! UP"
678
+ @markAsSelected(anchor_node)
679
+ @setupFirstAndLast()
680
+ false
681
+
682
+ if anchor_node
683
+ @markAsSelected(anchor_node)
684
+ @setupFirstAndLast()
685
+ @displayTooltipAt($(@el).find(".is-selected"))
686
+
687
+ #arrows key
688
+ if _.contains([37,38,39,40], e.which)
689
+ @handleArrow(e)
690
+ #return false
691
+
692
+ #TODO: Separate in little functions
693
+ handleLineBreakWith: (element_type, from_element)->
694
+ new_paragraph = $("<#{element_type} class='graf graf--#{element_type} graf--empty is-selected'><br/></#{element_type}>")
695
+ if from_element.parent().is('[class^="graf--"]')
696
+ new_paragraph.insertAfter(from_element.parent())
697
+ else
698
+ new_paragraph.insertAfter(from_element)
699
+ #set caret on new <p>
700
+ @setRangeAt(new_paragraph[0])
701
+ @scrollTo new_paragraph
702
+
703
+ #shows the (+) tooltip at current element
704
+ displayTooltipAt: (element)->
705
+ utils.log ("POSITION FOR TOOLTIP")
706
+ #utils.log $(element)
707
+ return if !element
708
+ @tooltip_view.hide()
709
+ return unless _.isEmpty( $(element).text() )
710
+ @position = $(element).offset()
711
+ @tooltip_view.render()
712
+ @tooltip_view.move(left: @position.left - 60 , top: @position.top - 5 )
713
+
714
+ #mark the current row as selected
715
+ markAsSelected: (element)->
716
+
717
+ return if _.isUndefined element
718
+
719
+ $(@el).find(".is-selected").removeClass("is-mediaFocused is-selected")
720
+ $(element).addClass("is-selected")
721
+
722
+ if $(element).prop("tagName").toLowerCase() is "figure"
723
+ $(element).addClass("is-mediaFocused")
724
+
725
+ $(element).find(".defaultValue").remove()
726
+ #set reached top if element is first!
727
+ if $(element).hasClass("graf--first")
728
+ @reachedTop = true
729
+ $(element).append("<br>") if $(element).find("br").length is 0
730
+
731
+ addClassesToElement: (element)=>
732
+ n = element
733
+ name = n.nodeName.toLowerCase()
734
+ switch name
735
+ when "p", "h2", "h3", "pre", "div"
736
+ #utils.log n
737
+ unless $(n).hasClass("graf--mixtapeEmbed")
738
+ $(n).removeClass().addClass("graf graf--#{name}")
739
+
740
+ if name is "p" and $(n).find("br").length is 0
741
+ $(n).append("<br>")
742
+
743
+ when "code"
744
+ #utils.log n
745
+ $(n).unwrap().wrap("<p class='graf graf--pre'></p>")
746
+ n = $(n).parent()
747
+
748
+ when "ol", "ul"
749
+ #utils.log "lists"
750
+ $(n).removeClass().addClass("postList")
751
+ _.each $(n).find("li"), (li)->
752
+ $(n).removeClass().addClass("graf graf--li")
753
+ #postList , and li as graf
754
+
755
+ when "img"
756
+ utils.log "images"
757
+ #@handleUnwrappedImages(n)
758
+ #@handleUnwrappedImages(nodes)
759
+ @tooltip_view.uploadExistentImage(n)
760
+ #set figure non editable
761
+
762
+ when "a", 'strong', 'em', 'br', 'b', 'u', 'i'
763
+ utils.log "links"
764
+ $(n).wrap("<p class='graf graf--#{name}'></p>")
765
+ n = $(n).parent()
766
+ #dont know
767
+
768
+ when "blockquote"
769
+ #TODO remove inner elements like P
770
+ #$(n).find("p").unwrap()
771
+ n = $(n).removeClass().addClass("graf graf--#{name}")
772
+
773
+ else
774
+ #TODO: for now leave this relaxed, because this is
775
+ #overwriting embeds
776
+ #wrap all the rest
777
+ $(n).wrap("<p class='graf graf--#{name}'></p>")
778
+ n = $(n).parent()
779
+
780
+ return n
781
+
782
+ setupElementsClasses: (element, cb)->
783
+ if _.isUndefined(element)
784
+ @element = $(@el).find('.section-inner')
785
+ else
786
+ @element = element
787
+
788
+ setTimeout ()=>
789
+ #clean context and wrap text nodes
790
+ @cleanContents(@element)
791
+ @wrapTextNodes(@element)
792
+ #setup classes
793
+ _.each @element.children(), (n)=>
794
+ name = $(n).prop("tagName").toLowerCase()
795
+ n = @addClassesToElement(n)
796
+
797
+ @setElementName(n)
798
+
799
+ @setupLinks(@element.find("a"))
800
+ @setupFirstAndLast()
801
+
802
+ cb() if _.isFunction(cb)
803
+ , 20
804
+
805
+ cleanContents: (element)->
806
+ #TODO: should config tags
807
+ if _.isUndefined(element)
808
+ @element = $(@el).find('.section-inner')
809
+ else
810
+ @element = element
811
+
812
+ s = new Sanitize
813
+ elements: ['strong','img', 'em', 'br', 'a', 'blockquote', 'b', 'u', 'i', 'pre', 'p', 'h2', 'h3']
814
+
815
+ attributes:
816
+ '__ALL__': ['class']
817
+ a: ['href', 'title', 'target']
818
+ img: ['src']
819
+
820
+ protocols:
821
+ a: { href: ['http', 'https', 'mailto'] }
822
+
823
+ transformers: [(input)->
824
+ if (input.node_name == "span" && $(input.node).hasClass("defaultValue") )
825
+ return whitelist_nodes: [input.node]
826
+ else
827
+ return null
828
+ (input)->
829
+ #page embeds
830
+ if(input.node_name == 'div' && $(input.node).hasClass("graf--mixtapeEmbed") )
831
+ return whitelist_nodes: [input.node]
832
+ else if(input.node_name == 'a' && $(input.node).parent(".graf--mixtapeEmbed").exists() )
833
+ return attr_whitelist: ["style"]
834
+ else
835
+ return null
836
+ ,
837
+ (input)->
838
+ #embeds
839
+ if( input.node_name == 'figure' && $(input.node).hasClass("graf--iframe") )
840
+ return whitelist_nodes: [input.node]
841
+ else if(input.node_name == 'div' && $(input.node).hasClass("iframeContainer") && $(input.node).parent(".graf--iframe").exists() )
842
+ return whitelist_nodes: [input.node]
843
+ else if(input.node_name == 'iframe' && $(input.node).parent(".iframeContainer").exists() )
844
+ return whitelist_nodes: [input.node]
845
+ else if(input.node_name == 'figcaption' && $(input.node).parent(".graf--iframe").exists() )
846
+ return whitelist_nodes: [input.node]
847
+ else
848
+ return null
849
+ ,
850
+ (input)->
851
+ #image embeds
852
+ if(input.node_name == 'figure' && $(input.node).hasClass("graf--figure") )
853
+ return whitelist_nodes: [input.node]
854
+
855
+ else if(input.node_name == 'div' && ($(input.node).hasClass("aspect-ratio-fill") || $(input.node).hasClass("aspectRatioPlaceholder")) && $(input.node).parent(".graf--figure").exists() )
856
+ return whitelist_nodes: [input.node]
857
+
858
+ else if(input.node_name == 'img' && $(input.node).parent(".graf--figure").exists() )
859
+ return whitelist_nodes: [input.node]
860
+
861
+ else if(input.node_name == 'a' && $(input.node).parent(".graf--mixtapeEmbed").exists() )
862
+ return attr_whitelist: ["style"]
863
+
864
+ else if(input.node_name == 'span' && $(input.node).parent(".imageCaption").exists())
865
+ return whitelist_nodes: [input.node]
866
+ else
867
+ return null
868
+ ]
869
+
870
+ if @element.exists()
871
+ utils.log "CLEAN HTML"
872
+ @element.html(s.clean_node( @element[0] ))
873
+
874
+ setupLinks: (elems)->
875
+ _.each elems, (n)=>
876
+ @setupLink(n)
877
+
878
+ setupLink: (n)->
879
+ parent_name = $(n).parent().prop("tagName").toLowerCase()
880
+ $(n).addClass("markup--anchor markup--#{parent_name}-anchor")
881
+ href = $(n).attr("href")
882
+ $(n).attr("data-href", href)
883
+
884
+ preCleanNode: (element)->
885
+ s = new Sanitize
886
+ elements: ['strong', 'em', 'br', 'a', 'b', 'u', 'i']
887
+
888
+ attributes:
889
+ a: ['href', 'title', 'target']
890
+
891
+ protocols:
892
+ a: { href: ['http', 'https', 'mailto'] }
893
+
894
+ $(element).html s.clean_node( element[0] )
895
+
896
+ element = @addClassesToElement( $(element)[0] )
897
+
898
+ $(element)
899
+
900
+ setupFirstAndLast: ()=>
901
+ childs = $(@el).find(".section-inner").children()
902
+ childs.removeClass("graf--last , graf--first")
903
+ childs.first().addClass("graf--first")
904
+ childs.last().addClass("graf--last")
905
+
906
+ wrapTextNodes: (element)->
907
+ if _.isUndefined(element)
908
+ element = $(@el).find('.section-inner')
909
+ else
910
+ element = element
911
+
912
+ element.contents().filter(->
913
+ @nodeType is 3 and @data.trim().length > 0
914
+ ).wrap "<p class='graf grap--p'></p>"
915
+
916
+ setElementName: (element)->
917
+ $(element).attr("name", utils.generateUniqueName())