diff options
Diffstat (limited to 'sources/core/tools.js')
-rw-r--r-- | sources/core/tools.js | 701 |
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 ) |