plugin.js 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  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.1.0 (2019-10-17)
  8. */
  9. (function (domGlobals) {
  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. var clone = function () {
  20. return Cell(get());
  21. };
  22. return {
  23. get: get,
  24. set: set,
  25. clone: clone
  26. };
  27. };
  28. var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  29. var get = function (fullscreenState) {
  30. return {
  31. isFullscreen: function () {
  32. return fullscreenState.get() !== null;
  33. }
  34. };
  35. };
  36. var Api = { get: get };
  37. var noop = function () {
  38. };
  39. var constant = function (value) {
  40. return function () {
  41. return value;
  42. };
  43. };
  44. var never = constant(false);
  45. var always = constant(true);
  46. var none = function () {
  47. return NONE;
  48. };
  49. var NONE = function () {
  50. var eq = function (o) {
  51. return o.isNone();
  52. };
  53. var call = function (thunk) {
  54. return thunk();
  55. };
  56. var id = function (n) {
  57. return n;
  58. };
  59. var me = {
  60. fold: function (n, s) {
  61. return n();
  62. },
  63. is: never,
  64. isSome: never,
  65. isNone: always,
  66. getOr: id,
  67. getOrThunk: call,
  68. getOrDie: function (msg) {
  69. throw new Error(msg || 'error: getOrDie called on none.');
  70. },
  71. getOrNull: constant(null),
  72. getOrUndefined: constant(undefined),
  73. or: id,
  74. orThunk: call,
  75. map: none,
  76. each: noop,
  77. bind: none,
  78. exists: never,
  79. forall: always,
  80. filter: none,
  81. equals: eq,
  82. equals_: eq,
  83. toArray: function () {
  84. return [];
  85. },
  86. toString: constant('none()')
  87. };
  88. if (Object.freeze) {
  89. Object.freeze(me);
  90. }
  91. return me;
  92. }();
  93. var some = function (a) {
  94. var constant_a = constant(a);
  95. var self = function () {
  96. return me;
  97. };
  98. var bind = function (f) {
  99. return f(a);
  100. };
  101. var me = {
  102. fold: function (n, s) {
  103. return s(a);
  104. },
  105. is: function (v) {
  106. return a === v;
  107. },
  108. isSome: always,
  109. isNone: never,
  110. getOr: constant_a,
  111. getOrThunk: constant_a,
  112. getOrDie: constant_a,
  113. getOrNull: constant_a,
  114. getOrUndefined: constant_a,
  115. or: self,
  116. orThunk: self,
  117. map: function (f) {
  118. return some(f(a));
  119. },
  120. each: function (f) {
  121. f(a);
  122. },
  123. bind: bind,
  124. exists: bind,
  125. forall: bind,
  126. filter: function (f) {
  127. return f(a) ? me : NONE;
  128. },
  129. toArray: function () {
  130. return [a];
  131. },
  132. toString: function () {
  133. return 'some(' + a + ')';
  134. },
  135. equals: function (o) {
  136. return o.is(a);
  137. },
  138. equals_: function (o, elementEq) {
  139. return o.fold(never, function (b) {
  140. return elementEq(a, b);
  141. });
  142. }
  143. };
  144. return me;
  145. };
  146. var from = function (value) {
  147. return value === null || value === undefined ? NONE : some(value);
  148. };
  149. var Option = {
  150. some: some,
  151. none: none,
  152. from: from
  153. };
  154. var value = function () {
  155. var subject = Cell(Option.none());
  156. var clear = function () {
  157. subject.set(Option.none());
  158. };
  159. var set = function (s) {
  160. subject.set(Option.some(s));
  161. };
  162. var on = function (f) {
  163. subject.get().each(f);
  164. };
  165. var isSet = function () {
  166. return subject.get().isSome();
  167. };
  168. return {
  169. clear: clear,
  170. set: set,
  171. isSet: isSet,
  172. on: on
  173. };
  174. };
  175. var typeOf = function (x) {
  176. if (x === null) {
  177. return 'null';
  178. }
  179. var t = typeof x;
  180. if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
  181. return 'array';
  182. }
  183. if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
  184. return 'string';
  185. }
  186. return t;
  187. };
  188. var isType = function (type) {
  189. return function (value) {
  190. return typeOf(value) === type;
  191. };
  192. };
  193. var isString = isType('string');
  194. var isArray = isType('array');
  195. var isBoolean = isType('boolean');
  196. var isFunction = isType('function');
  197. var isNumber = isType('number');
  198. var nativeSlice = Array.prototype.slice;
  199. var nativePush = Array.prototype.push;
  200. var map = function (xs, f) {
  201. var len = xs.length;
  202. var r = new Array(len);
  203. for (var i = 0; i < len; i++) {
  204. var x = xs[i];
  205. r[i] = f(x, i);
  206. }
  207. return r;
  208. };
  209. var each = function (xs, f) {
  210. for (var i = 0, len = xs.length; i < len; i++) {
  211. var x = xs[i];
  212. f(x, i);
  213. }
  214. };
  215. var filter = function (xs, pred) {
  216. var r = [];
  217. for (var i = 0, len = xs.length; i < len; i++) {
  218. var x = xs[i];
  219. if (pred(x, i)) {
  220. r.push(x);
  221. }
  222. }
  223. return r;
  224. };
  225. var find = function (xs, pred) {
  226. for (var i = 0, len = xs.length; i < len; i++) {
  227. var x = xs[i];
  228. if (pred(x, i)) {
  229. return Option.some(x);
  230. }
  231. }
  232. return Option.none();
  233. };
  234. var flatten = function (xs) {
  235. var r = [];
  236. for (var i = 0, len = xs.length; i < len; ++i) {
  237. if (!isArray(xs[i])) {
  238. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  239. }
  240. nativePush.apply(r, xs[i]);
  241. }
  242. return r;
  243. };
  244. var bind = function (xs, f) {
  245. var output = map(xs, f);
  246. return flatten(output);
  247. };
  248. var from$1 = isFunction(Array.from) ? Array.from : function (x) {
  249. return nativeSlice.call(x);
  250. };
  251. var keys = Object.keys;
  252. var each$1 = function (obj, f) {
  253. var props = keys(obj);
  254. for (var k = 0, len = props.length; k < len; k++) {
  255. var i = props[k];
  256. var x = obj[i];
  257. f(x, i);
  258. }
  259. };
  260. var contains = function (str, substr) {
  261. return str.indexOf(substr) !== -1;
  262. };
  263. var isSupported = function (dom) {
  264. return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  265. };
  266. var fromHtml = function (html, scope) {
  267. var doc = scope || domGlobals.document;
  268. var div = doc.createElement('div');
  269. div.innerHTML = html;
  270. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  271. domGlobals.console.error('HTML does not have a single root node', html);
  272. throw new Error('HTML must have a single root node');
  273. }
  274. return fromDom(div.childNodes[0]);
  275. };
  276. var fromTag = function (tag, scope) {
  277. var doc = scope || domGlobals.document;
  278. var node = doc.createElement(tag);
  279. return fromDom(node);
  280. };
  281. var fromText = function (text, scope) {
  282. var doc = scope || domGlobals.document;
  283. var node = doc.createTextNode(text);
  284. return fromDom(node);
  285. };
  286. var fromDom = function (node) {
  287. if (node === null || node === undefined) {
  288. throw new Error('Node cannot be null or undefined');
  289. }
  290. return { dom: constant(node) };
  291. };
  292. var fromPoint = function (docElm, x, y) {
  293. var doc = docElm.dom();
  294. return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
  295. };
  296. var Element = {
  297. fromHtml: fromHtml,
  298. fromTag: fromTag,
  299. fromText: fromText,
  300. fromDom: fromDom,
  301. fromPoint: fromPoint
  302. };
  303. var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
  304. var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
  305. var COMMENT = domGlobals.Node.COMMENT_NODE;
  306. var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
  307. var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
  308. var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
  309. var ELEMENT = domGlobals.Node.ELEMENT_NODE;
  310. var TEXT = domGlobals.Node.TEXT_NODE;
  311. var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
  312. var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
  313. var ENTITY = domGlobals.Node.ENTITY_NODE;
  314. var NOTATION = domGlobals.Node.NOTATION_NODE;
  315. var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();
  316. var type = function (element) {
  317. return element.dom().nodeType;
  318. };
  319. var isType$1 = function (t) {
  320. return function (element) {
  321. return type(element) === t;
  322. };
  323. };
  324. var isText = isType$1(TEXT);
  325. var inBody = function (element) {
  326. var dom = isText(element) ? element.dom().parentNode : element.dom();
  327. return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom);
  328. };
  329. var rawSet = function (dom, key, value) {
  330. if (isString(value) || isBoolean(value) || isNumber(value)) {
  331. dom.setAttribute(key, value + '');
  332. } else {
  333. domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  334. throw new Error('Attribute value was not simple');
  335. }
  336. };
  337. var set = function (element, key, value) {
  338. rawSet(element.dom(), key, value);
  339. };
  340. var get$1 = function (element, key) {
  341. var v = element.dom().getAttribute(key);
  342. return v === null ? undefined : v;
  343. };
  344. var remove = function (element, key) {
  345. element.dom().removeAttribute(key);
  346. };
  347. var internalSet = function (dom, property, value) {
  348. if (!isString(value)) {
  349. domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  350. throw new Error('CSS value must be a string: ' + value);
  351. }
  352. if (isSupported(dom)) {
  353. dom.style.setProperty(property, value);
  354. }
  355. };
  356. var setAll = function (element, css) {
  357. var dom = element.dom();
  358. each$1(css, function (v, k) {
  359. internalSet(dom, k, v);
  360. });
  361. };
  362. var get$2 = function (element, property) {
  363. var dom = element.dom();
  364. var styles = domGlobals.window.getComputedStyle(dom);
  365. var r = styles.getPropertyValue(property);
  366. var v = r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  367. return v === null ? undefined : v;
  368. };
  369. var getUnsafeProperty = function (dom, property) {
  370. return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
  371. };
  372. var firstMatch = function (regexes, s) {
  373. for (var i = 0; i < regexes.length; i++) {
  374. var x = regexes[i];
  375. if (x.test(s)) {
  376. return x;
  377. }
  378. }
  379. return undefined;
  380. };
  381. var find$1 = function (regexes, agent) {
  382. var r = firstMatch(regexes, agent);
  383. if (!r) {
  384. return {
  385. major: 0,
  386. minor: 0
  387. };
  388. }
  389. var group = function (i) {
  390. return Number(agent.replace(r, '$' + i));
  391. };
  392. return nu(group(1), group(2));
  393. };
  394. var detect = function (versionRegexes, agent) {
  395. var cleanedAgent = String(agent).toLowerCase();
  396. if (versionRegexes.length === 0) {
  397. return unknown();
  398. }
  399. return find$1(versionRegexes, cleanedAgent);
  400. };
  401. var unknown = function () {
  402. return nu(0, 0);
  403. };
  404. var nu = function (major, minor) {
  405. return {
  406. major: major,
  407. minor: minor
  408. };
  409. };
  410. var Version = {
  411. nu: nu,
  412. detect: detect,
  413. unknown: unknown
  414. };
  415. var edge = 'Edge';
  416. var chrome = 'Chrome';
  417. var ie = 'IE';
  418. var opera = 'Opera';
  419. var firefox = 'Firefox';
  420. var safari = 'Safari';
  421. var isBrowser = function (name, current) {
  422. return function () {
  423. return current === name;
  424. };
  425. };
  426. var unknown$1 = function () {
  427. return nu$1({
  428. current: undefined,
  429. version: Version.unknown()
  430. });
  431. };
  432. var nu$1 = function (info) {
  433. var current = info.current;
  434. var version = info.version;
  435. return {
  436. current: current,
  437. version: version,
  438. isEdge: isBrowser(edge, current),
  439. isChrome: isBrowser(chrome, current),
  440. isIE: isBrowser(ie, current),
  441. isOpera: isBrowser(opera, current),
  442. isFirefox: isBrowser(firefox, current),
  443. isSafari: isBrowser(safari, current)
  444. };
  445. };
  446. var Browser = {
  447. unknown: unknown$1,
  448. nu: nu$1,
  449. edge: constant(edge),
  450. chrome: constant(chrome),
  451. ie: constant(ie),
  452. opera: constant(opera),
  453. firefox: constant(firefox),
  454. safari: constant(safari)
  455. };
  456. var windows = 'Windows';
  457. var ios = 'iOS';
  458. var android = 'Android';
  459. var linux = 'Linux';
  460. var osx = 'OSX';
  461. var solaris = 'Solaris';
  462. var freebsd = 'FreeBSD';
  463. var isOS = function (name, current) {
  464. return function () {
  465. return current === name;
  466. };
  467. };
  468. var unknown$2 = function () {
  469. return nu$2({
  470. current: undefined,
  471. version: Version.unknown()
  472. });
  473. };
  474. var nu$2 = function (info) {
  475. var current = info.current;
  476. var version = info.version;
  477. return {
  478. current: current,
  479. version: version,
  480. isWindows: isOS(windows, current),
  481. isiOS: isOS(ios, current),
  482. isAndroid: isOS(android, current),
  483. isOSX: isOS(osx, current),
  484. isLinux: isOS(linux, current),
  485. isSolaris: isOS(solaris, current),
  486. isFreeBSD: isOS(freebsd, current)
  487. };
  488. };
  489. var OperatingSystem = {
  490. unknown: unknown$2,
  491. nu: nu$2,
  492. windows: constant(windows),
  493. ios: constant(ios),
  494. android: constant(android),
  495. linux: constant(linux),
  496. osx: constant(osx),
  497. solaris: constant(solaris),
  498. freebsd: constant(freebsd)
  499. };
  500. var DeviceType = function (os, browser, userAgent, mediaMatch) {
  501. var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  502. var isiPhone = os.isiOS() && !isiPad;
  503. var isMobile = os.isiOS() || os.isAndroid();
  504. var isTouch = isMobile || mediaMatch('(pointer:coarse)');
  505. var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  506. var isPhone = isiPhone || isMobile && !isTablet;
  507. var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  508. var isDesktop = !isPhone && !isTablet && !iOSwebview;
  509. return {
  510. isiPad: constant(isiPad),
  511. isiPhone: constant(isiPhone),
  512. isTablet: constant(isTablet),
  513. isPhone: constant(isPhone),
  514. isTouch: constant(isTouch),
  515. isAndroid: os.isAndroid,
  516. isiOS: os.isiOS,
  517. isWebView: constant(iOSwebview),
  518. isDesktop: constant(isDesktop)
  519. };
  520. };
  521. var detect$1 = function (candidates, userAgent) {
  522. var agent = String(userAgent).toLowerCase();
  523. return find(candidates, function (candidate) {
  524. return candidate.search(agent);
  525. });
  526. };
  527. var detectBrowser = function (browsers, userAgent) {
  528. return detect$1(browsers, userAgent).map(function (browser) {
  529. var version = Version.detect(browser.versionRegexes, userAgent);
  530. return {
  531. current: browser.name,
  532. version: version
  533. };
  534. });
  535. };
  536. var detectOs = function (oses, userAgent) {
  537. return detect$1(oses, userAgent).map(function (os) {
  538. var version = Version.detect(os.versionRegexes, userAgent);
  539. return {
  540. current: os.name,
  541. version: version
  542. };
  543. });
  544. };
  545. var UaString = {
  546. detectBrowser: detectBrowser,
  547. detectOs: detectOs
  548. };
  549. var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  550. var checkContains = function (target) {
  551. return function (uastring) {
  552. return contains(uastring, target);
  553. };
  554. };
  555. var browsers = [
  556. {
  557. name: 'Edge',
  558. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  559. search: function (uastring) {
  560. return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
  561. }
  562. },
  563. {
  564. name: 'Chrome',
  565. versionRegexes: [
  566. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  567. normalVersionRegex
  568. ],
  569. search: function (uastring) {
  570. return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
  571. }
  572. },
  573. {
  574. name: 'IE',
  575. versionRegexes: [
  576. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  577. /.*?rv:([0-9]+)\.([0-9]+).*/
  578. ],
  579. search: function (uastring) {
  580. return contains(uastring, 'msie') || contains(uastring, 'trident');
  581. }
  582. },
  583. {
  584. name: 'Opera',
  585. versionRegexes: [
  586. normalVersionRegex,
  587. /.*?opera\/([0-9]+)\.([0-9]+).*/
  588. ],
  589. search: checkContains('opera')
  590. },
  591. {
  592. name: 'Firefox',
  593. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  594. search: checkContains('firefox')
  595. },
  596. {
  597. name: 'Safari',
  598. versionRegexes: [
  599. normalVersionRegex,
  600. /.*?cpu os ([0-9]+)_([0-9]+).*/
  601. ],
  602. search: function (uastring) {
  603. return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
  604. }
  605. }
  606. ];
  607. var oses = [
  608. {
  609. name: 'Windows',
  610. search: checkContains('win'),
  611. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  612. },
  613. {
  614. name: 'iOS',
  615. search: function (uastring) {
  616. return contains(uastring, 'iphone') || contains(uastring, 'ipad');
  617. },
  618. versionRegexes: [
  619. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  620. /.*cpu os ([0-9]+)_([0-9]+).*/,
  621. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  622. ]
  623. },
  624. {
  625. name: 'Android',
  626. search: checkContains('android'),
  627. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  628. },
  629. {
  630. name: 'OSX',
  631. search: checkContains('os x'),
  632. versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
  633. },
  634. {
  635. name: 'Linux',
  636. search: checkContains('linux'),
  637. versionRegexes: []
  638. },
  639. {
  640. name: 'Solaris',
  641. search: checkContains('sunos'),
  642. versionRegexes: []
  643. },
  644. {
  645. name: 'FreeBSD',
  646. search: checkContains('freebsd'),
  647. versionRegexes: []
  648. }
  649. ];
  650. var PlatformInfo = {
  651. browsers: constant(browsers),
  652. oses: constant(oses)
  653. };
  654. var detect$2 = function (userAgent, mediaMatch) {
  655. var browsers = PlatformInfo.browsers();
  656. var oses = PlatformInfo.oses();
  657. var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
  658. var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  659. var deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  660. return {
  661. browser: browser,
  662. os: os,
  663. deviceType: deviceType
  664. };
  665. };
  666. var PlatformDetection = { detect: detect$2 };
  667. var mediaMatch = function (query) {
  668. return domGlobals.window.matchMedia(query).matches;
  669. };
  670. var platform = Cell(PlatformDetection.detect(domGlobals.navigator.userAgent, mediaMatch));
  671. var detect$3 = function () {
  672. return platform.get();
  673. };
  674. var Immutable = function () {
  675. var fields = [];
  676. for (var _i = 0; _i < arguments.length; _i++) {
  677. fields[_i] = arguments[_i];
  678. }
  679. return function () {
  680. var values = [];
  681. for (var _i = 0; _i < arguments.length; _i++) {
  682. values[_i] = arguments[_i];
  683. }
  684. if (fields.length !== values.length) {
  685. throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
  686. }
  687. var struct = {};
  688. each(fields, function (name, i) {
  689. struct[name] = constant(values[i]);
  690. });
  691. return struct;
  692. };
  693. };
  694. var compareDocumentPosition = function (a, b, match) {
  695. return (a.compareDocumentPosition(b) & match) !== 0;
  696. };
  697. var documentPositionPreceding = function (a, b) {
  698. return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_PRECEDING);
  699. };
  700. var documentPositionContainedBy = function (a, b) {
  701. return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_CONTAINED_BY);
  702. };
  703. var Node = {
  704. documentPositionPreceding: documentPositionPreceding,
  705. documentPositionContainedBy: documentPositionContainedBy
  706. };
  707. var ELEMENT$1 = ELEMENT;
  708. var DOCUMENT$1 = DOCUMENT;
  709. var is = function (element, selector) {
  710. var dom = element.dom();
  711. if (dom.nodeType !== ELEMENT$1) {
  712. return false;
  713. } else {
  714. var elem = dom;
  715. if (elem.matches !== undefined) {
  716. return elem.matches(selector);
  717. } else if (elem.msMatchesSelector !== undefined) {
  718. return elem.msMatchesSelector(selector);
  719. } else if (elem.webkitMatchesSelector !== undefined) {
  720. return elem.webkitMatchesSelector(selector);
  721. } else if (elem.mozMatchesSelector !== undefined) {
  722. return elem.mozMatchesSelector(selector);
  723. } else {
  724. throw new Error('Browser lacks native selectors');
  725. }
  726. }
  727. };
  728. var bypassSelector = function (dom) {
  729. return dom.nodeType !== ELEMENT$1 && dom.nodeType !== DOCUMENT$1 || dom.childElementCount === 0;
  730. };
  731. var all = function (selector, scope) {
  732. var base = scope === undefined ? domGlobals.document : scope.dom();
  733. return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), Element.fromDom);
  734. };
  735. var eq = function (e1, e2) {
  736. return e1.dom() === e2.dom();
  737. };
  738. var regularContains = function (e1, e2) {
  739. var d1 = e1.dom();
  740. var d2 = e2.dom();
  741. return d1 === d2 ? false : d1.contains(d2);
  742. };
  743. var ieContains = function (e1, e2) {
  744. return Node.documentPositionContainedBy(e1.dom(), e2.dom());
  745. };
  746. var browser = detect$3().browser;
  747. var contains$1 = browser.isIE() ? ieContains : regularContains;
  748. var parent = function (element) {
  749. return Option.from(element.dom().parentNode).map(Element.fromDom);
  750. };
  751. var parents = function (element, isRoot) {
  752. var stop = isFunction(isRoot) ? isRoot : never;
  753. var dom = element.dom();
  754. var ret = [];
  755. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  756. var rawParent = dom.parentNode;
  757. var p = Element.fromDom(rawParent);
  758. ret.push(p);
  759. if (stop(p) === true) {
  760. break;
  761. } else {
  762. dom = rawParent;
  763. }
  764. }
  765. return ret;
  766. };
  767. var siblings = function (element) {
  768. var filterSelf = function (elements) {
  769. return filter(elements, function (x) {
  770. return !eq(element, x);
  771. });
  772. };
  773. return parent(element).map(children).map(filterSelf).getOr([]);
  774. };
  775. var children = function (element) {
  776. return map(element.dom().childNodes, Element.fromDom);
  777. };
  778. var spot = Immutable('element', 'offset');
  779. var r = function (left, top) {
  780. var translate = function (x, y) {
  781. return r(left + x, top + y);
  782. };
  783. return {
  784. left: constant(left),
  785. top: constant(top),
  786. translate: translate
  787. };
  788. };
  789. var Position = r;
  790. var isSafari = detect$3().browser.isSafari();
  791. var get$3 = function (_DOC) {
  792. var doc = _DOC !== undefined ? _DOC.dom() : domGlobals.document;
  793. var x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  794. var y = doc.body.scrollTop || doc.documentElement.scrollTop;
  795. return Position(x, y);
  796. };
  797. var bounds = function (x, y, width, height) {
  798. return {
  799. x: constant(x),
  800. y: constant(y),
  801. width: constant(width),
  802. height: constant(height),
  803. right: constant(x + width),
  804. bottom: constant(y + height)
  805. };
  806. };
  807. var getBounds = function (_win) {
  808. var win = _win === undefined ? domGlobals.window : _win;
  809. var visualViewport = win['visualViewport'];
  810. if (visualViewport !== undefined) {
  811. return bounds(visualViewport.pageLeft, visualViewport.pageTop, visualViewport.width, visualViewport.height);
  812. } else {
  813. var doc = Element.fromDom(win.document);
  814. var html = win.document.documentElement;
  815. var scroll = get$3(doc);
  816. var width = html.clientWidth;
  817. var height = html.clientHeight;
  818. return bounds(scroll.left(), scroll.top(), width, height);
  819. }
  820. };
  821. var fireFullscreenStateChanged = function (editor, state) {
  822. editor.fire('FullscreenStateChanged', { state: state });
  823. };
  824. var Events = { fireFullscreenStateChanged: fireFullscreenStateChanged };
  825. var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
  826. var global$2 = tinymce.util.Tools.resolve('tinymce.Env');
  827. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  828. var ancestors = function (scope, predicate, isRoot) {
  829. return filter(parents(scope, isRoot), predicate);
  830. };
  831. var siblings$1 = function (scope, predicate) {
  832. return filter(siblings(scope), predicate);
  833. };
  834. var all$1 = function (selector) {
  835. return all(selector);
  836. };
  837. var ancestors$1 = function (scope, selector, isRoot) {
  838. return ancestors(scope, function (e) {
  839. return is(e, selector);
  840. }, isRoot);
  841. };
  842. var siblings$2 = function (scope, selector) {
  843. return siblings$1(scope, function (e) {
  844. return is(e, selector);
  845. });
  846. };
  847. var attr = 'data-ephox-mobile-fullscreen-style';
  848. var siblingStyles = 'display:none!important;';
  849. var ancestorPosition = 'position:absolute!important;';
  850. var ancestorStyles = 'top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;';
  851. var bgFallback = 'background-color:rgb(255,255,255)!important;';
  852. var isAndroid = global$2.os.isAndroid();
  853. var matchColor = function (editorBody) {
  854. var color = get$2(editorBody, 'background-color');
  855. return color !== undefined && color !== '' ? 'background-color:' + color + '!important' : bgFallback;
  856. };
  857. var clobberStyles = function (container, editorBody) {
  858. var gatherSibilings = function (element) {
  859. var siblings = siblings$2(element, '*:not(.tox-silver-sink)');
  860. return siblings;
  861. };
  862. var clobber = function (clobberStyle) {
  863. return function (element) {
  864. var styles = get$1(element, 'style');
  865. var backup = styles === undefined ? 'no-styles' : styles.trim();
  866. if (backup === clobberStyle) {
  867. return;
  868. } else {
  869. set(element, attr, backup);
  870. set(element, 'style', clobberStyle);
  871. }
  872. };
  873. };
  874. var ancestors = ancestors$1(container, '*');
  875. var siblings = bind(ancestors, gatherSibilings);
  876. var bgColor = matchColor(editorBody);
  877. each(siblings, clobber(siblingStyles));
  878. each(ancestors, clobber(ancestorPosition + ancestorStyles + bgColor));
  879. var containerStyles = isAndroid === true ? '' : ancestorPosition;
  880. clobber(containerStyles + ancestorStyles + bgColor)(container);
  881. };
  882. var restoreStyles = function () {
  883. var clobberedEls = all$1('[' + attr + ']');
  884. each(clobberedEls, function (element) {
  885. var restore = get$1(element, attr);
  886. if (restore !== 'no-styles') {
  887. set(element, 'style', restore);
  888. } else {
  889. remove(element, 'style');
  890. }
  891. remove(element, attr);
  892. });
  893. };
  894. var Thor = {
  895. clobberStyles: clobberStyles,
  896. restoreStyles: restoreStyles
  897. };
  898. var DOM = global$1.DOM;
  899. var getScrollPos = function () {
  900. var vp = getBounds(domGlobals.window);
  901. return {
  902. x: vp.x(),
  903. y: vp.y()
  904. };
  905. };
  906. var setScrollPos = function (pos) {
  907. domGlobals.window.scrollTo(pos.x, pos.y);
  908. };
  909. var visualViewport = domGlobals.window['visualViewport'];
  910. var isSafari$1 = global$2.browser.isSafari();
  911. var viewportUpdate = !isSafari$1 || visualViewport === undefined ? {
  912. bind: noop,
  913. unbind: noop,
  914. update: noop
  915. } : function () {
  916. var editorContainer = value();
  917. var refreshScroll = function () {
  918. domGlobals.document.body.scrollTop = 0;
  919. domGlobals.document.documentElement.scrollTop = 0;
  920. };
  921. var refreshVisualViewport = function () {
  922. domGlobals.window.requestAnimationFrame(function () {
  923. editorContainer.on(function (container) {
  924. return setAll(container, {
  925. top: visualViewport.offsetTop + 'px',
  926. left: visualViewport.offsetLeft + 'px',
  927. height: visualViewport.height + 'px',
  928. width: visualViewport.width + 'px'
  929. });
  930. });
  931. });
  932. };
  933. var update = global$3.throttle(function () {
  934. refreshScroll();
  935. refreshVisualViewport();
  936. }, 50);
  937. var bind = function (element) {
  938. editorContainer.set(element);
  939. update();
  940. visualViewport.addEventListener('resize', update);
  941. visualViewport.addEventListener('scroll', update);
  942. };
  943. var unbind = function () {
  944. editorContainer.on(function () {
  945. visualViewport.removeEventListener('scroll', update);
  946. visualViewport.removeEventListener('resize', update);
  947. });
  948. editorContainer.clear();
  949. };
  950. return {
  951. bind: bind,
  952. unbind: unbind
  953. };
  954. }();
  955. var toggleFullscreen = function (editor, fullscreenState) {
  956. var body = domGlobals.document.body;
  957. var documentElement = domGlobals.document.documentElement;
  958. var editorContainerStyle;
  959. var editorContainer, iframe, iframeStyle;
  960. editorContainer = editor.getContainer();
  961. var editorContainerS = Element.fromDom(editorContainer);
  962. var fullscreenInfo = fullscreenState.get();
  963. var editorBody = Element.fromDom(editor.getBody());
  964. var isTouch = global$2.deviceType.isTouch();
  965. editorContainerStyle = editorContainer.style;
  966. iframe = editor.getContentAreaContainer().firstChild;
  967. iframeStyle = iframe.style;
  968. if (!fullscreenInfo) {
  969. var newFullScreenInfo = {
  970. scrollPos: getScrollPos(),
  971. containerWidth: editorContainerStyle.width,
  972. containerHeight: editorContainerStyle.height,
  973. containerTop: editorContainerStyle.top,
  974. containerLeft: editorContainerStyle.left,
  975. iframeWidth: iframeStyle.width,
  976. iframeHeight: iframeStyle.height
  977. };
  978. if (isTouch) {
  979. Thor.clobberStyles(editorContainerS, editorBody);
  980. }
  981. iframeStyle.width = iframeStyle.height = '100%';
  982. editorContainerStyle.width = editorContainerStyle.height = '';
  983. DOM.addClass(body, 'tox-fullscreen');
  984. DOM.addClass(documentElement, 'tox-fullscreen');
  985. DOM.addClass(editorContainer, 'tox-fullscreen');
  986. viewportUpdate.bind(editorContainerS);
  987. editor.on('remove', viewportUpdate.unbind);
  988. fullscreenState.set(newFullScreenInfo);
  989. Events.fireFullscreenStateChanged(editor, true);
  990. } else {
  991. iframeStyle.width = fullscreenInfo.iframeWidth;
  992. iframeStyle.height = fullscreenInfo.iframeHeight;
  993. editorContainerStyle.width = fullscreenInfo.containerWidth;
  994. editorContainerStyle.height = fullscreenInfo.containerHeight;
  995. editorContainerStyle.top = fullscreenInfo.containerTop;
  996. editorContainerStyle.left = fullscreenInfo.containerLeft;
  997. if (isTouch) {
  998. Thor.restoreStyles();
  999. }
  1000. DOM.removeClass(body, 'tox-fullscreen');
  1001. DOM.removeClass(documentElement, 'tox-fullscreen');
  1002. DOM.removeClass(editorContainer, 'tox-fullscreen');
  1003. setScrollPos(fullscreenInfo.scrollPos);
  1004. fullscreenState.set(null);
  1005. Events.fireFullscreenStateChanged(editor, false);
  1006. viewportUpdate.unbind();
  1007. editor.off('remove', viewportUpdate.unbind);
  1008. }
  1009. };
  1010. var Actions = { toggleFullscreen: toggleFullscreen };
  1011. var register = function (editor, fullscreenState) {
  1012. editor.addCommand('mceFullScreen', function () {
  1013. Actions.toggleFullscreen(editor, fullscreenState);
  1014. });
  1015. };
  1016. var Commands = { register: register };
  1017. var makeSetupHandler = function (editor, fullscreenState) {
  1018. return function (api) {
  1019. api.setActive(fullscreenState.get() !== null);
  1020. var editorEventCallback = function (e) {
  1021. return api.setActive(e.state);
  1022. };
  1023. editor.on('FullscreenStateChanged', editorEventCallback);
  1024. return function () {
  1025. return editor.off('FullscreenStateChanged', editorEventCallback);
  1026. };
  1027. };
  1028. };
  1029. var register$1 = function (editor, fullscreenState) {
  1030. editor.ui.registry.addToggleMenuItem('fullscreen', {
  1031. text: 'Fullscreen',
  1032. shortcut: 'Meta+Shift+F',
  1033. onAction: function () {
  1034. return editor.execCommand('mceFullScreen');
  1035. },
  1036. onSetup: makeSetupHandler(editor, fullscreenState)
  1037. });
  1038. editor.ui.registry.addToggleButton('fullscreen', {
  1039. tooltip: 'Fullscreen',
  1040. icon: 'fullscreen',
  1041. onAction: function () {
  1042. return editor.execCommand('mceFullScreen');
  1043. },
  1044. onSetup: makeSetupHandler(editor, fullscreenState)
  1045. });
  1046. };
  1047. var Buttons = { register: register$1 };
  1048. function Plugin () {
  1049. global.add('fullscreen', function (editor) {
  1050. var fullscreenState = Cell(null);
  1051. if (editor.settings.inline) {
  1052. return Api.get(fullscreenState);
  1053. }
  1054. Commands.register(editor, fullscreenState);
  1055. Buttons.register(editor, fullscreenState);
  1056. editor.addShortcut('Meta+Shift+F', '', 'mceFullScreen');
  1057. return Api.get(fullscreenState);
  1058. });
  1059. }
  1060. Plugin();
  1061. }(window));