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