xmt_froala 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +2 -0
  5. data/app/assets/javascripts/xmt_froala.js +31 -0
  6. data/app/assets/stylesheets/xmt_froala.css +17 -0
  7. data/app/controllers/xmt_froala/application_controller.rb +5 -0
  8. data/app/controllers/xmt_froala/assets_controller.rb +94 -0
  9. data/app/models/xmt_froala/asset_uploader.rb +107 -0
  10. data/app/models/xmt_froala/file_uploader.rb +10 -0
  11. data/app/models/xmt_froala/flash_uploader.rb +10 -0
  12. data/app/models/xmt_froala/image_uploader.rb +10 -0
  13. data/app/models/xmt_froala/media_uploader.rb +10 -0
  14. data/config/routes.rb +6 -0
  15. data/lib/generators/xmt_froala/install/USAGE +10 -0
  16. data/lib/generators/xmt_froala/install/install_generator.rb +23 -0
  17. data/lib/generators/xmt_froala/install/templates/application.js +17 -0
  18. data/lib/generators/xmt_froala/install/templates/xmt_froala.rb +29 -0
  19. data/lib/generators/xmt_froala/migration/USAGE +14 -0
  20. data/lib/generators/xmt_froala/migration/migration_generator.rb +36 -0
  21. data/lib/generators/xmt_froala/migration/templates/migration/migration.rb +18 -0
  22. data/lib/generators/xmt_froala/migration/templates/models/active_record/xmt_froala/asset.rb +14 -0
  23. data/lib/generators/xmt_froala/migration/templates/models/active_record/xmt_froala/file.rb +3 -0
  24. data/lib/generators/xmt_froala/migration/templates/models/active_record/xmt_froala/flash.rb +3 -0
  25. data/lib/generators/xmt_froala/migration/templates/models/active_record/xmt_froala/image.rb +3 -0
  26. data/lib/generators/xmt_froala/migration/templates/models/active_record/xmt_froala/media.rb +3 -0
  27. data/lib/generators/xmt_froala/migration/templates/models/mongoid/xmt_froala/asset.rb +27 -0
  28. data/lib/generators/xmt_froala/migration/templates/models/mongoid/xmt_froala/file.rb +3 -0
  29. data/lib/generators/xmt_froala/migration/templates/models/mongoid/xmt_froala/flash.rb +3 -0
  30. data/lib/generators/xmt_froala/migration/templates/models/mongoid/xmt_froala/image.rb +3 -0
  31. data/lib/generators/xmt_froala/migration/templates/models/mongoid/xmt_froala/media.rb +3 -0
  32. data/lib/tasks/xmt_froala_tasks.rake +9 -0
  33. data/lib/xmt_froala.rb +65 -0
  34. data/lib/xmt_froala/active_record.rb +14 -0
  35. data/lib/xmt_froala/engine.rb +32 -0
  36. data/lib/xmt_froala/formtastic.rb +12 -0
  37. data/lib/xmt_froala/helper.rb +105 -0
  38. data/lib/xmt_froala/simple_form.rb +11 -0
  39. data/lib/xmt_froala/version.rb +3 -0
  40. data/vendor/assets/javascripts/xmt_froala/froala_editor.js +0 -0
  41. data/vendor/assets/javascripts/xmt_froala/languages/ar.js +318 -0
  42. data/vendor/assets/javascripts/xmt_froala/languages/bs.js +318 -0
  43. data/vendor/assets/javascripts/xmt_froala/languages/cs.js +318 -0
  44. data/vendor/assets/javascripts/xmt_froala/languages/da.js +318 -0
  45. data/vendor/assets/javascripts/xmt_froala/languages/de.js +318 -0
  46. data/vendor/assets/javascripts/xmt_froala/languages/en_ca.js +262 -0
  47. data/vendor/assets/javascripts/xmt_froala/languages/en_gb.js +262 -0
  48. data/vendor/assets/javascripts/xmt_froala/languages/es.js +318 -0
  49. data/vendor/assets/javascripts/xmt_froala/languages/et.js +318 -0
  50. data/vendor/assets/javascripts/xmt_froala/languages/fa.js +318 -0
  51. data/vendor/assets/javascripts/xmt_froala/languages/fi.js +318 -0
  52. data/vendor/assets/javascripts/xmt_froala/languages/fr.js +318 -0
  53. data/vendor/assets/javascripts/xmt_froala/languages/he.js +318 -0
  54. data/vendor/assets/javascripts/xmt_froala/languages/hr.js +318 -0
  55. data/vendor/assets/javascripts/xmt_froala/languages/hu.js +318 -0
  56. data/vendor/assets/javascripts/xmt_froala/languages/id.js +319 -0
  57. data/vendor/assets/javascripts/xmt_froala/languages/it.js +318 -0
  58. data/vendor/assets/javascripts/xmt_froala/languages/ja.js +318 -0
  59. data/vendor/assets/javascripts/xmt_froala/languages/ko.js +318 -0
  60. data/vendor/assets/javascripts/xmt_froala/languages/me.js +318 -0
  61. data/vendor/assets/javascripts/xmt_froala/languages/nb.js +318 -0
  62. data/vendor/assets/javascripts/xmt_froala/languages/nl.js +318 -0
  63. data/vendor/assets/javascripts/xmt_froala/languages/pl.js +318 -0
  64. data/vendor/assets/javascripts/xmt_froala/languages/pt_br.js +318 -0
  65. data/vendor/assets/javascripts/xmt_froala/languages/pt_pt.js +318 -0
  66. data/vendor/assets/javascripts/xmt_froala/languages/ro.js +319 -0
  67. data/vendor/assets/javascripts/xmt_froala/languages/ru.js +318 -0
  68. data/vendor/assets/javascripts/xmt_froala/languages/sk.js +318 -0
  69. data/vendor/assets/javascripts/xmt_froala/languages/sr.js +318 -0
  70. data/vendor/assets/javascripts/xmt_froala/languages/sv.js +318 -0
  71. data/vendor/assets/javascripts/xmt_froala/languages/th.js +318 -0
  72. data/vendor/assets/javascripts/xmt_froala/languages/tr.js +318 -0
  73. data/vendor/assets/javascripts/xmt_froala/languages/uk.js +318 -0
  74. data/vendor/assets/javascripts/xmt_froala/languages/vi.js +258 -0
  75. data/vendor/assets/javascripts/xmt_froala/languages/zh_cn.js +320 -0
  76. data/vendor/assets/javascripts/xmt_froala/languages/zh_tw.js +318 -0
  77. data/vendor/assets/javascripts/xmt_froala/plugins/align.js +139 -0
  78. data/vendor/assets/javascripts/xmt_froala/plugins/align.min.js +7 -0
  79. data/vendor/assets/javascripts/xmt_froala/plugins/char_counter.js +154 -0
  80. data/vendor/assets/javascripts/xmt_froala/plugins/char_counter.min.js +7 -0
  81. data/vendor/assets/javascripts/xmt_froala/plugins/code_beautifier.js +3270 -0
  82. data/vendor/assets/javascripts/xmt_froala/plugins/code_beautifier.min.js +7 -0
  83. data/vendor/assets/javascripts/xmt_froala/plugins/code_view.js +393 -0
  84. data/vendor/assets/javascripts/xmt_froala/plugins/code_view.min.js +7 -0
  85. data/vendor/assets/javascripts/xmt_froala/plugins/colors.js +492 -0
  86. data/vendor/assets/javascripts/xmt_froala/plugins/colors.min.js +7 -0
  87. data/vendor/assets/javascripts/xmt_froala/plugins/draggable.js +459 -0
  88. data/vendor/assets/javascripts/xmt_froala/plugins/draggable.min.js +7 -0
  89. data/vendor/assets/javascripts/xmt_froala/plugins/emoticons.js +509 -0
  90. data/vendor/assets/javascripts/xmt_froala/plugins/emoticons.min.js +7 -0
  91. data/vendor/assets/javascripts/xmt_froala/plugins/entities.js +121 -0
  92. data/vendor/assets/javascripts/xmt_froala/plugins/entities.min.js +7 -0
  93. data/vendor/assets/javascripts/xmt_froala/plugins/file.js +736 -0
  94. data/vendor/assets/javascripts/xmt_froala/plugins/file.min.js +239 -0
  95. data/vendor/assets/javascripts/xmt_froala/plugins/font_family.js +182 -0
  96. data/vendor/assets/javascripts/xmt_froala/plugins/font_family.min.js +7 -0
  97. data/vendor/assets/javascripts/xmt_froala/plugins/font_size.js +118 -0
  98. data/vendor/assets/javascripts/xmt_froala/plugins/font_size.min.js +7 -0
  99. data/vendor/assets/javascripts/xmt_froala/plugins/forms.js +430 -0
  100. data/vendor/assets/javascripts/xmt_froala/plugins/forms.min.js +7 -0
  101. data/vendor/assets/javascripts/xmt_froala/plugins/fullscreen.js +274 -0
  102. data/vendor/assets/javascripts/xmt_froala/plugins/fullscreen.min.js +7 -0
  103. data/vendor/assets/javascripts/xmt_froala/plugins/help.js +216 -0
  104. data/vendor/assets/javascripts/xmt_froala/plugins/help.min.js +7 -0
  105. data/vendor/assets/javascripts/xmt_froala/plugins/image.js +3323 -0
  106. data/vendor/assets/javascripts/xmt_froala/plugins/image.min.js +7 -0
  107. data/vendor/assets/javascripts/xmt_froala/plugins/image_manager.js +1056 -0
  108. data/vendor/assets/javascripts/xmt_froala/plugins/image_manager.min.js +7 -0
  109. data/vendor/assets/javascripts/xmt_froala/plugins/inline_style.js +94 -0
  110. data/vendor/assets/javascripts/xmt_froala/plugins/inline_style.min.js +7 -0
  111. data/vendor/assets/javascripts/xmt_froala/plugins/line_breaker.js +537 -0
  112. data/vendor/assets/javascripts/xmt_froala/plugins/line_breaker.min.js +7 -0
  113. data/vendor/assets/javascripts/xmt_froala/plugins/link.js +1157 -0
  114. data/vendor/assets/javascripts/xmt_froala/plugins/link.min.js +7 -0
  115. data/vendor/assets/javascripts/xmt_froala/plugins/lists.js +462 -0
  116. data/vendor/assets/javascripts/xmt_froala/plugins/lists.min.js +7 -0
  117. data/vendor/assets/javascripts/xmt_froala/plugins/paragraph_format.js +290 -0
  118. data/vendor/assets/javascripts/xmt_froala/plugins/paragraph_format.min.js +7 -0
  119. data/vendor/assets/javascripts/xmt_froala/plugins/paragraph_style.js +144 -0
  120. data/vendor/assets/javascripts/xmt_froala/plugins/paragraph_style.min.js +7 -0
  121. data/vendor/assets/javascripts/xmt_froala/plugins/plain_paste.js +96 -0
  122. data/vendor/assets/javascripts/xmt_froala/plugins/print.js +137 -0
  123. data/vendor/assets/javascripts/xmt_froala/plugins/print.min.js +7 -0
  124. data/vendor/assets/javascripts/xmt_froala/plugins/quick_format.js +89 -0
  125. data/vendor/assets/javascripts/xmt_froala/plugins/quick_insert.js +478 -0
  126. data/vendor/assets/javascripts/xmt_froala/plugins/quick_insert.min.js +7 -0
  127. data/vendor/assets/javascripts/xmt_froala/plugins/quote.js +141 -0
  128. data/vendor/assets/javascripts/xmt_froala/plugins/quote.min.js +7 -0
  129. data/vendor/assets/javascripts/xmt_froala/plugins/save.js +189 -0
  130. data/vendor/assets/javascripts/xmt_froala/plugins/save.min.js +7 -0
  131. data/vendor/assets/javascripts/xmt_froala/plugins/special_characters.js +781 -0
  132. data/vendor/assets/javascripts/xmt_froala/plugins/special_characters.min.js +7 -0
  133. data/vendor/assets/javascripts/xmt_froala/plugins/table.js +4194 -0
  134. data/vendor/assets/javascripts/xmt_froala/plugins/table.min.js +7 -0
  135. data/vendor/assets/javascripts/xmt_froala/plugins/url.js +194 -0
  136. data/vendor/assets/javascripts/xmt_froala/plugins/url.min.js +7 -0
  137. data/vendor/assets/javascripts/xmt_froala/plugins/video.js +2342 -0
  138. data/vendor/assets/javascripts/xmt_froala/plugins/video.min.js +7 -0
  139. data/vendor/assets/javascripts/xmt_froala/plugins/word_paste.js +1403 -0
  140. data/vendor/assets/javascripts/xmt_froala/plugins/word_paste.min.js +7 -0
  141. data/vendor/assets/javascripts/xmt_froala/third_party/embedly.js +543 -0
  142. data/vendor/assets/javascripts/xmt_froala/third_party/embedly.min.js +7 -0
  143. data/vendor/assets/javascripts/xmt_froala/third_party/image_aviary.js +163 -0
  144. data/vendor/assets/javascripts/xmt_froala/third_party/image_aviary.min.js +7 -0
  145. data/vendor/assets/javascripts/xmt_froala/third_party/spell_checker.js +222 -0
  146. data/vendor/assets/javascripts/xmt_froala/third_party/spell_checker.min.js +7 -0
  147. data/vendor/assets/javascripts/xmt_froala/xmt_froala.js +15172 -0
  148. data/vendor/assets/stylesheets/xmt_froala/css/font-awesome.css +2546 -0
  149. data/vendor/assets/stylesheets/xmt_froala/css/froala_editor.min.css +7 -0
  150. data/vendor/assets/stylesheets/xmt_froala/css/froala_editor.pkgd.css +2902 -0
  151. data/vendor/assets/stylesheets/xmt_froala/css/froala_editor.pkgd.min.css +7 -0
  152. data/vendor/assets/stylesheets/xmt_froala/css/froala_style.css +413 -0
  153. data/vendor/assets/stylesheets/xmt_froala/css/froala_style.min.css +7 -0
  154. data/vendor/assets/stylesheets/xmt_froala/css/plugins/char_counter.css +57 -0
  155. data/vendor/assets/stylesheets/xmt_froala/css/plugins/char_counter.min.css +7 -0
  156. data/vendor/assets/stylesheets/xmt_froala/css/plugins/code_view.css +112 -0
  157. data/vendor/assets/stylesheets/xmt_froala/css/plugins/code_view.min.css +7 -0
  158. data/vendor/assets/stylesheets/xmt_froala/css/plugins/colors.css +155 -0
  159. data/vendor/assets/stylesheets/xmt_froala/css/plugins/colors.min.css +7 -0
  160. data/vendor/assets/stylesheets/xmt_froala/css/plugins/draggable.css +43 -0
  161. data/vendor/assets/stylesheets/xmt_froala/css/plugins/draggable.min.css +7 -0
  162. data/vendor/assets/stylesheets/xmt_froala/css/plugins/emoticons.css +42 -0
  163. data/vendor/assets/stylesheets/xmt_froala/css/plugins/emoticons.min.css +7 -0
  164. data/vendor/assets/stylesheets/xmt_froala/css/plugins/file.css +146 -0
  165. data/vendor/assets/stylesheets/xmt_froala/css/plugins/file.min.css +7 -0
  166. data/vendor/assets/stylesheets/xmt_froala/css/plugins/fullscreen.css +28 -0
  167. data/vendor/assets/stylesheets/xmt_froala/css/plugins/fullscreen.min.css +7 -0
  168. data/vendor/assets/stylesheets/xmt_froala/css/plugins/help.css +52 -0
  169. data/vendor/assets/stylesheets/xmt_froala/css/plugins/help.min.css +7 -0
  170. data/vendor/assets/stylesheets/xmt_froala/css/plugins/image.css +244 -0
  171. data/vendor/assets/stylesheets/xmt_froala/css/plugins/image.min.css +7 -0
  172. data/vendor/assets/stylesheets/xmt_froala/css/plugins/image_manager.css +266 -0
  173. data/vendor/assets/stylesheets/xmt_froala/css/plugins/image_manager.min.css +7 -0
  174. data/vendor/assets/stylesheets/xmt_froala/css/plugins/line_breaker.css +37 -0
  175. data/vendor/assets/stylesheets/xmt_froala/css/plugins/line_breaker.min.css +7 -0
  176. data/vendor/assets/stylesheets/xmt_froala/css/plugins/quick_insert.css +70 -0
  177. data/vendor/assets/stylesheets/xmt_froala/css/plugins/quick_insert.min.css +7 -0
  178. data/vendor/assets/stylesheets/xmt_froala/css/plugins/special_characters.css +51 -0
  179. data/vendor/assets/stylesheets/xmt_froala/css/plugins/special_characters.min.css +7 -0
  180. data/vendor/assets/stylesheets/xmt_froala/css/plugins/table.css +181 -0
  181. data/vendor/assets/stylesheets/xmt_froala/css/plugins/table.min.css +7 -0
  182. data/vendor/assets/stylesheets/xmt_froala/css/plugins/video.css +231 -0
  183. data/vendor/assets/stylesheets/xmt_froala/css/plugins/video.min.css +7 -0
  184. data/vendor/assets/stylesheets/xmt_froala/css/themes/dark.css +1281 -0
  185. data/vendor/assets/stylesheets/xmt_froala/css/themes/dark.min.css +7 -0
  186. data/vendor/assets/stylesheets/xmt_froala/css/themes/gray.css +1281 -0
  187. data/vendor/assets/stylesheets/xmt_froala/css/themes/gray.min.css +7 -0
  188. data/vendor/assets/stylesheets/xmt_froala/css/themes/red.css +1281 -0
  189. data/vendor/assets/stylesheets/xmt_froala/css/themes/red.min.css +7 -0
  190. data/vendor/assets/stylesheets/xmt_froala/css/themes/royal.css +1281 -0
  191. data/vendor/assets/stylesheets/xmt_froala/css/themes/royal.min.css +7 -0
  192. data/vendor/assets/stylesheets/xmt_froala/css/third_party/embedly.css +64 -0
  193. data/vendor/assets/stylesheets/xmt_froala/css/third_party/embedly.min.css +7 -0
  194. data/vendor/assets/stylesheets/xmt_froala/css/third_party/spell_checker.css +72 -0
  195. data/vendor/assets/stylesheets/xmt_froala/css/third_party/spell_checker.min.css +7 -0
  196. data/vendor/assets/stylesheets/xmt_froala/css/xmt_froala.css +1423 -0
  197. data/vendor/assets/stylesheets/xmt_froala/fonts/FontAwesome.otf +0 -0
  198. data/vendor/assets/stylesheets/xmt_froala/fonts/fontawesome-webfont.eot +0 -0
  199. data/vendor/assets/stylesheets/xmt_froala/fonts/fontawesome-webfont.svg +2671 -0
  200. data/vendor/assets/stylesheets/xmt_froala/fonts/fontawesome-webfont.ttf +0 -0
  201. data/vendor/assets/stylesheets/xmt_froala/fonts/fontawesome-webfont.woff +0 -0
  202. data/vendor/assets/stylesheets/xmt_froala/fonts/fontawesome-webfont.woff2 +0 -0
  203. metadata +273 -0
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * froala_editor v2.8.1 (https://www.froala.com/wysiwyg-editor)
3
+ * License https://froala.com/wysiwyg-editor/terms/
4
+ * Copyright 2014-2018 Froala Labs
5
+ */
6
+
7
+ !function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return t===undefined&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t)}:n(window.jQuery)}(function(v){v.extend(v.FE.DEFAULTS,{lineBreakerTags:["table","hr","form","dl","span.fr-video",".fr-embedly"],lineBreakerOffset:15,lineBreakerHorizontalOffset:10}),v.FE.PLUGINS.lineBreaker=function(d){var g,t,a;function s(e,t){var n,r,a,o,i,s,f,l;if(null==e)i=(o=t.parent()).offset().top,n=(f=t.offset().top)-Math.min((f-i)/2,d.opts.lineBreakerOffset),a=o.outerWidth(),r=o.offset().left;else if(null==t)(s=(o=e.parent()).offset().top+o.outerHeight())<(l=e.offset().top+e.outerHeight())&&(s=(o=v(o).parent()).offset().top+o.outerHeight()),n=l+Math.min(Math.abs(s-l)/2,d.opts.lineBreakerOffset),a=o.outerWidth(),r=o.offset().left;else{o=e.parent();var p=e.offset().top+e.height(),u=t.offset().top;if(u<p)return!1;n=(p+u)/2,a=o.outerWidth(),r=o.offset().left}d.opts.iframe&&(r+=d.$iframe.offset().left-d.helpers.scrollLeft(),n+=d.$iframe.offset().top-d.helpers.scrollTop()),d.$box.append(g),g.css("top",n-d.win.pageYOffset),g.css("left",r-d.win.pageXOffset),g.css("width",a),g.data("tag1",e),g.data("tag2",t),g.addClass("fr-visible").data("instance",d)}function f(e){if(e){var t=v(e);if(0===d.$el.find(t).length)return null;if(e.nodeType!=Node.TEXT_NODE&&t.is(d.opts.lineBreakerTags.join(",")))return t;if(0<t.parents(d.opts.lineBreakerTags.join(",")).length)return e=t.parents(d.opts.lineBreakerTags.join(",")).get(0),0!==d.$el.find(e).length&&v(e).is(d.opts.lineBreakerTags.join(","))?v(e):null}return null}function o(e,t){var n=d.doc.elementFromPoint(e,t);return n&&!v(n).closest(".fr-line-breaker").length&&!d.node.isElement(n)&&n!=d.$wp.get(0)&&function(e){if("undefined"!=typeof e.inFroalaWrapper)return e.inFroalaWrapper;for(var t=e;e.parentNode&&e.parentNode!==d.$wp.get(0);)e=e.parentNode;return t.inFroalaWrapper=e.parentNode==d.$wp.get(0),t.inFroalaWrapper}(n)?n:null}function i(e,t,n){for(var r=n,a=null;r<=d.opts.lineBreakerOffset&&!a;)(a=o(e,t-r))||(a=o(e,t+r)),r+=n;return a}function l(e,t,n){for(var r=null,a=100;!r&&e>d.$box.offset().left&&e<d.$box.offset().left+d.$box.outerWidth()&&0<a;)(r=o(e,t))||(r=i(e,t,5)),"left"==n?e-=d.opts.lineBreakerHorizontalOffset:e+=d.opts.lineBreakerHorizontalOffset,a-=d.opts.lineBreakerHorizontalOffset;return r}function n(e){var t=a=null,n=null,r=d.doc.elementFromPoint(e.pageX-d.win.pageXOffset,e.pageY-d.win.pageYOffset);r&&("HTML"==r.tagName||"BODY"==r.tagName||d.node.isElement(r)||0<=(r.getAttribute("class")||"").indexOf("fr-line-breaker"))?((n=i(e.pageX-d.win.pageXOffset,e.pageY-d.win.pageYOffset,1))||(n=l(e.pageX-d.win.pageXOffset-d.opts.lineBreakerHorizontalOffset,e.pageY-d.win.pageYOffset,"left")),n||(n=l(e.pageX-d.win.pageXOffset+d.opts.lineBreakerHorizontalOffset,e.pageY-d.win.pageYOffset,"right")),t=f(n)):t=f(r),t?function(e,t){var n,r,a=e.offset().top,o=e.offset().top+e.outerHeight();if(Math.abs(o-t)<=d.opts.lineBreakerOffset||Math.abs(t-a)<=d.opts.lineBreakerOffset)if(Math.abs(o-t)<Math.abs(t-a)){for(var i=(r=e.get(0)).nextSibling;i&&i.nodeType==Node.TEXT_NODE&&0===i.textContent.length;)i=i.nextSibling;if(!i)return s(e,null);if(n=f(i))return s(e,n)}else{if(!(r=e.get(0)).previousSibling)return s(null,e);if(n=f(r.previousSibling))return s(n,e)}g.removeClass("fr-visible").removeData("instance")}(t,e.pageY):d.core.sameInstance(g)&&g.removeClass("fr-visible").removeData("instance")}function e(e){return!(g.hasClass("fr-visible")&&!d.core.sameInstance(g))&&(d.popups.areVisible()||d.el.querySelector(".fr-selected-cell")?(g.removeClass("fr-visible"),!0):void(!1!==t||d.edit.isDisabled()||(a&&clearTimeout(a),a=setTimeout(n,30,e))))}function r(){a&&clearTimeout(a),g.hasClass("fr-visible")&&g.removeClass("fr-visible").removeData("instance")}function p(){t=!0,r()}function u(){t=!1}function c(e){e.preventDefault();var t=g.data("instance")||d;g.removeClass("fr-visible").removeData("instance");var n=g.data("tag1"),r=g.data("tag2"),a=d.html.defaultTag();null==n?a&&"TD"!=r.parent().get(0).tagName&&0===r.parents(a).length?r.before("<"+a+">"+v.FE.MARKERS+"<br></"+a+">"):r.before(v.FE.MARKERS+"<br>"):a&&"TD"!=n.parent().get(0).tagName&&0===n.parents(a).length?n.after("<"+a+">"+v.FE.MARKERS+"<br></"+a+">"):n.after(v.FE.MARKERS+"<br>"),t.selection.restore()}return{_init:function(){if(!d.$wp)return!1;d.shared.$line_breaker||(d.shared.$line_breaker=v('<div class="fr-line-breaker"><a class="fr-floating-btn" role="button" tabIndex="-1" title="'+d.language.translate("Break")+'"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect x="21" y="11" width="2" height="8"/><rect x="14" y="17" width="7" height="2"/><path d="M14.000,14.000 L14.000,22.013 L9.000,18.031 L14.000,14.000 Z"/></svg></a></div>')),g=d.shared.$line_breaker,d.events.on("shared.destroy",function(){g.html("").removeData().remove(),g=null},!0),d.events.on("destroy",function(){g.removeData("instance").removeClass("fr-visible").appendTo("body:first"),clearTimeout(a)},!0),d.events.$on(g,"mousemove",function(e){e.stopPropagation()},!0),d.events.bindClick(g,"a",c),t=!1,d.events.$on(d.$win,"mousemove",e),d.events.$on(v(d.win),"scroll",r),d.events.on("popups.show.table.edit",r),d.events.on("commands.after",r),d.events.$on(v(d.win),"mousedown",p),d.events.$on(v(d.win),"mouseup",u)}}}});
@@ -0,0 +1,1157 @@
1
+ /*!
2
+ * froala_editor v2.8.1 (https://www.froala.com/wysiwyg-editor)
3
+ * License https://froala.com/wysiwyg-editor/terms/
4
+ * Copyright 2014-2018 Froala Labs
5
+ */
6
+
7
+ (function (factory) {
8
+ if (typeof define === 'function' && define.amd) {
9
+ // AMD. Register as an anonymous module.
10
+ define(['jquery'], factory);
11
+ } else if (typeof module === 'object' && module.exports) {
12
+ // Node/CommonJS
13
+ module.exports = function( root, jQuery ) {
14
+ if ( jQuery === undefined ) {
15
+ // require('jQuery') returns a factory that requires window to
16
+ // build a jQuery instance, we normalize how we use modules
17
+ // that require this pattern but the window provided is a noop
18
+ // if it's defined (how jquery works)
19
+ if ( typeof window !== 'undefined' ) {
20
+ jQuery = require('jquery');
21
+ }
22
+ else {
23
+ jQuery = require('jquery')(root);
24
+ }
25
+ }
26
+ return factory(jQuery);
27
+ };
28
+ } else {
29
+ // Browser globals
30
+ factory(window.jQuery);
31
+ }
32
+ }(function ($) {
33
+
34
+
35
+
36
+ $.extend($.FE.POPUP_TEMPLATES, {
37
+ 'link.edit': '[_BUTTONS_]',
38
+ 'link.insert': '[_BUTTONS_][_INPUT_LAYER_]'
39
+ })
40
+
41
+ $.extend($.FE.DEFAULTS, {
42
+ linkEditButtons: ['linkOpen', 'linkStyle', 'linkEdit', 'linkRemove'],
43
+ linkInsertButtons: ['linkBack', '|', 'linkList'],
44
+ linkAttributes: {},
45
+ linkAutoPrefix: 'http://',
46
+ linkStyles: {
47
+ 'fr-green': 'Green',
48
+ 'fr-strong': 'Thick'
49
+ },
50
+ linkMultipleStyles: true,
51
+ linkConvertEmailAddress: true,
52
+ linkAlwaysBlank: false,
53
+ linkAlwaysNoFollow: false,
54
+ linkNoOpener: true,
55
+ linkNoReferrer: true,
56
+ linkList: [
57
+ {
58
+ text: 'Froala',
59
+ href: 'https://froala.com',
60
+ target: '_blank'
61
+ },
62
+ {
63
+ text: 'Google',
64
+ href: 'https://google.com',
65
+ target: '_blank'
66
+ },
67
+ {
68
+ displayText: 'Facebook',
69
+ href: 'https://facebook.com'
70
+ }
71
+ ],
72
+ linkText: true
73
+ });
74
+
75
+ $.FE.PLUGINS.link = function (editor) {
76
+ function get () {
77
+ var $current_image = editor.image ? editor.image.get() : null;
78
+
79
+ if (!$current_image && editor.$wp) {
80
+ var c_el = editor.selection.ranges(0).commonAncestorContainer;
81
+
82
+ try {
83
+ if (c_el && ((c_el.contains && c_el.contains(editor.el)) || !editor.el.contains(c_el) || editor.el == c_el)) c_el = null;
84
+ }
85
+ catch (ex) {
86
+ c_el = null;
87
+ }
88
+
89
+ if (c_el && c_el.tagName === 'A') return c_el;
90
+ var s_el = editor.selection.element();
91
+ var e_el = editor.selection.endElement();
92
+
93
+ if (s_el.tagName != 'A' && !editor.node.isElement(s_el)) {
94
+ s_el = $(s_el).parentsUntil(editor.$el, 'a:first').get(0);
95
+ }
96
+
97
+ if (e_el.tagName != 'A' && !editor.node.isElement(e_el)) {
98
+ e_el = $(e_el).parentsUntil(editor.$el, 'a:first').get(0);
99
+ }
100
+
101
+ try {
102
+ if (e_el && ((e_el.contains && e_el.contains(editor.el)) || !editor.el.contains(e_el) || editor.el == e_el)) e_el = null;
103
+ }
104
+ catch (ex) {
105
+ e_el = null;
106
+ }
107
+
108
+ try {
109
+ if (s_el && ((s_el.contains && s_el.contains(editor.el)) || !editor.el.contains(s_el) || editor.el == s_el)) s_el = null;
110
+ }
111
+ catch (ex) {
112
+ s_el = null;
113
+ }
114
+
115
+ if (e_el && e_el == s_el && e_el.tagName == 'A') {
116
+
117
+ // We do not clicking at the end / input of links because in IE the selection is changing shortly after mouseup.
118
+ // https://jsfiddle.net/jredzam3/
119
+ if ((editor.browser.msie || editor.helpers.isMobile()) && (editor.selection.info(s_el).atEnd || editor.selection.info(s_el).atStart)) {
120
+ return null;
121
+ }
122
+
123
+ return s_el;
124
+ }
125
+
126
+ return null;
127
+ }
128
+ else if (editor.el.tagName == 'A') {
129
+
130
+ return editor.el;
131
+ }
132
+ else {
133
+ if ($current_image && $current_image.get(0).parentNode && $current_image.get(0).parentNode.tagName == 'A') {
134
+
135
+ return $current_image.get(0).parentNode;
136
+ }
137
+ }
138
+ }
139
+
140
+ function allSelected () {
141
+ var $current_image = editor.image ? editor.image.get() : null;
142
+ var selectedLinks = [];
143
+
144
+ if ($current_image) {
145
+ if ($current_image.get(0).parentNode.tagName == 'A') {
146
+ selectedLinks.push($current_image.get(0).parentNode);
147
+ }
148
+ }
149
+ else {
150
+ var range;
151
+ var containerEl;
152
+ var links;
153
+ var linkRange;
154
+
155
+ if (editor.win.getSelection) {
156
+ var sel = editor.win.getSelection();
157
+
158
+ if (sel.getRangeAt && sel.rangeCount) {
159
+ linkRange = editor.doc.createRange();
160
+
161
+ for (var r = 0; r < sel.rangeCount; ++r) {
162
+ range = sel.getRangeAt(r);
163
+ containerEl = range.commonAncestorContainer;
164
+
165
+ if (containerEl && containerEl.nodeType != 1) {
166
+ containerEl = containerEl.parentNode;
167
+ }
168
+
169
+ if (containerEl && containerEl.nodeName.toLowerCase() == 'a') {
170
+ selectedLinks.push(containerEl);
171
+ }
172
+ else {
173
+ links = containerEl.getElementsByTagName('a');
174
+
175
+ for (var i = 0; i < links.length; ++i) {
176
+ linkRange.selectNodeContents(links[i]);
177
+
178
+ if (linkRange.compareBoundaryPoints(range.END_TO_START, range) < 1 && linkRange.compareBoundaryPoints(range.START_TO_END, range) > -1) {
179
+ selectedLinks.push(links[i]);
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ // linkRange.detach();
186
+ }
187
+ }
188
+ else if (editor.doc.selection && editor.doc.selection.type != 'Control') {
189
+ range = editor.doc.selection.createRange();
190
+ containerEl = range.parentElement();
191
+
192
+ if (containerEl.nodeName.toLowerCase() == 'a') {
193
+ selectedLinks.push(containerEl);
194
+ }
195
+ else {
196
+ links = containerEl.getElementsByTagName('a');
197
+ linkRange = editor.doc.body.createTextRange();
198
+
199
+ for (var j = 0; j < links.length; ++j) {
200
+ linkRange.moveToElementText(links[j]);
201
+
202
+ if (linkRange.compareEndPoints('StartToEnd', range) > -1 && linkRange.compareEndPoints('EndToStart', range) < 1) {
203
+ selectedLinks.push(links[j]);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ return selectedLinks;
211
+ }
212
+
213
+ function _edit (e) {
214
+ if (editor.core.hasFocus()) {
215
+ _hideEditPopup();
216
+
217
+ // Do not show edit popup for link when ALT is hit.
218
+ if (e && e.type === 'keyup' && (e.altKey || e.which == $.FE.KEYCODE.ALT)) return true;
219
+
220
+ setTimeout (function () {
221
+
222
+ // No event passed.
223
+ // Event passed and (left click or other event type).
224
+ if (!e || (e && (e.which == 1 || e.type != 'mouseup'))) {
225
+ var link = get();
226
+ var $current_image = editor.image ? editor.image.get() : null;
227
+
228
+ if (link && !$current_image) {
229
+ if (editor.image) {
230
+ var contents = editor.node.contents(link);
231
+
232
+ // https://github.com/froala/wysiwyg-editor/issues/1103
233
+ if (contents.length == 1 && contents[0].tagName == 'IMG') {
234
+ var range = editor.selection.ranges(0);
235
+
236
+ if (range.startOffset === 0 && range.endOffset === 0) {
237
+ $(link).before($.FE.MARKERS);
238
+ }
239
+ else {
240
+ $(link).after($.FE.MARKERS);
241
+ }
242
+
243
+ editor.selection.restore();
244
+
245
+ return false;
246
+ }
247
+ }
248
+
249
+ if (e) {
250
+ e.stopPropagation();
251
+ }
252
+ _showEditPopup(link);
253
+ }
254
+ }
255
+ }, editor.helpers.isIOS() ? 100 : 0);
256
+ }
257
+ }
258
+
259
+ function _showEditPopup (link) {
260
+ var $popup = editor.popups.get('link.edit');
261
+
262
+ if (!$popup) $popup = _initEditPopup();
263
+
264
+ var $link = $(link);
265
+
266
+ if (!editor.popups.isVisible('link.edit')) {
267
+ editor.popups.refresh('link.edit');
268
+ }
269
+ editor.popups.setContainer('link.edit', editor.$sc);
270
+ var left = $link.offset().left + $(link).outerWidth() / 2;
271
+ var top = $link.offset().top + $link.outerHeight();
272
+ editor.popups.show('link.edit', left, top, $link.outerHeight());
273
+ }
274
+
275
+ function _hideEditPopup () {
276
+ editor.popups.hide('link.edit');
277
+ }
278
+
279
+ function _initEditPopup () {
280
+
281
+ // Link buttons.
282
+ var link_buttons = '';
283
+
284
+ if (editor.opts.linkEditButtons.length >= 1) {
285
+ if (editor.el.tagName == 'A' && editor.opts.linkEditButtons.indexOf('linkRemove') >= 0) {
286
+ editor.opts.linkEditButtons.splice(editor.opts.linkEditButtons.indexOf('linkRemove'), 1);
287
+ }
288
+
289
+ link_buttons = '<div class="fr-buttons">' + editor.button.buildList(editor.opts.linkEditButtons) + '</div>';
290
+ }
291
+
292
+ var template = {
293
+ buttons: link_buttons
294
+ };
295
+
296
+ // Set the template in the popup.
297
+ var $popup = editor.popups.create('link.edit', template);
298
+
299
+ if (editor.$wp) {
300
+ editor.events.$on(editor.$wp, 'scroll.link-edit', function () {
301
+ if (get() && editor.popups.isVisible('link.edit')) {
302
+ _showEditPopup(get());
303
+ }
304
+ });
305
+ }
306
+
307
+ return $popup;
308
+ }
309
+
310
+ /**
311
+ * Hide link insert popup.
312
+ */
313
+ function _hideInsertPopup () {
314
+ }
315
+
316
+ function _refreshInsertPopup () {
317
+ var $popup = editor.popups.get('link.insert');
318
+ var link = get();
319
+
320
+ if (link) {
321
+ var $link = $(link);
322
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
323
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
324
+ var i;
325
+ var $input;
326
+
327
+ for (i = 0; i < text_inputs.length; i++) {
328
+ $input = $(text_inputs[i]);
329
+ $input.val($link.attr($input.attr('name') || ''));
330
+ }
331
+
332
+ check_inputs.prop('checked', false);
333
+
334
+ for (i = 0; i < check_inputs.length; i++) {
335
+ $input = $(check_inputs[i]);
336
+
337
+ if ($link.attr($input.attr('name')) == $input.data('checked')) {
338
+ $input.prop('checked', true);
339
+ }
340
+ }
341
+
342
+ $popup.find('input.fr-link-attr[type="text"][name="text"]').val($link.text());
343
+ }
344
+ else {
345
+ $popup.find('input.fr-link-attr[type="text"]').val('');
346
+ $popup.find('input.fr-link-attr[type="checkbox"]').prop('checked', false);
347
+ $popup.find('input.fr-link-attr[type="text"][name="text"]').val(editor.selection.text());
348
+ }
349
+ $popup.find('input.fr-link-attr').trigger('change');
350
+ var $current_image = editor.image ? editor.image.get() : null;
351
+
352
+ if ($current_image) {
353
+ $popup.find('.fr-link-attr[name="text"]').parent().hide();
354
+ }
355
+ else {
356
+ $popup.find('.fr-link-attr[name="text"]').parent().show();
357
+ }
358
+ }
359
+
360
+ function _showInsertPopup () {
361
+ var $btn = editor.$tb.find('.fr-command[data-cmd="insertLink"]');
362
+ var $popup = editor.popups.get('link.insert');
363
+
364
+ if (!$popup) $popup = _initInsertPopup();
365
+
366
+ if (!$popup.hasClass('fr-active')) {
367
+ editor.popups.refresh('link.insert');
368
+ editor.popups.setContainer('link.insert', editor.$tb || editor.$sc);
369
+
370
+ if ($btn.is(':visible')) {
371
+ var left = $btn.offset().left + $btn.outerWidth() / 2;
372
+ var top = $btn.offset().top + (editor.opts.toolbarBottom ? 10 : $btn.outerHeight() - 10);
373
+ editor.popups.show('link.insert', left, top, $btn.outerHeight());
374
+ }
375
+ else {
376
+ editor.position.forSelection($popup);
377
+ editor.popups.show('link.insert');
378
+ }
379
+ }
380
+ }
381
+
382
+ function _initInsertPopup (delayed) {
383
+ if (delayed) {
384
+ editor.popups.onRefresh('link.insert', _refreshInsertPopup);
385
+ editor.popups.onHide('link.insert', _hideInsertPopup);
386
+
387
+ return true;
388
+ }
389
+
390
+ // Image buttons.
391
+ var link_buttons = '';
392
+
393
+ if (editor.opts.linkInsertButtons.length >= 1) {
394
+ link_buttons = '<div class="fr-buttons">' + editor.button.buildList(editor.opts.linkInsertButtons) + '</div>';
395
+ }
396
+
397
+ var checkmark = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="10" height="10" viewBox="0 0 32 32"><path d="M27 4l-15 15-7-7-5 5 12 12 20-20z" fill="#FFF"></path></svg>';
398
+
399
+ // Image by url layer.
400
+ var input_layer = '';
401
+ var tab_idx = 0;
402
+ input_layer = '<div class="fr-link-insert-layer fr-layer fr-active" id="fr-link-insert-layer-' + editor.id + '">';
403
+ input_layer += '<div class="fr-input-line"><input id="fr-link-insert-layer-url-' + editor.id + '" name="href" type="text" class="fr-link-attr" placeholder="' + editor.language.translate('URL') + '" tabIndex="' + (++tab_idx) + '"></div>';
404
+
405
+ if (editor.opts.linkText) {
406
+ input_layer += '<div class="fr-input-line"><input id="fr-link-insert-layer-text-' + editor.id + '" name="text" type="text" class="fr-link-attr" placeholder="' + editor.language.translate('Text') + '" tabIndex="' + (++tab_idx) + '"></div>';
407
+ }
408
+
409
+ // Add any additional fields.
410
+ for (var attr in editor.opts.linkAttributes) {
411
+ if (editor.opts.linkAttributes.hasOwnProperty(attr)) {
412
+ var placeholder = editor.opts.linkAttributes[attr];
413
+ input_layer += '<div class="fr-input-line"><input name="' + attr + '" type="text" class="fr-link-attr" placeholder="' + editor.language.translate(placeholder) + '" tabIndex="' + (++tab_idx) + '"></div>';
414
+ }
415
+ }
416
+
417
+ if (!editor.opts.linkAlwaysBlank) {
418
+ input_layer += '<div class="fr-checkbox-line"><span class="fr-checkbox"><input name="target" class="fr-link-attr" data-checked="_blank" type="checkbox" id="fr-link-target-' + editor.id + '" tabIndex="' + (++tab_idx) + '"><span>' + checkmark + '</span></span><label for="fr-link-target-' + editor.id + '">' + editor.language.translate('Open in new tab') + '</label></div>';
419
+ }
420
+
421
+ input_layer += '<div class="fr-action-buttons"><button class="fr-command fr-submit" role="button" data-cmd="linkInsert" href="#" tabIndex="' + (++tab_idx) + '" type="button">' + editor.language.translate('Insert') + '</button></div></div>'
422
+
423
+ var template = {
424
+ buttons: link_buttons,
425
+ input_layer: input_layer
426
+ }
427
+
428
+ // Set the template in the popup.
429
+ var $popup = editor.popups.create('link.insert', template);
430
+
431
+ if (editor.$wp) {
432
+ editor.events.$on(editor.$wp, 'scroll.link-insert', function () {
433
+ var $current_image = editor.image ? editor.image.get() : null;
434
+
435
+ if ($current_image && editor.popups.isVisible('link.insert')) {
436
+ imageLink();
437
+ }
438
+
439
+ if (get && editor.popups.isVisible('link.insert')) {
440
+ update();
441
+ }
442
+ });
443
+ }
444
+
445
+ return $popup;
446
+ }
447
+
448
+ function remove () {
449
+ var link = get();
450
+
451
+ var $current_image = editor.image ? editor.image.get() : null;
452
+
453
+ if (editor.events.trigger('link.beforeRemove', [link]) === false) return false;
454
+
455
+ if ($current_image && link) {
456
+ $current_image.unwrap();
457
+ editor.image.edit($current_image);
458
+ }
459
+ else if (link) {
460
+ editor.selection.save();
461
+ $(link).replaceWith($(link).html());
462
+ editor.selection.restore();
463
+ _hideEditPopup();
464
+ }
465
+ }
466
+
467
+ function _init () {
468
+
469
+ // Edit on keyup.
470
+ editor.events.on('keyup', function (e) {
471
+ if (e.which != $.FE.KEYCODE.ESC) {
472
+ _edit(e);
473
+ }
474
+ });
475
+
476
+ editor.events.on('window.mouseup', _edit);
477
+
478
+ // Do not follow links when edit is disabled.
479
+ editor.events.$on(editor.$el, 'click', 'a', function (e) {
480
+ if (editor.edit.isDisabled()) {
481
+ e.preventDefault();
482
+ }
483
+ });
484
+
485
+ if (editor.helpers.isMobile()) {
486
+ editor.events.$on(editor.$doc, 'selectionchange', _edit);
487
+ }
488
+
489
+ _initInsertPopup(true);
490
+
491
+ // Init on link.
492
+ if (editor.el.tagName == 'A') {
493
+ editor.$el.addClass('fr-view');
494
+ }
495
+
496
+ // Hit ESC when focus is in link edit popup.
497
+ editor.events.on('toolbar.esc', function () {
498
+ if (editor.popups.isVisible('link.edit')) {
499
+ editor.events.disableBlur();
500
+ editor.events.focus();
501
+
502
+ return false;
503
+ }
504
+ }, true);
505
+ }
506
+
507
+ function usePredefined (val) {
508
+ var link = editor.opts.linkList[val];
509
+ var $popup = editor.popups.get('link.insert');
510
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
511
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
512
+ var $input;
513
+ var i;
514
+
515
+ for (i = 0; i < text_inputs.length; i++) {
516
+ $input = $(text_inputs[i]);
517
+
518
+ if (link[$input.attr('name')]) {
519
+ $input.val(link[$input.attr('name')]);
520
+ }
521
+ else if ($input.attr('name') != 'text') {
522
+ $input.val('');
523
+ }
524
+ }
525
+
526
+ for (i = 0; i < check_inputs.length; i++) {
527
+ $input = $(check_inputs[i]);
528
+ $input.prop('checked', $input.data('checked') == link[$input.attr('name')]);
529
+ }
530
+ editor.accessibility.focusPopup($popup);
531
+ }
532
+
533
+ function insertCallback () {
534
+ var $popup = editor.popups.get('link.insert');
535
+ var text_inputs = $popup.find('input.fr-link-attr[type="text"]');
536
+ var check_inputs = $popup.find('input.fr-link-attr[type="checkbox"]');
537
+ var href = (text_inputs.filter('[name="href"]').val() || '').trim();
538
+ var text = text_inputs.filter('[name="text"]').val();
539
+ var attrs = {};
540
+ var $input;
541
+ var i;
542
+
543
+ for (i = 0; i < text_inputs.length; i++) {
544
+ $input = $(text_inputs[i]);
545
+
546
+ if (['href', 'text'].indexOf($input.attr('name')) < 0) {
547
+ attrs[$input.attr('name')] = $input.val();
548
+ }
549
+ }
550
+
551
+ for (i = 0; i < check_inputs.length; i++) {
552
+ $input = $(check_inputs[i]);
553
+
554
+ if ($input.is(':checked')) {
555
+ attrs[$input.attr('name')] = $input.data('checked');
556
+ }
557
+ else {
558
+ attrs[$input.attr('name')] = $input.data('unchecked') || null;
559
+ }
560
+ }
561
+
562
+ var t = editor.helpers.scrollTop();
563
+ insert(href, text, attrs);
564
+ $(editor.o_win).scrollTop(t);
565
+ }
566
+
567
+ function _split () {
568
+ if (!editor.selection.isCollapsed()) {
569
+ editor.selection.save();
570
+ var markers = editor.$el.find('.fr-marker').addClass('fr-unprocessed').toArray();
571
+
572
+ while (markers.length) {
573
+ var $marker = $(markers.pop());
574
+ $marker.removeClass('fr-unprocessed');
575
+
576
+ // Get deepest parent.
577
+ var deep_parent = editor.node.deepestParent($marker.get(0));
578
+
579
+ if (deep_parent) {
580
+ var node = $marker.get(0);
581
+ var close_str = '';
582
+ var open_str = '';
583
+
584
+ do {
585
+ node = node.parentNode;
586
+
587
+ if (!editor.node.isBlock(node)) {
588
+ close_str = close_str + editor.node.closeTagString(node);
589
+ open_str = editor.node.openTagString(node) + open_str;
590
+ }
591
+ } while (node != deep_parent);
592
+
593
+ var marker_str = editor.node.openTagString($marker.get(0)) + $marker.html() + editor.node.closeTagString($marker.get(0));
594
+
595
+ $marker.replaceWith('<span id="fr-break"></span>');
596
+ var h = deep_parent.outerHTML;
597
+
598
+ h = h.replace(/<span id="fr-break"><\/span>/g, close_str + marker_str + open_str);
599
+
600
+ deep_parent.outerHTML = h;
601
+ }
602
+
603
+ markers = editor.$el.find('.fr-marker.fr-unprocessed').toArray();
604
+ }
605
+
606
+ editor.html.cleanEmptyTags();
607
+
608
+ editor.selection.restore();
609
+ }
610
+ }
611
+
612
+ /**
613
+ * Insert link into the editor.
614
+ */
615
+ function insert (href, text, attrs) {
616
+ if (typeof attrs == 'undefined') attrs = {};
617
+
618
+ if (editor.events.trigger('link.beforeInsert', [href, text, attrs]) === false) return false;
619
+
620
+ // Get image if we have one selected.
621
+ var $current_image = editor.image ? editor.image.get() : null;
622
+
623
+ if (!$current_image && editor.el.tagName != 'A') {
624
+ editor.selection.restore();
625
+ editor.popups.hide('link.insert');
626
+ }
627
+ else if (editor.el.tagName == 'A') {
628
+ editor.$el.focus();
629
+ }
630
+
631
+ var original_href = href;
632
+
633
+ // Convert email address.
634
+ if (editor.opts.linkConvertEmailAddress) {
635
+ if (editor.helpers.isEmail(href) && !/^mailto:.*/i.test(href)) {
636
+ href = 'mailto:' + href;
637
+ }
638
+ }
639
+
640
+ // Check if is local path.
641
+ var local_path = /^([A-Za-z]:(\\){1,2}|[A-Za-z]:((\\){1,2}[^\\]+)+)(\\)?$/i;
642
+
643
+ // Add autoprefix.
644
+ if (editor.opts.linkAutoPrefix !== '' && !new RegExp('^(' + $.FE.LinkProtocols.join('|') + '):.', 'i').test(href) && !/^data:image.*/i.test(href) && !/^(https?:|ftps?:|file:|)\/\//i.test(href) && !local_path.test(href)) {
645
+
646
+ // Do prefix only if starting character is not absolute.
647
+ if (['/', '{', '[', '#', '(', '.'].indexOf((href || '')[0]) < 0) {
648
+ href = editor.opts.linkAutoPrefix + editor.helpers.sanitizeURL(href);
649
+ }
650
+ }
651
+
652
+ // Sanitize the URL.
653
+ href = editor.helpers.sanitizeURL(href);
654
+
655
+ // Default attributs.
656
+ if (editor.opts.linkAlwaysBlank) attrs.target = '_blank';
657
+
658
+ if (editor.opts.linkAlwaysNoFollow) attrs.rel = 'nofollow';
659
+
660
+ // https://github.com/froala/wysiwyg-editor/issues/1576.
661
+ if (attrs.target == '_blank') {
662
+ if (editor.opts.linkNoOpener) {
663
+ if (!attrs.rel) attrs.rel = 'noopener';
664
+ else attrs.rel += ' noopener';
665
+ }
666
+
667
+ if (editor.opts.linkNoReferrer) {
668
+ if (!attrs.rel) attrs.rel = 'noreferrer';
669
+ else attrs.rel += ' noreferrer';
670
+ }
671
+ }
672
+ else if (attrs.target == null) {
673
+ if (attrs.rel) {
674
+ attrs.rel = attrs.rel.replace(/noopener/, '').replace(/noreferrer/, '');
675
+ }
676
+ else {
677
+ attrs.rel = null;
678
+ }
679
+ }
680
+
681
+ // Format text.
682
+ text = text || '';
683
+
684
+ if (href === editor.opts.linkAutoPrefix) {
685
+ var $popup = editor.popups.get('link.insert');
686
+ $popup.find('input[name="href"]').addClass('fr-error');
687
+ editor.events.trigger('link.bad', [original_href]);
688
+
689
+ return false;
690
+ }
691
+
692
+ // Check if we have selection only in one link.
693
+ var link = get();
694
+ var $link;
695
+
696
+ if (link) {
697
+ $link = $(link);
698
+
699
+ $link.attr('href', href);
700
+
701
+ // Change text if it is different.
702
+ if (text.length > 0 && $link.text() != text && !$current_image) {
703
+ var child = $link.get(0);
704
+
705
+ while (child.childNodes.length === 1 && child.childNodes[0].nodeType == Node.ELEMENT_NODE) {
706
+ child = child.childNodes[0];
707
+ }
708
+
709
+ $(child).text(text);
710
+ }
711
+
712
+ if (!$current_image) {
713
+ $link
714
+ .prepend($.FE.START_MARKER)
715
+ .append($.FE.END_MARKER);
716
+ }
717
+
718
+ // Set attributes.
719
+ $link.attr(attrs);
720
+
721
+ if (!$current_image) {
722
+ editor.selection.restore();
723
+ }
724
+ }
725
+ else {
726
+
727
+ // We don't have any image selected.
728
+ if (!$current_image) {
729
+
730
+ // Remove current links.
731
+ editor.format.remove('a');
732
+
733
+ // Nothing is selected.
734
+ if (editor.selection.isCollapsed()) {
735
+ text = (text.length === 0 ? original_href : text);
736
+ editor.html.insert('<a href="' + href + '">' + $.FE.START_MARKER + text.replace(/&/g, '&amp;') + $.FE.END_MARKER + '</a>');
737
+ editor.selection.restore();
738
+ }
739
+ else {
740
+ if (text.length > 0 && text != editor.selection.text().replace(/\n/g, '')) {
741
+ editor.selection.remove();
742
+ editor.html.insert('<a href="' + href + '">' + $.FE.START_MARKER + text.replace(/&/g, '&amp;') + $.FE.END_MARKER + '</a>');
743
+ editor.selection.restore();
744
+ }
745
+ else {
746
+ _split();
747
+
748
+ // Add link.
749
+ editor.format.apply('a', { href: href });
750
+ }
751
+ }
752
+ }
753
+ else {
754
+
755
+ // Just wrap current image with a link.
756
+ $current_image.wrap('<a href="' + href + '"></a>');
757
+ }
758
+
759
+ // Set attributes.
760
+ var links = allSelected();
761
+
762
+ for (var i = 0; i < links.length; i++) {
763
+ $link = $(links[i]);
764
+ $link.attr(attrs);
765
+ $link.removeAttr('_moz_dirty');
766
+ }
767
+
768
+ // Show link edit if only one link.
769
+ if (links.length == 1 && editor.$wp && !$current_image) {
770
+ $(links[0])
771
+ .prepend($.FE.START_MARKER)
772
+ .append($.FE.END_MARKER);
773
+
774
+ editor.selection.restore();
775
+ }
776
+ }
777
+
778
+ // Hide popup and try to edit.
779
+ if (!$current_image) {
780
+ _edit();
781
+ }
782
+ else {
783
+ var $pop = editor.popups.get('link.insert');
784
+
785
+ if ($pop) {
786
+ $pop.find('input:focus').blur();
787
+ }
788
+
789
+ editor.image.edit($current_image);
790
+ }
791
+ }
792
+
793
+ function update () {
794
+ _hideEditPopup();
795
+
796
+ var link = get();
797
+
798
+ if (link) {
799
+ var $popup = editor.popups.get('link.insert');
800
+
801
+ if (!$popup) $popup = _initInsertPopup();
802
+
803
+ if (!editor.popups.isVisible('link.insert')) {
804
+ editor.popups.refresh('link.insert');
805
+ editor.selection.save();
806
+
807
+ if (editor.helpers.isMobile()) {
808
+ editor.events.disableBlur();
809
+ editor.$el.blur();
810
+ editor.events.enableBlur();
811
+ }
812
+ }
813
+
814
+ editor.popups.setContainer('link.insert', editor.$sc);
815
+ var $ref = (editor.image ? editor.image.get() : null) || $(link);
816
+ var left = $ref.offset().left + $ref.outerWidth() / 2;
817
+ var top = $ref.offset().top + $ref.outerHeight();
818
+
819
+ editor.popups.show('link.insert', left, top, $ref.outerHeight());
820
+ }
821
+ }
822
+
823
+ function back () {
824
+ var $current_image = editor.image ? editor.image.get() : null;
825
+
826
+ if (!$current_image) {
827
+ editor.events.disableBlur();
828
+ editor.selection.restore();
829
+ editor.events.enableBlur();
830
+
831
+ var link = get();
832
+
833
+ if (link && editor.$wp) {
834
+ editor.selection.restore();
835
+ _hideEditPopup();
836
+ _edit();
837
+ }
838
+ else if (editor.el.tagName == 'A') {
839
+ editor.$el.focus();
840
+ _edit();
841
+ }
842
+ else {
843
+ editor.popups.hide('link.insert');
844
+ editor.toolbar.showInline();
845
+ }
846
+ }
847
+ else {
848
+ editor.image.back();
849
+ }
850
+ }
851
+
852
+ function imageLink () {
853
+ var $el = editor.image ? editor.image.getEl() : null;
854
+
855
+ if ($el) {
856
+ var $popup = editor.popups.get('link.insert');
857
+
858
+ if (editor.image.hasCaption()) {
859
+ $el = $el.find('.fr-img-wrap');
860
+ }
861
+
862
+ if (!$popup) $popup = _initInsertPopup();
863
+ _refreshInsertPopup(true);
864
+ editor.popups.setContainer('link.insert', editor.$sc);
865
+ var left = $el.offset().left + $el.outerWidth() / 2;
866
+ var top = $el.offset().top + $el.outerHeight();
867
+
868
+ editor.popups.show('link.insert', left, top, $el.outerHeight());
869
+ }
870
+ }
871
+
872
+ /**
873
+ * Apply specific style.
874
+ */
875
+ function applyStyle (val, linkStyles, multipleStyles) {
876
+ if (typeof multipleStyles == 'undefined') multipleStyles = editor.opts.linkMultipleStyles;
877
+
878
+ if (typeof linkStyles == 'undefined') linkStyles = editor.opts.linkStyles;
879
+ var link = get();
880
+
881
+ if (!link) return false;
882
+
883
+ // Remove multiple styles.
884
+ if (!multipleStyles) {
885
+ var styles = Object.keys(linkStyles);
886
+ styles.splice(styles.indexOf(val), 1);
887
+ $(link).removeClass(styles.join(' '));
888
+ }
889
+
890
+ $(link).toggleClass(val);
891
+
892
+ _edit();
893
+ }
894
+
895
+ return {
896
+ _init: _init,
897
+ remove: remove,
898
+ showInsertPopup: _showInsertPopup,
899
+ usePredefined: usePredefined,
900
+ insertCallback: insertCallback,
901
+ insert: insert,
902
+ update: update,
903
+ get: get,
904
+ allSelected: allSelected,
905
+ back: back,
906
+ imageLink: imageLink,
907
+ applyStyle: applyStyle
908
+ }
909
+ }
910
+
911
+ // Register the link command.
912
+ $.FE.DefineIcon('insertLink', { NAME: 'link' });
913
+ $.FE.RegisterShortcut($.FE.KEYCODE.K, 'insertLink', null, 'K');
914
+ $.FE.RegisterCommand('insertLink', {
915
+ title: 'Insert Link',
916
+ undo: false,
917
+ focus: true,
918
+ refreshOnCallback: false,
919
+ popup: true,
920
+ callback: function () {
921
+ if (!this.popups.isVisible('link.insert')) {
922
+ this.link.showInsertPopup();
923
+ }
924
+ else {
925
+ if (this.$el.find('.fr-marker').length) {
926
+ this.events.disableBlur();
927
+ this.selection.restore();
928
+ }
929
+ this.popups.hide('link.insert');
930
+ }
931
+ },
932
+ plugin: 'link'
933
+ })
934
+
935
+ $.FE.DefineIcon('linkOpen', {
936
+ NAME: 'external-link',
937
+ FA5NAME: 'external-link-alt'
938
+ });
939
+ $.FE.RegisterCommand('linkOpen', {
940
+ title: 'Open Link',
941
+ undo: false,
942
+ refresh: function ($btn) {
943
+ var link = this.link.get();
944
+
945
+ if (link) {
946
+ $btn.removeClass('fr-hidden');
947
+ }
948
+ else {
949
+ $btn.addClass('fr-hidden');
950
+ }
951
+ },
952
+ callback: function () {
953
+ var link = this.link.get();
954
+
955
+ if (link) {
956
+ this.o_win.open(link.href, '_blank', 'noopener');
957
+
958
+ this.popups.hide('link.edit');
959
+ }
960
+ },
961
+ plugin: 'link'
962
+ })
963
+
964
+ $.FE.DefineIcon('linkEdit', { NAME: 'edit' });
965
+ $.FE.RegisterCommand('linkEdit', {
966
+ title: 'Edit Link',
967
+ undo: false,
968
+ refreshAfterCallback: false,
969
+ popup: true,
970
+ callback: function () {
971
+ this.link.update();
972
+ },
973
+ refresh: function ($btn) {
974
+ var link = this.link.get();
975
+
976
+ if (link) {
977
+ $btn.removeClass('fr-hidden');
978
+ }
979
+ else {
980
+ $btn.addClass('fr-hidden');
981
+ }
982
+ },
983
+ plugin: 'link'
984
+ })
985
+
986
+ $.FE.DefineIcon('linkRemove', { NAME: 'unlink' });
987
+ $.FE.RegisterCommand('linkRemove', {
988
+ title: 'Unlink',
989
+ callback: function () {
990
+ this.link.remove();
991
+ },
992
+ refresh: function ($btn) {
993
+ var link = this.link.get();
994
+
995
+ if (link) {
996
+ $btn.removeClass('fr-hidden');
997
+ }
998
+ else {
999
+ $btn.addClass('fr-hidden');
1000
+ }
1001
+ },
1002
+ plugin: 'link'
1003
+ })
1004
+
1005
+ $.FE.DefineIcon('linkBack', { NAME: 'arrow-left' });
1006
+ $.FE.RegisterCommand('linkBack', {
1007
+ title: 'Back',
1008
+ undo: false,
1009
+ focus: false,
1010
+ back: true,
1011
+ refreshAfterCallback: false,
1012
+ callback: function () {
1013
+ this.link.back();
1014
+ },
1015
+ refresh: function ($btn) {
1016
+ var link = this.link.get() && this.doc.hasFocus();
1017
+ var $current_image = this.image ? this.image.get() : null;
1018
+
1019
+ if (!$current_image && !link && !this.opts.toolbarInline) {
1020
+ $btn.addClass('fr-hidden');
1021
+ $btn.next('.fr-separator').addClass('fr-hidden');
1022
+ }
1023
+ else {
1024
+ $btn.removeClass('fr-hidden');
1025
+ $btn.next('.fr-separator').removeClass('fr-hidden');
1026
+ }
1027
+ },
1028
+ plugin: 'link'
1029
+ });
1030
+
1031
+ $.FE.DefineIcon('linkList', { NAME: 'search' });
1032
+ $.FE.RegisterCommand('linkList', {
1033
+ title: 'Choose Link',
1034
+ type: 'dropdown',
1035
+ focus: false,
1036
+ undo: false,
1037
+ refreshAfterCallback: false,
1038
+ html: function () {
1039
+ var c = '<ul class="fr-dropdown-list" role="presentation">';
1040
+ var options = this.opts.linkList;
1041
+
1042
+ for (var i = 0; i < options.length; i++) {
1043
+ c += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="linkList" data-param1="' + i + '">' + (options[i].displayText || options[i].text) + '</a></li>';
1044
+ }
1045
+ c += '</ul>';
1046
+
1047
+ return c;
1048
+ },
1049
+ callback: function (cmd, val) {
1050
+ this.link.usePredefined(val);
1051
+ },
1052
+ plugin: 'link'
1053
+ })
1054
+
1055
+ $.FE.RegisterCommand('linkInsert', {
1056
+ focus: false,
1057
+ refreshAfterCallback: false,
1058
+ callback: function () {
1059
+ this.link.insertCallback();
1060
+ },
1061
+ refresh: function ($btn) {
1062
+ var link = this.link.get();
1063
+
1064
+ if (link) {
1065
+ $btn.text(this.language.translate('Update'));
1066
+ }
1067
+ else {
1068
+ $btn.text(this.language.translate('Insert'));
1069
+ }
1070
+ },
1071
+ plugin: 'link'
1072
+ })
1073
+
1074
+ // Image link.
1075
+ $.FE.DefineIcon('imageLink', { NAME: 'link' })
1076
+ $.FE.RegisterCommand('imageLink', {
1077
+ title: 'Insert Link',
1078
+ undo: false,
1079
+ focus: false,
1080
+ popup: true,
1081
+ callback: function () {
1082
+ this.link.imageLink();
1083
+ },
1084
+ refresh: function ($btn) {
1085
+ var link = this.link.get();
1086
+ var $prev;
1087
+
1088
+ if (link) {
1089
+ $prev = $btn.prev();
1090
+
1091
+ if ($prev.hasClass('fr-separator')) {
1092
+ $prev.removeClass('fr-hidden');
1093
+ }
1094
+
1095
+ $btn.addClass('fr-hidden');
1096
+ }
1097
+ else {
1098
+ $prev = $btn.prev();
1099
+
1100
+ if ($prev.hasClass('fr-separator')) {
1101
+ $prev.addClass('fr-hidden');
1102
+ }
1103
+
1104
+ $btn.removeClass('fr-hidden');
1105
+ }
1106
+ },
1107
+ plugin: 'link'
1108
+ })
1109
+
1110
+ // Link styles.
1111
+ $.FE.DefineIcon('linkStyle', { NAME: 'magic' })
1112
+ $.FE.RegisterCommand('linkStyle', {
1113
+ title: 'Style',
1114
+ type: 'dropdown',
1115
+ html: function () {
1116
+ var c = '<ul class="fr-dropdown-list" role="presentation">';
1117
+ var options = this.opts.linkStyles;
1118
+
1119
+ for (var cls in options) {
1120
+ if (options.hasOwnProperty(cls)) {
1121
+ c += '<li role="presentation"><a class="fr-command" tabIndex="-1" role="option" data-cmd="linkStyle" data-param1="' + cls + '">' + this.language.translate(options[cls]) + '</a></li>';
1122
+ }
1123
+ }
1124
+ c += '</ul>';
1125
+
1126
+ return c;
1127
+ },
1128
+ callback: function (cmd, val) {
1129
+ this.link.applyStyle(val);
1130
+ },
1131
+ refreshOnShow: function ($btn, $dropdown) {
1132
+ var link = this.link.get();
1133
+
1134
+ if (link) {
1135
+ var $link = $(link);
1136
+
1137
+ $dropdown.find('.fr-command').each (function () {
1138
+ var cls = $(this).data('param1');
1139
+ var active = $link.hasClass(cls);
1140
+ $(this).toggleClass('fr-active', active).attr('aria-selected', active);
1141
+ })
1142
+ }
1143
+ },
1144
+ refresh: function ($btn) {
1145
+ var link = this.link.get();
1146
+
1147
+ if (link) {
1148
+ $btn.removeClass('fr-hidden');
1149
+ }
1150
+ else {
1151
+ $btn.addClass('fr-hidden');
1152
+ }
1153
+ },
1154
+ plugin: 'link'
1155
+ })
1156
+
1157
+ }));