Project

General

Profile

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
 * Useful functions used by almost all dialog window pages.
22
 * Dialogs should link to this file as the very first script on the page.
23
 */
24

    
25
// Automatically detect the correct document.domain (#123).
26
(function()
27
{
28
	var d = document.domain ;
29

    
30
	while ( true )
31
	{
32
		// Test if we can access a parent property.
33
		try
34
		{
35
			var test = window.parent.document.domain ;
36
			break ;
37
		}
38
		catch( e ) {}
39

    
40
		// Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ...
41
		d = d.replace( /.*?(?:\.|$)/, '' ) ;
42

    
43
		if ( d.length == 0 )
44
			break ;		// It was not able to detect the domain.
45

    
46
		try
47
		{
48
			document.domain = d ;
49
		}
50
		catch (e)
51
		{
52
			break ;
53
		}
54
	}
55
})() ;
56

    
57
// Attention: FCKConfig must be available in the page.
58
function GetCommonDialogCss( prefix )
59
{
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}' ;
62
}
63

    
64
// Gets a element by its Id. Used for shorter coding.
65
function GetE( elementId )
66
{
67
	return document.getElementById( elementId )  ;
68
}
69

    
70
function ShowE( element, isVisible )
71
{
72
	if ( typeof( element ) == 'string' )
73
		element = GetE( element ) ;
74
	element.style.display = isVisible ? '' : 'none' ;
75
}
76

    
77
function SetAttribute( element, attName, attValue )
78
{
79
	if ( attValue == null || attValue.length == 0 )
80
		element.removeAttribute( attName, 0 ) ;			// 0 : Case Insensitive
81
	else
82
		element.setAttribute( attName, attValue, 0 ) ;	// 0 : Case Insensitive
83
}
84

    
85
function GetAttribute( element, attName, valueIfNull )
86
{
87
	var oAtt = element.attributes[attName] ;
88

    
89
	if ( oAtt == null || !oAtt.specified )
90
		return valueIfNull ? valueIfNull : '' ;
91

    
92
	var oValue = element.getAttribute( attName, 2 ) ;
93

    
94
	if ( oValue == null )
95
		oValue = oAtt.nodeValue ;
96

    
97
	return ( oValue == null ? valueIfNull : oValue ) ;
98
}
99

    
100
function SelectField( elementId )
101
{
102
	var element = GetE( elementId ) ;
103
	element.focus() ;
104

    
105
	// element.select may not be available for some fields (like <select>).
106
	if ( element.select )
107
		element.select() ;
108
}
109

    
110
// Functions used by text fields to accept numbers only.
111
var IsDigit = ( function()
112
	{
113
		var KeyIdentifierMap =
114
		{
115
			End			: 35,
116
			Home		: 36,
117
			Left		: 37,
118
			Right		: 39,
119
			'U+00007F'	: 46		// Delete
120
		} ;
121

    
122
		return function ( e )
123
			{
124
				if ( !e )
125
					e = event ;
126

    
127
				var iCode = ( e.keyCode || e.charCode ) ;
128

    
129
				if ( !iCode && e.keyIdentifier && ( e.keyIdentifier in KeyIdentifierMap ) )
130
						iCode = KeyIdentifierMap[ e.keyIdentifier ] ;
131

    
132
				return (
133
						( iCode >= 48 && iCode <= 57 )		// Numbers
134
						|| (iCode >= 35 && iCode <= 40)		// Arrows, Home, End
135
						|| iCode == 8						// Backspace
136
						|| iCode == 46						// Delete
137
						|| iCode == 9						// Tab
138
				) ;
139
			}
140
	} )() ;
141

    
142
String.prototype.Trim = function()
143
{
144
	return this.replace( /(^\s*)|(\s*$)/g, '' ) ;
145
}
146

    
147
String.prototype.StartsWith = function( value )
148
{
149
	return ( this.substr( 0, value.length ) == value ) ;
150
}
151

    
152
String.prototype.Remove = function( start, length )
153
{
154
	var s = '' ;
155

    
156
	if ( start > 0 )
157
		s = this.substring( 0, start ) ;
158

    
159
	if ( start + length < this.length )
160
		s += this.substring( start + length , this.length ) ;
161

    
162
	return s ;
163
}
164

    
165
String.prototype.ReplaceAll = function( searchArray, replaceArray )
166
{
167
	var replaced = this ;
168

    
169
	for ( var i = 0 ; i < searchArray.length ; i++ )
170
	{
171
		replaced = replaced.replace( searchArray[i], replaceArray[i] ) ;
172
	}
173

    
174
	return replaced ;
175
}
176

    
177
function OpenFileBrowser( url, width, height )
178
{
179
	// oEditor must be defined.
180

    
181
	var iLeft = ( oEditor.FCKConfig.ScreenWidth  - width ) / 2 ;
182
	var iTop  = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ;
183

    
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 ;
189

    
190
	window.open( url, 'FCKBrowseWindow', sOptions ) ;
191
}
192

    
193
/**
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
202
*/
203
function CreateNamedElement( oEditor, oOriginal, nodeName, oAttributes )
204
{
205
	var oNewNode ;
206

    
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.
209
	var oldNode = null ;
210
	if ( oOriginal && oEditor.FCKBrowserInfo.IsIE )
211
	{
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] ) ;
216

    
217
		if ( bChanged )
