CLICK HERE TO BUY IT TODAY! OR GET IT FREE VIA TRIALPAY  

PHP Demo Application - Source Code

/Framework/Model/Vendor/CkEditor/_source/core/htmlparser/fragment.js



/*
Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
 * A lightweight representation of an HTML DOM structure.
 * @constructor
 * @example
 */
CKEDITOR.htmlParser.fragment = function()
{
	    /**
	     * The nodes contained in the root of this fragment.
	     * @type Array
	     * @example
	     * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<b>Sample</b> Text' );
	     * alert( fragment.children.length );
	  "2"
	     */
	    this.children [];
	    /**
	     * Get the fragment parent. Should always be null.
	     * @type Object
	     * @default null
	     * @example
	     */
	    this.parent null;
	    /** @private */
	    this.=
	    {
		        isBlockLike true,
		        hasInlineStarted false
		    };
	};
(function()
{
	    // Elements which the end tag is marked as optional in the HTML 4.01 DTD
	    // (expect empty elements).
	    var optionalClose = {colgroup:1,dd:1,dt:1,li:1,option:1,p:1,td:1,tfoot:1,th:1,thead:1,tr:1};
	    // Block-level elements whose internal structure should be respected during
	    // parser fixing.
	    var nonBreakingBlocks CKEDITOR.tools.extend(
	            {table:1,ul:1,ol:1,dl:1},
	            CKEDITOR.dtd.tableCKEDITOR.dtd.ulCKEDITOR.dtd.olCKEDITOR.dtd.dl ),
	        listBlocks CKEDITOR.dtd.$listlistItems CKEDITOR.dtd.$listItem;
	    /**
	     * Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string.
	     * @param {String} fragmentHtml The HTML to be parsed, filling the fragment.
	     * @param {Number} [fixForBody=false] Wrap body with specified element if needed.
	     * @returns CKEDITOR.htmlParser.fragment The fragment created.
	     * @example
	     * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<b>Sample</b> Text' );
	     * alert( fragment.children[0].name );
	  "b"
	     * alert( fragment.children[1].value );
	  " Text"
	     */
	    CKEDITOR.htmlParser.fragment.fromHtml = function( fragmentHtmlfixForBody )
	    {
		        var parser = new CKEDITOR.htmlParser(),
		            html [],
		            fragment = new CKEDITOR.htmlParser.fragment(),
		            pendingInline [],
		            pendingBRs [],
		            currentNode fragment,
		            // Indicate we're inside a <pre> element, spaces should be touched differently.
		            inPre false,
		            returnPoint;
		        function checkPendingnewTagName )
		        {
			            var pendingBRsSent;
			            if ( pendingInline.length )
			            {
				                for ( var ;
				 pendingInline.length ;
				 i++ )
				                {
					                    var pendingElement pendingInline],
					                        pendingName pendingElement.name,
					                        pendingDtd CKEDITOR.dtdpendingName ],
					                        currentDtd currentNode.name && CKEDITOR.dtdcurrentNode.name ];
					                    if ( ( !currentDtd || currentDtdpendingName ] ) && ( !newTagName || !pendingDtd || pendingDtdnewTagName ] || !CKEDITOR.dtdnewTagName ] ) )
					                    {
						                        if ( !pendingBRsSent )
						                        {
							                            sendPendingBRs();
							                            pendingBRsSent 1;
							                        }
						                        // Get a clone for the pending element.
						                        pendingElement pendingElement.clone();
						                        // Add it to the current node and make it the current,
						                        // so the new element will be added inside of it.
						                        pendingElement.parent currentNode;
						                        currentNode pendingElement;
						                        // Remove the pending element (back the index by one
						                        // to properly process the next entry).
						                        pendingInline.splicei);
						                        i--;
						                    }
					                }
				            }
			        }
		        function sendPendingBRsbrsToIgnore )
		        {
			            while ( pendingBRs.length - ( brsToIgnore || ) > )
			                currentNode.addpendingBRs.shift() );
			        }
		        function addElementelementtargetenforceCurrent )
		        {
			            target target || currentNode || fragment;
			            // If the target is the fragment and this element can't go inside
			            // body (if fixForBody).
			            if ( fixForBody && !target.type )
			            {
				                var elementNamerealElementName;
				                if ( element.attributes
				                     && ( realElementName =
				                          element.attributes'_cke_real_element_type' ] ) )
				                    elementName realElementName;
				                else
				                    elementName =  element.name;
				                if ( elementName
				                        && !( elementName in CKEDITOR.dtd.$body )
				                        && !( elementName in CKEDITOR.dtd.$nonBodyContent )  )
				                {
					                    var savedCurrent currentNode;
					                    // Create a <p> in the fragment.
					                    currentNode target;
					                    parser.onTagOpenfixForBody{} );
					                    // The new target now is the <p>.
					                    target currentNode;
					                    if ( enforceCurrent )
					                        currentNode savedCurrent;
					                }
				            }
			            // Rtrim empty spaces on block end boundary. (#3585)
			            if ( element._.isBlockLike
			                 && element.name != 'pre' )
			            {
				                var length element.children.length,
				                    lastChild element.childrenlength ],
				                    text;
				                if ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT )
				                {
					                    if ( !( text CKEDITOR.tools.rtrimlastChild.value ) ) )
					                        element.children.length length -1;
					                    else
					                        lastChild.value text;
					                }
				            }
			            target.addelement );
			            if ( element.returnPoint )
			            {
				                currentNode element.returnPoint;
				                delete element.returnPoint;
				            }
			        }
		        parser.onTagOpen = function( tagNameattributesselfClosing )
		        {
			            var element = new CKEDITOR.htmlParser.elementtagNameattributes );
			            // "isEmpty" will be always "false" for unknown elements, so we
			            // must force it if the parser has identified it as a selfClosing tag.
			            if ( element.isUnknown && selfClosing )
			                element.isEmpty true;
			            // This is a tag to be removed if empty, so do not add it immediately.
			            if ( CKEDITOR.dtd.$removeEmptytagName ] )
			            {
				                pendingInline.pushelement );
				                return;
				            }
			            else if ( tagName == 'pre' )
			                inPre true;
			            else if ( tagName == 'br' && inPre )
			            {
				                currentNode.add( new CKEDITOR.htmlParser.text'\n' ) );
				                return;
				            }
			            if ( tagName == 'br' )
			            {
				                pendingBRs.pushelement );
				                return;
				            }
			            var currentName currentNode.name;
			            var currentDtd currentName
			                && ( CKEDITOR.dtdcurrentName ]
			                    || ( currentNode._.isBlockLike CKEDITOR.dtd.div CKEDITOR.dtd.span ) );
			            // If the element cannot be child of the current element.
			            if ( currentDtd   // Fragment could receive any elements.
			                 && !element.isUnknown && !currentNode.isUnknown && !currentDtdtagName ] )
			            {
				                var reApply false,
				                    addPoint;
				   // New position to start adding nodes.
				                // Fixing malformed nested lists by moving it into a previous list item. (#3828)
				                if ( tagName in listBlocks
				                    && currentName in listBlocks )
				                {
					                    var children currentNode.children,
					                        lastChild childrenchildren.length ];
					                    // Establish the list item if it's not existed.
					                    if ( !( lastChild && lastChild.name in listItems ) )
					                        addElement( ( lastChild = new CKEDITOR.htmlParser.element'li' ) ), currentNode );
					                    returnPoint currentNodeaddPoint lastChild;
					                }
				                // If the element name is the same as the current element name,
				                // then just close the current one and append the new one to the
				                // parent. This situation usually happens with <p>, <li>, <dt> and
				                // <dd>, specially in IE. Do not enter in this if block in this case.
				                else if ( tagName == currentName )
				                {
					                    addElementcurrentNodecurrentNode.parent );
					                }
				                else
				                {
					                    if ( nonBreakingBlockscurrentName ] )
					                    {
						                        if ( !returnPoint )
						                            returnPoint currentNode;
						                    }
					                    else
					                    {
						                        addElementcurrentNodecurrentNode.parenttrue );
						                        if ( !optionalClosecurrentName ] )
						                        {
							                            // The current element is an inline element, which
							                            // cannot hold the new one. Put it in the pending list,
							                            // and try adding the new one after it.
							                            pendingInline.unshiftcurrentNode );
							                        }
						                    }
					                    reApply true;
					                }
				                if ( addPoint )
				                    currentNode addPoint;
				                // Try adding it to the return point, or the parent element.
				                else
				                    currentNode currentNode.returnPoint || currentNode.parent;
				                if ( reApply )
				                {
					                    parser.onTagOpen.applythisarguments );
					                    return;
					                }
				            }
			            checkPendingtagName );
			            sendPendingBRs();
			            element.parent currentNode;
			            element.returnPoint returnPoint;
			            returnPoint 0;
			            if ( element.isEmpty )
			                addElementelement );
			            else
			                currentNode element;
			        };
		        parser.onTagClose = function( tagName )
		        {
			            // Check if there is any pending tag to be closed.
			            for ( var pendingInline.length ;
			 >= ;
			 i-- )
			            {
				                // If found, just remove it from the list.
				                if ( tagName == pendingInline].name )
				                {
					                    pendingInline.splicei);
					                    return;
					                }
				            }
			            var pendingAdd [],
			                newPendingInline [],
			                candidate currentNode;
			            while ( candidate.type && candidate.name != tagName )
			            {
				                // If this is an inline element, add it to the pending list, if we're
				                // really closing one of the parents element later, they will continue
				                // after it.
				                if ( !candidate._.isBlockLike )
				                    newPendingInline.unshiftcandidate );
				                // This node should be added to it's parent at this point. But,
				                // it should happen only if the closing tag is really closing
				                // one of the nodes. So, for now, we just cache it.
				                pendingAdd.pushcandidate );
				                candidate candidate.parent;
				            }
			            if ( candidate.type )
			            {
				                // Add all elements that have been found in the above loop.
				                for ( ;
				 pendingAdd.length ;
				 i++ )
				                {
					                    var node pendingAdd];
					                    addElementnodenode.parent );
					                }
				                currentNode candidate;
				                if ( currentNode.name == 'pre' )
				                    inPre false;
				                if ( candidate._.isBlockLike )
				                    sendPendingBRs();
				                addElementcandidatecandidate.parent );
				                // The parent should start receiving new nodes now, except if
				                // addElement changed the currentNode.
				                if ( candidate == currentNode )
				                    currentNode currentNode.parent;
				                pendingInline pendingInline.concatnewPendingInline );
				            }
			            if ( tagName == 'body' )
			                fixForBody false;
			        };
		        parser.onText = function( text )
		        {
			            // Trim empty spaces at beginning of element contents except <pre>.
			            if ( !currentNode._.hasInlineStarted && !inPre )
			            {
				                text CKEDITOR.tools.ltrimtext );
				                if ( text.length === )
				                    return;
				            }
			            sendPendingBRs();
			            checkPending();
			            if ( fixForBody
			                 && ( !currentNode.type || currentNode.name == 'body' )
			                 && CKEDITOR.tools.trimtext ) )
			            {
				                this.onTagOpenfixForBody{} );
				            }
			            // Shrinking consequential spaces into one single for all elements
			            // text contents.
			            if ( !inPre )
			                text text.replace( /[\t\r\]{2,}|[\t\r\n]/g' ' );
			            currentNode.add( new CKEDITOR.htmlParser.texttext ) );
			        };
		        parser.onCDATA = function( cdata )
		        {
			            currentNode.add( new CKEDITOR.htmlParser.cdatacdata ) );
			        };
		        parser.onComment = function( comment )
		        {
			            currentNode.add( new CKEDITOR.htmlParser.commentcomment ) );
			        };
		        // Parse it.
		        parser.parsefragmentHtml );
		        // Send all pending BRs except one, which we consider a unwanted bogus. (#5293)
		        sendPendingBRs( !CKEDITOR.env.ie && );
		        // Close all pending nodes.
		        while ( currentNode.type )
		        {
			            var parent currentNode.parent,
			                node currentNode;
			            if ( fixForBody
			                 && ( !parent.type || parent.name == 'body' )
			                 && !CKEDITOR.dtd.$bodynode.name ] )
			            {
				                currentNode parent;
				                parser.onTagOpenfixForBody{} );
				                parent currentNode;
				            }
			            parent.addnode );
			            currentNode parent;
			        }
		        return fragment;
		    };
	    CKEDITOR.htmlParser.fragment.prototype =
	    {
		        /**
		         * Adds a node to this fragment.
		         * @param {Object} node The node to be added. It can be any of of the
		         *        following types: {@link CKEDITOR.htmlParser.element},
		         *        {@link CKEDITOR.htmlParser.text} and
		         *        {@link CKEDITOR.htmlParser.comment}.
		         * @example
		         */
		        add : function( node )
		        {
			            var len this.children.length,
			                previous len && this.childrenlen ] || null;
			            if ( previous )
			            {
				                // If the block to be appended is following text, trim spaces at
				                // the right of it.
				                if ( node._.isBlockLike && previous.type == CKEDITOR.NODE_TEXT )
				                {
					                    previous.value CKEDITOR.tools.rtrimprevious.value );
					                    // If we have completely cleared the previous node.
					                    if ( previous.value.length === )
					                    {
						                        // Remove it from the list and add the node again.
						                        this.children.pop();
						                        this.addnode );
						                        return;
						                    }
					                }
				                previous.next node;
				            }
			            node.previous previous;
			            node.parent this;
			            this.children.pushnode );
			            this._.hasInlineStarted node.type == CKEDITOR.NODE_TEXT || ( node.type == CKEDITOR.NODE_ELEMENT && !node._.isBlockLike );
			        },
		        /**
		         * Writes the fragment HTML to a CKEDITOR.htmlWriter.
		         * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
		         * @example
		         * var writer = new CKEDITOR.htmlWriter();
		         * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '&lt;
		P&gt;
		&lt;
		B&gt;
		Example' );
		         * fragment.writeHtml( writer )
		         * alert( writer.getHtml() );
		  "&lt;
		p&gt;
		&lt;
		b&gt;
		Example&lt;
		/b&gt;
		&lt;
		/p&gt;
		"
		         */
		        writeHtml : function( writerfilter )
		        {
			            var isChildrenFiltered;
			            this.filterChildren = function()
			            {
				                var writer = new CKEDITOR.htmlParser.basicWriter();
				                this.writeChildrenHtml.callthiswriterfiltertrue );
				                var html writer.getHtml();
				                this.children = new CKEDITOR.htmlParser.fragment.fromHtmlhtml ).children;
				                isChildrenFiltered 1;
				            };
			            // Filtering the root fragment before anything else.
			            !this.name && filter && filter.onFragmentthis );
			            this.writeChildrenHtmlwriterisChildrenFiltered null filter );
			        },
		        writeChildrenHtml : function( writerfilter )
		        {
			            for ( var ;
			 this.children.length ;
			 i++ )
			                this.children[i].writeHtmlwriterfilter );
			        }
		    };
	})();





PHP Demo Source Code Index