bedrock_sass 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/_vendor/tinymce/plugins/advlist/index.js +7 -0
  4. data/assets/_vendor/tinymce/plugins/advlist/plugin.js +428 -0
  5. data/assets/_vendor/tinymce/plugins/advlist/plugin.min.js +1 -0
  6. data/assets/_vendor/tinymce/plugins/anchor/index.js +7 -0
  7. data/assets/_vendor/tinymce/plugins/anchor/plugin.js +338 -0
  8. data/assets/_vendor/tinymce/plugins/anchor/plugin.min.js +1 -0
  9. data/assets/_vendor/tinymce/plugins/autolink/index.js +7 -0
  10. data/assets/_vendor/tinymce/plugins/autolink/plugin.js +404 -0
  11. data/assets/_vendor/tinymce/plugins/autolink/plugin.min.js +1 -0
  12. data/assets/_vendor/tinymce/plugins/autoresize/index.js +7 -0
  13. data/assets/_vendor/tinymce/plugins/autoresize/plugin.js +451 -0
  14. data/assets/_vendor/tinymce/plugins/autoresize/plugin.min.js +1 -0
  15. data/assets/_vendor/tinymce/plugins/autosave/index.js +7 -0
  16. data/assets/_vendor/tinymce/plugins/autosave/plugin.js +608 -0
  17. data/assets/_vendor/tinymce/plugins/autosave/plugin.min.js +1 -0
  18. data/assets/_vendor/tinymce/plugins/bbcode/index.js +7 -0
  19. data/assets/_vendor/tinymce/plugins/bbcode/plugin.js +264 -0
  20. data/assets/_vendor/tinymce/plugins/bbcode/plugin.min.js +1 -0
  21. data/assets/_vendor/tinymce/plugins/charmap/index.js +7 -0
  22. data/assets/_vendor/tinymce/plugins/charmap/plugin.js +850 -0
  23. data/assets/_vendor/tinymce/plugins/charmap/plugin.min.js +1 -0
  24. data/assets/_vendor/tinymce/plugins/code/index.js +7 -0
  25. data/assets/_vendor/tinymce/plugins/code/plugin.js +338 -0
  26. data/assets/_vendor/tinymce/plugins/code/plugin.min.js +1 -0
  27. data/assets/_vendor/tinymce/plugins/codesample/css/prism.css +138 -0
  28. data/assets/_vendor/tinymce/plugins/codesample/index.js +7 -0
  29. data/assets/_vendor/tinymce/plugins/codesample/plugin.js +1582 -0
  30. data/assets/_vendor/tinymce/plugins/codesample/plugin.min.js +1 -0
  31. data/assets/_vendor/tinymce/plugins/colorpicker/index.js +7 -0
  32. data/assets/_vendor/tinymce/plugins/colorpicker/plugin.js +272 -0
  33. data/assets/_vendor/tinymce/plugins/colorpicker/plugin.min.js +1 -0
  34. data/assets/_vendor/tinymce/plugins/contextmenu/index.js +7 -0
  35. data/assets/_vendor/tinymce/plugins/contextmenu/plugin.js +496 -0
  36. data/assets/_vendor/tinymce/plugins/contextmenu/plugin.min.js +1 -0
  37. data/assets/_vendor/tinymce/plugins/directionality/index.js +7 -0
  38. data/assets/_vendor/tinymce/plugins/directionality/plugin.js +270 -0
  39. data/assets/_vendor/tinymce/plugins/directionality/plugin.min.js +1 -0
  40. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-cool.gif +0 -0
  41. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-cry.gif +0 -0
  42. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-embarassed.gif +0 -0
  43. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif +0 -0
  44. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-frown.gif +0 -0
  45. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-innocent.gif +0 -0
  46. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-kiss.gif +0 -0
  47. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-laughing.gif +0 -0
  48. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-money-mouth.gif +0 -0
  49. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-sealed.gif +0 -0
  50. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-smile.gif +0 -0
  51. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-surprised.gif +0 -0
  52. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-tongue-out.gif +0 -0
  53. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-undecided.gif +0 -0
  54. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-wink.gif +0 -0
  55. data/assets/_vendor/tinymce/plugins/emoticons/img/smiley-yell.gif +0 -0
  56. data/assets/_vendor/tinymce/plugins/emoticons/index.js +7 -0
  57. data/assets/_vendor/tinymce/plugins/emoticons/plugin.js +256 -0
  58. data/assets/_vendor/tinymce/plugins/emoticons/plugin.min.js +1 -0
  59. data/assets/_vendor/tinymce/plugins/fullpage/index.js +7 -0
  60. data/assets/_vendor/tinymce/plugins/fullpage/plugin.js +962 -0
  61. data/assets/_vendor/tinymce/plugins/fullpage/plugin.min.js +1 -0
  62. data/assets/_vendor/tinymce/plugins/fullscreen/index.js +7 -0
  63. data/assets/_vendor/tinymce/plugins/fullscreen/plugin.js +455 -0
  64. data/assets/_vendor/tinymce/plugins/fullscreen/plugin.min.js +1 -0
  65. data/assets/_vendor/tinymce/plugins/help/img/logo.png +0 -0
  66. data/assets/_vendor/tinymce/plugins/help/index.js +7 -0
  67. data/assets/_vendor/tinymce/plugins/help/plugin.js +1527 -0
  68. data/assets/_vendor/tinymce/plugins/help/plugin.min.js +1 -0
  69. data/assets/_vendor/tinymce/plugins/hr/index.js +7 -0
  70. data/assets/_vendor/tinymce/plugins/hr/plugin.js +195 -0
  71. data/assets/_vendor/tinymce/plugins/hr/plugin.min.js +1 -0
  72. data/assets/_vendor/tinymce/plugins/image/index.js +7 -0
  73. data/assets/_vendor/tinymce/plugins/image/plugin.js +1572 -0
  74. data/assets/_vendor/tinymce/plugins/image/plugin.min.js +1 -0
  75. data/assets/_vendor/tinymce/plugins/imagetools/index.js +7 -0
  76. data/assets/_vendor/tinymce/plugins/imagetools/plugin.js +4444 -0
  77. data/assets/_vendor/tinymce/plugins/imagetools/plugin.min.js +2 -0
  78. data/assets/_vendor/tinymce/plugins/importcss/index.js +7 -0
  79. data/assets/_vendor/tinymce/plugins/importcss/plugin.js +577 -0
  80. data/assets/_vendor/tinymce/plugins/importcss/plugin.min.js +1 -0
  81. data/assets/_vendor/tinymce/plugins/insertdatetime/index.js +7 -0
  82. data/assets/_vendor/tinymce/plugins/insertdatetime/plugin.js +482 -0
  83. data/assets/_vendor/tinymce/plugins/insertdatetime/plugin.min.js +1 -0
  84. data/assets/_vendor/tinymce/plugins/legacyoutput/index.js +7 -0
  85. data/assets/_vendor/tinymce/plugins/legacyoutput/plugin.js +395 -0
  86. data/assets/_vendor/tinymce/plugins/legacyoutput/plugin.min.js +1 -0
  87. data/assets/_vendor/tinymce/plugins/link/index.js +7 -0
  88. data/assets/_vendor/tinymce/plugins/link/plugin.js +1231 -0
  89. data/assets/_vendor/tinymce/plugins/link/plugin.min.js +1 -0
  90. data/assets/_vendor/tinymce/plugins/lists/index.js +7 -0
  91. data/assets/_vendor/tinymce/plugins/lists/plugin.js +1985 -0
  92. data/assets/_vendor/tinymce/plugins/lists/plugin.min.js +1 -0
  93. data/assets/_vendor/tinymce/plugins/media/index.js +7 -0
  94. data/assets/_vendor/tinymce/plugins/media/plugin.js +2026 -0
  95. data/assets/_vendor/tinymce/plugins/media/plugin.min.js +1 -0
  96. data/assets/_vendor/tinymce/plugins/nonbreaking/index.js +7 -0
  97. data/assets/_vendor/tinymce/plugins/nonbreaking/plugin.js +313 -0
  98. data/assets/_vendor/tinymce/plugins/nonbreaking/plugin.min.js +1 -0
  99. data/assets/_vendor/tinymce/plugins/noneditable/index.js +7 -0
  100. data/assets/_vendor/tinymce/plugins/noneditable/plugin.js +316 -0
  101. data/assets/_vendor/tinymce/plugins/noneditable/plugin.min.js +1 -0
  102. data/assets/_vendor/tinymce/plugins/pagebreak/index.js +7 -0
  103. data/assets/_vendor/tinymce/plugins/pagebreak/plugin.js +354 -0
  104. data/assets/_vendor/tinymce/plugins/pagebreak/plugin.min.js +1 -0
  105. data/assets/_vendor/tinymce/plugins/paste/index.js +7 -0
  106. data/assets/_vendor/tinymce/plugins/paste/plugin.js +2935 -0
  107. data/assets/_vendor/tinymce/plugins/paste/plugin.min.js +1 -0
  108. data/assets/_vendor/tinymce/plugins/preview/index.js +7 -0
  109. data/assets/_vendor/tinymce/plugins/preview/plugin.js +410 -0
  110. data/assets/_vendor/tinymce/plugins/preview/plugin.min.js +1 -0
  111. data/assets/_vendor/tinymce/plugins/print/index.js +7 -0
  112. data/assets/_vendor/tinymce/plugins/print/plugin.js +194 -0
  113. data/assets/_vendor/tinymce/plugins/print/plugin.min.js +1 -0
  114. data/assets/_vendor/tinymce/plugins/save/index.js +7 -0
  115. data/assets/_vendor/tinymce/plugins/save/plugin.js +370 -0
  116. data/assets/_vendor/tinymce/plugins/save/plugin.min.js +1 -0
  117. data/assets/_vendor/tinymce/plugins/searchreplace/index.js +7 -0
  118. data/assets/_vendor/tinymce/plugins/searchreplace/plugin.js +977 -0
  119. data/assets/_vendor/tinymce/plugins/searchreplace/plugin.min.js +1 -0
  120. data/assets/_vendor/tinymce/plugins/spellchecker/index.js +7 -0
  121. data/assets/_vendor/tinymce/plugins/spellchecker/plugin.js +1419 -0
  122. data/assets/_vendor/tinymce/plugins/spellchecker/plugin.min.js +1 -0
  123. data/assets/_vendor/tinymce/plugins/tabfocus/index.js +7 -0
  124. data/assets/_vendor/tinymce/plugins/tabfocus/plugin.js +419 -0
  125. data/assets/_vendor/tinymce/plugins/tabfocus/plugin.min.js +1 -0
  126. data/assets/_vendor/tinymce/plugins/table/index.js +7 -0
  127. data/assets/_vendor/tinymce/plugins/table/plugin.js +15527 -0
  128. data/assets/_vendor/tinymce/plugins/table/plugin.min.js +5 -0
  129. data/assets/_vendor/tinymce/plugins/template/index.js +7 -0
  130. data/assets/_vendor/tinymce/plugins/template/plugin.js +807 -0
  131. data/assets/_vendor/tinymce/plugins/template/plugin.min.js +1 -0
  132. data/assets/_vendor/tinymce/plugins/textcolor/index.js +7 -0
  133. data/assets/_vendor/tinymce/plugins/textcolor/plugin.js +619 -0
  134. data/assets/_vendor/tinymce/plugins/textcolor/plugin.min.js +1 -0
  135. data/assets/_vendor/tinymce/plugins/textpattern/index.js +7 -0
  136. data/assets/_vendor/tinymce/plugins/textpattern/plugin.js +718 -0
  137. data/assets/_vendor/tinymce/plugins/textpattern/plugin.min.js +1 -0
  138. data/assets/_vendor/tinymce/plugins/toc/index.js +7 -0
  139. data/assets/_vendor/tinymce/plugins/toc/plugin.js +559 -0
  140. data/assets/_vendor/tinymce/plugins/toc/plugin.min.js +1 -0
  141. data/assets/_vendor/tinymce/plugins/visualblocks/css/visualblocks.css +154 -0
  142. data/assets/_vendor/tinymce/plugins/visualblocks/index.js +7 -0
  143. data/assets/_vendor/tinymce/plugins/visualblocks/plugin.js +459 -0
  144. data/assets/_vendor/tinymce/plugins/visualblocks/plugin.min.js +1 -0
  145. data/assets/_vendor/tinymce/plugins/visualchars/index.js +7 -0
  146. data/assets/_vendor/tinymce/plugins/visualchars/plugin.js +1325 -0
  147. data/assets/_vendor/tinymce/plugins/visualchars/plugin.min.js +1 -0
  148. data/assets/_vendor/tinymce/plugins/wordcount/index.js +7 -0
  149. data/assets/_vendor/tinymce/plugins/wordcount/plugin.js +735 -0
  150. data/assets/_vendor/tinymce/plugins/wordcount/plugin.min.js +1 -0
  151. data/assets/_vendor/tinymce/skins/lightgray/content.inline.min.css +1 -0
  152. data/assets/_vendor/tinymce/skins/lightgray/content.min.css +1 -0
  153. data/assets/_vendor/tinymce/skins/lightgray/content.mobile.min.css +1 -0
  154. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-mobile.woff +0 -0
  155. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.eot +0 -0
  156. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.svg +63 -0
  157. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.ttf +0 -0
  158. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce-small.woff +0 -0
  159. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.eot +0 -0
  160. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.svg +131 -0
  161. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.ttf +0 -0
  162. data/assets/_vendor/tinymce/skins/lightgray/fonts/tinymce.woff +0 -0
  163. data/assets/_vendor/tinymce/skins/lightgray/img/anchor.gif +0 -0
  164. data/assets/_vendor/tinymce/skins/lightgray/img/loader.gif +0 -0
  165. data/assets/_vendor/tinymce/skins/lightgray/img/object.gif +0 -0
  166. data/assets/_vendor/tinymce/skins/lightgray/img/trans.gif +0 -0
  167. data/assets/_vendor/tinymce/skins/lightgray/skin.min.css +1 -0
  168. data/assets/_vendor/tinymce/skins/lightgray/skin.mobile.min.css +2 -0
  169. data/assets/_vendor/tinymce/themes/inlite/index.js +7 -0
  170. data/assets/_vendor/tinymce/themes/inlite/theme.js +18787 -0
  171. data/assets/_vendor/tinymce/themes/inlite/theme.min.js +5 -0
  172. data/assets/_vendor/tinymce/themes/mobile/index.js +7 -0
  173. data/assets/_vendor/tinymce/themes/mobile/theme.js +23384 -0
  174. data/assets/_vendor/tinymce/themes/mobile/theme.min.js +8 -0
  175. data/assets/_vendor/tinymce/themes/modern/index.js +7 -0
  176. data/assets/_vendor/tinymce/themes/modern/theme.js +18311 -0
  177. data/assets/_vendor/tinymce/themes/modern/theme.min.js +5 -0
  178. data/assets/_vendor/tinymce/tinymce.js +44399 -0
  179. data/assets/bedrock/js/bedrock.js +16587 -6193
  180. data/assets/bedrock/scss/_bedrock-components.scss +16 -0
  181. data/assets/bedrock/scss/_bedrock-settings.scss +15 -0
  182. data/assets/bedrock/scss/components/attachments-grid.scss +138 -0
  183. data/assets/bedrock/scss/components/dropzone-upload.scss +158 -0
  184. data/assets/bedrock/scss/components/global.scss +16 -8
  185. data/assets/bedrock/scss/components/helper-classes.scss +59 -0
  186. data/assets/bedrock/scss/components/inline-edit-box.scss +80 -0
  187. data/assets/bedrock/scss/components/login-box.scss +48 -0
  188. data/assets/bedrock/scss/components/no-content.scss +31 -0
  189. data/assets/bedrock/scss/components/off-canvas-menu.scss +1 -1
  190. data/assets/bedrock/scss/components/page-content.scss +51 -0
  191. data/assets/bedrock/scss/components/reveal-panel.scss +89 -0
  192. data/assets/bedrock/scss/components/select-box.scss +332 -0
  193. data/assets/bedrock/scss/components/tiny-mce-editor.scss +14 -7
  194. data/lib/bedrock_sass.rb +6 -0
  195. data/lib/bedrock_sass/engine.rb +8 -0
  196. data/lib/bedrock_sass/version.rb +1 -1
  197. data/lib/tasks/before_assets_precompile.rake +11 -0
  198. metadata +188 -2
