mirador_rails 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/app/controllers/mirador_rails/locales_controller.rb +10 -0
  4. data/config/routes.rb +7 -0
  5. data/lib/mirador_rails/exceptions.rb +6 -0
  6. data/lib/mirador_rails/locale.rb +24 -0
  7. data/lib/mirador_rails/version.rb +1 -1
  8. data/lib/mirador_rails.rb +9 -2
  9. data/mirador_rails.gemspec +3 -0
  10. data/tasks/mirador_rails.rake +44 -10
  11. data/vendor/assets/images/border_type_4.png +0 -0
  12. data/vendor/assets/images/border_type_5.png +0 -0
  13. data/vendor/assets/javascripts/mirador/mirador.js.erb +20105 -0
  14. data/vendor/assets/javascripts/mirador.js +4 -1
  15. data/vendor/assets/locales/de/translation.json +3 -0
  16. data/vendor/assets/locales/en/translation.json +11 -7
  17. data/vendor/assets/locales/ko/translation.json +18 -9
  18. data/vendor/assets/stylesheets/enhancements.scss +36 -0
  19. data/vendor/assets/stylesheets/mirador-combined.css +1488 -1642
  20. data/vendor/assets/stylesheets/mirador.css +1 -0
  21. metadata +52 -174
  22. data/vendor/assets/javascripts/mirador.min.js +0 -89
  23. data/vendor/assets/javascripts/mirador.min.js.map +0 -1
  24. data/vendor/assets/plugins/plugins/advlist/plugin.js +0 -97
  25. data/vendor/assets/plugins/plugins/advlist/plugin.min.js +0 -1
  26. data/vendor/assets/plugins/plugins/anchor/plugin.js +0 -45
  27. data/vendor/assets/plugins/plugins/anchor/plugin.min.js +0 -1
  28. data/vendor/assets/plugins/plugins/autolink/plugin.js +0 -194
  29. data/vendor/assets/plugins/plugins/autolink/plugin.min.js +0 -1
  30. data/vendor/assets/plugins/plugins/autoresize/plugin.js +0 -152
  31. data/vendor/assets/plugins/plugins/autoresize/plugin.min.js +0 -1
  32. data/vendor/assets/plugins/plugins/autosave/plugin.js +0 -165
  33. data/vendor/assets/plugins/plugins/autosave/plugin.min.js +0 -1
  34. data/vendor/assets/plugins/plugins/bbcode/plugin.js +0 -123
  35. data/vendor/assets/plugins/plugins/bbcode/plugin.min.js +0 -1
  36. data/vendor/assets/plugins/plugins/charmap/plugin.js +0 -370
  37. data/vendor/assets/plugins/plugins/charmap/plugin.min.js +0 -1
  38. data/vendor/assets/plugins/plugins/code/plugin.js +0 -60
  39. data/vendor/assets/plugins/plugins/code/plugin.min.js +0 -1
  40. data/vendor/assets/plugins/plugins/colorpicker/plugin.js +0 -112
  41. data/vendor/assets/plugins/plugins/colorpicker/plugin.min.js +0 -1
  42. data/vendor/assets/plugins/plugins/compat3x/css/dialog.css +0 -118
  43. data/vendor/assets/plugins/plugins/compat3x/img/buttons.png +0 -0
  44. data/vendor/assets/plugins/plugins/compat3x/img/icons.gif +0 -0
  45. data/vendor/assets/plugins/plugins/compat3x/img/items.gif +0 -0
  46. data/vendor/assets/plugins/plugins/compat3x/img/menu_arrow.gif +0 -0
  47. data/vendor/assets/plugins/plugins/compat3x/img/menu_check.gif +0 -0
  48. data/vendor/assets/plugins/plugins/compat3x/img/progress.gif +0 -0
  49. data/vendor/assets/plugins/plugins/compat3x/img/tabs.gif +0 -0
  50. data/vendor/assets/plugins/plugins/compat3x/plugin.js +0 -297
  51. data/vendor/assets/plugins/plugins/compat3x/plugin.min.js +0 -1
  52. data/vendor/assets/plugins/plugins/compat3x/tiny_mce_popup.js +0 -542
  53. data/vendor/assets/plugins/plugins/compat3x/utils/editable_selects.js +0 -70
  54. data/vendor/assets/plugins/plugins/compat3x/utils/form_utils.js +0 -210
  55. data/vendor/assets/plugins/plugins/compat3x/utils/mctabs.js +0 -164
  56. data/vendor/assets/plugins/plugins/compat3x/utils/validate.js +0 -252
  57. data/vendor/assets/plugins/plugins/contextmenu/plugin.js +0 -87
  58. data/vendor/assets/plugins/plugins/contextmenu/plugin.min.js +0 -1
  59. data/vendor/assets/plugins/plugins/directionality/plugin.js +0 -64
  60. data/vendor/assets/plugins/plugins/directionality/plugin.min.js +0 -1
  61. data/vendor/assets/plugins/plugins/emoticons/img/smiley-cool.gif +0 -0
  62. data/vendor/assets/plugins/plugins/emoticons/img/smiley-cry.gif +0 -0
  63. data/vendor/assets/plugins/plugins/emoticons/img/smiley-embarassed.gif +0 -0
  64. data/vendor/assets/plugins/plugins/emoticons/img/smiley-foot-in-mouth.gif +0 -0
  65. data/vendor/assets/plugins/plugins/emoticons/img/smiley-frown.gif +0 -0
  66. data/vendor/assets/plugins/plugins/emoticons/img/smiley-innocent.gif +0 -0
  67. data/vendor/assets/plugins/plugins/emoticons/img/smiley-kiss.gif +0 -0
  68. data/vendor/assets/plugins/plugins/emoticons/img/smiley-laughing.gif +0 -0
  69. data/vendor/assets/plugins/plugins/emoticons/img/smiley-money-mouth.gif +0 -0
  70. data/vendor/assets/plugins/plugins/emoticons/img/smiley-sealed.gif +0 -0
  71. data/vendor/assets/plugins/plugins/emoticons/img/smiley-smile.gif +0 -0
  72. data/vendor/assets/plugins/plugins/emoticons/img/smiley-surprised.gif +0 -0
  73. data/vendor/assets/plugins/plugins/emoticons/img/smiley-tongue-out.gif +0 -0
  74. data/vendor/assets/plugins/plugins/emoticons/img/smiley-undecided.gif +0 -0
  75. data/vendor/assets/plugins/plugins/emoticons/img/smiley-wink.gif +0 -0
  76. data/vendor/assets/plugins/plugins/emoticons/img/smiley-yell.gif +0 -0
  77. data/vendor/assets/plugins/plugins/emoticons/plugin.js +0 -65
  78. data/vendor/assets/plugins/plugins/emoticons/plugin.min.js +0 -1
  79. data/vendor/assets/plugins/plugins/example/dialog.html +0 -8
  80. data/vendor/assets/plugins/plugins/example/plugin.js +0 -68
  81. data/vendor/assets/plugins/plugins/example/plugin.min.js +0 -1
  82. data/vendor/assets/plugins/plugins/example_dependency/plugin.js +0 -22
  83. data/vendor/assets/plugins/plugins/example_dependency/plugin.min.js +0 -1
  84. data/vendor/assets/plugins/plugins/fullpage/plugin.js +0 -490
  85. data/vendor/assets/plugins/plugins/fullpage/plugin.min.js +0 -1
  86. data/vendor/assets/plugins/plugins/fullscreen/plugin.js +0 -136
  87. data/vendor/assets/plugins/plugins/fullscreen/plugin.min.js +0 -1
  88. data/vendor/assets/plugins/plugins/hr/plugin.js +0 -30
  89. data/vendor/assets/plugins/plugins/hr/plugin.min.js +0 -1
  90. data/vendor/assets/plugins/plugins/image/plugin.js +0 -439
  91. data/vendor/assets/plugins/plugins/image/plugin.min.js +0 -1
  92. data/vendor/assets/plugins/plugins/importcss/plugin.js +0 -195
  93. data/vendor/assets/plugins/plugins/importcss/plugin.min.js +0 -1
  94. data/vendor/assets/plugins/plugins/insertdatetime/plugin.js +0 -121
  95. data/vendor/assets/plugins/plugins/insertdatetime/plugin.min.js +0 -1
  96. data/vendor/assets/plugins/plugins/layer/plugin.js +0 -225
  97. data/vendor/assets/plugins/plugins/layer/plugin.min.js +0 -1
  98. data/vendor/assets/plugins/plugins/legacyoutput/plugin.js +0 -211
  99. data/vendor/assets/plugins/plugins/legacyoutput/plugin.min.js +0 -1
  100. data/vendor/assets/plugins/plugins/link/plugin.js +0 -400
  101. data/vendor/assets/plugins/plugins/link/plugin.min.js +0 -1
  102. data/vendor/assets/plugins/plugins/lists/plugin.js +0 -791
  103. data/vendor/assets/plugins/plugins/lists/plugin.min.js +0 -1
  104. data/vendor/assets/plugins/plugins/media/moxieplayer.swf +0 -0
  105. data/vendor/assets/plugins/plugins/media/plugin.js +0 -774
  106. data/vendor/assets/plugins/plugins/media/plugin.min.js +0 -1
  107. data/vendor/assets/plugins/plugins/nonbreaking/plugin.js +0 -53
  108. data/vendor/assets/plugins/plugins/nonbreaking/plugin.min.js +0 -1
  109. data/vendor/assets/plugins/plugins/noneditable/plugin.js +0 -540
  110. data/vendor/assets/plugins/plugins/noneditable/plugin.min.js +0 -1
  111. data/vendor/assets/plugins/plugins/pagebreak/plugin.js +0 -88
  112. data/vendor/assets/plugins/plugins/pagebreak/plugin.min.js +0 -1
  113. data/vendor/assets/plugins/plugins/paste/classes/Clipboard.js +0 -634
  114. data/vendor/assets/plugins/plugins/paste/classes/Plugin.js +0 -110
  115. data/vendor/assets/plugins/plugins/paste/classes/Quirks.js +0 -159
  116. data/vendor/assets/plugins/plugins/paste/classes/Utils.js +0 -130
  117. data/vendor/assets/plugins/plugins/paste/classes/WordFilter.js +0 -493
  118. data/vendor/assets/plugins/plugins/paste/plugin.dev.js +0 -120
  119. data/vendor/assets/plugins/plugins/paste/plugin.js +0 -1625
  120. data/vendor/assets/plugins/plugins/paste/plugin.min.js +0 -1
  121. data/vendor/assets/plugins/plugins/preview/plugin.js +0 -88
  122. data/vendor/assets/plugins/plugins/preview/plugin.min.js +0 -1
  123. data/vendor/assets/plugins/plugins/print/plugin.js +0 -32
  124. data/vendor/assets/plugins/plugins/print/plugin.min.js +0 -1
  125. data/vendor/assets/plugins/plugins/save/plugin.js +0 -94
  126. data/vendor/assets/plugins/plugins/save/plugin.min.js +0 -1
  127. data/vendor/assets/plugins/plugins/searchreplace/plugin.js +0 -594
  128. data/vendor/assets/plugins/plugins/searchreplace/plugin.min.js +0 -1
  129. data/vendor/assets/plugins/plugins/spellchecker/classes/DomTextMatcher.js +0 -470
  130. data/vendor/assets/plugins/plugins/spellchecker/classes/Plugin.js +0 -436
  131. data/vendor/assets/plugins/plugins/spellchecker/plugin.dev.js +0 -117
  132. data/vendor/assets/plugins/plugins/spellchecker/plugin.js +0 -996
  133. data/vendor/assets/plugins/plugins/spellchecker/plugin.min.js +0 -1
  134. data/vendor/assets/plugins/plugins/tabfocus/plugin.js +0 -120
  135. data/vendor/assets/plugins/plugins/tabfocus/plugin.min.js +0 -1
  136. data/vendor/assets/plugins/plugins/table/classes/CellSelection.js +0 -176
  137. data/vendor/assets/plugins/plugins/table/classes/Dialogs.js +0 -749
  138. data/vendor/assets/plugins/plugins/table/classes/Plugin.js +0 -422
  139. data/vendor/assets/plugins/plugins/table/classes/Quirks.js +0 -372
  140. data/vendor/assets/plugins/plugins/table/classes/TableGrid.js +0 -864
  141. data/vendor/assets/plugins/plugins/table/plugin.dev.js +0 -118
  142. data/vendor/assets/plugins/plugins/table/plugin.js +0 -2680
  143. data/vendor/assets/plugins/plugins/table/plugin.min.js +0 -1
  144. data/vendor/assets/plugins/plugins/template/plugin.js +0 -262
  145. data/vendor/assets/plugins/plugins/template/plugin.min.js +0 -1
  146. data/vendor/assets/plugins/plugins/textcolor/plugin.js +0 -272
  147. data/vendor/assets/plugins/plugins/textcolor/plugin.min.js +0 -1
  148. data/vendor/assets/plugins/plugins/textpattern/plugin.js +0 -268
  149. data/vendor/assets/plugins/plugins/textpattern/plugin.min.js +0 -1
  150. data/vendor/assets/plugins/plugins/visualblocks/css/visualblocks.css +0 -135
  151. data/vendor/assets/plugins/plugins/visualblocks/img/address.gif +0 -0
  152. data/vendor/assets/plugins/plugins/visualblocks/img/article.gif +0 -0
  153. data/vendor/assets/plugins/plugins/visualblocks/img/aside.gif +0 -0
  154. data/vendor/assets/plugins/plugins/visualblocks/img/blockquote.gif +0 -0
  155. data/vendor/assets/plugins/plugins/visualblocks/img/div.gif +0 -0
  156. data/vendor/assets/plugins/plugins/visualblocks/img/dl.gif +0 -0
  157. data/vendor/assets/plugins/plugins/visualblocks/img/figure.gif +0 -0
  158. data/vendor/assets/plugins/plugins/visualblocks/img/h1.gif +0 -0
  159. data/vendor/assets/plugins/plugins/visualblocks/img/h2.gif +0 -0
  160. data/vendor/assets/plugins/plugins/visualblocks/img/h3.gif +0 -0
  161. data/vendor/assets/plugins/plugins/visualblocks/img/h4.gif +0 -0
  162. data/vendor/assets/plugins/plugins/visualblocks/img/h5.gif +0 -0
  163. data/vendor/assets/plugins/plugins/visualblocks/img/h6.gif +0 -0
  164. data/vendor/assets/plugins/plugins/visualblocks/img/hgroup.gif +0 -0
  165. data/vendor/assets/plugins/plugins/visualblocks/img/ol.gif +0 -0
  166. data/vendor/assets/plugins/plugins/visualblocks/img/p.gif +0 -0
  167. data/vendor/assets/plugins/plugins/visualblocks/img/pre.gif +0 -0
  168. data/vendor/assets/plugins/plugins/visualblocks/img/section.gif +0 -0
  169. data/vendor/assets/plugins/plugins/visualblocks/img/ul.gif +0 -0
  170. data/vendor/assets/plugins/plugins/visualblocks/plugin.js +0 -86
  171. data/vendor/assets/plugins/plugins/visualblocks/plugin.min.js +0 -1
  172. data/vendor/assets/plugins/plugins/visualchars/plugin.js +0 -88
  173. data/vendor/assets/plugins/plugins/visualchars/plugin.min.js +0 -1
  174. data/vendor/assets/plugins/plugins/wordcount/plugin.js +0 -69
  175. data/vendor/assets/plugins/plugins/wordcount/plugin.min.js +0 -1
  176. data/vendor/assets/skins/skins/lightgray/content.inline.min.css +0 -1
  177. data/vendor/assets/skins/skins/lightgray/content.min.css +0 -1
  178. data/vendor/assets/skins/skins/lightgray/fonts/tinymce-small.eot +0 -0
  179. data/vendor/assets/skins/skins/lightgray/fonts/tinymce-small.svg +0 -62
  180. data/vendor/assets/skins/skins/lightgray/fonts/tinymce-small.ttf +0 -0
  181. data/vendor/assets/skins/skins/lightgray/fonts/tinymce-small.woff +0 -0
  182. data/vendor/assets/skins/skins/lightgray/fonts/tinymce.eot +0 -0
  183. data/vendor/assets/skins/skins/lightgray/fonts/tinymce.svg +0 -63
  184. data/vendor/assets/skins/skins/lightgray/fonts/tinymce.ttf +0 -0
  185. data/vendor/assets/skins/skins/lightgray/fonts/tinymce.woff +0 -0
  186. data/vendor/assets/skins/skins/lightgray/img/anchor.gif +0 -0
  187. data/vendor/assets/skins/skins/lightgray/img/loader.gif +0 -0
  188. data/vendor/assets/skins/skins/lightgray/img/object.gif +0 -0
  189. data/vendor/assets/skins/skins/lightgray/img/trans.gif +0 -0
  190. data/vendor/assets/skins/skins/lightgray/skin.ie7.min.css +0 -1
  191. data/vendor/assets/skins/skins/lightgray/skin.min.css +0 -1
  192. data/vendor/assets/themes/themes/modern/theme.js +0 -617
  193. data/vendor/assets/themes/themes/modern/theme.min.js +0 -1
