home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / js / tinymce / themes / modern / theme.js next >
Encoding:
JavaScript  |  2017-05-24  |  43.9 KB  |  1,682 lines

  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.themes.modern.Theme","global!window","tinymce.core.AddOnManager","tinymce.core.EditorManager","tinymce.core.Env","tinymce.core.ui.Api","tinymce.themes.modern.modes.Iframe","tinymce.themes.modern.modes.Inline","tinymce.themes.modern.ui.ProgressState","tinymce.themes.modern.ui.Resize","global!tinymce.util.Tools.resolve","tinymce.core.dom.DOMUtils","tinymce.core.ui.Factory","tinymce.core.util.Tools","tinymce.themes.modern.ui.A11y","tinymce.themes.modern.ui.Branding","tinymce.themes.modern.ui.ContextToolbars","tinymce.themes.modern.ui.Menubar","tinymce.themes.modern.ui.Sidebar","tinymce.themes.modern.ui.SkinLoaded","tinymce.themes.modern.ui.Toolbar","tinymce.core.ui.FloatPanel","tinymce.core.ui.Throbber","tinymce.core.util.Delay","tinymce.core.geom.Rect"]
  85. jsc*/
  86. defineGlobal("global!window", window);
  87. defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
  88. /**
  89.  * ResolveGlobal.js
  90.  *
  91.  * Released under LGPL License.
  92.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  93.  *
  94.  * License: http://www.tinymce.com/license
  95.  * Contributing: http://www.tinymce.com/contributing
  96.  */
  97.  
  98. define(
  99.   'tinymce.core.AddOnManager',
  100.   [
  101.     'global!tinymce.util.Tools.resolve'
  102.   ],
  103.   function (resolve) {
  104.     return resolve('tinymce.AddOnManager');
  105.   }
  106. );
  107.  
  108. /**
  109.  * ResolveGlobal.js
  110.  *
  111.  * Released under LGPL License.
  112.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  113.  *
  114.  * License: http://www.tinymce.com/license
  115.  * Contributing: http://www.tinymce.com/contributing
  116.  */
  117.  
  118. define(
  119.   'tinymce.core.EditorManager',
  120.   [
  121.     'global!tinymce.util.Tools.resolve'
  122.   ],
  123.   function (resolve) {
  124.     return resolve('tinymce.EditorManager');
  125.   }
  126. );
  127.  
  128. /**
  129.  * ResolveGlobal.js
  130.  *
  131.  * Released under LGPL License.
  132.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  133.  *
  134.  * License: http://www.tinymce.com/license
  135.  * Contributing: http://www.tinymce.com/contributing
  136.  */
  137.  
  138. define(
  139.   'tinymce.core.Env',
  140.   [
  141.     'global!tinymce.util.Tools.resolve'
  142.   ],
  143.   function (resolve) {
  144.     return resolve('tinymce.Env');
  145.   }
  146. );
  147.  
  148. /**
  149.  * ResolveGlobal.js
  150.  *
  151.  * Released under LGPL License.
  152.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  153.  *
  154.  * License: http://www.tinymce.com/license
  155.  * Contributing: http://www.tinymce.com/contributing
  156.  */
  157.  
  158. define(
  159.   'tinymce.core.ui.Api',
  160.   [
  161.     'global!tinymce.util.Tools.resolve'
  162.   ],
  163.   function (resolve) {
  164.     return resolve('tinymce.ui.Api');
  165.   }
  166. );
  167.  
  168. /**
  169.  * ResolveGlobal.js
  170.  *
  171.  * Released under LGPL License.
  172.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  173.  *
  174.  * License: http://www.tinymce.com/license
  175.  * Contributing: http://www.tinymce.com/contributing
  176.  */
  177.  
  178. define(
  179.   'tinymce.core.dom.DOMUtils',
  180.   [
  181.     'global!tinymce.util.Tools.resolve'
  182.   ],
  183.   function (resolve) {
  184.     return resolve('tinymce.dom.DOMUtils');
  185.   }
  186. );
  187.  
  188. /**
  189.  * ResolveGlobal.js
  190.  *
  191.  * Released under LGPL License.
  192.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  193.  *
  194.  * License: http://www.tinymce.com/license
  195.  * Contributing: http://www.tinymce.com/contributing
  196.  */
  197.  
  198. define(
  199.   'tinymce.core.ui.Factory',
  200.   [
  201.     'global!tinymce.util.Tools.resolve'
  202.   ],
  203.   function (resolve) {
  204.     return resolve('tinymce.ui.Factory');
  205.   }
  206. );
  207.  
  208. /**
  209.  * ResolveGlobal.js
  210.  *
  211.  * Released under LGPL License.
  212.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  213.  *
  214.  * License: http://www.tinymce.com/license
  215.  * Contributing: http://www.tinymce.com/contributing
  216.  */
  217.  
  218. define(
  219.   'tinymce.core.util.Tools',
  220.   [
  221.     'global!tinymce.util.Tools.resolve'
  222.   ],
  223.   function (resolve) {
  224.     return resolve('tinymce.util.Tools');
  225.   }
  226. );
  227.  
  228. /**
  229.  * A11y.js
  230.  *
  231.  * Released under LGPL License.
  232.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  233.  *
  234.  * License: http://www.tinymce.com/license
  235.  * Contributing: http://www.tinymce.com/contributing
  236.  */
  237.  
  238. define(
  239.   'tinymce.themes.modern.ui.A11y',
  240.   [
  241.   ],
  242.   function () {
  243.     var focus = function (panel, type) {
  244.       return function () {
  245.         var item = panel.find(type)[0];
  246.  
  247.         if (item) {
  248.           item.focus(true);
  249.         }
  250.       };
  251.     };
  252.  
  253.     var addKeys = function (editor, panel) {
  254.       editor.shortcuts.add('Alt+F9', '', focus(panel, 'menubar'));
  255.       editor.shortcuts.add('Alt+F10,F10', '', focus(panel, 'toolbar'));
  256.       editor.shortcuts.add('Alt+F11', '', focus(panel, 'elementpath'));
  257.       panel.on('cancel', function () {
  258.         editor.focus();
  259.       });
  260.     };
  261.  
  262.     return {
  263.       addKeys: addKeys
  264.     };
  265.   }
  266. );
  267.  
  268. /**
  269.  * Branding.js
  270.  *
  271.  * Released under LGPL License.
  272.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  273.  *
  274.  * License: http://www.tinymce.com/license
  275.  * Contributing: http://www.tinymce.com/contributing
  276.  */
  277.  
  278. define(
  279.   'tinymce.themes.modern.ui.Branding',
  280.   [
  281.     'tinymce.core.dom.DOMUtils'
  282.   ],
  283.   function (DOMUtils) {
  284.     var DOM = DOMUtils.DOM;
  285.  
  286.     var reposition = function (editor, poweredByElm, hasStatusbar) {
  287.       return function () {
  288.         var iframeWidth = editor.getContentAreaContainer().querySelector('iframe').offsetWidth;
  289.         var scrollbarWidth = Math.max(iframeWidth - editor.getDoc().documentElement.offsetWidth, 0);
  290.  
  291.         DOM.setStyle(poweredByElm, 'right', scrollbarWidth + 'px');
  292.         if (hasStatusbar) {
  293.           DOM.setStyle(poweredByElm, 'top', '-16px');
  294.         } else {
  295.           DOM.setStyle(poweredByElm, 'bottom', '1px');
  296.         }
  297.       };
  298.     };
  299.  
  300.     var hide = function (poweredByElm) {
  301.       return function () {
  302.         DOM.hide(poweredByElm);
  303.       };
  304.     };
  305.  
  306.     var setupReposition = function (editor, poweredByElm, hasStatusbar) {
  307.       reposition(editor, poweredByElm, hasStatusbar)();
  308.       editor.on('NodeChange ResizeEditor', reposition(editor, poweredByElm, hasStatusbar));
  309.     };
  310.  
  311.     var appendToStatusbar = function (editor, poweredByElm, statusbarElm) {
  312.       statusbarElm.appendChild(poweredByElm);
  313.       setupReposition(editor, poweredByElm, true);
  314.     };
  315.  
  316.     var appendToContainer = function (editor, poweredByElm) {
  317.       editor.getContainer().appendChild(poweredByElm);
  318.       setupReposition(editor, poweredByElm, false);
  319.     };
  320.  
  321.     var setupEventListeners = function (editor) {
  322.       editor.on('SkinLoaded', function () {
  323.         var poweredByElm = DOM.create('div', { 'class': 'mce-branding-powered-by' });
  324.         var statusbarElm = editor.getContainer().querySelector('.mce-statusbar');
  325.  
  326.         if (statusbarElm) {
  327.           appendToStatusbar(editor, poweredByElm, statusbarElm);
  328.         } else {
  329.           appendToContainer(editor, poweredByElm);
  330.         }
  331.  
  332.         DOM.bind(poweredByElm, 'click', hide(poweredByElm));
  333.       });
  334.     };
  335.  
  336.     var setup = function (editor) {
  337.       if (editor.settings.branding !== false) {
  338.         setupEventListeners(editor);
  339.       }
  340.     };
  341.  
  342.     return {
  343.       setup: setup
  344.     };
  345.   }
  346. );
  347.  
  348. /**
  349.  * ResolveGlobal.js
  350.  *
  351.  * Released under LGPL License.
  352.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  353.  *
  354.  * License: http://www.tinymce.com/license
  355.  * Contributing: http://www.tinymce.com/contributing
  356.  */
  357.  
  358. define(
  359.   'tinymce.core.util.Delay',
  360.   [
  361.     'global!tinymce.util.Tools.resolve'
  362.   ],
  363.   function (resolve) {
  364.     return resolve('tinymce.util.Delay');
  365.   }
  366. );
  367.  
  368. /**
  369.  * ResolveGlobal.js
  370.  *
  371.  * Released under LGPL License.
  372.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  373.  *
  374.  * License: http://www.tinymce.com/license
  375.  * Contributing: http://www.tinymce.com/contributing
  376.  */
  377.  
  378. define(
  379.   'tinymce.core.geom.Rect',
  380.   [
  381.     'global!tinymce.util.Tools.resolve'
  382.   ],
  383.   function (resolve) {
  384.     return resolve('tinymce.geom.Rect');
  385.   }
  386. );
  387.  
  388. /**
  389.  * Toolbar.js
  390.  *
  391.  * Released under LGPL License.
  392.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  393.  *
  394.  * License: http://www.tinymce.com/license
  395.  * Contributing: http://www.tinymce.com/contributing
  396.  */
  397.  
  398. define(
  399.   'tinymce.themes.modern.ui.Toolbar',
  400.   [
  401.     'tinymce.core.util.Tools',
  402.     'tinymce.core.ui.Factory'
  403.   ],
  404.   function (Tools, Factory) {
  405.     var defaultToolbar = "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | " +
  406.       "bullist numlist outdent indent | link image";
  407.  
  408.     var createToolbar = function (editor, items, size) {
  409.       var toolbarItems = [], buttonGroup;
  410.  
  411.       if (!items) {
  412.         return;
  413.       }
  414.  
  415.       Tools.each(items.split(/[ ,]/), function (item) {
  416.         var itemName;
  417.  
  418.         var bindSelectorChanged = function () {
  419.           var selection = editor.selection;
  420.  
  421.           if (item.settings.stateSelector) {
  422.             selection.selectorChanged(item.settings.stateSelector, function (state) {
  423.               item.active(state);
  424.             }, true);
  425.           }
  426.  
  427.           if (item.settings.disabledStateSelector) {
  428.             selection.selectorChanged(item.settings.disabledStateSelector, function (state) {
  429.               item.disabled(state);
  430.             });
  431.           }
  432.         };
  433.  
  434.         if (item == "|") {
  435.           buttonGroup = null;
  436.         } else {
  437.           if (!buttonGroup) {
  438.             buttonGroup = { type: 'buttongroup', items: [] };
  439.             toolbarItems.push(buttonGroup);
  440.           }
  441.  
  442.           if (editor.buttons[item]) {
  443.             // TODO: Move control creation to some UI class
  444.             itemName = item;
  445.             item = editor.buttons[itemName];
  446.  
  447.             if (typeof item == "function") {
  448.               item = item();
  449.             }
  450.  
  451.             item.type = item.type || 'button';
  452.             item.size = size;
  453.  
  454.             item = Factory.create(item);
  455.             buttonGroup.items.push(item);
  456.  
  457.             if (editor.initialized) {
  458.               bindSelectorChanged();
  459.             } else {
  460.               editor.on('init', bindSelectorChanged);
  461.             }
  462.           }
  463.         }
  464.       });
  465.  
  466.       return {
  467.         type: 'toolbar',
  468.         layout: 'flow',
  469.         items: toolbarItems
  470.       };
  471.     };
  472.  
  473.     /**
  474.      * Creates the toolbars from config and returns a toolbar array.
  475.      *
  476.      * @param {String} size Optional toolbar item size.
  477.      * @return {Array} Array with toolbars.
  478.      */
  479.     var createToolbars = function (editor, size) {
  480.       var toolbars = [], settings = editor.settings;
  481.  
  482.       var addToolbar = function (items) {
  483.         if (items) {
  484.           toolbars.push(createToolbar(editor, items, size));
  485.           return true;
  486.         }
  487.       };
  488.  
  489.       // Convert toolbar array to multiple options
  490.       if (Tools.isArray(settings.toolbar)) {
  491.         // Empty toolbar array is the same as a disabled toolbar
  492.         if (settings.toolbar.length === 0) {
  493.           return;
  494.         }
  495.  
  496.         Tools.each(settings.toolbar, function (toolbar, i) {
  497.           settings["toolbar" + (i + 1)] = toolbar;
  498.         });
  499.  
  500.         delete settings.toolbar;
  501.       }
  502.  
  503.       // Generate toolbar<n>
  504.       for (var i = 1; i < 10; i++) {
  505.         if (!addToolbar(settings["toolbar" + i])) {
  506.           break;
  507.         }
  508.       }
  509.  
  510.       // Generate toolbar or default toolbar unless it's disabled
  511.       if (!toolbars.length && settings.toolbar !== false) {
  512.         addToolbar(settings.toolbar || defaultToolbar);
  513.       }
  514.  
  515.       if (toolbars.length) {
  516.         return {
  517.           type: 'panel',
  518.           layout: 'stack',
  519.           classes: "toolbar-grp",
  520.           ariaRoot: true,
  521.           ariaRemember: true,
  522.           items: toolbars
  523.         };
  524.       }
  525.     };
  526.  
  527.     return {
  528.       createToolbar: createToolbar,
  529.       createToolbars: createToolbars
  530.     };
  531.   }
  532. );
  533.  
  534. /**
  535.  * ContextToolbars.js
  536.  *
  537.  * Released under LGPL License.
  538.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  539.  *
  540.  * License: http://www.tinymce.com/license
  541.  * Contributing: http://www.tinymce.com/contributing
  542.  */
  543.  
  544. define(
  545.   'tinymce.themes.modern.ui.ContextToolbars',
  546.   [
  547.     'tinymce.core.dom.DOMUtils',
  548.     'tinymce.core.util.Tools',
  549.     'tinymce.core.util.Delay',
  550.     'tinymce.core.ui.Factory',
  551.     'tinymce.core.geom.Rect',
  552.     'tinymce.themes.modern.ui.Toolbar'
  553.   ],
  554.   function (DOMUtils, Tools, Delay, Factory, Rect, Toolbar) {
  555.     var DOM = DOMUtils.DOM;
  556.  
  557.     var toClientRect = function (geomRect) {
  558.       return {
  559.         left: geomRect.x,
  560.         top: geomRect.y,
  561.         width: geomRect.w,
  562.         height: geomRect.h,
  563.         right: geomRect.x + geomRect.w,
  564.         bottom: geomRect.y + geomRect.h
  565.       };
  566.     };
  567.  
  568.     var hideAllFloatingPanels = function (editor) {
  569.       Tools.each(editor.contextToolbars, function (toolbar) {
  570.         if (toolbar.panel) {
  571.           toolbar.panel.hide();
  572.         }
  573.       });
  574.     };
  575.  
  576.     var movePanelTo = function (panel, pos) {
  577.       panel.moveTo(pos.left, pos.top);
  578.     };
  579.  
  580.     var togglePositionClass = function (panel, relPos, predicate) {
  581.       relPos = relPos ? relPos.substr(0, 2) : '';
  582.  
  583.       Tools.each({
  584.         t: 'down',
  585.         b: 'up'
  586.       }, function (cls, pos) {
  587.         panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(0, 1)));
  588.       });
  589.  
  590.       Tools.each({
  591.         l: 'left',
  592.         r: 'right'
  593.       }, function (cls, pos) {
  594.         panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(1, 1)));
  595.       });
  596.     };
  597.  
  598.     var userConstrain = function (handler, x, y, elementRect, contentAreaRect, panelRect) {
  599.       panelRect = toClientRect({ x: x, y: y, w: panelRect.w, h: panelRect.h });
  600.  
  601.       if (handler) {
  602.         panelRect = handler({
  603.           elementRect: toClientRect(elementRect),
  604.           contentAreaRect: toClientRect(contentAreaRect),
  605.           panelRect: panelRect
  606.         });
  607.       }
  608.  
  609.       return panelRect;
  610.     };
  611.  
  612.     var addContextualToolbars = function (editor) {
  613.       var scrollContainer, settings = editor.settings;
  614.  
  615.       var getContextToolbars = function () {
  616.         return editor.contextToolbars || [];
  617.       };
  618.  
  619.       var getElementRect = function (elm) {
  620.         var pos, targetRect, root;
  621.  
  622.         pos = DOM.getPos(editor.getContentAreaContainer());
  623.         targetRect = editor.dom.getRect(elm);
  624.         root = editor.dom.getRoot();
  625.  
  626.         // Adjust targetPos for scrolling in the editor
  627.         if (root.nodeName === 'BODY') {
  628.           targetRect.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
  629.           targetRect.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
  630.         }
  631.  
  632.         targetRect.x += pos.x;
  633.         targetRect.y += pos.y;
  634.  
  635.         return targetRect;
  636.       };
  637.  
  638.       var reposition = function (match, shouldShow) {
  639.         var relPos, panelRect, elementRect, contentAreaRect, panel, relRect, testPositions, smallElementWidthThreshold;
  640.         var handler = settings.inline_toolbar_position_handler;
  641.  
  642.         if (editor.removed) {
  643.           return;
  644.         }
  645.  
  646.         if (!match || !match.toolbar.panel) {
  647.           hideAllFloatingPanels(editor);
  648.           return;
  649.         }
  650.  
  651.         testPositions = [
  652.           'bc-tc', 'tc-bc',
  653.           'tl-bl', 'bl-tl',
  654.           'tr-br', 'br-tr'
  655.         ];
  656.  
  657.         panel = match.toolbar.panel;
  658.  
  659.         // Only show the panel on some events not for example nodeChange since that fires when context menu is opened
  660.         if (shouldShow) {
  661.           panel.show();
  662.         }
  663.  
  664.         elementRect = getElementRect(match.element);
  665.         panelRect = DOM.getRect(panel.getEl());
  666.         contentAreaRect = DOM.getRect(editor.getContentAreaContainer() || editor.getBody());
  667.         smallElementWidthThreshold = 25;
  668.  
  669.         if (DOM.getStyle(match.element, 'display', true) !== 'inline') {
  670.           // We need to use these instead of the rect values since the style
  671.           // size properites might not be the same as the real size for a table
  672.           elementRect.w = match.element.clientWidth;
  673.           elementRect.h = match.element.clientHeight;
  674.         }
  675.  
  676.         if (!editor.inline) {
  677.           contentAreaRect.w = editor.getDoc().documentElement.offsetWidth;
  678.         }
  679.  
  680.         // Inflate the elementRect so it doesn't get placed above resize handles
  681.         if (editor.selection.controlSelection.isResizable(match.element) && elementRect.w < smallElementWidthThreshold) {
  682.           elementRect = Rect.inflate(elementRect, 0, 8);
  683.         }
  684.  
  685.         relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, testPositions);
  686.         elementRect = Rect.clamp(elementRect, contentAreaRect);
  687.  
  688.         if (relPos) {
  689.           relRect = Rect.relativePosition(panelRect, elementRect, relPos);
  690.           movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
  691.         } else {
  692.           // Allow overflow below the editor to avoid placing toolbars ontop of tables
  693.           contentAreaRect.h += panelRect.h;
  694.  
  695.           elementRect = Rect.intersect(contentAreaRect, elementRect);
  696.           if (elementRect) {
  697.             relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, [
  698.               'bc-tc', 'bl-tl', 'br-tr'
  699.             ]);
  700.  
  701.             if (relPos) {
  702.               relRect = Rect.relativePosition(panelRect, elementRect, relPos);
  703.               movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
  704.             } else {
  705.               movePanelTo(panel, userConstrain(handler, elementRect.x, elementRect.y, elementRect, contentAreaRect, panelRect));
  706.             }
  707.           } else {
  708.             panel.hide();
  709.           }
  710.         }
  711.  
  712.         togglePositionClass(panel, relPos, function (pos1, pos2) {
  713.           return pos1 === pos2;
  714.         });
  715.  
  716.         //drawRect(contentAreaRect, 'blue');
  717.         //drawRect(elementRect, 'red');
  718.         //drawRect(panelRect, 'green');
  719.       };
  720.  
  721.       var repositionHandler = function (show) {
  722.         return function () {
  723.           var execute = function () {
  724.             if (editor.selection) {
  725.               reposition(findFrontMostMatch(editor.selection.getNode()), show);
  726.             }
  727.           };
  728.  
  729.           Delay.requestAnimationFrame(execute);
  730.         };
  731.       };
  732.  
  733.       var bindScrollEvent = function () {
  734.         if (!scrollContainer) {
  735.           scrollContainer = editor.selection.getScrollContainer() || editor.getWin();
  736.           DOM.bind(scrollContainer, 'scroll', repositionHandler(true));
  737.  
  738.           editor.on('remove', function () {
  739.             DOM.unbind(scrollContainer, 'scroll');
  740.           });
  741.         }
  742.       };
  743.  
  744.       var showContextToolbar = function (match) {
  745.         var panel;
  746.  
  747.         if (match.toolbar.panel) {
  748.           match.toolbar.panel.show();
  749.           reposition(match);
  750.           return;
  751.         }
  752.  
  753.         bindScrollEvent();
  754.  
  755.         panel = Factory.create({
  756.           type: 'floatpanel',
  757.           role: 'dialog',
  758.           classes: 'tinymce tinymce-inline arrow',
  759.           ariaLabel: 'Inline toolbar',
  760.           layout: 'flex',
  761.           direction: 'column',
  762.           align: 'stretch',
  763.           autohide: false,
  764.           autofix: true,
  765.           fixed: true,
  766.           border: 1,
  767.           items: Toolbar.createToolbar(editor, match.toolbar.items),
  768.           oncancel: function () {
  769.             editor.focus();
  770.           }
  771.         });
  772.  
  773.         match.toolbar.panel = panel;
  774.         panel.renderTo(document.body).reflow();
  775.         reposition(match);
  776.       };
  777.  
  778.       var hideAllContextToolbars = function () {
  779.         Tools.each(getContextToolbars(), function (toolbar) {
  780.           if (toolbar.panel) {
  781.             toolbar.panel.hide();
  782.           }
  783.         });
  784.       };
  785.  
  786.       var findFrontMostMatch = function (targetElm) {
  787.         var i, y, parentsAndSelf, toolbars = getContextToolbars();
  788.  
  789.         parentsAndSelf = editor.$(targetElm).parents().add(targetElm);
  790.         for (i = parentsAndSelf.length - 1; i >= 0; i--) {
  791.           for (y = toolbars.length - 1; y >= 0; y--) {
  792.             if (toolbars[y].predicate(parentsAndSelf[i])) {
  793.               return {
  794.                 toolbar: toolbars[y],
  795.                 element: parentsAndSelf[i]
  796.               };
  797.             }
  798.           }
  799.         }
  800.  
  801.         return null;
  802.       };
  803.  
  804.       editor.on('click keyup setContent ObjectResized', function (e) {
  805.         // Only act on partial inserts
  806.         if (e.type === 'setcontent' && !e.selection) {
  807.           return;
  808.         }
  809.  
  810.         // Needs to be delayed to avoid Chrome img focus out bug
  811.         Delay.setEditorTimeout(editor, function () {
  812.           var match;
  813.  
  814.           match = findFrontMostMatch(editor.selection.getNode());
  815.           if (match) {
  816.             hideAllContextToolbars();
  817.             showContextToolbar(match);
  818.           } else {
  819.             hideAllContextToolbars();
  820.           }
  821.         });
  822.       });
  823.  
  824.       editor.on('blur hide contextmenu', hideAllContextToolbars);
  825.  
  826.       editor.on('ObjectResizeStart', function () {
  827.         var match = findFrontMostMatch(editor.selection.getNode());
  828.  
  829.         if (match && match.toolbar.panel) {
  830.           match.toolbar.panel.hide();
  831.         }
  832.       });
  833.  
  834.       editor.on('ResizeEditor ResizeWindow', repositionHandler(true));
  835.       editor.on('nodeChange', repositionHandler(false));
  836.  
  837.       editor.on('remove', function () {
  838.         Tools.each(getContextToolbars(), function (toolbar) {
  839.           if (toolbar.panel) {
  840.             toolbar.panel.remove();
  841.           }
  842.         });
  843.  
  844.         editor.contextToolbars = {};
  845.       });
  846.  
  847.       editor.shortcuts.add('ctrl+shift+e > ctrl+shift+p', '', function () {
  848.         var match = findFrontMostMatch(editor.selection.getNode());
  849.         if (match && match.toolbar.panel) {
  850.           match.toolbar.panel.items()[0].focus();
  851.         }
  852.       });
  853.     };
  854.  
  855.     return {
  856.       addContextualToolbars: addContextualToolbars
  857.     };
  858.   }
  859. );
  860.  
  861. /**
  862.  * Menubar.js
  863.  *
  864.  * Released under LGPL License.
  865.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  866.  *
  867.  * License: http://www.tinymce.com/license
  868.  * Contributing: http://www.tinymce.com/contributing
  869.  */
  870.  
  871. define(
  872.   'tinymce.themes.modern.ui.Menubar',
  873.   [
  874.     'tinymce.core.util.Tools'
  875.   ],
  876.   function (Tools) {
  877.     var defaultMenus = {
  878.       file: { title: 'File', items: 'newdocument' },
  879.       edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall' },
  880.       insert: { title: 'Insert', items: '|' },
  881.       view: { title: 'View', items: 'visualaid |' },
  882.       format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript | formats | removeformat' },
  883.       table: { title: 'Table' },
  884.       tools: { title: 'Tools' }
  885.     };
  886.  
  887.     var createMenuItem = function (menuItems, name) {
  888.       var menuItem;
  889.  
  890.       if (name == '|') {
  891.         return { text: '|' };
  892.       }
  893.  
  894.       menuItem = menuItems[name];
  895.  
  896.       return menuItem;
  897.     };
  898.  
  899.     var createMenu = function (editorMenuItems, settings, context) {
  900.       var menuButton, menu, menuItems, isUserDefined, removedMenuItems;
  901.  
  902.       removedMenuItems = Tools.makeMap((settings.removed_menuitems || '').split(/[ ,]/));
  903.  
  904.       // User defined menu
  905.       if (settings.menu) {
  906.         menu = settings.menu[context];
  907.         isUserDefined = true;
  908.       } else {
  909.         menu = defaultMenus[context];
  910.       }
  911.  
  912.       if (menu) {
  913.         menuButton = { text: menu.title };
  914.         menuItems = [];
  915.  
  916.         // Default/user defined items
  917.         Tools.each((menu.items || '').split(/[ ,]/), function (item) {
  918.           var menuItem = createMenuItem(editorMenuItems, item);
  919.  
  920.           if (menuItem && !removedMenuItems[item]) {
  921.             menuItems.push(createMenuItem(editorMenuItems, item));
  922.           }
  923.         });
  924.  
  925.         // Added though context
  926.         if (!isUserDefined) {
  927.           Tools.each(editorMenuItems, function (menuItem) {
  928.             if (menuItem.context == context) {
  929.               if (menuItem.separator == 'before') {
  930.                 menuItems.push({ text: '|' });
  931.               }
  932.  
  933.               if (menuItem.prependToContext) {
  934.                 menuItems.unshift(menuItem);
  935.               } else {
  936.                 menuItems.push(menuItem);
  937.               }
  938.  
  939.               if (menuItem.separator == 'after') {
  940.                 menuItems.push({ text: '|' });
  941.               }
  942.             }
  943.           });
  944.         }
  945.  
  946.         for (var i = 0; i < menuItems.length; i++) {
  947.           if (menuItems[i].text == '|') {
  948.             if (i === 0 || i == menuItems.length - 1) {
  949.               menuItems.splice(i, 1);
  950.             }
  951.           }
  952.         }
  953.  
  954.         menuButton.menu = menuItems;
  955.  
  956.         if (!menuButton.menu.length) {
  957.           return null;
  958.         }
  959.       }
  960.  
  961.       return menuButton;
  962.     };
  963.  
  964.     var createMenuButtons = function (editor) {
  965.       var name, menuButtons = [], settings = editor.settings;
  966.  
  967.       var defaultMenuBar = [];
  968.       if (settings.menu) {
  969.         for (name in settings.menu) {
  970.           defaultMenuBar.push(name);
  971.         }
  972.       } else {
  973.         for (name in defaultMenus) {
  974.           defaultMenuBar.push(name);
  975.         }
  976.       }
  977.  
  978.       var enabledMenuNames = typeof settings.menubar == "string" ? settings.menubar.split(/[ ,]/) : defaultMenuBar;
  979.       for (var i = 0; i < enabledMenuNames.length; i++) {
  980.         var menu = enabledMenuNames[i];
  981.         menu = createMenu(editor.menuItems, editor.settings, menu);
  982.  
  983.         if (menu) {
  984.           menuButtons.push(menu);
  985.         }
  986.       }
  987.  
  988.       return menuButtons;
  989.     };
  990.  
  991.     return {
  992.       createMenuButtons: createMenuButtons
  993.     };
  994.   }
  995. );
  996.  
  997. /**
  998.  * Resize.js
  999.  *
  1000.  * Released under LGPL License.
  1001.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1002.  *
  1003.  * License: http://www.tinymce.com/license
  1004.  * Contributing: http://www.tinymce.com/contributing
  1005.  */
  1006.  
  1007. define(
  1008.   'tinymce.themes.modern.ui.Resize',
  1009.   [
  1010.     'tinymce.core.dom.DOMUtils'
  1011.   ],
  1012.   function (DOMUtils) {
  1013.     var DOM = DOMUtils.DOM;
  1014.     var getSize = function (elm) {
  1015.       return {
  1016.         width: elm.clientWidth,
  1017.         height: elm.clientHeight
  1018.       };
  1019.     };
  1020.  
  1021.     var resizeTo = function (editor, width, height) {
  1022.       var containerElm, iframeElm, containerSize, iframeSize, settings = editor.settings;
  1023.  
  1024.       containerElm = editor.getContainer();
  1025.       iframeElm = editor.getContentAreaContainer().firstChild;
  1026.       containerSize = getSize(containerElm);
  1027.       iframeSize = getSize(iframeElm);
  1028.  
  1029.       if (width !== null) {
  1030.         width = Math.max(settings.min_width || 100, width);
  1031.         width = Math.min(settings.max_width || 0xFFFF, width);
  1032.  
  1033.         DOM.setStyle(containerElm, 'width', width + (containerSize.width - iframeSize.width));
  1034.         DOM.setStyle(iframeElm, 'width', width);
  1035.       }
  1036.  
  1037.       height = Math.max(settings.min_height || 100, height);
  1038.       height = Math.min(settings.max_height || 0xFFFF, height);
  1039.       DOM.setStyle(iframeElm, 'height', height);
  1040.  
  1041.       editor.fire('ResizeEditor');
  1042.     };
  1043.  
  1044.     var resizeBy = function (editor, dw, dh) {
  1045.       var elm = editor.getContentAreaContainer();
  1046.       resizeTo(editor, elm.clientWidth + dw, elm.clientHeight + dh);
  1047.     };
  1048.  
  1049.     return {
  1050.       resizeTo: resizeTo,
  1051.       resizeBy: resizeBy
  1052.     };
  1053.   }
  1054. );
  1055.  
  1056. /**
  1057.  * Sidebar.js
  1058.  *
  1059.  * Released under LGPL License.
  1060.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1061.  *
  1062.  * License: http://www.tinymce.com/license
  1063.  * Contributing: http://www.tinymce.com/contributing
  1064.  */
  1065.  
  1066. define(
  1067.   'tinymce.themes.modern.ui.Sidebar',
  1068.   [
  1069.     'tinymce.core.util.Tools',
  1070.     'tinymce.core.ui.Factory',
  1071.     'tinymce.core.Env'
  1072.   ],
  1073.   function (Tools, Factory, Env) {
  1074.     var api = function (elm) {
  1075.       return {
  1076.         element: function () {
  1077.           return elm;
  1078.         }
  1079.       };
  1080.     };
  1081.  
  1082.     var trigger = function (sidebar, panel, callbackName) {
  1083.       var callback = sidebar.settings[callbackName];
  1084.       if (callback) {
  1085.         callback(api(panel.getEl('body')));
  1086.       }
  1087.     };
  1088.  
  1089.     var hidePanels = function (name, container, sidebars) {
  1090.       Tools.each(sidebars, function (sidebar) {
  1091.         var panel = container.items().filter('#' + sidebar.name)[0];
  1092.  
  1093.         if (panel && panel.visible() && sidebar.name !== name) {
  1094.           trigger(sidebar, panel, 'onhide');
  1095.           panel.visible(false);
  1096.         }
  1097.       });
  1098.     };
  1099.  
  1100.     var deactivateButtons = function (toolbar) {
  1101.       toolbar.items().each(function (ctrl) {
  1102.         ctrl.active(false);
  1103.       });
  1104.     };
  1105.  
  1106.     var findSidebar = function (sidebars, name) {
  1107.       return Tools.grep(sidebars, function (sidebar) {
  1108.         return sidebar.name === name;
  1109.       })[0];
  1110.     };
  1111.  
  1112.     var showPanel = function (editor, name, sidebars) {
  1113.       return function (e) {
  1114.         var btnCtrl = e.control;
  1115.         var container = btnCtrl.parents().filter('panel')[0];
  1116.         var panel = container.find('#' + name)[0];
  1117.         var sidebar = findSidebar(sidebars, name);
  1118.  
  1119.         hidePanels(name, container, sidebars);
  1120.         deactivateButtons(btnCtrl.parent());
  1121.  
  1122.         if (panel && panel.visible()) {
  1123.           trigger(sidebar, panel, 'onhide');
  1124.           panel.hide();
  1125.           btnCtrl.active(false);
  1126.         } else {
  1127.           if (panel) {
  1128.             panel.show();
  1129.             trigger(sidebar, panel, 'onshow');
  1130.           } else {
  1131.             panel = Factory.create({
  1132.               type: 'container',
  1133.               name: name,
  1134.               layout: 'stack',
  1135.               classes: 'sidebar-panel',
  1136.               html: ''
  1137.             });
  1138.  
  1139.             container.prepend(panel);
  1140.             trigger(sidebar, panel, 'onrender');
  1141.             trigger(sidebar, panel, 'onshow');
  1142.           }
  1143.  
  1144.           btnCtrl.active(true);
  1145.         }
  1146.  
  1147.         editor.fire('ResizeEditor');
  1148.       };
  1149.     };
  1150.  
  1151.     var isModernBrowser = function () {
  1152.       return !Env.ie || Env.ie >= 11;
  1153.     };
  1154.  
  1155.     var hasSidebar = function (editor) {
  1156.       return isModernBrowser() && editor.sidebars ? editor.sidebars.length > 0 : false;
  1157.     };
  1158.  
  1159.     var createSidebar = function (editor) {
  1160.       var buttons = Tools.map(editor.sidebars, function (sidebar) {
  1161.         var settings = sidebar.settings;
  1162.  
  1163.         return {
  1164.           type: 'button',
  1165.           icon: settings.icon,
  1166.           image: settings.image,
  1167.           tooltip: settings.tooltip,
  1168.           onclick: showPanel(editor, sidebar.name, editor.sidebars)
  1169.         };
  1170.       });
  1171.  
  1172.       return {
  1173.         type: 'panel',
  1174.         name: 'sidebar',
  1175.         layout: 'stack',
  1176.         classes: 'sidebar',
  1177.         items: [
  1178.           {
  1179.             type: 'toolbar',
  1180.             layout: 'stack',
  1181.             classes: 'sidebar-toolbar',
  1182.             items: buttons
  1183.           }
  1184.         ]
  1185.       };
  1186.     };
  1187.  
  1188.     return {
  1189.       hasSidebar: hasSidebar,
  1190.       createSidebar: createSidebar
  1191.     };
  1192.   }
  1193. );
  1194. /**
  1195.  * SkinLoaded.js
  1196.  *
  1197.  * Released under LGPL License.
  1198.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1199.  *
  1200.  * License: http://www.tinymce.com/license
  1201.  * Contributing: http://www.tinymce.com/contributing
  1202.  */
  1203.  
  1204. define(
  1205.   'tinymce.themes.modern.ui.SkinLoaded', [
  1206.   ],
  1207.   function () {
  1208.     var fireSkinLoaded = function (editor) {
  1209.       var done = function () {
  1210.         editor._skinLoaded = true;
  1211.         editor.fire('SkinLoaded');
  1212.       };
  1213.  
  1214.       return function () {
  1215.         if (editor.initialized) {
  1216.           done();
  1217.         } else {
  1218.           editor.on('init', done);
  1219.         }
  1220.       };
  1221.     };
  1222.  
  1223.     return {
  1224.       fireSkinLoaded: fireSkinLoaded
  1225.     };
  1226.   }
  1227. );
  1228.  
  1229. /**
  1230.  * Iframe.js
  1231.  *
  1232.  * Released under LGPL License.
  1233.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1234.  *
  1235.  * License: http://www.tinymce.com/license
  1236.  * Contributing: http://www.tinymce.com/contributing
  1237.  */
  1238.  
  1239. define(
  1240.   'tinymce.themes.modern.modes.Iframe',
  1241.   [
  1242.     'tinymce.core.dom.DOMUtils',
  1243.     'tinymce.core.ui.Factory',
  1244.     'tinymce.core.util.Tools',
  1245.     'tinymce.themes.modern.ui.A11y',
  1246.     'tinymce.themes.modern.ui.Branding',
  1247.     'tinymce.themes.modern.ui.ContextToolbars',
  1248.     'tinymce.themes.modern.ui.Menubar',
  1249.     'tinymce.themes.modern.ui.Resize',
  1250.     'tinymce.themes.modern.ui.Sidebar',
  1251.     'tinymce.themes.modern.ui.SkinLoaded',
  1252.     'tinymce.themes.modern.ui.Toolbar'
  1253.   ],
  1254.   function (DOMUtils, Factory, Tools, A11y, Branding, ContextToolbars, Menubar, Resize, Sidebar, SkinLoaded, Toolbar) {
  1255.     var DOM = DOMUtils.DOM;
  1256.  
  1257.     var switchMode = function (panel) {
  1258.       return function (e) {
  1259.         panel.find('*').disabled(e.mode === 'readonly');
  1260.       };
  1261.     };
  1262.  
  1263.     var editArea = function (border) {
  1264.       return {
  1265.         type: 'panel',
  1266.         name: 'iframe',
  1267.         layout: 'stack',
  1268.         classes: 'edit-area',
  1269.         border: border,
  1270.         html: ''
  1271.       };
  1272.     };
  1273.  
  1274.     var editAreaContainer = function (editor) {
  1275.       return {
  1276.         type: 'panel',
  1277.         layout: 'stack',
  1278.         classes: 'edit-aria-container',
  1279.         border: '1 0 0 0',
  1280.         items: [
  1281.           editArea('0'),
  1282.           Sidebar.createSidebar(editor)
  1283.         ]
  1284.       };
  1285.     };
  1286.  
  1287.     var render = function (editor, theme, args) {
  1288.       var panel, resizeHandleCtrl, startSize, settings = editor.settings;
  1289.  
  1290.       if (args.skinUiCss) {
  1291.         DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
  1292.       }
  1293.  
  1294.       panel = theme.panel = Factory.create({
  1295.         type: 'panel',
  1296.         role: 'application',
  1297.         classes: 'tinymce',
  1298.         style: 'visibility: hidden',
  1299.         layout: 'stack',
  1300.         border: 1,
  1301.         items: [
  1302.           settings.menubar === false ? null : { type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor) },
  1303.           Toolbar.createToolbars(editor, settings.toolbar_items_size),
  1304.           Sidebar.hasSidebar(editor) ? editAreaContainer(editor) : editArea('1 0 0 0')
  1305.         ]
  1306.       });
  1307.  
  1308.       if (settings.resize !== false) {
  1309.         resizeHandleCtrl = {
  1310.           type: 'resizehandle',
  1311.           direction: settings.resize,
  1312.  
  1313.           onResizeStart: function () {
  1314.             var elm = editor.getContentAreaContainer().firstChild;
  1315.  
  1316.             startSize = {
  1317.               width: elm.clientWidth,
  1318.               height: elm.clientHeight
  1319.             };
  1320.           },
  1321.  
  1322.           onResize: function (e) {
  1323.             if (settings.resize === 'both') {
  1324.               Resize.resizeTo(editor, startSize.width + e.deltaX, startSize.height + e.deltaY);
  1325.             } else {
  1326.               Resize.resizeTo(editor, null, startSize.height + e.deltaY);
  1327.             }
  1328.           }
  1329.         };
  1330.       }
  1331.  
  1332.       // Add statusbar if needed
  1333.       if (settings.statusbar !== false) {
  1334.         panel.add({
  1335.           type: 'panel', name: 'statusbar', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', ariaRoot: true, items: [
  1336.             { type: 'elementpath', editor: editor },
  1337.             resizeHandleCtrl
  1338.           ]
  1339.         });
  1340.       }
  1341.  
  1342.       editor.fire('BeforeRenderUI');
  1343.       editor.on('SwitchMode', switchMode(panel));
  1344.       panel.renderBefore(args.targetNode).reflow();
  1345.  
  1346.       if (settings.readonly) {
  1347.         editor.setMode('readonly');
  1348.       }
  1349.  
  1350.       if (args.width) {
  1351.         DOM.setStyle(panel.getEl(), 'width', args.width);
  1352.       }
  1353.  
  1354.       // Remove the panel when the editor is removed
  1355.       editor.on('remove', function () {
  1356.         panel.remove();
  1357.         panel = null;
  1358.       });
  1359.  
  1360.       // Add accesibility shortcuts
  1361.       A11y.addKeys(editor, panel);
  1362.       ContextToolbars.addContextualToolbars(editor);
  1363.       Branding.setup(editor);
  1364.  
  1365.       return {
  1366.         iframeContainer: panel.find('#iframe')[0].getEl(),
  1367.         editorContainer: panel.getEl()
  1368.       };
  1369.     };
  1370.  
  1371.     return {
  1372.       render: render
  1373.     };
  1374.   }
  1375. );
  1376.  
  1377. /**
  1378.  * ResolveGlobal.js
  1379.  *
  1380.  * Released under LGPL License.
  1381.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  1382.  *
  1383.  * License: http://www.tinymce.com/license
  1384.  * Contributing: http://www.tinymce.com/contributing
  1385.  */
  1386.  
  1387. define(
  1388.   'tinymce.core.ui.FloatPanel',
  1389.   [
  1390.     'global!tinymce.util.Tools.resolve'
  1391.   ],
  1392.   function (resolve) {
  1393.     return resolve('tinymce.ui.FloatPanel');
  1394.   }
  1395. );
  1396.  
  1397. /**
  1398.  * Inline.js
  1399.  *
  1400.  * Released under LGPL License.
  1401.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1402.  *
  1403.  * License: http://www.tinymce.com/license
  1404.  * Contributing: http://www.tinymce.com/contributing
  1405.  */
  1406.  
  1407. define(
  1408.   'tinymce.themes.modern.modes.Inline',
  1409.   [
  1410.     'tinymce.core.util.Tools',
  1411.     'tinymce.core.ui.Factory',
  1412.     'tinymce.core.dom.DOMUtils',
  1413.     'tinymce.core.ui.FloatPanel',
  1414.     'tinymce.themes.modern.ui.Toolbar',
  1415.     'tinymce.themes.modern.ui.Menubar',
  1416.     'tinymce.themes.modern.ui.ContextToolbars',
  1417.     'tinymce.themes.modern.ui.A11y',
  1418.     'tinymce.themes.modern.ui.SkinLoaded'
  1419.   ],
  1420.   function (Tools, Factory, DOMUtils, FloatPanel, Toolbar, Menubar, ContextToolbars, A11y, SkinLoaded) {
  1421.     var render = function (editor, theme, args) {
  1422.       var panel, inlineToolbarContainer, settings = editor.settings;
  1423.       var DOM = DOMUtils.DOM;
  1424.  
  1425.       if (settings.fixed_toolbar_container) {
  1426.         inlineToolbarContainer = DOM.select(settings.fixed_toolbar_container)[0];
  1427.       }
  1428.  
  1429.       var reposition = function () {
  1430.         if (panel && panel.moveRel && panel.visible() && !panel._fixed) {
  1431.           // TODO: This is kind of ugly and doesn't handle multiple scrollable elements
  1432.           var scrollContainer = editor.selection.getScrollContainer(), body = editor.getBody();
  1433.           var deltaX = 0, deltaY = 0;
  1434.  
  1435.           if (scrollContainer) {
  1436.             var bodyPos = DOM.getPos(body), scrollContainerPos = DOM.getPos(scrollContainer);
  1437.  
  1438.             deltaX = Math.max(0, scrollContainerPos.x - bodyPos.x);
  1439.             deltaY = Math.max(0, scrollContainerPos.y - bodyPos.y);
  1440.           }
  1441.  
  1442.           panel.fixed(false).moveRel(body, editor.rtl ? ['tr-br', 'br-tr'] : ['tl-bl', 'bl-tl', 'tr-br']).moveBy(deltaX, deltaY);
  1443.         }
  1444.       };
  1445.  
  1446.       var show = function () {
  1447.         if (panel) {
  1448.           panel.show();
  1449.           reposition();
  1450.           DOM.addClass(editor.getBody(), 'mce-edit-focus');
  1451.         }
  1452.       };
  1453.  
  1454.       var hide = function () {
  1455.         if (panel) {
  1456.           // We require two events as the inline float panel based toolbar does not have autohide=true
  1457.           panel.hide();
  1458.  
  1459.           // All other autohidden float panels will be closed below.
  1460.           FloatPanel.hideAll();
  1461.  
  1462.           DOM.removeClass(editor.getBody(), 'mce-edit-focus');
  1463.         }
  1464.       };
  1465.  
  1466.       var render = function () {
  1467.         if (panel) {
  1468.           if (!panel.visible()) {
  1469.             show();
  1470.           }
  1471.  
  1472.           return;
  1473.         }
  1474.  
  1475.         // Render a plain panel inside the inlineToolbarContainer if it's defined
  1476.         panel = theme.panel = Factory.create({
  1477.           type: inlineToolbarContainer ? 'panel' : 'floatpanel',
  1478.           role: 'application',
  1479.           classes: 'tinymce tinymce-inline',
  1480.           layout: 'flex',
  1481.           direction: 'column',
  1482.           align: 'stretch',
  1483.           autohide: false,
  1484.           autofix: true,
  1485.           fixed: !!inlineToolbarContainer,
  1486.           border: 1,
  1487.           items: [
  1488.             settings.menubar === false ? null : { type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor) },
  1489.             Toolbar.createToolbars(editor, settings.toolbar_items_size)
  1490.           ]
  1491.         });
  1492.  
  1493.         // Add statusbar
  1494.         /*if (settings.statusbar !== false) {
  1495.           panel.add({type: 'panel', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', items: [
  1496.             {type: 'elementpath'}
  1497.           ]});
  1498.         }*/
  1499.  
  1500.         editor.fire('BeforeRenderUI');
  1501.         panel.renderTo(inlineToolbarContainer || document.body).reflow();
  1502.  
  1503.         A11y.addKeys(editor, panel);
  1504.         show();
  1505.         ContextToolbars.addContextualToolbars(editor);
  1506.  
  1507.         editor.on('nodeChange', reposition);
  1508.         editor.on('activate', show);
  1509.         editor.on('deactivate', hide);
  1510.  
  1511.         editor.nodeChanged();
  1512.       };
  1513.  
  1514.       settings.content_editable = true;
  1515.  
  1516.       editor.on('focus', function () {
  1517.         // Render only when the CSS file has been loaded
  1518.         if (args.skinUiCss) {
  1519.           DOM.styleSheetLoader.load(args.skinUiCss, render, render);
  1520.         } else {
  1521.           render();
  1522.         }
  1523.       });
  1524.  
  1525.       editor.on('blur hide', hide);
  1526.  
  1527.       // Remove the panel when the editor is removed
  1528.       editor.on('remove', function () {
  1529.         if (panel) {
  1530.           panel.remove();
  1531.           panel = null;
  1532.         }
  1533.       });
  1534.  
  1535.       // Preload skin css
  1536.       if (args.skinUiCss) {
  1537.         DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
  1538.       }
  1539.  
  1540.       return {};
  1541.     };
  1542.  
  1543.     return {
  1544.       render: render
  1545.     };
  1546.   }
  1547. );
  1548.  
  1549. /**
  1550.  * ResolveGlobal.js
  1551.  *
  1552.  * Released under LGPL License.
  1553.  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
  1554.  *
  1555.  * License: http://www.tinymce.com/license
  1556.  * Contributing: http://www.tinymce.com/contributing
  1557.  */
  1558.  
  1559. define(
  1560.   'tinymce.core.ui.Throbber',
  1561.   [
  1562.     'global!tinymce.util.Tools.resolve'
  1563.   ],
  1564.   function (resolve) {
  1565.     return resolve('tinymce.ui.Throbber');
  1566.   }
  1567. );
  1568.  
  1569. /**
  1570.  * ProgressState.js
  1571.  *
  1572.  * Released under LGPL License.
  1573.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1574.  *
  1575.  * License: http://www.tinymce.com/license
  1576.  * Contributing: http://www.tinymce.com/contributing
  1577.  */
  1578.  
  1579. define(
  1580.   'tinymce.themes.modern.ui.ProgressState',
  1581.   [
  1582.     'tinymce.core.ui.Throbber'
  1583.   ],
  1584.   function (Throbber) {
  1585.     var setup = function (editor, theme) {
  1586.       var throbber;
  1587.  
  1588.       editor.on('ProgressState', function (e) {
  1589.         throbber = throbber || new Throbber(theme.panel.getEl('body'));
  1590.  
  1591.         if (e.state) {
  1592.           throbber.show(e.time);
  1593.         } else {
  1594.           throbber.hide();
  1595.         }
  1596.       });
  1597.     };
  1598.  
  1599.     return {
  1600.       setup: setup
  1601.     };
  1602.   }
  1603. );
  1604.  
  1605. /**
  1606.  * Theme.js
  1607.  *
  1608.  * Released under LGPL License.
  1609.  * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
  1610.  *
  1611.  * License: http://www.tinymce.com/license
  1612.  * Contributing: http://www.tinymce.com/contributing
  1613.  */
  1614.  
  1615. define(
  1616.   'tinymce.themes.modern.Theme',
  1617.   [
  1618.     'global!window',
  1619.     'tinymce.core.AddOnManager',
  1620.     'tinymce.core.EditorManager',
  1621.     'tinymce.core.Env',
  1622.     'tinymce.core.ui.Api',
  1623.     'tinymce.themes.modern.modes.Iframe',
  1624.     'tinymce.themes.modern.modes.Inline',
  1625.     'tinymce.themes.modern.ui.ProgressState',
  1626.     'tinymce.themes.modern.ui.Resize'
  1627.   ],
  1628.   function (window, AddOnManager, EditorManager, Env, Api, Iframe, Inline, ProgressState, Resize) {
  1629.     var ThemeManager = AddOnManager.ThemeManager;
  1630.  
  1631.     Api.appendTo(window.tinymce ? window.tinymce : {});
  1632.  
  1633.     var renderUI = function (editor, theme, args) {
  1634.       var settings = editor.settings;
  1635.       var skin = settings.skin !== false ? settings.skin || 'lightgray' : false;
  1636.  
  1637.       if (skin) {
  1638.         var skinUrl = settings.skin_url;
  1639.  
  1640.         if (skinUrl) {
  1641.           skinUrl = editor.documentBaseURI.toAbsolute(skinUrl);
  1642.         } else {
  1643.           skinUrl = EditorManager.baseURL + '/skins/' + skin;
  1644.         }
  1645.  
  1646.         args.skinUiCss = skinUrl + '/skin.min.css';
  1647.  
  1648.         // Load content.min.css or content.inline.min.css
  1649.         editor.contentCSS.push(skinUrl + '/content' + (editor.inline ? '.inline' : '') + '.min.css');
  1650.       }
  1651.  
  1652.       ProgressState.setup(editor, theme);
  1653.  
  1654.       if (settings.inline) {
  1655.         return Inline.render(editor, theme, args);
  1656.       }
  1657.  
  1658.       return Iframe.render(editor, theme, args);
  1659.     };
  1660.  
  1661.     ThemeManager.add('modern', function (editor) {
  1662.       return {
  1663.         renderUI: function (args) {
  1664.           return renderUI(editor, this, args);
  1665.         },
  1666.         resizeTo: function (w, h) {
  1667.           return Resize.resizeTo(editor, w, h);
  1668.         },
  1669.         resizeBy: function (dw, dh) {
  1670.           return Resize.resizeBy(editor, dw, dh);
  1671.         }
  1672.       };
  1673.     });
  1674.  
  1675.     return function () {
  1676.     };
  1677.   }
  1678. );
  1679.  
  1680. dem('tinymce.themes.modern.Theme')();
  1681. })();
  1682.