PageRenderTime 85ms CodeModel.GetById 16ms app.highlight 58ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-includes/js/tinymce/themes/inlite/theme.js

https://bitbucket.org/skyarch-iijima/wordpress
JavaScript | 2168 lines | 1485 code | 335 blank | 348 comment | 120 complexity | 0708be140b906ad238f8080afd1fd280 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file