@@ -1,996 +0,0 @@
1
- /**
2
- * Compiled inline version. (Library mode)
3
- */
4
-
5
- /*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
6
- /*globals $code */
7
-
8
- (function(exports, undefined) {
9
- "use strict";
10
-
11
- var modules = {};
12
-
13
- function require(ids, callback) {
14
- var module, defs = [];
15
-
16
- for (var i = 0; i < ids.length; ++i) {
17
- module = modules[ids[i]] || resolve(ids[i]);
18
- if (!module) {
19
- throw 'module definition dependecy not found: ' + ids[i];
20
- }
21
-
22
- defs.push(module);
23
- }
24
-
25
- callback.apply(null, defs);
26
- }
27
-
28
- function define(id, dependencies, definition) {
29
- if (typeof id !== 'string') {
30
- throw 'invalid module definition, module id must be defined and be a string';
31
- }
32
-
33
- if (dependencies === undefined) {
34
- throw 'invalid module definition, dependencies must be specified';
35
- }
36
-
37
- if (definition === undefined) {
38
- throw 'invalid module definition, definition function must be specified';
39
- }
40
-
41
- require(dependencies, function() {
42
- modules[id] = definition.apply(null, arguments);
43
- });
44
- }
45
-
46
- function defined(id) {
47
- return !!modules[id];
48
- }
49
-
50
- function resolve(id) {
51
- var target = exports;
52
- var fragments = id.split(/[.\/]/);
53
-
54
- for (var fi = 0; fi < fragments.length; ++fi) {
55
- if (!target[fragments[fi]]) {
56
- return;
57
- }
58
-
59
- target = target[fragments[fi]];
60
- }
61
-
62
- return target;
63
- }
64
-
65
- function expose(ids) {
66
- for (var i = 0; i < ids.length; i++) {
67
- var target = exports;
68
- var id = ids[i];
69
- var fragments = id.split(/[.\/]/);
70
-
71
- for (var fi = 0; fi < fragments.length - 1; ++fi) {
72
- if (target[fragments[fi]] === undefined) {
73
- target[fragments[fi]] = {};
74
- }
75
-
76
- target = target[fragments[fi]];
77
- }
78
-
79
- target[fragments[fragments.length - 1]] = modules[id];
80
- }
81
- }
82
-
83
- // Included from: js/tinymce/plugins/spellchecker/classes/DomTextMatcher.js
84
-
85
- /**
86
- * DomTextMatcher.js
87
- *
88
- * Copyright, Moxiecode Systems AB
89
- * Released under LGPL License.
90
- *
91
- * License: http://www.tinymce.com/license
92
- * Contributing: http://www.tinymce.com/contributing
93
- */
94
-
95
- /*eslint no-labels:0, no-constant-condition: 0 */
96
-
97
- /**
98
- * This class logic for filtering text and matching words.
99
- *
100
- * @class tinymce.spellcheckerplugin.TextFilter
101
- * @private
102
- */
103
- define("tinymce/spellcheckerplugin/DomTextMatcher", [], function() {
104
- // Based on work developed by: James Padolsey http://james.padolsey.com
105
- // released under UNLICENSE that is compatible with LGPL
106
- // TODO: Handle contentEditable edgecase:
107
- // <p>text<span contentEditable="false">text<span contentEditable="true">text</span>text</span>text</p>
108
- return function(node, editor) {
109
- var m, matches = [], text, dom = editor.dom;
110
- var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap;
111
-
112
- blockElementsMap = editor.schema.getBlockElements(); // H1-H6, P, TD etc
113
- hiddenTextElementsMap = editor.schema.getWhiteSpaceElements(); // TEXTAREA, PRE, STYLE, SCRIPT
114
- shortEndedElementsMap = editor.schema.getShortEndedElements(); // BR, IMG, INPUT
115
-
116
- function createMatch(m, data) {
117
- if (!m[0]) {
118
- throw 'findAndReplaceDOMText cannot handle zero-length matches';
119
- }
120
-
121
- return {
122
- start: m.index,
123
- end: m.index + m[0].length,
124
- text: m[0],
125
- data: data
126
- };
127
- }
128
-
129
- function getText(node) {
130
- var txt;
131
-
132
- if (node.nodeType === 3) {
133
- return node.data;
134
- }
135
-
136
- if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) {
137
- return '';
138
- }
139
-
140
- txt = '';
141
-
142
- if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) {
143
- txt += '\n';
144
- }
145
-
146
- if ((node = node.firstChild)) {
147
- do {
148
- txt += getText(node);
149
- } while ((node = node.nextSibling));
150
- }
151
-
152
- return txt;
153
- }
154
-
155
- function stepThroughMatches(node, matches, replaceFn) {
156
- var startNode, endNode, startNodeIndex,
157
- endNodeIndex, innerNodes = [], atIndex = 0, curNode = node,
158
- matchLocation, matchIndex = 0;
159
-
160
- matches = matches.slice(0);
161
- matches.sort(function(a, b) {
162
- return a.start - b.start;
163
- });
164
-
165
- matchLocation = matches.shift();
166
-
167
- out: while (true) {
168
- if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName]) {
169
- atIndex++;
170
- }
171
-
172
- if (curNode.nodeType === 3) {
173
- if (!endNode && curNode.length + atIndex >= matchLocation.end) {
174
- // We've found the ending
175
- endNode = curNode;
176
- endNodeIndex = matchLocation.end - atIndex;
177
- } else if (startNode) {
178
- // Intersecting node
179
- innerNodes.push(curNode);
180
- }
181
-
182
- if (!startNode && curNode.length + atIndex > matchLocation.start) {
183
- // We've found the match start
184
- startNode = curNode;
185
- startNodeIndex = matchLocation.start - atIndex;
186
- }
187
-
188
- atIndex += curNode.length;
189
- }
190
-
191
- if (startNode && endNode) {
192
- curNode = replaceFn({
193
- startNode: startNode,
194
- startNodeIndex: startNodeIndex,
195
- endNode: endNode,
196
- endNodeIndex: endNodeIndex,
197
- innerNodes: innerNodes,
198
- match: matchLocation.text,
199
- matchIndex: matchIndex
200
- });
201
-
202
- // replaceFn has to return the node that replaced the endNode
203
- // and then we step back so we can continue from the end of the
204
- // match:
205
- atIndex -= (endNode.length - endNodeIndex);
206
- startNode = null;
207
- endNode = null;
208
- innerNodes = [];
209
- matchLocation = matches.shift();
210
- matchIndex++;
211
-
212
- if (!matchLocation) {
213
- break; // no more matches
214
- }
215
- } else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) {
216
- // Move down
217
- curNode = curNode.firstChild;
218
- continue;
219
- } else if (curNode.nextSibling) {
220
- // Move forward:
221
- curNode = curNode.nextSibling;
222
- continue;
223
- }
224
-
225
- // Move forward or up:
226
- while (true) {
227
- if (curNode.nextSibling) {
228
- curNode = curNode.nextSibling;
229
- break;
230
- } else if (curNode.parentNode !== node) {
231
- curNode = curNode.parentNode;
232
- } else {
233
- break out;
234
- }
235
- }
236
- }
237
- }
238
-
239
- /**
240
- * Generates the actual replaceFn which splits up text nodes
241
- * and inserts the replacement element.
242
- */
243
- function genReplacer(callback) {
244
- function makeReplacementNode(fill, matchIndex) {
245
- var match = matches[matchIndex];
246
-
247
- if (!match.stencil) {
248
- match.stencil = callback(match);
249
- }
250
-
251
- var clone = match.stencil.cloneNode(false);
252
- clone.setAttribute('data-mce-index', matchIndex);
253
-
254
- if (fill) {
255
- clone.appendChild(dom.doc.createTextNode(fill));
256
- }
257
-
258
- return clone;
259
- }
260
-
261
- return function(range) {
262
- var before, after, parentNode, startNode = range.startNode,
263
- endNode = range.endNode, matchIndex = range.matchIndex,
264
- doc = dom.doc;
265
-
266
- if (startNode === endNode) {
267
- var node = startNode;
268
-
269
- parentNode = node.parentNode;
270
- if (range.startNodeIndex > 0) {
271
- // Add "before" text node (before the match)
272
- before = doc.createTextNode(node.data.substring(0, range.startNodeIndex));
273
- parentNode.insertBefore(before, node);
274
- }
275
-
276
- // Create the replacement node:
277
- var el = makeReplacementNode(range.match, matchIndex);
278
- parentNode.insertBefore(el, node);
279
- if (range.endNodeIndex < node.length) {
280
- // Add "after" text node (after the match)
281
- after = doc.createTextNode(node.data.substring(range.endNodeIndex));
282
- parentNode.insertBefore(after, node);
283
- }
284
-
285
- node.parentNode.removeChild(node);
286
-
287
- return el;
288
- } else {
289
- // Replace startNode -> [innerNodes...] -> endNode (in that order)
290
- before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex));
291
- after = doc.createTextNode(endNode.data.substring(range.endNodeIndex));
292
- var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex);
293
- var innerEls = [];
294
-
295
- for (var i = 0, l = range.innerNodes.length; i < l; ++i) {
296
- var innerNode = range.innerNodes[i];
297
- var innerEl = makeReplacementNode(innerNode.data, matchIndex);
298
- innerNode.parentNode.replaceChild(innerEl, innerNode);
299
- innerEls.push(innerEl);
300
- }
301
-
302
- var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex);
303
-
304
- parentNode = startNode.parentNode;
305
- parentNode.insertBefore(before, startNode);
306
- parentNode.insertBefore(elA, startNode);
307
- parentNode.removeChild(startNode);
308
-
309
- parentNode = endNode.parentNode;
310
- parentNode.insertBefore(elB, endNode);
311
- parentNode.insertBefore(after, endNode);
312
- parentNode.removeChild(endNode);
313
-
314
- return elB;
315
- }
316
- };
317
- }
318
-
319
- function unwrapElement(element) {
320
- var parentNode = element.parentNode;
321
- parentNode.insertBefore(element.firstChild, element);
322
- element.parentNode.removeChild(element);
323
- }
324
-
325
- function getWrappersByIndex(index) {
326
- var elements = node.getElementsByTagName('*'), wrappers = [];
327
-
328
- index = typeof(index) == "number" ? "" + index : null;
329
-
330
- for (var i = 0; i < elements.length; i++) {
331
- var element = elements[i], dataIndex = element.getAttribute('data-mce-index');
332
-
333
- if (dataIndex !== null && dataIndex.length) {
334
- if (dataIndex === index || index === null) {
335
- wrappers.push(element);
336
- }
337
- }
338
- }
339
-
340
- return wrappers;
341
- }
342
-
343
- /**
344
- * Returns the index of a specific match object or -1 if it isn't found.
345
- *
346
- * @param {Match} match Text match object.
347
- * @return {Number} Index of match or -1 if it isn't found.
348
- */
349
- function indexOf(match) {
350
- var i = matches.length;
351
- while (i--) {
352
- if (matches[i] === match) {
353
- return i;
354
- }
355
- }
356
-
357
- return -1;
358
- }
359
-
360
- /**
361
- * Filters the matches. If the callback returns true it stays if not it gets removed.
362
- *
363
- * @param {Function} callback Callback to execute for each match.
364
- * @return {DomTextMatcher} Current DomTextMatcher instance.
365
- */
366
- function filter(callback) {
367
- var filteredMatches = [];
368
-
369
- each(function(match, i) {
370
- if (callback(match, i)) {
371
- filteredMatches.push(match);
372
- }
373
- });
374
-
375
- matches = filteredMatches;
376
-
377
- /*jshint validthis:true*/
378
- return this;
379
- }
380
-
381
- /**
382
- * Executes the specified callback for each match.
383
- *
384
- * @param {Function} callback Callback to execute for each match.
385
- * @return {DomTextMatcher} Current DomTextMatcher instance.
386
- */
387
- function each(callback) {
388
- for (var i = 0, l = matches.length; i < l; i++) {
389
- if (callback(matches[i], i) === false) {
390
- break;
391
- }
392
- }
393
-
394
- /*jshint validthis:true*/
395
- return this;
396
- }
397
-
398
- /**
399
- * Wraps the current matches with nodes created by the specified callback.
400
- * Multiple clones of these matches might occur on matches that are on multiple nodex.
401
- *
402
- * @param {Function} callback Callback to execute in order to create elements for matches.
403
- * @return {DomTextMatcher} Current DomTextMatcher instance.
404
- */
405
- function wrap(callback) {
406
- if (matches.length) {
407
- stepThroughMatches(node, matches, genReplacer(callback));
408
- }
409
-
410
- /*jshint validthis:true*/
411
- return this;
412
- }
413
-
414
- /**
415
- * Finds the specified regexp and adds them to the matches collection.
416
- *
417
- * @param {RegExp} regex Global regexp to search the current node by.
418
- * @param {Object} [data] Optional custom data element for the match.
419
- * @return {DomTextMatcher} Current DomTextMatcher instance.
420
- */
421
- function find(regex, data) {
422
- if (text && regex.global) {
423
- while ((m = regex.exec(text))) {
424
- matches.push(createMatch(m, data));
425
- }
426
- }
427
-
428
- return this;
429
- }
430
-
431
- /**
432
- * Unwraps the specified match object or all matches if unspecified.
433
- *
434
- * @param {Object} [match] Optional match object.
435
- * @return {DomTextMatcher} Current DomTextMatcher instance.
436
- */
437
- function unwrap(match) {
438
- var i, elements = getWrappersByIndex(match ? indexOf(match) : null);
439
-
440
- i = elements.length;
441
- while (i--) {
442
- unwrapElement(elements[i]);
443
- }
444
-
445
- return this;
446
- }
447
-
448
- /**
449
- * Returns a match object by the specified DOM element.
450
- *
451
- * @param {DOMElement} element Element to return match object for.
452
- * @return {Object} Match object for the specified element.
453
- */
454
- function matchFromElement(element) {
455
- return matches[element.getAttribute('data-mce-index')];
456
- }
457
-
458
- /**
459
- * Returns a DOM element from the specified match element. This will be the first element if it's split
460
- * on multiple nodes.
461
- *
462
- * @param {Object} match Match element to get first element of.
463
- * @return {DOMElement} DOM element for the specified match object.
464
- */
465
- function elementFromMatch(match) {
466
- return getWrappersByIndex(indexOf(match))[0];
467
- }
468
-
469
- /**
470
- * Adds match the specified range for example a grammar line.
471
- *
472
- * @param {Number} start Start offset.
473
- * @param {Number} length Length of the text.
474
- * @param {Object} data Custom data object for match.
475
- * @return {DomTextMatcher} Current DomTextMatcher instance.
476
- */
477
- function add(start, length, data) {
478
- matches.push({
479
- start: start,
480
- end: start + length,
481
- text: text.substr(start, length),
482
- data: data
483
- });
484
-
485
- return this;
486
- }
487
-
488
- /**
489
- * Returns a DOM range for the specified match.
490
- *
491
- * @param {Object} match Match object to get range for.
492
- * @return {DOMRange} DOM Range for the specified match.
493
- */
494
- function rangeFromMatch(match) {
495
- var wrappers = getWrappersByIndex(indexOf(match));
496
-
497
- var rng = editor.dom.createRng();
498
- rng.setStartBefore(wrappers[0]);
499
- rng.setEndAfter(wrappers[wrappers.length - 1]);
500
-
501
- return rng;
502
- }
503
-
504
- /**
505
- * Replaces the specified match with the specified text.
506
- *
507
- * @param {Object} match Match object to replace.
508
- * @param {String} text Text to replace the match with.
509
- * @return {DOMRange} DOM range produced after the replace.
510
- */
511
- function replace(match, text) {
512
- var rng = rangeFromMatch(match);
513
-
514
- rng.deleteContents();
515
-
516
- if (text.length > 0) {
517
- rng.insertNode(editor.dom.doc.createTextNode(text));
518
- }
519
-
520
- return rng;
521
- }
522
-
523
- /**
524
- * Resets the DomTextMatcher instance. This will remove any wrapped nodes and remove any matches.
525
- *
526
- * @return {[type]} [description]
527
- */
528
- function reset() {
529
- matches.splice(0, matches.length);
530
- unwrap();
531
-
532
- return this;
533
- }
534
-
535
- text = getText(node);
536
-
537
- return {
538
- text: text,
539
- matches: matches,
540
- each: each,
541
- filter: filter,
542
- reset: reset,
543
- matchFromElement: matchFromElement,
544
- elementFromMatch: elementFromMatch,
545
- find: find,
546
- add: add,
547
- wrap: wrap,
548
- unwrap: unwrap,
549
- replace: replace,
550
- rangeFromMatch: rangeFromMatch,
551
- indexOf: indexOf
552
- };
553
- };
554
- });
555
-
556
- // Included from: js/tinymce/plugins/spellchecker/classes/Plugin.js
557
-
558
- /**
559
- * Plugin.js
560
- *
561
- * Copyright, Moxiecode Systems AB
562
- * Released under LGPL License.
563
- *
564
- * License: http://www.tinymce.com/license
565
- * Contributing: http://www.tinymce.com/contributing
566
- */
567
-
568
- /*jshint camelcase:false */
569
-
570
- /**
571
- * This class contains all core logic for the spellchecker plugin.
572
- *
573
- * @class tinymce.spellcheckerplugin.Plugin
574
- * @private
575
- */
576
- define("tinymce/spellcheckerplugin/Plugin", [
577
- "tinymce/spellcheckerplugin/DomTextMatcher",
578
- "tinymce/PluginManager",
579
- "tinymce/util/Tools",
580
- "tinymce/ui/Menu",
581
- "tinymce/dom/DOMUtils",
582
- "tinymce/util/XHR",
583
- "tinymce/util/URI",
584
- "tinymce/util/JSON"
585
- ], function(DomTextMatcher, PluginManager, Tools, Menu, DOMUtils, XHR, URI, JSON) {
586
- PluginManager.add('spellchecker', function(editor, url) {
587
- var languageMenuItems, self = this, lastSuggestions, started, suggestionsMenu, settings = editor.settings;
588
- var hasDictionarySupport;
589
-
590
- function getTextMatcher() {
591
- if (!self.textMatcher) {
592
- self.textMatcher = new DomTextMatcher(editor.getBody(), editor);
593
- }
594
-
595
- return self.textMatcher;
596
- }
597
-
598
- function buildMenuItems(listName, languageValues) {
599
- var items = [];
600
-
601
- Tools.each(languageValues, function(languageValue) {
602
- items.push({
603
- selectable: true,
604
- text: languageValue.name,
605
- data: languageValue.value
606
- });
607
- });
608
-
609
- return items;
610
- }
611
-
612
- var languagesString = settings.spellchecker_languages ||
613
- 'English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,' +
614
- 'German=de,Italian=it,Polish=pl,Portuguese=pt_BR,' +
615
- 'Spanish=es,Swedish=sv';
616
-
617
- languageMenuItems = buildMenuItems('Language',
618
- Tools.map(languagesString.split(','), function(langPair) {
619
- langPair = langPair.split('=');
620
-
621
- return {
622
- name: langPair[0],
623
- value: langPair[1]
624
- };
625
- })
626
- );
627
-
628
- function isEmpty(obj) {
629
- /*jshint unused:false*/
630
- /*eslint no-unused-vars:0 */
631
- for (var name in obj) {
632
- return false;
633
- }
634
-
635
- return true;
636
- }
637
-
638
- function showSuggestions(word, spans) {
639
- var items = [], suggestions = lastSuggestions[word];
640
-
641
- Tools.each(suggestions, function(suggestion) {
642
- items.push({
643
- text: suggestion,
644
- onclick: function() {
645
- editor.insertContent(editor.dom.encode(suggestion));
646
- editor.dom.remove(spans);
647
- checkIfFinished();
648
- }
649
- });
650
- });
651
-
652
- items.push({text: '-'});
653
-
654
- if (hasDictionarySupport) {
655
- items.push({text: 'Add to Dictionary', onclick: function() {
656
- addToDictionary(word, spans);
657
- }});
658
- }
659
-
660
- items.push.apply(items, [
661
- {text: 'Ignore', onclick: function() {
662
- ignoreWord(word, spans);
663
- }},
664
-
665
- {text: 'Ignore all', onclick: function() {
666
- ignoreWord(word, spans, true);
667
- }}
668
- ]);
669
-
670
- // Render menu
671
- suggestionsMenu = new Menu({
672
- items: items,
673
- context: 'contextmenu',
674
- onautohide: function(e) {
675
- if (e.target.className.indexOf('spellchecker') != -1) {
676
- e.preventDefault();
677
- }
678
- },
679
- onhide: function() {
680
- suggestionsMenu.remove();
681
- suggestionsMenu = null;
682
- }
683
- });
684
-
685
- suggestionsMenu.renderTo(document.body);
686
-
687
- // Position menu
688
- var pos = DOMUtils.DOM.getPos(editor.getContentAreaContainer());
689
- var targetPos = editor.dom.getPos(spans[0]);
690
- var root = editor.dom.getRoot();
691
-
692
- // Adjust targetPos for scrolling in the editor
693
- if (root.nodeName == 'BODY') {
694
- targetPos.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
695
- targetPos.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
696
- } else {
697
- targetPos.x -= root.scrollLeft;
698
- targetPos.y -= root.scrollTop;
699
- }
700
-
701
- pos.x += targetPos.x;
702
- pos.y += targetPos.y;
703
-
704
- suggestionsMenu.moveTo(pos.x, pos.y + spans[0].offsetHeight);
705
- }
706
-
707
- function getWordCharPattern() {
708
- // Regexp for finding word specific characters this will split words by
709
- // spaces, quotes, copy right characters etc. It's escaped with unicode characters
710
- // to make it easier to output scripts on servers using different encodings
711
- // so if you add any characters outside the 128 byte range make sure to escape it
712
- return editor.getParam('spellchecker_wordchar_pattern') || new RegExp("[^" +
713
- "\\s!\"#$%&()*+,-./:;<=>?@[\\]^_{|}`" +
714
- "\u00a7\u00a9\u00ab\u00ae\u00b1\u00b6\u00b7\u00b8\u00bb" +
715
- "\u00bc\u00bd\u00be\u00bf\u00d7\u00f7\u00a4\u201d\u201c\u201e\u00a0\u2002\u2003\u2009" +
716
- "]+", "g");
717
- }
718
-
719
- function defaultSpellcheckCallback(method, text, doneCallback, errorCallback) {
720
- var data = {method: method}, postData = '';
721
-
722
- if (method == "spellcheck") {
723
- data.text = text;
724
- data.lang = settings.spellchecker_language;
725
- }
726
-
727
- if (method == "addToDictionary") {
728
- data.word = text;
729
- }
730
-
731
- Tools.each(data, function(value, key) {
732
- if (postData) {
733
- postData += '&';
734
- }
735
-
736
- postData += key + '=' + encodeURIComponent(value);
737
- });
738
-
739
- XHR.send({
740
- url: new URI(url).toAbsolute(settings.spellchecker_rpc_url),
741
- type: "post",
742
- content_type: 'application/x-www-form-urlencoded',
743
- data: postData,
744
- success: function(result) {
745
- result = JSON.parse(result);
746
-
747
- if (!result) {
748
- errorCallback("Sever response wasn't proper JSON.");
749
- } else if (result.error) {
750
- errorCallback(result.error);
751
- } else {
752
- doneCallback(result);
753
- }
754
- },
755
- error: function(type, xhr) {
756
- errorCallback("Spellchecker request error: " + xhr.status);
757
- }
758
- });
759
- }
760
-
761
- function sendRpcCall(name, data, successCallback, errorCallback) {
762
- var spellCheckCallback = settings.spellchecker_callback || defaultSpellcheckCallback;
763
- spellCheckCallback.call(self, name, data, successCallback, errorCallback);
764
- }
765
-
766
- function spellcheck() {
767
- if (started) {
768
- finish();
769
- return;
770
- } else {
771
- finish();
772
- }
773
-
774
- function errorCallback(message) {
775
- editor.windowManager.alert(message);
776
- editor.setProgressState(false);
777
- finish();
778
- }
779
-
780
- editor.setProgressState(true);
781
- sendRpcCall("spellcheck", getTextMatcher().text, markErrors, errorCallback);
782
- editor.focus();
783
- }
784
-
785
- function checkIfFinished() {
786
- if (!editor.dom.select('span.mce-spellchecker-word').length) {
787
- finish();
788
- }
789
- }
790
-
791
- function addToDictionary(word, spans) {
792
- editor.setProgressState(true);
793
-
794
- sendRpcCall("addToDictionary", word, function() {
795
- editor.setProgressState(false);
796
- editor.dom.remove(spans, true);
797
- checkIfFinished();
798
- }, function(message) {
799
- editor.windowManager.alert(message);
800
- editor.setProgressState(false);
801
- });
802
- }
803
-
804
- function ignoreWord(word, spans, all) {
805
- editor.selection.collapse();
806
-
807
- if (all) {
808
- Tools.each(editor.dom.select('span.mce-spellchecker-word'), function(span) {
809
- if (span.getAttribute('data-mce-word') == word) {
810
- editor.dom.remove(span, true);
811
- }
812
- });
813
- } else {
814
- editor.dom.remove(spans, true);
815
- }
816
-
817
- checkIfFinished();
818
- }
819
-
820
- function finish() {
821
- getTextMatcher().reset();
822
- self.textMatcher = null;
823
-
824
- if (started) {
825
- started = false;
826
- editor.fire('SpellcheckEnd');
827
- }
828
- }
829
-
830
- function getElmIndex(elm) {
831
- var value = elm.getAttribute('data-mce-index');
832
-
833
- if (typeof(value) == "number") {
834
- return "" + value;
835
- }
836
-
837
- return value;
838
- }
839
-
840
- function findSpansByIndex(index) {
841
- var nodes, spans = [];
842
-
843
- nodes = Tools.toArray(editor.getBody().getElementsByTagName('span'));
844
- if (nodes.length) {
845
- for (var i = 0; i < nodes.length; i++) {
846
- var nodeIndex = getElmIndex(nodes[i]);
847
-
848
- if (nodeIndex === null || !nodeIndex.length) {
849
- continue;
850
- }
851
-
852
- if (nodeIndex === index.toString()) {
853
- spans.push(nodes[i]);
854
- }
855
- }
856
- }
857
-
858
- return spans;
859
- }
860
-
861
- editor.on('click', function(e) {
862
- var target = e.target;
863
-
864
- if (target.className == "mce-spellchecker-word") {
865
- e.preventDefault();
866
-
867
- var spans = findSpansByIndex(getElmIndex(target));
868
-
869
- if (spans.length > 0) {
870
- var rng = editor.dom.createRng();
871
- rng.setStartBefore(spans[0]);
872
- rng.setEndAfter(spans[spans.length - 1]);
873
- editor.selection.setRng(rng);
874
- showSuggestions(target.getAttribute('data-mce-word'), spans);
875
- }
876
- }
877
- });
878
-
879
- editor.addMenuItem('spellchecker', {
880
- text: 'Spellcheck',
881
- context: 'tools',
882
- onclick: spellcheck,
883
- selectable: true,
884
- onPostRender: function() {
885
- var self = this;
886
-
887
- self.active(started);
888
-
889
- editor.on('SpellcheckStart SpellcheckEnd', function() {
890
- self.active(started);
891
- });
892
- }
893
- });
894
-
895
- function updateSelection(e) {
896
- var selectedLanguage = settings.spellchecker_language;
897
-
898
- e.control.items().each(function(ctrl) {
899
- ctrl.active(ctrl.settings.data === selectedLanguage);
900
- });
901
- }
902
-
903
- /**
904
- * Find the specified words and marks them. It will also show suggestions for those words.
905
- *
906
- * @example
907
- * editor.plugins.spellchecker.markErrors({
908
- * dictionary: true,
909
- * words: {
910
- * "word1": ["suggestion 1", "Suggestion 2"]
911
- * }
912
- * });
913
- * @param {Object} data Data object containing the words with suggestions.
914
- */
915
- function markErrors(data) {
916
- var suggestions;
917
-
918
- if (data.words) {
919
- hasDictionarySupport = !!data.dictionary;
920
- suggestions = data.words;
921
- } else {
922
- // Fallback to old format
923
- suggestions = data;
924
- }
925
-
926
- editor.setProgressState(false);
927
-
928
- if (isEmpty(suggestions)) {
929
- editor.windowManager.alert('No misspellings found');
930
- started = false;
931
- return;
932
- }
933
-
934
- lastSuggestions = suggestions;
935
-
936
- getTextMatcher().find(getWordCharPattern()).filter(function(match) {
937
- return !!suggestions[match.text];
938
- }).wrap(function(match) {
939
- return editor.dom.create('span', {
940
- "class": 'mce-spellchecker-word',
941
- "data-mce-bogus": 1,
942
- "data-mce-word": match.text
943
- });
944
- });
945
-
946
- started = true;
947
- editor.fire('SpellcheckStart');
948
- }
949
-
950
- var buttonArgs = {
951
- tooltip: 'Spellcheck',
952
- onclick: spellcheck,
953
- onPostRender: function() {
954
- var self = this;
955
-
956
- editor.on('SpellcheckStart SpellcheckEnd', function() {
957
- self.active(started);
958
- });
959
- }
960
- };
961
-
962
- if (languageMenuItems.length > 1) {
963
- buttonArgs.type = 'splitbutton';
964
- buttonArgs.menu = languageMenuItems;
965
- buttonArgs.onshow = updateSelection;
966
- buttonArgs.onselect = function(e) {
967
- settings.spellchecker_language = e.control.settings.data;
968
- };
969
- }
970
-
971
- editor.addButton('spellchecker', buttonArgs);
972
- editor.addCommand('mceSpellCheck', spellcheck);
973
-
974
- editor.on('remove', function() {
975
- if (suggestionsMenu) {
976
- suggestionsMenu.remove();
977
- suggestionsMenu = null;
978
- }
979
- });
980
-
981
- editor.on('change', checkIfFinished);
982
-
983
- this.getTextMatcher = getTextMatcher;
984
- this.getWordCharPattern = getWordCharPattern;
985
- this.markErrors = markErrors;
986
- this.getLanguage = function() {
987
- return settings.spellchecker_language;
988
- };
989
-
990
- // Set default spellchecker language if it's not specified
991
- settings.spellchecker_language = settings.spellchecker_language || settings.language || 'en';
992
- });
993
- });
994
-
995
- expose(["tinymce/spellcheckerplugin/DomTextMatcher"]);
996
- })(this);