mosaico 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (425) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE +680 -0
  5. data/README.md +179 -0
  6. data/Rakefile +5 -0
  7. data/app/assets/images/mosaico/logo_transparent.png +0 -0
  8. data/app/assets/javascripts/mosaico/application.js.erb +51 -0
  9. data/app/assets/javascripts/mosaico/plugins/debug.js.erb +10 -0
  10. data/app/assets/javascripts/mosaico/plugins/logo.js.erb +10 -0
  11. data/app/assets/javascripts/mosaico/plugins/preview.js +85 -0
  12. data/app/assets/javascripts/mosaico/plugins/save.js.erb +72 -0
  13. data/app/assets/javascripts/mosaico/plugins/template_path.js.erb +22 -0
  14. data/app/assets/javascripts/mosaico/plugins/translations.js +10 -0
  15. data/app/assets/javascripts/mosaico/utilities.js +25 -0
  16. data/app/assets/stylesheets/mosaico/application.css +6 -0
  17. data/app/controllers/mosaico/application_controller.rb +17 -0
  18. data/app/controllers/mosaico/images_controller.rb +142 -0
  19. data/app/controllers/mosaico/projects_controller.rb +31 -0
  20. data/app/controllers/mosaico/templates_controller.rb +8 -0
  21. data/app/helpers/mosaico/application_helper.rb +7 -0
  22. data/app/models/mosaico/image.rb +9 -0
  23. data/app/models/mosaico/placeholder_image.rb +9 -0
  24. data/app/models/mosaico/project.rb +13 -0
  25. data/app/models/mosaico/uploaded_image.rb +26 -0
  26. data/app/views/layouts/mosaico/application.html.erb +13 -0
  27. data/app/views/mosaico/projects/new.html.erb +1 -0
  28. data/app/views/mosaico/projects/show.html.erb +1 -0
  29. data/app/views/mosaico/shared/_metadata.html.erb +12 -0
  30. data/config/routes.rb +12 -0
  31. data/db/migrate/20170817202255_add_images.rb +14 -0
  32. data/db/migrate/20170824233755_add_projects.rb +11 -0
  33. data/lib/mosaico.rb +100 -0
  34. data/lib/mosaico/engine.rb +72 -0
  35. data/lib/mosaico/local_backend.rb +23 -0
  36. data/lib/mosaico/local_image_backend.rb +7 -0
  37. data/lib/mosaico/local_placeholder_backend.rb +7 -0
  38. data/lib/mosaico/placeholder.png +0 -0
  39. data/lib/mosaico/template.rb +89 -0
  40. data/lib/mosaico/versafix_template.rb +43 -0
  41. data/lib/mosaico/version.rb +4 -0
  42. data/lib/tasks/makeThumbs.js.erb +57 -0
  43. data/lib/tasks/thumbs.rake +35 -0
  44. data/mosaico.gemspec +22 -0
  45. data/screenshot.png +0 -0
  46. data/vendor/assets/fonts/LiberationSans-Regular.ttf +0 -0
  47. data/vendor/assets/mosaico-0.16.0/mosaico/.jsbeautifyrc +6 -0
  48. data/vendor/assets/mosaico-0.16.0/mosaico/.jshintrc +8 -0
  49. data/vendor/assets/mosaico-0.16.0/mosaico/.travis.yml +6 -0
  50. data/vendor/assets/mosaico-0.16.0/mosaico/CONTRIBUTING.md +37 -0
  51. data/vendor/assets/mosaico-0.16.0/mosaico/Dockerfile +21 -0
  52. data/vendor/assets/mosaico-0.16.0/mosaico/Gruntfile.js +241 -0
  53. data/vendor/assets/mosaico-0.16.0/mosaico/LICENSE +680 -0
  54. data/vendor/assets/mosaico-0.16.0/mosaico/NOTICE.txt +87 -0
  55. data/vendor/assets/mosaico-0.16.0/mosaico/README.md +73 -0
  56. data/vendor/assets/mosaico-0.16.0/mosaico/backend/README.txt +23 -0
  57. data/vendor/assets/mosaico-0.16.0/mosaico/backend/main.js +162 -0
  58. data/vendor/assets/mosaico-0.16.0/mosaico/bower.json +76 -0
  59. data/vendor/assets/mosaico-0.16.0/mosaico/build/mosaico-material.css +7425 -0
  60. data/vendor/assets/mosaico-0.16.0/mosaico/build/mosaico.css +7133 -0
  61. data/vendor/assets/mosaico-0.16.0/mosaico/build/mosaico.debug.js +1517 -0
  62. data/vendor/assets/mosaico-0.16.0/mosaico/build/mosaico.js +12828 -0
  63. data/vendor/assets/mosaico-0.16.0/mosaico/build/templates.js +15 -0
  64. data/vendor/assets/mosaico-0.16.0/mosaico/dist/fa/fonts/fontawesome-webfont.eot +0 -0
  65. data/vendor/assets/mosaico-0.16.0/mosaico/dist/fa/fonts/fontawesome-webfont.svg +685 -0
  66. data/vendor/assets/mosaico-0.16.0/mosaico/dist/fa/fonts/fontawesome-webfont.ttf +0 -0
  67. data/vendor/assets/mosaico-0.16.0/mosaico/dist/fa/fonts/fontawesome-webfont.woff +0 -0
  68. data/vendor/assets/mosaico-0.16.0/mosaico/dist/fa/fonts/fontawesome-webfont.woff2 +0 -0
  69. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/byvoxmail.png +0 -0
  70. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/mosaico-badge.gif +0 -0
  71. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/mosaico-v.gif +0 -0
  72. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/mosaico32.png +0 -0
  73. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/mosaicologo.png +0 -0
  74. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/screenshot-orig.png +0 -0
  75. data/vendor/assets/mosaico-0.16.0/mosaico/dist/img/screenshot.png +0 -0
  76. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/README.md +26 -0
  77. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-de.json +88 -0
  78. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-en.json +88 -0
  79. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-es.json +88 -0
  80. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-fr.json +88 -0
  81. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-it.json +88 -0
  82. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-nl.json +88 -0
  83. data/vendor/assets/mosaico-0.16.0/mosaico/dist/lang/mosaico-sv.json +88 -0
  84. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico-material.min.css +5 -0
  85. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico-material.min.css.map +1 -0
  86. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico.min.css +5 -0
  87. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico.min.css.map +1 -0
  88. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico.min.js +1517 -0
  89. data/vendor/assets/mosaico-0.16.0/mosaico/dist/mosaico.min.js.map +147 -0
  90. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/canvas-to-blob.min.js +2 -0
  91. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery-ui.min.css +7 -0
  92. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery-ui.min.js +13 -0
  93. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.fileupload-image.js +324 -0
  94. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.fileupload-process.js +175 -0
  95. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.fileupload-validate.js +122 -0
  96. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.fileupload.js +1482 -0
  97. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.iframe-transport.js +217 -0
  98. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.min.js +5 -0
  99. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.min.map +1 -0
  100. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/jquery.ui.touch-punch.min.js +11 -0
  101. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/knockout-jqueryui.min.js +1 -0
  102. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/knockout.js +123 -0
  103. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/load-image.all.min.js +2 -0
  104. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/notoregular/NotoSans-Regular-webfont.eot +0 -0
  105. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/notoregular/NotoSans-Regular-webfont.ttf +0 -0
  106. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/notoregular/NotoSans-Regular-webfont.woff +0 -0
  107. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/notoregular/stylesheet.css +9 -0
  108. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/advlist/plugin.js +101 -0
  109. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/advlist/plugin.min.js +1 -0
  110. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/anchor/plugin.js +55 -0
  111. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/anchor/plugin.min.js +1 -0
  112. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autolink/plugin.js +204 -0
  113. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autolink/plugin.min.js +1 -0
  114. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autoresize/plugin.js +162 -0
  115. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autoresize/plugin.min.js +1 -0
  116. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autosave/plugin.js +165 -0
  117. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/autosave/plugin.min.js +1 -0
  118. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/bbcode/plugin.js +123 -0
  119. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/bbcode/plugin.min.js +1 -0
  120. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/charmap/plugin.js +462 -0
  121. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/charmap/plugin.min.js +1 -0
  122. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/code/plugin.js +60 -0
  123. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/code/plugin.min.js +1 -0
  124. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/codesample/css/prism.css +138 -0
  125. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/codesample/plugin.js +1319 -0
  126. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/codesample/plugin.min.js +1 -0
  127. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/colorpicker/plugin.js +112 -0
  128. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/colorpicker/plugin.min.js +1 -0
  129. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/contextmenu/plugin.js +100 -0
  130. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/contextmenu/plugin.min.js +1 -0
  131. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/directionality/plugin.js +64 -0
  132. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/directionality/plugin.min.js +1 -0
  133. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-cool.gif +0 -0
  134. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-cry.gif +0 -0
  135. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-embarassed.gif +0 -0
  136. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-foot-in-mouth.gif +0 -0
  137. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-frown.gif +0 -0
  138. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-innocent.gif +0 -0
  139. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-kiss.gif +0 -0
  140. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-laughing.gif +0 -0
  141. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-money-mouth.gif +0 -0
  142. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-sealed.gif +0 -0
  143. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-smile.gif +0 -0
  144. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-surprised.gif +0 -0
  145. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-tongue-out.gif +0 -0
  146. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-undecided.gif +0 -0
  147. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-wink.gif +0 -0
  148. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/img/smiley-yell.gif +0 -0
  149. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/plugin.js +65 -0
  150. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/emoticons/plugin.min.js +1 -0
  151. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/fullpage/plugin.js +490 -0
  152. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/fullpage/plugin.min.js +1 -0
  153. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/fullscreen/plugin.js +154 -0
  154. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/fullscreen/plugin.min.js +1 -0
  155. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/hr/plugin.js +30 -0
  156. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/hr/plugin.min.js +1 -0
  157. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/image/plugin.js +630 -0
  158. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/image/plugin.min.js +1 -0
  159. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/imagetools/plugin.js +2944 -0
  160. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/imagetools/plugin.min.js +1 -0
  161. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/importcss/plugin.js +273 -0
  162. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/importcss/plugin.min.js +1 -0
  163. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/insertdatetime/plugin.js +121 -0
  164. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/insertdatetime/plugin.min.js +1 -0
  165. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/layer/plugin.js +225 -0
  166. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/layer/plugin.min.js +1 -0
  167. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/legacyoutput/plugin.js +208 -0
  168. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/legacyoutput/plugin.min.js +1 -0
  169. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/link/plugin.js +403 -0
  170. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/link/plugin.min.js +1 -0
  171. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/lists/plugin.js +965 -0
  172. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/lists/plugin.min.js +1 -0
  173. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/media/moxieplayer.swf +0 -0
  174. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/media/plugin.js +879 -0
  175. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/media/plugin.min.js +1 -0
  176. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/nonbreaking/plugin.js +53 -0
  177. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/nonbreaking/plugin.min.js +1 -0
  178. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/noneditable/plugin.js +101 -0
  179. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/noneditable/plugin.min.js +1 -0
  180. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/pagebreak/plugin.js +88 -0
  181. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/pagebreak/plugin.min.js +1 -0
  182. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/paste/plugin.js +1844 -0
  183. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/paste/plugin.min.js +1 -0
  184. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/preview/plugin.js +101 -0
  185. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/preview/plugin.min.js +1 -0
  186. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/print/plugin.js +32 -0
  187. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/print/plugin.min.js +1 -0
  188. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/save/plugin.js +98 -0
  189. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/save/plugin.min.js +1 -0
  190. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/searchreplace/plugin.js +609 -0
  191. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/searchreplace/plugin.min.js +1 -0
  192. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/spellchecker/plugin.js +1031 -0
  193. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/spellchecker/plugin.min.js +1 -0
  194. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/tabfocus/plugin.js +120 -0
  195. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/tabfocus/plugin.min.js +1 -0
  196. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/table/plugin.js +4400 -0
  197. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/table/plugin.min.js +2 -0
  198. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/template/plugin.js +276 -0
  199. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/template/plugin.min.js +1 -0
  200. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/textcolor/plugin.js +297 -0
  201. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/textcolor/plugin.min.js +1 -0
  202. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/textpattern/plugin.js +268 -0
  203. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/textpattern/plugin.min.js +1 -0
  204. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/visualblocks/css/visualblocks.css +135 -0
  205. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/visualblocks/plugin.js +86 -0
  206. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/visualblocks/plugin.min.js +1 -0
  207. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/visualchars/plugin.js +123 -0
  208. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/visualchars/plugin.min.js +1 -0
  209. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/wordcount/plugin.js +69 -0
  210. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/plugins/wordcount/plugin.min.js +1 -0
  211. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/Variables.less +196 -0
  212. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/content.inline.min.css +1 -0
  213. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/content.min.css +1 -0
  214. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/readme.md +1 -0
  215. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce-small.eot +0 -0
  216. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce-small.json +1277 -0
  217. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce-small.svg +63 -0
  218. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce-small.ttf +0 -0
  219. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce-small.woff +0 -0
  220. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce.eot +0 -0
  221. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce.json +1972 -0
  222. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce.svg +98 -0
  223. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce.ttf +0 -0
  224. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/fonts/tinymce.woff +0 -0
  225. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/img/anchor.gif +0 -0
  226. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/img/loader.gif +0 -0
  227. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/img/object.gif +0 -0
  228. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/img/trans.gif +0 -0
  229. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/skin.ie7.min.css +1 -0
  230. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/skin.json +79 -0
  231. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/gray-flat/skin.min.css +1 -0
  232. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/content.inline.min.css +1 -0
  233. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/content.min.css +1 -0
  234. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce-small.eot +0 -0
  235. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce-small.svg +63 -0
  236. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce-small.ttf +0 -0
  237. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce-small.woff +0 -0
  238. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce.eot +0 -0
  239. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce.svg +129 -0
  240. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce.ttf +0 -0
  241. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/fonts/tinymce.woff +0 -0
  242. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/img/anchor.gif +0 -0
  243. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/img/loader.gif +0 -0
  244. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/img/object.gif +0 -0
  245. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/img/trans.gif +0 -0
  246. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/skin.ie7.min.css +1 -0
  247. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/skins/lightgray/skin.min.css +1 -0
  248. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/themes/inlite/theme.js +1828 -0
  249. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/themes/inlite/theme.min.js +1 -0
  250. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/themes/modern/theme.js +934 -0
  251. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/themes/modern/theme.min.js +1 -0
  252. data/vendor/assets/mosaico-0.16.0/mosaico/dist/vendor/tinymce.min.js +14 -0
  253. data/vendor/assets/mosaico-0.16.0/mosaico/editor.html +63 -0
  254. data/vendor/assets/mosaico-0.16.0/mosaico/favicon.ico +0 -0
  255. data/vendor/assets/mosaico-0.16.0/mosaico/index.html +368 -0
  256. data/vendor/assets/mosaico-0.16.0/mosaico/package.json +92 -0
  257. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/byvoxmail.png +0 -0
  258. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/mosaico-badge.gif +0 -0
  259. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/mosaico-v.gif +0 -0
  260. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/mosaico32.png +0 -0
  261. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/mosaicologo.png +0 -0
  262. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/screenshot-orig.png +0 -0
  263. data/vendor/assets/mosaico-0.16.0/mosaico/res/img/screenshot.png +0 -0
  264. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/README.md +26 -0
  265. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-de.json +88 -0
  266. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-en.json +88 -0
  267. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-es.json +88 -0
  268. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-fr.json +88 -0
  269. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-it.json +88 -0
  270. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-nl.json +88 -0
  271. data/vendor/assets/mosaico-0.16.0/mosaico/res/lang/mosaico-sv.json +88 -0
  272. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/Variables.less +196 -0
  273. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/content.inline.min.css +1 -0
  274. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/content.min.css +1 -0
  275. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/readme.md +1 -0
  276. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce-small.eot +0 -0
  277. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce-small.json +1277 -0
  278. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce-small.svg +63 -0
  279. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce-small.ttf +0 -0
  280. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce-small.woff +0 -0
  281. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce.eot +0 -0
  282. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce.json +1972 -0
  283. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce.svg +98 -0
  284. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce.ttf +0 -0
  285. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/fonts/tinymce.woff +0 -0
  286. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/img/anchor.gif +0 -0
  287. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/img/loader.gif +0 -0
  288. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/img/object.gif +0 -0
  289. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/img/trans.gif +0 -0
  290. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/skin.ie7.min.css +1 -0
  291. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/skin.json +79 -0
  292. data/vendor/assets/mosaico-0.16.0/mosaico/res/vendor/skins/gray-flat/skin.min.css +1 -0
  293. data/vendor/assets/mosaico-0.16.0/mosaico/server-config.js +12 -0
  294. data/vendor/assets/mosaico-0.16.0/mosaico/spec/converter-spec.js +115 -0
  295. data/vendor/assets/mosaico-0.16.0/mosaico/spec/data/template-versafix-1.model.json +137 -0
  296. data/vendor/assets/mosaico-0.16.0/mosaico/spec/declarations-spec.js +282 -0
  297. data/vendor/assets/mosaico-0.16.0/mosaico/spec/mensch-spec.js +114 -0
  298. data/vendor/assets/mosaico-0.16.0/mosaico/spec/model-spec.js +88 -0
  299. data/vendor/assets/mosaico-0.16.0/mosaico/spec/stylesheet-spec.js +177 -0
  300. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/app_standalone.less +7 -0
  301. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/app_standalone_material.less +350 -0
  302. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/safarihack.css +17 -0
  303. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_elements.less +497 -0
  304. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_elements_jquery.less +344 -0
  305. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_elements_mixins.less +406 -0
  306. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_elements_moxie.less +130 -0
  307. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_mosaico.less +529 -0
  308. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_mosaico_content.less +391 -0
  309. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_mosaico_tools.less +1043 -0
  310. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_reset.less +45 -0
  311. data/vendor/assets/mosaico-0.16.0/mosaico/src/css/style_variables.less +156 -0
  312. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/app.js +167 -0
  313. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/bind-iframe.js +64 -0
  314. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/blocks.js +118 -0
  315. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/choose-template.js +7 -0
  316. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/colorpicker.js +58 -0
  317. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/csstext.js +16 -0
  318. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/droppable.js +87 -0
  319. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/eventable.js +33 -0
  320. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/extender-pagination.js +60 -0
  321. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/extsortables.js +103 -0
  322. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/fileupload.js +373 -0
  323. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/if-subs.js +110 -0
  324. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/jqueryui-spinner.js +31 -0
  325. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/jqueryui-tabs.js +17 -0
  326. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/script-template.js +30 -0
  327. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/scrollfix.js +48 -0
  328. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/scrollintoview.js +83 -0
  329. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/string-template.js +76 -0
  330. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/tooltips.js +36 -0
  331. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/validated-value.js +40 -0
  332. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/virtuals.js +102 -0
  333. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/bindings/wysiwygs.js +304 -0
  334. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/checkmodel.js +114 -0
  335. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/declarations.js +279 -0
  336. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/domutils.js +93 -0
  337. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/editor.js +411 -0
  338. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/main.js +42 -0
  339. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/model.js +536 -0
  340. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/parser.js +485 -0
  341. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/stylesheet.js +205 -0
  342. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/utils.js +156 -0
  343. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/converter/wrapper.js +308 -0
  344. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/ext/color.js +53 -0
  345. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/ext/inliner.js +35 -0
  346. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/ext/localstorage.js +100 -0
  347. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/ko-bindings.js +22 -0
  348. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/template-loader.js +446 -0
  349. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/timed-call.js +31 -0
  350. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/undomanager/undomain.js +49 -0
  351. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/undomanager/undoserializer.js +120 -0
  352. data/vendor/assets/mosaico-0.16.0/mosaico/src/js/viewmodel.js +595 -0
  353. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/array.tmpl.html +1 -0
  354. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/block-show.tmpl.html +1 -0
  355. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/block-wysiwyg.tmpl.html +18 -0
  356. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/blocks-show.tmpl.html +1 -0
  357. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/blocks-wysiwyg.tmpl.html +2 -0
  358. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/customstyle.tmpl.html +3 -0
  359. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/empty.tmpl.html +0 -0
  360. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/error.tmpl.html +1 -0
  361. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/gallery-images.tmpl.html +16 -0
  362. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/img-wysiwyg.tmpl.html +43 -0
  363. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/main.tmpl.html +102 -0
  364. data/vendor/assets/mosaico-0.16.0/mosaico/src/tmpl/toolbox.tmpl.html +111 -0
  365. data/vendor/assets/mosaico-0.16.0/mosaico/tasks/combineKOTemplates.js +24 -0
  366. data/vendor/assets/mosaico-0.16.0/mosaico/tasks/lib/phantom-thumbnailer-editor.js +168 -0
  367. data/vendor/assets/mosaico-0.16.0/mosaico/tasks/makeThumbs.js +79 -0
  368. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/README.md +1 -0
  369. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/_full.png +0 -0
  370. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/footerBlock.png +0 -0
  371. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/headerBlock.png +0 -0
  372. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/heroBlock.png +0 -0
  373. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/socialBlock.png +0 -0
  374. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/threetwoBlock.png +0 -0
  375. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/edres/twoColumnBlock.png +0 -0
  376. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tedc15/template-tedc15.html +567 -0
  377. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/edres/HeaderAndText.png +0 -0
  378. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/edres/_full.png +0 -0
  379. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/edres/fixedlist.png +0 -0
  380. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/mosaico-tutorial.md +335 -0
  381. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/mosaico-tutorial.pdf +0 -0
  382. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_384.jpg +0 -0
  383. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_385.jpg +0 -0
  384. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_386.jpg +0 -0
  385. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_387.jpg +0 -0
  386. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_407.jpg +0 -0
  387. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/screenshot_408.jpg +0 -0
  388. data/vendor/assets/mosaico-0.16.0/mosaico/templates/tutorial/template-tutorial.html +68 -0
  389. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/_full.png +0 -0
  390. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/buttonBlock.png +0 -0
  391. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/doubleArticleBlock.png +0 -0
  392. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/doubleImageBlock.png +0 -0
  393. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/hrBlock.png +0 -0
  394. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/imageBlock.png +0 -0
  395. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/logoBlock.png +0 -0
  396. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/sideArticleBlock.png +0 -0
  397. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/singleArticleBlock.png +0 -0
  398. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/socialBlock.png +0 -0
  399. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/spacerBlock.png +0 -0
  400. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/textBlock.png +0 -0
  401. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/titleBlock.png +0 -0
  402. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/tripleArticleBlock.png +0 -0
  403. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/edres/tripleImageBlock.png +0 -0
  404. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/facebook_bw_ok.png +0 -0
  405. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/facebook_ok.png +0 -0
  406. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/flickr_bw_ok.png +0 -0
  407. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/flickr_ok.png +0 -0
  408. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/google+_bw_ok.png +0 -0
  409. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/google+_ok.png +0 -0
  410. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/instagram_bw_ok.png +0 -0
  411. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/instagram_ok.png +0 -0
  412. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/linkedin_bw_ok.png +0 -0
  413. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/linkedin_ok.png +0 -0
  414. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/twitter_bw_ok.png +0 -0
  415. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/twitter_ok.png +0 -0
  416. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/vimeo_bw_ok.png +0 -0
  417. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/vimeo_ok.png +0 -0
  418. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/web_bw_ok.png +0 -0
  419. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/web_ok.png +0 -0
  420. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/youtube_bw_ok.png +0 -0
  421. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/social_def/youtube_ok.png +0 -0
  422. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/img/sponsor.gif +0 -0
  423. data/vendor/assets/mosaico-0.16.0/mosaico/templates/versafix-1/template-versafix-1.html +1531 -0
  424. data/vendor/assets/mosaico-0.16.0/mosaico/uploads/README.md +1 -0
  425. metadata +536 -0
