import rt 3.8.7
[freeside.git] / rt / share / html / NoAuth / RichText / FCKeditor / editor / _source / internals / fcktools_gecko.js
1 /*\r
2  * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
3  * Copyright (C) 2003-2009 Frederico Caldeira Knabben\r
4  *\r
5  * == BEGIN LICENSE ==\r
6  *\r
7  * Licensed under the terms of any of the following licenses at your\r
8  * choice:\r
9  *\r
10  *  - GNU General Public License Version 2 or later (the "GPL")\r
11  *    http://www.gnu.org/licenses/gpl.html\r
12  *\r
13  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
14  *    http://www.gnu.org/licenses/lgpl.html\r
15  *\r
16  *  - Mozilla Public License Version 1.1 or later (the "MPL")\r
17  *    http://www.mozilla.org/MPL/MPL-1.1.html\r
18  *\r
19  * == END LICENSE ==\r
20  *\r
21  * Utility functions. (Gecko version).\r
22  */\r
23 \r
24 FCKTools.CancelEvent = function( e )\r
25 {\r
26         if ( e )\r
27                 e.preventDefault() ;\r
28 }\r
29 \r
30 FCKTools.DisableSelection = function( element )\r
31 {\r
32         if ( FCKBrowserInfo.IsGecko )\r
33                 element.style.MozUserSelect             = 'none' ;      // Gecko only.\r
34         else if ( FCKBrowserInfo.IsSafari )\r
35                 element.style.KhtmlUserSelect   = 'none' ;      // WebKit only.\r
36         else\r
37                 element.style.userSelect                = 'none' ;      // CSS3 (not supported yet).\r
38 }\r
39 \r
40 // Appends a CSS file to a document.\r
41 FCKTools._AppendStyleSheet = function( documentElement, cssFileUrl )\r
42 {\r
43         var e = documentElement.createElement( 'LINK' ) ;\r
44         e.rel   = 'stylesheet' ;\r
45         e.type  = 'text/css' ;\r
46         e.href  = cssFileUrl ;\r
47         documentElement.getElementsByTagName("HEAD")[0].appendChild( e ) ;\r
48         return e ;\r
49 }\r
50 \r
51 // Appends a CSS style string to a document.\r
52 FCKTools.AppendStyleString = function( documentElement, cssStyles )\r
53 {\r
54         if ( !cssStyles )\r
55                 return null ;\r
56 \r
57         var e = documentElement.createElement( "STYLE" ) ;\r
58         e.appendChild( documentElement.createTextNode( cssStyles ) ) ;\r
59         documentElement.getElementsByTagName( "HEAD" )[0].appendChild( e ) ;\r
60         return e ;\r
61 }\r
62 \r
63 // Removes all attributes and values from the element.\r
64 FCKTools.ClearElementAttributes = function( element )\r
65 {\r
66         // Loop throw all attributes in the element\r
67         for ( var i = 0 ; i < element.attributes.length ; i++ )\r
68         {\r
69                 // Remove the element by name.\r
70                 element.removeAttribute( element.attributes[i].name, 0 ) ;      // 0 : Case Insensitive\r
71         }\r
72 }\r
73 \r
74 // Returns an Array of strings with all defined in the elements inside another element.\r
75 FCKTools.GetAllChildrenIds = function( parentElement )\r
76 {\r
77         // Create the array that will hold all Ids.\r
78         var aIds = new Array() ;\r
79 \r
80         // Define a recursive function that search for the Ids.\r
81         var fGetIds = function( parent )\r
82         {\r
83                 for ( var i = 0 ; i < parent.childNodes.length ; i++ )\r
84                 {\r
85                         var sId = parent.childNodes[i].id ;\r
86 \r
87                         // Check if the Id is defined for the element.\r
88                         if ( sId && sId.length > 0 ) aIds[ aIds.length ] = sId ;\r
89 \r
90                         // Recursive call.\r
91                         fGetIds( parent.childNodes[i] ) ;\r
92                 }\r
93         }\r
94 \r
95         // Start the recursive calls.\r
96         fGetIds( parentElement ) ;\r
97 \r
98         return aIds ;\r
99 }\r
100 \r
101 // Replaces a tag with its contents. For example "<span>My <b>tag</b></span>"\r
102 // will be replaced with "My <b>tag</b>".\r
103 FCKTools.RemoveOuterTags = function( e )\r
104 {\r
105         var oFragment = e.ownerDocument.createDocumentFragment() ;\r
106 \r
107         for ( var i = 0 ; i < e.childNodes.length ; i++ )\r
108                 oFragment.appendChild( e.childNodes[i].cloneNode(true) ) ;\r
109 \r
110         e.parentNode.replaceChild( oFragment, e ) ;\r
111 }\r
112 \r
113 FCKTools.CreateXmlObject = function( object )\r
114 {\r
115         switch ( object )\r
116         {\r
117                 case 'XmlHttp' :\r
118                         return new XMLHttpRequest() ;\r
119 \r
120                 case 'DOMDocument' :\r
121                         // Originaly, we were had the following here:\r
122                         // return document.implementation.createDocument( '', '', null ) ;\r
123                         // But that doesn't work if we're running under domain relaxation mode, so we need a workaround.\r
124                         // See http://ajaxian.com/archives/xml-messages-with-cross-domain-json about the trick we're using.\r
125                         var doc = ( new DOMParser() ).parseFromString( '<tmp></tmp>', 'text/xml' ) ;\r
126                         FCKDomTools.RemoveNode( doc.firstChild ) ;\r
127                         return doc ;\r
128         }\r
129         return null ;\r
130 }\r
131 \r
132 FCKTools.GetScrollPosition = function( relativeWindow )\r
133 {\r
134         return { X : relativeWindow.pageXOffset, Y : relativeWindow.pageYOffset } ;\r
135 }\r
136 \r
137 FCKTools.AddEventListener = function( sourceObject, eventName, listener )\r
138 {\r
139         sourceObject.addEventListener( eventName, listener, false ) ;\r
140 }\r
141 \r
142 FCKTools.RemoveEventListener = function( sourceObject, eventName, listener )\r
143 {\r
144         sourceObject.removeEventListener( eventName, listener, false ) ;\r
145 }\r
146 \r
147 // Listeners attached with this function cannot be detached.\r
148 FCKTools.AddEventListenerEx = function( sourceObject, eventName, listener, paramsArray )\r
149 {\r
150         sourceObject.addEventListener(\r
151                 eventName,\r
152                 function( e )\r
153                 {\r
154                         listener.apply( sourceObject, [ e ].concat( paramsArray || [] ) ) ;\r
155                 },\r
156                 false\r
157         ) ;\r
158 }\r
159 \r
160 // Returns and object with the "Width" and "Height" properties.\r
161 FCKTools.GetViewPaneSize = function( win )\r
162 {\r
163         return { Width : win.innerWidth, Height : win.innerHeight } ;\r
164 }\r
165 \r
166 FCKTools.SaveStyles = function( element )\r
167 {\r
168         var data = FCKTools.ProtectFormStyles( element ) ;\r
169 \r
170         var oSavedStyles = new Object() ;\r
171 \r
172         if ( element.className.length > 0 )\r
173         {\r
174                 oSavedStyles.Class = element.className ;\r
175                 element.className = '' ;\r
176         }\r
177 \r
178         var sInlineStyle = element.getAttribute( 'style' ) ;\r
179 \r
180         if ( sInlineStyle && sInlineStyle.length > 0 )\r
181         {\r
182                 oSavedStyles.Inline = sInlineStyle ;\r
183                 element.setAttribute( 'style', '', 0 ) ;        // 0 : Case Insensitive\r
184         }\r
185 \r
186         FCKTools.RestoreFormStyles( element, data ) ;\r
187         return oSavedStyles ;\r
188 }\r
189 \r
190 FCKTools.RestoreStyles = function( element, savedStyles )\r
191 {\r
192         var data = FCKTools.ProtectFormStyles( element ) ;\r
193         element.className = savedStyles.Class || '' ;\r
194 \r
195         if ( savedStyles.Inline )\r
196                 element.setAttribute( 'style', savedStyles.Inline, 0 ) ;        // 0 : Case Insensitive\r
197         else\r
198                 element.removeAttribute( 'style', 0 ) ;\r
199         FCKTools.RestoreFormStyles( element, data ) ;\r
200 }\r
201 \r
202 FCKTools.RegisterDollarFunction = function( targetWindow )\r
203 {\r
204         targetWindow.$ = function( id )\r
205         {\r
206                 return targetWindow.document.getElementById( id ) ;\r
207         } ;\r
208 }\r
209 \r
210 FCKTools.AppendElement = function( target, elementName )\r
211 {\r
212         return target.appendChild( target.ownerDocument.createElement( elementName ) ) ;\r
213 }\r
214 \r
215 // Get the coordinates of an element.\r
216 //              @el : The element to get the position.\r
217 //              @relativeWindow: The window to which we want the coordinates relative to.\r
218 FCKTools.GetElementPosition = function( el, relativeWindow )\r
219 {\r
220         // Initializes the Coordinates object that will be returned by the function.\r
221         var c = { X:0, Y:0 } ;\r
222 \r
223         var oWindow = relativeWindow || window ;\r
224 \r
225         var oOwnerWindow = FCKTools.GetElementWindow( el ) ;\r
226 \r
227         var previousElement = null ;\r
228         // Loop throw the offset chain.\r
229         while ( el )\r
230         {\r
231                 var sPosition = oOwnerWindow.getComputedStyle(el, '').position ;\r
232 \r
233                 // Check for non "static" elements.\r
234                 // 'FCKConfig.FloatingPanelsZIndex' -- Submenus are under a positioned IFRAME.\r
235                 if ( sPosition && sPosition != 'static' && el.style.zIndex != FCKConfig.FloatingPanelsZIndex )\r
236                         break ;\r
237 \r
238                 /*\r
239                 FCKDebug.Output( el.tagName + ":" + "offset=" + el.offsetLeft + "," + el.offsetTop + "  "\r
240                                 + "scroll=" + el.scrollLeft + "," + el.scrollTop ) ;\r
241                 */\r
242 \r
243                 c.X += el.offsetLeft - el.scrollLeft ;\r
244                 c.Y += el.offsetTop - el.scrollTop  ;\r
245 \r
246                 // Backtrack due to offsetParent's calculation by the browser ignores scrollLeft and scrollTop.\r
247                 // Backtracking is not needed for Opera\r
248                 if ( ! FCKBrowserInfo.IsOpera )\r
249                 {\r
250                         var scrollElement = previousElement ;\r
251                         while ( scrollElement && scrollElement != el )\r
252                         {\r
253                                 c.X -= scrollElement.scrollLeft ;\r
254                                 c.Y -= scrollElement.scrollTop ;\r
255                                 scrollElement = scrollElement.parentNode ;\r
256                         }\r
257                 }\r
258 \r
259                 previousElement = el ;\r
260                 if ( el.offsetParent )\r
261                         el = el.offsetParent ;\r
262                 else\r
263                 {\r
264                         if ( oOwnerWindow != oWindow )\r
265                         {\r
266                                 el = oOwnerWindow.frameElement ;\r
267                                 previousElement = null ;\r
268                                 if ( el )\r
269                                         oOwnerWindow = FCKTools.GetElementWindow( el ) ;\r
270                         }\r
271                         else\r
272                         {\r
273                                 c.X += el.scrollLeft ;\r
274                                 c.Y += el.scrollTop  ;\r
275                                 break ;\r
276                         }\r
277                 }\r
278         }\r
279 \r
280         // Return the Coordinates object\r
281         return c ;\r
282 }\r