--- /dev/null
+/*\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, '&' ) ;\r
+ text = text.replace( /</g, '<' ) ;\r
+ text = text.replace( />/g, '>' ) ;\r
+\r
+ return text ;\r
+}\r
+\r
+FCKTools.HTMLDecode = function( text )\r
+{\r
+ if ( !text )\r
+ return '' ;\r
+\r
+ text = text.replace( />/g, '>' ) ;\r
+ text = text.replace( /</g, '<' ) ;\r
+ text = text.replace( /&/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( " " ) ;\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