218
		{
219
			oldNode = oOriginal ;
220
			oOriginal = null ;
221
		}
222
	}
223

    
224
	// If the node existed (and it's not IE), then we just have to update its attributes
225
	if ( oOriginal )
226
	{
227
		oNewNode = oOriginal ;
228
	}
229
	else
230
	{
231
		// #676, IE doesn't play nice with the name or type attribute
232
		if ( oEditor.FCKBrowserInfo.IsIE )
233
		{
234
			var sbHTML = [] ;
235
			sbHTML.push( '<' + nodeName ) ;
236
			for( var prop in oAttributes )
237
			{
238
				sbHTML.push( ' ' + prop + '="' + oAttributes[prop] + '"' ) ;
239
			}
240
			sbHTML.push( '>' ) ;
241
			if ( !oEditor.FCKListsLib.EmptyElements[nodeName.toLowerCase()] )
242
				sbHTML.push( '</' + nodeName + '>' ) ;
243

    
244
			oNewNode = oEditor.FCK.EditorDocument.createElement( sbHTML.join('') ) ;
245
			// Check if we are just changing the properties of an existing node: copy its properties
246
			if ( oldNode )
247
			{
248
				CopyAttributes( oldNode, oNewNode, oAttributes ) ;
249
				oEditor.FCKDomTools.MoveChildren( oldNode, oNewNode ) ;
250
				oldNode.parentNode.removeChild( oldNode ) ;
251
				oldNode = null ;
252

    
253
				if ( oEditor.FCK.Selection.SelectionData )
254
				{
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
259
				}
260
			}
261
			oNewNode = oEditor.FCK.InsertElement( oNewNode ) ;
262

    
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 )
266
			{
267
				var range = oEditor.FCK.EditorDocument.body.createControlRange() ;
268
				range.add( oNewNode ) ;
269
				oEditor.FCK.Selection.SelectionData = range ;
270
			}
271
		}
272
		else
273
		{
274
			oNewNode = oEditor.FCK.InsertElement( nodeName ) ;
275
		}
276
	}
277

    
278
	// Set the basic attributes
279
	for( var attName in oAttributes )
280
		oNewNode.setAttribute( attName, oAttributes[attName], 0 ) ;	// 0 : Case Insensitive
281

    
282
	return oNewNode ;
283
}
284

    
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 )
288
{
289
	var aAttributes = oSource.attributes ;
290

    
291
	for ( var n = 0 ; n < aAttributes.length ; n++ )
292
	{
293
		var oAttribute = aAttributes[n] ;
294

    
295
		if ( oAttribute.specified )
296
		{
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 )
300
				continue ;
301

    
302
			var sAttValue = oSource.getAttribute( sAttName, 2 ) ;
303
			if ( sAttValue == null )
304
				sAttValue = oAttribute.nodeValue ;
305

    
306
			oDest.setAttribute( sAttName, sAttValue, 0 ) ;	// 0 : Case Insensitive
307
		}
308
	}
309
	// The style:
310
	if ( oSource.style.cssText !== '' )
311
		oDest.style.cssText = oSource.style.cssText ;
312
}
313

    
314
/**
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
319
*/
320
function RenameNode( oNode , newTag )
321
{
322
	// TODO: if the browser natively supports document.renameNode call it.
323
	// does any browser currently support it in order to test?
324

    
325
	// Only rename element nodes.
326
	if ( oNode.nodeType != 1 )
327
		return null ;
328

    
329
	// If it's already correct exit here.
330
	if ( oNode.nodeName == newTag )
331
		return oNode ;
332

    
333
	var oDoc = oNode.ownerDocument ;
334
	// Create the new node
335
	var newNode = oDoc.createElement( newTag ) ;
336

    
337
	// Copy all attributes
338
	CopyAttributes( oNode, newNode, {} ) ;
339

    
340
	// Move children to the new node
341
	FCKDomTools.MoveChildren( oNode, newNode ) ;
342

    
343
	// Finally replace the node and return the new one
344
	oNode.parentNode.replaceChild( newNode, oNode ) ;
345

    
346
	return newNode ;
347
}
(2-2/2)