spiderfw 0.6.38 → 0.6.39

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