~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/js/tinymce/tiny_mce_popup.js

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

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