Update wmts-hidpi, add nicer-api-docs
This commit is contained in:
@@ -0,0 +1,334 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview An abstract superclass for TrogEdit dialog plugins. Each
|
||||
* Trogedit dialog has its own plugin.
|
||||
*
|
||||
* @author nicksantos@google.com (Nick Santos)
|
||||
* @author marcosalmeida@google.com (Marcos Almeida)
|
||||
*/
|
||||
|
||||
goog.provide('goog.editor.plugins.AbstractDialogPlugin');
|
||||
goog.provide('goog.editor.plugins.AbstractDialogPlugin.EventType');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.Range');
|
||||
goog.require('goog.editor.Field.EventType');
|
||||
goog.require('goog.editor.Plugin');
|
||||
goog.require('goog.editor.range');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.ui.editor.AbstractDialog.EventType');
|
||||
|
||||
|
||||
// *** Public interface ***************************************************** //
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An abstract superclass for a Trogedit plugin that creates exactly one
|
||||
* dialog. By default dialogs are not reused -- each time execCommand is called,
|
||||
* a new instance of the dialog object is created (and the old one disposed of).
|
||||
* To enable reusing of the dialog object, subclasses should call
|
||||
* setReuseDialog() after calling the superclass constructor.
|
||||
* @param {string} command The command that this plugin handles.
|
||||
* @constructor
|
||||
* @extends {goog.editor.Plugin}
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin = function(command) {
|
||||
goog.editor.Plugin.call(this);
|
||||
this.command_ = command;
|
||||
};
|
||||
goog.inherits(goog.editor.plugins.AbstractDialogPlugin, goog.editor.Plugin);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.isSupportedCommand =
|
||||
function(command) {
|
||||
return command == this.command_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles execCommand. Dialog plugins don't make any changes when they open a
|
||||
* dialog, just when the dialog closes (because only modal dialogs are
|
||||
* supported). Hence this method does not dispatch the change events that the
|
||||
* superclass method does.
|
||||
* @param {string} command The command to execute.
|
||||
* @param {...*} var_args Any additional parameters needed to
|
||||
* execute the command.
|
||||
* @return {*} The result of the execCommand, if any.
|
||||
* @override
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.execCommand = function(
|
||||
command, var_args) {
|
||||
return this.execCommandInternal.apply(this, arguments);
|
||||
};
|
||||
|
||||
|
||||
// *** Events *************************************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* Event type constants for events the dialog plugins fire.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.EventType = {
|
||||
// This event is fired when a dialog has been opened.
|
||||
OPENED: 'dialogOpened',
|
||||
// This event is fired when a dialog has been closed.
|
||||
CLOSED: 'dialogClosed'
|
||||
};
|
||||
|
||||
|
||||
// *** Protected interface ************************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of this plugin's dialog. Must be overridden by
|
||||
* subclasses.
|
||||
* @param {!goog.dom.DomHelper} dialogDomHelper The dom helper to be used to
|
||||
* create the dialog.
|
||||
* @param {*=} opt_arg The dialog specific argument. Concrete subclasses should
|
||||
* declare a specific type.
|
||||
* @return {goog.ui.editor.AbstractDialog} The newly created dialog.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.createDialog =
|
||||
goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current dialog that was created and opened by this plugin.
|
||||
* @return {goog.ui.editor.AbstractDialog} The current dialog that was created
|
||||
* and opened by this plugin.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.getDialog = function() {
|
||||
return this.dialog_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether this plugin should reuse the same instance of the dialog each
|
||||
* time execCommand is called or create a new one. This is intended for use by
|
||||
* subclasses only, hence protected.
|
||||
* @param {boolean} reuse Whether to reuse the dialog.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.setReuseDialog =
|
||||
function(reuse) {
|
||||
this.reuseDialog_ = reuse;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles execCommand by opening the dialog. Dispatches
|
||||
* {@link goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED} after the
|
||||
* dialog is shown.
|
||||
* @param {string} command The command to execute.
|
||||
* @param {*=} opt_arg The dialog specific argument. Should be the same as
|
||||
* {@link createDialog}.
|
||||
* @return {*} Always returns true, indicating the dialog was shown.
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.execCommandInternal =
|
||||
function(command, opt_arg) {
|
||||
// If this plugin should not reuse dialog instances, first dispose of the
|
||||
// previous dialog.
|
||||
if (!this.reuseDialog_) {
|
||||
this.disposeDialog_();
|
||||
}
|
||||
// If there is no dialog yet (or we aren't reusing the previous one), create
|
||||
// one.
|
||||
if (!this.dialog_) {
|
||||
this.dialog_ = this.createDialog(
|
||||
// TODO(user): Add Field.getAppDomHelper. (Note dom helper will
|
||||
// need to be updated if setAppWindow is called by clients.)
|
||||
goog.dom.getDomHelper(this.getFieldObject().getAppWindow()),
|
||||
opt_arg);
|
||||
}
|
||||
|
||||
// Since we're opening a dialog, we need to clear the selection because the
|
||||
// focus will be going to the dialog, and if we leave an selection in the
|
||||
// editor while another selection is active in the dialog as the user is
|
||||
// typing, some browsers will screw up the original selection. But first we
|
||||
// save it so we can restore it when the dialog closes.
|
||||
// getRange may return null if there is no selection in the field.
|
||||
var tempRange = this.getFieldObject().getRange();
|
||||
// saveUsingDom() did not work as well as saveUsingNormalizedCarets(),
|
||||
// not sure why.
|
||||
this.savedRange_ = tempRange && goog.editor.range.saveUsingNormalizedCarets(
|
||||
tempRange);
|
||||
goog.dom.Range.clearSelection(
|
||||
this.getFieldObject().getEditableDomHelper().getWindow());
|
||||
|
||||
// Listen for the dialog closing so we can clean up.
|
||||
goog.events.listenOnce(this.dialog_,
|
||||
goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE,
|
||||
this.handleAfterHide,
|
||||
false,
|
||||
this);
|
||||
|
||||
this.getFieldObject().setModalMode(true);
|
||||
this.dialog_.show();
|
||||
this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED);
|
||||
|
||||
// Since the selection has left the document, dispatch a selection
|
||||
// change event.
|
||||
this.getFieldObject().dispatchSelectionChangeEvent();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cleans up after the dialog has closed, including restoring the selection to
|
||||
* what it was before the dialog was opened. If a subclass modifies the editable
|
||||
* field's content such that the original selection is no longer valid (usually
|
||||
* the case when the user clicks OK, and sometimes also on Cancel), it is that
|
||||
* subclass' responsibility to place the selection in the desired place during
|
||||
* the OK or Cancel (or other) handler. In that case, this method will leave the
|
||||
* selection in place.
|
||||
* @param {goog.events.Event} e The AFTER_HIDE event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.handleAfterHide = function(
|
||||
e) {
|
||||
this.getFieldObject().setModalMode(false);
|
||||
this.restoreOriginalSelection();
|
||||
|
||||
if (!this.reuseDialog_) {
|
||||
this.disposeDialog_();
|
||||
}
|
||||
|
||||
this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED);
|
||||
|
||||
// Since the selection has returned to the document, dispatch a selection
|
||||
// change event.
|
||||
this.getFieldObject().dispatchSelectionChangeEvent();
|
||||
|
||||
// When the dialog closes due to pressing enter or escape, that happens on the
|
||||
// keydown event. But the browser will still fire a keyup event after that,
|
||||
// which is caught by the editable field and causes it to try to fire a
|
||||
// selection change event. To avoid that, we "debounce" the selection change
|
||||
// event, meaning the editable field will not fire that event if the keyup
|
||||
// that caused it immediately after this dialog was hidden ("immediately"
|
||||
// means a small number of milliseconds defined by the editable field).
|
||||
this.getFieldObject().debounceEvent(
|
||||
goog.editor.Field.EventType.SELECTIONCHANGE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Restores the selection in the editable field to what it was before the dialog
|
||||
* was opened. This is not guaranteed to work if the contents of the field
|
||||
* have changed.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.restoreOriginalSelection =
|
||||
function() {
|
||||
this.getFieldObject().restoreSavedRange(this.savedRange_);
|
||||
this.savedRange_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cleans up the structure used to save the original selection before the dialog
|
||||
* was opened. Should be used by subclasses that don't restore the original
|
||||
* selection via restoreOriginalSelection.
|
||||
* @protected
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.disposeOriginalSelection =
|
||||
function() {
|
||||
if (this.savedRange_) {
|
||||
this.savedRange_.dispose();
|
||||
this.savedRange_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.disposeInternal =
|
||||
function() {
|
||||
this.disposeDialog_();
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
// *** Private implementation *********************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* The command that this plugin handles.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.command_;
|
||||
|
||||
|
||||
/**
|
||||
* The current dialog that was created and opened by this plugin.
|
||||
* @type {goog.ui.editor.AbstractDialog}
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.dialog_;
|
||||
|
||||
|
||||
/**
|
||||
* Whether this plugin should reuse the same instance of the dialog each time
|
||||
* execCommand is called or create a new one.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.reuseDialog_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Mutex to prevent recursive calls to disposeDialog_.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.isDisposingDialog_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* SavedRange representing the selection before the dialog was opened.
|
||||
* @type {goog.dom.SavedRange}
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.savedRange_;
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the dialog if needed. It is this abstract class' responsibility
|
||||
* to dispose of the dialog. The "if needed" refers to the fact this method
|
||||
* might be called twice (nested calls, not sequential) in the dispose flow, so
|
||||
* if the dialog was already disposed once it should not be disposed again.
|
||||
* @private
|
||||
*/
|
||||
goog.editor.plugins.AbstractDialogPlugin.prototype.disposeDialog_ = function() {
|
||||
// Wrap disposing the dialog in a mutex. Otherwise disposing it would cause it
|
||||
// to get hidden (if it is still open) and fire AFTER_HIDE, which in
|
||||
// turn would cause the dialog to be disposed again (closure only flags an
|
||||
// object as disposed after the dispose call chain completes, so it doesn't
|
||||
// prevent recursive dispose calls).
|
||||
if (this.dialog_ && !this.isDisposingDialog_) {
|
||||
this.isDisposingDialog_ = true;
|
||||
this.dialog_.dispose();
|
||||
this.dialog_ = null;
|
||||
this.isDisposingDialog_ = false;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user