1 | /*
|
---|
2 | * FCKeditor - The text editor for Internet - http://www.fckeditor.net
|
---|
3 | * Copyright (C) 2003-2009 Frederico Caldeira Knabben
|
---|
4 | *
|
---|
5 | * == BEGIN LICENSE ==
|
---|
6 | *
|
---|
7 | * Licensed under the terms of any of the following licenses at your
|
---|
8 | * choice:
|
---|
9 | *
|
---|
10 | * - GNU General Public License Version 2 or later (the "GPL")
|
---|
11 | * http://www.gnu.org/licenses/gpl.html
|
---|
12 | *
|
---|
13 | * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
|
---|
14 | * http://www.gnu.org/licenses/lgpl.html
|
---|
15 | *
|
---|
16 | * - Mozilla Public License Version 1.1 or later (the "MPL")
|
---|
17 | * http://www.mozilla.org/MPL/MPL-1.1.html
|
---|
18 | *
|
---|
19 | * == END LICENSE ==
|
---|
20 | *
|
---|
21 | * Utility functions.
|
---|
22 | */
|
---|
23 |
|
---|
24 | var FCKTools = new Object() ;
|
---|
25 |
|
---|
26 | FCKTools.CreateBogusBR = function( targetDocument )
|
---|
27 | {
|
---|
28 | var eBR = targetDocument.createElement( 'br' ) ;
|
---|
29 | // eBR.setAttribute( '_moz_editor_bogus_node', 'TRUE' ) ;
|
---|
30 | eBR.setAttribute( 'type', '_moz' ) ;
|
---|
31 | return eBR ;
|
---|
32 | }
|
---|
33 |
|
---|
34 | /**
|
---|
35 | * Fixes relative URL entries defined inside CSS styles by appending a prefix
|
---|
36 | * to them.
|
---|
37 | * @param (String) cssStyles The CSS styles definition possibly containing url()
|
---|
38 | * paths.
|
---|
39 | * @param (String) urlFixPrefix The prefix to append to relative URLs.
|
---|
40 | */
|
---|
41 | FCKTools.FixCssUrls = function( urlFixPrefix, cssStyles )
|
---|
42 | {
|
---|
43 | if ( !urlFixPrefix || urlFixPrefix.length == 0 )
|
---|
44 | return cssStyles ;
|
---|
45 |
|
---|
46 | return cssStyles.replace( /url\s*\(([\s'"]*)(.*?)([\s"']*)\)/g, function( match, opener, path, closer )
|
---|
47 | {
|
---|
48 | if ( /^\/|^\w?:/.test( path ) )
|
---|
49 | return match ;
|
---|
50 | else
|
---|
51 | return 'url(' + opener + urlFixPrefix + path + closer + ')' ;
|
---|
52 | } ) ;
|
---|
53 | }
|
---|
54 |
|
---|
55 | FCKTools._GetUrlFixedCss = function( cssStyles, urlFixPrefix )
|
---|
56 | {
|
---|
57 | var match = cssStyles.match( /^([^|]+)\|([\s\S]*)/ ) ;
|
---|
58 |
|
---|
59 | if ( match )
|
---|
60 | return FCKTools.FixCssUrls( match[1], match[2] ) ;
|
---|
61 | else
|
---|
62 | return cssStyles ;
|
---|
63 | }
|
---|
64 |
|
---|
65 | /**
|
---|
66 | * Appends a <link css> or <style> element to the document.
|
---|
67 | * @param (Object) documentElement The DOM document object to which append the
|
---|
68 | * stylesheet.
|
---|
69 | * @param (Variant) cssFileOrDef A String pointing to the CSS file URL or an
|
---|
70 | * Array with many CSS file URLs or the CSS definitions for the <style>
|
---|
71 | * element.
|
---|
72 | * @return {Array} An array containing all elements created in the target
|
---|
73 | * document. It may include <link> or <style> elements, depending on the
|
---|
74 | * value passed with cssFileOrDef.
|
---|
75 | */
|
---|
76 | FCKTools.AppendStyleSheet = function( domDocument, cssFileOrArrayOrDef )
|
---|
77 | {
|
---|
78 | if ( !cssFileOrArrayOrDef )
|
---|
79 | return [] ;
|
---|
80 |
|
---|
81 | if ( typeof( cssFileOrArrayOrDef ) == 'string' )
|
---|
82 | {
|
---|
83 | // Test if the passed argument is an URL.
|
---|
84 | if ( /[\\\/\.][^{}]*$/.test( cssFileOrArrayOrDef ) )
|
---|
85 | {
|
---|
86 | // The string may have several URLs separated by comma.
|
---|
87 | return this.AppendStyleSheet( domDocument, cssFileOrArrayOrDef.split(',') ) ;
|
---|
88 | }
|
---|
89 | else
|
---|
90 | return [ this.AppendStyleString( domDocument, FCKTools._GetUrlFixedCss( cssFileOrArrayOrDef ) ) ] ;
|
---|
91 | }
|
---|
92 | else
|
---|
93 | {
|
---|
94 | var styles = [] ;
|
---|
95 | for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ )
|
---|
96 | styles.push( this._AppendStyleSheet( domDocument, cssFileOrArrayOrDef[i] ) ) ;
|
---|
97 | return styles ;
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 | FCKTools.GetStyleHtml = (function()
|
---|
102 | {
|
---|
103 | var getStyle = function( styleDef, markTemp )
|
---|
104 | {
|
---|
105 | if ( styleDef.length == 0 )
|
---|
106 | return '' ;
|
---|
107 |
|
---|
108 | var temp = markTemp ? ' _fcktemp="true"' : '' ;
|
---|
109 | return '<' + 'style type="text/css"' + temp + '>' + styleDef + '<' + '/style>' ;
|
---|
110 | }
|
---|
111 |
|
---|
112 | var getLink = function( cssFileUrl, markTemp )
|
---|
113 | {
|
---|
114 | if ( cssFileUrl.length == 0 )
|
---|
115 | return '' ;
|
---|
116 |
|
---|
117 | var temp = markTemp ? ' _fcktemp="true"' : '' ;
|
---|
118 | return '<' + 'link href="' + cssFileUrl + '" type="text/css" rel="stylesheet" ' + temp + '/>' ;
|
---|
119 | }
|
---|
120 |
|
---|
121 | return function( cssFileOrArrayOrDef, markTemp )
|
---|
122 | {
|
---|
123 | if ( !cssFileOrArrayOrDef )
|
---|
124 | return '' ;
|
---|
125 |
|
---|
126 | if ( typeof( cssFileOrArrayOrDef ) == 'string' )
|
---|
127 | {
|
---|
128 | // Test if the passed argument is an URL.
|
---|
129 | if ( /[\\\/\.][^{}]*$/.test( cssFileOrArrayOrDef ) )
|
---|
130 | {
|
---|
131 | // The string may have several URLs separated by comma.
|
---|
132 | return this.GetStyleHtml( cssFileOrArrayOrDef.split(','), markTemp ) ;
|
---|
133 | }
|
---|
134 | else
|
---|
135 | return getStyle( this._GetUrlFixedCss( cssFileOrArrayOrDef ), markTemp ) ;
|
---|
136 | }
|
---|
137 | else
|
---|
138 | {
|
---|
139 | var html = '' ;
|
---|
140 |
|
---|
141 | for ( var i = 0 ; i < cssFileOrArrayOrDef.length ; i++ )
|
---|
142 | html += getLink( cssFileOrArrayOrDef[i], markTemp ) ;
|
---|
143 |
|
---|
144 | return html ;
|
---|
145 | }
|
---|
146 | }
|
---|
147 | })() ;
|
---|
148 |
|
---|
149 | FCKTools.GetElementDocument = function ( element )
|
---|
150 | {
|
---|
151 | return element.ownerDocument || element.document ;
|
---|
152 | }
|
---|
153 |
|
---|
154 | // Get the window object where the element is placed in.
|
---|
155 | FCKTools.GetElementWindow = function( element )
|
---|
156 | {
|
---|
157 | return this.GetDocumentWindow( this.GetElementDocument( element ) ) ;
|
---|
158 | }
|
---|
159 |
|
---|
160 | FCKTools.GetDocumentWindow = function( document )
|
---|
161 | {
|
---|
162 | // With Safari, there is not way to retrieve the window from the document, so we must fix it.
|
---|
163 | if ( FCKBrowserInfo.IsSafari && !document.parentWindow )
|
---|
164 | this.FixDocumentParentWindow( window.top ) ;
|
---|
165 |
|
---|
166 | return document.parentWindow || document.defaultView ;
|
---|
167 | }
|
---|
168 |
|
---|
169 | /*
|
---|
170 | This is a Safari specific function that fix the reference to the parent
|
---|
171 | window from the document object.
|
---|
172 | */
|
---|
173 | FCKTools.FixDocumentParentWindow = function( targetWindow )
|
---|
174 | {
|
---|
175 | if ( targetWindow.document )
|
---|
176 | targetWindow.document.parentWindow = targetWindow ;
|
---|
177 |
|
---|
178 | for ( var i = 0 ; i < targetWindow.frames.length ; i++ )
|
---|
179 | FCKTools.FixDocumentParentWindow( targetWindow.frames[i] ) ;
|
---|
180 | }
|
---|
181 |
|
---|
182 | FCKTools.HTMLEncode = function( text )
|
---|
183 | {
|
---|
184 | if ( !text )
|
---|
185 | return '' ;
|
---|
186 |
|
---|
187 | text = text.replace( /&/g, '&' ) ;
|
---|
188 | text = text.replace( /</g, '<' ) ;
|
---|
189 | text = text.replace( />/g, '>' ) ;
|
---|
190 |
|
---|
191 | return text ;
|
---|
192 | }
|
---|
193 |
|
---|
194 | FCKTools.HTMLDecode = function( text )
|
---|
195 | {
|
---|
196 | if ( !text )
|
---|
197 | return '' ;
|
---|
198 |
|
---|
199 | text = text.replace( />/g, '>' ) ;
|
---|
200 | text = text.replace( /</g, '<' ) ;
|
---|
201 | text = text.replace( /&/g, '&' ) ;
|
---|
202 |
|
---|
203 | return text ;
|
---|
204 | }
|
---|
205 |
|
---|
206 | FCKTools._ProcessLineBreaksForPMode = function( oEditor, text, liState, node, strArray )
|
---|
207 | {
|
---|
208 | var closeState = 0 ;
|
---|
209 | var blockStartTag = "<p>" ;
|
---|
210 | var blockEndTag = "</p>" ;
|
---|
211 | var lineBreakTag = "<br />" ;
|
---|
212 | if ( liState )
|
---|
213 | {
|
---|
214 | blockStartTag = "<li>" ;
|
---|
215 | blockEndTag = "</li>" ;
|
---|
216 | closeState = 1 ;
|
---|
217 | }
|
---|
218 |
|
---|
219 | // Are we currently inside a <p> tag now?
|
---|
220 | // If yes, close it at the next double line break.
|
---|
221 | while ( node && node != oEditor.FCK.EditorDocument.body )
|
---|
222 | {
|
---|
223 | if ( node.tagName.toLowerCase() == 'p' )
|
---|
224 | {
|
---|
225 | closeState = 1 ;
|
---|
226 | break;
|
---|
227 | }
|
---|
228 | node = node.parentNode ;
|
---|
229 | }
|
---|
230 |
|
---|
231 | for ( var i = 0 ; i < text.length ; i++ )
|
---|
232 | {
|
---|
233 | var c = text.charAt( i ) ;
|
---|
234 | if ( c == '\r' )
|
---|
235 | continue ;
|
---|
236 |
|
---|
237 | if ( c != '\n' )
|
---|
238 | {
|
---|
239 | strArray.push( c ) ;
|
---|
240 | continue ;
|
---|
241 | }
|
---|
242 |
|
---|
243 | // Now we have encountered a line break.
|
---|
244 | // Check if the next character is also a line break.
|
---|
245 | var n = text.charAt( i + 1 ) ;
|
---|
246 | if ( n == '\r' )
|
---|
247 | {
|
---|
248 | i++ ;
|
---|
249 | n = text.charAt( i + 1 ) ;
|
---|
250 | }
|
---|
251 | if ( n == '\n' )
|
---|
252 | {
|
---|
253 | i++ ; // ignore next character - we have already processed it.
|
---|
254 | if ( closeState )
|
---|
255 | strArray.push( blockEndTag ) ;
|
---|
256 | strArray.push( blockStartTag ) ;
|
---|
257 | closeState = 1 ;
|
---|
258 | }
|
---|
259 | else
|
---|
260 | strArray.push( lineBreakTag ) ;
|
---|
261 | }
|
---|
262 | }
|
---|
263 |
|
---|
264 | FCKTools._ProcessLineBreaksForDivMode = function( oEditor, text, liState, node, strArray )
|
---|
265 | {
|
---|
266 | var closeState = 0 ;
|
---|
267 | var blockStartTag = "<div>" ;
|
---|
268 | var blockEndTag = "</div>" ;
|
---|
269 | if ( liState )
|
---|
270 | {
|
---|
271 | blockStartTag = "<li>" ;
|
---|
272 | blockEndTag = "</li>" ;
|
---|
273 | closeState = 1 ;
|
---|
274 | }
|
---|
275 |
|
---|
276 | // Are we currently inside a <div> tag now?
|
---|
277 | // If yes, close it at the next double line break.
|
---|
278 | while ( node && node != oEditor.FCK.EditorDocument.body )
|
---|
279 | {
|
---|
280 | if ( node.tagName.toLowerCase() == 'div' )
|
---|
281 | {
|
---|
282 | closeState = 1 ;
|
---|
283 | break ;
|
---|
284 | }
|
---|
285 | node = node.parentNode ;
|
---|
286 | }
|
---|
287 |
|
---|
288 | for ( var i = 0 ; i < text.length ; i++ )
|
---|
289 | {
|
---|
290 | var c = text.charAt( i ) ;
|
---|
291 | if ( c == '\r' )
|
---|
292 | continue ;
|
---|
293 |
|
---|
294 | if ( c != '\n' )
|
---|
295 | {
|
---|
296 | strArray.push( c ) ;
|
---|
297 | continue ;
|
---|
298 | }
|
---|
299 |
|
---|
300 | if ( closeState )
|
---|
301 | {
|
---|
302 | if ( strArray[ strArray.length - 1 ] == blockStartTag )
|
---|
303 | {
|
---|
304 | // A div tag must have some contents inside for it to be visible.
|
---|
305 | strArray.push( " " ) ;
|
---|
306 | }
|
---|
307 | strArray.push( blockEndTag ) ;
|
---|
308 | }
|
---|
309 | strArray.push( blockStartTag ) ;
|
---|
310 | closeState = 1 ;
|
---|
311 | }
|
---|
312 | if ( closeState )
|
---|
313 | strArray.push( blockEndTag ) ;
|
---|
314 | }
|
---|
315 |
|
---|
316 | FCKTools._ProcessLineBreaksForBrMode = function( oEditor, text, liState, node, strArray )
|
---|
317 | {
|
---|
318 | var closeState = 0 ;
|
---|
319 | var blockStartTag = "<br />" ;
|
---|
320 | var blockEndTag = "" ;
|
---|
321 | if ( liState )
|
---|
322 | {
|
---|
323 | blockStartTag = "<li>" ;
|
---|
324 | blockEndTag = "</li>" ;
|
---|
325 | closeState = 1 ;
|
---|
326 | }
|
---|
327 |
|
---|
328 | for ( var i = 0 ; i < text.length ; i++ )
|
---|
329 | {
|
---|
330 | var c = text.charAt( i ) ;
|
---|
331 | if ( c == '\r' )
|
---|
332 | continue ;
|
---|
333 |
|
---|
334 | if ( c != '\n' )
|
---|
335 | {
|
---|
336 | strArray.push( c ) ;
|
---|
337 | continue ;
|
---|
338 | }
|
---|
339 |
|
---|
340 | if ( closeState && blockEndTag.length )
|
---|
341 | strArray.push ( blockEndTag ) ;
|
---|
342 | strArray.push( blockStartTag ) ;
|
---|
343 | closeState = 1 ;
|
---|
344 | }
|
---|
345 | }
|
---|
346 |
|
---|
347 | FCKTools.ProcessLineBreaks = function( oEditor, oConfig, text )
|
---|
348 | {
|
---|
349 | var enterMode = oConfig.EnterMode.toLowerCase() ;
|
---|
350 | var strArray = [] ;
|
---|
351 |
|
---|
352 | // Is the caret or selection inside an <li> tag now?
|
---|
353 | var liState = 0 ;
|
---|
354 | var range = new oEditor.FCKDomRange( oEditor.FCK.EditorWindow ) ;
|
---|
355 | range.MoveToSelection() ;
|
---|
356 | var node = range._Range.startContainer ;
|
---|
357 | while ( node && node.nodeType != 1 )
|
---|
358 | node = node.parentNode ;
|
---|
359 | if ( node && node.tagName.toLowerCase() == 'li' )
|
---|
360 | liState = 1 ;
|
---|
361 |
|
---|
362 | if ( enterMode == 'p' )
|
---|
363 | this._ProcessLineBreaksForPMode( oEditor, text, liState, node, strArray ) ;
|
---|
364 | else if ( enterMode == 'div' )
|
---|
365 | this._ProcessLineBreaksForDivMode( oEditor, text, liState, node, strArray ) ;
|
---|
366 | else if ( enterMode == 'br' )
|
---|
367 | this._ProcessLineBreaksForBrMode( oEditor, text, liState, node, strArray ) ;
|
---|
368 | return strArray.join( "" ) ;
|
---|
369 | }
|
---|
370 |
|
---|
371 | /**
|
---|
372 | * Adds an option to a SELECT element.
|
---|
373 | */
|
---|
374 | FCKTools.AddSelectOption = function( selectElement, optionText, optionValue )
|
---|
375 | {
|
---|
376 | var oOption = FCKTools.GetElementDocument( selectElement ).createElement( "OPTION" ) ;
|
---|
377 |
|
---|
378 | oOption.text = optionText ;
|
---|
379 | oOption.value = optionValue ;
|
---|
380 |
|
---|
381 | selectElement.options.add(oOption) ;
|
---|
382 |
|
---|
383 | return oOption ;
|
---|
384 | }
|
---|
385 |
|
---|
386 | FCKTools.RunFunction = function( func, thisObject, paramsArray, timerWindow )
|
---|
387 | {
|
---|
388 | if ( func )
|
---|
389 | this.SetTimeout( func, 0, thisObject, paramsArray, timerWindow ) ;
|
---|
390 | }
|
---|
391 |
|
---|
392 | FCKTools.SetTimeout = function( func, milliseconds, thisObject, paramsArray, timerWindow )
|
---|
393 | {
|
---|
394 | return ( timerWindow || window ).setTimeout(
|
---|
395 | function()
|
---|
396 | {
|
---|
397 | if ( paramsArray )
|
---|
398 | func.apply( thisObject, [].concat( paramsArray ) ) ;
|
---|
399 | else
|
---|
400 | func.apply( thisObject ) ;
|
---|
401 | },
|
---|
402 | milliseconds ) ;
|
---|
403 | }
|
---|
404 |
|
---|
405 | FCKTools.SetInterval = function( func, milliseconds, thisObject, paramsArray, timerWindow )
|
---|
406 | {
|
---|
407 | return ( timerWindow || window ).setInterval(
|
---|
408 | function()
|
---|
409 | {
|
---|
410 | func.apply( thisObject, paramsArray || [] ) ;
|
---|
411 | },
|
---|
412 | milliseconds ) ;
|
---|
413 | }
|
---|
414 |
|
---|
415 | FCKTools.ConvertStyleSizeToHtml = function( size )
|
---|
416 | {
|
---|
417 | return size.EndsWith( '%' ) ? size : parseInt( size, 10 ) ;
|
---|
418 | }
|
---|
419 |
|
---|
420 | FCKTools.ConvertHtmlSizeToStyle = function( size )
|
---|
421 | {
|
---|
422 | return size.EndsWith( '%' ) ? size : ( size + 'px' ) ;
|
---|
423 | }
|
---|
424 |
|
---|
425 | // START iCM MODIFICATIONS
|
---|
426 | // Amended to accept a list of one or more ascensor tag names
|
---|
427 | // Amended to check the element itself before working back up through the parent hierarchy
|
---|
428 | FCKTools.GetElementAscensor = function( element, ascensorTagNames )
|
---|
429 | {
|
---|
430 | // var e = element.parentNode ;
|
---|
431 | var e = element ;
|
---|
432 | var lstTags = "," + ascensorTagNames.toUpperCase() + "," ;
|
---|
433 |
|
---|
434 | while ( e )
|
---|
435 | {
|
---|
436 | if ( lstTags.indexOf( "," + e.nodeName.toUpperCase() + "," ) != -1 )
|
---|
437 | return e ;
|
---|
438 |
|
---|
439 | e = e.parentNode ;
|
---|
440 | }
|
---|
441 | return null ;
|
---|
442 | }
|
---|
443 | // END iCM MODIFICATIONS
|
---|
444 |
|
---|
445 | FCKTools.CreateEventListener = function( func, params )
|
---|
446 | {
|
---|
447 | var f = function()
|
---|
448 | {
|
---|
449 | var aAllParams = [] ;
|
---|
450 |
|
---|
451 | for ( var i = 0 ; i < arguments.length ; i++ )
|
---|
452 | aAllParams.push( arguments[i] ) ;
|
---|
453 |
|
---|
454 | func.apply( this, aAllParams.concat( params ) ) ;
|
---|
455 | }
|
---|
456 |
|
---|
457 | return f ;
|
---|
458 | }
|
---|
459 |
|
---|
460 | FCKTools.IsStrictMode = function( document )
|
---|
461 | {
|
---|
462 | // There is no compatMode in Safari, but it seams that it always behave as
|
---|
463 | // CSS1Compat, so let's assume it as the default for that browser.
|
---|
464 | return ( 'CSS1Compat' == ( document.compatMode || ( FCKBrowserInfo.IsSafari ? 'CSS1Compat' : null ) ) ) ;
|
---|
465 | }
|
---|
466 |
|
---|
467 | // Transforms a "arguments" object to an array.
|
---|
468 | FCKTools.ArgumentsToArray = function( args, startIndex, maxLength )
|
---|
469 | {
|
---|
470 | startIndex = startIndex || 0 ;
|
---|
471 | maxLength = maxLength || args.length ;
|
---|
472 |
|
---|
473 | var argsArray = new Array() ;
|
---|
474 |
|
---|
475 | for ( var i = startIndex ; i < startIndex + maxLength && i < args.length ; i++ )
|
---|
476 | argsArray.push( args[i] ) ;
|
---|
477 |
|
---|
478 | return argsArray ;
|
---|
479 | }
|
---|
480 |
|
---|
481 | FCKTools.CloneObject = function( sourceObject )
|
---|
482 | {
|
---|
483 | var fCloneCreator = function() {} ;
|
---|
484 | fCloneCreator.prototype = sourceObject ;
|
---|
485 | return new fCloneCreator ;
|
---|
486 | }
|
---|
487 |
|
---|
488 | // Appends a bogus <br> at the end of the element, if not yet available.
|
---|
489 | FCKTools.AppendBogusBr = function( element )
|
---|
490 | {
|
---|
491 | if ( !element )
|
---|
492 | return ;
|
---|
493 |
|
---|
494 | var eLastChild = this.GetLastItem( element.getElementsByTagName('br') ) ;
|
---|
495 |
|
---|
496 | if ( !eLastChild || ( eLastChild.getAttribute( 'type', 2 ) != '_moz' && eLastChild.getAttribute( '_moz_dirty' ) == null ) )
|
---|
497 | {
|
---|
498 | var doc = this.GetElementDocument( element ) ;
|
---|
499 |
|
---|
500 | if ( FCKBrowserInfo.IsOpera )
|
---|
501 | element.appendChild( doc.createTextNode('') ) ;
|
---|
502 | else
|
---|
503 | element.appendChild( this.CreateBogusBR( doc ) ) ;
|
---|
504 | }
|
---|
505 | }
|
---|
506 |
|
---|
507 | FCKTools.GetLastItem = function( list )
|
---|
508 | {
|
---|
509 | if ( list.length > 0 )
|
---|
510 | return list[ list.length - 1 ] ;
|
---|
511 |
|
---|
512 | return null ;
|
---|
513 | }
|
---|
514 |
|
---|
515 | FCKTools.GetDocumentPosition = function( w, node )
|
---|
516 | {
|
---|
517 | var x = 0 ;
|
---|
518 | var y = 0 ;
|
---|
519 | var curNode = node ;
|
---|
520 | var prevNode = null ;
|
---|
521 | var curWindow = FCKTools.GetElementWindow( curNode ) ;
|
---|
522 | while ( curNode && !( curWindow == w && ( curNode == w.document.body || curNode == w.document.documentElement ) ) )
|
---|
523 | {
|
---|
524 | x += curNode.offsetLeft - curNode.scrollLeft ;
|
---|
525 | y += curNode.offsetTop - curNode.scrollTop ;
|
---|
526 |
|
---|
527 | if ( ! FCKBrowserInfo.IsOpera )
|
---|
528 | {
|
---|
529 | var scrollNode = prevNode ;
|
---|
530 | while ( scrollNode && scrollNode != curNode )
|
---|
531 | {
|
---|
532 | x -= scrollNode.scrollLeft ;
|
---|
533 | y -= scrollNode.scrollTop ;
|
---|
534 | scrollNode = scrollNode.parentNode ;
|
---|
535 | }
|
---|
536 | }
|
---|
537 |
|
---|
538 | prevNode = curNode ;
|
---|
539 | if ( curNode.offsetParent )
|
---|
540 | curNode = curNode.offsetParent ;
|
---|
541 | else
|
---|
542 | {
|
---|
543 | if ( curWindow != w )
|
---|
544 | {
|
---|
545 | curNode = curWindow.frameElement ;
|
---|
546 | prevNode = null ;
|
---|
547 | if ( curNode )
|
---|
548 | curWindow = curNode.contentWindow.parent ;
|
---|
549 | }
|
---|
550 | else
|
---|
551 | curNode = null ;
|
---|
552 | }
|
---|
553 | }
|
---|
554 |
|
---|
555 | // document.body is a special case when it comes to offsetTop and offsetLeft values.
|
---|
556 | // 1. It matters if document.body itself is a positioned element;
|
---|
557 | // 2. It matters is when we're in IE and the element has no positioned ancestor.
|
---|
558 | // Otherwise the values should be ignored.
|
---|
559 | if ( FCKDomTools.GetCurrentElementStyle( w.document.body, 'position') != 'static'
|
---|
560 | || ( FCKBrowserInfo.IsIE && FCKDomTools.GetPositionedAncestor( node ) == null ) )
|
---|
561 | {
|
---|
562 | x += w.document.body.offsetLeft ;
|
---|
563 | y += w.document.body.offsetTop ;
|
---|
564 | }
|
---|
565 |
|
---|
566 | return { "x" : x, "y" : y } ;
|
---|
567 | }
|
---|
568 |
|
---|
569 | FCKTools.GetWindowPosition = function( w, node )
|
---|
570 | {
|
---|
571 | var pos = this.GetDocumentPosition( w, node ) ;
|
---|
572 | var scroll = FCKTools.GetScrollPosition( w ) ;
|
---|
573 | pos.x -= scroll.X ;
|
---|
574 | pos.y -= scroll.Y ;
|
---|
575 | return pos ;
|
---|
576 | }
|
---|
577 |
|
---|
578 | FCKTools.ProtectFormStyles = function( formNode )
|
---|
579 | {
|
---|
580 | if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )
|
---|
581 | return [] ;
|
---|
582 | var hijackRecord = [] ;
|
---|
583 | var hijackNames = [ 'style', 'className' ] ;
|
---|
584 | for ( var i = 0 ; i < hijackNames.length ; i++ )
|
---|
585 | {
|
---|
586 | var name = hijackNames[i] ;
|
---|
587 | if ( formNode.elements.namedItem( name ) )
|
---|
588 | {
|
---|
589 | var hijackNode = formNode.elements.namedItem( name ) ;
|
---|
590 | hijackRecord.push( [ hijackNode, hijackNode.nextSibling ] ) ;
|
---|
591 | formNode.removeChild( hijackNode ) ;
|
---|
592 | }
|
---|
593 | }
|
---|
594 | return hijackRecord ;
|
---|
595 | }
|
---|
596 |
|
---|
597 | FCKTools.RestoreFormStyles = function( formNode, hijackRecord )
|
---|
598 | {
|
---|
599 | if ( !formNode || formNode.nodeType != 1 || formNode.tagName.toLowerCase() != 'form' )
|
---|
600 | return ;
|
---|
601 | if ( hijackRecord.length > 0 )
|
---|
602 | {
|
---|
603 | for ( var i = hijackRecord.length - 1 ; i >= 0 ; i-- )
|
---|
604 | {
|
---|
605 | var node = hijackRecord[i][0] ;
|
---|
606 | var sibling = hijackRecord[i][1] ;
|
---|
607 | if ( sibling )
|
---|
608 | formNode.insertBefore( node, sibling ) ;
|
---|
609 | else
|
---|
610 | formNode.appendChild( node ) ;
|
---|
611 | }
|
---|
612 | }
|
---|
613 | }
|
---|
614 |
|
---|
615 | // Perform a one-step DFS walk.
|
---|
616 | FCKTools.GetNextNode = function( node, limitNode )
|
---|
617 | {
|
---|
618 | if ( node.firstChild )
|
---|
619 | return node.firstChild ;
|
---|
620 | else if ( node.nextSibling )
|
---|
621 | return node.nextSibling ;
|
---|
622 | else
|
---|
623 | {
|
---|
624 | var ancestor = node.parentNode ;
|
---|
625 | while ( ancestor )
|
---|
626 | {
|
---|
627 | if ( ancestor == limitNode )
|
---|
628 | return null ;
|
---|
629 | if ( ancestor.nextSibling )
|
---|
630 | return ancestor.nextSibling ;
|
---|
631 | else
|
---|
632 | ancestor = ancestor.parentNode ;
|
---|
633 | }
|
---|
634 | }
|
---|
635 | return null ;
|
---|
636 | }
|
---|
637 |
|
---|
638 | FCKTools.GetNextTextNode = function( textnode, limitNode, checkStop )
|
---|
639 | {
|
---|
640 | node = this.GetNextNode( textnode, limitNode ) ;
|
---|
641 | if ( checkStop && node && checkStop( node ) )
|
---|
642 | return null ;
|
---|
643 | while ( node && node.nodeType != 3 )
|
---|
644 | {
|
---|
645 | node = this.GetNextNode( node, limitNode ) ;
|
---|
646 | if ( checkStop && node && checkStop( node ) )
|
---|
647 | return null ;
|
---|
648 | }
|
---|
649 | return node ;
|
---|
650 | }
|
---|
651 |
|
---|
652 | /**
|
---|
653 | * Merge all objects passed by argument into a single object.
|
---|
654 | */
|
---|
655 | FCKTools.Merge = function()
|
---|
656 | {
|
---|
657 | var args = arguments ;
|
---|
658 | var o = args[0] ;
|
---|
659 |
|
---|
660 | for ( var i = 1 ; i < args.length ; i++ )
|
---|
661 | {
|
---|
662 | var arg = args[i] ;
|
---|
663 | for ( var p in arg )
|
---|
664 | o[p] = arg[p] ;
|
---|
665 | }
|
---|
666 |
|
---|
667 | return o ;
|
---|
668 | }
|
---|
669 |
|
---|
670 | /**
|
---|
671 | * Check if the passed argument is a real Array. It may not working when
|
---|
672 | * calling it cross windows.
|
---|
673 | */
|
---|
674 | FCKTools.IsArray = function( it )
|
---|
675 | {
|
---|
676 | return ( it instanceof Array ) ;
|
---|
677 | }
|
---|
678 |
|
---|
679 | /**
|
---|
680 | * Appends a "length" property to an object, containing the number of
|
---|
681 | * properties available on it, excluded the append property itself.
|
---|
682 | */
|
---|
683 | FCKTools.AppendLengthProperty = function( targetObject, propertyName )
|
---|
684 | {
|
---|
685 | var counter = 0 ;
|
---|
686 |
|
---|
687 | for ( var n in targetObject )
|
---|
688 | counter++ ;
|
---|
689 |
|
---|
690 | return targetObject[ propertyName || 'length' ] = counter ;
|
---|
691 | }
|
---|
692 |
|
---|
693 | /**
|
---|
694 | * Gets the browser parsed version of a css text (style attribute value). On
|
---|
695 | * some cases, the browser makes changes to the css text, returning a different
|
---|
696 | * value. For example, hexadecimal colors get transformed to rgb().
|
---|
697 | */
|
---|
698 | FCKTools.NormalizeCssText = function( unparsedCssText )
|
---|
699 | {
|
---|
700 | // Injects the style in a temporary span object, so the browser parses it,
|
---|
701 | // retrieving its final format.
|
---|
702 | var tempSpan = document.createElement( 'span' ) ;
|
---|
703 | tempSpan.style.cssText = unparsedCssText ;
|
---|
704 | return tempSpan.style.cssText ;
|
---|
705 | }
|
---|
706 |
|
---|
707 | /**
|
---|
708 | * Binding the "this" reference to an object for a function.
|
---|
709 | */
|
---|
710 | FCKTools.Bind = function( subject, func )
|
---|
711 | {
|
---|
712 | return function(){ return func.apply( subject, arguments ) ; } ;
|
---|
713 | }
|
---|
714 |
|
---|
715 | /**
|
---|
716 | * Retrieve the correct "empty iframe" URL for the current browser, which
|
---|
717 | * causes the minimum fuzz (e.g. security warnings in HTTPS, DNS error in
|
---|
718 | * IE5.5, etc.) for that browser, making the iframe ready to DOM use whithout
|
---|
719 | * having to loading an external file.
|
---|
720 | */
|
---|
721 | FCKTools.GetVoidUrl = function()
|
---|
722 | {
|
---|
723 | if ( FCK_IS_CUSTOM_DOMAIN )
|
---|
724 | return "javascript: void( function(){" +
|
---|
725 | "document.open();" +
|
---|
726 | "document.write('<html><head><title></title></head><body></body></html>');" +
|
---|
727 | "document.domain = '" + FCK_RUNTIME_DOMAIN + "';" +
|
---|
728 | "document.close();" +
|
---|
729 | "}() ) ;";
|
---|
730 |
|
---|
731 | if ( FCKBrowserInfo.IsIE )
|
---|
732 | {
|
---|
733 | if ( FCKBrowserInfo.IsIE7 || !FCKBrowserInfo.IsIE6 )
|
---|
734 | return "" ; // IE7+ / IE5.5
|
---|
735 | else
|
---|
736 | return "javascript: '';" ; // IE6+
|
---|
737 | }
|
---|
738 |
|
---|
739 | return "javascript: void(0);" ; // All other browsers.
|
---|
740 | }
|
---|
741 |
|
---|
742 | FCKTools.ResetStyles = function( element )
|
---|
743 | {
|
---|
744 | element.style.cssText = 'margin:0;' +
|
---|
745 | 'padding:0;' +
|
---|
746 | 'border:0;' +
|
---|
747 | 'background-color:transparent;' +
|
---|
748 | 'background-image:none;' ;
|
---|
749 | }
|
---|