ncludeReadonly == undefined ) includeReadonly = document.getCustomData( 'cke_includeReadonly' ); // Get the DTD definition for the element. Defaults to "span". var dtd = CKEDITOR.dtd[ elementName ] || ( isUnknownElement = true, CKEDITOR.dtd.span ); // Expand the range. range.enlarge( CKEDITOR.ENLARGE_ELEMENT, 1 ); range.trim(); // Get the first node to be processed and the last, which concludes the // processing. var boundaryNodes = range.createBookmark(), firstNode = boundaryNodes.startNode, lastNode = boundaryNodes.endNode; var currentNode = firstNode; var styleRange; // Check if the boundaries are inside non stylable elements. var firstUnstylable = getUnstylableParent( firstNode ), lastUnstylable = getUnstylableParent( lastNode ); // If the first element can't be styled, we'll start processing right // after its unstylable root. if ( firstUnstylable ) currentNode = firstUnstylable.getNextSourceNode( true ); // If the last element can't be styled, we'll stop processing on its // unstylable root. if ( lastUnstylable ) lastNode = lastUnstylable; // Do nothing if the current node now follows the last node to be processed. if ( currentNode.getPosition( lastNode ) == CKEDITOR.POSITION_FOLLOWING ) currentNode = 0; while ( currentNode ) { var applyStyle = false; if ( currentNode.equals( lastNode ) ) { currentNode = null; applyStyle = true; } else { var nodeType = currentNode.type; var nodeName = nodeType == CKEDITOR.NODE_ELEMENT ? currentNode.getName() : null; var nodeIsReadonly = nodeName && ( currentNode.getAttribute( 'contentEditable' ) == 'false' ); var nodeIsNoStyle = nodeName && currentNode.getAttribute( 'data-nostyle' ); if ( nodeName && currentNode.data( 'cke-bookmark' ) ) { currentNode = currentNode.getNextSourceNode( true ); continue; } // Check if the current node can be a child of the style element. if ( !nodeName || ( dtd[ nodeName ] && !nodeIsNoStyle && ( !nodeIsReadonly || includeReadonly ) && ( currentNode.getPosition( lastNode ) | CKEDITOR.POSITION_PRECEDING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) && ( !def.childRule || def.childRule( currentNode ) ) ) ) { var currentParent = currentNode.getParent(); // Check if the style element can be a child of the current // node parent or if the element is not defined in the DTD. if ( currentParent && ( ( currentParent.getDtd() || CKEDITOR.dtd.span )[ elementName ] || isUnknownElement ) && ( !def.parentRule || def.parentRule( currentParent ) ) ) { // This node will be part of our range, so if it has not // been started, place its start right before the node. // In the case of an element node, it will be included // only if it is entirely inside the range. if ( !styleRange && ( !nodeName || !CKEDITOR.dtd.$removeEmpty[ nodeName ] || ( currentNode.getPosition( lastNode ) | CKEDITOR.POSITION_PRECEDING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) ) ) { styleRange = new CKEDITOR.dom.range( document ); styleRange.setStartBefore( currentNode ); } // Non element nodes, readonly elements, or empty // elements can be added completely to the range. if ( nodeType == CKEDITOR.NODE_TEXT || nodeIsReadonly || ( nodeType == CKEDITOR.NODE_ELEMENT && !currentNode.getChildCount() ) ) { var includedNode = currentNode; var parentNode; // This node is about to be included completelly, but, // if this is the last node in its parent, we must also // check if the parent itself can be added completelly // to the range, otherwise apply the style immediately. while ( ( applyStyle = !includedNode.getNext( notBookmark ) ) && ( parentNode = includedNode.getParent(), dtd[ parentNode.getName() ] ) && ( parentNode.getPosition( firstNode ) | CKEDITOR.POSITION_FOLLOWING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_FOLLOWING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) && ( !def.childRule || def.childRule( parentNode ) ) ) { includedNode = parentNode; } styleRange.setEndAfter( includedNode ); } } else applyStyle = true; } else applyStyle = true; // Get the next node to be processed. currentNode = currentNode.getNextSourceNode( nodeIsNoStyle || nodeIsReadonly ); } // Apply the style if we have something to which apply it. if ( applyStyle && styleRange && !styleRange.collapsed ) { // Build the style element, based on the style object definition. var styleNode = getElement( this, document ), styleHasAttrs = styleNode.hasAttributes(); // Get the element that holds the entire range. var parent = styleRange.getCommonAncestor(); var removeList = { styles : {}, attrs : {}, // Styles cannot be removed. blockedStyles : {}, // Attrs cannot be removed. blockedAttrs : {} }; var attName, styleName, value; // Loop through the parents, removing the redundant attributes // from the element to be applied. while ( styleNode && parent ) { if ( parent.getName() == elementName ) { for ( attName in def.attributes ) { if ( removeList.blockedAttrs[ attName ] || !( value = parent.getAttribute( styleName ) ) ) continue; if ( styleNode.getAttribute( attName ) == value ) removeList.attrs[ attName ] = 1; else removeList.blockedAttrs[ attName ] = 1; } for ( styleName in def.styles ) { if ( removeList.blockedStyles[ styleName ] || !( value = parent.getStyle( styleName ) ) ) continue; if ( styleNode.getStyle( styleName ) == value ) removeList.styles[ styleName ] = 1; else removeList.blockedStyles[ styleName ] = 1; } } parent = parent.getParent(); } for ( attName in removeList.attrs ) styleNode.removeAttribute( attName ); for ( styleName in removeList.styles ) styleNode.removeStyle( styleName ); if ( styleHasAttrs && !styleNode.hasAttributes() ) styleNode = null; if ( styleNode ) { // Move the contents of the range to the style element. styleRange.extractContents().appendTo( styleNode ); // Here we do some cleanup, removing all duplicated // elements from the style element. removeFromInsideElement( this, styleNode ); // Insert it into the range position (it is collapsed after // extractContents. styleRange.insertNode( styleNode ); // Let's merge our new style with its neighbors, if possible. styleNode.mergeSiblings(); // As the style system breaks text nodes constantly, let's normalize // things for performance. // With IE, some paragraphs get broken when calling normalize() // repeatedly. Also, for IE, we must normalize body, not documentElement. // IE is also known for having a "crash effect" with normalize(). // We should try to normalize with IE too in some way, somewhere. if ( !CKEDITOR.env.ie ) styleNode.$.normalize(); } // Style already inherit from parents, left just to clear up any internal overrides. (#5931) else { styleNode = new CKEDITOR.dom.element( 'span' ); styleRange.extractContents().appendTo( styleNode ); styleRange.insertNode( styleNode ); removeFromInsideElement( this, styleNode ); styleNode.remove( true ); } // Style applied, let's release the range, so it gets // re-initialization in the next loop. styleRange = null; } } // Remove the bookmark nodes. range.moveToBookmark( boundaryNodes ); // Minimize the result range to exclude empty text nodes. (#5374) range.shrink( CKEDITOR.SHRINK_TEXT ); } function removeInlineStyle( range ) { /* * Make sure our range has included all "collpased" parent inline nodes so * that our operation logic can be simpler. */ range.enlarge( CKEDITOR.ENLARGE_ELEMENT, 1 ); var bookmark = range.createBookmark(), startNode = bookmark.startNode; if ( range.collapsed ) { var startPath = new CKEDITOR.dom.elementPath( startNode.getParent() ), // The topmost element in elementspatch which we should jump out of. boundaryElement; for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] ) ; i++ ) { /* * 1. If it's collaped inside text nodes, try to remove the style from the whole element. * * 2. Otherwise if it's collapsed on element boundaries, moving the selection * outside the styles instead of removing the whole tag, * also make sure other inner styles were well preserverd.(#3309) */ if ( element == startPath.block || element == startPath.blockLimit ) break; if ( this.checkElementRemovable( element ) ) { var isStart; if ( range.collapsed && ( range.checkBoundaryOfElement( element, CKEDITOR.END ) || ( isStart = range.checkBoundaryOfElement( element, CKEDITOR.START ) ) ) ) { boundaryElement = element; boundaryElement.match = isStart ? 'start' : 'end'; } else { /* * Before removing the style node, there may be a sibling to the style node * that's exactly the same to the one to be removed. To the user, it makes * no difference that they're separate entities in the DOM tree. So, merge * them before removal. */ element.mergeSiblings(); removeFromElement( this, element ); } } } // Re-create the style tree after/before the boundary element, // the replication start from bookmark start node to define the // new range. if ( boundaryElement ) { var clonedElement = startNode; for ( i = 0 ;; i++ ) { var newElement = startPath.elements[ i ]; if ( newElement.equals( boundaryElement ) ) break; // Avoid copying any matched element. else if ( newElement.match ) continue; else newElement = newElement.clone(); newElement.append( clonedElement ); clonedElement = newElement; } clonedElement[ boundaryElement.match == 'start' ? 'insertBefore' : 'insertAfter' ]( boundaryElement ); } } else { /* * Now our range isn't collapsed. Lets walk from the start node to the end * node via DFS and remove the styles one-by-one. */ var endNode = bookmark.endNode, me = this; /* * Find out the style ancestor that needs to be broken down at startNode * and endNode. */ function breakNodes() { var startPath = new CKEDITOR.dom.elementPath( startNode.getParent() ), endPath = new CKEDITOR.dom.elementPath( endNode.getParent() ), breakStart = null, breakEnd = null; for ( var i = 0 ; i < startPath.elements.length ; i++ ) { var element = startPath.elements[ i ]; if ( element == startPath.block || element == startPath.blockLimit ) break; if ( me.checkElementRemovable( element ) ) breakStart = element; } for ( i = 0 ; i < endPath.elements.length ; i++ ) { element = endPath.elements[ i ]; if ( element == endPath.block || element == endPath.blockLimit ) break; if ( me.checkElementRemovable( element ) ) breakEnd = element; } if ( breakEnd ) endNode.breakParent( breakEnd ); if ( breakStart ) startNode.breakParent( breakStart ); } bre Каталог - България - Други - Dir.bg