[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/tinymce/ -> tiny_mce_popup.js (source)

   1  /**
   2   * tinymce_mce_popup.js
   3   *
   4   * Released under LGPL License.
   5   * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
   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 retrieve.
 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 retrieve.
 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      var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback;
 253      if (colorPickerCallback) {
 254        colorPickerCallback.call(
 255          this.editor,
 256          function (value) {
 257            el.value = value;
 258            try {
 259              el.onchange();
 260            } catch (ex) {
 261              // Try fire event, ignore errors
 262            }
 263          },
 264          el.value
 265        );
 266      }
 267    },
 268  
 269    /**
 270     * Opens a filebrowser/imagebrowser this will set the output value from
 271     * the browser as a value on the specified element.
 272     *
 273     * @method openBrowser
 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.
 276     * @param {string} option Option name to get the file_broswer_callback function name from.
 277     */
 278    openBrowser: function (element_id, type) {
 279      tinyMCEPopup.restoreSelection();
 280      this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
 281    },
 282  
 283    /**
 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.
 286     *
 287     * @method confirm
 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.
 290     * @param {Object} s Optional scope to execute the callback in.
 291     */
 292    confirm: function (t, cb, s) {
 293      this.editor.windowManager.confirm(t, cb, s, window);
 294    },
 295  
 296    /**
 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.
 299     *
 300     * @method alert
 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.
 303     * @param {Object} s Optional scope to execute the callback in.
 304     */
 305    alert: function (tx, cb, s) {
 306      this.editor.windowManager.alert(tx, cb, s, window);
 307    },
 308  
 309    /**
 310     * Closes the current window.
 311     *
 312     * @method close
 313     */
 314    close: function () {
 315      var t = this;
 316  
 317      // To avoid domain relaxing issue in Opera
 318      function close() {
 319        t.editor.windowManager.close(window);
 320        tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup
 321      }
 322  
 323      if (tinymce.isOpera) {
 324        t.getWin().setTimeout(close, 0);
 325      } else {
 326        close();
 327      }
 328    },
 329  
 330    // Internal functions
 331  
 332    _restoreSelection: function () {
 333      var e = window.event.srcElement;
 334  
 335      if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) {
 336        tinyMCEPopup.restoreSelection();
 337      }
 338    },
 339  
 340    /* _restoreSelection : function() {
 341        var e = window.event.srcElement;
 342  
 343        // If user focus a non text input or textarea
 344        if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
 345          tinyMCEPopup.restoreSelection();
 346      },*/
 347  
 348    _onDOMLoaded: function () {
 349      var t = tinyMCEPopup, ti = document.title, h, nv;
 350  
 351      // Translate page
 352      if (t.features.translate_i18n !== false) {
 353        var map = {
 354          "update": "Ok",
 355          "insert": "Ok",
 356          "cancel": "Cancel",
 357          "not_set": "--",
 358          "class_name": "Class name",
 359          "browse": "Browse"
 360        };
 361  
 362        var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en';
 363        for (var key in map) {
 364          tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]);
 365        }
 366  
 367        h = document.body.innerHTML;
 368  
 369        // Replace a=x with a="x" in IE
 370        if (tinymce.isIE) {
 371          h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"');
 372        }
 373  
 374        document.dir = t.editor.getParam('directionality', '');
 375  
 376        if ((nv = t.editor.translate(h)) && nv != h) {
 377          document.body.innerHTML = nv;
 378        }
 379  
 380        if ((nv = t.editor.translate(ti)) && nv != ti) {
 381          document.title = ti = nv;
 382        }
 383      }
 384  
 385      if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) {
 386        t.dom.addClass(document.body, 'forceColors');
 387      }
 388  
 389      document.body.style.display = '';
 390  
 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) {
 393        if (tinymce.Env.ie < 11) {
 394          document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
 395  
 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' });
 398        } else {
 399          document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false);
 400        }
 401      }
 402  
 403      t.restoreSelection();
 404      t.resizeToInnerSize();
 405  
 406      // Set inline title
 407      if (!t.isWindow) {
 408        t.editor.windowManager.setTitle(window, ti);
 409      } else {
 410        window.focus();
 411      }
 412  
 413      if (!tinymce.isIE && !t.isWindow) {
 414        t.dom.bind(document, 'focus', function () {
 415          t.editor.windowManager.focus(t.id);
 416        });
 417      }
 418  
 419      // Patch for accessibility
 420      tinymce.each(t.dom.select('select'), function (e) {
 421        e.onkeydown = tinyMCEPopup._accessHandler;
 422      });
 423  
 424      // Call onInit
 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) {
 427        o.func.call(o.scope, t.editor);
 428      });
 429  
 430      // Move focus to window
 431      if (t.getWindowArg('mce_auto_focus', true)) {
 432        window.focus();
 433  
 434        // Focus element with mceFocus class
 435        tinymce.each(document.forms, function (f) {
 436          tinymce.each(f.elements, function (e) {
 437            if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) {
 438              e.focus();
 439              return false; // Break loop
 440            }
 441          });
 442        });
 443      }
 444  
 445      document.onkeyup = tinyMCEPopup._closeWinKeyHandler;
 446  
 447      if ('textContent' in document) {
 448        t.uiWindow.getEl('head').firstChild.textContent = document.title;
 449      } else {
 450        t.uiWindow.getEl('head').firstChild.innerText = document.title;
 451      }
 452    },
 453  
 454    _accessHandler: function (e) {
 455      e = e || window.event;
 456  
 457      if (e.keyCode == 13 || e.keyCode == 32) {
 458        var elm = e.target || e.srcElement;
 459  
 460        if (elm.onchange) {
 461          elm.onchange();
 462        }
 463  
 464        return tinymce.dom.Event.cancel(e);
 465      }
 466    },
 467  
 468    _closeWinKeyHandler: function (e) {
 469      e = e || window.event;
 470  
 471      if (e.keyCode == 27) {
 472        tinyMCEPopup.close();
 473      }
 474    },
 475  
 476    _eventProxy: function (id) {
 477      return function (evt) {
 478        tinyMCEPopup.dom.events.callNativeHandler(id, evt);
 479      };
 480    }
 481  };
 482  
 483  tinyMCEPopup.init();
 484  
 485  tinymce.util.Dispatcher = function (scope) {
 486    this.scope = scope || this;
 487    this.listeners = [];
 488  
 489    this.add = function (callback, scope) {
 490      this.listeners.push({ cb: callback, scope: scope || this.scope });
 491  
 492      return callback;
 493    };
 494  
 495    this.addToTop = function (callback, scope) {
 496      var self = this, listener = { cb: callback, scope: scope || self.scope };
 497  
 498      // Create new listeners if addToTop is executed in a dispatch loop
 499      if (self.inDispatch) {
 500        self.listeners = [listener].concat(self.listeners);
 501      } else {
 502        self.listeners.unshift(listener);
 503      }
 504  
 505      return callback;
 506    };
 507  
 508    this.remove = function (callback) {
 509      var listeners = this.listeners, output = null;
 510  
 511      tinymce.each(listeners, function (listener, i) {
 512        if (callback == listener.cb) {
 513          output = listener;
 514          listeners.splice(i, 1);
 515          return false;
 516        }
 517      });
 518  
 519      return output;
 520    };
 521  
 522    this.dispatch = function () {
 523      var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
 524  
 525      self.inDispatch = true;
 526  
 527      // Needs to be a real loop since the listener count might change while looping
 528      // And this is also more efficient
 529      for (i = 0; i < listeners.length; i++) {
 530        listener = listeners[i];
 531        returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
 532  
 533        if (returnValue === false) {
 534          break;
 535        }
 536      }
 537  
 538      self.inDispatch = false;
 539  
 540      return returnValue;
 541    };
 542  };


Generated : Fri Nov 15 08:20:01 2024 Cross-referenced by PHPXref