import torrus 1.0.9
[freeside.git] / httemplate / elements / fckeditor / editor / dialog / common / fck_dialog_common.js
1 /*\r
2  * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
3  * Copyright (C) 2003-2010 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  * Useful functions used by almost all dialog window pages.\r
22  * Dialogs should link to this file as the very first script on the page.\r
23  */\r
24 \r
25 // Automatically detect the correct document.domain (#123).\r
26 (function()\r
27 {\r
28         var d = document.domain ;\r
29 \r
30         while ( true )\r
31         {\r
32                 // Test if we can access a parent property.\r
33                 try\r
34                 {\r
35                         var test = window.parent.document.domain ;\r
36                         break ;\r
37                 }\r
38                 catch( e ) {}\r
39 \r
40                 // Remove a domain part: www.mytest.example.com => mytest.example.com => example.com ...\r
41                 d = d.replace( /.*?(?:\.|$)/, '' ) ;\r
42 \r
43                 if ( d.length == 0 )\r
44                         break ;         // It was not able to detect the domain.\r
45 \r
46                 try\r
47                 {\r
48                         document.domain = d ;\r
49                 }\r
50                 catch (e)\r
51                 {\r
52                         break ;\r
53                 }\r
54         }\r
55 })() ;\r
56 \r
57 // Attention: FCKConfig must be available in the page.\r
58 function GetCommonDialogCss( prefix )\r
59 {\r
60         // CSS minified by http://iceyboard.no-ip.org/projects/css_compressor (see _dev/css_compression.txt).\r
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}' ;\r
62 }\r
63 \r
64 // Gets a element by its Id. Used for shorter coding.\r
65 function GetE( elementId )\r
66 {\r
67         return document.getElementById( elementId )  ;\r
68 }\r
69 \r
70 function ShowE( element, isVisible )\r
71 {\r
72         if ( typeof( element ) == 'string' )\r
73                 element = GetE( element ) ;\r
74         element.style.display = isVisible ? '' : 'none' ;\r
75 }\r
76 \r
77 function SetAttribute( element, attName, attValue )\r
78 {\r
79         if ( attValue == null || attValue.length == 0 )\r
80                 element.removeAttribute( attName, 0 ) ;                 // 0 : Case Insensitive\r
81         else\r
82                 element.setAttribute( attName, attValue, 0 ) ;  // 0 : Case Insensitive\r
83 }\r
84 \r
85 function GetAttribute( element, attName, valueIfNull )\r
86 {\r
87         var oAtt = element.attributes[attName] ;\r
88 \r
89         if ( oAtt == null || !oAtt.specified )\r
90                 return valueIfNull ? valueIfNull : '' ;\r
91 \r
92         var oValue = element.getAttribute( attName, 2 ) ;\r
93 \r
94         if ( oValue == null )\r
95                 oValue = oAtt.nodeValue ;\r
96 \r
97         return ( oValue == null ? valueIfNull : oValue ) ;\r
98 }\r
99 \r
100 function SelectField( elementId )\r
101 {\r
102         var element = GetE( elementId ) ;\r
103         element.focus() ;\r
104 \r
105         // element.select may not be available for some fields (like <select>).\r
106         if ( element.select )\r
107                 element.select() ;\r
108 }\r
109 \r
110 // Functions used by text fields to accept numbers only.\r
111 var IsDigit = ( function()\r
112         {\r
113                 var KeyIdentifierMap =\r
114                 {\r
115                         End                     : 35,\r
116                         Home            : 36,\r
117                         Left            : 37,\r
118                         Right           : 39,\r
119                         'U+00007F'      : 46            // Delete\r
120                 } ;\r
121 \r
122                 return function ( e )\r
123                         {\r
124                                 if ( !e )\r
125                                         e = event ;\r
126 \r
127                                 var iCode = ( e.keyCode || e.charCode ) ;\r
128 \r
129                                 if ( !iCode && e.keyIdentifier && ( e.keyIdentifier in KeyIdentifierMap ) )\r
130                                                 iCode = KeyIdentifierMap[ e.keyIdentifier ] ;\r
131 \r
132                                 return (\r
133                                                 ( iCode >= 48 && iCode <= 57 )          // Numbers\r
134                                                 || (iCode >= 35 && iCode <= 40)         // Arrows, Home, End\r
135                                                 || iCode == 8                                           // Backspace\r
136                                                 || iCode == 46                                          // Delete\r
137                                                 || iCode == 9                                           // Tab\r
138                                 ) ;\r
139                         }\r
140         } )() ;\r
141 \r
142 String.prototype.Trim = function()\r
143 {\r
144         return this.replace( /(^\s*)|(\s*$)/g, '' ) ;\r
145 }\r
146 \r
147 String.prototype.StartsWith = function( value )\r
148 {\r
149         return ( this.substr( 0, value.length ) == value ) ;\r
150 }\r
151 \r
152 String.prototype.Remove = function( start, length )\r
153 {\r
154         var s = '' ;\r
155 \r
156         if ( start > 0 )\r
157                 s = this.substring( 0, start ) ;\r
158 \r
159         if ( start + length < this.length )\r
160                 s += this.substring( start + length , this.length ) ;\r
161 \r
162         return s ;\r
163 }\r
164 \r
165 String.prototype.ReplaceAll = function( searchArray, replaceArray )\r
166 {\r
167         var replaced = this ;\r
168 \r
169         for ( var i = 0 ; i < searchArray.length ; i++ )\r
170         {\r
171                 replaced = replaced.replace( searchArray[i], replaceArray[i] ) ;\r
172         }\r
173 \r
174         return replaced ;\r
175 }\r
176 \r
177 function OpenFileBrowser( url, width, height )\r
178 {\r
179         // oEditor must be defined.\r
180 \r
181         var iLeft = ( oEditor.FCKConfig.ScreenWidth  - width ) / 2 ;\r
182         var iTop  = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ;\r
183 \r
184         var sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes,scrollbars=yes" ;\r
185         sOptions += ",width=" + width ;\r
186         sOptions += ",height=" + height ;\r
187         sOptions += ",left=" + iLeft ;\r
188         sOptions += ",top=" + iTop ;\r
189 \r
190         window.open( url, 'FCKBrowseWindow', sOptions ) ;\r
191 }\r
192 \r
193 /**\r
194  Utility function to create/update an element with a name attribute in IE, so it behaves properly when moved around\r
195  It also allows to change the name or other special attributes in an existing node\r
196         oEditor : instance of FCKeditor where the element will be created\r
197         oOriginal : current element being edited or null if it has to be created\r
198         nodeName : string with the name of the element to create\r
199         oAttributes : Hash object with the attributes that must be set at creation time in IE\r
200                                                                 Those attributes will be set also after the element has been\r
201                                                                 created for any other browser to avoid redudant code\r
202 */\r
203 function CreateNamedElement( oEditor, oOriginal, nodeName, oAttributes )\r
204 {\r
205         var oNewNode ;\r
206 \r
207         // IE doesn't allow easily to change properties of an existing object,\r
208         // so remove the old and force the creation of a new one.\r
209         var oldNode = null ;\r
210         if ( oOriginal && oEditor.FCKBrowserInfo.IsIE )\r
211         {\r
212                 // Force the creation only if some of the special attributes have changed:\r
213                 var bChanged = false;\r
214                 for( var attName in oAttributes )\r
215                         bChanged |= ( oOriginal.getAttribute( attName, 2) != oAttributes[attName] ) ;\r
216 \r
217                 if ( bChanged )\r
218                 {\r
219                         oldNode = oOriginal ;\r
220                         oOriginal = null ;\r
221                 }\r
222         }\r
223 \r
224         // If the node existed (and it's not IE), then we just have to update its attributes\r
225         if ( oOriginal )\r
226         {\r
227                 oNewNode = oOriginal ;\r
228         }\r
229         else\r
230         {\r
231                 // #676, IE doesn't play nice with the name or type attribute\r
232                 if ( oEditor.FCKBrowserInfo.IsIE )\r
233                 {\r
234                         var sbHTML = [] ;\r
235                         sbHTML.push( '<' + nodeName ) ;\r
236                         for( var prop in oAttributes )\r
237                         {\r
238                                 sbHTML.push( ' ' + prop + '="' + oAttributes[prop] + '"' ) ;\r
239                         }\r
240                         sbHTML.push( '>' ) ;\r
241                         if ( !oEditor.FCKListsLib.EmptyElements[nodeName.toLowerCase()] )\r
242                                 sbHTML.push( '</' + nodeName + '>' ) ;\r
243 \r
244                         oNewNode = oEditor.FCK.EditorDocument.createElement( sbHTML.join('') ) ;\r
245                         // Check if we are just changing the properties of an existing node: copy its properties\r
246                         if ( oldNode )\r
247                         {\r
248                                 CopyAttributes( oldNode, oNewNode, oAttributes ) ;\r
249                                 oEditor.FCKDomTools.MoveChildren( oldNode, oNewNode ) ;\r
250                                 oldNode.parentNode.removeChild( oldNode ) ;\r
251                                 oldNode = null ;\r
252 \r
253                                 if ( oEditor.FCK.Selection.SelectionData )\r
254                                 {\r
255                                         // Trick to refresh the selection object and avoid error in\r
256                                         // fckdialog.html Selection.EnsureSelection\r
257                                         var oSel = oEditor.FCK.EditorDocument.selection ;\r
258                                         oEditor.FCK.Selection.SelectionData = oSel.createRange() ; // Now oSel.type will be 'None' reflecting the real situation\r
259                                 }\r
260                         }\r
261                         oNewNode = oEditor.FCK.InsertElement( oNewNode ) ;\r
262 \r
263                         // FCK.Selection.SelectionData is broken by now since we've\r
264                         // deleted the previously selected element. So we need to reassign it.\r
265                         if ( oEditor.FCK.Selection.SelectionData )\r
266                         {\r
267                                 var range = oEditor.FCK.EditorDocument.body.createControlRange() ;\r
268                                 range.add( oNewNode ) ;\r
269                                 oEditor.FCK.Selection.SelectionData = range ;\r
270                         }\r
271                 }\r
272                 else\r
273                 {\r
274                         oNewNode = oEditor.FCK.InsertElement( nodeName ) ;\r
275                 }\r
276         }\r
277 \r
278         // Set the basic attributes\r
279         for( var attName in oAttributes )\r
280                 oNewNode.setAttribute( attName, oAttributes[attName], 0 ) ;     // 0 : Case Insensitive\r
281 \r
282         return oNewNode ;\r
283 }\r
284 \r
285 // Copy all the attributes from one node to the other, kinda like a clone\r
286 // But oSkipAttributes is an object with the attributes that must NOT be copied\r
287 function CopyAttributes( oSource, oDest, oSkipAttributes )\r
288 {\r
289         var aAttributes = oSource.attributes ;\r
290 \r
291         for ( var n = 0 ; n < aAttributes.length ; n++ )\r
292         {\r
293                 var oAttribute = aAttributes[n] ;\r
294 \r
295                 if ( oAttribute.specified )\r
296                 {\r
297                         var sAttName = oAttribute.nodeName ;\r
298                         // We can set the type only once, so do it with the proper value, not copying it.\r
299                         if ( sAttName in oSkipAttributes )\r
300                                 continue ;\r
301 \r
302                         var sAttValue = oSource.getAttribute( sAttName, 2 ) ;\r
303                         if ( sAttValue == null )\r
304                                 sAttValue = oAttribute.nodeValue ;\r
305 \r
306                         oDest.setAttribute( sAttName, sAttValue, 0 ) ;  // 0 : Case Insensitive\r
307                 }\r
308         }\r
309         // The style:\r
310         if ( oSource.style.cssText !== '' )\r
311                 oDest.style.cssText = oSource.style.cssText ;\r
312 }\r
313 \r
314 /**\r
315 * Replaces a tag with another one, keeping its contents:\r
316 * for example TD --> TH, and TH --> TD.\r
317 * input: the original node, and the new tag name\r
318 * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Document3-renameNode\r
319 */\r
320 function RenameNode( oNode , newTag )\r
321 {\r
322         // TODO: if the browser natively supports document.renameNode call it.\r
323         // does any browser currently support it in order to test?\r
324 \r
325         // Only rename element nodes.\r
326         if ( oNode.nodeType != 1 )\r
327                 return null ;\r
328 \r
329         // If it's already correct exit here.\r
330         if ( oNode.nodeName == newTag )\r
331                 return oNode ;\r
332 \r
333         var oDoc = oNode.ownerDocument ;\r
334         // Create the new node\r
335         var newNode = oDoc.createElement( newTag ) ;\r
336 \r
337         // Copy all attributes\r
338         CopyAttributes( oNode, newNode, {} ) ;\r
339 \r
340         // Move children to the new node\r
341         FCKDomTools.MoveChildren( oNode, newNode ) ;\r
342 \r
343         // Finally replace the node and return the new one\r
344         oNode.parentNode.replaceChild( newNode, oNode ) ;\r
345 \r
346         return newNode ;\r
347 }\r