@@ -0,0 +1 @@
1
+ tinymce.PluginManager.add("image",function(e){function t(e,t){function n(e,n){r.parentNode&&r.parentNode.removeChild(r),t({width:e,height:n})}var r=document.createElement("img");r.onload=function(){n(Math.max(r.width,r.clientWidth),Math.max(r.height,r.clientHeight))},r.onerror=function(){n()};var i=r.style;i.visibility="hidden",i.position="fixed",i.bottom=i.left=0,i.width=i.height="auto",document.body.appendChild(r),r.src=e}function n(e,t,n){function r(e,n){return n=n||[],tinymce.each(e,function(e){var i={text:e.text||e.title};e.menu?i.menu=r(e.menu):(i.value=e.value,t(i)),n.push(i)}),n}return r(e,n||[])}function r(t){return function(){var n=e.settings.image_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(e){t(tinymce.util.JSON.parse(e))}}):"function"==typeof n?n(t):t(n)}}function i(r){function i(){var e,t,n,r;e=d.find("#width")[0],t=d.find("#height")[0],e&&t&&(n=e.value(),r=t.value(),d.find("#constrain")[0].checked()&&p&&m&&n&&r&&(p!=n?(r=Math.round(n/p*r),isNaN(r)||t.value(r)):(n=Math.round(r/m*n),isNaN(n)||e.value(n))),p=n,m=r)}function o(){function t(t){function n(){t.onload=t.onerror=null,e.selection&&(e.selection.select(t),e.nodeChanged())}t.onload=function(){y.width||y.height||!C||b.setAttribs(t,{width:t.clientWidth,height:t.clientHeight}),n()},t.onerror=n}var n,r;c(),i(),y=tinymce.extend(y,d.toJSON()),y.alt||(y.alt=""),y.title||(y.title=""),""===y.width&&(y.width=null),""===y.height&&(y.height=null),y.style||(y.style=null),y={src:y.src,alt:y.alt,title:y.title,width:y.width,height:y.height,style:y.style,caption:y.caption,class:y.class},e.undoManager.transact(function(){function i(t){return e.schema.getTextBlockElements()[t.nodeName]}if(!y.src)return void(f&&(b.remove(f),e.focus(),e.nodeChanged()));if(""===y.title&&(y.title=null),f?b.setAttribs(f,y):(y.id="__mcenew",e.focus(),e.selection.setContent(b.createHTML("img",y)),f=b.get("__mcenew"),b.setAttrib(f,"id",null)),e.editorUpload.uploadImagesAuto(),y.caption===!1&&b.is(f.parentNode,"figure.image")&&(n=f.parentNode,b.insertAfter(f,n),b.remove(n)),y.caption!==!0)t(f);else if(!b.is(f.parentNode,"figure.image")){r=f,f=f.cloneNode(!0),n=b.create("figure",{class:"image"}),n.appendChild(f),n.appendChild(b.create("figcaption",{contentEditable:!0},"Caption")),n.contentEditable=!1;var o=b.getParent(r,i);o?b.split(o,r,n):b.replace(n,r),e.selection.select(n)}})}function a(e){return e&&(e=e.replace(/px$/,"")),e}function s(n){var r,i,o,a=n.meta||{};g&&g.value(e.convertURL(this.value(),"src")),tinymce.each(a,function(e,t){d.find("#"+t).value(e)}),a.width||a.height||(r=e.convertURL(this.value(),"src"),i=e.settings.image_prepend_url,o=new RegExp("^(?:[a-z]+:)?//","i"),i&&!o.test(r)&&r.substring(0,i.length)!==i&&(r=i+r),this.value(r),t(e.documentBaseURI.toAbsolute(this.value()),function(e){e.width&&e.height&&C&&(p=e.width,m=e.height,d.find("#width").value(p),d.find("#height").value(m))}))}function l(e){if(e.margin){var t=e.margin.split(" ");switch(t.length){case 1:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[0],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[0];break;case 2:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[1];break;case 3:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[1];break;case 4:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[3]}delete e.margin}return e}function c(){function t(e){return e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e}if(e.settings.image_advtab){var n=d.toJSON(),r=b.parseStyle(n.style);r=l(r),n.vspace&&(r["margin-top"]=r["margin-bottom"]=t(n.vspace)),n.hspace&&(r["margin-left"]=r["margin-right"]=t(n.hspace)),n.border&&(r["border-width"]=t(n.border)),d.find("#style").value(b.serializeStyle(b.parseStyle(b.serializeStyle(r))))}}function u(){if(e.settings.image_advtab){var t=d.toJSON(),n=b.parseStyle(t.style);d.find("#vspace").value(""),d.find("#hspace").value(""),n=l(n),(n["margin-top"]&&n["margin-bottom"]||n["margin-right"]&&n["margin-left"])&&(n["margin-top"]===n["margin-bottom"]?d.find("#vspace").value(a(n["margin-top"])):d.find("#vspace").value(""),n["margin-right"]===n["margin-left"]?d.find("#hspace").value(a(n["margin-right"])):d.find("#hspace").value("")),n["border-width"]&&d.find("#border").value(a(n["border-width"])),d.find("#style").value(b.serializeStyle(b.parseStyle(b.serializeStyle(n))))}}var d,f,h,p,m,g,v,y={},b=e.dom,C=e.settings.image_dimensions!==!1;f=e.selection.getNode(),h=b.getParent(f,"figure.image"),h&&(f=b.select("img",h)[0]),f&&("IMG"!=f.nodeName||f.getAttribute("data-mce-object")||f.getAttribute("data-mce-placeholder"))&&(f=null),f&&(p=b.getAttrib(f,"width"),m=b.getAttrib(f,"height"),y={src:b.getAttrib(f,"src"),alt:b.getAttrib(f,"alt"),title:b.getAttrib(f,"title"),class:b.getAttrib(f,"class"),width:p,height:m,caption:!!h}),r&&(g={type:"listbox",label:"Image list",values:n(r,function(t){t.value=e.convertURL(t.value||t.url,"src")},[{text:"None",value:""}]),value:y.src&&e.convertURL(y.src,"src"),onselect:function(e){var t=d.find("#alt");(!t.value()||e.lastControl&&t.value()==e.lastControl.text())&&t.value(e.control.text()),d.find("#src").value(e.control.value()).fire("change")},onPostRender:function(){g=this}}),e.settings.image_class_list&&(v={name:"class",type:"listbox",label:"Class",values:n(e.settings.image_class_list,function(t){t.value&&(t.textStyle=function(){return e.formatter.getCssText({inline:"img",classes:[t.value]})})})});var x=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:s},g];e.settings.image_description!==!1&&x.push({name:"alt",type:"textbox",label:"Image description"}),e.settings.image_title&&x.push({name:"title",type:"textbox",label:"Image Title"}),C&&x.push({type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:3,onchange:i,ariaLabel:"Width"},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:3,onchange:i,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}),x.push(v),e.settings.image_caption&&tinymce.Env.ceFalse&&x.push({name:"caption",type:"checkbox",label:"Caption"}),e.settings.image_advtab?(f&&(f.style.marginLeft&&f.style.marginRight&&f.style.marginLeft===f.style.marginRight&&(y.hspace=a(f.style.marginLeft)),f.style.marginTop&&f.style.marginBottom&&f.style.marginTop===f.style.marginBottom&&(y.vspace=a(f.style.marginTop)),f.style.borderWidth&&(y.border=a(f.style.borderWidth)),y.style=e.dom.serializeStyle(e.dom.parseStyle(e.dom.getAttrib(f,"style")))),d=e.windowManager.open({title:"Insert/edit image",data:y,bodyType:"tabpanel",body:[{title:"General",type:"form",items:x},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox",onchange:u},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:c},items:[{label:"Vertical space",name:"vspace"},{label:"Horizontal space",name:"hspace"},{label:"Border",name:"border"}]}]}],onSubmit:o})):d=e.windowManager.open({title:"Insert/edit image",data:y,body:x,onSubmit:o})}e.on("preInit",function(){function t(e){var t=e.attr("class");return t&&/\bimage\b/.test(t)}function n(e){return function(n){function r(t){t.attr("contenteditable",e?"true":null)}for(var i,o=n.length;o--;)i=n[o],t(i)&&(i.attr("contenteditable",e?"false":null),tinymce.each(i.getAll("figcaption"),r))}}e.parser.addNodeFilter("figure",n(!0)),e.serializer.addNodeFilter("figure",n(!1))}),e.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:r(i),stateSelector:"img:not([data-mce-object],[data-mce-placeholder]),figure.image"}),e.addMenuItem("image",{icon:"image",text:"Insert/edit image",onclick:r(i),context:"insert",prependToContext:!0}),e.addCommand("mceImage",r(i))});
@@ -0,0 +1,2944 @@
1
+ (function () {
2
+
3
+ var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
4
+
5
+ // Used when there is no 'main' module.
6
+ // The name is probably (hopefully) unique so minification removes for releases.
7
+ var register_3795 = function (id) {
8
+ var module = dem(id);
9
+ var fragments = id.split('.');
10
+ var target = Function('return this;')();
11
+ for (var i = 0; i < fragments.length - 1; ++i) {
12
+ if (target[fragments[i]] === undefined)
13
+ target[fragments[i]] = {};
14
+ target = target[fragments[i]];
15
+ }
16
+ target[fragments[fragments.length - 1]] = module;
17
+ };
18
+
19
+ var instantiate = function (id) {
20
+ var actual = defs[id];
21
+ var dependencies = actual.deps;
22
+ var definition = actual.defn;
23
+ var len = dependencies.length;
24
+ var instances = new Array(len);
25
+ for (var i = 0; i < len; ++i)
26
+ instances[i] = dem(dependencies[i]);
27
+ var defResult = definition.apply(null, instances);
28
+ if (defResult === undefined)
29
+ throw 'module [' + id + '] returned undefined';
30
+ actual.instance = defResult;
31
+ };
32
+
33
+ var def = function (id, dependencies, definition) {
34
+ if (typeof id !== 'string')
35
+ throw 'module id must be a string';
36
+ else if (dependencies === undefined)
37
+ throw 'no dependencies for ' + id;
38
+ else if (definition === undefined)
39
+ throw 'no definition function for ' + id;
40
+ defs[id] = {
41
+ deps: dependencies,
42
+ defn: definition,
43
+ instance: undefined
44
+ };
45
+ };
46
+
47
+ var dem = function (id) {
48
+ var actual = defs[id];
49
+ if (actual === undefined)
50
+ throw 'module [' + id + '] was undefined';
51
+ else if (actual.instance === undefined)
52
+ instantiate(id);
53
+ return actual.instance;
54
+ };
55
+
56
+ var req = function (ids, callback) {
57
+ var len = ids.length;
58
+ var instances = new Array(len);
59
+ for (var i = 0; i < len; ++i)
60
+ instances.push(dem(ids[i]));
61
+ callback.apply(null, callback);
62
+ };
63
+
64
+ var ephox = {};
65
+
66
+ ephox.bolt = {
67
+ module: {
68
+ api: {
69
+ define: def,
70
+ require: req,
71
+ demand: dem
72
+ }
73
+ }
74
+ };
75
+
76
+ var define = def;
77
+ var require = req;
78
+ var demand = dem;
79
+ // this helps with minificiation when using a lot of global references
80
+ var defineGlobal = function (id, ref) {
81
+ define(id, [], function () { return ref; });
82
+ };
83
+ /*jsc
84
+ ["tinymce/imagetoolsplugin/Plugin","global!tinymce.PluginManager","global!tinymce.Env","global!tinymce.util.Promise","global!tinymce.util.URI","global!tinymce.util.Tools","global!tinymce.util.Delay","ephox/imagetools/api/ImageTransformations","ephox/imagetools/api/BlobConversions","tinymce/imagetoolsplugin/Dialog","tinymce/imagetoolsplugin/ImageSize","tinymce/imagetoolsplugin/Proxy","ephox/imagetools/transformations/Filters","ephox/imagetools/transformations/ImageTools","ephox/imagetools/util/Conversions","global!tinymce.dom.DOMUtils","global!tinymce.ui.Factory","global!tinymce.ui.Form","global!tinymce.ui.Container","tinymce/imagetoolsplugin/ImagePanel","tinymce/imagetoolsplugin/UndoStack","tinymce/imagetoolsplugin/Utils","ephox/imagetools/util/Canvas","ephox/imagetools/util/ImageSize","ephox/imagetools/util/Promise","ephox/imagetools/util/Mime","ephox/imagetools/transformations/ColorMatrix","ephox/imagetools/transformations/ImageResizerCanvas","global!tinymce.ui.Control","global!tinymce.ui.DragHelper","global!tinymce.geom.Rect","tinymce/imagetoolsplugin/CropRect","global!tinymce.dom.DomQuery","global!tinymce.util.Observable","global!tinymce.util.VK"]
85
+ jsc*/
86
+ defineGlobal("global!tinymce.PluginManager", tinymce.PluginManager);
87
+ defineGlobal("global!tinymce.Env", tinymce.Env);
88
+ defineGlobal("global!tinymce.util.Promise", tinymce.util.Promise);
89
+ defineGlobal("global!tinymce.util.URI", tinymce.util.URI);
90
+ defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
91
+ defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
92
+ /**
93
+ * Canvas.js
94
+ *
95
+ * Released under LGPL License.
96
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
97
+ *
98
+ * License: http://www.tinymce.com/license
99
+ * Contributing: http://www.tinymce.com/contributing
100
+ */
101
+
102
+ /**
103
+ * Contains various canvas functions.
104
+ */
105
+ define("ephox/imagetools/util/Canvas", [], function() {
106
+ function create(width, height) {
107
+ return resize(document.createElement('canvas'), width, height);
108
+ }
109
+
110
+ function get2dContext(canvas) {
111
+ return canvas.getContext("2d");
112
+ }
113
+
114
+ function get3dContext(canvas) {
115
+ var gl = null;
116
+ try {
117
+ gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
118
+ }
119
+ catch(e) {}
120
+
121
+ if (!gl) { // it seems that sometimes it doesn't throw exception, but still fails to get context
122
+ gl = null;
123
+ }
124
+ return gl;
125
+ }
126
+
127
+ function resize(canvas, width, height) {
128
+ canvas.width = width;
129
+ canvas.height = height;
130
+
131
+ return canvas;
132
+ }
133
+
134
+ return {
135
+ create: create,
136
+ resize: resize,
137
+ get2dContext: get2dContext,
138
+ get3dContext: get3dContext
139
+ };
140
+ });
141
+ /**
142
+ * ImageSize.js
143
+ *
144
+ * Released under LGPL License.
145
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
146
+ *
147
+ * License: http://www.tinymce.com/license
148
+ * Contributing: http://www.tinymce.com/contributing
149
+ */
150
+
151
+ /**
152
+ * Returns the size of images.
153
+ */
154
+ define("ephox/imagetools/util/ImageSize", [], function() {
155
+ function getWidth(image) {
156
+ return image.naturalWidth || image.width;
157
+ }
158
+
159
+ function getHeight(image) {
160
+ return image.naturalHeight || image.height;
161
+ }
162
+
163
+ return {
164
+ getWidth: getWidth,
165
+ getHeight: getHeight
166
+ };
167
+ });
168
+ /**
169
+ * Promise.js
170
+ *
171
+ * Released under LGPL License.
172
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
173
+ *
174
+ * Promise polyfill under MIT license: https://github.com/taylorhakes/promise-polyfill
175
+ *
176
+ * License: http://www.tinymce.com/license
177
+ * Contributing: http://www.tinymce.com/contributing
178
+ */
179
+
180
+ /* eslint-disable */
181
+ /* jshint ignore:start */
182
+
183
+ /**
184
+ * Modifed to be a feature fill and wrapped as tinymce module.
185
+ */
186
+ define("ephox/imagetools/util/Promise", [], function() {
187
+ if (window.Promise) {
188
+ return window.Promise;
189
+ }
190
+
191
+ // Use polyfill for setImmediate for performance gains
192
+ var asap = Promise.immediateFn || (typeof setImmediate === 'function' && setImmediate) ||
193
+ function(fn) { setTimeout(fn, 1); };
194
+
195
+ // Polyfill for Function.prototype.bind
196
+ function bind(fn, thisArg) {
197
+ return function() {
198
+ fn.apply(thisArg, arguments);
199
+ };
200
+ }
201
+
202
+ var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]"; };
203
+
204
+ function Promise(fn) {
205
+ if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
206
+ if (typeof fn !== 'function') throw new TypeError('not a function');
207
+ this._state = null;
208
+ this._value = null;
209
+ this._deferreds = [];
210
+
211
+ doResolve(fn, bind(resolve, this), bind(reject, this));
212
+ }
213
+
214
+ function handle(deferred) {
215
+ var me = this;
216
+ if (this._state === null) {
217
+ this._deferreds.push(deferred);
218
+ return;
219
+ }
220
+ asap(function() {
221
+ var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
222
+ if (cb === null) {
223
+ (me._state ? deferred.resolve : deferred.reject)(me._value);
224
+ return;
225
+ }
226
+ var ret;
227
+ try {
228
+ ret = cb(me._value);
229
+ }
230
+ catch (e) {
231
+ deferred.reject(e);
232
+ return;
233
+ }
234
+ deferred.resolve(ret);
235
+ });
236
+ }
237
+
238
+ function resolve(newValue) {
239
+ try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
240
+ if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.');
241
+ if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
242
+ var then = newValue.then;
243
+ if (typeof then === 'function') {
244
+ doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
245
+ return;
246
+ }
247
+ }
248
+ this._state = true;
249
+ this._value = newValue;
250
+ finale.call(this);
251
+ } catch (e) { reject.call(this, e); }
252
+ }
253
+
254
+ function reject(newValue) {
255
+ this._state = false;
256
+ this._value = newValue;
257
+ finale.call(this);
258
+ }
259
+
260
+ function finale() {
261
+ for (var i = 0, len = this._deferreds.length; i < len; i++) {
262
+ handle.call(this, this._deferreds[i]);
263
+ }
264
+ this._deferreds = null;
265
+ }
266
+
267
+ function Handler(onFulfilled, onRejected, resolve, reject){
268
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
269
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null;
270
+ this.resolve = resolve;
271
+ this.reject = reject;
272
+ }
273
+
274
+ /**
275
+ * Take a potentially misbehaving resolver function and make sure
276
+ * onFulfilled and onRejected are only called once.
277
+ *
278
+ * Makes no guarantees about asynchrony.
279
+ */
280
+ function doResolve(fn, onFulfilled, onRejected) {
281
+ var done = false;
282
+ try {
283
+ fn(function (value) {
284
+ if (done) return;
285
+ done = true;
286
+ onFulfilled(value);
287
+ }, function (reason) {
288
+ if (done) return;
289
+ done = true;
290
+ onRejected(reason);
291
+ });
292
+ } catch (ex) {
293
+ if (done) return;
294
+ done = true;
295
+ onRejected(ex);
296
+ }
297
+ }
298
+
299
+ Promise.prototype['catch'] = function (onRejected) {
300
+ return this.then(null, onRejected);
301
+ };
302
+
303
+ Promise.prototype.then = function(onFulfilled, onRejected) {
304
+ var me = this;
305
+ return new Promise(function(resolve, reject) {
306
+ handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
307
+ });
308
+ };
309
+
310
+ Promise.all = function () {
311
+ var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
312
+
313
+ return new Promise(function (resolve, reject) {
314
+ if (args.length === 0) return resolve([]);
315
+ var remaining = args.length;
316
+ function res(i, val) {
317
+ try {
318
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
319
+ var then = val.then;
320
+ if (typeof then === 'function') {
321
+ then.call(val, function (val) { res(i, val); }, reject);
322
+ return;
323
+ }
324
+ }
325
+ args[i] = val;
326
+ if (--remaining === 0) {
327
+ resolve(args);
328
+ }
329
+ } catch (ex) {
330
+ reject(ex);
331
+ }
332
+ }
333
+ for (var i = 0; i < args.length; i++) {
334
+ res(i, args[i]);
335
+ }
336
+ });
337
+ };
338
+
339
+ Promise.resolve = function (value) {
340
+ if (value && typeof value === 'object' && value.constructor === Promise) {
341
+ return value;
342
+ }
343
+
344
+ return new Promise(function (resolve) {
345
+ resolve(value);
346
+ });
347
+ };
348
+
349
+ Promise.reject = function (value) {
350
+ return new Promise(function (resolve, reject) {
351
+ reject(value);
352
+ });
353
+ };
354
+
355
+ Promise.race = function (values) {
356
+ return new Promise(function (resolve, reject) {
357
+ for(var i = 0, len = values.length; i < len; i++) {
358
+ values[i].then(resolve, reject);
359
+ }
360
+ });
361
+ };
362
+
363
+ return Promise;
364
+ });
365
+
366
+ /* jshint ignore:end */
367
+ /* eslint-enable */
368
+ /**
369
+ * Mime.js
370
+ *
371
+ * Released under LGPL License.
372
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
373
+ *
374
+ * License: http://www.tinymce.com/license
375
+ * Contributing: http://www.tinymce.com/contributing
376
+ */
377
+
378
+ /**
379
+ * Returns mime types for uris.
380
+ */
381
+ define("ephox/imagetools/util/Mime", [], function() {
382
+ function getUriPathName(uri) {
383
+ var a = document.createElement('a');
384
+
385
+ a.href = uri;
386
+
387
+ return a.pathname;
388
+ }
389
+
390
+ function guessMimeType(uri) {
391
+ var parts = getUriPathName(uri).split('.'),
392
+ ext = parts[parts.length - 1],
393
+ mimes = {
394
+ 'jpg': 'image/jpeg',
395
+ 'jpeg': 'image/jpeg',
396
+ 'png': 'image/png'
397
+ };
398
+
399
+ if (ext) {
400
+ ext = ext.toLowerCase();
401
+ }
402
+
403
+ return mimes[ext];
404
+ }
405
+
406
+ return {
407
+ guessMimeType: guessMimeType
408
+ };
409
+ });
410
+ /**
411
+ * Conversions.js
412
+ *
413
+ * Released under LGPL License.
414
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
415
+ *
416
+ * License: http://www.tinymce.com/license
417
+ * Contributing: http://www.tinymce.com/contributing
418
+ */
419
+
420
+ /**
421
+ * Converts blob/uris/images back and forth.
422
+ */
423
+ define("ephox/imagetools/util/Conversions", [
424
+ "ephox/imagetools/util/Promise",
425
+ "ephox/imagetools/util/Canvas",
426
+ "ephox/imagetools/util/Mime",
427
+ "ephox/imagetools/util/ImageSize"
428
+ ], function(Promise, Canvas, Mime, ImageSize) {
429
+ function loadImage(image) {
430
+ return new Promise(function(resolve) {
431
+ function loaded() {
432
+ image.removeEventListener('load', loaded);
433
+ resolve(image);
434
+ }
435
+
436
+ if (image.complete) {
437
+ resolve(image);
438
+ } else {
439
+ image.addEventListener('load', loaded);
440
+ }
441
+ });
442
+ }
443
+
444
+ function imageToCanvas(image) {
445
+ return loadImage(image).then(function(image) {
446
+ var context, canvas;
447
+
448
+ canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image));
449
+ context = Canvas.get2dContext(canvas);
450
+ context.drawImage(image, 0, 0);
451
+
452
+ return canvas;
453
+ });
454
+ }
455
+
456
+ function imageToBlob(image) {
457
+ return loadImage(image).then(function(image) {
458
+ var src = image.src;
459
+
460
+ if (src.indexOf('blob:') === 0) {
461
+ return blobUriToBlob(src);
462
+ }
463
+
464
+ if (src.indexOf('data:') === 0) {
465
+ return dataUriToBlob(src);
466
+ }
467
+
468
+ return imageToCanvas(image).then(function(canvas) {
469
+ return dataUriToBlob(canvas.toDataURL(Mime.guessMimeType(src)));
470
+ });
471
+ });
472
+ }
473
+
474
+ function blobToImage(blob) {
475
+ return new Promise(function(resolve) {
476
+ var image = new Image();
477
+
478
+ function loaded() {
479
+ image.removeEventListener('load', loaded);
480
+ resolve(image);
481
+ }
482
+
483
+ image.addEventListener('load', loaded);
484
+ image.src = URL.createObjectURL(blob);
485
+
486
+ if (image.complete) {
487
+ loaded();
488
+ }
489
+ });
490
+ }
491
+
492
+ function blobUriToBlob(url) {
493
+ return new Promise(function(resolve) {
494
+ var xhr = new XMLHttpRequest();
495
+
496
+ xhr.open('GET', url, true);
497
+ xhr.responseType = 'blob';
498
+
499
+ xhr.onload = function() {
500
+ if (this.status == 200) {
501
+ resolve(this.response);
502
+ }
503
+ };
504
+
505
+ xhr.send();
506
+ });
507
+ }
508
+
509
+ function dataUriToBlob(uri) {
510
+ return new Promise(function(resolve) {
511
+ var str, arr, i, matches, type, blobBuilder;
512
+
513
+ uri = uri.split(',');
514
+
515
+ matches = /data:([^;]+)/.exec(uri[0]);
516
+ if (matches) {
517
+ type = matches[1];
518
+ }
519
+
520
+ str = atob(uri[1]);
521
+
522
+ if (window.WebKitBlobBuilder) {
523
+ /*globals WebKitBlobBuilder:false */
524
+ blobBuilder = new WebKitBlobBuilder();
525
+
526
+ arr = new ArrayBuffer(str.length);
527
+ for (i = 0; i < arr.length; i++) {
528
+ arr[i] = str.charCodeAt(i);
529
+ }
530
+
531
+ blobBuilder.append(arr);
532
+
533
+ resolve(blobBuilder.getBlob(type));
534
+ return;
535
+ }
536
+
537
+ arr = new Uint8Array(str.length);
538
+
539
+ for (i = 0; i < arr.length; i++) {
540
+ arr[i] = str.charCodeAt(i);
541
+ }
542
+
543
+ resolve(new Blob([arr], {type: type}));
544
+ });
545
+ }
546
+
547
+ function uriToBlob(url) {
548
+ if (url.indexOf('blob:') === 0) {
549
+ return blobUriToBlob(url);
550
+ }
551
+
552
+ if (url.indexOf('data:') === 0) {
553
+ return dataUriToBlob(url);
554
+ }
555
+
556
+ return null;
557
+ }
558
+
559
+ function canvasToBlob(canvas, type) {
560
+ return dataUriToBlob(canvas.toDataURL(type));
561
+ }
562
+
563
+ function blobToDataUri(blob) {
564
+ return new Promise(function(resolve) {
565
+ var reader = new FileReader();
566
+
567
+ reader.onloadend = function() {
568
+ resolve(reader.result);
569
+ };
570
+
571
+ reader.readAsDataURL(blob);
572
+ });
573
+ }
574
+
575
+ function blobToBase64(blob) {
576
+ return blobToDataUri(blob).then(function(dataUri) {
577
+ return dataUri.split(',')[1];
578
+ });
579
+ }
580
+
581
+ function revokeImageUrl(image) {
582
+ URL.revokeObjectURL(image.src);
583
+ }
584
+
585
+ return {
586
+ // used outside
587
+ blobToImage: blobToImage,
588
+ // used outside
589
+ imageToBlob: imageToBlob,
590
+ // used outside
591
+ blobToDataUri: blobToDataUri,
592
+ // used outside
593
+ blobToBase64: blobToBase64,
594
+
595
+ // helper method
596
+ imageToCanvas: imageToCanvas,
597
+
598
+ // helper method
599
+ canvasToBlob: canvasToBlob,
600
+
601
+ // helper method
602
+ revokeImageUrl: revokeImageUrl,
603
+
604
+ // helper method
605
+ uriToBlob: uriToBlob
606
+
607
+ };
608
+ });
609
+ /**
610
+ * ImageTools.js
611
+ *
612
+ * Released under LGPL License.
613
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
614
+ *
615
+ * License: http://www.tinymce.com/license
616
+ * Contributing: http://www.tinymce.com/contributing
617
+ *
618
+ * Some of the matrix calculations and constants are from the EaselJS library released under MIT:
619
+ * https://github.com/CreateJS/EaselJS/blob/master/src/easeljs/filters/ColorMatrix.js
620
+ */
621
+
622
+ /**
623
+ * Various operations for color matrices.
624
+ */
625
+ define("ephox/imagetools/transformations/ColorMatrix", [], function() {
626
+ function clamp(value, min, max) {
627
+ value = parseFloat(value);
628
+
629
+ if (value > max) {
630
+ value = max;
631
+ } else if (value < min) {
632
+ value = min;
633
+ }
634
+
635
+ return value;
636
+ }
637
+
638
+ function identity() {
639
+ return [
640
+ 1, 0, 0, 0, 0,
641
+ 0, 1, 0, 0, 0,
642
+ 0, 0, 1, 0, 0,
643
+ 0, 0, 0, 1, 0,
644
+ 0, 0, 0, 0, 1
645
+ ];
646
+ }
647
+
648
+ var DELTA_INDEX = [
649
+ 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
650
+ 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
651
+ 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
652
+ 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
653
+ 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
654
+ 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
655
+ 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
656
+ 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
657
+ 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
658
+ 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
659
+ 10.0
660
+ ];
661
+
662
+ function multiply(matrix1, matrix2) {
663
+ var i, j, k, val, col = [], out = new Array(10);
664
+
665
+ for (i = 0; i < 5; i++) {
666
+ for (j = 0; j < 5; j++) {
667
+ col[j] = matrix2[j + i * 5];
668
+ }
669
+
670
+ for (j = 0; j < 5; j++) {
671
+ val = 0;
672
+
673
+ for (k = 0; k < 5; k++) {
674
+ val += matrix1[j + k * 5] * col[k];
675
+ }
676
+
677
+ out[j + i * 5] = val;
678
+ }
679
+ }
680
+
681
+ return out;
682
+ }
683
+
684
+ function adjust(matrix, adjustValue) {
685
+ adjustValue = clamp(adjustValue, 0, 1);
686
+
687
+ return matrix.map(function(value, index) {
688
+ if (index % 6 === 0) {
689
+ value = 1.0 - ((1 - value) * adjustValue);
690
+ } else {
691
+ value *= adjustValue;
692
+ }
693
+
694
+ return clamp(value, 0, 1);
695
+ });
696
+ }
697
+
698
+ function adjustContrast(matrix, value) {
699
+ var x;
700
+
701
+ value = clamp(value, -1, 1);
702
+ value *= 100;
703
+
704
+ if (value < 0) {
705
+ x = 127 + value / 100 * 127;
706
+ } else {
707
+ x = value % 1;
708
+
709
+ if (x === 0) {
710
+ x = DELTA_INDEX[value];
711
+ } else {
712
+ // use linear interpolation for more granularity.
713
+ x = DELTA_INDEX[(Math.floor(value))] * (1 - x) + DELTA_INDEX[(Math.floor(value)) + 1] * x;
714
+ }
715
+
716
+ x = x * 127 + 127;
717
+ }
718
+
719
+ return multiply(matrix, [
720
+ x / 127, 0, 0, 0, 0.5 * (127 - x),
721
+ 0, x / 127, 0, 0, 0.5 * (127 - x),
722
+ 0, 0, x / 127, 0, 0.5 * (127 - x),
723
+ 0, 0, 0, 1, 0,
724
+ 0, 0, 0, 0, 1
725
+ ]);
726
+ }
727
+
728
+ function adjustSaturation(matrix, value) {
729
+ var x, lumR, lumG, lumB;
730
+
731
+ value = clamp(value, -1, 1);
732
+ x = 1 + ((value > 0) ? 3 * value : value);
733
+ lumR = 0.3086;
734
+ lumG = 0.6094;
735
+ lumB = 0.0820;
736
+
737
+ return multiply(matrix, [
738
+ lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0,
739
+ lumR * (1 - x), lumG * (1 - x) + x, lumB * (1 - x), 0, 0,
740
+ lumR * (1 - x), lumG * (1 - x), lumB * (1 - x) + x, 0, 0,
741
+ 0, 0, 0, 1, 0,
742
+ 0, 0, 0, 0, 1
743
+ ]);
744
+ }
745
+
746
+ function adjustHue(matrix, angle) {
747
+ var cosVal, sinVal, lumR, lumG, lumB;
748
+
749
+ angle = clamp(angle, -180, 180) / 180 * Math.PI;
750
+ cosVal = Math.cos(angle);
751
+ sinVal = Math.sin(angle);
752
+ lumR = 0.213;
753
+ lumG = 0.715;
754
+ lumB = 0.072;
755
+
756
+ return multiply(matrix, [
757
+ lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG),
758
+ lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
759
+ lumR + cosVal * (-lumR) + sinVal * (0.143), lumG + cosVal * (1 - lumG) + sinVal * (0.140),
760
+ lumB + cosVal * (-lumB) + sinVal * (-0.283), 0, 0,
761
+ lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG),
762
+ lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
763
+ 0, 0, 0, 1, 0,
764
+ 0, 0, 0, 0, 1
765
+ ]);
766
+ }
767
+
768
+ function adjustBrightness(matrix, value) {
769
+ value = clamp(255 * value, -255, 255);
770
+
771
+ return multiply(matrix, [
772
+ 1, 0, 0, 0, value,
773
+ 0, 1, 0, 0, value,
774
+ 0, 0, 1, 0, value,
775
+ 0, 0, 0, 1, 0,
776
+ 0, 0, 0, 0, 1
777
+ ]);
778
+ }
779
+
780
+ function adjustColors(matrix, adjustR, adjustG, adjustB) {
781
+ adjustR = clamp(adjustR, 0, 2);
782
+ adjustG = clamp(adjustG, 0, 2);
783
+ adjustB = clamp(adjustB, 0, 2);
784
+
785
+ return multiply(matrix, [
786
+ adjustR, 0, 0, 0, 0,
787
+ 0, adjustG, 0, 0, 0,
788
+ 0, 0, adjustB, 0, 0,
789
+ 0, 0, 0, 1, 0,
790
+ 0, 0, 0, 0, 1
791
+ ]);
792
+ }
793
+
794
+ function adjustSepia(matrix, value) {
795
+ value = clamp(value, 0, 1);
796
+
797
+ return multiply(matrix, adjust([
798
+ 0.393, 0.769, 0.189, 0, 0,
799
+ 0.349, 0.686, 0.168, 0, 0,
800
+ 0.272, 0.534, 0.131, 0, 0,
801
+ 0, 0, 0, 1, 0,
802
+ 0, 0, 0, 0, 1
803
+ ], value));
804
+ }
805
+
806
+ function adjustGrayscale(matrix, value) {
807
+ value = clamp(value, 0, 1);
808
+
809
+ return multiply(matrix, adjust([
810
+ 0.33, 0.34, 0.33, 0, 0,
811
+ 0.33, 0.34, 0.33, 0, 0,
812
+ 0.33, 0.34, 0.33, 0, 0,
813
+ 0, 0, 0, 1, 0,
814
+ 0, 0, 0, 0, 1
815
+ ], value));
816
+ }
817
+
818
+ return {
819
+ identity: identity,
820
+ adjust: adjust,
821
+ multiply: multiply,
822
+ adjustContrast: adjustContrast,
823
+ adjustBrightness: adjustBrightness,
824
+ adjustSaturation: adjustSaturation,
825
+ adjustHue: adjustHue,
826
+ adjustColors: adjustColors,
827
+ adjustSepia: adjustSepia,
828
+ adjustGrayscale: adjustGrayscale
829
+ };
830
+ });
831
+ /**
832
+ * Filters.js
833
+ *
834
+ * Released under LGPL License.
835
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
836
+ *
837
+ * License: http://www.tinymce.com/license
838
+ * Contributing: http://www.tinymce.com/contributing
839
+ */
840
+
841
+ /**
842
+ * Applies various filters to blobs.
843
+ */
844
+ define("ephox/imagetools/transformations/Filters", [
845
+ "ephox/imagetools/util/Canvas",
846
+ "ephox/imagetools/util/ImageSize",
847
+ "ephox/imagetools/util/Conversions",
848
+ "ephox/imagetools/transformations/ColorMatrix"
849
+ ], function(Canvas, ImageSize, Conversions, ColorMatrix) {
850
+ var revokeImageUrl = Conversions.revokeImageUrl;
851
+
852
+ function colorFilter(blob, matrix) {
853
+ return Conversions.blobToImage(blob).then(function(image) {
854
+ var canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image)),
855
+ context = Canvas.get2dContext(canvas),
856
+ pixels;
857
+
858
+ function applyMatrix(pixels, m) {
859
+ var d = pixels.data, r, g, b, a, i,
860
+ m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4],
861
+ m5 = m[5], m6 = m[6], m7 = m[7], m8 = m[8], m9 = m[9],
862
+ m10 = m[10], m11 = m[11], m12 = m[12], m13 = m[13], m14 = m[14],
863
+ m15 = m[15], m16 = m[16], m17 = m[17], m18 = m[18], m19 = m[19];
864
+
865
+ for (i = 0; i < d.length; i += 4) {
866
+ r = d[i];
867
+ g = d[i + 1];
868
+ b = d[i + 2];
869
+ a = d[i + 3];
870
+
871
+ d[i] = r * m0 + g * m1 + b * m2 + a * m3 + m4;
872
+ d[i + 1] = r * m5 + g * m6 + b * m7 + a * m8 + m9;
873
+ d[i + 2] = r * m10 + g * m11 + b * m12 + a * m13 + m14;
874
+ d[i + 3] = r * m15 + g * m16 + b * m17 + a * m18 + m19;
875
+ }
876
+
877
+ return pixels;
878
+ }
879
+
880
+ context.drawImage(image, 0, 0);
881
+ revokeImageUrl(image);
882
+ pixels = applyMatrix(context.getImageData(0, 0, canvas.width, canvas.height), matrix);
883
+ context.putImageData(pixels, 0, 0);
884
+
885
+ return Conversions.canvasToBlob(canvas);
886
+ });
887
+ }
888
+
889
+ function convoluteFilter(blob, matrix) {
890
+ return Conversions.blobToImage(blob).then(function(image) {
891
+ var canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image)),
892
+ context = Canvas.get2dContext(canvas),
893
+ pixelsIn, pixelsOut;
894
+
895
+ function applyMatrix(pixelsIn, pixelsOut, matrix) {
896
+ var rgba, drgba, side, halfSide, x, y, r, g, b,
897
+ cx, cy, scx, scy, offset, wt, w, h;
898
+
899
+ function clamp(value, min, max) {
900
+ if (value > max) {
901
+ value = max;
902
+ } else if (value < min) {
903
+ value = min;
904
+ }
905
+
906
+ return value;
907
+ }
908
+
909
+ // Calc side and half side of matrix
910
+ side = Math.round(Math.sqrt(matrix.length));
911
+ halfSide = Math.floor(side / 2);
912
+ rgba = pixelsIn.data;
913
+ drgba = pixelsOut.data;
914
+ w = pixelsIn.width;
915
+ h = pixelsIn.height;
916
+
917
+ // Apply convolution matrix to pixels
918
+ for (y = 0; y < h; y++) {
919
+ for (x = 0; x < w; x++) {
920
+ r = g = b = 0;
921
+
922
+ for (cy = 0; cy < side; cy++) {
923
+ for (cx = 0; cx < side; cx++) {
924
+ // Calc relative x, y based on matrix
925
+ scx = clamp(x + cx - halfSide, 0, w - 1);
926
+ scy = clamp(y + cy - halfSide, 0, h - 1);
927
+
928
+ // Calc r, g, b
929
+ offset = (scy * w + scx) * 4;
930
+ wt = matrix[cy * side + cx];
931
+ r += rgba[offset] * wt;
932
+ g += rgba[offset + 1] * wt;
933
+ b += rgba[offset + 2] * wt;
934
+ }
935
+ }
936
+
937
+ // Set new RGB to destination buffer
938
+ offset = (y * w + x) * 4;
939
+ drgba[offset] = clamp(r, 0, 255);
940
+ drgba[offset + 1] = clamp(g, 0, 255);
941
+ drgba[offset + 2] = clamp(b, 0, 255);
942
+ }
943
+ }
944
+
945
+ return pixelsOut;
946
+ }
947
+
948
+ context.drawImage(image, 0, 0);
949
+ revokeImageUrl(image);
950
+ pixelsIn = context.getImageData(0, 0, canvas.width, canvas.height);
951
+ pixelsOut = context.getImageData(0, 0, canvas.width, canvas.height);
952
+ pixelsOut = applyMatrix(pixelsIn, pixelsOut, matrix);
953
+ context.putImageData(pixelsOut, 0, 0);
954
+
955
+ return Conversions.canvasToBlob(canvas);
956
+ });
957
+ }
958
+
959
+ function functionColorFilter(colorFn) {
960
+ return function(blob, value) {
961
+ return Conversions.blobToImage(blob).then(function(image) {
962
+ var canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image)),
963
+ context = Canvas.get2dContext(canvas),
964
+ pixels, i, lookup = new Array(256);
965
+
966
+ function applyLookup(pixels, lookup) {
967
+ var d = pixels.data, i;
968
+
969
+ for (i = 0; i < d.length; i += 4) {
970
+ d[i] = lookup[d[i]];
971
+ d[i + 1] = lookup[d[i + 1]];
972
+ d[i + 2] = lookup[d[i + 2]];
973
+ }
974
+
975
+ return pixels;
976
+ }
977
+
978
+ for (i = 0; i < lookup.length; i++) {
979
+ lookup[i] = colorFn(i, value);
980
+ }
981
+
982
+ context.drawImage(image, 0, 0);
983
+ revokeImageUrl(image);
984
+ pixels = applyLookup(context.getImageData(0, 0, canvas.width, canvas.height), lookup);
985
+ context.putImageData(pixels, 0, 0);
986
+
987
+ return Conversions.canvasToBlob(canvas);
988
+ });
989
+ };
990
+ }
991
+
992
+ function complexAdjustableColorFilter(matrixAdjustFn) {
993
+ return function(blob, adjust) {
994
+ return colorFilter(blob, matrixAdjustFn(ColorMatrix.identity(), adjust));
995
+ };
996
+ }
997
+
998
+ function basicColorFilter(matrix) {
999
+ return function(blob) {
1000
+ return colorFilter(blob, matrix);
1001
+ };
1002
+ }
1003
+
1004
+ function basicConvolutionFilter(kernel) {
1005
+ return function(blob) {
1006
+ return convoluteFilter(blob, kernel);
1007
+ };
1008
+ }
1009
+
1010
+ return {
1011
+ invert: basicColorFilter([
1012
+ -1, 0, 0, 0, 255,
1013
+ 0, -1, 0, 0, 255,
1014
+ 0, 0, -1, 0, 255,
1015
+ 0, 0, 0, 1, 0
1016
+ ]),
1017
+
1018
+ brightness: complexAdjustableColorFilter(ColorMatrix.adjustBrightness),
1019
+ hue: complexAdjustableColorFilter(ColorMatrix.adjustHue),
1020
+ saturate: complexAdjustableColorFilter(ColorMatrix.adjustSaturation),
1021
+ contrast: complexAdjustableColorFilter(ColorMatrix.adjustContrast),
1022
+ grayscale: complexAdjustableColorFilter(ColorMatrix.adjustGrayscale),
1023
+ sepia: complexAdjustableColorFilter(ColorMatrix.adjustSepia),
1024
+ colorize: function(blob, adjustR, adjustG, adjustB) {
1025
+ return colorFilter(blob, ColorMatrix.adjustColors(ColorMatrix.identity(), adjustR, adjustG, adjustB));
1026
+ },
1027
+
1028
+ sharpen: basicConvolutionFilter([
1029
+ 0, -1, 0,
1030
+ -1, 5, -1,
1031
+ 0, -1, 0
1032
+ ]),
1033
+
1034
+ emboss: basicConvolutionFilter([
1035
+ -2, -1, 0,
1036
+ -1, 1, 1,
1037
+ 0, 1, 2
1038
+ ]),
1039
+
1040
+ gamma: functionColorFilter(function(color, value) {
1041
+ return Math.pow(color / 255, 1 - value) * 255;
1042
+ }),
1043
+
1044
+ exposure: functionColorFilter(function(color, value) {
1045
+ return 255 * (1 - Math.exp(-(color / 255) * value));
1046
+ }),
1047
+
1048
+ colorFilter: colorFilter,
1049
+ convoluteFilter: convoluteFilter
1050
+ };
1051
+ });
1052
+ /**
1053
+ * ImageResizerCanvas.js
1054
+ *
1055
+ * Released under LGPL License.
1056
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
1057
+ *
1058
+ * License: http://www.tinymce.com/license
1059
+ * Contributing: http://www.tinymce.com/contributing
1060
+ */
1061
+
1062
+ /**
1063
+ * Resizes image/canvas using canvas
1064
+ */
1065
+ define("ephox/imagetools/transformations/ImageResizerCanvas", [
1066
+ "ephox/imagetools/util/Promise",
1067
+ "ephox/imagetools/util/Conversions",
1068
+ "ephox/imagetools/util/Canvas",
1069
+ "ephox/imagetools/util/ImageSize"
1070
+ ], function(Promise, Conversions, Canvas, ImageSize) {
1071
+
1072
+ /**
1073
+ * @method scale
1074
+ * @static
1075
+ * @param image {Image|Canvas}
1076
+ * @param dW {Number} Width that the image should be scaled to
1077
+ * @param dH {Number} Height that the image should be scaled to
1078
+ * @returns {Promise}
1079
+ */
1080
+ function scale(image, dW, dH) {
1081
+ var sW = ImageSize.getWidth(image);
1082
+ var sH = ImageSize.getHeight(image);
1083
+ var wRatio = dW / sW;
1084
+ var hRatio = dH / sH;
1085
+ var scaleCapped = false;
1086
+
1087
+ if (wRatio < 0.5 || wRatio > 2) {
1088
+ wRatio = wRatio < 0.5 ? 0.5 : 2;
1089
+ scaleCapped = true;
1090
+ }
1091
+ if (hRatio < 0.5 || hRatio > 2) {
1092
+ hRatio = hRatio < 0.5 ? 0.5 : 2;
1093
+ scaleCapped = true;
1094
+ }
1095
+
1096
+ var scaled = _scale(image, wRatio, hRatio);
1097
+
1098
+ return !scaleCapped ? scaled : scaled.then(function (tCanvas) {
1099
+ return scale(tCanvas, dW, dH);
1100
+ });
1101
+ }
1102
+
1103
+
1104
+ function _scale(image, wRatio, hRatio) {
1105
+ return new Promise(function(resolve) {
1106
+ var sW = ImageSize.getWidth(image);
1107
+ var sH = ImageSize.getHeight(image);
1108
+ var dW = Math.floor(sW * wRatio);
1109
+ var dH = Math.floor(sH * hRatio);
1110
+ var canvas = Canvas.create(dW, dH);
1111
+ var context = Canvas.get2dContext(canvas);
1112
+
1113
+ context.drawImage(image, 0, 0, sW, sH, 0, 0, dW, dH);
1114
+
1115
+ resolve(canvas);
1116
+ });
1117
+ }
1118
+
1119
+ return {
1120
+ scale: scale
1121
+ };
1122
+
1123
+ });
1124
+
1125
+ /**
1126
+ * ImageTools.js
1127
+ *
1128
+ * Released under LGPL License.
1129
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
1130
+ *
1131
+ * License: http://www.tinymce.com/license
1132
+ * Contributing: http://www.tinymce.com/contributing
1133
+ */
1134
+
1135
+ /**
1136
+ * Modifies image blobs.
1137
+ */
1138
+ define("ephox/imagetools/transformations/ImageTools", [
1139
+ "ephox/imagetools/util/Conversions",
1140
+ "ephox/imagetools/util/Canvas",
1141
+ "ephox/imagetools/util/ImageSize",
1142
+ "ephox/imagetools/transformations/ImageResizerCanvas"
1143
+ ], function(Conversions, Canvas, ImageSize, ImageResizerCanvas) {
1144
+ var revokeImageUrl = Conversions.revokeImageUrl;
1145
+
1146
+ function rotate(blob, angle) {
1147
+ return Conversions.blobToImage(blob).then(function(image) {
1148
+ var canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image)),
1149
+ context = Canvas.get2dContext(canvas),
1150
+ translateX = 0, translateY = 0;
1151
+
1152
+ angle = angle < 0 ? 360 + angle : angle;
1153
+
1154
+ if (angle == 90 || angle == 270) {
1155
+ Canvas.resize(canvas, canvas.height, canvas.width);
1156
+ }
1157
+
1158
+ if (angle == 90 || angle == 180) {
1159
+ translateX = canvas.width;
1160
+ }
1161
+
1162
+ if (angle == 270 || angle == 180) {
1163
+ translateY = canvas.height;
1164
+ }
1165
+
1166
+ context.translate(translateX, translateY);
1167
+ context.rotate(angle * Math.PI / 180);
1168
+ context.drawImage(image, 0, 0);
1169
+ revokeImageUrl(image);
1170
+
1171
+ return Conversions.canvasToBlob(canvas, blob.type);
1172
+ });
1173
+ }
1174
+
1175
+ function flip(blob, axis) {
1176
+ return Conversions.blobToImage(blob).then(function(image) {
1177
+ var canvas = Canvas.create(ImageSize.getWidth(image), ImageSize.getHeight(image)),
1178
+ context = Canvas.get2dContext(canvas);
1179
+
1180
+ if (axis == 'v') {
1181
+ context.scale(1, -1);
1182
+ context.drawImage(image, 0, -canvas.height);
1183
+ } else {
1184
+ context.scale(-1, 1);
1185
+ context.drawImage(image, -canvas.width, 0);
1186
+ }
1187
+
1188
+ revokeImageUrl(image);
1189
+
1190
+ return Conversions.canvasToBlob(canvas);
1191
+ });
1192
+ }
1193
+
1194
+ function crop(blob, x, y, w, h) {
1195
+ return Conversions.blobToImage(blob).then(function(image) {
1196
+ var canvas = Canvas.create(w, h),
1197
+ context = Canvas.get2dContext(canvas);
1198
+
1199
+ context.drawImage(image, -x, -y);
1200
+ revokeImageUrl(image);
1201
+
1202
+ return Conversions.canvasToBlob(canvas);
1203
+ });
1204
+ }
1205
+
1206
+ var revokeImage = function (image) {
1207
+ return function (result) {
1208
+ revokeImageUrl(image);
1209
+ return result;
1210
+ };
1211
+ };
1212
+
1213
+ function resize(blob, w, h) {
1214
+ return Conversions.blobToImage(blob).then(function(image) {
1215
+ var result;
1216
+
1217
+ result = ImageResizerCanvas.scale(image, w, h)
1218
+ .then(function(canvas) {
1219
+ return Conversions.canvasToBlob(canvas, blob.type);
1220
+ })
1221
+ .then(revokeImage(image))
1222
+ .catch(revokeImage(image));
1223
+
1224
+ return result;
1225
+ });
1226
+ }
1227
+
1228
+ return {
1229
+ rotate: rotate,
1230
+ flip: flip,
1231
+ crop: crop,
1232
+ resize: resize
1233
+ };
1234
+ });
1235
+
1236
+ define(
1237
+ 'ephox/imagetools/api/ImageTransformations',
1238
+
1239
+ [
1240
+ 'ephox/imagetools/transformations/Filters',
1241
+ 'ephox/imagetools/transformations/ImageTools'
1242
+ ],
1243
+
1244
+ function (Filters, ImageTools) {
1245
+ var invert = function (blob) {
1246
+ return Filters.invert(blob);
1247
+ };
1248
+
1249
+ var sharpen = function (blob) {
1250
+ return Filters.sharpen(blob);
1251
+ };
1252
+
1253
+ var emboss = function (blob) {
1254
+ return Filters.emboss(blob);
1255
+ };
1256
+
1257
+ var gamma = function (blob, value) {
1258
+ return Filters.gamma(blob, value);
1259
+ };
1260
+
1261
+ var exposure = function (blob, value) {
1262
+ return Filters.exposure(blob, value);
1263
+ };
1264
+
1265
+ var colorize = function (blob, adjustR, adjustG, adjustB) {
1266
+ return Filters.colorize(blob, adjustR, adjustG, adjustB);
1267
+ };
1268
+
1269
+ var brightness = function (blob, adjust) {
1270
+ return Filters.brightness(blob, adjust);
1271
+ };
1272
+
1273
+ var hue = function (blob, adjust) {
1274
+ return Filters.hue(blob, adjust);
1275
+ };
1276
+
1277
+ var saturate = function (blob, adjust) {
1278
+ return Filters.saturate(blob, adjust);
1279
+ };
1280
+
1281
+ var contrast = function (blob, adjust) {
1282
+ return Filters.contrast(blob, adjust);
1283
+ };
1284
+
1285
+ var grayscale = function (blob, adjust) {
1286
+ return Filters.grayscale(blob, adjust);
1287
+ };
1288
+
1289
+ var sepia = function (blob, adjust) {
1290
+ return Filters.sepia(blob, adjust);
1291
+ };
1292
+
1293
+ var flip = function (blob, axis) {
1294
+ return ImageTools.flip(blob, axis);
1295
+ };
1296
+
1297
+ var crop = function (blob, x, y, w, h) {
1298
+ return ImageTools.crop(blob, x, y, w, h);
1299
+ };
1300
+
1301
+ var resize = function (blob, w, h) {
1302
+ return ImageTools.resize(blob, w, h);
1303
+ };
1304
+
1305
+ var rotate = function (blob, angle) {
1306
+ return ImageTools.rotate(blob, angle);
1307
+ };
1308
+
1309
+ return {
1310
+ invert: invert,
1311
+ sharpen: sharpen,
1312
+ emboss: emboss,
1313
+ brightness: brightness,
1314
+ hue: hue,
1315
+ saturate: saturate,
1316
+ contrast: contrast,
1317
+ grayscale: grayscale,
1318
+ sepia: sepia,
1319
+ colorize: colorize,
1320
+ gamma: gamma,
1321
+ exposure: exposure,
1322
+
1323
+ flip: flip,
1324
+ crop: crop,
1325
+ resize: resize,
1326
+ rotate: rotate
1327
+ };
1328
+ }
1329
+ );
1330
+ define(
1331
+ 'ephox/imagetools/api/BlobConversions',
1332
+
1333
+ [
1334
+ 'ephox/imagetools/util/Conversions'
1335
+ ],
1336
+
1337
+ function (Conversions) {
1338
+ var blobToImage = function (image) {
1339
+ return Conversions.blobToImage(image);
1340
+ };
1341
+
1342
+ var imageToBlob = function (blob) {
1343
+ return Conversions.imageToBlob(blob);
1344
+ };
1345
+
1346
+ var blobToDataUri = function (blob) {
1347
+ return Conversions.blobToDataUri(blob);
1348
+ };
1349
+
1350
+ var blobToBase64 = function (blob) {
1351
+ return Conversions.blobToBase64(blob);
1352
+ };
1353
+
1354
+ return {
1355
+ // used outside
1356
+ blobToImage: blobToImage,
1357
+ // used outside
1358
+ imageToBlob: imageToBlob,
1359
+ // used outside
1360
+ blobToDataUri: blobToDataUri,
1361
+ // used outside
1362
+ blobToBase64: blobToBase64
1363
+ };
1364
+ }
1365
+ );
1366
+ defineGlobal("global!tinymce.dom.DOMUtils", tinymce.dom.DOMUtils);
1367
+ defineGlobal("global!tinymce.ui.Factory", tinymce.ui.Factory);
1368
+ defineGlobal("global!tinymce.ui.Form", tinymce.ui.Form);
1369
+ defineGlobal("global!tinymce.ui.Container", tinymce.ui.Container);
1370
+ defineGlobal("global!tinymce.ui.Control", tinymce.ui.Control);
1371
+ defineGlobal("global!tinymce.ui.DragHelper", tinymce.ui.DragHelper);
1372
+ defineGlobal("global!tinymce.geom.Rect", tinymce.geom.Rect);
1373
+ defineGlobal("global!tinymce.dom.DomQuery", tinymce.dom.DomQuery);
1374
+ defineGlobal("global!tinymce.util.Observable", tinymce.util.Observable);
1375
+ defineGlobal("global!tinymce.util.VK", tinymce.util.VK);
1376
+ /**
1377
+ * CropRect.js
1378
+ *
1379
+ * Released under LGPL License.
1380
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1381
+ *
1382
+ * License: http://www.tinymce.com/license
1383
+ * Contributing: http://www.tinymce.com/contributing
1384
+ */
1385
+
1386
+ /**
1387
+ * ...
1388
+ */
1389
+ define("tinymce/imagetoolsplugin/CropRect", [
1390
+ "global!tinymce.dom.DomQuery",
1391
+ "global!tinymce.ui.DragHelper",
1392
+ "global!tinymce.geom.Rect",
1393
+ "global!tinymce.util.Tools",
1394
+ "global!tinymce.util.Observable",
1395
+ "global!tinymce.util.VK"
1396
+ ], function($, DragHelper, Rect, Tools, Observable, VK) {
1397
+ var count = 0;
1398
+
1399
+ return function(currentRect, viewPortRect, clampRect, containerElm, action) {
1400
+ var instance, handles, dragHelpers, blockers, prefix = 'mce-', id = prefix + 'crid-' + (count++);
1401
+
1402
+ handles = [
1403
+ {name: 'move', xMul: 0, yMul: 0, deltaX: 1, deltaY: 1, deltaW: 0, deltaH: 0, label: 'Crop Mask'},
1404
+ {name: 'nw', xMul: 0, yMul: 0, deltaX: 1, deltaY: 1, deltaW: -1, deltaH: -1, label: 'Top Left Crop Handle'},
1405
+ {name: 'ne', xMul: 1, yMul: 0, deltaX: 0, deltaY: 1, deltaW: 1, deltaH: -1, label: 'Top Right Crop Handle'},
1406
+ {name: 'sw', xMul: 0, yMul: 1, deltaX: 1, deltaY: 0, deltaW: -1, deltaH: 1, label: 'Bottom Left Crop Handle'},
1407
+ {name: 'se', xMul: 1, yMul: 1, deltaX: 0, deltaY: 0, deltaW: 1, deltaH: 1, label: 'Bottom Right Crop Handle'}
1408
+ ];
1409
+
1410
+ blockers = ["top", "right", "bottom", "left"];
1411
+
1412
+ function getAbsoluteRect(outerRect, relativeRect) {
1413
+ return {
1414
+ x: relativeRect.x + outerRect.x,
1415
+ y: relativeRect.y + outerRect.y,
1416
+ w: relativeRect.w,
1417
+ h: relativeRect.h
1418
+ };
1419
+ }
1420
+
1421
+ function getRelativeRect(outerRect, innerRect) {
1422
+ return {
1423
+ x: innerRect.x - outerRect.x,
1424
+ y: innerRect.y - outerRect.y,
1425
+ w: innerRect.w,
1426
+ h: innerRect.h
1427
+ };
1428
+ }
1429
+
1430
+ function getInnerRect() {
1431
+ return getRelativeRect(clampRect, currentRect);
1432
+ }
1433
+
1434
+ function moveRect(handle, startRect, deltaX, deltaY) {
1435
+ var x, y, w, h, rect;
1436
+
1437
+ x = startRect.x;
1438
+ y = startRect.y;
1439
+ w = startRect.w;
1440
+ h = startRect.h;
1441
+
1442
+ x += deltaX * handle.deltaX;
1443
+ y += deltaY * handle.deltaY;
1444
+ w += deltaX * handle.deltaW;
1445
+ h += deltaY * handle.deltaH;
1446
+
1447
+ if (w < 20) {
1448
+ w = 20;
1449
+ }
1450
+
1451
+ if (h < 20) {
1452
+ h = 20;
1453
+ }
1454
+
1455
+ rect = currentRect = Rect.clamp({x: x, y: y, w: w, h: h}, clampRect, handle.name == 'move');
1456
+ rect = getRelativeRect(clampRect, rect);
1457
+
1458
+ instance.fire('updateRect', {rect: rect});
1459
+ setInnerRect(rect);
1460
+ }
1461
+
1462
+ function render() {
1463
+ function createDragHelper(handle) {
1464
+ var startRect;
1465
+
1466
+ return new DragHelper(id, {
1467
+ document: containerElm.ownerDocument,
1468
+ handle: id + '-' + handle.name,
1469
+
1470
+ start: function() {
1471
+ startRect = currentRect;
1472
+ },
1473
+
1474
+ drag: function(e) {
1475
+ moveRect(handle, startRect, e.deltaX, e.deltaY);
1476
+ }
1477
+ });
1478
+ }
1479
+
1480
+ $(
1481
+ '<div id="' + id + '" class="' + prefix + 'croprect-container"' +
1482
+ ' role="grid" aria-dropeffect="execute">'
1483
+ ).appendTo(containerElm);
1484
+
1485
+ Tools.each(blockers, function(blocker) {
1486
+ $('#' + id, containerElm).append(
1487
+ '<div id="' + id + '-' + blocker + '"class="' + prefix + 'croprect-block" style="display: none" data-mce-bogus="all">'
1488
+ );
1489
+ });
1490
+
1491
+ Tools.each(handles, function(handle) {
1492
+ $('#' + id, containerElm).append(
1493
+ '<div id="' + id + '-' + handle.name + '" class="' + prefix +
1494
+ 'croprect-handle ' + prefix + 'croprect-handle-' + handle.name + '"' +
1495
+ 'style="display: none" data-mce-bogus="all" role="gridcell" tabindex="-1"' +
1496
+ ' aria-label="' + handle.label + '" aria-grabbed="false">'
1497
+ );
1498
+ });
1499
+
1500
+ dragHelpers = Tools.map(handles, createDragHelper);
1501
+
1502
+ repaint(currentRect);
1503
+
1504
+ $(containerElm).on('focusin focusout', function(e) {
1505
+ $(e.target).attr('aria-grabbed', e.type === 'focus');
1506
+ });
1507
+
1508
+ $(containerElm).on('keydown', function(e) {
1509
+ var activeHandle;
1510
+
1511
+ Tools.each(handles, function(handle) {
1512
+ if (e.target.id == id + '-' + handle.name) {
1513
+ activeHandle = handle;
1514
+ return false;
1515
+ }
1516
+ });
1517
+
1518
+ function moveAndBlock(evt, handle, startRect, deltaX, deltaY) {
1519
+ evt.stopPropagation();
1520
+ evt.preventDefault();
1521
+
1522
+ moveRect(activeHandle, startRect, deltaX, deltaY);
1523
+ }
1524
+
1525
+ switch (e.keyCode) {
1526
+ case VK.LEFT:
1527
+ moveAndBlock(e, activeHandle, currentRect, -10, 0);
1528
+ break;
1529
+
1530
+ case VK.RIGHT:
1531
+ moveAndBlock(e, activeHandle, currentRect, 10, 0);
1532
+ break;
1533
+
1534
+ case VK.UP:
1535
+ moveAndBlock(e, activeHandle, currentRect, 0, -10);
1536
+ break;
1537
+
1538
+ case VK.DOWN:
1539
+ moveAndBlock(e, activeHandle, currentRect, 0, 10);
1540
+ break;
1541
+
1542
+ case VK.ENTER:
1543
+ case VK.SPACEBAR:
1544
+ e.preventDefault();
1545
+ action();
1546
+ break;
1547
+ }
1548
+ });
1549
+ }
1550
+
1551
+ function toggleVisibility(state) {
1552
+ var selectors;
1553
+
1554
+ selectors = Tools.map(handles, function(handle) {
1555
+ return '#' + id + '-' + handle.name;
1556
+ }).concat(Tools.map(blockers, function(blocker) {
1557
+ return '#' + id + '-' + blocker;
1558
+ })).join(',');
1559
+
1560
+ if (state) {
1561
+ $(selectors, containerElm).show();
1562
+ } else {
1563
+ $(selectors, containerElm).hide();
1564
+ }
1565
+ }
1566
+
1567
+ function repaint(rect) {
1568
+ function updateElementRect(name, rect) {
1569
+ if (rect.h < 0) {
1570
+ rect.h = 0;
1571
+ }
1572
+
1573
+ if (rect.w < 0) {
1574
+ rect.w = 0;
1575
+ }
1576
+
1577
+ $('#' + id + '-' + name, containerElm).css({
1578
+ left: rect.x,
1579
+ top: rect.y,
1580
+ width: rect.w,
1581
+ height: rect.h
1582
+ });
1583
+ }
1584
+
1585
+ Tools.each(handles, function(handle) {
1586
+ $('#' + id + '-' + handle.name, containerElm).css({
1587
+ left: rect.w * handle.xMul + rect.x,
1588
+ top: rect.h * handle.yMul + rect.y
1589
+ });
1590
+ });
1591
+
1592
+ updateElementRect('top', {x: viewPortRect.x, y: viewPortRect.y, w: viewPortRect.w, h: rect.y - viewPortRect.y});
1593
+ updateElementRect('right', {x: rect.x + rect.w, y: rect.y, w: viewPortRect.w - rect.x - rect.w + viewPortRect.x, h: rect.h});
1594
+ updateElementRect('bottom', {
1595
+ x: viewPortRect.x,
1596
+ y: rect.y + rect.h,
1597
+ w: viewPortRect.w,
1598
+ h: viewPortRect.h - rect.y - rect.h + viewPortRect.y
1599
+ });
1600
+ updateElementRect('left', {x: viewPortRect.x, y: rect.y, w: rect.x - viewPortRect.x, h: rect.h});
1601
+ updateElementRect('move', rect);
1602
+ }
1603
+
1604
+ function setRect(rect) {
1605
+ currentRect = rect;
1606
+ repaint(currentRect);
1607
+ }
1608
+
1609
+ function setViewPortRect(rect) {
1610
+ viewPortRect = rect;
1611
+ repaint(currentRect);
1612
+ }
1613
+
1614
+ function setInnerRect(rect) {
1615
+ setRect(getAbsoluteRect(clampRect, rect));
1616
+ }
1617
+
1618
+ function setClampRect(rect) {
1619
+ clampRect = rect;
1620
+ repaint(currentRect);
1621
+ }
1622
+
1623
+ function destroy() {
1624
+ Tools.each(dragHelpers, function(helper) {
1625
+ helper.destroy();
1626
+ });
1627
+
1628
+ dragHelpers = [];
1629
+ }
1630
+
1631
+ render(containerElm);
1632
+
1633
+ instance = Tools.extend({
1634
+ toggleVisibility: toggleVisibility,
1635
+ setClampRect: setClampRect,
1636
+ setRect: setRect,
1637
+ getInnerRect: getInnerRect,
1638
+ setInnerRect: setInnerRect,
1639
+ setViewPortRect: setViewPortRect,
1640
+ destroy: destroy
1641
+ }, Observable);
1642
+
1643
+ return instance;
1644
+ };
1645
+ });
1646
+
1647
+ /**
1648
+ * ImagePanel.js
1649
+ *
1650
+ * Released under LGPL License.
1651
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1652
+ *
1653
+ * License: http://www.tinymce.com/license
1654
+ * Contributing: http://www.tinymce.com/contributing
1655
+ */
1656
+
1657
+ /**
1658
+ * ...
1659
+ *
1660
+ * @-x-less ImagePanel.less
1661
+ */
1662
+ define("tinymce/imagetoolsplugin/ImagePanel", [
1663
+ "global!tinymce.ui.Control",
1664
+ "global!tinymce.ui.DragHelper",
1665
+ "global!tinymce.geom.Rect",
1666
+ "global!tinymce.util.Tools",
1667
+ "global!tinymce.util.Promise",
1668
+ "tinymce/imagetoolsplugin/CropRect"
1669
+ ], function(Control, DragHelper, Rect, Tools, Promise, CropRect) {
1670
+ function loadImage(image) {
1671
+ return new Promise(function(resolve) {
1672
+ function loaded() {
1673
+ image.removeEventListener('load', loaded);
1674
+ resolve(image);
1675
+ }
1676
+
1677
+ if (image.complete) {
1678
+ resolve(image);
1679
+ } else {
1680
+ image.addEventListener('load', loaded);
1681
+ }
1682
+ });
1683
+ }
1684
+
1685
+ return Control.extend({
1686
+ Defaults: {
1687
+ classes: "imagepanel"
1688
+ },
1689
+
1690
+ selection: function(rect) {
1691
+ if (arguments.length) {
1692
+ this.state.set('rect', rect);
1693
+ return this;
1694
+ }
1695
+
1696
+ return this.state.get('rect');
1697
+ },
1698
+
1699
+ imageSize: function() {
1700
+ var viewRect = this.state.get('viewRect');
1701
+
1702
+ return {
1703
+ w: viewRect.w,
1704
+ h: viewRect.h
1705
+ };
1706
+ },
1707
+
1708
+ toggleCropRect: function(state) {
1709
+ this.state.set('cropEnabled', state);
1710
+ },
1711
+
1712
+ imageSrc: function(url) {
1713
+ var self = this, img = new Image();
1714
+
1715
+ img.src = url;
1716
+
1717
+ loadImage(img).then(function() {
1718
+ var rect, $img, lastRect = self.state.get('viewRect');
1719
+
1720
+ $img = self.$el.find('img');
1721
+ if ($img[0]) {
1722
+ $img.replaceWith(img);
1723
+ } else {
1724
+ self.getEl().appendChild(img);
1725
+ }
1726
+
1727
+ rect = {x: 0, y: 0, w: img.naturalWidth, h: img.naturalHeight};
1728
+ self.state.set('viewRect', rect);
1729
+ self.state.set('rect', Rect.inflate(rect, -20, -20));
1730
+
1731
+ if (!lastRect || lastRect.w != rect.w || lastRect.h != rect.h) {
1732
+ self.zoomFit();
1733
+ }
1734
+
1735
+ self.repaintImage();
1736
+ self.fire('load');
1737
+ });
1738
+ },
1739
+
1740
+ zoom: function(value) {
1741
+ if (arguments.length) {
1742
+ this.state.set('zoom', value);
1743
+ return this;
1744
+ }
1745
+
1746
+ return this.state.get('zoom');
1747
+ },
1748
+
1749
+ postRender: function() {
1750
+ this.imageSrc(this.settings.imageSrc);
1751
+ return this._super();
1752
+ },
1753
+
1754
+ zoomFit: function() {
1755
+ var self = this, $img, pw, ph, w, h, zoom, padding;
1756
+
1757
+ padding = 10;
1758
+ $img = self.$el.find('img');
1759
+ pw = self.getEl().clientWidth;
1760
+ ph = self.getEl().clientHeight;
1761
+ w = $img[0].naturalWidth;
1762
+ h = $img[0].naturalHeight;
1763
+ zoom = Math.min((pw - padding) / w, (ph - padding) / h);
1764
+
1765
+ if (zoom >= 1) {
1766
+ zoom = 1;
1767
+ }
1768
+
1769
+ self.zoom(zoom);
1770
+ },
1771
+
1772
+ repaintImage: function() {
1773
+ var x, y, w, h, pw, ph, $img, zoom, rect, elm;
1774
+
1775
+ elm = this.getEl();
1776
+ zoom = this.zoom();
1777
+ rect = this.state.get('rect');
1778
+ $img = this.$el.find('img');
1779
+ pw = elm.offsetWidth;
1780
+ ph = elm.offsetHeight;
1781
+ w = $img[0].naturalWidth * zoom;
1782
+ h = $img[0].naturalHeight * zoom;
1783
+ x = Math.max(0, pw / 2 - w / 2);
1784
+ y = Math.max(0, ph / 2 - h / 2);
1785
+
1786
+ $img.css({
1787
+ left: x,
1788
+ top: y,
1789
+ width: w,
1790
+ height: h
1791
+ });
1792
+
1793
+ if (this.cropRect) {
1794
+ this.cropRect.setRect({
1795
+ x: rect.x * zoom + x,
1796
+ y: rect.y * zoom + y,
1797
+ w: rect.w * zoom,
1798
+ h: rect.h * zoom
1799
+ });
1800
+
1801
+ this.cropRect.setClampRect({
1802
+ x: x,
1803
+ y: y,
1804
+ w: w,
1805
+ h: h
1806
+ });
1807
+
1808
+ this.cropRect.setViewPortRect({
1809
+ x: 0,
1810
+ y: 0,
1811
+ w: pw,
1812
+ h: ph
1813
+ });
1814
+ }
1815
+ },
1816
+
1817
+ bindStates: function() {
1818
+ var self = this;
1819
+
1820
+ function setupCropRect(rect) {
1821
+ self.cropRect = new CropRect(
1822
+ rect,
1823
+ self.state.get('viewRect'),
1824
+ self.state.get('viewRect'),
1825
+ self.getEl(),
1826
+ function() {
1827
+ self.fire('crop');
1828
+ }
1829
+ );
1830
+
1831
+ self.cropRect.on('updateRect', function(e) {
1832
+ var rect = e.rect, zoom = self.zoom();
1833
+
1834
+ rect = {
1835
+ x: Math.round(rect.x / zoom),
1836
+ y: Math.round(rect.y / zoom),
1837
+ w: Math.round(rect.w / zoom),
1838
+ h: Math.round(rect.h / zoom)
1839
+ };
1840
+
1841
+ self.state.set('rect', rect);
1842
+ });
1843
+
1844
+ self.on('remove', self.cropRect.destroy);
1845
+ }
1846
+
1847
+ self.state.on('change:cropEnabled', function(e) {
1848
+ self.cropRect.toggleVisibility(e.value);
1849
+ self.repaintImage();
1850
+ });
1851
+
1852
+ self.state.on('change:zoom', function() {
1853
+ self.repaintImage();
1854
+ });
1855
+
1856
+ self.state.on('change:rect', function(e) {
1857
+ var rect = e.value;
1858
+
1859
+ if (!self.cropRect) {
1860
+ setupCropRect(rect);
1861
+ }
1862
+
1863
+ self.cropRect.setRect(rect);
1864
+ });
1865
+ }
1866
+ });
1867
+ });
1868
+
1869
+ /**
1870
+ * UndoStack.js
1871
+ *
1872
+ * Released under LGPL License.
1873
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1874
+ *
1875
+ * License: http://www.tinymce.com/license
1876
+ * Contributing: http://www.tinymce.com/contributing
1877
+ */
1878
+
1879
+ define("tinymce/imagetoolsplugin/UndoStack", [
1880
+ ], function() {
1881
+ return function() {
1882
+ var data = [], index = -1;
1883
+
1884
+ function add(state) {
1885
+ var removed;
1886
+
1887
+ removed = data.splice(++index);
1888
+ data.push(state);
1889
+
1890
+ return {
1891
+ state: state,
1892
+ removed: removed
1893
+ };
1894
+ }
1895
+
1896
+ function undo() {
1897
+ if (canUndo()) {
1898
+ return data[--index];
1899
+ }
1900
+ }
1901
+
1902
+ function redo() {
1903
+ if (canRedo()) {
1904
+ return data[++index];
1905
+ }
1906
+ }
1907
+
1908
+ function canUndo() {
1909
+ return index > 0;
1910
+ }
1911
+
1912
+ function canRedo() {
1913
+ return index != -1 && index < data.length - 1;
1914
+ }
1915
+
1916
+ return {
1917
+ data: data,
1918
+ add: add,
1919
+ undo: undo,
1920
+ redo: redo,
1921
+ canUndo: canUndo,
1922
+ canRedo: canRedo
1923
+ };
1924
+ };
1925
+ });
1926
+
1927
+ /**
1928
+ * Dialog.js
1929
+ *
1930
+ * Released under LGPL License.
1931
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1932
+ *
1933
+ * License: http://www.tinymce.com/license
1934
+ * Contributing: http://www.tinymce.com/contributing
1935
+ */
1936
+
1937
+ /**
1938
+ * ...
1939
+ */
1940
+ define("tinymce/imagetoolsplugin/Dialog", [
1941
+ "global!tinymce.dom.DOMUtils",
1942
+ "global!tinymce.util.Tools",
1943
+ "global!tinymce.util.Promise",
1944
+ "global!tinymce.ui.Factory",
1945
+ "global!tinymce.ui.Form",
1946
+ "global!tinymce.ui.Container",
1947
+ "tinymce/imagetoolsplugin/ImagePanel",
1948
+ "ephox/imagetools/api/ImageTransformations",
1949
+ "ephox/imagetools/api/BlobConversions",
1950
+ "tinymce/imagetoolsplugin/UndoStack"
1951
+ ], function(DOMUtils, Tools, Promise, Factory, Form, Container, ImagePanel, ImageTransformations, BlobConversions, UndoStack) {
1952
+ function createState(blob) {
1953
+ return {
1954
+ blob: blob,
1955
+ url: URL.createObjectURL(blob)
1956
+ };
1957
+ }
1958
+
1959
+ function destroyState(state) {
1960
+ if (state) {
1961
+ URL.revokeObjectURL(state.url);
1962
+ }
1963
+ }
1964
+
1965
+ function destroyStates(states) {
1966
+ Tools.each(states, destroyState);
1967
+ }
1968
+
1969
+ function open(currentState, resolve, reject) {
1970
+ var win, undoStack = new UndoStack(), mainPanel, filtersPanel, tempState,
1971
+ cropPanel, resizePanel, flipRotatePanel, imagePanel, sidePanel, mainViewContainer,
1972
+ invertPanel, brightnessPanel, huePanel, saturatePanel, contrastPanel, grayscalePanel,
1973
+ sepiaPanel, colorizePanel, sharpenPanel, embossPanel, gammaPanel, exposurePanel, panels,
1974
+ width, height, ratioW, ratioH;
1975
+
1976
+ function recalcSize(e) {
1977
+ var widthCtrl, heightCtrl, newWidth, newHeight;
1978
+
1979
+ widthCtrl = win.find('#w')[0];
1980
+ heightCtrl = win.find('#h')[0];
1981
+
1982
+ newWidth = parseInt(widthCtrl.value(), 10);
1983
+ newHeight = parseInt(heightCtrl.value(), 10);
1984
+
1985
+ if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
1986
+ if (e.control.settings.name == 'w') {
1987
+ newHeight = Math.round(newWidth * ratioW);
1988
+ heightCtrl.value(newHeight);
1989
+ } else {
1990
+ newWidth = Math.round(newHeight * ratioH);
1991
+ widthCtrl.value(newWidth);
1992
+ }
1993
+ }
1994
+
1995
+ width = newWidth;
1996
+ height = newHeight;
1997
+ }
1998
+
1999
+ function floatToPercent(value) {
2000
+ return Math.round(value * 100) + '%';
2001
+ }
2002
+
2003
+ function updateButtonUndoStates() {
2004
+ win.find('#undo').disabled(!undoStack.canUndo());
2005
+ win.find('#redo').disabled(!undoStack.canRedo());
2006
+ win.statusbar.find('#save').disabled(!undoStack.canUndo());
2007
+ }
2008
+
2009
+ function disableUndoRedo() {
2010
+ win.find('#undo').disabled(true);
2011
+ win.find('#redo').disabled(true);
2012
+ }
2013
+
2014
+ function displayState(state) {
2015
+ if (state) {
2016
+ imagePanel.imageSrc(state.url);
2017
+ }
2018
+ }
2019
+
2020
+ function switchPanel(targetPanel) {
2021
+ return function() {
2022
+ var hidePanels = Tools.grep(panels, function(panel) {
2023
+ return panel.settings.name != targetPanel;
2024
+ });
2025
+
2026
+ Tools.each(hidePanels, function(panel) {
2027
+ panel.hide();
2028
+ });
2029
+
2030
+ targetPanel.show();
2031
+ targetPanel.focus();
2032
+ };
2033
+ }
2034
+
2035
+ function addTempState(blob) {
2036
+ tempState = createState(blob);
2037
+ displayState(tempState);
2038
+ }
2039
+
2040
+ function addBlobState(blob) {
2041
+ currentState = createState(blob);
2042
+ displayState(currentState);
2043
+ destroyStates(undoStack.add(currentState).removed);
2044
+ updateButtonUndoStates();
2045
+ }
2046
+
2047
+ function crop() {
2048
+ var rect = imagePanel.selection();
2049
+
2050
+ ImageTransformations.crop(currentState.blob, rect.x, rect.y, rect.w, rect.h).then(function(blob) {
2051
+ addBlobState(blob);
2052
+ cancel();
2053
+ });
2054
+ }
2055
+
2056
+ function tempAction(fn) {
2057
+ var args = [].slice.call(arguments, 1);
2058
+
2059
+ return function() {
2060
+ var state = tempState || currentState;
2061
+
2062
+ fn.apply(this, [state.blob].concat(args)).then(addTempState);
2063
+ };
2064
+ }
2065
+
2066
+ function action(fn) {
2067
+ var args = [].slice.call(arguments, 1);
2068
+
2069
+ return function() {
2070
+ fn.apply(this, [currentState.blob].concat(args)).then(addBlobState);
2071
+ };
2072
+ }
2073
+
2074
+ function cancel() {
2075
+ displayState(currentState);
2076
+ destroyState(tempState);
2077
+ switchPanel(mainPanel)();
2078
+ updateButtonUndoStates();
2079
+ }
2080
+
2081
+ function applyTempState() {
2082
+ if (tempState) {
2083
+ addBlobState(tempState.blob);
2084
+ cancel();
2085
+ }
2086
+ }
2087
+
2088
+ function zoomIn() {
2089
+ var zoom = imagePanel.zoom();
2090
+
2091
+ if (zoom < 2) {
2092
+ zoom += 0.1;
2093
+ }
2094
+
2095
+ imagePanel.zoom(zoom);
2096
+ }
2097
+
2098
+ function zoomOut() {
2099
+ var zoom = imagePanel.zoom();
2100
+
2101
+ if (zoom > 0.1) {
2102
+ zoom -= 0.1;
2103
+ }
2104
+
2105
+ imagePanel.zoom(zoom);
2106
+ }
2107
+
2108
+ function undo() {
2109
+ currentState = undoStack.undo();
2110
+ displayState(currentState);
2111
+ updateButtonUndoStates();
2112
+ }
2113
+
2114
+ function redo() {
2115
+ currentState = undoStack.redo();
2116
+ displayState(currentState);
2117
+ updateButtonUndoStates();
2118
+ }
2119
+
2120
+ function save() {
2121
+ resolve(currentState.blob);
2122
+ win.close();
2123
+ }
2124
+
2125
+ function createPanel(items) {
2126
+ return new Form({
2127
+ layout: 'flex',
2128
+ direction: 'row',
2129
+ labelGap: 5,
2130
+ border: '0 0 1 0',
2131
+ align: 'center',
2132
+ pack: 'center',
2133
+ padding: '0 10 0 10',
2134
+ spacing: 5,
2135
+ flex: 0,
2136
+ minHeight: 60,
2137
+ defaults: {
2138
+ classes: 'imagetool',
2139
+ type: 'button'
2140
+ },
2141
+ items: items
2142
+ });
2143
+ }
2144
+
2145
+ function createFilterPanel(title, filter) {
2146
+ return createPanel([
2147
+ {text: 'Back', onclick: cancel},
2148
+ {type: 'spacer', flex: 1},
2149
+ {text: 'Apply', subtype: 'primary', onclick: applyTempState}
2150
+ ]).hide().on('show', function() {
2151
+ disableUndoRedo();
2152
+
2153
+ filter(currentState.blob).then(function(blob) {
2154
+ var newTempState = createState(blob);
2155
+
2156
+ displayState(newTempState);
2157
+ destroyState(tempState);
2158
+ tempState = newTempState;
2159
+ });
2160
+ });
2161
+ }
2162
+
2163
+ function createVariableFilterPanel(title, filter, value, min, max) {
2164
+ function update(value) {
2165
+ filter(currentState.blob, value).then(function(blob) {
2166
+ var newTempState = createState(blob);
2167
+ displayState(newTempState);
2168
+ destroyState(tempState);
2169
+ tempState = newTempState;
2170
+ });
2171
+ }
2172
+
2173
+ return createPanel([
2174
+ {text: 'Back', onclick: cancel},
2175
+ {type: 'spacer', flex: 1},
2176
+ {
2177
+ type: 'slider',
2178
+ flex: 1,
2179
+ ondragend: function(e) {
2180
+ update(e.value);
2181
+ },
2182
+ minValue: min,
2183
+ maxValue: max,
2184
+ value: value,
2185
+ previewFilter: floatToPercent
2186
+ },
2187
+ {type: 'spacer', flex: 1},
2188
+ {text: 'Apply', subtype: 'primary', onclick: applyTempState}
2189
+ ]).hide().on('show', function() {
2190
+ this.find('slider').value(value);
2191
+ disableUndoRedo();
2192
+ });
2193
+ }
2194
+
2195
+ function createRgbFilterPanel(title, filter) {
2196
+ function update() {
2197
+ var r, g, b;
2198
+
2199
+ r = win.find('#r')[0].value();
2200
+ g = win.find('#g')[0].value();
2201
+ b = win.find('#b')[0].value();
2202
+
2203
+ filter(currentState.blob, r, g, b).then(function(blob) {
2204
+ var newTempState = createState(blob);
2205
+ displayState(newTempState);
2206
+ destroyState(tempState);
2207
+ tempState = newTempState;
2208
+ });
2209
+ }
2210
+
2211
+ return createPanel([
2212
+ {text: 'Back', onclick: cancel},
2213
+ {type: 'spacer', flex: 1},
2214
+ {
2215
+ type: 'slider', label: 'R', name: 'r', minValue: 0,
2216
+ value: 1, maxValue: 2, ondragend: update, previewFilter: floatToPercent
2217
+ },
2218
+ {
2219
+ type: 'slider', label: 'G', name: 'g', minValue: 0,
2220
+ value: 1, maxValue: 2, ondragend: update, previewFilter: floatToPercent
2221
+ },
2222
+ {
2223
+ type: 'slider', label: 'B', name: 'b', minValue: 0,
2224
+ value: 1, maxValue: 2, ondragend: update, previewFilter: floatToPercent
2225
+ },
2226
+ {type: 'spacer', flex: 1},
2227
+ {text: 'Apply', subtype: 'primary', onclick: applyTempState}
2228
+ ]).hide().on('show', function() {
2229
+ win.find('#r,#g,#b').value(1);
2230
+ disableUndoRedo();
2231
+ });
2232
+ }
2233
+
2234
+ cropPanel = createPanel([
2235
+ {text: 'Back', onclick: cancel},
2236
+ {type: 'spacer', flex: 1},
2237
+ {text: 'Apply', subtype: 'primary', onclick: crop}
2238
+ ]).hide().on('show hide', function(e) {
2239
+ imagePanel.toggleCropRect(e.type == 'show');
2240
+ }).on('show', disableUndoRedo);
2241
+
2242
+ function toggleConstrain(e) {
2243
+ if (e.control.value() === true) {
2244
+ ratioW = height / width;
2245
+ ratioH = width / height;
2246
+ }
2247
+ }
2248
+
2249
+ resizePanel = createPanel([
2250
+ {text: 'Back', onclick: cancel},
2251
+ {type: 'spacer', flex: 1},
2252
+ {type: 'textbox', name: 'w', label: 'Width', size: 4, onkeyup: recalcSize},
2253
+ {type: 'textbox', name: 'h', label: 'Height', size: 4, onkeyup: recalcSize},
2254
+ {type: 'checkbox', name: 'constrain', text: 'Constrain proportions', checked: true, onchange: toggleConstrain},
2255
+ {type: 'spacer', flex: 1},
2256
+ {text: 'Apply', subtype: 'primary', onclick: 'submit'}
2257
+ ]).hide().on('submit', function(e) {
2258
+ var width = parseInt(win.find('#w').value(), 10),
2259
+ height = parseInt(win.find('#h').value(), 10);
2260
+
2261
+ e.preventDefault();
2262
+
2263
+ action(ImageTransformations.resize, width, height)();
2264
+ cancel();
2265
+ }).on('show', disableUndoRedo);
2266
+
2267
+ flipRotatePanel = createPanel([
2268
+ {text: 'Back', onclick: cancel},
2269
+ {type: 'spacer', flex: 1},
2270
+ {icon: 'fliph', tooltip: 'Flip horizontally', onclick: tempAction(ImageTransformations.flip, 'h')},
2271
+ {icon: 'flipv', tooltip: 'Flip vertically', onclick: tempAction(ImageTransformations.flip, 'v')},
2272
+ {icon: 'rotateleft', tooltip: 'Rotate counterclockwise', onclick: tempAction(ImageTransformations.rotate, -90)},
2273
+ {icon: 'rotateright', tooltip: 'Rotate clockwise', onclick: tempAction(ImageTransformations.rotate, 90)},
2274
+ {type: 'spacer', flex: 1},
2275
+ {text: 'Apply', subtype: 'primary', onclick: applyTempState}
2276
+ ]).hide().on('show', disableUndoRedo);
2277
+
2278
+ invertPanel = createFilterPanel("Invert", ImageTransformations.invert);
2279
+ sharpenPanel = createFilterPanel("Sharpen", ImageTransformations.sharpen);
2280
+ embossPanel = createFilterPanel("Emboss", ImageTransformations.emboss);
2281
+
2282
+ brightnessPanel = createVariableFilterPanel("Brightness", ImageTransformations.brightness, 0, -1, 1);
2283
+ huePanel = createVariableFilterPanel("Hue", ImageTransformations.hue, 180, 0, 360);
2284
+ saturatePanel = createVariableFilterPanel("Saturate", ImageTransformations.saturate, 0, -1, 1);
2285
+ contrastPanel = createVariableFilterPanel("Contrast", ImageTransformations.contrast, 0, -1, 1);
2286
+ grayscalePanel = createVariableFilterPanel("Grayscale", ImageTransformations.grayscale, 0, 0, 1);
2287
+ sepiaPanel = createVariableFilterPanel("Sepia", ImageTransformations.sepia, 0, 0, 1);
2288
+ colorizePanel = createRgbFilterPanel("Colorize", ImageTransformations.colorize);
2289
+ gammaPanel = createVariableFilterPanel("Gamma", ImageTransformations.gamma, 0, -1, 1);
2290
+ exposurePanel = createVariableFilterPanel("Exposure", ImageTransformations.exposure, 1, 0, 2);
2291
+
2292
+ filtersPanel = createPanel([
2293
+ {text: 'Back', onclick: cancel},
2294
+ {type: 'spacer', flex: 1},
2295
+ {text: 'hue', icon: 'hue', onclick: switchPanel(huePanel)},
2296
+ {text: 'saturate', icon: 'saturate', onclick: switchPanel(saturatePanel)},
2297
+ {text: 'sepia', icon: 'sepia', onclick: switchPanel(sepiaPanel)},
2298
+ {text: 'emboss', icon: 'emboss', onclick: switchPanel(embossPanel)},
2299
+ {text: 'exposure', icon: 'exposure', onclick: switchPanel(exposurePanel)},
2300
+ {type: 'spacer', flex: 1}
2301
+ ]).hide();
2302
+
2303
+ mainPanel = createPanel([
2304
+ {tooltip: 'Crop', icon: 'crop', onclick: switchPanel(cropPanel)},
2305
+ {tooltip: 'Resize', icon: 'resize2', onclick: switchPanel(resizePanel)},
2306
+ {tooltip: 'Orientation', icon: 'orientation', onclick: switchPanel(flipRotatePanel)},
2307
+ {tooltip: 'Brightness', icon: 'sun', onclick: switchPanel(brightnessPanel)},
2308
+ {tooltip: 'Sharpen', icon: 'sharpen', onclick: switchPanel(sharpenPanel)},
2309
+ {tooltip: 'Contrast', icon: 'contrast', onclick: switchPanel(contrastPanel)},
2310
+ {tooltip: 'Color levels', icon: 'drop', onclick: switchPanel(colorizePanel)},
2311
+ {tooltip: 'Gamma', icon: 'gamma', onclick: switchPanel(gammaPanel)},
2312
+ {tooltip: 'Invert', icon: 'invert', onclick: switchPanel(invertPanel)}
2313
+ //{text: 'More', onclick: switchPanel(filtersPanel)}
2314
+ ]);
2315
+
2316
+ imagePanel = new ImagePanel({
2317
+ flex: 1,
2318
+ imageSrc: currentState.url
2319
+ });
2320
+
2321
+ sidePanel = new Container({
2322
+ layout: 'flex',
2323
+ direction: 'column',
2324
+ border: '0 1 0 0',
2325
+ padding: 5,
2326
+ spacing: 5,
2327
+ items: [
2328
+ {type: 'button', icon: 'undo', tooltip: 'Undo', name: 'undo', onclick: undo},
2329
+ {type: 'button', icon: 'redo', tooltip: 'Redo', name: 'redo', onclick: redo},
2330
+ {type: 'button', icon: 'zoomin', tooltip: 'Zoom in', onclick: zoomIn},
2331
+ {type: 'button', icon: 'zoomout', tooltip: 'Zoom out', onclick: zoomOut}
2332
+ ]
2333
+ });
2334
+
2335
+ mainViewContainer = new Container({
2336
+ type: 'container',
2337
+ layout: 'flex',
2338
+ direction: 'row',
2339
+ align: 'stretch',
2340
+ flex: 1,
2341
+ items: [sidePanel, imagePanel]
2342
+ });
2343
+
2344
+ panels = [
2345
+ mainPanel,
2346
+ cropPanel,
2347
+ resizePanel,
2348
+ flipRotatePanel,
2349
+ filtersPanel,
2350
+ invertPanel,
2351
+ brightnessPanel,
2352
+ huePanel,
2353
+ saturatePanel,
2354
+ contrastPanel,
2355
+ grayscalePanel,
2356
+ sepiaPanel,
2357
+ colorizePanel,
2358
+ sharpenPanel,
2359
+ embossPanel,
2360
+ gammaPanel,
2361
+ exposurePanel
2362
+ ];
2363
+
2364
+ win = Factory.create('window', {
2365
+ layout: 'flex',
2366
+ direction: 'column',
2367
+ align: 'stretch',
2368
+ minWidth: Math.min(DOMUtils.DOM.getViewPort().w, 800),
2369
+ minHeight: Math.min(DOMUtils.DOM.getViewPort().h, 650),
2370
+ title: 'Edit image',
2371
+ items: panels.concat([mainViewContainer]),
2372
+ buttons: [
2373
+ {text: 'Save', name: 'save', subtype: 'primary', onclick: save},
2374
+ {text: 'Cancel', onclick: 'close'}
2375
+ ]
2376
+ });
2377
+
2378
+ win.renderTo(document.body).reflow();
2379
+
2380
+ win.on('close', function() {
2381
+ reject();
2382
+ destroyStates(undoStack.data);
2383
+ undoStack = null;
2384
+ tempState = null;
2385
+ });
2386
+
2387
+ undoStack.add(currentState);
2388
+ updateButtonUndoStates();
2389
+
2390
+ imagePanel.on('load', function() {
2391
+ width = imagePanel.imageSize().w;
2392
+ height = imagePanel.imageSize().h;
2393
+ ratioW = height / width;
2394
+ ratioH = width / height;
2395
+
2396
+ win.find('#w').value(width);
2397
+ win.find('#h').value(height);
2398
+ });
2399
+
2400
+ imagePanel.on('crop', crop);
2401
+ }
2402
+
2403
+ function edit(blob) {
2404
+ return new Promise(function(resolve, reject) {
2405
+ open(createState(blob), resolve, reject);
2406
+ });
2407
+ }
2408
+
2409
+ //edit('img/dogleft.jpg');
2410
+
2411
+ return {
2412
+ edit: edit
2413
+ };
2414
+ });
2415
+
2416
+ /**
2417
+ * ImageSize.js
2418
+ *
2419
+ * Released under LGPL License.
2420
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
2421
+ *
2422
+ * License: http://www.tinymce.com/license
2423
+ * Contributing: http://www.tinymce.com/contributing
2424
+ */
2425
+
2426
+ define("tinymce/imagetoolsplugin/ImageSize", [
2427
+ ], function() {
2428
+ function getImageSize(img) {
2429
+ var width, height;
2430
+
2431
+ function isPxValue(value) {
2432
+ return /^[0-9\.]+px$/.test(value);
2433
+ }
2434
+
2435
+ width = img.style.width;
2436
+ height = img.style.height;
2437
+ if (width || height) {
2438
+ if (isPxValue(width) && isPxValue(height)) {
2439
+ return {
2440
+ w: parseInt(width, 10),
2441
+ h: parseInt(height, 10)
2442
+ };
2443
+ }
2444
+
2445
+ return null;
2446
+ }
2447
+
2448
+ width = img.width;
2449
+ height = img.height;
2450
+
2451
+ if (width && height) {
2452
+ return {
2453
+ w: parseInt(width, 10),
2454
+ h: parseInt(height, 10)
2455
+ };
2456
+ }
2457
+
2458
+ return null;
2459
+ }
2460
+
2461
+ function setImageSize(img, size) {
2462
+ var width, height;
2463
+
2464
+ if (size) {
2465
+ width = img.style.width;
2466
+ height = img.style.height;
2467
+
2468
+ if (width || height) {
2469
+ img.style.width = size.w + 'px';
2470
+ img.style.height = size.h + 'px';
2471
+ img.removeAttribute('data-mce-style');
2472
+ }
2473
+
2474
+ width = img.width;
2475
+ height = img.height;
2476
+
2477
+ if (width || height) {
2478
+ img.setAttribute('width', size.w);
2479
+ img.setAttribute('height', size.h);
2480
+ }
2481
+ }
2482
+ }
2483
+
2484
+ function getNaturalImageSize(img) {
2485
+ return {
2486
+ w: img.naturalWidth,
2487
+ h: img.naturalHeight
2488
+ };
2489
+ }
2490
+
2491
+ return {
2492
+ getImageSize: getImageSize,
2493
+ setImageSize: setImageSize,
2494
+ getNaturalImageSize: getNaturalImageSize
2495
+ };
2496
+ });
2497
+
2498
+ /**
2499
+ * Utils.js
2500
+ *
2501
+ * Released under LGPL License.
2502
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
2503
+ *
2504
+ * License: http://www.tinymce.com/license
2505
+ * Contributing: http://www.tinymce.com/contributing
2506
+ */
2507
+
2508
+ define("tinymce/imagetoolsplugin/Utils", [
2509
+ "global!tinymce.util.Promise",
2510
+ "global!tinymce.util.Tools"
2511
+ ], function(Promise, Tools) {
2512
+ var isValue = function (obj) {
2513
+ return obj !== null && obj !== undefined;
2514
+ };
2515
+
2516
+ var traverse = function (json, path) {
2517
+ var value;
2518
+
2519
+ value = path.reduce(function(result, key) {
2520
+ return isValue(result) ? result[key] : undefined;
2521
+ }, json);
2522
+
2523
+ return isValue(value) ? value : null;
2524
+ };
2525
+
2526
+ var requestUrlAsBlob = function (url, headers) {
2527
+ return new Promise(function(resolve) {
2528
+ var xhr;
2529
+
2530
+ xhr = new XMLHttpRequest();
2531
+
2532
+ xhr.onreadystatechange = function () {
2533
+ if (xhr.readyState === 4) {
2534
+ resolve({
2535
+ status: xhr.status,
2536
+ blob: this.response
2537
+ });
2538
+ }
2539
+ };
2540
+
2541
+ xhr.open('GET', url, true);
2542
+
2543
+ Tools.each(headers, function (value, key) {
2544
+ xhr.setRequestHeader(key, value);
2545
+ });
2546
+
2547
+ xhr.responseType = 'blob';
2548
+ xhr.send();
2549
+ });
2550
+ };
2551
+
2552
+ var readBlob = function (blob) {
2553
+ return new Promise(function(resolve) {
2554
+ var fr = new FileReader();
2555
+
2556
+ fr.onload = function (e) {
2557
+ var data = e.target;
2558
+ resolve(data.result);
2559
+ };
2560
+
2561
+ fr.readAsText(blob);
2562
+ });
2563
+ };
2564
+
2565
+ var parseJson = function (text) {
2566
+ var json;
2567
+
2568
+ try {
2569
+ json = JSON.parse(text);
2570
+ } catch (ex) {
2571
+ // Ignore
2572
+ }
2573
+
2574
+ return json;
2575
+ };
2576
+
2577
+ return {
2578
+ traverse: traverse,
2579
+ readBlob: readBlob,
2580
+ requestUrlAsBlob: requestUrlAsBlob,
2581
+ parseJson: parseJson
2582
+ };
2583
+ });
2584
+
2585
+ /**
2586
+ * Proxy.js
2587
+ *
2588
+ * Released under LGPL License.
2589
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
2590
+ *
2591
+ * License: http://www.tinymce.com/license
2592
+ * Contributing: http://www.tinymce.com/contributing
2593
+ */
2594
+
2595
+ /**
2596
+ * Handles loading images though a proxy for working around cors.
2597
+ */
2598
+ define("tinymce/imagetoolsplugin/Proxy", [
2599
+ "global!tinymce.util.Promise",
2600
+ "global!tinymce.util.Tools",
2601
+ "tinymce/imagetoolsplugin/Utils"
2602
+ ], function(Promise, Tools, Utils) {
2603
+ var isServiceErrorCode = function (code) {
2604
+ return code === 400 || code === 403 || code === 500;
2605
+ };
2606
+
2607
+ var handleHttpError = function (status) {
2608
+ return Promise.reject("ImageProxy HTTP error: " + status);
2609
+ };
2610
+
2611
+ var proxyServiceError = function (error) {
2612
+ Promise.reject("ImageProxy Service error: " + error);
2613
+ };
2614
+
2615
+ var handleServiceError = function (status, blob) {
2616
+ return Utils.readBlob(blob).then(function(text) {
2617
+ var serviceError = Utils.parseJson(text);
2618
+ var errorType = Utils.traverse(serviceError, ['error', 'type']);
2619
+ return errorType ? proxyServiceError(errorType) : proxyServiceError('Invalid JSON');
2620
+ });
2621
+ };
2622
+
2623
+ var handleServiceErrorResponse = function (status, blob) {
2624
+ return isServiceErrorCode(status) ? handleServiceError(status, blob) : handleHttpError(status);
2625
+ };
2626
+
2627
+ var requestServiceBlob = function (url, apiKey) {
2628
+ return Utils.requestUrlAsBlob(url, {
2629
+ 'Content-Type': 'application/json;charset=UTF-8',
2630
+ 'tiny-api-key': apiKey
2631
+ }).then(function (result) {
2632
+ return result.status >= 400 ? handleServiceErrorResponse(result.status, result.blob) : Promise.resolve(result.blob);
2633
+ });
2634
+ };
2635
+
2636
+ function requestBlob(url) {
2637
+ return Utils.requestUrlAsBlob(url, {}).then(function (result) {
2638
+ return result.status >= 400 ? handleHttpError(result.status) : Promise.resolve(result.blob);
2639
+ });
2640
+ }
2641
+
2642
+ var getUrl = function (url, apiKey) {
2643
+ return apiKey ? requestServiceBlob(url, apiKey) : requestBlob(url);
2644
+ };
2645
+
2646
+ return {
2647
+ getUrl: getUrl
2648
+ };
2649
+ });
2650
+
2651
+ /**
2652
+ * Plugin.js
2653
+ *
2654
+ * Released under LGPL License.
2655
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
2656
+ *
2657
+ * License: http://www.tinymce.com/license
2658
+ * Contributing: http://www.tinymce.com/contributing
2659
+ */
2660
+
2661
+ /**
2662
+ *
2663
+ * Settings:
2664
+ * imagetools_cors_hosts - Array of remote domains that has CORS setup.
2665
+ * imagetools_proxy - Url to proxy that streams images from remote host to local host.
2666
+ * imagetools_toolbar - Toolbar items to render when an editable image is selected.
2667
+ */
2668
+ define("tinymce/imagetoolsplugin/Plugin", [
2669
+ "global!tinymce.PluginManager",
2670
+ "global!tinymce.Env",
2671
+ "global!tinymce.util.Promise",
2672
+ "global!tinymce.util.URI",
2673
+ "global!tinymce.util.Tools",
2674
+ "global!tinymce.util.Delay",
2675
+ "ephox/imagetools/api/ImageTransformations",
2676
+ "ephox/imagetools/api/BlobConversions",
2677
+ "tinymce/imagetoolsplugin/Dialog",
2678
+ "tinymce/imagetoolsplugin/ImageSize",
2679
+ "tinymce/imagetoolsplugin/Proxy"
2680
+ ], function(PluginManager, Env, Promise, URI, Tools, Delay, ImageTransformations, BlobConversions, Dialog, ImageSize, Proxy) {
2681
+ var plugin = function(editor) {
2682
+ var count = 0, imageUploadTimer, lastSelectedImage;
2683
+
2684
+ if (!Env.fileApi) {
2685
+ return;
2686
+ }
2687
+
2688
+ function displayError(error) {
2689
+ editor.notificationManager.open({
2690
+ text: error,
2691
+ type: 'error'
2692
+ });
2693
+ }
2694
+
2695
+ function getSelectedImage() {
2696
+ return editor.selection.getNode();
2697
+ }
2698
+
2699
+ function createId() {
2700
+ return 'imagetools' + count++;
2701
+ }
2702
+
2703
+ function isLocalImage(img) {
2704
+ var url = img.src;
2705
+
2706
+ return url.indexOf('data:') === 0 || url.indexOf('blob:') === 0 || new URI(url).host === editor.documentBaseURI.host;
2707
+ }
2708
+
2709
+ function isCorsImage(img) {
2710
+ return Tools.inArray(editor.settings.imagetools_cors_hosts, new URI(img.src).host) !== -1;
2711
+ }
2712
+
2713
+ function getApiKey() {
2714
+ return editor.settings.api_key || editor.settings.imagetools_api_key;
2715
+ }
2716
+
2717
+ function imageToBlob(img) {
2718
+ var src = img.src, apiKey;
2719
+
2720
+ if (isCorsImage(img)) {
2721
+ return Proxy.getUrl(img.src, null);
2722
+ }
2723
+
2724
+ if (!isLocalImage(img)) {
2725
+ src = editor.settings.imagetools_proxy;
2726
+ src += (src.indexOf('?') === -1 ? '?' : '&') + 'url=' + encodeURIComponent(img.src);
2727
+ apiKey = getApiKey();
2728
+ return Proxy.getUrl(src, apiKey);
2729
+ }
2730
+
2731
+ return BlobConversions.imageToBlob(img);
2732
+ }
2733
+
2734
+ function findSelectedBlob() {
2735
+ var blobInfo;
2736
+
2737
+ blobInfo = editor.editorUpload.blobCache.getByUri(getSelectedImage().src);
2738
+ if (blobInfo) {
2739
+ return blobInfo.blob();
2740
+ }
2741
+
2742
+ return imageToBlob(getSelectedImage());
2743
+ }
2744
+
2745
+ function startTimedUpload() {
2746
+ imageUploadTimer = Delay.setEditorTimeout(editor, function() {
2747
+ editor.editorUpload.uploadImagesAuto();
2748
+ }, 30000);
2749
+ }
2750
+
2751
+ function cancelTimedUpload() {
2752
+ clearTimeout(imageUploadTimer);
2753
+ }
2754
+
2755
+ function updateSelectedImage(blob, uploadImmediately) {
2756
+ return BlobConversions.blobToDataUri(blob).then(function(dataUri) {
2757
+ var id, base64, blobCache, blobInfo, selectedImage;
2758
+
2759
+ selectedImage = getSelectedImage();
2760
+ id = createId();
2761
+ blobCache = editor.editorUpload.blobCache;
2762
+ base64 = URI.parseDataUri(dataUri).data;
2763
+
2764
+ blobInfo = blobCache.create(id, blob, base64);
2765
+ blobCache.add(blobInfo);
2766
+
2767
+ editor.undoManager.transact(function() {
2768
+ function imageLoadedHandler() {
2769
+ editor.$(selectedImage).off('load', imageLoadedHandler);
2770
+ editor.nodeChanged();
2771
+
2772
+ if (uploadImmediately) {
2773
+ editor.editorUpload.uploadImagesAuto();
2774
+ } else {
2775
+ cancelTimedUpload();
2776
+ startTimedUpload();
2777
+ }
2778
+ }
2779
+
2780
+ editor.$(selectedImage).on('load', imageLoadedHandler);
2781
+
2782
+ editor.$(selectedImage).attr({
2783
+ src: blobInfo.blobUri()
2784
+ }).removeAttr('data-mce-src');
2785
+ });
2786
+
2787
+ return blobInfo;
2788
+ });
2789
+ }
2790
+
2791
+ function selectedImageOperation(fn) {
2792
+ return function() {
2793
+ return editor._scanForImages().then(findSelectedBlob).then(fn).then(updateSelectedImage, displayError);
2794
+ };
2795
+ }
2796
+
2797
+ function rotate(angle) {
2798
+ return function() {
2799
+ return selectedImageOperation(function(blob) {
2800
+ var size = ImageSize.getImageSize(getSelectedImage());
2801
+
2802
+ if (size) {
2803
+ ImageSize.setImageSize(getSelectedImage(), {
2804
+ w: size.h,
2805
+ h: size.w
2806
+ });
2807
+ }
2808
+
2809
+ return ImageTransformations.rotate(blob, angle);
2810
+ })();
2811
+ };
2812
+ }
2813
+
2814
+ function flip(axis) {
2815
+ return function() {
2816
+ return selectedImageOperation(function(blob) {
2817
+ return ImageTransformations.flip(blob, axis);
2818
+ })();
2819
+ };
2820
+ }
2821
+
2822
+ function editImageDialog() {
2823
+ var img = getSelectedImage(), originalSize = ImageSize.getNaturalImageSize(img);
2824
+ var handleDialogBlob = function(blob) {
2825
+ return new Promise(function(resolve) {
2826
+ BlobConversions.blobToImage(blob).then(function(newImage) {
2827
+ var newSize = ImageSize.getNaturalImageSize(newImage);
2828
+
2829
+ if (originalSize.w != newSize.w || originalSize.h != newSize.h) {
2830
+ if (ImageSize.getImageSize(img)) {
2831
+ ImageSize.setImageSize(img, newSize);
2832
+ }
2833
+ }
2834
+
2835
+ URL.revokeObjectURL(newImage.src);
2836
+ resolve(blob);
2837
+ });
2838
+ });
2839
+ };
2840
+
2841
+ var openDialog = function (blob) {
2842
+ return Dialog.edit(blob).then(handleDialogBlob).then(function(blob) {
2843
+ updateSelectedImage(blob, true);
2844
+ }, function () {
2845
+ // Close dialog
2846
+ });
2847
+ };
2848
+
2849
+ if (img) {
2850
+ imageToBlob(img).then(openDialog, displayError);
2851
+ }
2852
+ }
2853
+
2854
+ function addButtons() {
2855
+ editor.addButton('rotateleft', {
2856
+ title: 'Rotate counterclockwise',
2857
+ onclick: rotate(-90)
2858
+ });
2859
+
2860
+ editor.addButton('rotateright', {
2861
+ title: 'Rotate clockwise',
2862
+ onclick: rotate(90)
2863
+ });
2864
+
2865
+ editor.addButton('flipv', {
2866
+ title: 'Flip vertically',
2867
+ onclick: flip('v')
2868
+ });
2869
+
2870
+ editor.addButton('fliph', {
2871
+ title: 'Flip horizontally',
2872
+ onclick: flip('h')
2873
+ });
2874
+
2875
+ editor.addButton('editimage', {
2876
+ title: 'Edit image',
2877
+ onclick: editImageDialog
2878
+ });
2879
+
2880
+ editor.addButton('imageoptions', {
2881
+ title: 'Image options',
2882
+ icon: 'options',
2883
+ cmd: 'mceImage'
2884
+ });
2885
+
2886
+ /*
2887
+ editor.addButton('crop', {
2888
+ title: 'Crop',
2889
+ onclick: startCrop
2890
+ });
2891
+ */
2892
+ }
2893
+
2894
+ function addEvents() {
2895
+ editor.on('NodeChange', function(e) {
2896
+ //If the last node we selected was an image
2897
+ //And had a source that doesn't match the current blob url
2898
+ //We need to attempt to upload it
2899
+ if (lastSelectedImage && lastSelectedImage.src != e.element.src) {
2900
+ cancelTimedUpload();
2901
+ editor.editorUpload.uploadImagesAuto();
2902
+ lastSelectedImage = undefined;
2903
+ }
2904
+
2905
+ //Set up the lastSelectedImage
2906
+ if (isEditableImage(e.element)) {
2907
+ lastSelectedImage = e.element;
2908
+ }
2909
+ });
2910
+ }
2911
+
2912
+ function isEditableImage(img) {
2913
+ var selectorMatched = editor.dom.is(img, 'img:not([data-mce-object],[data-mce-placeholder])');
2914
+
2915
+ return selectorMatched && (isLocalImage(img) || isCorsImage(img) || editor.settings.imagetools_proxy);
2916
+ }
2917
+
2918
+ function addToolbars() {
2919
+ var toolbarItems = editor.settings.imagetools_toolbar;
2920
+
2921
+ if (!toolbarItems) {
2922
+ toolbarItems = 'rotateleft rotateright | flipv fliph | crop editimage imageoptions';
2923
+ }
2924
+
2925
+ editor.addContextToolbar(
2926
+ isEditableImage,
2927
+ toolbarItems
2928
+ );
2929
+ }
2930
+
2931
+ addButtons();
2932
+ addToolbars();
2933
+ addEvents();
2934
+
2935
+ editor.addCommand('mceEditImage', editImageDialog);
2936
+ };
2937
+
2938
+ PluginManager.add('imagetools', plugin);
2939
+
2940
+ return function() {};
2941
+ });
2942
+
2943
+ dem('tinymce/imagetoolsplugin/Plugin')();
2944
+ })();