plugin.js 36 KB

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