plugin.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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 global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  12. var unique = 0;
  13. var generate = function (prefix) {
  14. var date = new Date();
  15. var time = date.getTime();
  16. var random = Math.floor(Math.random() * 1000000000);
  17. unique++;
  18. return prefix + '_' + random + unique + String(time);
  19. };
  20. var createTableHtml = function (cols, rows) {
  21. var x, y, html;
  22. html = '<table data-mce-id="mce" style="width: 100%">';
  23. html += '<tbody>';
  24. for (y = 0; y < rows; y++) {
  25. html += '<tr>';
  26. for (x = 0; x < cols; x++) {
  27. html += '<td><br></td>';
  28. }
  29. html += '</tr>';
  30. }
  31. html += '</tbody>';
  32. html += '</table>';
  33. return html;
  34. };
  35. var getInsertedElement = function (editor) {
  36. var elms = editor.dom.select('*[data-mce-id]');
  37. return elms[0];
  38. };
  39. var insertTableHtml = function (editor, cols, rows) {
  40. editor.undoManager.transact(function () {
  41. var tableElm, cellElm;
  42. editor.insertContent(createTableHtml(cols, rows));
  43. tableElm = getInsertedElement(editor);
  44. tableElm.removeAttribute('data-mce-id');
  45. cellElm = editor.dom.select('td,th', tableElm);
  46. editor.selection.setCursorLocation(cellElm[0], 0);
  47. });
  48. };
  49. var insertTable = function (editor, cols, rows) {
  50. editor.plugins.table ? editor.plugins.table.insertTable(cols, rows) : insertTableHtml(editor, cols, rows);
  51. };
  52. var insertBlob = function (editor, base64, blob) {
  53. var blobCache, blobInfo;
  54. blobCache = editor.editorUpload.blobCache;
  55. blobInfo = blobCache.create(generate('mceu'), blob, base64);
  56. blobCache.add(blobInfo);
  57. editor.insertContent(editor.dom.createHTML('img', { src: blobInfo.blobUri() }));
  58. };
  59. var Actions = {
  60. insertTable: insertTable,
  61. insertBlob: insertBlob
  62. };
  63. var global$1 = tinymce.util.Tools.resolve('tinymce.util.Promise');
  64. var blobToBase64 = function (blob) {
  65. return new global$1(function (resolve) {
  66. var reader = new domGlobals.FileReader();
  67. reader.onloadend = function () {
  68. resolve(reader.result.split(',')[1]);
  69. };
  70. reader.readAsDataURL(blob);
  71. });
  72. };
  73. var Conversions = { blobToBase64: blobToBase64 };
  74. var global$2 = tinymce.util.Tools.resolve('tinymce.Env');
  75. var global$3 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  76. var pickFile = function (editor) {
  77. return new global$1(function (resolve) {
  78. var fileInput = domGlobals.document.createElement('input');
  79. fileInput.type = 'file';
  80. fileInput.style.position = 'fixed';
  81. fileInput.style.left = '0';
  82. fileInput.style.top = '0';
  83. fileInput.style.opacity = '0.001';
  84. domGlobals.document.body.appendChild(fileInput);
  85. var changeHandler = function (e) {
  86. resolve(Array.prototype.slice.call(e.target.files));
  87. };
  88. fileInput.addEventListener('change', changeHandler);
  89. var cancelHandler = function (e) {
  90. var cleanup = function () {
  91. resolve([]);
  92. fileInput.parentNode.removeChild(fileInput);
  93. };
  94. if (global$2.os.isAndroid() && e.type !== 'remove') {
  95. global$3.setEditorTimeout(editor, cleanup, 0);
  96. } else {
  97. cleanup();
  98. }
  99. editor.off('focusin remove', cancelHandler);
  100. };
  101. editor.on('focusin remove', cancelHandler);
  102. fileInput.click();
  103. });
  104. };
  105. var Picker = { pickFile: pickFile };
  106. var setupButtons = function (editor) {
  107. editor.ui.registry.addButton('quickimage', {
  108. icon: 'image',
  109. tooltip: 'Insert image',
  110. onAction: function () {
  111. Picker.pickFile(editor).then(function (files) {
  112. if (files.length > 0) {
  113. var blob_1 = files[0];
  114. Conversions.blobToBase64(blob_1).then(function (base64) {
  115. Actions.insertBlob(editor, base64, blob_1);
  116. });
  117. }
  118. });
  119. }
  120. });
  121. editor.ui.registry.addButton('quicktable', {
  122. icon: 'table',
  123. tooltip: 'Insert table',
  124. onAction: function () {
  125. Actions.insertTable(editor, 2, 2);
  126. }
  127. });
  128. };
  129. var InsertButtons = { setupButtons: setupButtons };
  130. var noop = function () {
  131. };
  132. var constant = function (value) {
  133. return function () {
  134. return value;
  135. };
  136. };
  137. var never = constant(false);
  138. var always = constant(true);
  139. var none = function () {
  140. return NONE;
  141. };
  142. var NONE = function () {
  143. var eq = function (o) {
  144. return o.isNone();
  145. };
  146. var call = function (thunk) {
  147. return thunk();
  148. };
  149. var id = function (n) {
  150. return n;
  151. };
  152. var me = {
  153. fold: function (n, s) {
  154. return n();
  155. },
  156. is: never,
  157. isSome: never,
  158. isNone: always,
  159. getOr: id,
  160. getOrThunk: call,
  161. getOrDie: function (msg) {
  162. throw new Error(msg || 'error: getOrDie called on none.');
  163. },
  164. getOrNull: constant(null),
  165. getOrUndefined: constant(undefined),
  166. or: id,
  167. orThunk: call,
  168. map: none,
  169. each: noop,
  170. bind: none,
  171. exists: never,
  172. forall: always,
  173. filter: none,
  174. equals: eq,
  175. equals_: eq,
  176. toArray: function () {
  177. return [];
  178. },
  179. toString: constant('none()')
  180. };
  181. if (Object.freeze) {
  182. Object.freeze(me);
  183. }
  184. return me;
  185. }();
  186. var some = function (a) {
  187. var constant_a = constant(a);
  188. var self = function () {
  189. return me;
  190. };
  191. var bind = function (f) {
  192. return f(a);
  193. };
  194. var me = {
  195. fold: function (n, s) {
  196. return s(a);
  197. },
  198. is: function (v) {
  199. return a === v;
  200. },
  201. isSome: always,
  202. isNone: never,
  203. getOr: constant_a,
  204. getOrThunk: constant_a,
  205. getOrDie: constant_a,
  206. getOrNull: constant_a,
  207. getOrUndefined: constant_a,
  208. or: self,
  209. orThunk: self,
  210. map: function (f) {
  211. return some(f(a));
  212. },
  213. each: function (f) {
  214. f(a);
  215. },
  216. bind: bind,
  217. exists: bind,
  218. forall: bind,
  219. filter: function (f) {
  220. return f(a) ? me : NONE;
  221. },
  222. toArray: function () {
  223. return [a];
  224. },
  225. toString: function () {
  226. return 'some(' + a + ')';
  227. },
  228. equals: function (o) {
  229. return o.is(a);
  230. },
  231. equals_: function (o, elementEq) {
  232. return o.fold(never, function (b) {
  233. return elementEq(a, b);
  234. });
  235. }
  236. };
  237. return me;
  238. };
  239. var from = function (value) {
  240. return value === null || value === undefined ? NONE : some(value);
  241. };
  242. var Option = {
  243. some: some,
  244. none: none,
  245. from: from
  246. };
  247. var fromHtml = function (html, scope) {
  248. var doc = scope || domGlobals.document;
  249. var div = doc.createElement('div');
  250. div.innerHTML = html;
  251. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  252. domGlobals.console.error('HTML does not have a single root node', html);
  253. throw new Error('HTML must have a single root node');
  254. }
  255. return fromDom(div.childNodes[0]);
  256. };
  257. var fromTag = function (tag, scope) {
  258. var doc = scope || domGlobals.document;
  259. var node = doc.createElement(tag);
  260. return fromDom(node);
  261. };
  262. var fromText = function (text, scope) {
  263. var doc = scope || domGlobals.document;
  264. var node = doc.createTextNode(text);
  265. return fromDom(node);
  266. };
  267. var fromDom = function (node) {
  268. if (node === null || node === undefined) {
  269. throw new Error('Node cannot be null or undefined');
  270. }
  271. return { dom: constant(node) };
  272. };
  273. var fromPoint = function (docElm, x, y) {
  274. var doc = docElm.dom();
  275. return Option.from(doc.elementFromPoint(x, y)).map(fromDom);
  276. };
  277. var Element = {
  278. fromHtml: fromHtml,
  279. fromTag: fromTag,
  280. fromText: fromText,
  281. fromDom: fromDom,
  282. fromPoint: fromPoint
  283. };
  284. var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE;
  285. var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE;
  286. var COMMENT = domGlobals.Node.COMMENT_NODE;
  287. var DOCUMENT = domGlobals.Node.DOCUMENT_NODE;
  288. var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE;
  289. var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE;
  290. var ELEMENT = domGlobals.Node.ELEMENT_NODE;
  291. var TEXT = domGlobals.Node.TEXT_NODE;
  292. var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE;
  293. var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE;
  294. var ENTITY = domGlobals.Node.ENTITY_NODE;
  295. var NOTATION = domGlobals.Node.NOTATION_NODE;
  296. var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')();
  297. var name = function (element) {
  298. var r = element.dom().nodeName;
  299. return r.toLowerCase();
  300. };
  301. var typeOf = function (x) {
  302. if (x === null) {
  303. return 'null';
  304. }
  305. var t = typeof x;
  306. if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
  307. return 'array';
  308. }
  309. if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
  310. return 'string';
  311. }
  312. return t;
  313. };
  314. var isType = function (type) {
  315. return function (value) {
  316. return typeOf(value) === type;
  317. };
  318. };
  319. var isString = isType('string');
  320. var isObject = isType('object');
  321. var isArray = isType('array');
  322. var isBoolean = isType('boolean');
  323. var isUndefined = isType('undefined');
  324. var isFunction = isType('function');
  325. var nativeSlice = Array.prototype.slice;
  326. var find = function (xs, pred) {
  327. for (var i = 0, len = xs.length; i < len; i++) {
  328. var x = xs[i];
  329. if (pred(x, i)) {
  330. return Option.some(x);
  331. }
  332. }
  333. return Option.none();
  334. };
  335. var from$1 = isFunction(Array.from) ? Array.from : function (x) {
  336. return nativeSlice.call(x);
  337. };
  338. function ClosestOrAncestor (is, ancestor, scope, a, isRoot) {
  339. return is(scope, a) ? Option.some(scope) : isFunction(isRoot) && isRoot(scope) ? Option.none() : ancestor(scope, a, isRoot);
  340. }
  341. var compareDocumentPosition = function (a, b, match) {
  342. return (a.compareDocumentPosition(b) & match) !== 0;
  343. };
  344. var documentPositionPreceding = function (a, b) {
  345. return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_PRECEDING);
  346. };
  347. var documentPositionContainedBy = function (a, b) {
  348. return compareDocumentPosition(a, b, domGlobals.Node.DOCUMENT_POSITION_CONTAINED_BY);
  349. };
  350. var Node = {
  351. documentPositionPreceding: documentPositionPreceding,
  352. documentPositionContainedBy: documentPositionContainedBy
  353. };
  354. var Cell = function (initial) {
  355. var value = initial;
  356. var get = function () {
  357. return value;
  358. };
  359. var set = function (v) {
  360. value = v;
  361. };
  362. var clone = function () {
  363. return Cell(get());
  364. };
  365. return {
  366. get: get,
  367. set: set,
  368. clone: clone
  369. };
  370. };
  371. var firstMatch = function (regexes, s) {
  372. for (var i = 0; i < regexes.length; i++) {
  373. var x = regexes[i];
  374. if (x.test(s)) {
  375. return x;
  376. }
  377. }
  378. return undefined;
  379. };
  380. var find$1 = function (regexes, agent) {
  381. var r = firstMatch(regexes, agent);
  382. if (!r) {
  383. return {
  384. major: 0,
  385. minor: 0
  386. };
  387. }
  388. var group = function (i) {
  389. return Number(agent.replace(r, '$' + i));
  390. };
  391. return nu(group(1), group(2));
  392. };
  393. var detect = function (versionRegexes, agent) {
  394. var cleanedAgent = String(agent).toLowerCase();
  395. if (versionRegexes.length === 0) {
  396. return unknown();
  397. }
  398. return find$1(versionRegexes, cleanedAgent);
  399. };
  400. var unknown = function () {
  401. return nu(0, 0);
  402. };
  403. var nu = function (major, minor) {
  404. return {
  405. major: major,
  406. minor: minor
  407. };
  408. };
  409. var Version = {
  410. nu: nu,
  411. detect: detect,
  412. unknown: unknown
  413. };
  414. var edge = 'Edge';
  415. var chrome = 'Chrome';
  416. var ie = 'IE';
  417. var opera = 'Opera';
  418. var firefox = 'Firefox';
  419. var safari = 'Safari';
  420. var isBrowser = function (name, current) {
  421. return function () {
  422. return current === name;
  423. };
  424. };
  425. var unknown$1 = function () {
  426. return nu$1({
  427. current: undefined,
  428. version: Version.unknown()
  429. });
  430. };
  431. var nu$1 = function (info) {
  432. var current = info.current;
  433. var version = info.version;
  434. return {
  435. current: current,
  436. version: version,
  437. isEdge: isBrowser(edge, current),
  438. isChrome: isBrowser(chrome, current),
  439. isIE: isBrowser(ie, current),
  440. isOpera: isBrowser(opera, current),
  441. isFirefox: isBrowser(firefox, current),
  442. isSafari: isBrowser(safari, current)
  443. };
  444. };
  445. var Browser = {
  446. unknown: unknown$1,
  447. nu: nu$1,
  448. edge: constant(edge),
  449. chrome: constant(chrome),
  450. ie: constant(ie),
  451. opera: constant(opera),
  452. firefox: constant(firefox),
  453. safari: constant(safari)
  454. };
  455. var windows = 'Windows';
  456. var ios = 'iOS';
  457. var android = 'Android';
  458. var linux = 'Linux';
  459. var osx = 'OSX';
  460. var solaris = 'Solaris';
  461. var freebsd = 'FreeBSD';
  462. var chromeos = 'ChromeOS';
  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. isChromeOS: isOS(chromeos, current)
  488. };
  489. };
  490. var OperatingSystem = {
  491. unknown: unknown$2,
  492. nu: nu$2,
  493. windows: constant(windows),
  494. ios: constant(ios),
  495. android: constant(android),
  496. linux: constant(linux),
  497. osx: constant(osx),
  498. solaris: constant(solaris),
  499. freebsd: constant(freebsd),
  500. chromeos: constant(chromeos)
  501. };
  502. var DeviceType = function (os, browser, userAgent, mediaMatch) {
  503. var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  504. var isiPhone = os.isiOS() && !isiPad;
  505. var isMobile = os.isiOS() || os.isAndroid();
  506. var isTouch = isMobile || mediaMatch('(pointer:coarse)');
  507. var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  508. var isPhone = isiPhone || isMobile && !isTablet;
  509. var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  510. var isDesktop = !isPhone && !isTablet && !iOSwebview;
  511. return {
  512. isiPad: constant(isiPad),
  513. isiPhone: constant(isiPhone),
  514. isTablet: constant(isTablet),
  515. isPhone: constant(isPhone),
  516. isTouch: constant(isTouch),
  517. isAndroid: os.isAndroid,
  518. isiOS: os.isiOS,
  519. isWebView: constant(iOSwebview),
  520. isDesktop: constant(isDesktop)
  521. };
  522. };
  523. var detect$1 = function (candidates, userAgent) {
  524. var agent = String(userAgent).toLowerCase();
  525. return find(candidates, function (candidate) {
  526. return candidate.search(agent);
  527. });
  528. };
  529. var detectBrowser = function (browsers, userAgent) {
  530. return detect$1(browsers, userAgent).map(function (browser) {
  531. var version = Version.detect(browser.versionRegexes, userAgent);
  532. return {
  533. current: browser.name,
  534. version: version
  535. };
  536. });
  537. };
  538. var detectOs = function (oses, userAgent) {
  539. return detect$1(oses, userAgent).map(function (os) {
  540. var version = Version.detect(os.versionRegexes, userAgent);
  541. return {
  542. current: os.name,
  543. version: version
  544. };
  545. });
  546. };
  547. var UaString = {
  548. detectBrowser: detectBrowser,
  549. detectOs: detectOs
  550. };
  551. var contains = function (str, substr) {
  552. return str.indexOf(substr) !== -1;
  553. };
  554. var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  555. var checkContains = function (target) {
  556. return function (uastring) {
  557. return contains(uastring, target);
  558. };
  559. };
  560. var browsers = [
  561. {
  562. name: 'Edge',
  563. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  564. search: function (uastring) {
  565. return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
  566. }
  567. },
  568. {
  569. name: 'Chrome',
  570. versionRegexes: [
  571. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  572. normalVersionRegex
  573. ],
  574. search: function (uastring) {
  575. return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
  576. }
  577. },
  578. {
  579. name: 'IE',
  580. versionRegexes: [
  581. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  582. /.*?rv:([0-9]+)\.([0-9]+).*/
  583. ],
  584. search: function (uastring) {
  585. return contains(uastring, 'msie') || contains(uastring, 'trident');
  586. }
  587. },
  588. {
  589. name: 'Opera',
  590. versionRegexes: [
  591. normalVersionRegex,
  592. /.*?opera\/([0-9]+)\.([0-9]+).*/
  593. ],
  594. search: checkContains('opera')
  595. },
  596. {
  597. name: 'Firefox',
  598. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  599. search: checkContains('firefox')
  600. },
  601. {
  602. name: 'Safari',
  603. versionRegexes: [
  604. normalVersionRegex,
  605. /.*?cpu os ([0-9]+)_([0-9]+).*/
  606. ],
  607. search: function (uastring) {
  608. return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
  609. }
  610. }
  611. ];
  612. var oses = [
  613. {
  614. name: 'Windows',
  615. search: checkContains('win'),
  616. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  617. },
  618. {
  619. name: 'iOS',
  620. search: function (uastring) {
  621. return contains(uastring, 'iphone') || contains(uastring, 'ipad');
  622. },
  623. versionRegexes: [
  624. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  625. /.*cpu os ([0-9]+)_([0-9]+).*/,
  626. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  627. ]
  628. },
  629. {
  630. name: 'Android',
  631. search: checkContains('android'),
  632. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  633. },
  634. {
  635. name: 'OSX',
  636. search: checkContains('mac os x'),
  637. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
  638. },
  639. {
  640. name: 'Linux',
  641. search: checkContains('linux'),
  642. versionRegexes: []
  643. },
  644. {
  645. name: 'Solaris',
  646. search: checkContains('sunos'),
  647. versionRegexes: []
  648. },
  649. {
  650. name: 'FreeBSD',
  651. search: checkContains('freebsd'),
  652. versionRegexes: []
  653. },
  654. {
  655. name: 'ChromeOS',
  656. search: checkContains('cros'),
  657. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
  658. }
  659. ];
  660. var PlatformInfo = {
  661. browsers: constant(browsers),
  662. oses: constant(oses)
  663. };
  664. var detect$2 = function (userAgent, mediaMatch) {
  665. var browsers = PlatformInfo.browsers();
  666. var oses = PlatformInfo.oses();
  667. var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu);
  668. var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  669. var deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  670. return {
  671. browser: browser,
  672. os: os,
  673. deviceType: deviceType
  674. };
  675. };
  676. var PlatformDetection = { detect: detect$2 };
  677. var mediaMatch = function (query) {
  678. return domGlobals.window.matchMedia(query).matches;
  679. };
  680. var platform = Cell(PlatformDetection.detect(domGlobals.navigator.userAgent, mediaMatch));
  681. var detect$3 = function () {
  682. return platform.get();
  683. };
  684. var ELEMENT$1 = ELEMENT;
  685. var is = function (element, selector) {
  686. var dom = element.dom();
  687. if (dom.nodeType !== ELEMENT$1) {
  688. return false;
  689. } else {
  690. var elem = dom;
  691. if (elem.matches !== undefined) {
  692. return elem.matches(selector);
  693. } else if (elem.msMatchesSelector !== undefined) {
  694. return elem.msMatchesSelector(selector);
  695. } else if (elem.webkitMatchesSelector !== undefined) {
  696. return elem.webkitMatchesSelector(selector);
  697. } else if (elem.mozMatchesSelector !== undefined) {
  698. return elem.mozMatchesSelector(selector);
  699. } else {
  700. throw new Error('Browser lacks native selectors');
  701. }
  702. }
  703. };
  704. var regularContains = function (e1, e2) {
  705. var d1 = e1.dom();
  706. var d2 = e2.dom();
  707. return d1 === d2 ? false : d1.contains(d2);
  708. };
  709. var ieContains = function (e1, e2) {
  710. return Node.documentPositionContainedBy(e1.dom(), e2.dom());
  711. };
  712. var browser = detect$3().browser;
  713. var contains$1 = browser.isIE() ? ieContains : regularContains;
  714. var ancestor = function (scope, predicate, isRoot) {
  715. var element = scope.dom();
  716. var stop = isFunction(isRoot) ? isRoot : constant(false);
  717. while (element.parentNode) {
  718. element = element.parentNode;
  719. var el = Element.fromDom(element);
  720. if (predicate(el)) {
  721. return Option.some(el);
  722. } else if (stop(el)) {
  723. break;
  724. }
  725. }
  726. return Option.none();
  727. };
  728. var closest = function (scope, predicate, isRoot) {
  729. var is = function (s, test) {
  730. return test(s);
  731. };
  732. return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot);
  733. };
  734. var ancestor$1 = function (scope, selector, isRoot) {
  735. return ancestor(scope, function (e) {
  736. return is(e, selector);
  737. }, isRoot);
  738. };
  739. var closest$1 = function (scope, selector, isRoot) {
  740. return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
  741. };
  742. var validDefaultOrDie = function (value, predicate) {
  743. if (predicate(value)) {
  744. return true;
  745. }
  746. throw new Error('Default value doesn\'t match requested type.');
  747. };
  748. var items = function (value, defaultValue) {
  749. if (isArray(value) || isObject(value)) {
  750. throw new Error('expected a string but found: ' + value);
  751. }
  752. if (isUndefined(value)) {
  753. return defaultValue;
  754. }
  755. if (isBoolean(value)) {
  756. return value === false ? '' : defaultValue;
  757. }
  758. return value;
  759. };
  760. var getToolbarItemsOr = function (predicate) {
  761. return function (editor, name, defaultValue) {
  762. validDefaultOrDie(defaultValue, predicate);
  763. var value = editor.getParam(name, defaultValue);
  764. return items(value, defaultValue);
  765. };
  766. };
  767. var EditorSettings = { getToolbarItemsOr: getToolbarItemsOr(isString) };
  768. var getTextSelectionToolbarItems = function (editor) {
  769. return EditorSettings.getToolbarItemsOr(editor, 'quickbars_selection_toolbar', 'bold italic | quicklink h2 h3 blockquote');
  770. };
  771. var getInsertToolbarItems = function (editor) {
  772. return EditorSettings.getToolbarItemsOr(editor, 'quickbars_insert_toolbar', 'quickimage quicktable');
  773. };
  774. var getImageToolbarItems = function (editor) {
  775. return EditorSettings.getToolbarItemsOr(editor, 'quickbars_image_toolbar', 'alignleft aligncenter alignright');
  776. };
  777. var Settings = {
  778. getTextSelectionToolbarItems: getTextSelectionToolbarItems,
  779. getInsertToolbarItems: getInsertToolbarItems,
  780. getImageToolbarItems: getImageToolbarItems
  781. };
  782. var addToEditor = function (editor) {
  783. var insertToolbarItems = Settings.getInsertToolbarItems(editor);
  784. if (insertToolbarItems.trim().length > 0) {
  785. editor.ui.registry.addContextToolbar('quickblock', {
  786. predicate: function (node) {
  787. var sugarNode = Element.fromDom(node);
  788. var textBlockElementsMap = editor.schema.getTextBlockElements();
  789. var isRoot = function (elem) {
  790. return elem.dom() === editor.getBody();
  791. };
  792. return closest$1(sugarNode, 'table', isRoot).fold(function () {
  793. return closest(sugarNode, function (elem) {
  794. return name(elem) in textBlockElementsMap && editor.dom.isEmpty(elem.dom());
  795. }, isRoot).isSome();
  796. }, function () {
  797. return false;
  798. });
  799. },
  800. items: insertToolbarItems,
  801. position: 'line',
  802. scope: 'editor'
  803. });
  804. }
  805. };
  806. var InsertToolbars = { addToEditor: addToEditor };
  807. var addToEditor$1 = function (editor) {
  808. var isEditable = function (node) {
  809. return editor.dom.getContentEditableParent(node) !== 'false';
  810. };
  811. var isImage = function (node) {
  812. return node.nodeName === 'IMG' || node.nodeName === 'FIGURE' && /image/i.test(node.className);
  813. };
  814. var imageToolbarItems = Settings.getImageToolbarItems(editor);
  815. if (imageToolbarItems.trim().length > 0) {
  816. editor.ui.registry.addContextToolbar('imageselection', {
  817. predicate: isImage,
  818. items: imageToolbarItems,
  819. position: 'node'
  820. });
  821. }
  822. var textToolbarItems = Settings.getTextSelectionToolbarItems(editor);
  823. if (textToolbarItems.trim().length > 0) {
  824. editor.ui.registry.addContextToolbar('textselection', {
  825. predicate: function (node) {
  826. return !isImage(node) && !editor.selection.isCollapsed() && isEditable(node);
  827. },
  828. items: textToolbarItems,
  829. position: 'selection',
  830. scope: 'editor'
  831. });
  832. }
  833. };
  834. var SelectionToolbars = { addToEditor: addToEditor$1 };
  835. function Plugin () {
  836. global.add('quickbars', function (editor) {
  837. InsertButtons.setupButtons(editor);
  838. InsertToolbars.addToEditor(editor);
  839. SelectionToolbars.addToEditor(editor);
  840. });
  841. }
  842. Plugin();
  843. }(window));