tinymce-rails 4.3.13 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -2
  3. data/app/assets/source/tinymce/tinymce.js +224 -51
  4. data/lib/tinymce/rails/version.rb +2 -2
  5. data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +1 -1
  6. data/vendor/assets/javascripts/tinymce/plugins/imagetools/plugin.js +1 -1
  7. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +1 -1
  8. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +2 -2
  10. data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.ie7.min.css +1 -1
  11. data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.min.css +1 -1
  12. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/atomic.js +5 -0
  13. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/bootstrap-atomic.js +1491 -0
  14. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/bootstrap-browser.js +1491 -0
  15. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/bootstrap-demo.js +1491 -0
  16. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/bootstrap-prod.js +1491 -0
  17. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/browser.js +10 -0
  18. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/demo.js +8 -0
  19. data/vendor/assets/javascripts/tinymce/themes/inlite/config/bolt/prod.js +5 -0
  20. data/vendor/assets/javascripts/tinymce/themes/inlite/config/dent/depend.js +21 -0
  21. data/vendor/assets/javascripts/tinymce/themes/inlite/scratch/compile/bootstrap.js +1526 -0
  22. data/vendor/assets/javascripts/tinymce/themes/inlite/scratch/compile/theme.js +1589 -0
  23. data/vendor/assets/javascripts/tinymce/themes/inlite/scratch/inline/theme.js +1674 -0
  24. data/vendor/assets/javascripts/tinymce/themes/inlite/scratch/inline/theme.raw.js +1674 -0
  25. data/vendor/assets/javascripts/tinymce/themes/inlite/src/demo/css/demo.css +25 -0
  26. data/vendor/assets/javascripts/tinymce/themes/inlite/src/demo/html/demo.html +42 -0
  27. data/vendor/assets/javascripts/tinymce/themes/inlite/src/demo/js/tinymce/inlite/Demo.js +28 -0
  28. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/Theme.js +143 -0
  29. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/alien/Arr.js +22 -0
  30. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/alien/Bookmark.js +130 -0
  31. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/alien/Unlink.js +84 -0
  32. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/alien/Uuid.js +34 -0
  33. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/Actions.js +106 -0
  34. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/Convert.js +37 -0
  35. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/ElementMatcher.js +47 -0
  36. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/Layout.js +95 -0
  37. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/Matcher.js +39 -0
  38. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/Measure.js +70 -0
  39. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/PredicateId.js +32 -0
  40. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/SelectionMatcher.js +55 -0
  41. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/SkinLoader.js +45 -0
  42. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/core/UrlType.js +22 -0
  43. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/file/Conversions.js +31 -0
  44. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/file/Picker.js +40 -0
  45. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/ui/Buttons.js +80 -0
  46. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/ui/Forms.js +102 -0
  47. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/ui/Panel.js +216 -0
  48. data/vendor/assets/javascripts/tinymce/themes/inlite/src/main/js/tinymce/inlite/ui/Toolbar.js +126 -0
  49. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/atomic/alien/ArrTest.js +9 -0
  50. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/atomic/alien/UuidTest.js +10 -0
  51. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/atomic/core/ConvertTest.js +12 -0
  52. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/atomic/core/MatcherTest.js +51 -0
  53. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/atomic/core/UrlTypeTest.js +25 -0
  54. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/ThemeTest.js +202 -0
  55. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/alien/BookmarkTest.js +65 -0
  56. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/alien/UnlinkTest.js +38 -0
  57. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/ActionsTest.js +177 -0
  58. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/ElementMatcher.js +69 -0
  59. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/LayoutTest.js +118 -0
  60. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/MeasureTest.js +62 -0
  61. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/PredicateIdTest.js +26 -0
  62. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/core/SelectionMatcherTest.js +76 -0
  63. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/file/ConversionsTest.js +41 -0
  64. data/vendor/assets/javascripts/tinymce/themes/inlite/src/test/js/browser/file/SelectionMatcher.js +55 -0
  65. data/vendor/assets/javascripts/tinymce/themes/inlite/theme.js +1 -0
  66. data/vendor/assets/javascripts/tinymce/themes/modern/theme.js +1 -1
  67. data/vendor/assets/javascripts/tinymce/tinymce.js +13 -13
  68. metadata +57 -3
