2
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
3
* Copyright (C) 2003-2010 Frederico Caldeira Knabben
7
* Licensed under the terms of any of the following licenses at your
10
* - GNU General Public License Version 2 or later (the "GPL")
11
* http://www.gnu.org/licenses/gpl.html
13
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
14
* http://www.gnu.org/licenses/lgpl.html
16
* - Mozilla Public License Version 1.1 or later (the "MPL")
17
* http://www.mozilla.org/MPL/MPL-1.1.html
21
* Useful functions used by almost all dialog window pages.
22
* Dialogs should link to this file as the very first script on the page.
25
// Automatically detect the correct document.domain (#123).
28
var d = document.domain ;
32
// Test if we can access a parent property.
35
var test = window.parent.document.domain ;
40
// Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ...
41
d = d.replace( /.*?(?:\.|$)/, '' ) ;
44
break ; // It was not able to detect the domain.
57
// Attention: FCKConfig must be available in the page.
58
function GetCommonDialogCss( prefix )
60
// CSS minified by http://iceyboard.no-ip.org/projects/css_compressor (see _dev/css_compression.txt).
61
return FCKConfig.BasePath + 'dialog/common/' + '|.ImagePreviewArea{border:#000 1px solid;overflow:auto;width:100%;height:170px;background-color:#fff}.FlashPreviewArea{border:#000 1px solid;padding:5px;overflow:auto;width:100%;height:170px;background-color:#fff}.BtnReset{float:left;background-position:center center;background-image:url(images/reset.gif);width:16px;height:16px;background-repeat:no-repeat;border:1px none;font-size:1px}.BtnLocked,.BtnUnlocked{float:left;background-position:center center;background-image:url(images/locked.gif);width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.BtnUnlocked{background-image:url(images/unlocked.gif)}.BtnOver{border:outset 1px;cursor:pointer;cursor:hand}' ;
64
// Gets a element by its Id. Used for shorter coding.
65
function GetE( elementId )
67
return document.getElementById( elementId ) ;
70
function ShowE( element, isVisible )
72
if ( typeof( element ) == 'string' )
73
element = GetE( element ) ;
74
element.style.display = isVisible ? '' : 'none' ;
77
function SetAttribute( element, attName, attValue )
79
if ( attValue == null || attValue.length == 0 )
80
element.removeAttribute( attName, 0 ) ; // 0 : Case Insensitive
82
element.setAttribute( attName, attValue, 0 ) ; // 0 : Case Insensitive
85
function GetAttribute( element, attName, valueIfNull )
87
var oAtt = element.attributes[attName] ;
89
if ( oAtt == null || !oAtt.specified )
90
return valueIfNull ? valueIfNull : '' ;
92
var oValue = element.getAttribute( attName, 2 ) ;
95
oValue = oAtt.nodeValue ;
97
return ( oValue == null ? valueIfNull : oValue ) ;
100
function SelectField( elementId )
102
var element = GetE( elementId ) ;
105
// element.select may not be available for some fields (like <select>).
106
if ( element.select )
110
// Functions used by text fields to accept numbers only.
111
var IsDigit = ( function()
113
var KeyIdentifierMap =
119
'U+00007F' : 46 // Delete
122
return function ( e )
127
var iCode = ( e.keyCode || e.charCode ) ;
129
if ( !iCode && e.keyIdentifier && ( e.keyIdentifier in KeyIdentifierMap ) )
130
iCode = KeyIdentifierMap[ e.keyIdentifier ] ;
133
( iCode >= 48 && iCode <= 57 ) // Numbers
134
|| (iCode >= 35 && iCode <= 40) // Arrows, Home, End
135
|| iCode == 8 // Backspace
136
|| iCode == 46 // Delete
142
String.prototype.Trim = function()
144
return this.replace( /(^\s*)|(\s*$)/g, '' ) ;
147
String.prototype.StartsWith = function( value )
149
return ( this.substr( 0, value.length ) == value ) ;
152
String.prototype.Remove = function( start, length )
157
s = this.substring( 0, start ) ;
159
if ( start + length < this.length )
160
s += this.substring( start + length , this.length ) ;
165
String.prototype.ReplaceAll = function( searchArray, replaceArray )
167
var replaced = this ;
169
for ( var i = 0 ; i < searchArray.length ; i++ )
171
replaced = replaced.replace( searchArray[i], replaceArray[i] ) ;
177
function OpenFileBrowser( url, width, height )
179
// oEditor must be defined.
181
var iLeft = ( oEditor.FCKConfig.ScreenWidth - width ) / 2 ;
182
var iTop = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ;
184
var sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes,scrollbars=yes" ;
185
sOptions += ",width=" + width ;
186
sOptions += ",height=" + height ;
187
sOptions += ",left=" + iLeft ;
188
sOptions += ",top=" + iTop ;
190
window.open( url, 'FCKBrowseWindow', sOptions ) ;
194
Utility function to create/update an element with a name attribute in IE, so it behaves properly when moved around
195
It also allows to change the name or other special attributes in an existing node
196
oEditor : instance of FCKeditor where the element will be created
197
oOriginal : current element being edited or null if it has to be created
198
nodeName : string with the name of the element to create
199
oAttributes : Hash object with the attributes that must be set at creation time in IE
200
Those attributes will be set also after the element has been
201
created for any other browser to avoid redudant code
203
function CreateNamedElement( oEditor, oOriginal, nodeName, oAttributes )
207
// IE doesn't allow easily to change properties of an existing object,
208
// so remove the old and force the creation of a new one.
210
if ( oOriginal && oEditor.FCKBrowserInfo.IsIE )
212
// Force the creation only if some of the special attributes have changed:
213
var bChanged = false;
214
for( var attName in oAttributes )
215
bChanged |= ( oOriginal.getAttribute( attName, 2) != oAttributes[attName] ) ;
219
oldNode = oOriginal ;
224
// If the node existed (and it's not IE), then we just have to update its attributes
227
oNewNode = oOriginal ;
231
// #676, IE doesn't play nice with the name or type attribute
232
if ( oEditor.FCKBrowserInfo.IsIE )
235
sbHTML.push( '<' + nodeName ) ;
236
for( var prop in oAttributes )
238
sbHTML.push( ' ' + prop + '="' + oAttributes[prop] + '"' ) ;
241
if ( !oEditor.FCKListsLib.EmptyElements[nodeName.toLowerCase()] )
242
sbHTML.push( '</' + nodeName + '>' ) ;
244
oNewNode = oEditor.FCK.EditorDocument.createElement( sbHTML.join('') ) ;
245
// Check if we are just changing the properties of an existing node: copy its properties
248
CopyAttributes( oldNode, oNewNode, oAttributes ) ;
249
oEditor.FCKDomTools.MoveChildren( oldNode, oNewNode ) ;
250
oldNode.parentNode.removeChild( oldNode ) ;
253
if ( oEditor.FCK.Selection.SelectionData )
255
// Trick to refresh the selection object and avoid error in
256
// fckdialog.html Selection.EnsureSelection
257
var oSel = oEditor.FCK.EditorDocument.selection ;
258
oEditor.FCK.Selection.SelectionData = oSel.createRange() ; // Now oSel.type will be 'None' reflecting the real situation
261
oNewNode = oEditor.FCK.InsertElement( oNewNode ) ;
263
// FCK.Selection.SelectionData is broken by now since we've
264
// deleted the previously selected element. So we need to reassign it.
265
if ( oEditor.FCK.Selection.SelectionData )
267
var range = oEditor.FCK.EditorDocument.body.createControlRange() ;
268
range.add( oNewNode ) ;
269
oEditor.FCK.Selection.SelectionData = range ;
274
oNewNode = oEditor.FCK.InsertElement( nodeName ) ;
278
// Set the basic attributes
279
for( var attName in oAttributes )
280
oNewNode.setAttribute( attName, oAttributes[attName], 0 ) ; // 0 : Case Insensitive
285
// Copy all the attributes from one node to the other, kinda like a clone
286
// But oSkipAttributes is an object with the attributes that must NOT be copied
287
function CopyAttributes( oSource, oDest, oSkipAttributes )
289
var aAttributes = oSource.attributes ;
291
for ( var n = 0 ; n < aAttributes.length ; n++ )
293
var oAttribute = aAttributes[n] ;
295
if ( oAttribute.specified )
297
var sAttName = oAttribute.nodeName ;
298
// We can set the type only once, so do it with the proper value, not copying it.
299
if ( sAttName in oSkipAttributes )
302
var sAttValue = oSource.getAttribute( sAttName, 2 ) ;
303
if ( sAttValue == null )
304
sAttValue = oAttribute.nodeValue ;
306
oDest.setAttribute( sAttName, sAttValue, 0 ) ; // 0 : Case Insensitive
310
if ( oSource.style.cssText !== '' )
311
oDest.style.cssText = oSource.style.cssText ;
315
* Replaces a tag with another one, keeping its contents:
316
* for example TD --> TH, and TH --> TD.
317
* input: the original node, and the new tag name
318
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-renameNode
320
function RenameNode( oNode , newTag )
322
// TODO: if the browser natively supports document.renameNode call it.
323
// does any browser currently support it in order to test?
325
// Only rename element nodes.
326
if ( oNode.nodeType != 1 )
329
// If it's already correct exit here.
330
if ( oNode.nodeName == newTag )
333
var oDoc = oNode.ownerDocument ;
334
// Create the new node
335
var newNode = oDoc.createElement( newTag ) ;
337
// Copy all attributes
338
CopyAttributes( oNode, newNode, {} ) ;
340
// Move children to the new node
341
FCKDomTools.MoveChildren( oNode, newNode ) ;
343
// Finally replace the node and return the new one
344
oNode.parentNode.replaceChild( newNode, oNode ) ;