aboutsummaryrefslogtreecommitdiff
path: root/sources/core/style.js
diff options
context:
space:
mode:
Diffstat (limited to 'sources/core/style.js')
-rw-r--r--sources/core/style.js82
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 */
1889CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' ); 1919CKEDITOR.stylesSet = new CKEDITOR.resourceManager( '', 'stylesSet' );
1890 1920
1891// Backward compatibility (#5025). 1921// Backward compatibility (http://dev.ckeditor.com/ticket/5025).
1892CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet ); 1922CKEDITOR.addStylesSet = CKEDITOR.tools.bind( CKEDITOR.stylesSet.add, CKEDITOR.stylesSet );
1893CKEDITOR.loadStylesSet = function( name, url, callback ) { 1923CKEDITOR.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 );