aboutsummaryrefslogtreecommitdiff
path: root/sources/core/tools.js
diff options
context:
space:
mode:
Diffstat (limited to 'sources/core/tools.js')
-rw-r--r--sources/core/tools.js701
1 files changed, 694 insertions, 7 deletions
diff --git a/sources/core/tools.js b/sources/core/tools.js
index ae5b4d0..a4b736d 100644
--- a/sources/core/tools.js
+++ b/sources/core/tools.js
@@ -1,5 +1,5 @@
1/** 1/**
2 * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. 2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license 3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */ 4 */
5 5
@@ -981,6 +981,23 @@
981 }, 981 },
982 982
983 /** 983 /**
984 * Normalizes hexadecimal notation so that the color string is always 6 characters long and lowercase.
985 *
986 * @param {String} styleText The style data (or just a string containing hex colors) to be converted.
987 * @returns {String} The style data with hex colors normalized.
988 */
989 normalizeHex: function( styleText ) {
990 return styleText.replace( /#(([0-9a-f]{3}){1,2})($|;|\s+)/gi, function( match, hexColor, hexColorPart, separator ) {
991 var normalizedHexColor = hexColor.toLowerCase();
992 if ( normalizedHexColor.length == 3 ) {
993 var parts = normalizedHexColor.split( '' );
994 normalizedHexColor = [ parts[ 0 ], parts[ 0 ], parts[ 1 ], parts[ 1 ], parts[ 2 ], parts[ 2 ] ].join( '' );
995 }
996 return '#' + normalizedHexColor + separator;
997 } );
998 },
999
1000 /**
984 * Turns inline style text properties into one hash. 1001 * Turns inline style text properties into one hash.
985 * 1002 *
986 * @param {String} styleText The style data to be parsed. 1003 * @param {String} styleText The style data to be parsed.
@@ -996,21 +1013,24 @@
996 // Injects the style in a temporary span object, so the browser parses it, 1013 // Injects the style in a temporary span object, so the browser parses it,
997 // retrieving its final format. 1014 // retrieving its final format.
998 var temp = new CKEDITOR.dom.element( 'span' ); 1015 var temp = new CKEDITOR.dom.element( 'span' );
999 temp.setAttribute( 'style', styleText ); 1016 styleText = temp.setAttribute( 'style', styleText ).getAttribute( 'style' ) || '';
1000 styleText = CKEDITOR.tools.convertRgbToHex( temp.getAttribute( 'style' ) || '' ); 1017 }
1018
1019 // Normalize colors.
1020 if ( styleText ) {
1021 styleText = CKEDITOR.tools.normalizeHex( CKEDITOR.tools.convertRgbToHex( styleText ) );
1001 } 1022 }
1002 1023
1003 // IE will leave a single semicolon when failed to parse the style text. (#3891) 1024 // IE will leave a single semicolon when failed to parse the style text. (http://dev.ckeditor.com/ticket/3891)
1004 if ( !styleText || styleText == ';' ) 1025 if ( !styleText || styleText == ';' )
1005 return retval; 1026 return retval;
1006 1027
1007 styleText.replace( /"/g, '"' ).replace( /\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g, function( match, name, value ) { 1028 styleText.replace( /"/g, '"' ).replace( /\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g, function( match, name, value ) {
1008 if ( normalize ) { 1029 if ( normalize ) {
1009 name = name.toLowerCase(); 1030 name = name.toLowerCase();
1010 // Normalize font-family property, ignore quotes and being case insensitive. (#7322) 1031 // Drop extra whitespacing from font-family.
1011 // http://www.w3.org/TR/css3-fonts/#font-family-the-font-family-property
1012 if ( name == 'font-family' ) 1032 if ( name == 'font-family' )
1013 value = value.toLowerCase().replace( /["']/g, '' ).replace( /\s*,\s*/g, ',' ); 1033 value = value.replace( /\s*,\s*/g, ',' );
1014 value = CKEDITOR.tools.trim( value ); 1034 value = CKEDITOR.tools.trim( value );
1015 } 1035 }
1016 1036
@@ -1293,6 +1313,67 @@
1293 }, 1313 },
1294 1314
1295 /** 1315 /**
1316 * Converts a keystroke to its string representation. Returns an object with two fields:
1317 *
1318 * * `display` – A string that should be used for visible labels.
1319 * For Mac devices it uses `⌥` for `ALT`, `⇧` for `SHIFT` and `⌘` for `COMMAND`.
1320 * * `aria` – A string that should be used for ARIA descriptions.
1321 * It does not use special characters such as `⌥`, `⇧` or `⌘`.
1322 *
1323 * var lang = editor.lang.common.keyboard;
1324 * var shortcut = CKEDITOR.tools.keystrokeToString( lang, CKEDITOR.CTRL + 88 );
1325 * console.log( shortcut.display ); // 'CTRL + X', on Mac '⌘ + X'.
1326 * console.log( shortcut.aria ); // 'CTRL + X', on Mac 'COMMAND + X'.
1327 *
1328 * @since 4.6.0
1329 * @param {Object} lang A language object with the key name translation.
1330 * @param {Number} keystroke The keystroke to convert.
1331 * @returns {{display: String, aria: String}}
1332 */
1333 keystrokeToString: function( lang, keystroke ) {
1334 var special = keystroke & 0xFF0000,
1335 key = keystroke & 0x00FFFF,
1336 isMac = CKEDITOR.env.mac,
1337 CTRL = 17,
1338 CMD = 224,
1339 ALT = 18,
1340 SHIFT = 16,
1341 display = [],
1342 aria = [];
1343
1344
1345 if ( special & CKEDITOR.CTRL ) {
1346 display.push( isMac ? '⌘' : lang[ CTRL ] );
1347 aria.push( isMac ? lang[ CMD ] : lang[ CTRL ] );
1348 }
1349
1350 if ( special & CKEDITOR.ALT ) {
1351 display.push( isMac ? '⌥' : lang[ ALT ] );
1352 aria.push( lang[ ALT ] );
1353 }
1354
1355 if ( special & CKEDITOR.SHIFT ) {
1356 display.push( isMac ? '⇧' : lang[ SHIFT ] );
1357 aria.push( lang[ SHIFT ] );
1358 }
1359
1360 if ( key ) {
1361 if ( lang[ key ] ) {
1362 display.push( lang[ key ] );
1363 aria.push( lang[ key ] );
1364 } else {
1365 display.push( String.fromCharCode( key ) );
1366 aria.push( String.fromCharCode( key ) );
1367 }
1368 }
1369
1370 return {
1371 display: display.join( '+' ),
1372 aria: aria.join( '+' )
1373 };
1374 },
1375
1376 /**
1296 * The data URI of a transparent image. May be used e.g. in HTML as an image source or in CSS in `url()`. 1377 * The data URI of a transparent image. May be used e.g. in HTML as an image source or in CSS in `url()`.
1297 * 1378 *
1298 * @since 4.4 1379 * @since 4.4
@@ -1353,6 +1434,540 @@
1353 } 1434 }
1354 1435
1355 return token; 1436 return token;
1437 },
1438
1439 /**
1440 * Returns an escaped CSS selector. `CSS.escape()` is used if defined, leading digit is escaped otherwise.
1441 *
1442 * @since 4.5.10
1443 * @param {String} selector A CSS selector to escape.
1444 * @returns {String} An escaped selector.
1445 */
1446 escapeCss: function( selector ) {
1447 // Invalid input.
1448 if ( !selector ) {
1449 return '';
1450 }
1451
1452 // CSS.escape() can be used.
1453 if ( window.CSS && CSS.escape ) {
1454 return CSS.escape( selector );
1455 }
1456
1457 // Simple leading digit escape.
1458 if ( !isNaN( parseInt( selector.charAt( 0 ), 10 ) ) ) {
1459 return '\\3' + selector.charAt( 0 ) + ' ' + selector.substring( 1, selector.length );
1460 }
1461
1462 return selector;
1463 },
1464
1465 /**
1466 * Detects which mouse button generated a given DOM event.
1467 *
1468 * @since 4.7.3
1469 * @param {CKEDITOR.dom.event} evt DOM event.
1470 * @returns {Number|Boolean} Returns a number indicating the mouse button or `false`
1471 * if the mouse button cannot be determined.
1472 */
1473 getMouseButton: function( evt ) {
1474 var evtData = evt.data,
1475 domEvent = evtData && evtData.$;
1476
1477 if ( !( evtData && domEvent ) ) {
1478 // Added in case when there's no data available. That's the case in some unit test in built version which
1479 // mock event but doesn't put data object.
1480 return false;
1481 }
1482
1483 if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
1484 if ( domEvent.button === 4 ) {
1485 return CKEDITOR.MOUSE_BUTTON_MIDDLE;
1486 } else if ( domEvent.button === 1 ) {
1487 return CKEDITOR.MOUSE_BUTTON_LEFT;
1488 } else {
1489 return CKEDITOR.MOUSE_BUTTON_RIGHT;
1490 }
1491 }
1492
1493 return domEvent.button;
1494 },
1495
1496 /**
1497 * A set of functions for operations on styles.
1498 *
1499 * @property {CKEDITOR.tools.style}
1500 */
1501 style: {
1502 /**
1503 * Methods to parse miscellaneous CSS properties.
1504 *
1505 * @property {CKEDITOR.tools.style.parse}
1506 * @member CKEDITOR.tools.style
1507 */
1508 parse: {
1509 // Color list based on https://www.w3.org/TR/css-color-4/#named-colors.
1510 _colors: {
1511 aliceblue: '#F0F8FF',
1512 antiquewhite: '#FAEBD7',
1513 aqua: '#00FFFF',
1514 aquamarine: '#7FFFD4',
1515 azure: '#F0FFFF',
1516 beige: '#F5F5DC',
1517 bisque: '#FFE4C4',
1518 black: '#000000',
1519 blanchedalmond: '#FFEBCD',
1520 blue: '#0000FF',
1521 blueviolet: '#8A2BE2',
1522 brown: '#A52A2A',
1523 burlywood: '#DEB887',
1524 cadetblue: '#5F9EA0',
1525 chartreuse: '#7FFF00',
1526 chocolate: '#D2691E',
1527 coral: '#FF7F50',
1528 cornflowerblue: '#6495ED',
1529 cornsilk: '#FFF8DC',
1530 crimson: '#DC143C',
1531 cyan: '#00FFFF',
1532 darkblue: '#00008B',
1533 darkcyan: '#008B8B',
1534 darkgoldenrod: '#B8860B',
1535 darkgray: '#A9A9A9',
1536 darkgreen: '#006400',
1537 darkgrey: '#A9A9A9',
1538 darkkhaki: '#BDB76B',
1539 darkmagenta: '#8B008B',
1540 darkolivegreen: '#556B2F',
1541 darkorange: '#FF8C00',
1542 darkorchid: '#9932CC',
1543 darkred: '#8B0000',
1544 darksalmon: '#E9967A',
1545 darkseagreen: '#8FBC8F',
1546 darkslateblue: '#483D8B',
1547 darkslategray: '#2F4F4F',
1548 darkslategrey: '#2F4F4F',
1549 darkturquoise: '#00CED1',
1550 darkviolet: '#9400D3',
1551 deeppink: '#FF1493',
1552 deepskyblue: '#00BFFF',
1553 dimgray: '#696969',
1554 dimgrey: '#696969',
1555 dodgerblue: '#1E90FF',
1556 firebrick: '#B22222',
1557 floralwhite: '#FFFAF0',
1558 forestgreen: '#228B22',
1559 fuchsia: '#FF00FF',
1560 gainsboro: '#DCDCDC',
1561 ghostwhite: '#F8F8FF',
1562 gold: '#FFD700',
1563 goldenrod: '#DAA520',
1564 gray: '#808080',
1565 green: '#008000',
1566 greenyellow: '#ADFF2F',
1567 grey: '#808080',
1568 honeydew: '#F0FFF0',
1569 hotpink: '#FF69B4',
1570 indianred: '#CD5C5C',
1571 indigo: '#4B0082',
1572 ivory: '#FFFFF0',
1573 khaki: '#F0E68C',
1574 lavender: '#E6E6FA',
1575 lavenderblush: '#FFF0F5',
1576 lawngreen: '#7CFC00',
1577 lemonchiffon: '#FFFACD',
1578 lightblue: '#ADD8E6',
1579 lightcoral: '#F08080',
1580 lightcyan: '#E0FFFF',
1581 lightgoldenrodyellow: '#FAFAD2',
1582 lightgray: '#D3D3D3',
1583 lightgreen: '#90EE90',
1584 lightgrey: '#D3D3D3',
1585 lightpink: '#FFB6C1',
1586 lightsalmon: '#FFA07A',
1587 lightseagreen: '#20B2AA',
1588 lightskyblue: '#87CEFA',
1589 lightslategray: '#778899',
1590 lightslategrey: '#778899',
1591 lightsteelblue: '#B0C4DE',
1592 lightyellow: '#FFFFE0',
1593 lime: '#00FF00',
1594 limegreen: '#32CD32',
1595 linen: '#FAF0E6',
1596 magenta: '#FF00FF',
1597 maroon: '#800000',
1598 mediumaquamarine: '#66CDAA',
1599 mediumblue: '#0000CD',
1600 mediumorchid: '#BA55D3',
1601 mediumpurple: '#9370DB',
1602 mediumseagreen: '#3CB371',
1603 mediumslateblue: '#7B68EE',
1604 mediumspringgreen: '#00FA9A',
1605 mediumturquoise: '#48D1CC',
1606 mediumvioletred: '#C71585',
1607 midnightblue: '#191970',
1608 mintcream: '#F5FFFA',
1609 mistyrose: '#FFE4E1',
1610 moccasin: '#FFE4B5',
1611 navajowhite: '#FFDEAD',
1612 navy: '#000080',
1613 oldlace: '#FDF5E6',
1614 olive: '#808000',
1615 olivedrab: '#6B8E23',
1616 orange: '#FFA500',
1617 orangered: '#FF4500',
1618 orchid: '#DA70D6',
1619 palegoldenrod: '#EEE8AA',
1620 palegreen: '#98FB98',
1621 paleturquoise: '#AFEEEE',
1622 palevioletred: '#DB7093',
1623 papayawhip: '#FFEFD5',
1624 peachpuff: '#FFDAB9',
1625 peru: '#CD853F',
1626 pink: '#FFC0CB',
1627 plum: '#DDA0DD',
1628 powderblue: '#B0E0E6',
1629 purple: '#800080',
1630 rebeccapurple: '#663399',
1631 red: '#FF0000',
1632 rosybrown: '#BC8F8F',
1633 royalblue: '#4169E1',
1634 saddlebrown: '#8B4513',
1635 salmon: '#FA8072',
1636 sandybrown: '#F4A460',
1637 seagreen: '#2E8B57',
1638 seashell: '#FFF5EE',
1639 sienna: '#A0522D',
1640 silver: '#C0C0C0',
1641 skyblue: '#87CEEB',
1642 slateblue: '#6A5ACD',
1643 slategray: '#708090',
1644 slategrey: '#708090',
1645 snow: '#FFFAFA',
1646 springgreen: '#00FF7F',
1647 steelblue: '#4682B4',
1648 tan: '#D2B48C',
1649 teal: '#008080',
1650 thistle: '#D8BFD8',
1651 tomato: '#FF6347',
1652 turquoise: '#40E0D0',
1653 violet: '#EE82EE',
1654 wheat: '#F5DEB3',
1655 white: '#FFFFFF',
1656 whitesmoke: '#F5F5F5',
1657 yellow: '#FFFF00',
1658 yellowgreen: '#9ACD32'
1659 },
1660
1661 _borderStyle: [
1662 'none',
1663 'hidden',
1664 'dotted',
1665 'dashed',
1666 'solid',
1667 'double',
1668 'groove',
1669 'ridge',
1670 'inset',
1671 'outset'
1672 ],
1673
1674 _widthRegExp: /^(thin|medium|thick|[\+-]?\d+(\.\d+)?[a-z%]+|[\+-]?0+(\.0+)?|\.\d+[a-z%]+)$/,
1675
1676 _rgbaRegExp: /rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi,
1677
1678 _hslaRegExp: /hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi,
1679
1680 /**
1681 * Parses the `value` used as a `background` property shorthand and returns information as an object.
1682 *
1683 * **Note:** Currently only the `color` property is extracted. Any other parts will go into the `unprocessed` property.
1684 *
1685 * var background = CKEDITOR.tools.style.parse.background( '#0C0 url(foo.png)' );
1686 * console.log( background );
1687 * // Logs: { color: '#0C0', unprocessed: 'url(foo.png)' }
1688 *
1689 * @param {String} value The value of the `background` property.
1690 * @returns {Object} An object with information extracted from the background.
1691 * @returns {String} return.color The **first** color value found. The color format remains the same as in input.
1692 * @returns {String} return.unprocessed The remaining part of the `value` that has not been processed.
1693 * @member CKEDITOR.tools.style.parse
1694 */
1695 background: function( value ) {
1696 var ret = {},
1697 colors = this._findColor( value );
1698
1699 if ( colors.length ) {
1700 ret.color = colors[ 0 ];
1701
1702 CKEDITOR.tools.array.forEach( colors, function( colorToken ) {
1703 value = value.replace( colorToken, '' );
1704 } );
1705 }
1706
1707 value = CKEDITOR.tools.trim( value );
1708
1709 if ( value ) {
1710 // If anything was left unprocessed include it as unprocessed part.
1711 ret.unprocessed = value;
1712 }
1713
1714 return ret;
1715 },
1716
1717 /**
1718 * Parses the `margin` CSS property shorthand format.
1719 *
1720 * console.log( CKEDITOR.tools.parse.margin( '3px 0 2' ) );
1721 * // Logs: { top: "3px", right: "0", bottom: "2", left: "0" }
1722 *
1723 * @param {String} value The `margin` property value.
1724 * @returns {Object}
1725 * @returns {Number} return.top Top margin.
1726 * @returns {Number} return.right Right margin.
1727 * @returns {Number} return.bottom Bottom margin.
1728 * @returns {Number} return.left Left margin.
1729 * @member CKEDITOR.tools.style.parse
1730 */
1731 margin: function( value ) {
1732 var ret = {};
1733
1734 var widths = value.match( /(?:\-?[\.\d]+(?:%|\w*)|auto|inherit|initial|unset)/g ) || [ '0px' ];
1735
1736 switch ( widths.length ) {
1737 case 1:
1738 mapStyles( [ 0, 0, 0, 0 ] );
1739 break;
1740 case 2:
1741 mapStyles( [ 0, 1, 0, 1 ] );
1742 break;
1743 case 3:
1744 mapStyles( [ 0, 1, 2, 1 ] );
1745 break;
1746 case 4:
1747 mapStyles( [ 0, 1, 2, 3 ] );
1748 break;
1749 }
1750
1751 function mapStyles( map ) {
1752 ret.top = widths[ map[ 0 ] ];
1753 ret.right = widths[ map[ 1 ] ];
1754 ret.bottom = widths[ map[ 2 ] ];
1755 ret.left = widths[ map[ 3 ] ];
1756 }
1757
1758 return ret;
1759 },
1760
1761 /**
1762 * Parses the `border` CSS property shorthand format.
1763 * This CSS property does not support inheritance (https://www.w3.org/TR/css3-background/#the-border-shorthands).
1764 *
1765 * console.log( CKEDITOR.tools.style.parse.border( '3px solid #ffeedd' ) );
1766 * // Logs: { width: "3px", style: "solid", color: "#ffeedd" }
1767 *
1768 * @param {String} value The `border` property value.
1769 * @returns {Object}
1770 * @returns {String} return.width The border-width attribute.
1771 * @returns {String} return.style The border-style attribute.
1772 * @returns {String} return.color The border-color attribute.
1773 * @member CKEDITOR.tools.style.parse
1774 */
1775 border: function( value ) {
1776 var ret = {},
1777 input = value.split( /\s+/ );
1778
1779 CKEDITOR.tools.array.forEach( input, function( val ) {
1780 if ( !ret.color ) {
1781 var parseColor = CKEDITOR.tools.style.parse._findColor( val );
1782 if ( parseColor.length ) {
1783 ret.color = parseColor[ 0 ];
1784 return;
1785 }
1786 }
1787
1788 if ( !ret.style ) {
1789 if ( CKEDITOR.tools.indexOf( CKEDITOR.tools.style.parse._borderStyle, val ) !== -1 ) {
1790 ret.style = val;
1791 return;
1792 }
1793 }
1794
1795 if ( !ret.width ) {
1796 if ( CKEDITOR.tools.style.parse._widthRegExp.test( val ) ) {
1797 ret.width = val;
1798 return;
1799 }
1800 }
1801
1802 } );
1803 return ret;
1804 },
1805
1806 /**
1807 * Searches the `value` for any CSS color occurrences and returns it.
1808 *
1809 * @private
1810 * @param {String} value
1811 * @returns {String[]} An array of matched results.
1812 * @member CKEDITOR.tools.style.parse
1813 */
1814 _findColor: function( value ) {
1815 var ret = [],
1816 arrayTools = CKEDITOR.tools.array;
1817
1818
1819 // Check for rgb(a).
1820 ret = ret.concat( value.match( this._rgbaRegExp ) || [] );
1821
1822 // Check for hsl(a).
1823 ret = ret.concat( value.match( this._hslaRegExp ) || [] );
1824
1825 ret = ret.concat( arrayTools.filter( value.split( /\s+/ ), function( colorEntry ) {
1826 // Check for hex format.
1827 if ( colorEntry.match( /^\#[a-f0-9]{3}(?:[a-f0-9]{3})?$/gi ) ) {
1828 return true;
1829 }
1830
1831 // Check for preset names.
1832 return colorEntry.toLowerCase() in CKEDITOR.tools.style.parse._colors;
1833 } ) );
1834
1835 return ret;
1836 }
1837 }
1838 },
1839
1840 /**
1841 * A set of array helpers.
1842 *
1843 * @property {CKEDITOR.tools.array}
1844 * @member CKEDITOR.tools
1845 */
1846 array: {
1847 /**
1848 * Returns a copy of `array` filtered using the `fn` function. Any elements that the `fn` will return `false` for
1849 * will get removed from the returned array.
1850 *
1851 * var filtered = this.array.filter( [ 0, 1, 2, 3 ], function( value ) {
1852 * // Leave only values equal or greater than 2.
1853 * return value >= 2;
1854 * } );
1855 * console.log( filtered );
1856 * // Logs: [ 2, 3 ]
1857 *
1858 * @param {Array} array
1859 * @param {Function} fn A function that gets called with each `array` item. Any item that `fn`
1860 * returned a `false`-alike value for will be filtered out of the `array`.
1861 * @param {Mixed} fn.value The currently iterated array value.
1862 * @param {Number} fn.index The index of the currently iterated value in an array.
1863 * @param {Array} fn.array The original array passed as the `array` variable.
1864 * @param {Mixed} [thisArg=undefined] A context object for `fn`.
1865 * @returns {Array} The filtered array.
1866 * @member CKEDITOR.tools.array
1867 */
1868 filter: function( array, fn, thisArg ) {
1869 var ret = [];
1870
1871 this.forEach( array, function( val, i ) {
1872 if ( fn.call( thisArg, val, i, array ) ) {
1873 ret.push( val );
1874 }
1875 } );
1876
1877 return ret;
1878 },
1879
1880 /**
1881 * Iterates over every element in the `array`.
1882 *
1883 * @param {Array} array An array to be iterated over.
1884 * @param {Function} fn The function called for every `array` element.
1885 * @param {Mixed} fn.value The currently iterated array value.
1886 * @param {Number} fn.index The index of the currently iterated value in an array.
1887 * @param {Array} fn.array The original array passed as an `array` variable.
1888 * @param {Mixed} [thisArg=undefined] The context object for `fn`.
1889 * @member CKEDITOR.tools.array
1890 */
1891 forEach: function( array, fn, thisArg ) {
1892 var len = array.length,
1893 i;
1894
1895 for ( i = 0; i < len; i++ ) {
1896 fn.call( thisArg, array[ i ], i, array );
1897 }
1898 },
1899
1900 /**
1901 * Applies a function to each element of an array and returns the array of results in the same order.
1902 * Note the order of the parameters.
1903 *
1904 * @param {Array} array An array of elements that `fn` is applied on.
1905 * @param {Function} fn A function with the signature `a -> b`.
1906 * @param {Mixed} [thisArg=undefined] The context object for `fn`.
1907 * @returns {Array} An array of mapped elements.
1908 * @member CKEDITOR.tools.array
1909 * @since 4.6.2
1910 */
1911 map: function( array, fn, thisArg ) {
1912 var result = [];
1913 for ( var i = 0; i < array.length; i++ ) {
1914 result.push( fn.call( thisArg, array[ i ], i, array ) );
1915 }
1916 return result;
1917 },
1918
1919 /**
1920 * Applies a function against each value in an array storing the result in an accumulator passed to the next iteration.
1921 * Note the order of the parameters.
1922 *
1923 * @param {Array} array An array of elements that `fn` is applied on.
1924 * @param {Function} fn A function with the signature `(accumulator, a, index, array) -> b`.
1925 * @param {Mixed} initial Initial value of the accumulator.
1926 * @param {Mixed} [thisArg=undefined] The context object for `fn`.
1927 * @returns {Mixed} The final value of the accumulator.
1928 * @member CKEDITOR.tools.array
1929 * @since 4.6.2
1930 */
1931 reduce: function( array, fn, initial, thisArg ) {
1932 var acc = initial;
1933 for ( var i = 0; i < array.length; i++ ) {
1934 acc = fn.call( thisArg, acc, array[ i ], i, array );
1935 }
1936 return acc;
1937 }
1938 },
1939
1940 /**
1941 * A set of object helpers.
1942 *
1943 * @property {CKEDITOR.tools.object}
1944 * @member CKEDITOR.tools
1945 */
1946 object: {
1947 /**
1948 * Returns the first key from `obj` which has a given `value`.
1949 *
1950 * @param {Object} obj An object whose `key` is looked for.
1951 * @param {Mixed} value An object's `value` to be looked for.
1952 * @returns {String/null} Matched `key` or `null` if not found.
1953 * @member CKEDITOR.tools.object
1954 */
1955
1956 findKey: function( obj, value ) {
1957 if ( typeof obj !== 'object' ) {
1958 return null;
1959 }
1960
1961 var key;
1962
1963 for ( key in obj ) {
1964 if ( obj[ key ] === value ) {
1965 return key;
1966 }
1967 }
1968
1969 return null;
1970 }
1356 } 1971 }
1357 }; 1972 };
1358 1973
@@ -1381,6 +1996,78 @@
1381 1996
1382 return result; 1997 return result;
1383 } 1998 }
1999
2000 /**
2001 * @member CKEDITOR.tools.array
2002 * @method indexOf
2003 * @inheritdoc CKEDITOR.tools#indexOf
2004 */
2005 CKEDITOR.tools.array.indexOf = CKEDITOR.tools.indexOf;
2006
2007 /**
2008 * @member CKEDITOR.tools.array
2009 * @method isArray
2010 * @inheritdoc CKEDITOR.tools#isArray
2011 */
2012 CKEDITOR.tools.array.isArray = CKEDITOR.tools.isArray;
2013
2014 /**
2015 * Left mouse button.
2016 *
2017 * @since 4.7.3
2018 * @readonly
2019 * @property {Number} [=0]
2020 * @member CKEDITOR
2021 */
2022 CKEDITOR.MOUSE_BUTTON_LEFT = 0;
2023
2024 /**
2025 * Middle mouse button.
2026 *
2027 * @since 4.7.3
2028 * @readonly
2029 * @property {Number} [=1]
2030 * @member CKEDITOR
2031 */
2032 CKEDITOR.MOUSE_BUTTON_MIDDLE = 1;
2033
2034 /**
2035 * Right mouse button.
2036 *
2037 * @since 4.7.3
2038 * @readonly
2039 * @property {Number} [=2]
2040 * @member CKEDITOR
2041 */
2042 CKEDITOR.MOUSE_BUTTON_RIGHT = 2;
2043
2044 /**
2045 * The namespace containing functions to work on CSS properties.
2046 *
2047 * @since 4.6.1
2048 * @class CKEDITOR.tools.style
2049 */
2050
2051 /**
2052 * The namespace with helper functions to parse some common CSS properties.
2053 *
2054 * @since 4.6.1
2055 * @class CKEDITOR.tools.style.parse
2056 */
2057
2058 /**
2059 * The namespace with helper functions and polyfills for arrays.
2060 *
2061 * @since 4.6.1
2062 * @class CKEDITOR.tools.array
2063 */
2064
2065 /**
2066 * The namespace with helper functions and polyfills for objects.
2067 *
2068 * @since 4.7.1
2069 * @class CKEDITOR.tools.object
2070 */
1384} )(); 2071} )();
1385 2072
1386// PACKAGER_RENAME( CKEDITOR.tools ) 2073// PACKAGER_RENAME( CKEDITOR.tools )