import rt 3.8.7
[freeside.git] / rt / share / html / NoAuth / RichText / FCKeditor / editor / _source / internals / fcktools.js
diff --git a/rt/share/html/NoAuth/RichText/FCKeditor/editor/_source/internals/fcktools.js b/rt/share/html/NoAuth/RichText/FCKeditor/editor/_source/internals/fcktools.js
new file mode 100644 (file)
index 0000000..db64bdd
--- /dev/null
@@ -0,0 +1,749 @@
+/*\r
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
+ * Copyright (C) 2003-2009 Frederico Caldeira Knabben\r
+ *\r
+ * == BEGIN LICENSE ==\r
+ *\r
+ * Licensed under the terms of any of the following licenses at your\r
+ * choice:\r
+ *\r
+ *  - GNU General Public License Version 2 or later (the "GPL")\r
+ *    http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
+ *    http://www.gnu.org/licenses/lgpl.html\r
+ *\r
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")\r
+ *    http://www.mozilla.org/MPL/MPL-1.1.html\r
+ *\r
+ * == END LICENSE ==\r
+ *\r
+ * Utility functions.\r
+ */\r
+\r
+var FCKTools = new Object() ;\r
+\r
+FCKTools.CreateBogusBR = function( targetDocument )\r
+{\r
+       var eBR = targetDocument.createElement( 'br' ) ;\r
+//     eBR.setAttribute( '_moz_editor_bogus_node', 'TRUE' ) ;\r
+       eBR.setAttribute( 'type', '_moz' ) ;\r
+       return eBR ;\r
+}\r
+\r
+/**\r
+ * Fixes relative URL entries defined inside CSS styles by appending a prefix\r
+ * to them.\r
+ * @param (String) cssStyles The CSS styles definition possibly containing url()\r
+ *             paths.\r
+ * @param (String) urlFixPrefix The prefix to append to relative URLs.\r
+ */\r
+FCKTools.FixCssUrls = function( urlFixPrefix, cssStyles )\r
+{\r
+       if ( !urlFixPrefix || urlFixPrefix.length == 0 )\r
+               return cssStyles ;\r
+\r
+       return cssStyles.replace( /url\s*\(([\s'"]*)(.*?)([\s"']*)\)/g, function( match, opener, path, closer )\r
+               {\r
+                       if ( /^\/|^\w?:/.test( path ) )\r
+                               return match ;\r
+                       else\r
+                               return 'url(' + opener + urlFixPrefix + path + closer + ')' ;\r
+               } ) ;\r
+}\r
+\r
+FCKTools._GetUrlFixedCss = function( cssStyles, urlFixPrefix )\r
+{\r
+       var match = cssStyles.match( /^([^|]+)\|([\s\S]*)/ ) ;\r
+\r
+       if ( match )\r
+               return FCKTools.FixCssUrls( match[1], match[2] ) ;\r
+       else\r
+               return cssStyles ;\r
+}\r
+\r
+/**\r
+ * Appends a <link css> or <style> element to the document.\r
+ * @param (Object) documentElement The DOM document object to which append the\r
+ *             stylesheet.\r
+ * @param (Variant) cssFileOrDef A String pointing to the CSS file URL or an\r
+ *             Array with many CSS file URLs or the CSS definitions for the <style>\r
+ *             element.\r
+ * @return {Array} An array containing all elements created in the target\r
+ *             document. It may include <link> or <style> elements, depending on the\r
+ *             value passed with cssFileOrDef.\r
+ */\r
+FCKTools.AppendStyleSheet = function( domDocument, cssFileOrArrayOrDef )\r
+{\r
+       if ( !cssFileOrArrayOrDef )\r
+               return [] ;\r
+\r
+       if ( typeof( cssFileOrArrayOrDef ) == 'string' )\r
+       {\r
+               // Test if the passed argument is an URL.\r
+               if ( /[\\\/\.][^{}]*$/.test( cssFileOrArrayOrDef ) )\r
+               {\r
+                       // The string may have several URLs separated by comma.\r
+                       return this.AppendStyleSheet( domDocument, cssFileOrArrayOrDef.split(',') ) ;\r
+               }\r
+               else\r
+                       return [ this.AppendStyleString( domDocument, FCKTools._GetUrlFixedCss( cssFileOrArrayOrDef ) ) ] ;\r
+       }\r
+       else\r
+       {\r
+               var styles = [] ;\r
+               for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ )\r
+                       styles.push( this._AppendStyleSheet( domDocument, cssFileOrArrayOrDef[i] ) ) ;\r
+               return styles ;\r
+       }\r
+}\r
+\r
+FCKTools.GetStyleHtml = (function()\r
+{\r
+       var getStyle = function( styleDef, markTemp )\r
+       {\r
+               if ( styleDef.length == 0 )\r
+                       return '' ;\r
+\r
+               var temp = markTemp ? ' _fcktemp="true"' : '' ;\r
+               return '<' + 'style type="text/css"' + temp + '>' + styleDef + '<' + '/style>' ;\r
+       }\r
+\r
+       var getLink = function( cssFileUrl, markTemp )\r
+       {\r
+               if ( cssFileUrl.length == 0 )\r
+                       return '' ;\r
+\r
+               var temp = markTemp ? ' _fcktemp="true"' : '' ;\r
+               return '<' + 'link href="' + cssFileUrl + '" type="text/css" rel="stylesheet" ' + temp + '/>' ;\r
+       }\r
+\r
+       return function( cssFileOrArrayOrDef, markTemp )\r
+       {\r
+               if ( !cssFileOrArrayOrDef )\r
+                       return '' ;\r
+\r
+               if ( typeof( cssFileOrArrayOrDef ) == 'string' )\r
+               {\r
+                       // Test if the passed argument is an URL.\r
+                       if ( /[\\\/\.][^{}]*$/.test( cssFileOrArrayOrDef ) )\r
+                       {\r
+                               // The string may have several URLs separated by comma.\r
+                               return this.GetStyleHtml( cssFileOrArrayOrDef.split(','), markTemp ) ;\r
+                       }\r
+                       else\r
+                               return getStyle( this._GetUrlFixedCss( cssFileOrArrayOrDef ), markTemp ) ;\r
+               }\r
+               else\r
+               {\r
+                       var html = '' ;\r
+\r
+                       for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ )\r
+                               html += getLink( cssFileOrArrayOrDef[i], markTemp ) ;\r
+\r
+                       return html ;\r
+               }\r
+       }\r
+})() ;\r
+\r
+FCKTools.GetElementDocument = function ( element )\r
+{\r
+       return element.ownerDocument || element.document ;\r
+}\r
+\r
+// Get the window object where the element is placed in.\r
+FCKTools.GetElementWindow = function( element )\r
+{\r
+       return this.GetDocumentWindow( this.GetElementDocument( element ) ) ;\r
+}\r
+\r
+FCKTools.GetDocumentWindow = function( document )\r
+{\r
+       // With Safari, there is not way to retrieve the window from the document, so we must fix it.\r
+       if ( FCKBrowserInfo.IsSafari && !document.parentWindow )\r
+               this.FixDocumentParentWindow( window.top ) ;\r
+\r
+       return document.parentWindow || document.defaultView ;\r
+}\r
+\r
+/*\r
+       This is a Safari specific function that fix the reference to the parent\r
+       window from the document object.\r
+*/\r
+FCKTools.FixDocumentParentWindow = function( targetWindow )\r
+{\r
+       if ( targetWindow.document )\r
+               targetWindow.document.parentWindow = targetWindow ;\r
+\r
+       for ( var i = 0 ; i < targetWindow.frames.length ; i++ )\r
+               FCKTools.FixDocumentParentWindow( targetWindow.frames[i] ) ;\r
+}\r
+\r
+FCKTools.HTMLEncode = function( text )\r
+{\r
+       if ( !text )\r
+               return '' ;\r
+\r
+       text = text.replace( /&/g, '&amp;' ) ;\r
+       text = text.replace( /</g, '&lt;' ) ;\r
+       text = text.replace( />/g, '&gt;' ) ;\r
+\r
+       return text ;\r
+}\r
+\r
+FCKTools.HTMLDecode = function( text )\r
+{\r
+       if ( !text )\r
+               return '' ;\r
+\r
+       text = text.replace( /&gt;/g, '>' ) ;\r
+       text = text.replace( /&lt;/g, '<' ) ;\r
+       text = text.replace( /&amp;/g, '&' ) ;\r
+\r
+       return text ;\r
+}\r
+\r
+FCKTools._ProcessLineBreaksForPMode = function( oEditor, text, liState, node, strArray )\r
+{\r
+       var closeState = 0 ;\r
+       var blockStartTag = "<p>" ;\r
+       var blockEndTag = "</p>" ;\r
+       var lineBreakTag = "<br />" ;\r
+       if ( liState )\r
+       {\r
+               blockStartTag = "<li>" ;\r
+               blockEndTag = "</li>" ;\r
+               closeState = 1 ;\r
+       }\r
+\r
+       // Are we currently inside a <p> tag now?\r
+       // If yes, close it at the next double line break.\r
+       while ( node && node != oEditor.FCK.EditorDocument.body )\r
+       {\r
+               if ( node.tagName.toLowerCase() == 'p' )\r
+               {\r
+                       closeState = 1 ;\r
+                       break;\r
+               }\r
+               node = node.parentNode ;\r
+       }\r
+\r
+       for ( var i = 0 ; i < text.length ; i++ )\r
+       {\r
+               var c = text.charAt( i ) ;\r
+               if ( c == '\r' )\r
+                       continue ;\r
+\r
+               if ( c != '\n' )\r
+               {\r
+                       strArray.push( c ) ;\r
+                       continue ;\r
+               }\r
+\r
+               // Now we have encountered a line break.\r
+               // Check if the next character is also a line break.\r
+               var n = text.charAt( i + 1 ) ;\r
+               if ( n == '\r' )\r
+               {\r
+                       i++ ;\r
+                       n = text.charAt( i + 1 ) ;\r
+               }\r
+               if ( n == '\n' )\r
+               {\r
+                       i++ ;   // ignore next character - we have already processed it.\r
+                       if ( closeState )\r
+                               strArray.push( blockEndTag ) ;\r
+                       strArray.push( blockStartTag ) ;\r
+                       closeState = 1 ;\r
+               }\r
+               else\r
+                       strArray.push( lineBreakTag ) ;\r
+       }\r
+}\r
+\r
+FCKTools._ProcessLineBreaksForDivMode = function( oEditor, text, liState, node, strArray )\r
+{\r
+       var closeState = 0 ;\r
+       var blockStartTag = "<div>" ;\r
+       var blockEndTag = "</div>" ;\r
+       if ( liState )\r
+       {\r
+               blockStartTag = "<li>" ;\r
+               blockEndTag = "</li>" ;\r
+               closeState = 1 ;\r
+       }\r
+\r
+       // Are we currently inside a <div> tag now?\r
+       // If yes, close it at the next double line break.\r
+       while ( node && node != oEditor.FCK.EditorDocument.body )\r
+       {\r
+               if ( node.tagName.toLowerCase() == 'div' )\r
+               {\r
+                       closeState = 1 ;\r
+                       break ;\r
+               }\r
+               node = node.parentNode ;\r
+       }\r
+\r
+       for ( var i = 0 ; i < text.length ; i++ )\r
+       {\r
+               var c = text.charAt( i ) ;\r
+               if ( c == '\r' )\r
+                       continue ;\r
+\r
+               if ( c != '\n' )\r
+               {\r
+                       strArray.push( c ) ;\r
+                       continue ;\r
+               }\r
+\r
+               if ( closeState )\r
+               {\r
+                       if ( strArray[ strArray.length - 1 ] == blockStartTag )\r
+                       {\r
+                               // A div tag must have some contents inside for it to be visible.\r
+                               strArray.push( "&nbsp;" ) ;\r
+                       }\r
+                       strArray.push( blockEndTag ) ;\r
+               }\r
+               strArray.push( blockStartTag ) ;\r
+               closeState = 1 ;\r
+       }\r
+       if ( closeState )\r
+               strArray.push( blockEndTag ) ;\r
+}\r
+\r
+FCKTools._ProcessLineBreaksForBrMode = function( oEditor, text, liState, node, strArray )\r
+{\r
+       var closeState = 0 ;\r
+       var blockStartTag = "<br />" ;\r
+       var blockEndTag = "" ;\r
+       if ( liState )\r
+       {\r
+               blockStartTag = "<li>" ;\r
+               blockEndTag = "</li>" ;\r
+               closeState = 1 ;\r
+       }\r
+\r
+       for ( var i = 0 ; i < text.length ; i++ )\r
+       {\r
+               var c = text.charAt( i ) ;\r
+               if ( c == '\r' )\r
+                       continue ;\r
+\r
+               if ( c != '\n' )\r
+               {\r
+                       strArray.push( c ) ;\r
+                       continue ;\r
+               }\r
+\r
+               if ( closeState && blockEndTag.length )\r
+                       strArray.push ( blockEndTag ) ;\r
+               strArray.push( blockStartTag ) ;\r
+               closeState = 1 ;\r
+       }\r
+}\r
+\r
+FCKTools.ProcessLineBreaks = function( oEditor, oConfig, text )\r
+{\r
+       var enterMode = oConfig.EnterMode.toLowerCase() ;\r
+       var strArray = [] ;\r
+\r
+       // Is the caret or selection inside an <li> tag now?\r
+       var liState = 0 ;\r
+       var range = new oEditor.FCKDomRange( oEditor.FCK.EditorWindow ) ;\r
+       range.MoveToSelection() ;\r
+       var node = range._Range.startContainer ;\r
+       while ( node && node.nodeType != 1 )\r
+               node = node.parentNode ;\r
+       if ( node && node.tagName.toLowerCase() == 'li' )\r
+               liState = 1 ;\r
+\r
+       if ( enterMode == 'p' )\r
+               this._ProcessLineBreaksForPMode( oEditor, text, liState, node, strArray ) ;\r
+       else if ( enterMode == 'div' )\r
+               this._ProcessLineBreaksForDivMode( oEditor, text, liState, node, strArray ) ;\r
+       else if ( enterMode == 'br' )\r
+               this._ProcessLineBreaksForBrMode( oEditor, text, liState, node, strArray ) ;\r
+       return strArray.join( "" ) ;\r
+}\r
+\r
+/**\r
+ * Adds an option to a SELECT element.\r
+ */\r
+FCKTools.AddSelectOption = function( selectElement, optionText, optionValue )\r
+{\r
+       var oOption = FCKTools.GetElementDocument( selectElement ).createElement( "OPTION" ) ;\r
+\r
+       oOption.text    = optionText ;\r
+       oOption.value   = optionValue ;\r
+\r
+       selectElement.options.add(oOption) ;\r
+\r
+       return oOption ;\r
+}\r
+\r
+FCKTools.RunFunction = function( func, thisObject, paramsArray, timerWindow )\r
+{\r
+       if ( func )\r
+               this.SetTimeout( func, 0, thisObject, paramsArray, timerWindow ) ;\r
+}\r
+\r
+FCKTools.SetTimeout = function( func, milliseconds, thisObject, paramsArray, timerWindow )\r
+{\r
+       return ( timerWindow || window ).setTimeout(\r
+               function()\r
+               {\r
+                       if ( paramsArray )\r
+                               func.apply( thisObject, [].concat( paramsArray ) ) ;\r
+                       else\r
+                               func.apply( thisObject ) ;\r
+               },\r
+               milliseconds ) ;\r
+}\r
+\r
+FCKTools.SetInterval = function( func, milliseconds, thisObject, paramsArray, timerWindow )\r
+{\r
+       return ( timerWindow || window ).setInterval(\r
+               function()\r
+               {\r
+                       func.apply( thisObject, paramsArray || [] ) ;\r
+               },\r
+               milliseconds ) ;\r
+}\r
+\r
+FCKTools.ConvertStyleSizeToHtml = function( size )\r
+{\r
+       return size.EndsWith( '%' ) ? size : parseInt( size, 10 ) ;\r
+}\r
+\r
+FCKTools.ConvertHtmlSizeToStyle = function( size )\r
+{\r
+       return size.EndsWith( '%' ) ? size : ( size + 'px' ) ;\r
+}\r
+\r
+// START iCM MODIFICATIONS\r
+// Amended to accept a list of one or more ascensor tag names\r
+// Amended to check the element itself before working back up through the parent hierarchy\r
+FCKTools.GetElementAscensor = function( element, ascensorTagNames )\r
+{\r
+//     var e = element.parentNode ;\r
+       var e = element ;\r
+       var lstTags = "," + ascensorTagNames.toUpperCase() + "," ;\r
+\r
+       while ( e )\r
+       {\r
+               if ( lstTags.indexOf( "," + e.nodeName.toUpperCase() + "," ) != -1 )\r
+                       return e ;\r
+\r
+               e = e.parentNode ;\r
+       }\r
+       return null ;\r
+}\r
+// END iCM MODIFICATIONS\r
+\r
+FCKTools.CreateEventListener = function( func, params )\r
+{\r
+       var f = function()\r
+       {\r
+               var aAllParams = [] ;\r
+\r
+               for ( var i = 0 ; i < arguments.length ; i++ )\r
+                       aAllParams.push( arguments[i] ) ;\r
+\r
+               func.apply( this, aAllParams.concat( params ) ) ;\r
+       }\r
+\r
+       return f ;\r
+}\r
+\r
+FCKTools.IsStrictMode = function( document )\r
+{\r
+       // There is no compatMode in Safari, but it seams that it always behave as\r
+       // CSS1Compat, so let's assume it as the default for that browser.\r
+       return ( 'CSS1Compat' == ( document.compatMode || ( FCKBrowserInfo.IsSafari ? 'CSS1Compat' : null ) ) ) ;\r
+}\r
+\r
+// Transforms a "arguments" object to an array.\r
+FCKTools.ArgumentsToArray = function( args, startIndex, maxLength )\r
+{\r
+       startIndex = startIndex || 0 ;\r
+       maxLength = maxLength || args.length ;\r
+\r
+       var argsArray = new Array() ;\r
+\r
+       for ( var i = startIndex ; i < startIndex + maxLength && i < args.length ; i++ )\r
+               argsArray.push( args[i] ) ;\r
+\r
+       return argsArray ;\r
+}\r
+\r
+FCKTools.CloneObject = function( sourceObject )\r
+{\r
+       var fCloneCreator = function() {} ;\r
+       fCloneCreator.prototype = sourceObject ;\r
+       return new fCloneCreator ;\r
+}\r
+\r
+// Appends a bogus <br> at the end of the element, if not yet available.\r
+FCKTools.AppendBogusBr = function( element )\r
+{\r
+       if ( !element )\r
+               return ;\r
+\r
+       var eLastChild = this.GetLastItem( element.getElementsByTagName('br') ) ;\r
+\r
+       if ( !eLastChild || ( eLastChild.getAttribute( 'type', 2 ) != '_moz' && eLastChild.getAttribute( '_moz_dirty' ) == null ) )\r
+       {\r
+               var doc = this.GetElementDocument( element ) ;\r
+\r
+               if ( FCKBrowserInfo.IsOpera )\r
+                       element.appendChild( doc.createTextNode('') ) ;\r
+               else\r
+                       element.appendChild( this.CreateBogusBR( doc ) ) ;\r
+       }\r
+}\r
+\r
+FCKTools.GetLastItem = function( list )\r
+{\r
+       if ( list.length > 0 )\r
+               return list[ list.length - 1 ] ;\r
+\r
+       return null ;\r
+}\r
+\r
+FCKTools.GetDocumentPosition = function( w, node )\r
+{\r
+       var x = 0 ;\r
+       var y = 0 ;\r
+       var curNode = node ;\r
+       var prevNode = null ;\r
+       var curWindow = FCKTools.GetElementWindow( curNode ) ;\r
+       while ( curNode && !( curWindow == w && ( curNode == w.document.body || curNode == w.document.documentElement ) ) )\r
+       {\r
+               x += curNode.offsetLeft - curNode.scrollLeft ;\r
+               y += curNode.offsetTop - curNode.scrollTop ;\r
+\r
+               if ( ! FCKBrowserInfo.IsOpera )\r
+               {\r
+                       var scrollNode = prevNode ;\r
+                       while ( scrollNode && scrollNode != curNode )\r
+                       {\r
+                               x -= scrollNode.scrollLeft ;\r
+                               y -= scrollNode.scrollTop ;\r
+                               scrollNode = scrollNode.parentNode ;\r
+                       }\r
+               }\r
+\r
+               prevNode = curNode ;\r
+               if ( curNode.offsetParent )\r
+                       curNode = curNode.offsetParent ;\r
+               else\r
+               {\r
+                       if ( curWindow != w )\r
+                       {\r
+                               curNode = curWindow.frameElement ;\r
+                               prevNode = null ;\r
+                               if ( curNode )\r
+                                       curWindow = curNode.contentWindow.parent ;\r
+                       }\r
+                       else\r
+                               curNode = null ;\r
+               }\r
+       }\r
+\r
+       // document.body is a special case when it comes to offsetTop and offsetLeft values.\r
+       // 1. It matters if document.body itself is a positioned element;\r
+       // 2. It matters is when we're in IE and the element has no positioned ancestor.\r
+       // Otherwise the values should be ignored.\r
+       if ( FCKDomTools.GetCurrentElementStyle( w.document.body, 'position') != 'static'\r
+                       || ( FCKBrowserInfo.IsIE && FCKDomTools.GetPositionedAncestor( node ) == null ) )\r
+       {\r
+               x += w.document.body.offsetLeft ;\r
+               y += w.document.body.offsetTop ;\r
+       }\r
+\r
+       return { "x" : x, "y" : y } ;\r
+}\r
+\r
+FCKTools.GetWindowPosition = function( w, node )\r
+{\r
+       var pos = this.GetDocumentPosition( w, node ) ;\r
+       var scroll = FCKTools.GetScrollPosition( w ) ;\r
+       pos.x -= scroll.X ;\r
+       pos.y -= scroll.Y ;\r
+       return pos ;\r
+}\r
+\r
+FCKTools.ProtectFormStyles = function( formNode )\r
+{\r
+       if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )\r
+               return [] ;\r
+       var hijackRecord = [] ;\r
+       var hijackNames = [ 'style', 'className' ] ;\r
+       for ( var i = 0 ; i < hijackNames.length ; i++ )\r
+       {\r
+               var name = hijackNames[i] ;\r
+               if ( formNode.elements.namedItem( name ) )\r
+               {\r
+                       var hijackNode = formNode.elements.namedItem( name ) ;\r
+                       hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] ) ;\r
+                       formNode.removeChild( hijackNode ) ;\r
+               }\r
+       }\r
+       return hijackRecord ;\r
+}\r
+\r
+FCKTools.RestoreFormStyles = function( formNode, hijackRecord )\r
+{\r
+       if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )\r
+               return ;\r
+       if ( hijackRecord.length > 0 )\r
+       {\r
+               for ( var i = hijackRecord.length - 1 ; i >= 0 ; i-- )\r
+               {\r
+                       var node = hijackRecord[i][0] ;\r
+                       var sibling = hijackRecord[i][1] ;\r
+                       if ( sibling )\r
+                               formNode.insertBefore( node, sibling ) ;\r
+                       else\r
+                               formNode.appendChild( node ) ;\r
+               }\r
+       }\r
+}\r
+\r
+// Perform a one-step DFS walk.\r
+FCKTools.GetNextNode = function( node, limitNode )\r
+{\r
+       if ( node.firstChild )\r
+               return node.firstChild ;\r
+       else if ( node.nextSibling )\r
+               return node.nextSibling ;\r
+       else\r
+       {\r
+               var ancestor = node.parentNode ;\r
+               while ( ancestor )\r
+               {\r
+                       if ( ancestor == limitNode )\r
+                               return null ;\r
+                       if ( ancestor.nextSibling )\r
+                               return ancestor.nextSibling ;\r
+                       else\r
+                               ancestor = ancestor.parentNode ;\r
+               }\r
+       }\r
+       return null ;\r
+}\r
+\r
+FCKTools.GetNextTextNode = function( textnode, limitNode, checkStop )\r
+{\r
+       node = this.GetNextNode( textnode, limitNode ) ;\r
+       if ( checkStop && node && checkStop( node ) )\r
+               return null ;\r
+       while ( node && node.nodeType != 3 )\r
+       {\r
+               node = this.GetNextNode( node, limitNode ) ;\r
+               if ( checkStop && node && checkStop( node ) )\r
+                       return null ;\r
+       }\r
+       return node ;\r
+}\r
+\r
+/**\r
+ * Merge all objects passed by argument into a single object.\r
+ */\r
+FCKTools.Merge = function()\r
+{\r
+       var args = arguments ;\r
+       var o = args[0] ;\r
+\r
+       for ( var i = 1 ; i < args.length ; i++ )\r
+       {\r
+               var arg = args[i] ;\r
+               for ( var p in arg )\r
+                       o[p] = arg[p] ;\r
+       }\r
+\r
+       return o ;\r
+}\r
+\r
+/**\r
+ * Check if the passed argument is a real Array. It may not working when\r
+ * calling it cross windows.\r
+ */\r
+FCKTools.IsArray = function( it )\r
+{\r
+       return ( it instanceof Array ) ;\r
+}\r
+\r
+/**\r
+ * Appends a "length" property to an object, containing the number of\r
+ * properties available on it, excluded the append property itself.\r
+ */\r
+FCKTools.AppendLengthProperty = function( targetObject, propertyName )\r
+{\r
+       var counter = 0 ;\r
+\r
+       for ( var n in targetObject )\r
+               counter++ ;\r
+\r
+       return targetObject[ propertyName || 'length' ] = counter ;\r
+}\r
+\r
+/**\r
+ * Gets the browser parsed version of a css text (style attribute value). On\r
+ * some cases, the browser makes changes to the css text, returning a different\r
+ * value. For example, hexadecimal colors get transformed to rgb().\r
+ */\r
+FCKTools.NormalizeCssText = function( unparsedCssText )\r
+{\r
+       // Injects the style in a temporary span object, so the browser parses it,\r
+       // retrieving its final format.\r
+       var tempSpan = document.createElement( 'span' ) ;\r
+       tempSpan.style.cssText = unparsedCssText ;\r
+       return tempSpan.style.cssText ;\r
+}\r
+\r
+/**\r
+ * Binding the "this" reference to an object for a function.\r
+ */\r
+FCKTools.Bind = function( subject, func )\r
+{\r
+  return function(){ return func.apply( subject, arguments ) ; } ;\r
+}\r
+\r
+/**\r
+ * Retrieve the correct "empty iframe" URL for the current browser, which\r
+ * causes the minimum fuzz (e.g. security warnings in HTTPS, DNS error in\r
+ * IE5.5, etc.) for that browser, making the iframe ready to DOM use whithout\r
+ * having to loading an external file.\r
+ */\r
+FCKTools.GetVoidUrl = function()\r
+{\r
+       if ( FCK_IS_CUSTOM_DOMAIN )\r
+               return "javascript: void( function(){" +\r
+                       "document.open();" +\r
+                       "document.write('<html><head><title></title></head><body></body></html>');" +\r
+                       "document.domain = '" + FCK_RUNTIME_DOMAIN + "';" +\r
+                       "document.close();" +\r
+                       "}() ) ;";\r
+\r
+       if ( FCKBrowserInfo.IsIE )\r
+       {\r
+               if ( FCKBrowserInfo.IsIE7 || !FCKBrowserInfo.IsIE6 )\r
+                       return "" ;                                     // IE7+ / IE5.5\r
+               else\r
+                       return "javascript: '';" ;      // IE6+\r
+       }\r
+\r
+       return "javascript: void(0);" ;         // All other browsers.\r
+}\r
+\r
+FCKTools.ResetStyles = function( element )\r
+{\r
+       element.style.cssText = 'margin:0;' +\r
+               'padding:0;' +\r
+               'border:0;' +\r
+               'background-color:transparent;' +\r
+               'background-image:none;' ;\r
+}\r