diff options
Diffstat (limited to 'sources/core/style.js')
-rw-r--r-- | sources/core/style.js | 82 |
1 files changed, 56 insertions, 26 deletions
diff --git a/sources/core/style.js b/sources/core/style.js index 09b117b..b3cf0bc 100644 --- a/sources/core/style.js +++ b/sources/core/style.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 | ||
@@ -235,7 +235,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
235 | var initialEnterMode = this._.enterMode; | 235 | var initialEnterMode = this._.enterMode; |
236 | 236 | ||
237 | // Before CKEditor 4.4 style knew nothing about editor, so in order to provide enterMode | 237 | // Before CKEditor 4.4 style knew nothing about editor, so in order to provide enterMode |
238 | // which should be used developers were forced to hack the style object (see #10190). | 238 | // which should be used developers were forced to hack the style object (see http://dev.ckeditor.com/ticket/10190). |
239 | // Since CKEditor 4.4 style knows about editor (at least when it's being applied/removed), but we | 239 | // Since CKEditor 4.4 style knows about editor (at least when it's being applied/removed), but we |
240 | // use _.enterMode for backward compatibility with those hacks. | 240 | // use _.enterMode for backward compatibility with those hacks. |
241 | // Note: we should not change style's enter mode if it was already set. | 241 | // Note: we should not change style's enter mode if it was already set. |
@@ -569,7 +569,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
569 | var styleVal = stylesDef[ style ], | 569 | var styleVal = stylesDef[ style ], |
570 | text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' ); | 570 | text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' ); |
571 | 571 | ||
572 | // Some browsers don't support 'inherit' property value, leave them intact. (#5242) | 572 | // Some browsers don't support 'inherit' property value, leave them intact. (http://dev.ckeditor.com/ticket/5242) |
573 | if ( styleVal == 'inherit' ) | 573 | if ( styleVal == 'inherit' ) |
574 | specialStylesText += text; | 574 | specialStylesText += text; |
575 | else | 575 | else |
@@ -1024,7 +1024,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1024 | if ( !CKEDITOR.env.ie ) | 1024 | if ( !CKEDITOR.env.ie ) |
1025 | styleNode.$.normalize(); | 1025 | styleNode.$.normalize(); |
1026 | } | 1026 | } |
1027 | // Style already inherit from parents, left just to clear up any internal overrides. (#5931) | 1027 | // Style already inherit from parents, left just to clear up any internal overrides. (http://dev.ckeditor.com/ticket/5931) |
1028 | else { | 1028 | else { |
1029 | styleNode = new CKEDITOR.dom.element( 'span' ); | 1029 | styleNode = new CKEDITOR.dom.element( 'span' ); |
1030 | styleRange.extractContents().appendTo( styleNode ); | 1030 | styleRange.extractContents().appendTo( styleNode ); |
@@ -1042,7 +1042,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1042 | // Remove the bookmark nodes. | 1042 | // Remove the bookmark nodes. |
1043 | range.moveToBookmark( boundaryNodes ); | 1043 | range.moveToBookmark( boundaryNodes ); |
1044 | 1044 | ||
1045 | // Minimize the result range to exclude empty text nodes. (#5374) | 1045 | // Minimize the result range to exclude empty text nodes. (http://dev.ckeditor.com/ticket/5374) |
1046 | range.shrink( CKEDITOR.SHRINK_TEXT ); | 1046 | range.shrink( CKEDITOR.SHRINK_TEXT ); |
1047 | 1047 | ||
1048 | // Get inside the remaining element if range.shrink( TEXT ) has failed because of non-editable elements inside. | 1048 | // Get inside the remaining element if range.shrink( TEXT ) has failed because of non-editable elements inside. |
@@ -1058,27 +1058,31 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1058 | range.enlarge( CKEDITOR.ENLARGE_INLINE, 1 ); | 1058 | range.enlarge( CKEDITOR.ENLARGE_INLINE, 1 ); |
1059 | 1059 | ||
1060 | var bookmark = range.createBookmark(), | 1060 | var bookmark = range.createBookmark(), |
1061 | startNode = bookmark.startNode; | 1061 | startNode = bookmark.startNode, |
1062 | alwaysRemoveElement = this._.definition.alwaysRemoveElement; | ||
1062 | 1063 | ||
1063 | if ( range.collapsed ) { | 1064 | if ( range.collapsed ) { |
1064 | var startPath = new CKEDITOR.dom.elementPath( startNode.getParent(), range.root ), | 1065 | var startPath = new CKEDITOR.dom.elementPath( startNode.getParent(), range.root ), |
1065 | // The topmost element in elementspatch which we should jump out of. | 1066 | // The topmost element in elements path which we should jump out of. |
1066 | boundaryElement; | 1067 | boundaryElement; |
1067 | 1068 | ||
1068 | |||
1069 | for ( var i = 0, element; i < startPath.elements.length && ( element = startPath.elements[ i ] ); i++ ) { | 1069 | for ( var i = 0, element; i < startPath.elements.length && ( element = startPath.elements[ i ] ); i++ ) { |
1070 | // 1. If it's collaped inside text nodes, try to remove the style from the whole element. | 1070 | // 1. If it's collaped inside text nodes, try to remove the style from the whole element. |
1071 | // | 1071 | // |
1072 | // 2. Otherwise if it's collapsed on element boundaries, moving the selection | 1072 | // 2. Otherwise if it's collapsed on element boundaries, moving the selection |
1073 | // outside the styles instead of removing the whole tag, | 1073 | // outside the styles instead of removing the whole tag, |
1074 | // also make sure other inner styles were well preserverd.(#3309) | 1074 | // also make sure other inner styles were well preserved.(http://dev.ckeditor.com/ticket/3309) |
1075 | if ( element == startPath.block || element == startPath.blockLimit ) | 1075 | // |
1076 | // 3. Force removing the element even if it's an boundary element when alwaysRemoveElement is true. | ||
1077 | // Without it, the links won't be unlinked if the cursor is placed right before/after it. (http://dev.ckeditor.com/ticket/13062) | ||
1078 | if ( element == startPath.block || element == startPath.blockLimit ) { | ||
1076 | break; | 1079 | break; |
1080 | } | ||
1077 | 1081 | ||
1078 | if ( this.checkElementRemovable( element ) ) { | 1082 | if ( this.checkElementRemovable( element ) ) { |
1079 | var isStart; | 1083 | var isStart; |
1080 | 1084 | ||
1081 | if ( range.collapsed && ( range.checkBoundaryOfElement( element, CKEDITOR.END ) || ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) ) { | 1085 | if ( !alwaysRemoveElement && range.collapsed && ( range.checkBoundaryOfElement( element, CKEDITOR.END ) || ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) ) { |
1082 | boundaryElement = element; | 1086 | boundaryElement = element; |
1083 | boundaryElement.match = isStart ? 'start' : 'end'; | 1087 | boundaryElement.match = isStart ? 'start' : 'end'; |
1084 | } else { | 1088 | } else { |
@@ -1087,10 +1091,11 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1087 | // no difference that they're separate entities in the DOM tree. So, merge | 1091 | // no difference that they're separate entities in the DOM tree. So, merge |
1088 | // them before removal. | 1092 | // them before removal. |
1089 | element.mergeSiblings(); | 1093 | element.mergeSiblings(); |
1090 | if ( element.is( this.element ) ) | 1094 | if ( element.is( this.element ) ) { |
1091 | removeFromElement.call( this, element ); | 1095 | removeFromElement.call( this, element ); |
1092 | else | 1096 | } else { |
1093 | removeOverrides( element, getOverrides( this )[ element.getName() ] ); | 1097 | removeOverrides( element, getOverrides( this )[ element.getName() ] ); |
1098 | } | ||
1094 | } | 1099 | } |
1095 | } | 1100 | } |
1096 | } | 1101 | } |
@@ -1235,7 +1240,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1235 | } | 1240 | } |
1236 | 1241 | ||
1237 | function applyObjectStyle( range ) { | 1242 | function applyObjectStyle( range ) { |
1238 | // Selected or parent element. (#9651) | 1243 | // Selected or parent element. (http://dev.ckeditor.com/ticket/9651) |
1239 | var start = range.getEnclosedNode() || range.getCommonAncestor( false, true ), | 1244 | var start = range.getEnclosedNode() || range.getCommonAncestor( false, true ), |
1240 | element = new CKEDITOR.dom.elementPath( start, range.root ).contains( this.element, 1 ); | 1245 | element = new CKEDITOR.dom.elementPath( start, range.root ).contains( this.element, 1 ); |
1241 | 1246 | ||
@@ -1276,7 +1281,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1276 | var iterator = range.createIterator(); | 1281 | var iterator = range.createIterator(); |
1277 | iterator.enforceRealBlocks = true; | 1282 | iterator.enforceRealBlocks = true; |
1278 | 1283 | ||
1279 | // make recognize <br /> tag as a separator in ENTER_BR mode (#5121) | 1284 | // make recognize <br /> tag as a separator in ENTER_BR mode (http://dev.ckeditor.com/ticket/5121) |
1280 | if ( this._.enterMode ) | 1285 | if ( this._.enterMode ) |
1281 | iterator.enlargeBr = ( this._.enterMode != CKEDITOR.ENTER_BR ); | 1286 | iterator.enlargeBr = ( this._.enterMode != CKEDITOR.ENTER_BR ); |
1282 | 1287 | ||
@@ -1326,7 +1331,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1326 | 1331 | ||
1327 | // Replace the original block with new one, with special treatment | 1332 | // Replace the original block with new one, with special treatment |
1328 | // for <pre> blocks to make sure content format is well preserved, and merging/splitting adjacent | 1333 | // for <pre> blocks to make sure content format is well preserved, and merging/splitting adjacent |
1329 | // when necessary. (#3188) | 1334 | // when necessary. (http://dev.ckeditor.com/ticket/3188) |
1330 | function replaceBlock( block, newBlock ) { | 1335 | function replaceBlock( block, newBlock ) { |
1331 | // Block is to be removed, create a temp element to | 1336 | // Block is to be removed, create a temp element to |
1332 | // save contents. | 1337 | // save contents. |
@@ -1502,11 +1507,11 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1502 | 1507 | ||
1503 | // Remove definition attributes/style from the elemnt. | 1508 | // Remove definition attributes/style from the elemnt. |
1504 | for ( var attName in attributes ) { | 1509 | for ( var attName in attributes ) { |
1505 | // The 'class' element value must match (#1318). | 1510 | // The 'class' element value must match (http://dev.ckeditor.com/ticket/1318). |
1506 | if ( ( attName == 'class' || this._.definition.fullMatch ) && element.getAttribute( attName ) != normalizeProperty( attName, attributes[ attName ] ) ) | 1511 | if ( ( attName == 'class' || this._.definition.fullMatch ) && element.getAttribute( attName ) != normalizeProperty( attName, attributes[ attName ] ) ) |
1507 | continue; | 1512 | continue; |
1508 | 1513 | ||
1509 | // Do not touch data-* attributes (#11011) (#11258). | 1514 | // Do not touch data-* attributes (http://dev.ckeditor.com/ticket/11011) (http://dev.ckeditor.com/ticket/11258). |
1510 | if ( keepDataAttrs && attName.slice( 0, 5 ) == 'data-' ) | 1515 | if ( keepDataAttrs && attName.slice( 0, 5 ) == 'data-' ) |
1511 | continue; | 1516 | continue; |
1512 | 1517 | ||
@@ -1515,7 +1520,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1515 | } | 1520 | } |
1516 | 1521 | ||
1517 | for ( var styleName in styles ) { | 1522 | for ( var styleName in styles ) { |
1518 | // Full match style insist on having fully equivalence. (#5018) | 1523 | // Full match style insist on having fully equivalence. (http://dev.ckeditor.com/ticket/5018) |
1519 | if ( this._.definition.fullMatch && element.getStyle( styleName ) != normalizeProperty( styleName, styles[ styleName ], true ) ) | 1524 | if ( this._.definition.fullMatch && element.getStyle( styleName ) != normalizeProperty( styleName, styles[ styleName ], true ) ) |
1520 | continue; | 1525 | continue; |
1521 | 1526 | ||
@@ -1649,7 +1654,7 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1649 | // Create the element. | 1654 | // Create the element. |
1650 | el = new CKEDITOR.dom.element( elementName, targetDocument ); | 1655 | el = new CKEDITOR.dom.element( elementName, targetDocument ); |
1651 | 1656 | ||
1652 | // #6226: attributes should be copied before the new ones are applied | 1657 | // http://dev.ckeditor.com/ticket/6226: attributes should be copied before the new ones are applied |
1653 | if ( element ) | 1658 | if ( element ) |
1654 | element.copyAttributes( el ); | 1659 | element.copyAttributes( el ); |
1655 | 1660 | ||
@@ -1794,15 +1799,28 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1794 | // is treated as a wildcard which will match any value. | 1799 | // is treated as a wildcard which will match any value. |
1795 | // @param {Object/String} source | 1800 | // @param {Object/String} source |
1796 | // @param {Object/String} target | 1801 | // @param {Object/String} target |
1802 | // @returns {Boolean} | ||
1797 | function compareCssText( source, target ) { | 1803 | function compareCssText( source, target ) { |
1804 | function filter( string, propertyName ) { | ||
1805 | // In case of font-families we'll skip quotes. (http://dev.ckeditor.com/ticket/10750) | ||
1806 | return propertyName.toLowerCase() == 'font-family' ? string.replace( /["']/g, '' ) : string; | ||
1807 | } | ||
1808 | |||
1798 | if ( typeof source == 'string' ) | 1809 | if ( typeof source == 'string' ) |
1799 | source = CKEDITOR.tools.parseCssText( source ); | 1810 | source = CKEDITOR.tools.parseCssText( source ); |
1800 | if ( typeof target == 'string' ) | 1811 | if ( typeof target == 'string' ) |
1801 | target = CKEDITOR.tools.parseCssText( target, true ); | 1812 | target = CKEDITOR.tools.parseCssText( target, true ); |
1802 | 1813 | ||
1803 | for ( var name in source ) { | 1814 | for ( var name in source ) { |
1804 | if ( !( name in target && ( target[ name ] == source[ name ] || source[ name ] == 'inherit' || target[ name ] == 'inherit' ) ) ) | 1815 | if ( !( name in target ) ) { |
1805 | return false; | 1816 | return false; |
1817 | } | ||
1818 | |||
1819 | if ( !( filter( target[ name ], name ) == filter( source[ name ], name ) || | ||
1820 | source[ name ] == 'inherit' || | ||
1821 | target[ name ] == 'inherit' ) ) { | ||
1822 | return false; | ||
1823 | } | ||
1806 | } | 1824 | } |
1807 | return true; | 1825 | return true; |
1808 | } | 1826 | } |
@@ -1811,13 +1829,25 @@ CKEDITOR.STYLE_OBJECT = 3; | |||
1811 | var doc = selection.document, | 1829 | var doc = selection.document, |
1812 | ranges = selection.getRanges(), | 1830 | ranges = selection.getRanges(), |
1813 | func = remove ? this.removeFromRange : this.applyToRange, | 1831 | func = remove ? this.removeFromRange : this.applyToRange, |
1814 | range; | 1832 | originalRanges, |
1833 | range, | ||
1834 | i; | ||
1835 | |||
1836 | // In case of fake table selection, we would like to apply all styles and then select | ||
1837 | // the original ranges. Otherwise browsers would complain about discontiguous selection. | ||
1838 | if ( selection.isFake && selection.isInTable() ) { | ||
1839 | originalRanges = []; | ||
1840 | |||
1841 | for ( i = 0; i < ranges.length; i++ ) { | ||
1842 | originalRanges.push( ranges[ i ].clone() ); | ||
1843 | } | ||
1844 | } | ||
1815 | 1845 | ||
1816 | var iterator = ranges.createIterator(); | 1846 | var iterator = ranges.createIterator(); |
1817 | while ( ( range = iterator.getNextRange() ) ) | 1847 | while ( ( range = iterator.getNextRange() ) ) |
1818 | func.call( this, range, editor ); | 1848 | func.call( this, range, editor ); |
1819 | 1849 | ||
1820 | selection.selectRanges( ranges ); | 1850 | selection.selectRanges( originalRanges || ranges ); |
1821 | doc.removeCustomData( 'doc_processing_style' ); | 1851 | doc.removeCustomData( 'doc_processing_style' ); |
1822 | } | 1852 | } |
1823 | } )(); | 1853 | } )(); |
@@ -1888,7 +1918,7 @@ CKEDITOR.styleCommand.prototype.exec = function( editor ) { | |||
1888 | */ | 1918 | */ |
1889 | CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' ); | 1919 | CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' ); |
1890 | 1920 | ||
1891 | // Backward compatibility (#5025). | 1921 | // Backward compatibility (http://dev.ckeditor.com/ticket/5025). |
1892 | CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet ); | 1922 | CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet ); |
1893 | CKEDITOR.loadStylesSet = function( name, url, callback ) { | 1923 | CKEDITOR.loadStylesSet = function( name, url, callback ) { |
1894 | CKEDITOR.stylesSet.addExternal( name, url, '' ); | 1924 | CKEDITOR.stylesSet.addExternal( name, url, '' ); |
@@ -1991,7 +2021,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, { | |||
1991 | return; | 2021 | return; |
1992 | } | 2022 | } |
1993 | 2023 | ||
1994 | // #5352 Allow to define the styles directly in the config object | 2024 | // http://dev.ckeditor.com/ticket/5352 Allow to define the styles directly in the config object |
1995 | if ( configStyleSet instanceof Array ) { | 2025 | if ( configStyleSet instanceof Array ) { |
1996 | editor._.stylesDefinitions = configStyleSet; | 2026 | editor._.stylesDefinitions = configStyleSet; |
1997 | callback( configStyleSet ); | 2027 | callback( configStyleSet ); |