plugin.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /**
  2. * Copyright (c) Tiny Technologies, Inc. All rights reserved.
  3. * Licensed under the LGPL or a commercial license.
  4. * For LGPL see License.txt in the project root for license information.
  5. * For commercial licenses see https://www.tiny.cloud/
  6. *
  7. * Version: 5.7.0 (2021-02-10)
  8. */
  9. (function () {
  10. 'use strict';
  11. var Cell = function (initial) {
  12. var value = initial;
  13. var get = function () {
  14. return value;
  15. };
  16. var set = function (v) {
  17. value = v;
  18. };
  19. return {
  20. get: get,
  21. set: set
  22. };
  23. };
  24. var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  25. var get = function (fullscreenState) {
  26. return {
  27. isFullscreen: function () {
  28. return fullscreenState.get() !== null;
  29. }
  30. };
  31. };
  32. var noop = function () {
  33. };
  34. var compose = function (fa, fb) {
  35. return function () {
  36. var args = [];
  37. for (var _i = 0; _i < arguments.length; _i++) {
  38. args[_i] = arguments[_i];
  39. }
  40. return fa(fb.apply(null, args));
  41. };
  42. };
  43. var compose1 = function (fbc, fab) {
  44. return function (a) {
  45. return fbc(fab(a));
  46. };
  47. };
  48. var constant = function (value) {
  49. return function () {
  50. return value;
  51. };
  52. };
  53. function curry(fn) {
  54. var initialArgs = [];
  55. for (var _i = 1; _i < arguments.length; _i++) {
  56. initialArgs[_i - 1] = arguments[_i];
  57. }
  58. return function () {
  59. var restArgs = [];
  60. for (var _i = 0; _i < arguments.length; _i++) {
  61. restArgs[_i] = arguments[_i];
  62. }
  63. var all = initialArgs.concat(restArgs);
  64. return fn.apply(null, all);
  65. };
  66. }
  67. var never = constant(false);
  68. var always = constant(true);
  69. var none = function () {
  70. return NONE;
  71. };
  72. var NONE = function () {
  73. var eq = function (o) {
  74. return o.isNone();
  75. };
  76. var call = function (thunk) {
  77. return thunk();
  78. };
  79. var id = function (n) {
  80. return n;
  81. };
  82. var me = {
  83. fold: function (n, _s) {
  84. return n();
  85. },
  86. is: never,
  87. isSome: never,
  88. isNone: always,
  89. getOr: id,
  90. getOrThunk: call,
  91. getOrDie: function (msg) {
  92. throw new Error(msg || 'error: getOrDie called on none.');
  93. },
  94. getOrNull: constant(null),
  95. getOrUndefined: constant(undefined),
  96. or: id,
  97. orThunk: call,
  98. map: none,
  99. each: noop,
  100. bind: none,
  101. exists: never,
  102. forall: always,
  103. filter: none,
  104. equals: eq,
  105. equals_: eq,
  106. toArray: function () {
  107. return [];
  108. },
  109. toString: constant('none()')
  110. };
  111. return me;
  112. }();
  113. var some = function (a) {
  114. var constant_a = constant(a);
  115. var self = function () {
  116. return me;
  117. };
  118. var bind = function (f) {
  119. return f(a);
  120. };
  121. var me = {
  122. fold: function (n, s) {
  123. return s(a);
  124. },
  125. is: function (v) {
  126. return a === v;
  127. },
  128. isSome: always,
  129. isNone: never,
  130. getOr: constant_a,
  131. getOrThunk: constant_a,
  132. getOrDie: constant_a,
  133. getOrNull: constant_a,
  134. getOrUndefined: constant_a,
  135. or: self,
  136. orThunk: self,
  137. map: function (f) {
  138. return some(f(a));
  139. },
  140. each: function (f) {
  141. f(a);
  142. },
  143. bind: bind,
  144. exists: bind,
  145. forall: bind,
  146. filter: function (f) {
  147. return f(a) ? me : NONE;
  148. },
  149. toArray: function () {
  150. return [a];
  151. },
  152. toString: function () {
  153. return 'some(' + a + ')';
  154. },
  155. equals: function (o) {
  156. return o.is(a);
  157. },
  158. equals_: function (o, elementEq) {
  159. return o.fold(never, function (b) {
  160. return elementEq(a, b);
  161. });
  162. }
  163. };
  164. return me;
  165. };
  166. var from = function (value) {
  167. return value === null || value === undefined ? NONE : some(value);
  168. };
  169. var Optional = {
  170. some: some,
  171. none: none,
  172. from: from
  173. };
  174. var revocable = function (doRevoke) {
  175. var subject = Cell(Optional.none());
  176. var revoke = function () {
  177. return subject.get().each(doRevoke);
  178. };
  179. var clear = function () {
  180. revoke();
  181. subject.set(Optional.none());
  182. };
  183. var isSet = function () {
  184. return subject.get().isSome();
  185. };
  186. var set = function (s) {
  187. revoke();
  188. subject.set(Optional.some(s));
  189. };
  190. return {
  191. clear: clear,
  192. isSet: isSet,
  193. set: set
  194. };
  195. };
  196. var unbindable = function () {
  197. return revocable(function (s) {
  198. return s.unbind();
  199. });
  200. };
  201. var value = function () {
  202. var subject = Cell(Optional.none());
  203. var clear = function () {
  204. return subject.set(Optional.none());
  205. };
  206. var set = function (s) {
  207. return subject.set(Optional.some(s));
  208. };
  209. var isSet = function () {
  210. return subject.get().isSome();
  211. };
  212. var on = function (f) {
  213. return subject.get().each(f);
  214. };
  215. return {
  216. clear: clear,
  217. set: set,
  218. isSet: isSet,
  219. on: on
  220. };
  221. };
  222. var typeOf = function (x) {
  223. var t = typeof x;
  224. if (x === null) {
  225. return 'null';
  226. } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
  227. return 'array';
  228. } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
  229. return 'string';
  230. } else {
  231. return t;
  232. }
  233. };
  234. var isType = function (type) {
  235. return function (value) {
  236. return typeOf(value) === type;
  237. };
  238. };
  239. var isSimpleType = function (type) {
  240. return function (value) {
  241. return typeof value === type;
  242. };
  243. };
  244. var isString = isType('string');
  245. var isArray = isType('array');
  246. var isBoolean = isSimpleType('boolean');
  247. var isNullable = function (a) {
  248. return a === null || a === undefined;
  249. };
  250. var isNonNullable = function (a) {
  251. return !isNullable(a);
  252. };
  253. var isFunction = isSimpleType('function');
  254. var isNumber = isSimpleType('number');
  255. var nativePush = Array.prototype.push;
  256. var map = function (xs, f) {
  257. var len = xs.length;
  258. var r = new Array(len);
  259. for (var i = 0; i < len; i++) {
  260. var x = xs[i];
  261. r[i] = f(x, i);
  262. }
  263. return r;
  264. };
  265. var each = function (xs, f) {
  266. for (var i = 0, len = xs.length; i < len; i++) {
  267. var x = xs[i];
  268. f(x, i);
  269. }
  270. };
  271. var filter = function (xs, pred) {
  272. var r = [];
  273. for (var i = 0, len = xs.length; i < len; i++) {
  274. var x = xs[i];
  275. if (pred(x, i)) {
  276. r.push(x);
  277. }
  278. }
  279. return r;
  280. };
  281. var flatten = function (xs) {
  282. var r = [];
  283. for (var i = 0, len = xs.length; i < len; ++i) {
  284. if (!isArray(xs[i])) {
  285. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  286. }
  287. nativePush.apply(r, xs[i]);
  288. }
  289. return r;
  290. };
  291. var bind = function (xs, f) {
  292. return flatten(map(xs, f));
  293. };
  294. var get$1 = function (xs, i) {
  295. return i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  296. };
  297. var head = function (xs) {
  298. return get$1(xs, 0);
  299. };
  300. var keys = Object.keys;
  301. var each$1 = function (obj, f) {
  302. var props = keys(obj);
  303. for (var k = 0, len = props.length; k < len; k++) {
  304. var i = props[k];
  305. var x = obj[i];
  306. f(x, i);
  307. }
  308. };
  309. var isSupported = function (dom) {
  310. return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  311. };
  312. var fromHtml = function (html, scope) {
  313. var doc = scope || document;
  314. var div = doc.createElement('div');
  315. div.innerHTML = html;
  316. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  317. console.error('HTML does not have a single root node', html);
  318. throw new Error('HTML must have a single root node');
  319. }
  320. return fromDom(div.childNodes[0]);
  321. };
  322. var fromTag = function (tag, scope) {
  323. var doc = scope || document;
  324. var node = doc.createElement(tag);
  325. return fromDom(node);
  326. };
  327. var fromText = function (text, scope) {
  328. var doc = scope || document;
  329. var node = doc.createTextNode(text);
  330. return fromDom(node);
  331. };
  332. var fromDom = function (node) {
  333. if (node === null || node === undefined) {
  334. throw new Error('Node cannot be null or undefined');
  335. }
  336. return { dom: node };
  337. };
  338. var fromPoint = function (docElm, x, y) {
  339. return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
  340. };
  341. var SugarElement = {
  342. fromHtml: fromHtml,
  343. fromTag: fromTag,
  344. fromText: fromText,
  345. fromDom: fromDom,
  346. fromPoint: fromPoint
  347. };
  348. var Global = typeof window !== 'undefined' ? window : Function('return this;')();
  349. var DOCUMENT = 9;
  350. var DOCUMENT_FRAGMENT = 11;
  351. var ELEMENT = 1;
  352. var TEXT = 3;
  353. var type = function (element) {
  354. return element.dom.nodeType;
  355. };
  356. var isType$1 = function (t) {
  357. return function (element) {
  358. return type(element) === t;
  359. };
  360. };
  361. var isElement = isType$1(ELEMENT);
  362. var isText = isType$1(TEXT);
  363. var isDocument = isType$1(DOCUMENT);
  364. var isDocumentFragment = isType$1(DOCUMENT_FRAGMENT);
  365. var is = function (element, selector) {
  366. var dom = element.dom;
  367. if (dom.nodeType !== ELEMENT) {
  368. return false;
  369. } else {
  370. var elem = dom;
  371. if (elem.matches !== undefined) {
  372. return elem.matches(selector);
  373. } else if (elem.msMatchesSelector !== undefined) {
  374. return elem.msMatchesSelector(selector);
  375. } else if (elem.webkitMatchesSelector !== undefined) {
  376. return elem.webkitMatchesSelector(selector);
  377. } else if (elem.mozMatchesSelector !== undefined) {
  378. return elem.mozMatchesSelector(selector);
  379. } else {
  380. throw new Error('Browser lacks native selectors');
  381. }
  382. }
  383. };
  384. var bypassSelector = function (dom) {
  385. return dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
  386. };
  387. var all = function (selector, scope) {
  388. var base = scope === undefined ? document : scope.dom;
  389. return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), SugarElement.fromDom);
  390. };
  391. var eq = function (e1, e2) {
  392. return e1.dom === e2.dom;
  393. };
  394. var owner = function (element) {
  395. return SugarElement.fromDom(element.dom.ownerDocument);
  396. };
  397. var documentOrOwner = function (dos) {
  398. return isDocument(dos) ? dos : owner(dos);
  399. };
  400. var parent = function (element) {
  401. return Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  402. };
  403. var parents = function (element, isRoot) {
  404. var stop = isFunction(isRoot) ? isRoot : never;
  405. var dom = element.dom;
  406. var ret = [];
  407. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  408. var rawParent = dom.parentNode;
  409. var p = SugarElement.fromDom(rawParent);
  410. ret.push(p);
  411. if (stop(p) === true) {
  412. break;
  413. } else {
  414. dom = rawParent;
  415. }
  416. }
  417. return ret;
  418. };
  419. var siblings = function (element) {
  420. var filterSelf = function (elements) {
  421. return filter(elements, function (x) {
  422. return !eq(element, x);
  423. });
  424. };
  425. return parent(element).map(children).map(filterSelf).getOr([]);
  426. };
  427. var children = function (element) {
  428. return map(element.dom.childNodes, SugarElement.fromDom);
  429. };
  430. var isShadowRoot = function (dos) {
  431. return isDocumentFragment(dos) && isNonNullable(dos.dom.host);
  432. };
  433. var supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
  434. var isSupported$1 = constant(supported);
  435. var getRootNode = supported ? function (e) {
  436. return SugarElement.fromDom(e.dom.getRootNode());
  437. } : documentOrOwner;
  438. var getShadowRoot = function (e) {
  439. var r = getRootNode(e);
  440. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  441. };
  442. var getShadowHost = function (e) {
  443. return SugarElement.fromDom(e.dom.host);
  444. };
  445. var getOriginalEventTarget = function (event) {
  446. if (isSupported$1() && isNonNullable(event.target)) {
  447. var el = SugarElement.fromDom(event.target);
  448. if (isElement(el) && isOpenShadowHost(el)) {
  449. if (event.composed && event.composedPath) {
  450. var composedPath = event.composedPath();
  451. if (composedPath) {
  452. return head(composedPath);
  453. }
  454. }
  455. }
  456. }
  457. return Optional.from(event.target);
  458. };
  459. var isOpenShadowHost = function (element) {
  460. return isNonNullable(element.dom.shadowRoot);
  461. };
  462. var inBody = function (element) {
  463. var dom = isText(element) ? element.dom.parentNode : element.dom;
  464. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  465. return false;
  466. }
  467. var doc = dom.ownerDocument;
  468. return getShadowRoot(SugarElement.fromDom(dom)).fold(function () {
  469. return doc.body.contains(dom);
  470. }, compose1(inBody, getShadowHost));
  471. };
  472. var getBody = function (doc) {
  473. var b = doc.dom.body;
  474. if (b === null || b === undefined) {
  475. throw new Error('Body is not available yet');
  476. }
  477. return SugarElement.fromDom(b);
  478. };
  479. var rawSet = function (dom, key, value) {
  480. if (isString(value) || isBoolean(value) || isNumber(value)) {
  481. dom.setAttribute(key, value + '');
  482. } else {
  483. console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  484. throw new Error('Attribute value was not simple');
  485. }
  486. };
  487. var set = function (element, key, value) {
  488. rawSet(element.dom, key, value);
  489. };
  490. var get$2 = function (element, key) {
  491. var v = element.dom.getAttribute(key);
  492. return v === null ? undefined : v;
  493. };
  494. var remove = function (element, key) {
  495. element.dom.removeAttribute(key);
  496. };
  497. var internalSet = function (dom, property, value) {
  498. if (!isString(value)) {
  499. console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  500. throw new Error('CSS value must be a string: ' + value);
  501. }
  502. if (isSupported(dom)) {
  503. dom.style.setProperty(property, value);
  504. }
  505. };
  506. var setAll = function (element, css) {
  507. var dom = element.dom;
  508. each$1(css, function (v, k) {
  509. internalSet(dom, k, v);
  510. });
  511. };
  512. var get$3 = function (element, property) {
  513. var dom = element.dom;
  514. var styles = window.getComputedStyle(dom);
  515. var r = styles.getPropertyValue(property);
  516. return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  517. };
  518. var getUnsafeProperty = function (dom, property) {
  519. return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
  520. };
  521. var mkEvent = function (target, x, y, stop, prevent, kill, raw) {
  522. return {
  523. target: target,
  524. x: x,
  525. y: y,
  526. stop: stop,
  527. prevent: prevent,
  528. kill: kill,
  529. raw: raw
  530. };
  531. };
  532. var fromRawEvent = function (rawEvent) {
  533. var target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  534. var stop = function () {
  535. return rawEvent.stopPropagation();
  536. };
  537. var prevent = function () {
  538. return rawEvent.preventDefault();
  539. };
  540. var kill = compose(prevent, stop);
  541. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  542. };
  543. var handle = function (filter, handler) {
  544. return function (rawEvent) {
  545. if (filter(rawEvent)) {
  546. handler(fromRawEvent(rawEvent));
  547. }
  548. };
  549. };
  550. var binder = function (element, event, filter, handler, useCapture) {
  551. var wrapped = handle(filter, handler);
  552. element.dom.addEventListener(event, wrapped, useCapture);
  553. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  554. };
  555. var bind$1 = function (element, event, filter, handler) {
  556. return binder(element, event, filter, handler, false);
  557. };
  558. var unbind = function (element, event, handler, useCapture) {
  559. element.dom.removeEventListener(event, handler, useCapture);
  560. };
  561. var filter$1 = always;
  562. var bind$2 = function (element, event, handler) {
  563. return bind$1(element, event, filter$1, handler);
  564. };
  565. var r = function (left, top) {
  566. var translate = function (x, y) {
  567. return r(left + x, top + y);
  568. };
  569. return {
  570. left: left,
  571. top: top,
  572. translate: translate
  573. };
  574. };
  575. var SugarPosition = r;
  576. var get$4 = function (_DOC) {
  577. var doc = _DOC !== undefined ? _DOC.dom : document;
  578. var x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  579. var y = doc.body.scrollTop || doc.documentElement.scrollTop;
  580. return SugarPosition(x, y);
  581. };
  582. var get$5 = function (_win) {
  583. var win = _win === undefined ? window : _win;
  584. return Optional.from(win['visualViewport']);
  585. };
  586. var bounds = function (x, y, width, height) {
  587. return {
  588. x: x,
  589. y: y,
  590. width: width,
  591. height: height,
  592. right: x + width,
  593. bottom: y + height
  594. };
  595. };
  596. var getBounds = function (_win) {
  597. var win = _win === undefined ? window : _win;
  598. var doc = win.document;
  599. var scroll = get$4(SugarElement.fromDom(doc));
  600. return get$5(win).fold(function () {
  601. var html = win.document.documentElement;
  602. var width = html.clientWidth;
  603. var height = html.clientHeight;
  604. return bounds(scroll.left, scroll.top, width, height);
  605. }, function (visualViewport) {
  606. return bounds(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height);
  607. });
  608. };
  609. var bind$3 = function (name, callback, _win) {
  610. return get$5(_win).map(function (visualViewport) {
  611. var handler = function (e) {
  612. return callback(fromRawEvent(e));
  613. };
  614. visualViewport.addEventListener(name, handler);
  615. return {
  616. unbind: function () {
  617. return visualViewport.removeEventListener(name, handler);
  618. }
  619. };
  620. }).getOrThunk(function () {
  621. return { unbind: noop };
  622. });
  623. };
  624. var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
  625. var global$2 = tinymce.util.Tools.resolve('tinymce.Env');
  626. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  627. var fireFullscreenStateChanged = function (editor, state) {
  628. editor.fire('FullscreenStateChanged', { state: state });
  629. };
  630. var getFullscreenNative = function (editor) {
  631. return editor.getParam('fullscreen_native', false, 'boolean');
  632. };
  633. var getFullscreenRoot = function (editor) {
  634. var elem = SugarElement.fromDom(editor.getElement());
  635. return getShadowRoot(elem).map(getShadowHost).getOrThunk(function () {
  636. return getBody(owner(elem));
  637. });
  638. };
  639. var getFullscreenElement = function (root) {
  640. if (root.fullscreenElement !== undefined) {
  641. return root.fullscreenElement;
  642. } else if (root.msFullscreenElement !== undefined) {
  643. return root.msFullscreenElement;
  644. } else if (root.webkitFullscreenElement !== undefined) {
  645. return root.webkitFullscreenElement;
  646. } else {
  647. return null;
  648. }
  649. };
  650. var getFullscreenchangeEventName = function () {
  651. if (document.fullscreenElement !== undefined) {
  652. return 'fullscreenchange';
  653. } else if (document.msFullscreenElement !== undefined) {
  654. return 'MSFullscreenChange';
  655. } else if (document.webkitFullscreenElement !== undefined) {
  656. return 'webkitfullscreenchange';
  657. } else {
  658. return 'fullscreenchange';
  659. }
  660. };
  661. var requestFullscreen = function (sugarElem) {
  662. var elem = sugarElem.dom;
  663. if (elem.requestFullscreen) {
  664. elem.requestFullscreen();
  665. } else if (elem.msRequestFullscreen) {
  666. elem.msRequestFullscreen();
  667. } else if (elem.webkitRequestFullScreen) {
  668. elem.webkitRequestFullScreen();
  669. }
  670. };
  671. var exitFullscreen = function (sugarDoc) {
  672. var doc = sugarDoc.dom;
  673. if (doc.exitFullscreen) {
  674. doc.exitFullscreen();
  675. } else if (doc.msExitFullscreen) {
  676. doc.msExitFullscreen();
  677. } else if (doc.webkitCancelFullScreen) {
  678. doc.webkitCancelFullScreen();
  679. }
  680. };
  681. var isFullscreenElement = function (elem) {
  682. return elem.dom === getFullscreenElement(owner(elem).dom);
  683. };
  684. var ancestors = function (scope, predicate, isRoot) {
  685. return filter(parents(scope, isRoot), predicate);
  686. };
  687. var siblings$1 = function (scope, predicate) {
  688. return filter(siblings(scope), predicate);
  689. };
  690. var all$1 = function (selector) {
  691. return all(selector);
  692. };
  693. var ancestors$1 = function (scope, selector, isRoot) {
  694. return ancestors(scope, function (e) {
  695. return is(e, selector);
  696. }, isRoot);
  697. };
  698. var siblings$2 = function (scope, selector) {
  699. return siblings$1(scope, function (e) {
  700. return is(e, selector);
  701. });
  702. };
  703. var attr = 'data-ephox-mobile-fullscreen-style';
  704. var siblingStyles = 'display:none!important;';
  705. var ancestorPosition = 'position:absolute!important;';
  706. var ancestorStyles = 'top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;';
  707. var bgFallback = 'background-color:rgb(255,255,255)!important;';
  708. var isAndroid = global$2.os.isAndroid();
  709. var matchColor = function (editorBody) {
  710. var color = get$3(editorBody, 'background-color');
  711. return color !== undefined && color !== '' ? 'background-color:' + color + '!important' : bgFallback;
  712. };
  713. var clobberStyles = function (dom, container, editorBody) {
  714. var gatherSiblings = function (element) {
  715. return siblings$2(element, '*:not(.tox-silver-sink)');
  716. };
  717. var clobber = function (clobberStyle) {
  718. return function (element) {
  719. var styles = get$2(element, 'style');
  720. var backup = styles === undefined ? 'no-styles' : styles.trim();
  721. if (backup === clobberStyle) {
  722. return;
  723. } else {
  724. set(element, attr, backup);
  725. setAll(element, dom.parseStyle(clobberStyle));
  726. }
  727. };
  728. };
  729. var ancestors = ancestors$1(container, '*');
  730. var siblings = bind(ancestors, gatherSiblings);
  731. var bgColor = matchColor(editorBody);
  732. each(siblings, clobber(siblingStyles));
  733. each(ancestors, clobber(ancestorPosition + ancestorStyles + bgColor));
  734. var containerStyles = isAndroid === true ? '' : ancestorPosition;
  735. clobber(containerStyles + ancestorStyles + bgColor)(container);
  736. };
  737. var restoreStyles = function (dom) {
  738. var clobberedEls = all$1('[' + attr + ']');
  739. each(clobberedEls, function (element) {
  740. var restore = get$2(element, attr);
  741. if (restore !== 'no-styles') {
  742. setAll(element, dom.parseStyle(restore));
  743. } else {
  744. remove(element, 'style');
  745. }
  746. remove(element, attr);
  747. });
  748. };
  749. var DOM = global$1.DOM;
  750. var getScrollPos = function () {
  751. var vp = getBounds(window);
  752. return {
  753. x: vp.x,
  754. y: vp.y
  755. };
  756. };
  757. var setScrollPos = function (pos) {
  758. window.scrollTo(pos.x, pos.y);
  759. };
  760. var viewportUpdate = get$5().fold(function () {
  761. return {
  762. bind: noop,
  763. unbind: noop
  764. };
  765. }, function (visualViewport) {
  766. var editorContainer = value();
  767. var resizeBinder = unbindable();
  768. var scrollBinder = unbindable();
  769. var refreshScroll = function () {
  770. document.body.scrollTop = 0;
  771. document.documentElement.scrollTop = 0;
  772. };
  773. var refreshVisualViewport = function () {
  774. window.requestAnimationFrame(function () {
  775. editorContainer.on(function (container) {
  776. return setAll(container, {
  777. top: visualViewport.offsetTop + 'px',
  778. left: visualViewport.offsetLeft + 'px',
  779. height: visualViewport.height + 'px',
  780. width: visualViewport.width + 'px'
  781. });
  782. });
  783. });
  784. };
  785. var update = global$3.throttle(function () {
  786. refreshScroll();
  787. refreshVisualViewport();
  788. }, 50);
  789. var bind = function (element) {
  790. editorContainer.set(element);
  791. update();
  792. resizeBinder.set(bind$3('resize', update));
  793. scrollBinder.set(bind$3('scroll', update));
  794. };
  795. var unbind = function () {
  796. editorContainer.on(function () {
  797. resizeBinder.clear();
  798. scrollBinder.clear();
  799. });
  800. editorContainer.clear();
  801. };
  802. return {
  803. bind: bind,
  804. unbind: unbind
  805. };
  806. });
  807. var toggleFullscreen = function (editor, fullscreenState) {
  808. var body = document.body;
  809. var documentElement = document.documentElement;
  810. var editorContainer = editor.getContainer();
  811. var editorContainerS = SugarElement.fromDom(editorContainer);
  812. var fullscreenRoot = getFullscreenRoot(editor);
  813. var fullscreenInfo = fullscreenState.get();
  814. var editorBody = SugarElement.fromDom(editor.getBody());
  815. var isTouch = global$2.deviceType.isTouch();
  816. var editorContainerStyle = editorContainer.style;
  817. var iframe = editor.iframeElement;
  818. var iframeStyle = iframe.style;
  819. var handleClasses = function (handler) {
  820. handler(body, 'tox-fullscreen');
  821. handler(documentElement, 'tox-fullscreen');
  822. handler(editorContainer, 'tox-fullscreen');
  823. getShadowRoot(editorContainerS).map(function (root) {
  824. return getShadowHost(root).dom;
  825. }).each(function (host) {
  826. handler(host, 'tox-fullscreen');
  827. handler(host, 'tox-shadowhost');
  828. });
  829. };
  830. var cleanup = function () {
  831. if (isTouch) {
  832. restoreStyles(editor.dom);
  833. }
  834. handleClasses(DOM.removeClass);
  835. viewportUpdate.unbind();
  836. Optional.from(fullscreenState.get()).each(function (info) {
  837. return info.fullscreenChangeHandler.unbind();
  838. });
  839. };
  840. if (!fullscreenInfo) {
  841. var fullscreenChangeHandler = bind$2(owner(fullscreenRoot), getFullscreenchangeEventName(), function (_evt) {
  842. if (getFullscreenNative(editor)) {
  843. if (!isFullscreenElement(fullscreenRoot) && fullscreenState.get() !== null) {
  844. toggleFullscreen(editor, fullscreenState);
  845. }
  846. }
  847. });
  848. var newFullScreenInfo = {
  849. scrollPos: getScrollPos(),
  850. containerWidth: editorContainerStyle.width,
  851. containerHeight: editorContainerStyle.height,
  852. containerTop: editorContainerStyle.top,
  853. containerLeft: editorContainerStyle.left,
  854. iframeWidth: iframeStyle.width,
  855. iframeHeight: iframeStyle.height,
  856. fullscreenChangeHandler: fullscreenChangeHandler
  857. };
  858. if (isTouch) {
  859. clobberStyles(editor.dom, editorContainerS, editorBody);
  860. }
  861. iframeStyle.width = iframeStyle.height = '100%';
  862. editorContainerStyle.width = editorContainerStyle.height = '';
  863. handleClasses(DOM.addClass);
  864. viewportUpdate.bind(editorContainerS);
  865. editor.on('remove', cleanup);
  866. fullscreenState.set(newFullScreenInfo);
  867. if (getFullscreenNative(editor)) {
  868. requestFullscreen(fullscreenRoot);
  869. }
  870. fireFullscreenStateChanged(editor, true);
  871. } else {
  872. fullscreenInfo.fullscreenChangeHandler.unbind();
  873. if (getFullscreenNative(editor) && isFullscreenElement(fullscreenRoot)) {
  874. exitFullscreen(owner(fullscreenRoot));
  875. }
  876. iframeStyle.width = fullscreenInfo.iframeWidth;
  877. iframeStyle.height = fullscreenInfo.iframeHeight;
  878. editorContainerStyle.width = fullscreenInfo.containerWidth;
  879. editorContainerStyle.height = fullscreenInfo.containerHeight;
  880. editorContainerStyle.top = fullscreenInfo.containerTop;
  881. editorContainerStyle.left = fullscreenInfo.containerLeft;
  882. setScrollPos(fullscreenInfo.scrollPos);
  883. fullscreenState.set(null);
  884. fireFullscreenStateChanged(editor, false);
  885. cleanup();
  886. editor.off('remove', cleanup);
  887. }
  888. };
  889. var register = function (editor, fullscreenState) {
  890. editor.addCommand('mceFullScreen', function () {
  891. toggleFullscreen(editor, fullscreenState);
  892. });
  893. };
  894. var makeSetupHandler = function (editor, fullscreenState) {
  895. return function (api) {
  896. api.setActive(fullscreenState.get() !== null);
  897. var editorEventCallback = function (e) {
  898. return api.setActive(e.state);
  899. };
  900. editor.on('FullscreenStateChanged', editorEventCallback);
  901. return function () {
  902. return editor.off('FullscreenStateChanged', editorEventCallback);
  903. };
  904. };
  905. };
  906. var register$1 = function (editor, fullscreenState) {
  907. editor.ui.registry.addToggleMenuItem('fullscreen', {
  908. text: 'Fullscreen',
  909. icon: 'fullscreen',
  910. shortcut: 'Meta+Shift+F',
  911. onAction: function () {
  912. return editor.execCommand('mceFullScreen');
  913. },
  914. onSetup: makeSetupHandler(editor, fullscreenState)
  915. });
  916. editor.ui.registry.addToggleButton('fullscreen', {
  917. tooltip: 'Fullscreen',
  918. icon: 'fullscreen',
  919. onAction: function () {
  920. return editor.execCommand('mceFullScreen');
  921. },
  922. onSetup: makeSetupHandler(editor, fullscreenState)
  923. });
  924. };
  925. function Plugin () {
  926. global.add('fullscreen', function (editor) {
  927. var fullscreenState = Cell(null);
  928. if (editor.inline) {
  929. return get(fullscreenState);
  930. }
  931. register(editor, fullscreenState);
  932. register$1(editor, fullscreenState);
  933. editor.addShortcut('Meta+Shift+F', '', 'mceFullScreen');
  934. return get(fullscreenState);
  935. });
  936. }
  937. Plugin();
  938. }());