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