@@ -0,0 +1 @@
1
+ !function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e[f]=d(a[f]);b.apply(null,e)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};g("1",[],function(){var a=function(b){var c=b,d=function(){return c},e=function(a){c=a},f=function(){return a(d())};return{get:d,set:e,clone:f}};return a}),h("6",tinymce.util.Tools.resolve),g("2",["6"],function(a){return a("tinymce.PluginManager")}),g("9",["6"],function(a){return a("tinymce.util.Tools")}),g("a",[],function(){function a(a){return a&&1===a.nodeType&&"false"===a.contentEditable}function b(b,c,d,e,f){function g(a,b){if(b=b||0,!a[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var c=a.index;if(b>0){var d=a[b];if(!d)throw"Invalid capture group";c+=a[0].indexOf(d),a[0]=d}return[c,c+a[0].length,[a[0]]]}function h(b){var c;if(3===b.nodeType)return b.data;if(o[b.nodeName]&&!n[b.nodeName])return"";if(c="",a(b))return"\n";if((n[b.nodeName]||p[b.nodeName])&&(c+="\n"),b=b.firstChild)do c+=h(b);while(b=b.nextSibling);return c}function i(b,c,d){var e,f,g,h,i=[],j=0,k=b,l=c.shift(),m=0;a:for(;;){if((n[k.nodeName]||p[k.nodeName]||a(k))&&j++,3===k.nodeType&&(!f&&k.length+j>=l[1]?(f=k,h=l[1]-j):e&&i.push(k),!e&&k.length+j>l[0]&&(e=k,g=l[0]-j),j+=k.length),e&&f){if(k=d({startNode:e,startNodeIndex:g,endNode:f,endNodeIndex:h,innerNodes:i,match:l[2],matchIndex:m}),j-=f.length-h,e=null,f=null,i=[],l=c.shift(),m++,!l)break}else if(o[k.nodeName]&&!n[k.nodeName]||!k.firstChild){if(k.nextSibling){k=k.nextSibling;continue}}else if(!a(k)){k=k.firstChild;continue}for(;;){if(k.nextSibling){k=k.nextSibling;break}if(k.parentNode===b)break a;k=k.parentNode}}}function j(a){var b;if("function"!=typeof a){var c=a.nodeType?a:m.createElement(a);b=function(a,b){var d=c.cloneNode(!1);return d.setAttribute("data-mce-index",b),a&&d.appendChild(m.createTextNode(a)),d}}else b=a;return function(a){var c,d,e,f=a.startNode,g=a.endNode,h=a.matchIndex;if(f===g){var i=f;e=i.parentNode,a.startNodeIndex>0&&(c=m.createTextNode(i.data.substring(0,a.startNodeIndex)),e.insertBefore(c,i));var j=b(a.match[0],h);return e.insertBefore(j,i),a.endNodeIndex<i.length&&(d=m.createTextNode(i.data.substring(a.endNodeIndex)),e.insertBefore(d,i)),i.parentNode.removeChild(i),j}c=m.createTextNode(f.data.substring(0,a.startNodeIndex)),d=m.createTextNode(g.data.substring(a.endNodeIndex));for(var k=b(f.data.substring(a.startNodeIndex),h),l=[],n=0,o=a.innerNodes.length;n<o;++n){var p=a.innerNodes[n],q=b(p.data,h);p.parentNode.replaceChild(q,p),l.push(q)}var r=b(g.data.substring(0,a.endNodeIndex),h);return e=f.parentNode,e.insertBefore(c,f),e.insertBefore(k,f),e.removeChild(f),e=g.parentNode,e.insertBefore(r,g),e.insertBefore(d,g),e.removeChild(g),r}}var k,l,m,n,o,p,q=[],r=0;if(m=c.ownerDocument,n=f.getBlockElements(),o=f.getWhiteSpaceElements(),p=f.getShortEndedElements(),l=h(c)){if(b.global)for(;k=b.exec(l);)q.push(g(k,e));else k=l.match(b),q.push(g(k,e));return q.length&&(r=q.length,i(c,q,j(d))),r}}return{findAndReplaceDOMText:b}}),g("7",["9","a"],function(a,b){var c=function(a){var b=a.getAttribute("data-mce-index");return"number"==typeof b?""+b:b},d=function(a,c,d){var e,f;return f=a.dom.create("span",{"data-mce-bogus":1}),f.className="mce-match-marker",e=a.getBody(),n(a,c,!1),b.findAndReplaceDOMText(d,e,f,!1,a.schema)},e=function(a){var b=a.parentNode;a.firstChild&&b.insertBefore(a.firstChild,a),a.parentNode.removeChild(a)},f=function(b,d){var e,f=[];if(e=a.toArray(b.getBody().getElementsByTagName("span")),e.length)for(var g=0;g<e.length;g++){var h=c(e[g]);null!==h&&h.length&&h===d.toString()&&f.push(e[g])}return f},g=function(a,b,c){var d=b.get(),e=a.dom;c=c!==!1,c?d++:d--,e.removeClass(f(a,b.get()),"mce-match-marker-selected");var g=f(a,d);return g.length?(e.addClass(f(a,d),"mce-match-marker-selected"),a.selection.scrollIntoView(g[0]),d):-1},h=function(a,b){var c=b.parentNode;a.remove(b),a.isEmpty(c)&&a.remove(c)},i=function(a,b,c,e,f){c=c.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),c=c.replace(/\s/g,"\\s"),c=f?"\\b"+c+"\\b":c;var h=d(a,b,new RegExp(c,e?"g":"gi"));return h&&(b.set(-1),b.set(g(a,b,!0))),h},j=function(a,b){var c=g(a,b,!0);c!==-1&&b.set(c)},k=function(a,b){var c=g(a,b,!1);c!==-1&&b.set(c)},l=function(a){var b=c(a);return null!==b&&b.length>0},m=function(b,d,f,g,i){var m,n,q,r,s,t,u=d.get();for(g=g!==!1,q=b.getBody(),n=a.grep(a.toArray(q.getElementsByTagName("span")),l),m=0;m<n.length;m++){var v=c(n[m]);if(r=s=parseInt(v,10),i||r===d.get()){for(f.length?(n[m].firstChild.nodeValue=f,e(n[m])):h(b.dom,n[m]);n[++m];){if(r=parseInt(c(n[m]),10),r!==s){m--;break}h(b.dom,n[m])}g&&u--}else s>d.get()&&n[m].setAttribute("data-mce-index",s-1)}return d.set(u),g?(t=o(b,d),j(b,d)):(t=p(b,d),k(b,d)),!i&&t},n=function(b,d,f){var g,h,i,j;for(h=a.toArray(b.getBody().getElementsByTagName("span")),g=0;g<h.length;g++){var k=c(h[g]);null!==k&&k.length&&(k===d.get().toString()&&(i||(i=h[g].firstChild),j=h[g].firstChild),e(h[g]))}if(i&&j){var l=b.dom.createRng();return l.setStart(i,0),l.setEnd(j,j.data.length),f!==!1&&b.selection.setRng(l),l}},o=function(a,b){return f(a,b.get()+1).length>0},p=function(a,b){return f(a,b.get()-1).length>0};return{done:n,find:i,next:j,prev:k,replace:m,hasNext:o,hasPrev:p}}),g("3",["7"],function(a){var b=function(b,c){var d=function(d){return a.done(b,c,d)},e=function(d,e,f){return a.find(b,c,d,e,f)},f=function(){return a.next(b,c)},g=function(){return a.prev(b,c)},h=function(d,e,f){return a.replace(b,c,d,e,f)};return{done:d,find:e,next:f,prev:g,replace:h}};return{get:b}}),g("8",["9","7"],function(a,b){var c=function(c,d){function e(){i.statusbar.find("#next").disabled(b.hasNext(c,d)===!1),i.statusbar.find("#prev").disabled(b.hasPrev(c,d)===!1)}function f(){c.windowManager.alert("Could not find the specified string.",function(){i.find("#find")[0].focus()})}var g,h={};c.undoManager.add(),g=a.trim(c.selection.getContent({format:"text"}));var i=c.windowManager.open({layout:"flex",pack:"center",align:"center",onClose:function(){c.focus(),b.done(c,d),c.undoManager.add()},onSubmit:function(a){var g,j,k,l;return a.preventDefault(),j=i.find("#case").checked(),l=i.find("#words").checked(),k=i.find("#find").value(),k.length?h.text===k&&h.caseState===j&&h.wholeWord===l?b.hasNext(c,d)?(b.next(c,d),void e()):void f():(g=b.find(c,d,k,j,l),g||f(),i.statusbar.items().slice(1).disabled(0===g),e(),void(h={text:k,caseState:j,wholeWord:l})):(b.done(c,d,!1),void i.statusbar.items().slice(1).disabled(!0))},buttons:[{text:"Find",subtype:"primary",onclick:function(){i.submit()}},{text:"Replace",disabled:!0,onclick:function(){b.replace(c,d,i.find("#replace").value())||(i.statusbar.items().slice(1).disabled(!0),d.set(-1),h={})}},{text:"Replace all",disabled:!0,onclick:function(){b.replace(c,d,i.find("#replace").value(),!0,!0),i.statusbar.items().slice(1).disabled(!0),h={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){b.prev(c,d),e()}},{text:"Next",name:"next",disabled:!0,onclick:function(){b.next(c,d),e()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:g},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}})};return{open:c}}),g("4",["8"],function(a){var b=function(b,c){b.addCommand("SearchReplace",function(){a.open(b,c)})};return{register:b}}),g("5",["8"],function(a){var b=function(b,c){return function(){a.open(b,c)}},c=function(a,c){a.addMenuItem("searchreplace",{text:"Find and replace",shortcut:"Meta+F",onclick:b(a,c),separator:"before",context:"edit"}),a.addButton("searchreplace",{tooltip:"Find and replace",onclick:b(a,c)}),a.shortcuts.add("Meta+F","",b(a,c))};return{register:c}}),g("0",["1","2","3","4","5"],function(a,b,c,d,e){return b.add("searchreplace",function(b){var f=a(-1);return d.register(b,f),e.register(b,f),c.get(b,f)}),function(){}}),d("0")()}();
@@ -0,0 +1,7 @@
1
+ // Exports the "spellchecker" plugin for usage with module loaders
2
+ // Usage:
3
+ // CommonJS:
4
+ // require('tinymce/plugins/spellchecker')
5
+ // ES2015:
6
+ // import 'tinymce/plugins/spellchecker'
7
+ require('./plugin.js');
@@ -0,0 +1,1419 @@
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[i] = dem(ids[i]);
61
+ callback.apply(null, instances);
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 minification when using a lot of global references
80
+ var defineGlobal = function (id, ref) {
81
+ define(id, [], function () { return ref; });
82
+ };
83
+ /*jsc
84
+ ["tinymce.plugins.spellchecker.Plugin","ephox.katamari.api.Cell","tinymce.core.PluginManager","tinymce.plugins.spellchecker.alien.DetectProPlugin","tinymce.plugins.spellchecker.api.Api","tinymce.plugins.spellchecker.api.Commands","tinymce.plugins.spellchecker.api.Settings","tinymce.plugins.spellchecker.ui.Buttons","tinymce.plugins.spellchecker.ui.SuggestionsMenu","global!tinymce.util.Tools.resolve","global!window","tinymce.plugins.spellchecker.core.Actions","tinymce.core.util.Tools","global!document","tinymce.core.dom.DOMUtils","tinymce.core.ui.Factory","tinymce.core.util.URI","tinymce.core.util.XHR","tinymce.plugins.spellchecker.api.Events","tinymce.plugins.spellchecker.core.DomTextMatcher"]
85
+ jsc*/
86
+ define(
87
+ 'ephox.katamari.api.Cell',
88
+
89
+ [
90
+ ],
91
+
92
+ function () {
93
+ var Cell = function (initial) {
94
+ var value = initial;
95
+
96
+ var get = function () {
97
+ return value;
98
+ };
99
+
100
+ var set = function (v) {
101
+ value = v;
102
+ };
103
+
104
+ var clone = function () {
105
+ return Cell(get());
106
+ };
107
+
108
+ return {
109
+ get: get,
110
+ set: set,
111
+ clone: clone
112
+ };
113
+ };
114
+
115
+ return Cell;
116
+ }
117
+ );
118
+
119
+ defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
120
+ /**
121
+ * ResolveGlobal.js
122
+ *
123
+ * Released under LGPL License.
124
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
125
+ *
126
+ * License: http://www.tinymce.com/license
127
+ * Contributing: http://www.tinymce.com/contributing
128
+ */
129
+
130
+ define(
131
+ 'tinymce.core.PluginManager',
132
+ [
133
+ 'global!tinymce.util.Tools.resolve'
134
+ ],
135
+ function (resolve) {
136
+ return resolve('tinymce.PluginManager');
137
+ }
138
+ );
139
+
140
+ defineGlobal("global!window", window);
141
+ /**
142
+ * DetectProPlugin.js
143
+ *
144
+ * Released under LGPL License.
145
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
146
+ *
147
+ * License: http://www.tinymce.com/license
148
+ * Contributing: http://www.tinymce.com/contributing
149
+ */
150
+
151
+ define(
152
+ 'tinymce.plugins.spellchecker.alien.DetectProPlugin',
153
+ [
154
+ 'global!window',
155
+ 'tinymce.core.PluginManager'
156
+ ],
157
+ function (window, PluginManager) {
158
+ var hasProPlugin = function (editor) {
159
+ // draw back if power version is requested and registered
160
+ if (/(^|[ ,])tinymcespellchecker([, ]|$)/.test(editor.settings.plugins) && PluginManager.get('tinymcespellchecker')) {
161
+ /*eslint no-console:0 */
162
+ if (typeof window.console !== "undefined" && window.console.log) {
163
+ window.console.log(
164
+ "Spell Checker Pro is incompatible with Spell Checker plugin! " +
165
+ "Remove 'spellchecker' from the 'plugins' option."
166
+ );
167
+ }
168
+ return true;
169
+ } else {
170
+ return false;
171
+ }
172
+ };
173
+
174
+ return {
175
+ hasProPlugin: hasProPlugin
176
+ };
177
+ }
178
+ );
179
+
180
+ /**
181
+ * Settings.js
182
+ *
183
+ * Released under LGPL License.
184
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
185
+ *
186
+ * License: http://www.tinymce.com/license
187
+ * Contributing: http://www.tinymce.com/contributing
188
+ */
189
+
190
+ define(
191
+ 'tinymce.plugins.spellchecker.api.Settings',
192
+ [
193
+ ],
194
+ function () {
195
+ var getLanguages = function (editor) {
196
+ var defaultLanguages = 'English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,German=de,Italian=it,Polish=pl,Portuguese=pt_BR,Spanish=es,Swedish=sv';
197
+ return editor.getParam('spellchecker_languages', defaultLanguages);
198
+ };
199
+
200
+ var getLanguage = function (editor) {
201
+ var defaultLanguage = editor.getParam('language', 'en');
202
+ return editor.getParam('spellchecker_language', defaultLanguage);
203
+ };
204
+
205
+ var getRpcUrl = function (editor) {
206
+ return editor.getParam('spellchecker_rpc_url');
207
+ };
208
+
209
+ var getSpellcheckerCallback = function (editor) {
210
+ return editor.getParam('spellchecker_callback');
211
+ };
212
+
213
+ var getSpellcheckerWordcharPattern = function (editor) {
214
+ var defaultPattern = new RegExp("[^" +
215
+ "\\s!\"#$%&()*+,-./:;<=>?@[\\]^_{|}`" +
216
+ "\u00a7\u00a9\u00ab\u00ae\u00b1\u00b6\u00b7\u00b8\u00bb" +
217
+ "\u00bc\u00bd\u00be\u00bf\u00d7\u00f7\u00a4\u201d\u201c\u201e\u00a0\u2002\u2003\u2009" +
218
+ "]+", "g");
219
+ return editor.getParam('spellchecker_wordchar_pattern', defaultPattern);
220
+ };
221
+
222
+ return {
223
+ getLanguages: getLanguages,
224
+ getLanguage: getLanguage,
225
+ getRpcUrl: getRpcUrl,
226
+ getSpellcheckerCallback: getSpellcheckerCallback,
227
+ getSpellcheckerWordcharPattern: getSpellcheckerWordcharPattern
228
+ };
229
+ }
230
+ );
231
+ /**
232
+ * ResolveGlobal.js
233
+ *
234
+ * Released under LGPL License.
235
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
236
+ *
237
+ * License: http://www.tinymce.com/license
238
+ * Contributing: http://www.tinymce.com/contributing
239
+ */
240
+
241
+ define(
242
+ 'tinymce.core.util.Tools',
243
+ [
244
+ 'global!tinymce.util.Tools.resolve'
245
+ ],
246
+ function (resolve) {
247
+ return resolve('tinymce.util.Tools');
248
+ }
249
+ );
250
+
251
+ /**
252
+ * ResolveGlobal.js
253
+ *
254
+ * Released under LGPL License.
255
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
256
+ *
257
+ * License: http://www.tinymce.com/license
258
+ * Contributing: http://www.tinymce.com/contributing
259
+ */
260
+
261
+ define(
262
+ 'tinymce.core.util.URI',
263
+ [
264
+ 'global!tinymce.util.Tools.resolve'
265
+ ],
266
+ function (resolve) {
267
+ return resolve('tinymce.util.URI');
268
+ }
269
+ );
270
+
271
+ /**
272
+ * ResolveGlobal.js
273
+ *
274
+ * Released under LGPL License.
275
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
276
+ *
277
+ * License: http://www.tinymce.com/license
278
+ * Contributing: http://www.tinymce.com/contributing
279
+ */
280
+
281
+ define(
282
+ 'tinymce.core.util.XHR',
283
+ [
284
+ 'global!tinymce.util.Tools.resolve'
285
+ ],
286
+ function (resolve) {
287
+ return resolve('tinymce.util.XHR');
288
+ }
289
+ );
290
+
291
+ /**
292
+ * Events.js
293
+ *
294
+ * Released under LGPL License.
295
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
296
+ *
297
+ * License: http://www.tinymce.com/license
298
+ * Contributing: http://www.tinymce.com/contributing
299
+ */
300
+
301
+ define(
302
+ 'tinymce.plugins.spellchecker.api.Events',
303
+ [
304
+ ],
305
+ function () {
306
+ var fireSpellcheckStart = function (editor) {
307
+ return editor.fire('SpellcheckStart');
308
+ };
309
+
310
+ var fireSpellcheckEnd = function (editor) {
311
+ return editor.fire('SpellcheckEnd');
312
+ };
313
+
314
+ return {
315
+ fireSpellcheckStart: fireSpellcheckStart,
316
+ fireSpellcheckEnd: fireSpellcheckEnd
317
+ };
318
+ }
319
+ );
320
+ /**
321
+ * DomTextMatcher.js
322
+ *
323
+ * Released under LGPL License.
324
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
325
+ *
326
+ * License: http://www.tinymce.com/license
327
+ * Contributing: http://www.tinymce.com/contributing
328
+ */
329
+
330
+ define(
331
+ 'tinymce.plugins.spellchecker.core.DomTextMatcher',
332
+ [
333
+ ],
334
+ function () {
335
+ function isContentEditableFalse(node) {
336
+ return node && node.nodeType === 1 && node.contentEditable === "false";
337
+ }
338
+
339
+ // Based on work developed by: James Padolsey http://james.padolsey.com
340
+ // released under UNLICENSE that is compatible with LGPL
341
+ // TODO: Handle contentEditable edgecase:
342
+ // <p>text<span contentEditable="false">text<span contentEditable="true">text</span>text</span>text</p>
343
+ return function (node, editor) {
344
+ var m, matches = [], text, dom = editor.dom;
345
+ var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap;
346
+
347
+ blockElementsMap = editor.schema.getBlockElements(); // H1-H6, P, TD etc
348
+ hiddenTextElementsMap = editor.schema.getWhiteSpaceElements(); // TEXTAREA, PRE, STYLE, SCRIPT
349
+ shortEndedElementsMap = editor.schema.getShortEndedElements(); // BR, IMG, INPUT
350
+
351
+ function createMatch(m, data) {
352
+ if (!m[0]) {
353
+ throw 'findAndReplaceDOMText cannot handle zero-length matches';
354
+ }
355
+
356
+ return {
357
+ start: m.index,
358
+ end: m.index + m[0].length,
359
+ text: m[0],
360
+ data: data
361
+ };
362
+ }
363
+
364
+ function getText(node) {
365
+ var txt;
366
+
367
+ if (node.nodeType === 3) {
368
+ return node.data;
369
+ }
370
+
371
+ if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) {
372
+ return '';
373
+ }
374
+
375
+ if (isContentEditableFalse(node)) {
376
+ return '\n';
377
+ }
378
+
379
+ txt = '';
380
+
381
+ if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) {
382
+ txt += '\n';
383
+ }
384
+
385
+ if ((node = node.firstChild)) {
386
+ do {
387
+ txt += getText(node);
388
+ } while ((node = node.nextSibling));
389
+ }
390
+
391
+ return txt;
392
+ }
393
+
394
+ function stepThroughMatches(node, matches, replaceFn) {
395
+ var startNode, endNode, startNodeIndex,
396
+ endNodeIndex, innerNodes = [], atIndex = 0, curNode = node,
397
+ matchLocation, matchIndex = 0;
398
+
399
+ matches = matches.slice(0);
400
+ matches.sort(function (a, b) {
401
+ return a.start - b.start;
402
+ });
403
+
404
+ matchLocation = matches.shift();
405
+
406
+ out: while (true) { //eslint-disable-line no-constant-condition
407
+ if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName] || isContentEditableFalse(curNode)) {
408
+ atIndex++;
409
+ }
410
+
411
+ if (curNode.nodeType === 3) {
412
+ if (!endNode && curNode.length + atIndex >= matchLocation.end) {
413
+ // We've found the ending
414
+ endNode = curNode;
415
+ endNodeIndex = matchLocation.end - atIndex;
416
+ } else if (startNode) {
417
+ // Intersecting node
418
+ innerNodes.push(curNode);
419
+ }
420
+
421
+ if (!startNode && curNode.length + atIndex > matchLocation.start) {
422
+ // We've found the match start
423
+ startNode = curNode;
424
+ startNodeIndex = matchLocation.start - atIndex;
425
+ }
426
+
427
+ atIndex += curNode.length;
428
+ }
429
+
430
+ if (startNode && endNode) {
431
+ curNode = replaceFn({
432
+ startNode: startNode,
433
+ startNodeIndex: startNodeIndex,
434
+ endNode: endNode,
435
+ endNodeIndex: endNodeIndex,
436
+ innerNodes: innerNodes,
437
+ match: matchLocation.text,
438
+ matchIndex: matchIndex
439
+ });
440
+
441
+ // replaceFn has to return the node that replaced the endNode
442
+ // and then we step back so we can continue from the end of the
443
+ // match:
444
+ atIndex -= (endNode.length - endNodeIndex);
445
+ startNode = null;
446
+ endNode = null;
447
+ innerNodes = [];
448
+ matchLocation = matches.shift();
449
+ matchIndex++;
450
+
451
+ if (!matchLocation) {
452
+ break; // no more matches
453
+ }
454
+ } else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) {
455
+ if (!isContentEditableFalse(curNode)) {
456
+ // Move down
457
+ curNode = curNode.firstChild;
458
+ continue;
459
+ }
460
+ } else if (curNode.nextSibling) {
461
+ // Move forward:
462
+ curNode = curNode.nextSibling;
463
+ continue;
464
+ }
465
+
466
+ // Move forward or up:
467
+ while (true) { //eslint-disable-line no-constant-condition
468
+ if (curNode.nextSibling) {
469
+ curNode = curNode.nextSibling;
470
+ break;
471
+ } else if (curNode.parentNode !== node) {
472
+ curNode = curNode.parentNode;
473
+ } else {
474
+ break out;
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
+ /**
481
+ * Generates the actual replaceFn which splits up text nodes
482
+ * and inserts the replacement element.
483
+ */
484
+ function genReplacer(callback) {
485
+ function makeReplacementNode(fill, matchIndex) {
486
+ var match = matches[matchIndex];
487
+
488
+ if (!match.stencil) {
489
+ match.stencil = callback(match);
490
+ }
491
+
492
+ var clone = match.stencil.cloneNode(false);
493
+ clone.setAttribute('data-mce-index', matchIndex);
494
+
495
+ if (fill) {
496
+ clone.appendChild(dom.doc.createTextNode(fill));
497
+ }
498
+
499
+ return clone;
500
+ }
501
+
502
+ return function (range) {
503
+ var before, after, parentNode, startNode = range.startNode,
504
+ endNode = range.endNode, matchIndex = range.matchIndex,
505
+ doc = dom.doc;
506
+
507
+ if (startNode === endNode) {
508
+ var node = startNode;
509
+
510
+ parentNode = node.parentNode;
511
+ if (range.startNodeIndex > 0) {
512
+ // Add "before" text node (before the match)
513
+ before = doc.createTextNode(node.data.substring(0, range.startNodeIndex));
514
+ parentNode.insertBefore(before, node);
515
+ }
516
+
517
+ // Create the replacement node:
518
+ var el = makeReplacementNode(range.match, matchIndex);
519
+ parentNode.insertBefore(el, node);
520
+ if (range.endNodeIndex < node.length) {
521
+ // Add "after" text node (after the match)
522
+ after = doc.createTextNode(node.data.substring(range.endNodeIndex));
523
+ parentNode.insertBefore(after, node);
524
+ }
525
+
526
+ node.parentNode.removeChild(node);
527
+
528
+ return el;
529
+ }
530
+
531
+ // Replace startNode -> [innerNodes...] -> endNode (in that order)
532
+ before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex));
533
+ after = doc.createTextNode(endNode.data.substring(range.endNodeIndex));
534
+ var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex);
535
+ var innerEls = [];
536
+
537
+ for (var i = 0, l = range.innerNodes.length; i < l; ++i) {
538
+ var innerNode = range.innerNodes[i];
539
+ var innerEl = makeReplacementNode(innerNode.data, matchIndex);
540
+ innerNode.parentNode.replaceChild(innerEl, innerNode);
541
+ innerEls.push(innerEl);
542
+ }
543
+
544
+ var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex);
545
+
546
+ parentNode = startNode.parentNode;
547
+ parentNode.insertBefore(before, startNode);
548
+ parentNode.insertBefore(elA, startNode);
549
+ parentNode.removeChild(startNode);
550
+
551
+ parentNode = endNode.parentNode;
552
+ parentNode.insertBefore(elB, endNode);
553
+ parentNode.insertBefore(after, endNode);
554
+ parentNode.removeChild(endNode);
555
+
556
+ return elB;
557
+ };
558
+ }
559
+
560
+ function unwrapElement(element) {
561
+ var parentNode = element.parentNode;
562
+ parentNode.insertBefore(element.firstChild, element);
563
+ element.parentNode.removeChild(element);
564
+ }
565
+
566
+ function hasClass(elm) {
567
+ return elm.className.indexOf('mce-spellchecker-word') !== -1;
568
+ }
569
+
570
+ function getWrappersByIndex(index) {
571
+ var elements = node.getElementsByTagName('*'), wrappers = [];
572
+
573
+ index = typeof index === "number" ? "" + index : null;
574
+
575
+ for (var i = 0; i < elements.length; i++) {
576
+ var element = elements[i], dataIndex = element.getAttribute('data-mce-index');
577
+
578
+ if (dataIndex !== null && dataIndex.length && hasClass(element)) {
579
+ if (dataIndex === index || index === null) {
580
+ wrappers.push(element);
581
+ }
582
+ }
583
+ }
584
+
585
+ return wrappers;
586
+ }
587
+
588
+ /**
589
+ * Returns the index of a specific match object or -1 if it isn't found.
590
+ *
591
+ * @param {Match} match Text match object.
592
+ * @return {Number} Index of match or -1 if it isn't found.
593
+ */
594
+ function indexOf(match) {
595
+ var i = matches.length;
596
+ while (i--) {
597
+ if (matches[i] === match) {
598
+ return i;
599
+ }
600
+ }
601
+
602
+ return -1;
603
+ }
604
+
605
+ /**
606
+ * Filters the matches. If the callback returns true it stays if not it gets removed.
607
+ *
608
+ * @param {Function} callback Callback to execute for each match.
609
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
610
+ */
611
+ function filter(callback) {
612
+ var filteredMatches = [];
613
+
614
+ each(function (match, i) {
615
+ if (callback(match, i)) {
616
+ filteredMatches.push(match);
617
+ }
618
+ });
619
+
620
+ matches = filteredMatches;
621
+
622
+ /*jshint validthis:true*/
623
+ return this;
624
+ }
625
+
626
+ /**
627
+ * Executes the specified callback for each match.
628
+ *
629
+ * @param {Function} callback Callback to execute for each match.
630
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
631
+ */
632
+ function each(callback) {
633
+ for (var i = 0, l = matches.length; i < l; i++) {
634
+ if (callback(matches[i], i) === false) {
635
+ break;
636
+ }
637
+ }
638
+
639
+ /*jshint validthis:true*/
640
+ return this;
641
+ }
642
+
643
+ /**
644
+ * Wraps the current matches with nodes created by the specified callback.
645
+ * Multiple clones of these matches might occur on matches that are on multiple nodex.
646
+ *
647
+ * @param {Function} callback Callback to execute in order to create elements for matches.
648
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
649
+ */
650
+ function wrap(callback) {
651
+ if (matches.length) {
652
+ stepThroughMatches(node, matches, genReplacer(callback));
653
+ }
654
+
655
+ /*jshint validthis:true*/
656
+ return this;
657
+ }
658
+
659
+ /**
660
+ * Finds the specified regexp and adds them to the matches collection.
661
+ *
662
+ * @param {RegExp} regex Global regexp to search the current node by.
663
+ * @param {Object} [data] Optional custom data element for the match.
664
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
665
+ */
666
+ function find(regex, data) {
667
+ if (text && regex.global) {
668
+ while ((m = regex.exec(text))) {
669
+ matches.push(createMatch(m, data));
670
+ }
671
+ }
672
+
673
+ return this;
674
+ }
675
+
676
+ /**
677
+ * Unwraps the specified match object or all matches if unspecified.
678
+ *
679
+ * @param {Object} [match] Optional match object.
680
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
681
+ */
682
+ function unwrap(match) {
683
+ var i, elements = getWrappersByIndex(match ? indexOf(match) : null);
684
+
685
+ i = elements.length;
686
+ while (i--) {
687
+ unwrapElement(elements[i]);
688
+ }
689
+
690
+ return this;
691
+ }
692
+
693
+ /**
694
+ * Returns a match object by the specified DOM element.
695
+ *
696
+ * @param {DOMElement} element Element to return match object for.
697
+ * @return {Object} Match object for the specified element.
698
+ */
699
+ function matchFromElement(element) {
700
+ return matches[element.getAttribute('data-mce-index')];
701
+ }
702
+
703
+ /**
704
+ * Returns a DOM element from the specified match element. This will be the first element if it's split
705
+ * on multiple nodes.
706
+ *
707
+ * @param {Object} match Match element to get first element of.
708
+ * @return {DOMElement} DOM element for the specified match object.
709
+ */
710
+ function elementFromMatch(match) {
711
+ return getWrappersByIndex(indexOf(match))[0];
712
+ }
713
+
714
+ /**
715
+ * Adds match the specified range for example a grammar line.
716
+ *
717
+ * @param {Number} start Start offset.
718
+ * @param {Number} length Length of the text.
719
+ * @param {Object} data Custom data object for match.
720
+ * @return {DomTextMatcher} Current DomTextMatcher instance.
721
+ */
722
+ function add(start, length, data) {
723
+ matches.push({
724
+ start: start,
725
+ end: start + length,
726
+ text: text.substr(start, length),
727
+ data: data
728
+ });
729
+
730
+ return this;
731
+ }
732
+
733
+ /**
734
+ * Returns a DOM range for the specified match.
735
+ *
736
+ * @param {Object} match Match object to get range for.
737
+ * @return {DOMRange} DOM Range for the specified match.
738
+ */
739
+ function rangeFromMatch(match) {
740
+ var wrappers = getWrappersByIndex(indexOf(match));
741
+
742
+ var rng = editor.dom.createRng();
743
+ rng.setStartBefore(wrappers[0]);
744
+ rng.setEndAfter(wrappers[wrappers.length - 1]);
745
+
746
+ return rng;
747
+ }
748
+
749
+ /**
750
+ * Replaces the specified match with the specified text.
751
+ *
752
+ * @param {Object} match Match object to replace.
753
+ * @param {String} text Text to replace the match with.
754
+ * @return {DOMRange} DOM range produced after the replace.
755
+ */
756
+ function replace(match, text) {
757
+ var rng = rangeFromMatch(match);
758
+
759
+ rng.deleteContents();
760
+
761
+ if (text.length > 0) {
762
+ rng.insertNode(editor.dom.doc.createTextNode(text));
763
+ }
764
+
765
+ return rng;
766
+ }
767
+
768
+ /**
769
+ * Resets the DomTextMatcher instance. This will remove any wrapped nodes and remove any matches.
770
+ *
771
+ * @return {[type]} [description]
772
+ */
773
+ function reset() {
774
+ matches.splice(0, matches.length);
775
+ unwrap();
776
+
777
+ return this;
778
+ }
779
+
780
+ text = getText(node);
781
+
782
+ return {
783
+ text: text,
784
+ matches: matches,
785
+ each: each,
786
+ filter: filter,
787
+ reset: reset,
788
+ matchFromElement: matchFromElement,
789
+ elementFromMatch: elementFromMatch,
790
+ find: find,
791
+ add: add,
792
+ wrap: wrap,
793
+ unwrap: unwrap,
794
+ replace: replace,
795
+ rangeFromMatch: rangeFromMatch,
796
+ indexOf: indexOf
797
+ };
798
+ };
799
+ }
800
+ );
801
+ /**
802
+ * Actions.js
803
+ *
804
+ * Released under LGPL License.
805
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
806
+ *
807
+ * License: http://www.tinymce.com/license
808
+ * Contributing: http://www.tinymce.com/contributing
809
+ */
810
+
811
+ define(
812
+ 'tinymce.plugins.spellchecker.core.Actions',
813
+ [
814
+ 'tinymce.core.util.Tools',
815
+ 'tinymce.core.util.URI',
816
+ 'tinymce.core.util.XHR',
817
+ 'tinymce.plugins.spellchecker.api.Events',
818
+ 'tinymce.plugins.spellchecker.api.Settings',
819
+ 'tinymce.plugins.spellchecker.core.DomTextMatcher'
820
+ ],
821
+ function (Tools, URI, XHR, Events, Settings, DomTextMatcher) {
822
+ var getTextMatcher = function (editor, textMatcherState) {
823
+ if (!textMatcherState.get()) {
824
+ var textMatcher = new DomTextMatcher(editor.getBody(), editor);
825
+ textMatcherState.set(textMatcher);
826
+ }
827
+
828
+ return textMatcherState.get();
829
+ };
830
+
831
+ var isEmpty = function (obj) {
832
+ for (var name in obj) {
833
+ return false;
834
+ }
835
+
836
+ return true;
837
+ };
838
+
839
+ var defaultSpellcheckCallback = function (editor, pluginUrl, currentLanguageState) {
840
+ return function (method, text, doneCallback, errorCallback) {
841
+ var data = { method: method, lang: currentLanguageState.get() }, postData = '';
842
+
843
+ data[method === "addToDictionary" ? "word" : "text"] = text;
844
+
845
+ Tools.each(data, function (value, key) {
846
+ if (postData) {
847
+ postData += '&';
848
+ }
849
+
850
+ postData += key + '=' + encodeURIComponent(value);
851
+ });
852
+
853
+ XHR.send({
854
+ url: new URI(pluginUrl).toAbsolute(Settings.getRpcUrl(editor)),
855
+ type: "post",
856
+ content_type: 'application/x-www-form-urlencoded',
857
+ data: postData,
858
+ success: function (result) {
859
+ result = JSON.parse(result);
860
+
861
+ if (!result) {
862
+ var message = editor.translate("Server response wasn't proper JSON.");
863
+ errorCallback(message);
864
+ } else if (result.error) {
865
+ errorCallback(result.error);
866
+ } else {
867
+ doneCallback(result);
868
+ }
869
+ },
870
+ error: function () {
871
+ var message = editor.translate("The spelling service was not found: (") +
872
+ Settings.getRpcUrl(editor) +
873
+ editor.translate(")");
874
+ errorCallback(message);
875
+ }
876
+ });
877
+ };
878
+ };
879
+
880
+ var sendRpcCall = function (editor, pluginUrl, currentLanguageState, name, data, successCallback, errorCallback) {
881
+ var userSpellcheckCallback = Settings.getSpellcheckerCallback(editor);
882
+ var spellCheckCallback = userSpellcheckCallback ? userSpellcheckCallback : defaultSpellcheckCallback(editor, pluginUrl, currentLanguageState);
883
+ spellCheckCallback.call(editor.plugins.spellchecker, name, data, successCallback, errorCallback);
884
+ };
885
+
886
+ var spellcheck = function (editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState) {
887
+ if (finish(editor, startedState, textMatcherState)) {
888
+ return;
889
+ }
890
+
891
+ var errorCallback = function (message) {
892
+ editor.notificationManager.open({ text: message, type: 'error' });
893
+ editor.setProgressState(false);
894
+ finish(editor, startedState, textMatcherState);
895
+ };
896
+
897
+ var successCallback = function (data) {
898
+ markErrors(editor, startedState, textMatcherState, lastSuggestionsState, data);
899
+ };
900
+
901
+ editor.setProgressState(true);
902
+ sendRpcCall(editor, pluginUrl, currentLanguageState, "spellcheck", getTextMatcher(editor, textMatcherState).text, successCallback, errorCallback);
903
+ editor.focus();
904
+ };
905
+
906
+ var checkIfFinished = function (editor, startedState, textMatcherState) {
907
+ if (!editor.dom.select('span.mce-spellchecker-word').length) {
908
+ finish(editor, startedState, textMatcherState);
909
+ }
910
+ };
911
+
912
+ var addToDictionary = function (editor, pluginUrl, startedState, textMatcherState, word, spans) {
913
+ editor.setProgressState(true);
914
+
915
+ sendRpcCall(editor, pluginUrl, 'addToDictionary', word, function () {
916
+ editor.setProgressState(false);
917
+ editor.dom.remove(spans, true);
918
+ checkIfFinished(editor, startedState, textMatcherState);
919
+ }, function (message) {
920
+ editor.notificationManager.open({ text: message, type: 'error' });
921
+ editor.setProgressState(false);
922
+ });
923
+ };
924
+
925
+ var ignoreWord = function (editor, startedState, textMatcherState, word, spans, all) {
926
+ editor.selection.collapse();
927
+
928
+ if (all) {
929
+ Tools.each(editor.dom.select('span.mce-spellchecker-word'), function (span) {
930
+ if (span.getAttribute('data-mce-word') === word) {
931
+ editor.dom.remove(span, true);
932
+ }
933
+ });
934
+ } else {
935
+ editor.dom.remove(spans, true);
936
+ }
937
+
938
+ checkIfFinished(editor, startedState, textMatcherState);
939
+ };
940
+
941
+ var finish = function (editor, startedState, textMatcherState) {
942
+ getTextMatcher(editor, textMatcherState).reset();
943
+ textMatcherState.set(null);
944
+
945
+ if (startedState.get()) {
946
+ startedState.set(false);
947
+ Events.fireSpellcheckEnd(editor);
948
+ return true;
949
+ }
950
+ };
951
+
952
+ var getElmIndex = function (elm) {
953
+ var value = elm.getAttribute('data-mce-index');
954
+
955
+ if (typeof value === "number") {
956
+ return "" + value;
957
+ }
958
+
959
+ return value;
960
+ };
961
+
962
+ var findSpansByIndex = function (editor, index) {
963
+ var nodes, spans = [];
964
+
965
+ nodes = Tools.toArray(editor.getBody().getElementsByTagName('span'));
966
+ if (nodes.length) {
967
+ for (var i = 0; i < nodes.length; i++) {
968
+ var nodeIndex = getElmIndex(nodes[i]);
969
+
970
+ if (nodeIndex === null || !nodeIndex.length) {
971
+ continue;
972
+ }
973
+
974
+ if (nodeIndex === index.toString()) {
975
+ spans.push(nodes[i]);
976
+ }
977
+ }
978
+ }
979
+
980
+ return spans;
981
+ };
982
+
983
+ var markErrors = function (editor, startedState, textMatcherState, lastSuggestionsState, data) {
984
+ var suggestions, hasDictionarySupport;
985
+
986
+ if (data.words) {
987
+ hasDictionarySupport = !!data.dictionary;
988
+ suggestions = data.words;
989
+ } else {
990
+ // Fallback to old format
991
+ suggestions = data;
992
+ }
993
+
994
+ editor.setProgressState(false);
995
+
996
+ if (isEmpty(suggestions)) {
997
+ var message = editor.translate('No misspellings found.');
998
+ editor.notificationManager.open({ text: message, type: 'info' });
999
+ startedState.set(false);
1000
+ return;
1001
+ }
1002
+
1003
+ lastSuggestionsState.set({
1004
+ suggestions: suggestions,
1005
+ hasDictionarySupport: hasDictionarySupport
1006
+ });
1007
+
1008
+ getTextMatcher(editor, textMatcherState).find(Settings.getSpellcheckerWordcharPattern(editor)).filter(function (match) {
1009
+ return !!suggestions[match.text];
1010
+ }).wrap(function (match) {
1011
+ return editor.dom.create('span', {
1012
+ "class": 'mce-spellchecker-word',
1013
+ "data-mce-bogus": 1,
1014
+ "data-mce-word": match.text
1015
+ });
1016
+ });
1017
+
1018
+ startedState.set(true);
1019
+ Events.fireSpellcheckStart(editor);
1020
+ };
1021
+
1022
+ return {
1023
+ spellcheck: spellcheck,
1024
+ checkIfFinished: checkIfFinished,
1025
+ addToDictionary: addToDictionary,
1026
+ ignoreWord: ignoreWord,
1027
+ findSpansByIndex: findSpansByIndex,
1028
+ getElmIndex: getElmIndex,
1029
+ markErrors: markErrors
1030
+ };
1031
+ }
1032
+ );
1033
+ /**
1034
+ * Api.js
1035
+ *
1036
+ * Released under LGPL License.
1037
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1038
+ *
1039
+ * License: http://www.tinymce.com/license
1040
+ * Contributing: http://www.tinymce.com/contributing
1041
+ */
1042
+
1043
+ define(
1044
+ 'tinymce.plugins.spellchecker.api.Api',
1045
+ [
1046
+ 'tinymce.plugins.spellchecker.api.Settings',
1047
+ 'tinymce.plugins.spellchecker.core.Actions'
1048
+ ],
1049
+ function (Settings, Actions) {
1050
+ var get = function (editor, startedState, lastSuggestionsState, textMatcherState, url) {
1051
+ var getLanguage = function () {
1052
+ return Settings.getLanguage(editor);
1053
+ };
1054
+
1055
+ var getWordCharPattern = function () {
1056
+ return Settings.getSpellcheckerWordcharPattern(editor);
1057
+ };
1058
+
1059
+ var markErrors = function (data) {
1060
+ Actions.markErrors(editor, startedState, textMatcherState, lastSuggestionsState, data);
1061
+ };
1062
+
1063
+ var getTextMatcher = function () {
1064
+ return textMatcherState.get();
1065
+ };
1066
+
1067
+ return {
1068
+ getTextMatcher: getTextMatcher,
1069
+ getWordCharPattern: getWordCharPattern,
1070
+ markErrors: markErrors,
1071
+ getLanguage: getLanguage
1072
+ };
1073
+ };
1074
+
1075
+ return {
1076
+ get: get
1077
+ };
1078
+ }
1079
+ );
1080
+ /**
1081
+ * Commands.js
1082
+ *
1083
+ * Released under LGPL License.
1084
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1085
+ *
1086
+ * License: http://www.tinymce.com/license
1087
+ * Contributing: http://www.tinymce.com/contributing
1088
+ */
1089
+
1090
+ define(
1091
+ 'tinymce.plugins.spellchecker.api.Commands',
1092
+ [
1093
+ 'tinymce.plugins.spellchecker.core.Actions'
1094
+ ],
1095
+ function (Actions) {
1096
+ var register = function (editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState) {
1097
+ editor.addCommand('mceSpellCheck', function () {
1098
+ Actions.spellcheck(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState);
1099
+ });
1100
+ };
1101
+
1102
+ return {
1103
+ register: register
1104
+ };
1105
+ }
1106
+ );
1107
+ /**
1108
+ * Buttons.js
1109
+ *
1110
+ * Released under LGPL License.
1111
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1112
+ *
1113
+ * License: http://www.tinymce.com/license
1114
+ * Contributing: http://www.tinymce.com/contributing
1115
+ */
1116
+
1117
+ define(
1118
+ 'tinymce.plugins.spellchecker.ui.Buttons',
1119
+ [
1120
+ 'tinymce.core.util.Tools',
1121
+ 'tinymce.plugins.spellchecker.api.Settings',
1122
+ 'tinymce.plugins.spellchecker.core.Actions'
1123
+ ],
1124
+ function (Tools, Settings, Actions) {
1125
+ var buildMenuItems = function (listName, languageValues) {
1126
+ var items = [];
1127
+
1128
+ Tools.each(languageValues, function (languageValue) {
1129
+ items.push({
1130
+ selectable: true,
1131
+ text: languageValue.name,
1132
+ data: languageValue.value
1133
+ });
1134
+ });
1135
+
1136
+ return items;
1137
+ };
1138
+
1139
+ var updateSelection = function (editor) {
1140
+ return function (e) {
1141
+ var selectedLanguage = Settings.getLanguage(editor);
1142
+
1143
+ e.control.items().each(function (ctrl) {
1144
+ ctrl.active(ctrl.settings.data === selectedLanguage);
1145
+ });
1146
+ };
1147
+ };
1148
+
1149
+ var getItems = function (editor) {
1150
+ return Tools.map(Settings.getLanguages(editor).split(','), function (langPair) {
1151
+ langPair = langPair.split('=');
1152
+
1153
+ return {
1154
+ name: langPair[0],
1155
+ value: langPair[1]
1156
+ };
1157
+ });
1158
+ };
1159
+
1160
+ var register = function (editor, pluginUrl, startedState, textMatcherState, currentLanguageState, lastSuggestionsState) {
1161
+ var languageMenuItems = buildMenuItems('Language', getItems(editor));
1162
+ var startSpellchecking = function () {
1163
+ Actions.spellcheck(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState);
1164
+ };
1165
+
1166
+ var buttonArgs = {
1167
+ tooltip: 'Spellcheck',
1168
+ onclick: startSpellchecking,
1169
+ onPostRender: function (e) {
1170
+ var ctrl = e.control;
1171
+
1172
+ editor.on('SpellcheckStart SpellcheckEnd', function () {
1173
+ ctrl.active(startedState.get());
1174
+ });
1175
+ }
1176
+ };
1177
+
1178
+ if (languageMenuItems.length > 1) {
1179
+ buttonArgs.type = 'splitbutton';
1180
+ buttonArgs.menu = languageMenuItems;
1181
+ buttonArgs.onshow = updateSelection(editor);
1182
+ buttonArgs.onselect = function (e) {
1183
+ currentLanguageState.set(e.control.settings.data);
1184
+ };
1185
+ }
1186
+
1187
+ editor.addButton('spellchecker', buttonArgs);
1188
+
1189
+ editor.addMenuItem('spellchecker', {
1190
+ text: 'Spellcheck',
1191
+ context: 'tools',
1192
+ onclick: startSpellchecking,
1193
+ selectable: true,
1194
+ onPostRender: function () {
1195
+ var self = this;
1196
+
1197
+ self.active(startedState.get());
1198
+
1199
+ editor.on('SpellcheckStart SpellcheckEnd', function () {
1200
+ self.active(startedState.get());
1201
+ });
1202
+ }
1203
+ });
1204
+ };
1205
+
1206
+ return {
1207
+ register: register
1208
+ };
1209
+ }
1210
+ );
1211
+ defineGlobal("global!document", document);
1212
+ /**
1213
+ * ResolveGlobal.js
1214
+ *
1215
+ * Released under LGPL License.
1216
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1217
+ *
1218
+ * License: http://www.tinymce.com/license
1219
+ * Contributing: http://www.tinymce.com/contributing
1220
+ */
1221
+
1222
+ define(
1223
+ 'tinymce.core.dom.DOMUtils',
1224
+ [
1225
+ 'global!tinymce.util.Tools.resolve'
1226
+ ],
1227
+ function (resolve) {
1228
+ return resolve('tinymce.dom.DOMUtils');
1229
+ }
1230
+ );
1231
+
1232
+ /**
1233
+ * ResolveGlobal.js
1234
+ *
1235
+ * Released under LGPL License.
1236
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1237
+ *
1238
+ * License: http://www.tinymce.com/license
1239
+ * Contributing: http://www.tinymce.com/contributing
1240
+ */
1241
+
1242
+ define(
1243
+ 'tinymce.core.ui.Factory',
1244
+ [
1245
+ 'global!tinymce.util.Tools.resolve'
1246
+ ],
1247
+ function (resolve) {
1248
+ return resolve('tinymce.ui.Factory');
1249
+ }
1250
+ );
1251
+
1252
+ /**
1253
+ * SuggestionsMenu.js
1254
+ *
1255
+ * Released under LGPL License.
1256
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1257
+ *
1258
+ * License: http://www.tinymce.com/license
1259
+ * Contributing: http://www.tinymce.com/contributing
1260
+ */
1261
+
1262
+ define(
1263
+ 'tinymce.plugins.spellchecker.ui.SuggestionsMenu',
1264
+ [
1265
+ 'global!document',
1266
+ 'tinymce.core.dom.DOMUtils',
1267
+ 'tinymce.core.ui.Factory',
1268
+ 'tinymce.core.util.Tools',
1269
+ 'tinymce.plugins.spellchecker.api.Settings',
1270
+ 'tinymce.plugins.spellchecker.core.Actions'
1271
+ ],
1272
+ function (document, DOMUtils, Factory, Tools, Settings, Actions) {
1273
+ var suggestionsMenu;
1274
+
1275
+ var showSuggestions = function (editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, word, spans) {
1276
+ var items = [], suggestions = lastSuggestionsState.get().suggestions[word];
1277
+
1278
+ Tools.each(suggestions, function (suggestion) {
1279
+ items.push({
1280
+ text: suggestion,
1281
+ onclick: function () {
1282
+ editor.insertContent(editor.dom.encode(suggestion));
1283
+ editor.dom.remove(spans);
1284
+ Actions.checkIfFinished(editor, startedState, textMatcherState);
1285
+ }
1286
+ });
1287
+ });
1288
+
1289
+ items.push({ text: '-' });
1290
+
1291
+ var hasDictionarySupport = lastSuggestionsState.get().hasDictionarySupport;
1292
+ if (hasDictionarySupport) {
1293
+ items.push({
1294
+ text: 'Add to Dictionary', onclick: function () {
1295
+ Actions.addToDictionary(editor, pluginUrl, startedState, textMatcherState, word, spans);
1296
+ }
1297
+ });
1298
+ }
1299
+
1300
+ items.push.apply(items, [
1301
+ {
1302
+ text: 'Ignore', onclick: function () {
1303
+ Actions.ignoreWord(editor, startedState, textMatcherState, word, spans);
1304
+ }
1305
+ },
1306
+
1307
+ {
1308
+ text: 'Ignore all', onclick: function () {
1309
+ Actions.ignoreWord(editor, startedState, textMatcherState, word, spans, true);
1310
+ }
1311
+ }
1312
+ ]);
1313
+
1314
+ // Render menu
1315
+ suggestionsMenu = Factory.create('menu', {
1316
+ items: items,
1317
+ context: 'contextmenu',
1318
+ onautohide: function (e) {
1319
+ if (e.target.className.indexOf('spellchecker') !== -1) {
1320
+ e.preventDefault();
1321
+ }
1322
+ },
1323
+ onhide: function () {
1324
+ suggestionsMenu.remove();
1325
+ suggestionsMenu = null;
1326
+ }
1327
+ });
1328
+
1329
+ suggestionsMenu.renderTo(document.body);
1330
+
1331
+ // Position menu
1332
+ var pos = DOMUtils.DOM.getPos(editor.getContentAreaContainer());
1333
+ var targetPos = editor.dom.getPos(spans[0]);
1334
+ var root = editor.dom.getRoot();
1335
+
1336
+ // Adjust targetPos for scrolling in the editor
1337
+ if (root.nodeName === 'BODY') {
1338
+ targetPos.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
1339
+ targetPos.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
1340
+ } else {
1341
+ targetPos.x -= root.scrollLeft;
1342
+ targetPos.y -= root.scrollTop;
1343
+ }
1344
+
1345
+ pos.x += targetPos.x;
1346
+ pos.y += targetPos.y;
1347
+
1348
+ suggestionsMenu.moveTo(pos.x, pos.y + spans[0].offsetHeight);
1349
+ };
1350
+
1351
+ var setup = function (editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState) {
1352
+ editor.on('click', function (e) {
1353
+ var target = e.target;
1354
+
1355
+ if (target.className === "mce-spellchecker-word") {
1356
+ e.preventDefault();
1357
+
1358
+ var spans = Actions.findSpansByIndex(editor, Actions.getElmIndex(target));
1359
+
1360
+ if (spans.length > 0) {
1361
+ var rng = editor.dom.createRng();
1362
+ rng.setStartBefore(spans[0]);
1363
+ rng.setEndAfter(spans[spans.length - 1]);
1364
+ editor.selection.setRng(rng);
1365
+ showSuggestions(editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState, target.getAttribute('data-mce-word'), spans);
1366
+ }
1367
+ }
1368
+ });
1369
+ };
1370
+
1371
+ return {
1372
+ setup: setup
1373
+ };
1374
+ }
1375
+ );
1376
+
1377
+ /**
1378
+ * Plugin.js
1379
+ *
1380
+ * Released under LGPL License.
1381
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
1382
+ *
1383
+ * License: http://www.tinymce.com/license
1384
+ * Contributing: http://www.tinymce.com/contributing
1385
+ */
1386
+
1387
+ define(
1388
+ 'tinymce.plugins.spellchecker.Plugin',
1389
+ [
1390
+ 'ephox.katamari.api.Cell',
1391
+ 'tinymce.core.PluginManager',
1392
+ 'tinymce.plugins.spellchecker.alien.DetectProPlugin',
1393
+ 'tinymce.plugins.spellchecker.api.Api',
1394
+ 'tinymce.plugins.spellchecker.api.Commands',
1395
+ 'tinymce.plugins.spellchecker.api.Settings',
1396
+ 'tinymce.plugins.spellchecker.ui.Buttons',
1397
+ 'tinymce.plugins.spellchecker.ui.SuggestionsMenu'
1398
+ ],
1399
+ function (Cell, PluginManager, DetectProPlugin, Api, Commands, Settings, Buttons, SuggestionsMenu) {
1400
+ PluginManager.add('spellchecker', function (editor, pluginUrl) {
1401
+ if (DetectProPlugin.hasProPlugin(editor) === false) {
1402
+ var startedState = Cell(false);
1403
+ var currentLanguageState = Cell(Settings.getLanguage(editor));
1404
+ var textMatcherState = Cell(null);
1405
+ var lastSuggestionsState = Cell({});
1406
+
1407
+ Buttons.register(editor, pluginUrl, startedState, textMatcherState, currentLanguageState, lastSuggestionsState);
1408
+ SuggestionsMenu.setup(editor, pluginUrl, lastSuggestionsState, startedState, textMatcherState);
1409
+ Commands.register(editor, pluginUrl, startedState, textMatcherState, lastSuggestionsState, currentLanguageState);
1410
+
1411
+ return Api.get(editor, startedState, lastSuggestionsState, textMatcherState, pluginUrl);
1412
+ }
1413
+ });
1414
+
1415
+ return function () { };
1416
+ }
1417
+ );
1418
+ dem('tinymce.plugins.spellchecker.Plugin')();
1419
+ })();