@@ -0,0 +1,1674 @@
1
+ (function () {
2
+
3
+ var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
4
+
5
+ // Used when there is no 'main' module.
6
+ // The name is probably (hopefully) unique so minification removes for releases.
7
+ var register_3795 = function (id) {
8
+ var module = dem(id);
9
+ var fragments = id.split('.');
10
+ var target = Function('return this;')();
11
+ for (var i = 0; i < fragments.length - 1; ++i) {
12
+ if (target[fragments[i]] === undefined)
13
+ target[fragments[i]] = {};
14
+ target = target[fragments[i]];
15
+ }
16
+ target[fragments[fragments.length - 1]] = module;
17
+ };
18
+
19
+ var instantiate = function (id) {
20
+ var actual = defs[id];
21
+ var dependencies = actual.deps;
22
+ var definition = actual.defn;
23
+ var len = dependencies.length;
24
+ var instances = new Array(len);
25
+ for (var i = 0; i < len; ++i)
26
+ instances[i] = dem(dependencies[i]);
27
+ var defResult = definition.apply(null, instances);
28
+ if (defResult === undefined)
29
+ throw 'module [' + id + '] returned undefined';
30
+ actual.instance = defResult;
31
+ };
32
+
33
+ var def = function (id, dependencies, definition) {
34
+ if (typeof id !== 'string')
35
+ throw 'module id must be a string';
36
+ else if (dependencies === undefined)
37
+ throw 'no dependencies for ' + id;
38
+ else if (definition === undefined)
39
+ throw 'no definition function for ' + id;
40
+ defs[id] = {
41
+ deps: dependencies,
42
+ defn: definition,
43
+ instance: undefined
44
+ };
45
+ };
46
+
47
+ var dem = function (id) {
48
+ var actual = defs[id];
49
+ if (actual === undefined)
50
+ throw 'module [' + id + '] was undefined';
51
+ else if (actual.instance === undefined)
52
+ instantiate(id);
53
+ return actual.instance;
54
+ };
55
+
56
+ var req = function (ids, callback) {
57
+ var len = ids.length;
58
+ var instances = new Array(len);
59
+ for (var i = 0; i < len; ++i)
60
+ instances.push(dem(ids[i]));
61
+ callback.apply(null, callback);
62
+ };
63
+
64
+ var ephox = {};
65
+
66
+ ephox.bolt = {
67
+ module: {
68
+ api: {
69
+ define: def,
70
+ require: req,
71
+ demand: dem
72
+ }
73
+ }
74
+ };
75
+
76
+ var define = def;
77
+ var require = req;
78
+ var demand = dem;
79
+ // this helps with minificiation when using a lot of global references
80
+ var defineGlobal = function (id, ref) {
81
+ define(id, [], function () { return ref; });
82
+ };
83
+ /*jsc
84
+ ["tinymce/inlite/Theme","global!tinymce.ThemeManager","global!tinymce.util.Delay","tinymce/inlite/ui/Panel","tinymce/inlite/ui/Buttons","tinymce/inlite/core/SkinLoader","tinymce/inlite/core/SelectionMatcher","tinymce/inlite/core/ElementMatcher","tinymce/inlite/core/Matcher","tinymce/inlite/alien/Arr","tinymce/inlite/core/PredicateId","global!tinymce.util.Tools","global!tinymce.ui.Factory","global!tinymce.DOM","tinymce/inlite/ui/Toolbar","tinymce/inlite/ui/Forms","tinymce/inlite/core/Measure","tinymce/inlite/core/Layout","tinymce/inlite/file/Conversions","tinymce/inlite/file/Picker","tinymce/inlite/core/Actions","global!tinymce.EditorManager","global!tinymce.util.Promise","tinymce/inlite/alien/Uuid","tinymce/inlite/alien/Unlink","tinymce/inlite/core/UrlType","global!tinymce.geom.Rect","tinymce/inlite/core/Convert","tinymce/inlite/alien/Bookmark","global!tinymce.dom.TreeWalker","global!tinymce.dom.RangeUtils"]
85
+ jsc*/
86
+ defineGlobal("global!tinymce.ThemeManager", tinymce.ThemeManager);
87
+ defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
88
+ defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
89
+ defineGlobal("global!tinymce.ui.Factory", tinymce.ui.Factory);
90
+ defineGlobal("global!tinymce.DOM", tinymce.DOM);
91
+ /**
92
+ * Toolbar.js
93
+ *
94
+ * Released under LGPL License.
95
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
96
+ *
97
+ * License: http://www.tinymce.com/license
98
+ * Contributing: http://www.tinymce.com/contributing
99
+ */
100
+
101
+ define('tinymce/inlite/ui/Toolbar', [
102
+ 'global!tinymce.util.Tools',
103
+ 'global!tinymce.ui.Factory'
104
+ ], function (Tools, Factory) {
105
+ var setActiveItem = function (item, name) {
106
+ return function(state, args) {
107
+ var nodeName, i = args.parents.length;
108
+
109
+ while (i--) {
110
+ nodeName = args.parents[i].nodeName;
111
+ if (nodeName == 'OL' || nodeName == 'UL') {
112
+ break;
113
+ }
114
+ }
115
+
116
+ item.active(state && nodeName == name);
117
+ };
118
+ };
119
+
120
+ var getSelectorStateResult = function (itemName, item) {
121
+ var result = function (selector, handler) {
122
+ return {
123
+ selector: selector,
124
+ handler: handler
125
+ };
126
+ };
127
+
128
+ var activeHandler = function(state) {
129
+ item.active(state);
130
+ };
131
+
132
+ var disabledHandler = function (state) {
133
+ item.disabled(state);
134
+ };
135
+
136
+ if (itemName == 'bullist') {
137
+ return result('ul > li', setActiveItem(item, 'UL'));
138
+ }
139
+
140
+ if (itemName == 'numlist') {
141
+ return result('ol > li', setActiveItem(item, 'OL'));
142
+ }
143
+
144
+ if (item.settings.stateSelector) {
145
+ return result(item.settings.stateSelector, activeHandler);
146
+ }
147
+
148
+ if (item.settings.disabledStateSelector) {
149
+ return result(item.settings.disabledStateSelector, disabledHandler);
150
+ }
151
+
152
+ return null;
153
+ };
154
+
155
+ var bindSelectorChanged = function (editor, itemName, item) {
156
+ return function () {
157
+ var result = getSelectorStateResult(itemName, item);
158
+ if (result !== null) {
159
+ editor.selection.selectorChanged(result.selector, result.handler);
160
+ }
161
+ };
162
+ };
163
+
164
+ var create = function (editor, name, items) {
165
+ var toolbarItems = [], buttonGroup;
166
+
167
+ if (!items) {
168
+ return;
169
+ }
170
+
171
+ Tools.each(items.split(/[ ,]/), function(item) {
172
+ var itemName;
173
+
174
+ if (item == '|') {
175
+ buttonGroup = null;
176
+ } else {
177
+ if (Factory.has(item)) {
178
+ item = {type: item};
179
+ toolbarItems.push(item);
180
+ buttonGroup = null;
181
+ } else {
182
+ if (!buttonGroup) {
183
+ buttonGroup = {type: 'buttongroup', items: []};
184
+ toolbarItems.push(buttonGroup);
185
+ }
186
+
187
+ if (editor.buttons[item]) {
188
+ itemName = item;
189
+ item = editor.buttons[itemName];
190
+
191
+ if (typeof item == 'function') {
192
+ item = item();
193
+ }
194
+
195
+ item.type = item.type || 'button';
196
+
197
+ item = Factory.create(item);
198
+ item.on('postRender', bindSelectorChanged(editor, itemName, item));
199
+ buttonGroup.items.push(item);
200
+ }
201
+ }
202
+ }
203
+ });
204
+
205
+ return Factory.create({
206
+ type: 'toolbar',
207
+ layout: 'flow',
208
+ name: name,
209
+ items: toolbarItems
210
+ });
211
+ };
212
+
213
+ return {
214
+ create: create
215
+ };
216
+ });
217
+
218
+ defineGlobal("global!tinymce.util.Promise", tinymce.util.Promise);
219
+ /**
220
+ * Uuid.js
221
+ *
222
+ * Released under LGPL License.
223
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
224
+ *
225
+ * License: http://www.tinymce.com/license
226
+ * Contributing: http://www.tinymce.com/contributing
227
+ */
228
+
229
+ /**
230
+ * Generates unique ids this is the same as in core but since
231
+ * it's not exposed as a global we can't access it.
232
+ */
233
+ define("tinymce/inlite/alien/Uuid", [
234
+ ], function() {
235
+ var count = 0;
236
+
237
+ var seed = function () {
238
+ var rnd = function () {
239
+ return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
240
+ };
241
+
242
+ return 's' + Date.now().toString(36) + rnd() + rnd() + rnd();
243
+ };
244
+
245
+ var uuid = function (prefix) {
246
+ return prefix + (count++) + seed();
247
+ };
248
+
249
+ return {
250
+ uuid: uuid
251
+ };
252
+ });
253
+
254
+ /**
255
+ * Bookmark.js
256
+ *
257
+ * Released under LGPL License.
258
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
259
+ *
260
+ * License: http://www.tinymce.com/license
261
+ * Contributing: http://www.tinymce.com/contributing
262
+ */
263
+
264
+ define('tinymce/inlite/alien/Bookmark', [
265
+ ], function () {
266
+ /**
267
+ * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
268
+ * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
269
+ * added to them since they can be restored after a dom operation.
270
+ *
271
+ * So this: <p><b>|</b><b>|</b></p>
272
+ * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
273
+ *
274
+ * @param {DOMRange} rng DOM Range to get bookmark on.
275
+ * @return {Object} Bookmark object.
276
+ */
277
+ var create = function (dom, rng) {
278
+ var bookmark = {};
279
+
280
+ function setupEndPoint(start) {
281
+ var offsetNode, container, offset;
282
+
283
+ container = rng[start ? 'startContainer' : 'endContainer'];
284
+ offset = rng[start ? 'startOffset' : 'endOffset'];
285
+
286
+ if (container.nodeType == 1) {
287
+ offsetNode = dom.create('span', {'data-mce-type': 'bookmark'});
288
+
289
+ if (container.hasChildNodes()) {
290
+ offset = Math.min(offset, container.childNodes.length - 1);
291
+
292
+ if (start) {
293
+ container.insertBefore(offsetNode, container.childNodes[offset]);
294
+ } else {
295
+ dom.insertAfter(offsetNode, container.childNodes[offset]);
296
+ }
297
+ } else {
298
+ container.appendChild(offsetNode);
299
+ }
300
+
301
+ container = offsetNode;
302
+ offset = 0;
303
+ }
304
+
305
+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
306
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
307
+ }
308
+
309
+ setupEndPoint(true);
310
+
311
+ if (!rng.collapsed) {
312
+ setupEndPoint();
313
+ }
314
+
315
+ return bookmark;
316
+ };
317
+
318
+ /**
319
+ * Moves the selection to the current bookmark and removes any selection container wrappers.
320
+ *
321
+ * @param {Object} bookmark Bookmark object to move selection to.
322
+ */
323
+ var resolve = function (dom, bookmark) {
324
+ function restoreEndPoint(start) {
325
+ var container, offset, node;
326
+
327
+ function nodeIndex(container) {
328
+ var node = container.parentNode.firstChild, idx = 0;
329
+
330
+ while (node) {
331
+ if (node == container) {
332
+ return idx;
333
+ }
334
+
335
+ // Skip data-mce-type=bookmark nodes
336
+ if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
337
+ idx++;
338
+ }
339
+
340
+ node = node.nextSibling;
341
+ }
342
+
343
+ return -1;
344
+ }
345
+
346
+ container = node = bookmark[start ? 'startContainer' : 'endContainer'];
347
+ offset = bookmark[start ? 'startOffset' : 'endOffset'];
348
+
349
+ if (!container) {
350
+ return;
351
+ }
352
+
353
+ if (container.nodeType == 1) {
354
+ offset = nodeIndex(container);
355
+ container = container.parentNode;
356
+ dom.remove(node);
357
+ }
358
+
359
+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
360
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
361
+ }
362
+
363
+ restoreEndPoint(true);
364
+ restoreEndPoint();
365
+
366
+ var rng = dom.createRng();
367
+
368
+ rng.setStart(bookmark.startContainer, bookmark.startOffset);
369
+
370
+ if (bookmark.endContainer) {
371
+ rng.setEnd(bookmark.endContainer, bookmark.endOffset);
372
+ }
373
+
374
+ return rng;
375
+ };
376
+
377
+ return {
378
+ create: create,
379
+ resolve: resolve
380
+ };
381
+ });
382
+
383
+
384
+
385
+ defineGlobal("global!tinymce.dom.TreeWalker", tinymce.dom.TreeWalker);
386
+ defineGlobal("global!tinymce.dom.RangeUtils", tinymce.dom.RangeUtils);
387
+ /**
388
+ * Unlink.js
389
+ *
390
+ * Released under LGPL License.
391
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
392
+ *
393
+ * License: http://www.tinymce.com/license
394
+ * Contributing: http://www.tinymce.com/contributing
395
+ */
396
+
397
+ /**
398
+ * Unlink implementation that doesn't leave partial links for example it would produce:
399
+ * a[b<a href="x">c]d</a>e -> a[bc]de
400
+ * instead of:
401
+ * a[b<a href="x">c]d</a>e -> a[bc]<a href="x">d</a>e
402
+ */
403
+ define("tinymce/inlite/alien/Unlink", [
404
+ 'tinymce/inlite/alien/Bookmark',
405
+ 'global!tinymce.util.Tools',
406
+ 'global!tinymce.dom.TreeWalker',
407
+ 'global!tinymce.dom.RangeUtils'
408
+ ], function (Bookmark, Tools, TreeWalker, RangeUtils) {
409
+ var getSelectedElements = function (rootElm, startNode, endNode) {
410
+ var walker, node, elms = [];
411
+
412
+ walker = new TreeWalker(startNode, rootElm);
413
+ for (node = startNode; node; node = walker.next()) {
414
+ if (node.nodeType === 1) {
415
+ elms.push(node);
416
+ }
417
+
418
+ if (node === endNode) {
419
+ break;
420
+ }
421
+ }
422
+
423
+ return elms;
424
+ };
425
+
426
+ var unwrapElements = function (editor, elms) {
427
+ var bookmark, dom, selection;
428
+
429
+ dom = editor.dom;
430
+ selection = editor.selection;
431
+ bookmark = Bookmark.create(dom, selection.getRng());
432
+
433
+ Tools.each(elms, function (elm) {
434
+ editor.dom.remove(elm, true);
435
+ });
436
+
437
+ selection.setRng(Bookmark.resolve(dom, bookmark));
438
+ };
439
+
440
+ var isLink = function (elm) {
441
+ return elm.nodeName === 'A' && elm.hasAttribute('href');
442
+ };
443
+
444
+ var getParentAnchorOrSelf = function (dom, elm) {
445
+ var anchorElm = dom.getParent(elm, isLink);
446
+ return anchorElm ? anchorElm : elm;
447
+ };
448
+
449
+ var getSelectedAnchors = function (editor) {
450
+ var startElm, endElm, rootElm, anchorElms, selection, dom, rng;
451
+
452
+ selection = editor.selection;
453
+ dom = editor.dom;
454
+ rng = selection.getRng();
455
+ startElm = getParentAnchorOrSelf(dom, RangeUtils.getNode(rng.startContainer, rng.startOffset));
456
+ endElm = RangeUtils.getNode(rng.endContainer, rng.endOffset);
457
+ rootElm = editor.getBody();
458
+ anchorElms = Tools.grep(getSelectedElements(rootElm, startElm, endElm), isLink);
459
+
460
+ return anchorElms;
461
+ };
462
+
463
+ var unlinkSelection = function (editor) {
464
+ unwrapElements(editor, getSelectedAnchors(editor));
465
+ };
466
+
467
+ return {
468
+ unlinkSelection: unlinkSelection
469
+ };
470
+ });
471
+
472
+ /**
473
+ * Actions.js
474
+ *
475
+ * Released under LGPL License.
476
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
477
+ *
478
+ * License: http://www.tinymce.com/license
479
+ * Contributing: http://www.tinymce.com/contributing
480
+ */
481
+
482
+ define('tinymce/inlite/core/Actions', [
483
+ 'tinymce/inlite/alien/Uuid',
484
+ 'tinymce/inlite/alien/Unlink'
485
+ ], function (Uuid, Unlink) {
486
+ var createTableHtml = function (cols, rows) {
487
+ var x, y, html;
488
+
489
+ html = '<table data-mce-id="mce" style="width: 100%">';
490
+ html += '<tbody>';
491
+
492
+ for (y = 0; y < rows; y++) {
493
+ html += '<tr>';
494
+
495
+ for (x = 0; x < cols; x++) {
496
+ html += '<td><br></td>';
497
+ }
498
+
499
+ html += '</tr>';
500
+ }
501
+
502
+ html += '</tbody>';
503
+ html += '</table>';
504
+
505
+ return html;
506
+ };
507
+
508
+ var getInsertedElement = function (editor) {
509
+ var elms = editor.dom.select('*[data-mce-id]');
510
+ return elms[0];
511
+ };
512
+
513
+ var insertTable = function (editor, cols, rows) {
514
+ editor.undoManager.transact(function () {
515
+ var tableElm, cellElm;
516
+
517
+ editor.insertContent(createTableHtml(cols, rows));
518
+
519
+ tableElm = getInsertedElement(editor);
520
+ tableElm.removeAttribute('data-mce-id');
521
+ cellElm = editor.dom.select('td,th', tableElm);
522
+ editor.selection.setCursorLocation(cellElm[0], 0);
523
+ });
524
+ };
525
+
526
+ var formatBlock = function (editor, formatName) {
527
+ editor.execCommand('FormatBlock', false, formatName);
528
+ };
529
+
530
+ var insertBlob = function (editor, base64, blob) {
531
+ var blobCache, blobInfo;
532
+
533
+ blobCache = editor.editorUpload.blobCache;
534
+ blobInfo = blobCache.create(Uuid.uuid('mceu'), blob, base64);
535
+ blobCache.add(blobInfo);
536
+
537
+ editor.insertContent(editor.dom.createHTML('img', {src: blobInfo.blobUri()}));
538
+ };
539
+
540
+ var collapseSelectionToEnd = function (editor) {
541
+ editor.selection.collapse(false);
542
+ };
543
+
544
+ var unlink = function (editor) {
545
+ editor.focus();
546
+ Unlink.unlinkSelection(editor);
547
+ collapseSelectionToEnd(editor);
548
+ };
549
+
550
+ var changeHref = function (editor, elm, url) {
551
+ editor.focus();
552
+ editor.dom.setAttrib(elm, 'href', url);
553
+ collapseSelectionToEnd(editor);
554
+ };
555
+
556
+ var insertLink = function (editor, url) {
557
+ editor.execCommand('mceInsertLink', false, {href: url});
558
+ collapseSelectionToEnd(editor);
559
+ };
560
+
561
+ var updateOrInsertLink = function (editor, url) {
562
+ var elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
563
+ elm ? changeHref(editor, elm, url) : insertLink(editor, url);
564
+ };
565
+
566
+ var createLink = function (editor, url) {
567
+ url.trim().length === 0 ? unlink(editor) : updateOrInsertLink(editor, url);
568
+ };
569
+
570
+ return {
571
+ insertTable: insertTable,
572
+ formatBlock: formatBlock,
573
+ insertBlob: insertBlob,
574
+ createLink: createLink,
575
+ unlink: unlink
576
+ };
577
+ });
578
+
579
+ /**
580
+ * UrlType.js
581
+ *
582
+ * Released under LGPL License.
583
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
584
+ *
585
+ * License: http://www.tinymce.com/license
586
+ * Contributing: http://www.tinymce.com/contributing
587
+ */
588
+
589
+ define('tinymce/inlite/core/UrlType', [
590
+ ], function () {
591
+ var isDomainLike = function (href) {
592
+ return /^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(href.trim());
593
+ };
594
+
595
+ return {
596
+ isDomainLike: isDomainLike
597
+ };
598
+ });
599
+
600
+
601
+
602
+ /**
603
+ * Forms.js
604
+ *
605
+ * Released under LGPL License.
606
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
607
+ *
608
+ * License: http://www.tinymce.com/license
609
+ * Contributing: http://www.tinymce.com/contributing
610
+ */
611
+
612
+ define('tinymce/inlite/ui/Forms', [
613
+ 'global!tinymce.util.Tools',
614
+ 'global!tinymce.ui.Factory',
615
+ 'global!tinymce.util.Promise',
616
+ 'tinymce/inlite/core/Actions',
617
+ 'tinymce/inlite/core/UrlType'
618
+ ], function (Tools, Factory, Promise, Actions, UrlType) {
619
+ var focusFirstTextBox = function (form) {
620
+ form.find('textbox').eq(0).each(function (ctrl) {
621
+ ctrl.focus();
622
+ });
623
+ };
624
+
625
+ var createForm = function (name, spec) {
626
+ var form = Factory.create(
627
+ Tools.extend({
628
+ type: 'form',
629
+ layout: 'flex',
630
+ direction: 'row',
631
+ padding: 5,
632
+ name: name,
633
+ spacing: 3
634
+ }, spec)
635
+ );
636
+
637
+ form.on('show', function () {
638
+ focusFirstTextBox(form);
639
+ });
640
+
641
+ return form;
642
+ };
643
+
644
+ var toggleVisibility = function (ctrl, state) {
645
+ return state ? ctrl.show() : ctrl.hide();
646
+ };
647
+
648
+ var askAboutPrefix = function (editor, href) {
649
+ return new Promise(function (resolve) {
650
+ editor.windowManager.confirm(
651
+ 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
652
+ function (result) {
653
+ var output = result === true ? 'http://' + href : href;
654
+ resolve(output);
655
+ }
656
+ );
657
+ });
658
+ };
659
+
660
+ var convertLinkToAbsolute = function (editor, href) {
661
+ return UrlType.isDomainLike(href) ? askAboutPrefix(editor, href) : Promise.resolve(href);
662
+ };
663
+
664
+ var createQuickLinkForm = function (editor, hide) {
665
+ var unlink = function () {
666
+ editor.focus();
667
+ Actions.unlink(editor);
668
+ hide();
669
+ };
670
+
671
+ return createForm('quicklink', {
672
+ items: [
673
+ {type: 'button', name: 'unlink', icon: 'unlink', onclick: unlink, tooltip: 'Remove link'},
674
+ {type: 'textbox', name: 'linkurl', placeholder: 'Paste or type a link'},
675
+ {type: 'button', icon: 'checkmark', subtype: 'primary', tooltip: 'Ok', onclick: 'submit'}
676
+ ],
677
+ onshow: function () {
678
+ var elm, linkurl = '';
679
+
680
+ elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
681
+ if (elm) {
682
+ linkurl = editor.dom.getAttrib(elm, 'href');
683
+ }
684
+
685
+ this.fromJSON({
686
+ linkurl: linkurl
687
+ });
688
+
689
+ toggleVisibility(this.find('#unlink'), elm);
690
+ },
691
+ onsubmit: function (e) {
692
+ convertLinkToAbsolute(editor, e.data.linkurl).then(function (url) {
693
+ Actions.createLink(editor, url);
694
+ hide();
695
+ });
696
+ }
697
+ });
698
+ };
699
+
700
+ return {
701
+ createQuickLinkForm: createQuickLinkForm
702
+ };
703
+ });
704
+
705
+ defineGlobal("global!tinymce.geom.Rect", tinymce.geom.Rect);
706
+ /**
707
+ * Convert.js
708
+ *
709
+ * Released under LGPL License.
710
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
711
+ *
712
+ * License: http://www.tinymce.com/license
713
+ * Contributing: http://www.tinymce.com/contributing
714
+ */
715
+
716
+ define('tinymce/inlite/core/Convert', [
717
+ ], function () {
718
+ var fromClientRect = function (clientRect) {
719
+ return {
720
+ x: clientRect.left,
721
+ y: clientRect.top,
722
+ w: clientRect.width,
723
+ h: clientRect.height
724
+ };
725
+ };
726
+
727
+ var toClientRect = function (geomRect) {
728
+ return {
729
+ left: geomRect.x,
730
+ top: geomRect.y,
731
+ width: geomRect.w,
732
+ height: geomRect.h,
733
+ right: geomRect.x + geomRect.w,
734
+ bottom: geomRect.y + geomRect.h
735
+ };
736
+ };
737
+
738
+ return {
739
+ fromClientRect: fromClientRect,
740
+ toClientRect: toClientRect
741
+ };
742
+ });
743
+
744
+ /**
745
+ * Measure.js
746
+ *
747
+ * Released under LGPL License.
748
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
749
+ *
750
+ * License: http://www.tinymce.com/license
751
+ * Contributing: http://www.tinymce.com/contributing
752
+ */
753
+
754
+ define('tinymce/inlite/core/Measure', [
755
+ 'global!tinymce.DOM',
756
+ 'global!tinymce.geom.Rect',
757
+ 'tinymce/inlite/core/Convert'
758
+ ], function (DOM, Rect, Convert) {
759
+ var toAbsolute = function (rect) {
760
+ var vp = DOM.getViewPort();
761
+
762
+ return {
763
+ x: rect.x + vp.x,
764
+ y: rect.y + vp.y,
765
+ w: rect.w,
766
+ h: rect.h
767
+ };
768
+ };
769
+
770
+ var getElementRect = function (editor, elm) {
771
+ var pos, targetRect, root;
772
+
773
+ pos = DOM.getPos(editor.getContentAreaContainer());
774
+ targetRect = editor.dom.getRect(elm);
775
+ root = editor.dom.getRoot();
776
+
777
+ // Adjust targetPos for scrolling in the editor
778
+ if (root.nodeName == 'BODY') {
779
+ targetRect.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
780
+ targetRect.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
781
+ }
782
+
783
+ targetRect.x += pos.x;
784
+ targetRect.y += pos.y;
785
+
786
+ // We need to use these instead of the rect values since the style
787
+ // size properites might not be the same as the real size for a table
788
+ targetRect.w = elm.clientWidth > 0 ? elm.clientWidth : elm.offsetWidth;
789
+ targetRect.h = elm.clientHeight > 0 ? elm.clientHeight : elm.offsetHeight;
790
+
791
+ return targetRect;
792
+ };
793
+
794
+ var getPageAreaRect = function (editor) {
795
+ return DOM.getRect(editor.getElement().ownerDocument.body);
796
+ };
797
+
798
+ var getContentAreaRect = function (editor) {
799
+ return toAbsolute(DOM.getRect(editor.getContentAreaContainer() || editor.getBody()));
800
+ };
801
+
802
+ var getSelectionRect = function (editor) {
803
+ var clientRect = editor.selection.getBoundingClientRect();
804
+ return clientRect ? toAbsolute(Convert.fromClientRect(clientRect)) : null;
805
+ };
806
+
807
+ return {
808
+ getElementRect: getElementRect,
809
+ getPageAreaRect: getPageAreaRect,
810
+ getContentAreaRect: getContentAreaRect,
811
+ getSelectionRect: getSelectionRect
812
+ };
813
+ });
814
+
815
+ /**
816
+ * Layout.js
817
+ *
818
+ * Released under LGPL License.
819
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
820
+ *
821
+ * License: http://www.tinymce.com/license
822
+ * Contributing: http://www.tinymce.com/contributing
823
+ */
824
+
825
+ define('tinymce/inlite/core/Layout', [
826
+ 'global!tinymce.geom.Rect',
827
+ 'tinymce/inlite/core/Convert'
828
+ ], function (Rect, Convert) {
829
+ var result = function (rect, position) {
830
+ return {
831
+ rect: rect,
832
+ position: position
833
+ };
834
+ };
835
+
836
+ var moveTo = function (rect, toRect) {
837
+ return {x: toRect.x, y: toRect.y, w: rect.w, h: rect.h};
838
+ };
839
+
840
+ var calcByPositions = function (testPositions1, testPositions2, targetRect, contentAreaRect, panelRect) {
841
+ var relPos, relRect, outputPanelRect;
842
+
843
+ relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions1);
844
+ targetRect = Rect.clamp(targetRect, contentAreaRect);
845
+
846
+ if (relPos) {
847
+ relRect = Rect.relativePosition(panelRect, targetRect, relPos);
848
+ outputPanelRect = moveTo(panelRect, relRect);
849
+ return result(outputPanelRect, relPos);
850
+ }
851
+
852
+ targetRect = Rect.intersect(contentAreaRect, targetRect);
853
+ if (targetRect) {
854
+ relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions2);
855
+ if (relPos) {
856
+ relRect = Rect.relativePosition(panelRect, targetRect, relPos);
857
+ outputPanelRect = moveTo(panelRect, relRect);
858
+ return result(outputPanelRect, relPos);
859
+ }
860
+
861
+ outputPanelRect = moveTo(panelRect, targetRect);
862
+ return result(outputPanelRect, relPos);
863
+ }
864
+
865
+ return null;
866
+ };
867
+
868
+ var calcInsert = function (targetRect, contentAreaRect, panelRect) {
869
+ return calcByPositions(
870
+ ['cr-cl', 'cl-cr'],
871
+ ['bc-tc', 'bl-tl', 'br-tr'],
872
+ targetRect,
873
+ contentAreaRect,
874
+ panelRect
875
+ );
876
+ };
877
+
878
+ var calc = function (targetRect, contentAreaRect, panelRect) {
879
+ return calcByPositions(
880
+ ['tc-bc', 'bc-tc', 'tl-bl', 'bl-tl', 'tr-br', 'br-tr'],
881
+ ['bc-tc', 'bl-tl', 'br-tr'],
882
+ targetRect,
883
+ contentAreaRect,
884
+ panelRect
885
+ );
886
+ };
887
+
888
+ var userConstrain = function (handler, targetRect, contentAreaRect, panelRect) {
889
+ var userConstrainedPanelRect;
890
+
891
+ if (typeof handler === 'function') {
892
+ userConstrainedPanelRect = handler({
893
+ elementRect: Convert.toClientRect(targetRect),
894
+ contentAreaRect: Convert.toClientRect(contentAreaRect),
895
+ panelRect: Convert.toClientRect(panelRect)
896
+ });
897
+
898
+ return Convert.fromClientRect(userConstrainedPanelRect);
899
+ }
900
+
901
+ return panelRect;
902
+ };
903
+
904
+ return {
905
+ calcInsert: calcInsert,
906
+ calc: calc,
907
+ userConstrain: userConstrain
908
+ };
909
+ });
910
+
911
+ /**
912
+ * Panel.js
913
+ *
914
+ * Released under LGPL License.
915
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
916
+ *
917
+ * License: http://www.tinymce.com/license
918
+ * Contributing: http://www.tinymce.com/contributing
919
+ */
920
+
921
+ define('tinymce/inlite/ui/Panel', [
922
+ 'global!tinymce.util.Tools',
923
+ 'global!tinymce.ui.Factory',
924
+ 'global!tinymce.DOM',
925
+ 'tinymce/inlite/ui/Toolbar',
926
+ 'tinymce/inlite/ui/Forms',
927
+ 'tinymce/inlite/core/Measure',
928
+ 'tinymce/inlite/core/Layout'
929
+ ], function (Tools, Factory, DOM, Toolbar, Forms, Measure, Layout) {
930
+ var DEFAULT_TEXT_SELECTION_ITEMS = 'bold italic | quicklink h2 h3 blockquote';
931
+ var DEFAULT_INSERT_TOOLBAR_ITEMS = 'quickimage quicktable';
932
+ var panel, currentRect;
933
+
934
+ var createToolbars = function (editor, toolbars) {
935
+ return Tools.map(toolbars, function (toolbar) {
936
+ return Toolbar.create(editor, toolbar.id, toolbar.items);
937
+ });
938
+ };
939
+
940
+ var getTextSelectionToolbarItems = function (settings) {
941
+ var value = settings.selection_toolbar;
942
+ return value ? value : DEFAULT_TEXT_SELECTION_ITEMS;
943
+ };
944
+
945
+ var getInsertToolbarItems = function (settings) {
946
+ var value = settings.insert_toolbar;
947
+ return value ? value : DEFAULT_INSERT_TOOLBAR_ITEMS;
948
+ };
949
+
950
+ var create = function (editor, toolbars) {
951
+ var items, settings = editor.settings;
952
+
953
+ items = createToolbars(editor, toolbars);
954
+ items = items.concat([
955
+ Toolbar.create(editor, 'text', getTextSelectionToolbarItems(settings)),
956
+ Toolbar.create(editor, 'insert', getInsertToolbarItems(settings)),
957
+ Forms.createQuickLinkForm(editor, hide)
958
+ ]);
959
+
960
+ return Factory.create({
961
+ type: 'floatpanel',
962
+ role: 'dialog',
963
+ classes: 'tinymce tinymce-inline arrow',
964
+ ariaLabel: 'Inline toolbar',
965
+ layout: 'flex',
966
+ direction: 'column',
967
+ align: 'stretch',
968
+ autohide: false,
969
+ autofix: true,
970
+ fixed: true,
971
+ border: 1,
972
+ items: items,
973
+ oncancel: function() {
974
+ editor.focus();
975
+ }
976
+ });
977
+ };
978
+
979
+ var showPanel = function (panel) {
980
+ if (panel) {
981
+ panel.show();
982
+ }
983
+ };
984
+
985
+ var movePanelTo = function (panel, pos) {
986
+ panel.moveTo(pos.x, pos.y);
987
+ };
988
+
989
+ var togglePositionClass = function (panel, relPos) {
990
+ relPos = relPos ? relPos.substr(0, 2) : '';
991
+
992
+ Tools.each({
993
+ t: 'down',
994
+ b: 'up',
995
+ c: 'center'
996
+ }, function(cls, pos) {
997
+ panel.classes.toggle('arrow-' + cls, pos === relPos.substr(0, 1));
998
+ });
999
+
1000
+ if (relPos === 'cr') {
1001
+ panel.classes.toggle('arrow-left', true);
1002
+ panel.classes.toggle('arrow-right', false);
1003
+ } else if (relPos === 'cl') {
1004
+ panel.classes.toggle('arrow-left', true);
1005
+ panel.classes.toggle('arrow-right', true);
1006
+ } else {
1007
+ Tools.each({
1008
+ l: 'left',
1009
+ r: 'right'
1010
+ }, function(cls, pos) {
1011
+ panel.classes.toggle('arrow-' + cls, pos === relPos.substr(1, 1));
1012
+ });
1013
+ }
1014
+ };
1015
+
1016
+ var showToolbar = function (panel, id) {
1017
+ var toolbars = panel.items().filter('#' + id);
1018
+
1019
+ if (toolbars.length > 0) {
1020
+ toolbars[0].show();
1021
+ panel.reflow();
1022
+ }
1023
+ };
1024
+
1025
+ var showPanelAt = function (panel, id, editor, targetRect) {
1026
+ var contentAreaRect, panelRect, result, userConstainHandler;
1027
+
1028
+ showPanel(panel);
1029
+ panel.items().hide();
1030
+ showToolbar(panel, id);
1031
+
1032
+ userConstainHandler = editor.settings.inline_toolbar_position_handler;
1033
+ contentAreaRect = Measure.getContentAreaRect(editor);
1034
+ panelRect = DOM.getRect(panel.getEl());
1035
+
1036
+ if (id === 'insert') {
1037
+ result = Layout.calcInsert(targetRect, contentAreaRect, panelRect);
1038
+ } else {
1039
+ result = Layout.calc(targetRect, contentAreaRect, panelRect);
1040
+ }
1041
+
1042
+ if (result) {
1043
+ panelRect = result.rect;
1044
+ currentRect = targetRect;
1045
+ movePanelTo(panel, Layout.userConstrain(userConstainHandler, targetRect, contentAreaRect, panelRect));
1046
+
1047
+ togglePositionClass(panel, result.position);
1048
+ } else {
1049
+ hide(panel);
1050
+ }
1051
+ };
1052
+
1053
+ var hasFormVisible = function () {
1054
+ return panel.items().filter('form:visible').length > 0;
1055
+ };
1056
+
1057
+ var showForm = function (editor, id) {
1058
+ if (panel) {
1059
+ panel.items().hide();
1060
+ showToolbar(panel, id);
1061
+
1062
+ var contentAreaRect, panelRect, result, userConstainHandler;
1063
+
1064
+ showPanel(panel);
1065
+ panel.items().hide();
1066
+ showToolbar(panel, id);
1067
+
1068
+ userConstainHandler = editor.settings.inline_toolbar_position_handler;
1069
+ contentAreaRect = Measure.getContentAreaRect(editor);
1070
+ panelRect = DOM.getRect(panel.getEl());
1071
+
1072
+ result = Layout.calc(currentRect, contentAreaRect, panelRect);
1073
+
1074
+ if (result) {
1075
+ panelRect = result.rect;
1076
+ movePanelTo(panel, Layout.userConstrain(userConstainHandler, currentRect, contentAreaRect, panelRect));
1077
+
1078
+ togglePositionClass(panel, result.position);
1079
+ }
1080
+ }
1081
+ };
1082
+
1083
+ var show = function (editor, id, targetRect, toolbars) {
1084
+ if (!panel) {
1085
+ panel = create(editor, toolbars);
1086
+ panel.renderTo(document.body).reflow().moveTo(targetRect.x, targetRect.y);
1087
+ editor.nodeChanged();
1088
+ }
1089
+
1090
+ showPanelAt(panel, id, editor, targetRect);
1091
+ };
1092
+
1093
+ var hide = function () {
1094
+ if (panel) {
1095
+ panel.hide();
1096
+ }
1097
+ };
1098
+
1099
+ var focus = function () {
1100
+ if (panel) {
1101
+ panel.find('toolbar:visible').eq(0).each(function (item) {
1102
+ item.focus(true);
1103
+ });
1104
+ }
1105
+ };
1106
+
1107
+ var remove = function () {
1108
+ if (panel) {
1109
+ panel.remove();
1110
+ panel = null;
1111
+ }
1112
+ };
1113
+
1114
+ var inForm = function () {
1115
+ return panel && panel.visible() && hasFormVisible();
1116
+ };
1117
+
1118
+ return {
1119
+ show: show,
1120
+ showForm: showForm,
1121
+ inForm: inForm,
1122
+ hide: hide,
1123
+ focus: focus,
1124
+ remove: remove
1125
+ };
1126
+ });
1127
+
1128
+ /**
1129
+ * Conversions.js
1130
+ *
1131
+ * Released under LGPL License.
1132
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1133
+ *
1134
+ * License: http://www.tinymce.com/license
1135
+ * Contributing: http://www.tinymce.com/contributing
1136
+ */
1137
+
1138
+ define('tinymce/inlite/file/Conversions', [
1139
+ 'global!tinymce.util.Promise'
1140
+ ], function (Promise) {
1141
+ var blobToBase64 = function (blob) {
1142
+ return new Promise(function(resolve) {
1143
+ var reader = new FileReader();
1144
+
1145
+ reader.onloadend = function() {
1146
+ resolve(reader.result.split(',')[1]);
1147
+ };
1148
+
1149
+ reader.readAsDataURL(blob);
1150
+ });
1151
+ };
1152
+
1153
+ return {
1154
+ blobToBase64: blobToBase64
1155
+ };
1156
+ });
1157
+
1158
+
1159
+
1160
+ /**
1161
+ * Picker.js
1162
+ *
1163
+ * Released under LGPL License.
1164
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1165
+ *
1166
+ * License: http://www.tinymce.com/license
1167
+ * Contributing: http://www.tinymce.com/contributing
1168
+ */
1169
+
1170
+ define('tinymce/inlite/file/Picker', [
1171
+ 'global!tinymce.util.Promise'
1172
+ ], function (Promise) {
1173
+ var pickFile = function () {
1174
+ return new Promise(function (resolve) {
1175
+ var fileInput;
1176
+
1177
+ fileInput = document.createElement("input");
1178
+ fileInput.type = "file";
1179
+ fileInput.style.position = 'fixed';
1180
+ fileInput.style.left = 0;
1181
+ fileInput.style.top = 0;
1182
+ fileInput.style.opacity = 0.001;
1183
+ document.body.appendChild(fileInput);
1184
+
1185
+ fileInput.onchange = function(e) {
1186
+ resolve(Array.prototype.slice.call(e.target.files));
1187
+ };
1188
+
1189
+ fileInput.click();
1190
+ fileInput.parentNode.removeChild(fileInput);
1191
+ });
1192
+ };
1193
+
1194
+ return {
1195
+ pickFile: pickFile
1196
+ };
1197
+ });
1198
+
1199
+
1200
+
1201
+ /**
1202
+ * Buttons.js
1203
+ *
1204
+ * Released under LGPL License.
1205
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1206
+ *
1207
+ * License: http://www.tinymce.com/license
1208
+ * Contributing: http://www.tinymce.com/contributing
1209
+ */
1210
+
1211
+ define('tinymce/inlite/ui/Buttons', [
1212
+ 'tinymce/inlite/ui/Panel',
1213
+ 'tinymce/inlite/file/Conversions',
1214
+ 'tinymce/inlite/file/Picker',
1215
+ 'tinymce/inlite/core/Actions'
1216
+ ], function (Panel, Conversions, Picker, Actions) {
1217
+ var addHeaderButtons = function (editor) {
1218
+ var formatBlock = function (name) {
1219
+ return function () {
1220
+ Actions.formatBlock(editor, name);
1221
+ };
1222
+ };
1223
+
1224
+ for (var i = 1; i < 6; i++) {
1225
+ var name = 'h' + i;
1226
+
1227
+ editor.addButton(name, {
1228
+ text: name.toUpperCase(),
1229
+ tooltip: 'Heading ' + i,
1230
+ stateSelector: name,
1231
+ onclick: formatBlock(name),
1232
+ onPostRender: function () {
1233
+ // TODO: Remove this hack that produces bold H1-H6 when we have proper icons
1234
+ var span = this.getEl().firstChild.firstChild;
1235
+ span.style.fontWeight = 'bold';
1236
+ }
1237
+ });
1238
+ }
1239
+ };
1240
+
1241
+ var addToEditor = function (editor) {
1242
+ editor.addButton('quicklink', {
1243
+ icon: 'link',
1244
+ tooltip: 'Insert/Edit link',
1245
+ stateSelector: 'a[href]',
1246
+ onclick: function () {
1247
+ Panel.showForm(editor, 'quicklink');
1248
+ }
1249
+ });
1250
+
1251
+ editor.addButton('quickimage', {
1252
+ icon: 'image',
1253
+ tooltip: 'Insert image',
1254
+ onclick: function () {
1255
+ Picker.pickFile().then(function (files) {
1256
+ var blob = files[0];
1257
+
1258
+ Conversions.blobToBase64(blob).then(function (base64) {
1259
+ Actions.insertBlob(editor, base64, blob);
1260
+ });
1261
+ });
1262
+ }
1263
+ });
1264
+
1265
+ editor.addButton('quicktable', {
1266
+ icon: 'table',
1267
+ tooltip: 'Insert table',
1268
+ onclick: function () {
1269
+ Panel.hide();
1270
+ Actions.insertTable(editor, 2, 2);
1271
+ }
1272
+ });
1273
+
1274
+ addHeaderButtons(editor);
1275
+ };
1276
+
1277
+ return {
1278
+ addToEditor: addToEditor
1279
+ };
1280
+ });
1281
+
1282
+ defineGlobal("global!tinymce.EditorManager", tinymce.EditorManager);
1283
+ /**
1284
+ * SkinLoader.js
1285
+ *
1286
+ * Released under LGPL License.
1287
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1288
+ *
1289
+ * License: http://www.tinymce.com/license
1290
+ * Contributing: http://www.tinymce.com/contributing
1291
+ */
1292
+
1293
+ define('tinymce/inlite/core/SkinLoader', [
1294
+ 'global!tinymce.EditorManager',
1295
+ 'global!tinymce.DOM'
1296
+ ], function (EditorManager, DOM) {
1297
+ var fireSkinLoaded = function (editor, callback) {
1298
+ var done = function () {
1299
+ editor.fire('SkinLoaded');
1300
+ callback();
1301
+ };
1302
+
1303
+ if (editor.initialized) {
1304
+ done();
1305
+ } else {
1306
+ editor.on('init', done);
1307
+ }
1308
+ };
1309
+
1310
+ var load = function (editor, skin, callback) {
1311
+ var baseUrl = EditorManager.baseURL;
1312
+ var skinUrl = baseUrl + '/skins/' + skin;
1313
+
1314
+ var done = function () {
1315
+ fireSkinLoaded(editor, callback);
1316
+ };
1317
+
1318
+ DOM.styleSheetLoader.load(skinUrl + '/skin.min.css', done);
1319
+ editor.contentCSS.push(skinUrl + '/content.inline.min.css');
1320
+ };
1321
+
1322
+ return {
1323
+ load: load
1324
+ };
1325
+ });
1326
+
1327
+
1328
+
1329
+ /**
1330
+ * Matcher.js
1331
+ *
1332
+ * Released under LGPL License.
1333
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1334
+ *
1335
+ * License: http://www.tinymce.com/license
1336
+ * Contributing: http://www.tinymce.com/contributing
1337
+ */
1338
+
1339
+ define('tinymce/inlite/core/Matcher', [
1340
+ ], function () {
1341
+ // result :: String, Rect -> Matcher.result
1342
+ var result = function (id, rect) {
1343
+ return {
1344
+ id: id,
1345
+ rect: rect
1346
+ };
1347
+ };
1348
+
1349
+ // match :: Editor, [(Editor -> Matcher.result | Null)] -> Matcher.result | Null
1350
+ var match = function (editor, matchers) {
1351
+ for (var i = 0; i < matchers.length; i++) {
1352
+ var f = matchers[i];
1353
+ var result = f(editor);
1354
+
1355
+ if (result) {
1356
+ return result;
1357
+ }
1358
+ }
1359
+
1360
+ return null;
1361
+ };
1362
+
1363
+ return {
1364
+ match: match,
1365
+ result: result
1366
+ };
1367
+ });
1368
+
1369
+ /**
1370
+ * SelectionMatcher.js
1371
+ *
1372
+ * Released under LGPL License.
1373
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1374
+ *
1375
+ * License: http://www.tinymce.com/license
1376
+ * Contributing: http://www.tinymce.com/contributing
1377
+ */
1378
+
1379
+ define('tinymce/inlite/core/SelectionMatcher', [
1380
+ 'tinymce/inlite/core/Matcher',
1381
+ 'tinymce/inlite/core/Measure'
1382
+ ], function (Matcher, Measure) {
1383
+ // textSelection :: String -> (Editor -> Matcher.result | Null)
1384
+ var textSelection = function (id) {
1385
+ return function (editor) {
1386
+ if (!editor.selection.isCollapsed()) {
1387
+ return Matcher.result(id, Measure.getSelectionRect(editor));
1388
+ }
1389
+
1390
+ return null;
1391
+ };
1392
+ };
1393
+
1394
+ // emptyTextBlock :: [Elements], String -> (Editor -> Matcher.result | Null)
1395
+ var emptyTextBlock = function (elements, id) {
1396
+ return function (editor) {
1397
+ var i, textBlockElementsMap = editor.schema.getTextBlockElements();
1398
+
1399
+ for (i = 0; i < elements.length; i++) {
1400
+ if (elements[i].nodeName === 'TABLE') {
1401
+ return null;
1402
+ }
1403
+ }
1404
+
1405
+ for (i = 0; i < elements.length; i++) {
1406
+ if (elements[i].nodeName in textBlockElementsMap) {
1407
+ if (editor.dom.isEmpty(elements[i])) {
1408
+ return Matcher.result(id, Measure.getSelectionRect(editor));
1409
+ }
1410
+
1411
+ return null;
1412
+ }
1413
+ }
1414
+
1415
+ return null;
1416
+ };
1417
+ };
1418
+
1419
+ return {
1420
+ textSelection: textSelection,
1421
+ emptyTextBlock: emptyTextBlock
1422
+ };
1423
+ });
1424
+
1425
+ /**
1426
+ * ElementMatcher.js
1427
+ *
1428
+ * Released under LGPL License.
1429
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1430
+ *
1431
+ * License: http://www.tinymce.com/license
1432
+ * Contributing: http://www.tinymce.com/contributing
1433
+ */
1434
+
1435
+ define('tinymce/inlite/core/ElementMatcher', [
1436
+ 'tinymce/inlite/core/Matcher',
1437
+ 'tinymce/inlite/core/Measure'
1438
+ ], function (Matcher, Measure) {
1439
+ // element :: Element, [PredicateId] -> (Editor -> Matcher.result | Null)
1440
+ var element = function (element, predicateIds) {
1441
+ return function (editor) {
1442
+ for (var i = 0; i < predicateIds.length; i++) {
1443
+ if (predicateIds[i].predicate(element)) {
1444
+ return Matcher.result(predicateIds[i].id, Measure.getElementRect(editor, element));
1445
+ }
1446
+ }
1447
+
1448
+ return null;
1449
+ };
1450
+ };
1451
+
1452
+ // parent :: [Elements], [PredicateId] -> (Editor -> Matcher.result | Null)
1453
+ var parent = function (elements, predicateIds) {
1454
+ return function (editor) {
1455
+ for (var i = 0; i < elements.length; i++) {
1456
+ for (var x = 0; x < predicateIds.length; x++) {
1457
+ if (predicateIds[x].predicate(elements[i])) {
1458
+ return Matcher.result(predicateIds[x].id, Measure.getElementRect(editor, elements[i]));
1459
+ }
1460
+ }
1461
+ }
1462
+
1463
+ return null;
1464
+ };
1465
+ };
1466
+
1467
+ return {
1468
+ element: element,
1469
+ parent: parent
1470
+ };
1471
+ });
1472
+
1473
+ /**
1474
+ * Arr.js
1475
+ *
1476
+ * Released under LGPL License.
1477
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1478
+ *
1479
+ * License: http://www.tinymce.com/license
1480
+ * Contributing: http://www.tinymce.com/contributing
1481
+ */
1482
+
1483
+ define('tinymce/inlite/alien/Arr', [
1484
+ ], function () {
1485
+ var flatten = function (arr) {
1486
+ return arr.reduce(function (results, item) {
1487
+ return Array.isArray(item) ? results.concat(flatten(item)) : results.concat(item);
1488
+ }, []);
1489
+ };
1490
+
1491
+ return {
1492
+ flatten: flatten
1493
+ };
1494
+ });
1495
+
1496
+ /**
1497
+ * PredicateId.js
1498
+ *
1499
+ * Released under LGPL License.
1500
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1501
+ *
1502
+ * License: http://www.tinymce.com/license
1503
+ * Contributing: http://www.tinymce.com/contributing
1504
+ */
1505
+
1506
+ define('tinymce/inlite/core/PredicateId', [
1507
+ 'global!tinymce.util.Tools'
1508
+ ], function (Tools) {
1509
+ var create = function (id, predicate) {
1510
+ return {
1511
+ id: id,
1512
+ predicate: predicate
1513
+ };
1514
+ };
1515
+
1516
+ // fromContextToolbars :: [ContextToolbar] -> [PredicateId]
1517
+ var fromContextToolbars = function (toolbars) {
1518
+ return Tools.map(toolbars, function (toolbar) {
1519
+ return create(toolbar.id, toolbar.predicate);
1520
+ });
1521
+ };
1522
+
1523
+ return {
1524
+ create: create,
1525
+ fromContextToolbars: fromContextToolbars
1526
+ };
1527
+ });
1528
+
1529
+ /**
1530
+ * Theme.js
1531
+ *
1532
+ * Released under LGPL License.
1533
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
1534
+ *
1535
+ * License: http://www.tinymce.com/license
1536
+ * Contributing: http://www.tinymce.com/contributing
1537
+ */
1538
+
1539
+ define('tinymce/inlite/Theme', [
1540
+ 'global!tinymce.ThemeManager',
1541
+ 'global!tinymce.util.Delay',
1542
+ 'tinymce/inlite/ui/Panel',
1543
+ 'tinymce/inlite/ui/Buttons',
1544
+ 'tinymce/inlite/core/SkinLoader',
1545
+ 'tinymce/inlite/core/SelectionMatcher',
1546
+ 'tinymce/inlite/core/ElementMatcher',
1547
+ 'tinymce/inlite/core/Matcher',
1548
+ 'tinymce/inlite/alien/Arr',
1549
+ 'tinymce/inlite/core/PredicateId'
1550
+ ], function(ThemeManager, Delay, Panel, Buttons, SkinLoader, SelectionMatcher, ElementMatcher, Matcher, Arr, PredicateId) {
1551
+ var getSelectionElements = function (editor) {
1552
+ var node = editor.selection.getNode();
1553
+ var elms = editor.dom.getParents(node);
1554
+ return elms;
1555
+ };
1556
+
1557
+ var createToolbar = function (editor, selector, id, items) {
1558
+ var selectorPredicate = function (elm) {
1559
+ return editor.dom.is(elm, selector);
1560
+ };
1561
+
1562
+ return {
1563
+ predicate: selectorPredicate,
1564
+ id: id,
1565
+ items: items
1566
+ };
1567
+ };
1568
+
1569
+ var getToolbars = function (editor) {
1570
+ var contextToolbars = editor.contextToolbars;
1571
+
1572
+ return Arr.flatten([
1573
+ contextToolbars ? contextToolbars : [],
1574
+ createToolbar(editor, 'img', 'image', 'alignleft aligncenter alignright')
1575
+ ]);
1576
+ };
1577
+
1578
+ var findMatchResult = function (editor, toolbars) {
1579
+ var result, elements, contextToolbarsPredicateIds;
1580
+
1581
+ elements = getSelectionElements(editor);
1582
+ contextToolbarsPredicateIds = PredicateId.fromContextToolbars(toolbars);
1583
+
1584
+ result = Matcher.match(editor, [
1585
+ ElementMatcher.element(elements[0], contextToolbarsPredicateIds),
1586
+ SelectionMatcher.textSelection('text'),
1587
+ SelectionMatcher.emptyTextBlock(elements, 'insert'),
1588
+ ElementMatcher.parent(elements, contextToolbarsPredicateIds)
1589
+ ]);
1590
+
1591
+ return result && result.rect ? result : null;
1592
+ };
1593
+
1594
+ var togglePanel = function (editor) {
1595
+ var toggle = function () {
1596
+ var toolbars = getToolbars(editor);
1597
+ var result = findMatchResult(editor, toolbars);
1598
+ result ? Panel.show(editor, result.id, result.rect, toolbars) : Panel.hide();
1599
+ };
1600
+
1601
+ return function () {
1602
+ if (!editor.removed) {
1603
+ toggle();
1604
+ }
1605
+ };
1606
+ };
1607
+
1608
+ var ignoreWhenFormIsVisible = function (f) {
1609
+ return function () {
1610
+ if (!Panel.inForm()) {
1611
+ f();
1612
+ }
1613
+ };
1614
+ };
1615
+
1616
+ var bindContextualToolbarsEvents = function (editor) {
1617
+ var throttledTogglePanel = Delay.throttle(togglePanel(editor), 0);
1618
+ var throttledTogglePanelWhenNotInForm = Delay.throttle(ignoreWhenFormIsVisible(togglePanel(editor)), 0);
1619
+
1620
+ editor.on('blur hide ObjectResizeStart', Panel.hide);
1621
+ editor.on('click', throttledTogglePanel);
1622
+ editor.on('nodeChange mouseup', throttledTogglePanelWhenNotInForm);
1623
+ editor.on('ResizeEditor ResizeWindow keyup', throttledTogglePanel);
1624
+ editor.on('remove', Panel.remove);
1625
+
1626
+ editor.shortcuts.add('Alt+F10', '', Panel.focus);
1627
+ };
1628
+
1629
+ var overrideLinkShortcut = function (editor) {
1630
+ editor.shortcuts.remove('meta+k');
1631
+ editor.shortcuts.add('meta+k', '', function () {
1632
+ var toolbars = getToolbars(editor);
1633
+ var result = result = Matcher.match(editor, [
1634
+ SelectionMatcher.textSelection('quicklink')
1635
+ ]);
1636
+
1637
+ if (result) {
1638
+ Panel.show(editor, result.id, result.rect, toolbars);
1639
+ }
1640
+ });
1641
+ };
1642
+
1643
+ var renderInlineUI = function (editor) {
1644
+ var skinName = editor.settings.skin || 'lightgray';
1645
+
1646
+ SkinLoader.load(editor, skinName, function () {
1647
+ bindContextualToolbarsEvents(editor);
1648
+ overrideLinkShortcut(editor);
1649
+ });
1650
+
1651
+ return {};
1652
+ };
1653
+
1654
+ var fail = function (message) {
1655
+ throw new Error(message);
1656
+ };
1657
+
1658
+ ThemeManager.add('inlite', function (editor) {
1659
+ Buttons.addToEditor(editor);
1660
+
1661
+ var renderUI = function () {
1662
+ return editor.inline ? renderInlineUI(editor) : fail('inlite theme only supports inline mode.');
1663
+ };
1664
+
1665
+ return {
1666
+ renderUI: renderUI
1667
+ };
1668
+ });
1669
+
1670
+ return function() {};
1671
+ });
1672
+
1673
+ dem('tinymce/inlite/Theme')();
1674
+ })();