]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/tiny_mce/classes/Popup.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / tiny_mce / classes / Popup.js
1 /**
2  * Popup.js
3  *
4  * Copyright 2009, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://tinymce.moxiecode.com/license
8  * Contributing: http://tinymce.moxiecode.com/contributing
9  */
10
11 // Some global instances
12 var tinymce = null, tinyMCEPopup, tinyMCE;
13
14 /**
15  * TinyMCE popup/dialog helper class. This gives you easy access to the
16  * parent editor instance and a bunch of other things. It's higly recommended
17  * that you load this script into your dialogs.
18  *
19  * @static
20  * @class tinyMCEPopup
21  */
22 tinyMCEPopup = {
23         /**
24          * Initializes the popup this will be called automatically.
25          *
26          * @method init
27          */
28         init : function() {
29                 var t = this, w, ti;
30
31                 // Find window & API
32                 w = t.getWin();
33                 tinymce = w.tinymce;
34                 tinyMCE = w.tinyMCE;
35                 t.editor = tinymce.EditorManager.activeEditor;
36                 t.params = t.editor.windowManager.params;
37                 t.features = t.editor.windowManager.features;
38
39                 // Setup local DOM
40                 t.dom = t.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document);
41
42                 // Enables you to skip loading the default css
43                 if (t.features.popup_css !== false)
44                         t.dom.loadCSS(t.features.popup_css || t.editor.settings.popup_css);
45
46                 // Setup on init listeners
47                 t.listeners = [];
48
49                 /**
50                  * Fires when the popup is initialized.
51                  *
52                  * @event onInit
53                  * @param {tinymce.Editor} editor Editor instance.
54                  * @example
55                  * // Alerts the selected contents when the dialog is loaded
56                  * tinyMCEPopup.onInit.add(function(ed) {
57                  *     alert(ed.selection.getContent());
58                  * });
59                  * 
60                  * // Executes the init method on page load in some object using the SomeObject scope
61                  * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject);
62                  */
63                 t.onInit = {
64                         add : function(f, s) {
65                                 t.listeners.push({func : f, scope : s});
66                         }
67                 };
68
69                 t.isWindow = !t.getWindowArg('mce_inline');
70                 t.id = t.getWindowArg('mce_window_id');
71                 t.editor.windowManager.onOpen.dispatch(t.editor.windowManager, window);
72         },
73
74         /**
75          * Returns the reference to the parent window that opened the dialog.
76          *
77          * @method getWin
78          * @return {Window} Reference to the parent window that opened the dialog.
79          */
80         getWin : function() {
81                 // Added frameElement check to fix bug: #2817583
82                 return (!window.frameElement && window.dialogArguments) || opener || parent || top;
83         },
84
85         /**
86          * Returns a window argument/parameter by name.
87          *
88          * @method getWindowArg
89          * @param {String} n Name of the window argument to retrive.
90          * @param {String} dv Optional default value to return.
91          * @return {String} Argument value or default value if it wasn't found.
92          */
93         getWindowArg : function(n, dv) {
94                 var v = this.params[n];
95
96                 return tinymce.is(v) ? v : dv;
97         },
98
99         /**
100          * Returns a editor parameter/config option value.
101          *
102          * @method getParam
103          * @param {String} n Name of the editor config option to retrive.
104          * @param {String} dv Optional default value to return.
105          * @return {String} Parameter value or default value if it wasn't found.
106          */
107         getParam : function(n, dv) {
108                 return this.editor.getParam(n, dv);
109         },
110
111         /**
112          * Returns a language item by key.
113          *
114          * @method getLang
115          * @param {String} n Language item like mydialog.something.
116          * @param {String} dv Optional default value to return.
117          * @return {String} Language value for the item like "my string" or the default value if it wasn't found.
118          */
119         getLang : function(n, dv) {
120                 return this.editor.getLang(n, dv);
121         },
122
123         /**
124          * Executed a command on editor that opened the dialog/popup.
125          *
126          * @method execCommand
127          * @param {String} cmd Command to execute.
128          * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not.
129          * @param {Object} val Optional value to pass with the comman like an URL.
130          * @param {Object} a Optional arguments object.
131          */
132         execCommand : function(cmd, ui, val, a) {
133                 a = a || {};
134                 a.skip_focus = 1;
135
136                 this.restoreSelection();
137                 return this.editor.execCommand(cmd, ui, val, a);
138         },
139
140         /**
141          * Resizes the dialog to the inner size of the window. This is needed since various browsers
142          * have different border sizes on windows.
143          *
144          * @method resizeToInnerSize
145          */
146         resizeToInnerSize : function() {
147                 var t = this;
148
149                 // Detach it to workaround a Chrome specific bug
150                 // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281
151                 setTimeout(function() {
152                         var vp = t.dom.getViewPort(window);
153
154                         t.editor.windowManager.resizeBy(
155                                 t.getWindowArg('mce_width') - vp.w,
156                                 t.getWindowArg('mce_height') - vp.h,
157                                 t.id || window
158                         );
159                 }, 10);
160         },
161
162         /**
163          * Will executed the specified string when the page has been loaded. This function
164          * was added for compatibility with the 2.x branch.
165          *
166          * @method executeOnLoad
167          * @param {String} s String to evalutate on init.
168          */
169         executeOnLoad : function(s) {
170                 this.onInit.add(function() {
171                         eval(s);
172                 });
173         },
174
175         /**
176          * Stores the current editor selection for later restoration. This can be useful since some browsers
177          * looses it's selection if a control element is selected/focused inside the dialogs.
178          *
179          * @method storeSelection
180          */
181         storeSelection : function() {
182                 this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1);
183         },
184
185         /**
186          * Restores any stored selection. This can be useful since some browsers
187          * looses it's selection if a control element is selected/focused inside the dialogs.
188          *
189          * @method restoreSelection
190          */
191         restoreSelection : function() {
192                 var t = tinyMCEPopup;
193
194                 if (!t.isWindow && tinymce.isIE)
195                         t.editor.selection.moveToBookmark(t.editor.windowManager.bookmark);
196         },
197
198         /**
199          * Loads a specific dialog language pack. If you pass in plugin_url as a arugment
200          * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file.
201          *
202          * @method requireLangPack
203          */
204         requireLangPack : function() {
205                 var t = this, u = t.getWindowArg('plugin_url') || t.getWindowArg('theme_url');
206
207                 if (u && t.editor.settings.language && t.features.translate_i18n !== false && t.editor.settings.language_load !== false) {
208                         u += '/langs/' + t.editor.settings.language + '_dlg.js';
209
210                         if (!tinymce.ScriptLoader.isDone(u)) {
211                                 document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');
212                                 tinymce.ScriptLoader.markDone(u);
213                         }
214                 }
215         },
216
217         /**
218          * Executes a color picker on the specified element id. When the user
219          * then selects a color it will be set as the value of the specified element.
220          *
221          * @method pickColor
222          * @param {DOMEvent} e DOM event object.
223          * @param {string} element_id Element id to be filled with the color value from the picker.
224          */
225         pickColor : function(e, element_id) {
226                 this.execCommand('mceColorPicker', true, {
227                         color : document.getElementById(element_id).value,
228                         func : function(c) {
229                                 document.getElementById(element_id).value = c;
230
231                                 try {
232                                         document.getElementById(element_id).onchange();
233                                 } catch (ex) {
234                                         // Try fire event, ignore errors
235                                 }
236                         }
237                 });
238         },
239
240         /**
241          * Opens a filebrowser/imagebrowser this will set the output value from
242          * the browser as a value on the specified element.
243          *
244          * @method openBrowser
245          * @param {string} element_id Id of the element to set value in.
246          * @param {string} type Type of browser to open image/file/flash.
247          * @param {string} option Option name to get the file_broswer_callback function name from.
248          */
249         openBrowser : function(element_id, type, option) {
250                 tinyMCEPopup.restoreSelection();
251                 this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
252         },
253
254         /**
255          * Creates a confirm dialog. Please don't use the blocking behavior of this
256          * native version use the callback method instead then it can be extended.
257          *
258          * @method confirm
259          * @param {String} t Title for the new confirm dialog.
260          * @param {function} cb Callback function to be executed after the user has selected ok or cancel.
261          * @param {Object} s Optional scope to execute the callback in.
262          */
263         confirm : function(t, cb, s) {
264                 this.editor.windowManager.confirm(t, cb, s, window);
265         },
266
267         /**
268          * Creates a alert dialog. Please don't use the blocking behavior of this
269          * native version use the callback method instead then it can be extended.
270          *
271          * @method alert
272          * @param {String} t Title for the new alert dialog.
273          * @param {function} cb Callback function to be executed after the user has selected ok.
274          * @param {Object} s Optional scope to execute the callback in.
275          */
276         alert : function(tx, cb, s) {
277                 this.editor.windowManager.alert(tx, cb, s, window);
278         },
279
280         /**
281          * Closes the current window.
282          *
283          * @method close
284          */
285         close : function() {
286                 var t = this;
287
288                 // To avoid domain relaxing issue in Opera
289                 function close() {
290                         t.editor.windowManager.close(window);
291                         tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup
292                 };
293
294                 if (tinymce.isOpera)
295                         t.getWin().setTimeout(close, 0);
296                 else
297                         close();
298         },
299
300         // Internal functions   
301
302         _restoreSelection : function() {
303                 var e = window.event.srcElement;
304
305                 if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button'))
306                         tinyMCEPopup.restoreSelection();
307         },
308
309 /*      _restoreSelection : function() {
310                 var e = window.event.srcElement;
311
312                 // If user focus a non text input or textarea
313                 if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
314                         tinyMCEPopup.restoreSelection();
315         },*/
316
317         _onDOMLoaded : function() {
318                 var t = tinyMCEPopup, ti = document.title, bm, h, nv;
319
320                 if (t.domLoaded)
321                         return;
322
323                 t.domLoaded = 1;
324
325                 // Translate page
326                 if (t.features.translate_i18n !== false) {
327                         h = document.body.innerHTML;
328
329                         // Replace a=x with a="x" in IE
330                         if (tinymce.isIE)
331                                 h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"')
332
333                         document.dir = t.editor.getParam('directionality','');
334
335                         if ((nv = t.editor.translate(h)) && nv != h)
336                                 document.body.innerHTML = nv;
337
338                         if ((nv = t.editor.translate(ti)) && nv != ti)
339                                 document.title = ti = nv;
340                 }
341
342                 if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow)
343                         t.dom.addClass(document.body, 'forceColors');
344
345                 document.body.style.display = '';
346
347                 // Restore selection in IE when focus is placed on a non textarea or input element of the type text
348                 if (tinymce.isIE) {
349                         document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
350
351                         // Add base target element for it since it would fail with modal dialogs
352                         t.dom.add(t.dom.select('head')[0], 'base', {target : '_self'});
353                 }
354
355                 t.restoreSelection();
356                 t.resizeToInnerSize();
357
358                 // Set inline title
359                 if (!t.isWindow)
360                         t.editor.windowManager.setTitle(window, ti);
361                 else
362                         window.focus();
363
364                 if (!tinymce.isIE && !t.isWindow) {
365                         tinymce.dom.Event._add(document, 'focus', function() {
366                                 t.editor.windowManager.focus(t.id);
367                         });
368                 }
369
370                 // Patch for accessibility
371                 tinymce.each(t.dom.select('select'), function(e) {
372                         e.onkeydown = tinyMCEPopup._accessHandler;
373                 });
374
375                 // Call onInit
376                 // Init must be called before focus so the selection won't get lost by the focus call
377                 tinymce.each(t.listeners, function(o) {
378                         o.func.call(o.scope, t.editor);
379                 });
380
381                 // Move focus to window
382                 if (t.getWindowArg('mce_auto_focus', true)) {
383                         window.focus();
384
385                         // Focus element with mceFocus class
386                         tinymce.each(document.forms, function(f) {
387                                 tinymce.each(f.elements, function(e) {
388                                         if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) {
389                                                 e.focus();
390                                                 return false; // Break loop
391                                         }
392                                 });
393                         });
394                 }
395
396                 document.onkeyup = tinyMCEPopup._closeWinKeyHandler;
397         },
398
399         _accessHandler : function(e) {
400                 e = e || window.event;
401
402                 if (e.keyCode == 13 || e.keyCode == 32) {
403                         e = e.target || e.srcElement;
404
405                         if (e.onchange)
406                                 e.onchange();
407
408                         return tinymce.dom.Event.cancel(e);
409                 }
410         },
411
412         _closeWinKeyHandler : function(e) {
413                 e = e || window.event;
414
415                 if (e.keyCode == 27)
416                         tinyMCEPopup.close();
417         },
418
419         _wait : function() {
420                 // Use IE method
421                 if (document.attachEvent) {
422                         document.attachEvent("onreadystatechange", function() {
423                                 if (document.readyState === "complete") {
424                                         document.detachEvent("onreadystatechange", arguments.callee);
425                                         tinyMCEPopup._onDOMLoaded();
426                                 }
427                         });
428
429                         if (document.documentElement.doScroll && window == window.top) {
430                                 (function() {
431                                         if (tinyMCEPopup.domLoaded)
432                                                 return;
433
434                                         try {
435                                                 // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author.
436                                                 // http://javascript.nwbox.com/IEContentLoaded/
437                                                 document.documentElement.doScroll("left");
438                                         } catch (ex) {
439                                                 setTimeout(arguments.callee, 0);
440                                                 return;
441                                         }
442
443                                         tinyMCEPopup._onDOMLoaded();
444                                 })();
445                         }
446
447                         document.attachEvent('onload', tinyMCEPopup._onDOMLoaded);
448                 } else if (document.addEventListener) {
449                         window.addEventListener('DOMContentLoaded', tinyMCEPopup._onDOMLoaded, false);
450                         window.addEventListener('load', tinyMCEPopup._onDOMLoaded, false);
451                 }
452         }
453 };
454
455 tinyMCEPopup.init();
456 tinyMCEPopup._wait(); // Wait for DOM Content Loaded