Adding float-no-zero branch hosted build
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// Copyright 2007 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 Announcer that allows messages to be spoken by assistive
|
||||
* technologies.
|
||||
*/
|
||||
|
||||
goog.provide('goog.a11y.aria.Announcer');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.a11y.aria');
|
||||
goog.require('goog.a11y.aria.LivePriority');
|
||||
goog.require('goog.a11y.aria.State');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class that allows messages to be spoken by assistive technologies that the
|
||||
* user may have active.
|
||||
*
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper DOM helper.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
goog.a11y.aria.Announcer = function(opt_domHelper) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {goog.dom.DomHelper}
|
||||
* @private
|
||||
*/
|
||||
this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
|
||||
|
||||
/**
|
||||
* Map of priority to live region elements to use for communicating updates.
|
||||
* Elements are created on demand.
|
||||
* @type {Object.<goog.a11y.aria.LivePriority, Element>}
|
||||
* @private
|
||||
*/
|
||||
this.liveRegions_ = {};
|
||||
};
|
||||
goog.inherits(goog.a11y.aria.Announcer, goog.Disposable);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.a11y.aria.Announcer.prototype.disposeInternal = function() {
|
||||
goog.object.forEach(
|
||||
this.liveRegions_, this.domHelper_.removeNode, this.domHelper_);
|
||||
this.liveRegions_ = null;
|
||||
this.domHelper_ = null;
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Announce a message to be read by any assistive technologies the user may
|
||||
* have active.
|
||||
* @param {string} message The message to announce to screen readers.
|
||||
* @param {goog.a11y.aria.LivePriority=} opt_priority The priority of the
|
||||
* message. Defaults to POLITE.
|
||||
*/
|
||||
goog.a11y.aria.Announcer.prototype.say = function(message, opt_priority) {
|
||||
goog.dom.setTextContent(this.getLiveRegion_(
|
||||
opt_priority || goog.a11y.aria.LivePriority.POLITE), message);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an aria-live region that can be used to communicate announcements.
|
||||
* @param {!goog.a11y.aria.LivePriority} priority The required priority.
|
||||
* @return {Element} A live region of the requested priority.
|
||||
* @private
|
||||
*/
|
||||
goog.a11y.aria.Announcer.prototype.getLiveRegion_ = function(priority) {
|
||||
if (this.liveRegions_[priority]) {
|
||||
return this.liveRegions_[priority];
|
||||
}
|
||||
var liveRegion;
|
||||
liveRegion = this.domHelper_.createElement('div');
|
||||
// Note that IE has a habit of declaring things that aren't display:none as
|
||||
// invisible to third-party tools like JAWs, so we can't just use height:0.
|
||||
liveRegion.style.position = 'absolute';
|
||||
liveRegion.style.top = '-1000px';
|
||||
liveRegion.style.height = '1px';
|
||||
liveRegion.style.overflow = 'hidden';
|
||||
goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.LIVE,
|
||||
priority);
|
||||
goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.ATOMIC,
|
||||
'true');
|
||||
this.domHelper_.getDocument().body.appendChild(liveRegion);
|
||||
this.liveRegions_[priority] = liveRegion;
|
||||
return liveRegion;
|
||||
};
|
||||
362
float-no-zero/closure-library/closure/goog/a11y/aria/aria.js
Normal file
362
float-no-zero/closure-library/closure/goog/a11y/aria/aria.js
Normal file
@@ -0,0 +1,362 @@
|
||||
// Copyright 2007 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 Utilities for adding, removing and setting ARIA roles and
|
||||
* states as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/
|
||||
* All modern browsers have some form of ARIA support, so no browser checks are
|
||||
* performed when adding ARIA to components.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.a11y.aria');
|
||||
|
||||
goog.require('goog.a11y.aria.Role');
|
||||
goog.require('goog.a11y.aria.State');
|
||||
goog.require('goog.a11y.aria.datatables');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
/**
|
||||
* ARIA states/properties prefix.
|
||||
* @private
|
||||
*/
|
||||
goog.a11y.aria.ARIA_PREFIX_ = 'aria-';
|
||||
|
||||
|
||||
/**
|
||||
* ARIA role attribute.
|
||||
* @private
|
||||
*/
|
||||
goog.a11y.aria.ROLE_ATTRIBUTE_ = 'role';
|
||||
|
||||
|
||||
/**
|
||||
* A list of tag names for which we don't need to set ARIA role and states
|
||||
* because they have well supported semantics for screen readers or because
|
||||
* they don't contain content to be made accessible.
|
||||
* @private
|
||||
*/
|
||||
goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_ = [
|
||||
goog.dom.TagName.A,
|
||||
goog.dom.TagName.AREA,
|
||||
goog.dom.TagName.BUTTON,
|
||||
goog.dom.TagName.HEAD,
|
||||
goog.dom.TagName.INPUT,
|
||||
goog.dom.TagName.LINK,
|
||||
goog.dom.TagName.MENU,
|
||||
goog.dom.TagName.META,
|
||||
goog.dom.TagName.OPTGROUP,
|
||||
goog.dom.TagName.OPTION,
|
||||
goog.dom.TagName.PROGRESS,
|
||||
goog.dom.TagName.STYLE,
|
||||
goog.dom.TagName.SELECT,
|
||||
goog.dom.TagName.SOURCE,
|
||||
goog.dom.TagName.TEXTAREA,
|
||||
goog.dom.TagName.TITLE,
|
||||
goog.dom.TagName.TRACK
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Sets the role of an element. If the roleName is
|
||||
* empty string or null, the role for the element is removed.
|
||||
* We encourage clients to call the goog.a11y.aria.removeRole
|
||||
* method instead of setting null and empty string values.
|
||||
* Special handling for this case is added to ensure
|
||||
* backword compatibility with existing code.
|
||||
*
|
||||
* @param {!Element} element DOM node to set role of.
|
||||
* @param {!goog.a11y.aria.Role|string} roleName role name(s).
|
||||
*/
|
||||
goog.a11y.aria.setRole = function(element, roleName) {
|
||||
if (!roleName) {
|
||||
// Setting the ARIA role to empty string is not allowed
|
||||
// by the ARIA standard.
|
||||
goog.a11y.aria.removeRole(element);
|
||||
} else {
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
goog.asserts.assert(goog.object.containsValue(
|
||||
goog.a11y.aria.Role, roleName), 'No such ARIA role ' + roleName);
|
||||
}
|
||||
element.setAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_, roleName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets role of an element.
|
||||
* @param {!Element} element DOM element to get role of.
|
||||
* @return {?goog.a11y.aria.Role} ARIA Role name.
|
||||
*/
|
||||
goog.a11y.aria.getRole = function(element) {
|
||||
var role = element.getAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_);
|
||||
return /** @type {goog.a11y.aria.Role} */ (role) || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes role of an element.
|
||||
* @param {!Element} element DOM element to remove the role from.
|
||||
*/
|
||||
goog.a11y.aria.removeRole = function(element) {
|
||||
element.removeAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the state or property of an element.
|
||||
* @param {!Element} element DOM node where we set state.
|
||||
* @param {!(goog.a11y.aria.State|string)} stateName State attribute being set.
|
||||
* Automatically adds prefix 'aria-' to the state name if the attribute is
|
||||
* not an extra attribute.
|
||||
* @param {string|boolean|number|!goog.array.ArrayLike.<string>} value Value
|
||||
* for the state attribute.
|
||||
*/
|
||||
goog.a11y.aria.setState = function(element, stateName, value) {
|
||||
if (goog.isArrayLike(value)) {
|
||||
var array = /** @type {!goog.array.ArrayLike.<string>} */ (value);
|
||||
value = array.join(' ');
|
||||
}
|
||||
var attrStateName = goog.a11y.aria.getAriaAttributeName_(stateName);
|
||||
if (value === '' || value == undefined) {
|
||||
var defaultValueMap = goog.a11y.aria.datatables.getDefaultValuesMap();
|
||||
// Work around for browsers that don't properly support ARIA.
|
||||
// According to the ARIA W3C standard, user agents should allow
|
||||
// setting empty value which results in setting the default value
|
||||
// for the ARIA state if such exists. The exact text from the ARIA W3C
|
||||
// standard (http://www.w3.org/TR/wai-aria/states_and_properties):
|
||||
// "When a value is indicated as the default, the user agent
|
||||
// MUST follow the behavior prescribed by this value when the state or
|
||||
// property is empty or undefined."
|
||||
// The defaultValueMap contains the default values for the ARIA states
|
||||
// and has as a key the goog.a11y.aria.State constant for the state.
|
||||
if (stateName in defaultValueMap) {
|
||||
element.setAttribute(attrStateName, defaultValueMap[stateName]);
|
||||
} else {
|
||||
element.removeAttribute(attrStateName);
|
||||
}
|
||||
} else {
|
||||
element.setAttribute(attrStateName, value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the state or property for the element.
|
||||
* @param {!Element} element DOM node where we set state.
|
||||
* @param {!goog.a11y.aria.State} stateName State name.
|
||||
*/
|
||||
goog.a11y.aria.removeState = function(element, stateName) {
|
||||
element.removeAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets value of specified state or property.
|
||||
* @param {!Element} element DOM node to get state from.
|
||||
* @param {!goog.a11y.aria.State|string} stateName State name.
|
||||
* @return {string} Value of the state attribute.
|
||||
*/
|
||||
goog.a11y.aria.getState = function(element, stateName) {
|
||||
// TODO(user): return properly typed value result --
|
||||
// boolean, number, string, null. We should be able to chain
|
||||
// getState(...) and setState(...) methods.
|
||||
|
||||
var attr =
|
||||
/** @type {string|number|boolean} */ (element.getAttribute(
|
||||
goog.a11y.aria.getAriaAttributeName_(stateName)));
|
||||
var isNullOrUndefined = attr == null || attr == undefined;
|
||||
return isNullOrUndefined ? '' : String(attr);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the activedescendant element for the input element by
|
||||
* using the activedescendant ARIA property of the given element.
|
||||
* @param {!Element} element DOM node to get activedescendant
|
||||
* element for.
|
||||
* @return {?Element} DOM node of the activedescendant, if found.
|
||||
*/
|
||||
goog.a11y.aria.getActiveDescendant = function(element) {
|
||||
var id = goog.a11y.aria.getState(
|
||||
element, goog.a11y.aria.State.ACTIVEDESCENDANT);
|
||||
return goog.dom.getOwnerDocument(element).getElementById(id);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the activedescendant ARIA property value for an element.
|
||||
* If the activeElement is not null, it should have an id set.
|
||||
* @param {!Element} element DOM node to set activedescendant ARIA property to.
|
||||
* @param {?Element} activeElement DOM node being set as activedescendant.
|
||||
*/
|
||||
goog.a11y.aria.setActiveDescendant = function(element, activeElement) {
|
||||
var id = '';
|
||||
if (activeElement) {
|
||||
id = activeElement.id;
|
||||
goog.asserts.assert(id, 'The active element should have an id.');
|
||||
}
|
||||
|
||||
goog.a11y.aria.setState(element, goog.a11y.aria.State.ACTIVEDESCENDANT, id);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the label of the given element.
|
||||
* @param {!Element} element DOM node to get label from.
|
||||
* @return {string} label The label.
|
||||
*/
|
||||
goog.a11y.aria.getLabel = function(element) {
|
||||
return goog.a11y.aria.getState(element, goog.a11y.aria.State.LABEL);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the label of the given element.
|
||||
* @param {!Element} element DOM node to set label to.
|
||||
* @param {string} label The label to set.
|
||||
*/
|
||||
goog.a11y.aria.setLabel = function(element, label) {
|
||||
goog.a11y.aria.setState(element, goog.a11y.aria.State.LABEL, label);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that the element has a role set if it's not an HTML element whose
|
||||
* semantics is well supported by most screen readers.
|
||||
* Only to be used internally by the ARIA library in goog.a11y.aria.*.
|
||||
* @param {!Element} element The element to assert an ARIA role set.
|
||||
* @param {!goog.array.ArrayLike.<string>} allowedRoles The child roles of
|
||||
* the roles.
|
||||
*/
|
||||
goog.a11y.aria.assertRoleIsSetInternalUtil = function(element, allowedRoles) {
|
||||
if (goog.array.contains(goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_,
|
||||
element.tagName)) {
|
||||
return;
|
||||
}
|
||||
var elementRole = /** @type {string}*/ (goog.a11y.aria.getRole(element));
|
||||
goog.asserts.assert(elementRole != null,
|
||||
'The element ARIA role cannot be null.');
|
||||
|
||||
goog.asserts.assert(goog.array.contains(allowedRoles, elementRole),
|
||||
'Non existing or incorrect role set for element.' +
|
||||
'The role set is "' + elementRole +
|
||||
'". The role should be any of "' + allowedRoles +
|
||||
'". Check the ARIA specification for more details ' +
|
||||
'http://www.w3.org/TR/wai-aria/roles.');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the boolean value of an ARIA state/property.
|
||||
* Only to be used internally by the ARIA library in goog.a11y.aria.*.
|
||||
* @param {!Element} element The element to get the ARIA state for.
|
||||
* @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
|
||||
* @return {?boolean} Boolean value for the ARIA state value or null if
|
||||
* the state value is not 'true' or 'false'.
|
||||
*/
|
||||
goog.a11y.aria.getBooleanStateInternalUtil = function(element, stateName) {
|
||||
var stringValue = goog.a11y.aria.getState(element, stateName);
|
||||
if (stringValue == 'true') {
|
||||
return true;
|
||||
}
|
||||
if (stringValue == 'false') {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number value of an ARIA state/property.
|
||||
* Only to be used internally by the ARIA library in goog.a11y.aria.*.
|
||||
* @param {!Element} element The element to get the ARIA state for.
|
||||
* @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
|
||||
* @return {?number} Number value for the ARIA state value or null if
|
||||
* the state value is not a number.
|
||||
*/
|
||||
goog.a11y.aria.getNumberStateInternalUtil = function(element, stateName) {
|
||||
var stringValue = goog.a11y.aria.getState(element, stateName);
|
||||
if (goog.string.isNumeric(stringValue)) {
|
||||
return goog.string.toNumber(stringValue);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets array of strings value of the specified state or
|
||||
* property for the element.
|
||||
* Only to be used internally by the ARIA library in goog.a11y.aria.*.
|
||||
* @param {!Element} element DOM node to get state from.
|
||||
* @param {!goog.a11y.aria.State} stateName State name.
|
||||
* @return {!goog.array.ArrayLike.<string>} string Array
|
||||
* value of the state attribute.
|
||||
*/
|
||||
goog.a11y.aria.getStringArrayStateInternalUtil = function(element, stateName) {
|
||||
var attrValue = element.getAttribute(
|
||||
goog.a11y.aria.getAriaAttributeName_(stateName));
|
||||
return goog.a11y.aria.splitStringOnWhitespace_(attrValue);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the string value of an ARIA state/property.
|
||||
* Only to be used internally by the ARIA library in goog.a11y.aria.*.
|
||||
* @param {!Element} element The element to get the ARIA state for.
|
||||
* @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
|
||||
* @return {?string} String value for the ARIA state value or null if
|
||||
* the state value is empty string.
|
||||
*/
|
||||
goog.a11y.aria.getStringStateInternalUtil = function(element, stateName) {
|
||||
var stringValue = goog.a11y.aria.getState(element, stateName);
|
||||
return stringValue || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Splits the input stringValue on whitespace.
|
||||
* @param {string} stringValue The value of the string to split.
|
||||
* @return {!goog.array.ArrayLike.<string>} string Array
|
||||
* value as result of the split.
|
||||
* @private
|
||||
*/
|
||||
goog.a11y.aria.splitStringOnWhitespace_ = function(stringValue) {
|
||||
return stringValue ? stringValue.split(/\s+/) : [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds the 'aria-' prefix to ariaName.
|
||||
* @param {string} ariaName ARIA state/property name.
|
||||
* @private
|
||||
* @return {string} The ARIA attribute name with added 'aria-' prefix.
|
||||
* @throws {Error} If no such attribute exists.
|
||||
*/
|
||||
goog.a11y.aria.getAriaAttributeName_ = function(ariaName) {
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
goog.asserts.assert(ariaName, 'ARIA attribute cannot be empty.');
|
||||
goog.asserts.assert(goog.object.containsValue(
|
||||
goog.a11y.aria.State, ariaName),
|
||||
'No such ARIA attribute ' + ariaName);
|
||||
}
|
||||
return goog.a11y.aria.ARIA_PREFIX_ + ariaName;
|
||||
};
|
||||
@@ -0,0 +1,389 @@
|
||||
// Copyright 2013 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 The file contains generated enumerations for ARIA states
|
||||
* and properties as defined by W3C ARIA standard:
|
||||
* http://www.w3.org/TR/wai-aria/.
|
||||
*
|
||||
* This is auto-generated code. Do not manually edit! For more details
|
||||
* about how to edit it via the generator check go/closure-ariagen.
|
||||
*/
|
||||
|
||||
goog.provide('goog.a11y.aria.AutoCompleteValues');
|
||||
goog.provide('goog.a11y.aria.CheckedValues');
|
||||
goog.provide('goog.a11y.aria.DropEffectValues');
|
||||
goog.provide('goog.a11y.aria.ExpandedValues');
|
||||
goog.provide('goog.a11y.aria.GrabbedValues');
|
||||
goog.provide('goog.a11y.aria.InvalidValues');
|
||||
goog.provide('goog.a11y.aria.LivePriority');
|
||||
goog.provide('goog.a11y.aria.OrientationValues');
|
||||
goog.provide('goog.a11y.aria.PressedValues');
|
||||
goog.provide('goog.a11y.aria.RelevantValues');
|
||||
goog.provide('goog.a11y.aria.SelectedValues');
|
||||
goog.provide('goog.a11y.aria.SortValues');
|
||||
goog.provide('goog.a11y.aria.State');
|
||||
|
||||
|
||||
/**
|
||||
* ARIA states and properties.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.State = {
|
||||
// ARIA property for setting the currently active descendant of an element,
|
||||
// for example the selected item in a list box. Value: ID of an element.
|
||||
ACTIVEDESCENDANT: 'activedescendant',
|
||||
|
||||
// ARIA property that, if true, indicates that all of a changed region should
|
||||
// be presented, instead of only parts. Value: one of {true, false}.
|
||||
ATOMIC: 'atomic',
|
||||
|
||||
// ARIA property to specify that input completion is provided. Value:
|
||||
// one of {'inline', 'list', 'both', 'none'}.
|
||||
AUTOCOMPLETE: 'autocomplete',
|
||||
|
||||
// ARIA state to indicate that an element and its subtree are being updated.
|
||||
// Value: one of {true, false}.
|
||||
BUSY: 'busy',
|
||||
|
||||
// ARIA state for a checked item. Value: one of {'true', 'false', 'mixed',
|
||||
// undefined}.
|
||||
CHECKED: 'checked',
|
||||
|
||||
// ARIA property that identifies the element or elements whose contents or
|
||||
// presence are controlled by this element.
|
||||
// Value: space-separated IDs of other elements.
|
||||
CONTROLS: 'controls',
|
||||
|
||||
// ARIA property that identifies the element or elements that describe
|
||||
// this element. Value: space-separated IDs of other elements.
|
||||
DESCRIBEDBY: 'describedby',
|
||||
|
||||
// ARIA state for a disabled item. Value: one of {true, false}.
|
||||
DISABLED: 'disabled',
|
||||
|
||||
// ARIA property that indicates what functions can be performed when a
|
||||
// dragged object is released on the drop target. Value: one of
|
||||
// {'copy', 'move', 'link', 'execute', 'popup', 'none'}.
|
||||
DROPEFFECT: 'dropeffect',
|
||||
|
||||
// ARIA state for setting whether the element like a tree node is expanded.
|
||||
// Value: one of {true, false, undefined}.
|
||||
EXPANDED: 'expanded',
|
||||
|
||||
// ARIA property that identifies the next element (or elements) in the
|
||||
// recommended reading order of content. Value: space-separated ids of
|
||||
// elements to flow to.
|
||||
FLOWTO: 'flowto',
|
||||
|
||||
// ARIA state that indicates an element's "grabbed" state in drag-and-drop.
|
||||
// Value: one of {true, false, undefined}.
|
||||
GRABBED: 'grabbed',
|
||||
|
||||
// ARIA property indicating whether the element has a popup.
|
||||
// Value: one of {true, false}.
|
||||
HASPOPUP: 'haspopup',
|
||||
|
||||
// ARIA state indicating that the element is not visible or perceivable
|
||||
// to any user. Value: one of {true, false}.
|
||||
HIDDEN: 'hidden',
|
||||
|
||||
// ARIA state indicating that the entered value does not conform. Value:
|
||||
// one of {false, true, 'grammar', 'spelling'}
|
||||
INVALID: 'invalid',
|
||||
|
||||
// ARIA property that provides a label to override any other text, value, or
|
||||
// contents used to describe this element. Value: string.
|
||||
LABEL: 'label',
|
||||
|
||||
// ARIA property for setting the element which labels another element.
|
||||
// Value: space-separated IDs of elements.
|
||||
LABELLEDBY: 'labelledby',
|
||||
|
||||
// ARIA property for setting the level of an element in the hierarchy.
|
||||
// Value: integer.
|
||||
LEVEL: 'level',
|
||||
|
||||
// ARIA property indicating that an element will be updated, and
|
||||
// describes the types of updates the user agents, assistive technologies,
|
||||
// and user can expect from the live region. Value: one of {'off', 'polite',
|
||||
// 'assertive'}.
|
||||
LIVE: 'live',
|
||||
|
||||
// ARIA property indicating whether a text box can accept multiline input.
|
||||
// Value: one of {true, false}.
|
||||
MULTILINE: 'multiline',
|
||||
|
||||
// ARIA property indicating if the user may select more than one item.
|
||||
// Value: one of {true, false}.
|
||||
MULTISELECTABLE: 'multiselectable',
|
||||
|
||||
// ARIA property indicating if the element is horizontal or vertical.
|
||||
// Value: one of {'vertical', 'horizontal'}.
|
||||
ORIENTATION: 'orientation',
|
||||
|
||||
// ARIA property creating a visual, functional, or contextual parent/child
|
||||
// relationship when the DOM hierarchy can't be used to represent it.
|
||||
// Value: Space-separated IDs of elements.
|
||||
OWNS: 'owns',
|
||||
|
||||
// ARIA property that defines an element's number of position in a list.
|
||||
// Value: integer.
|
||||
POSINSET: 'posinset',
|
||||
|
||||
// ARIA state for a pressed item.
|
||||
// Value: one of {true, false, undefined, 'mixed'}.
|
||||
PRESSED: 'pressed',
|
||||
|
||||
// ARIA property indicating that an element is not editable.
|
||||
// Value: one of {true, false}.
|
||||
READONLY: 'readonly',
|
||||
|
||||
// ARIA property indicating that change notifications within this subtree
|
||||
// of a live region should be announced. Value: one of {'additions',
|
||||
// 'removals', 'text', 'all', 'additions text'}.
|
||||
RELEVANT: 'relevant',
|
||||
|
||||
// ARIA property indicating that user input is required on this element
|
||||
// before a form may be submitted. Value: one of {true, false}.
|
||||
REQUIRED: 'required',
|
||||
|
||||
// ARIA state for setting the currently selected item in the list.
|
||||
// Value: one of {true, false, undefined}.
|
||||
SELECTED: 'selected',
|
||||
|
||||
// ARIA property defining the number of items in a list. Value: integer.
|
||||
SETSIZE: 'setsize',
|
||||
|
||||
// ARIA property indicating if items are sorted. Value: one of {'ascending',
|
||||
// 'descending', 'none', 'other'}.
|
||||
SORT: 'sort',
|
||||
|
||||
// ARIA property for slider maximum value. Value: number.
|
||||
VALUEMAX: 'valuemax',
|
||||
|
||||
// ARIA property for slider minimum value. Value: number.
|
||||
VALUEMIN: 'valuemin',
|
||||
|
||||
// ARIA property for slider active value. Value: number.
|
||||
VALUENOW: 'valuenow',
|
||||
|
||||
// ARIA property for slider active value represented as text.
|
||||
// Value: string.
|
||||
VALUETEXT: 'valuetext'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for AutoCompleteValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.AutoCompleteValues = {
|
||||
// The system provides text after the caret as a suggestion
|
||||
// for how to complete the field.
|
||||
INLINE: 'inline',
|
||||
// A list of choices appears from which the user can choose,
|
||||
// but the edit box retains focus.
|
||||
LIST: 'list',
|
||||
// A list of choices appears and the currently selected suggestion
|
||||
// also appears inline.
|
||||
BOTH: 'both',
|
||||
// No input completion suggestions are provided.
|
||||
NONE: 'none'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for DropEffectValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.DropEffectValues = {
|
||||
// A duplicate of the source object will be dropped into the target.
|
||||
COPY: 'copy',
|
||||
// The source object will be removed from its current location
|
||||
// and dropped into the target.
|
||||
MOVE: 'move',
|
||||
// A reference or shortcut to the dragged object
|
||||
// will be created in the target object.
|
||||
LINK: 'link',
|
||||
// A function supported by the drop target is
|
||||
// executed, using the drag source as an input.
|
||||
EXECUTE: 'execute',
|
||||
// There is a popup menu or dialog that allows the user to choose
|
||||
// one of the drag operations (copy, move, link, execute) and any other
|
||||
// drag functionality, such as cancel.
|
||||
POPUP: 'popup',
|
||||
// No operation can be performed; effectively
|
||||
// cancels the drag operation if an attempt is made to drop on this object.
|
||||
NONE: 'none'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for LivePriority.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.LivePriority = {
|
||||
// Updates to the region will not be presented to the user
|
||||
// unless the assitive technology is currently focused on that region.
|
||||
OFF: 'off',
|
||||
// (Background change) Assistive technologies SHOULD announce
|
||||
// updates at the next graceful opportunity, such as at the end of
|
||||
// speaking the current sentence or when the user pauses typing.
|
||||
POLITE: 'polite',
|
||||
// This information has the highest priority and assistive
|
||||
// technologies SHOULD notify the user immediately.
|
||||
// Because an interruption may disorient users or cause them to not complete
|
||||
// their current task, authors SHOULD NOT use the assertive value unless the
|
||||
// interruption is imperative.
|
||||
ASSERTIVE: 'assertive'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for OrientationValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.OrientationValues = {
|
||||
// The element is oriented vertically.
|
||||
VERTICAL: 'vertical',
|
||||
// The element is oriented horizontally.
|
||||
HORIZONTAL: 'horizontal'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for RelevantValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.RelevantValues = {
|
||||
// Element nodes are added to the DOM within the live region.
|
||||
ADDITIONS: 'additions',
|
||||
// Text or element nodes within the live region are removed from the DOM.
|
||||
REMOVALS: 'removals',
|
||||
// Text is added to any DOM descendant nodes of the live region.
|
||||
TEXT: 'text',
|
||||
// Equivalent to the combination of all values, "additions removals text".
|
||||
ALL: 'all'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for SortValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.SortValues = {
|
||||
// Items are sorted in ascending order by this column.
|
||||
ASCENDING: 'ascending',
|
||||
// Items are sorted in descending order by this column.
|
||||
DESCENDING: 'descending',
|
||||
// There is no defined sort applied to the column.
|
||||
NONE: 'none',
|
||||
// A sort algorithm other than ascending or descending has been applied.
|
||||
OTHER: 'other'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for CheckedValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.CheckedValues = {
|
||||
// The selectable element is checked.
|
||||
TRUE: 'true',
|
||||
// The selectable element is not checked.
|
||||
FALSE: 'false',
|
||||
// Indicates a mixed mode value for a tri-state
|
||||
// checkbox or menuitemcheckbox.
|
||||
MIXED: 'mixed',
|
||||
// The element does not support being checked.
|
||||
UNDEFINED: 'undefined'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for ExpandedValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.ExpandedValues = {
|
||||
// The element, or another grouping element it controls, is expanded.
|
||||
TRUE: 'true',
|
||||
// The element, or another grouping element it controls, is collapsed.
|
||||
FALSE: 'false',
|
||||
// The element, or another grouping element
|
||||
// it controls, is neither expandable nor collapsible; all its
|
||||
// child elements are shown or there are no child elements.
|
||||
UNDEFINED: 'undefined'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for GrabbedValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.GrabbedValues = {
|
||||
// Indicates that the element has been "grabbed" for dragging.
|
||||
TRUE: 'true',
|
||||
// Indicates that the element supports being dragged.
|
||||
FALSE: 'false',
|
||||
// Indicates that the element does not support being dragged.
|
||||
UNDEFINED: 'undefined'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for InvalidValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.InvalidValues = {
|
||||
// There are no detected errors in the value.
|
||||
FALSE: 'false',
|
||||
// The value entered by the user has failed validation.
|
||||
TRUE: 'true',
|
||||
// A grammatical error was detected.
|
||||
GRAMMAR: 'grammar',
|
||||
// A spelling error was detected.
|
||||
SPELLING: 'spelling'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for PressedValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.PressedValues = {
|
||||
// The element is pressed.
|
||||
TRUE: 'true',
|
||||
// The element supports being pressed but is not currently pressed.
|
||||
FALSE: 'false',
|
||||
// Indicates a mixed mode value for a tri-state toggle button.
|
||||
MIXED: 'mixed',
|
||||
// The element does not support being pressed.
|
||||
UNDEFINED: 'undefined'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ARIA state values for SelectedValues.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.SelectedValues = {
|
||||
// The selectable element is selected.
|
||||
TRUE: 'true',
|
||||
// The selectable element is not selected.
|
||||
FALSE: 'false',
|
||||
// The element is not selectable.
|
||||
UNDEFINED: 'undefined'
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright 2013 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 The file contains data tables generated from the ARIA
|
||||
* standard schema http://www.w3.org/TR/wai-aria/.
|
||||
*
|
||||
* This is auto-generated code. Do not manually edit!
|
||||
*/
|
||||
|
||||
goog.provide('goog.a11y.aria.datatables');
|
||||
|
||||
goog.require('goog.a11y.aria.State');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
/**
|
||||
* A map that contains mapping between an ARIA state and the default value
|
||||
* for it. Note that not all ARIA states have default values.
|
||||
*
|
||||
* @type {Object.<!(goog.a11y.aria.State|string), (string|boolean|number)>}
|
||||
*/
|
||||
goog.a11y.aria.DefaultStateValueMap_;
|
||||
|
||||
|
||||
/**
|
||||
* A method that creates a map that contains mapping between an ARIA state and
|
||||
* the default value for it. Note that not all ARIA states have default values.
|
||||
*
|
||||
* @return {Object.<!(goog.a11y.aria.State|string), (string|boolean|number)>}
|
||||
* The names for each of the notification methods.
|
||||
*/
|
||||
goog.a11y.aria.datatables.getDefaultValuesMap = function() {
|
||||
if (!goog.a11y.aria.DefaultStateValueMap_) {
|
||||
goog.a11y.aria.DefaultStateValueMap_ = goog.object.create(
|
||||
goog.a11y.aria.State.ATOMIC, false,
|
||||
goog.a11y.aria.State.AUTOCOMPLETE, 'none',
|
||||
goog.a11y.aria.State.DROPEFFECT, 'none',
|
||||
goog.a11y.aria.State.HASPOPUP, false,
|
||||
goog.a11y.aria.State.LIVE, 'off',
|
||||
goog.a11y.aria.State.MULTILINE, false,
|
||||
goog.a11y.aria.State.MULTISELECTABLE, false,
|
||||
goog.a11y.aria.State.ORIENTATION, 'vertical',
|
||||
goog.a11y.aria.State.READONLY, false,
|
||||
goog.a11y.aria.State.RELEVANT, 'additions text',
|
||||
goog.a11y.aria.State.REQUIRED, false,
|
||||
goog.a11y.aria.State.SORT, 'none',
|
||||
goog.a11y.aria.State.BUSY, false,
|
||||
goog.a11y.aria.State.DISABLED, false,
|
||||
goog.a11y.aria.State.HIDDEN, false,
|
||||
goog.a11y.aria.State.INVALID, 'false');
|
||||
}
|
||||
|
||||
return goog.a11y.aria.DefaultStateValueMap_;
|
||||
};
|
||||
216
float-no-zero/closure-library/closure/goog/a11y/aria/roles.js
Normal file
216
float-no-zero/closure-library/closure/goog/a11y/aria/roles.js
Normal file
@@ -0,0 +1,216 @@
|
||||
// Copyright 2013 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 The file contains generated enumerations for ARIA roles
|
||||
* as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/.
|
||||
*
|
||||
* This is auto-generated code. Do not manually edit! For more details
|
||||
* about how to edit it via the generator check go/closure-ariagen.
|
||||
*/
|
||||
|
||||
goog.provide('goog.a11y.aria.Role');
|
||||
|
||||
|
||||
/**
|
||||
* ARIA role values.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.a11y.aria.Role = {
|
||||
// ARIA role for an alert element that doesn't need to be explicitly closed.
|
||||
ALERT: 'alert',
|
||||
|
||||
// ARIA role for an alert dialog element that takes focus and must be closed.
|
||||
ALERTDIALOG: 'alertdialog',
|
||||
|
||||
// ARIA role for an application that implements its own keyboard navigation.
|
||||
APPLICATION: 'application',
|
||||
|
||||
// ARIA role for an article.
|
||||
ARTICLE: 'article',
|
||||
|
||||
// ARIA role for a banner containing mostly site content, not page content.
|
||||
BANNER: 'banner',
|
||||
|
||||
// ARIA role for a button element.
|
||||
BUTTON: 'button',
|
||||
|
||||
// ARIA role for a checkbox button element; use with the CHECKED state.
|
||||
CHECKBOX: 'checkbox',
|
||||
|
||||
// ARIA role for a column header of a table or grid.
|
||||
COLUMNHEADER: 'columnheader',
|
||||
|
||||
// ARIA role for a combo box element.
|
||||
COMBOBOX: 'combobox',
|
||||
|
||||
// ARIA role for a supporting section of the document.
|
||||
COMPLEMENTARY: 'complementary',
|
||||
|
||||
// ARIA role for a large perceivable region that contains information
|
||||
// about the parent document.
|
||||
CONTENTINFO: 'contentinfo',
|
||||
|
||||
// ARIA role for a definition of a term or concept.
|
||||
DEFINITION: 'definition',
|
||||
|
||||
// ARIA role for a dialog, some descendant must take initial focus.
|
||||
DIALOG: 'dialog',
|
||||
|
||||
// ARIA role for a directory, like a table of contents.
|
||||
DIRECTORY: 'directory',
|
||||
|
||||
// ARIA role for a part of a page that's a document, not a web application.
|
||||
DOCUMENT: 'document',
|
||||
|
||||
// ARIA role for a landmark region logically considered one form.
|
||||
FORM: 'form',
|
||||
|
||||
// ARIA role for an interactive control of tabular data.
|
||||
GRID: 'grid',
|
||||
|
||||
// ARIA role for a cell in a grid.
|
||||
GRIDCELL: 'gridcell',
|
||||
|
||||
// ARIA role for a group of related elements like tree item siblings.
|
||||
GROUP: 'group',
|
||||
|
||||
// ARIA role for a heading element.
|
||||
HEADING: 'heading',
|
||||
|
||||
// ARIA role for a container of elements that together comprise one image.
|
||||
IMG: 'img',
|
||||
|
||||
// ARIA role for a link.
|
||||
LINK: 'link',
|
||||
|
||||
// ARIA role for a list of non-interactive list items.
|
||||
LIST: 'list',
|
||||
|
||||
// ARIA role for a listbox.
|
||||
LISTBOX: 'listbox',
|
||||
|
||||
// ARIA role for a list item.
|
||||
LISTITEM: 'listitem',
|
||||
|
||||
// ARIA role for a live region where new information is added.
|
||||
LOG: 'log',
|
||||
|
||||
// ARIA landmark role for the main content in a document. Use only once.
|
||||
MAIN: 'main',
|
||||
|
||||
// ARIA role for a live region of non-essential information that changes.
|
||||
MARQUEE: 'marquee',
|
||||
|
||||
// ARIA role for a mathematical expression.
|
||||
MATH: 'math',
|
||||
|
||||
// ARIA role for a popup menu.
|
||||
MENU: 'menu',
|
||||
|
||||
// ARIA role for a menubar element containing menu elements.
|
||||
MENUBAR: 'menubar',
|
||||
|
||||
// ARIA role for menu item elements.
|
||||
MENU_ITEM: 'menuitem',
|
||||
|
||||
// ARIA role for a checkbox box element inside a menu.
|
||||
MENU_ITEM_CHECKBOX: 'menuitemcheckbox',
|
||||
|
||||
// ARIA role for a radio button element inside a menu.
|
||||
MENU_ITEM_RADIO: 'menuitemradio',
|
||||
|
||||
// ARIA landmark role for a collection of navigation links.
|
||||
NAVIGATION: 'navigation',
|
||||
|
||||
// ARIA role for a section ancillary to the main content.
|
||||
NOTE: 'note',
|
||||
|
||||
// ARIA role for option items that are children of combobox, listbox, menu,
|
||||
// radiogroup, or tree elements.
|
||||
OPTION: 'option',
|
||||
|
||||
// ARIA role for ignorable cosmetic elements with no semantic significance.
|
||||
PRESENTATION: 'presentation',
|
||||
|
||||
// ARIA role for a progress bar element.
|
||||
PROGRESSBAR: 'progressbar',
|
||||
|
||||
// ARIA role for a radio button element.
|
||||
RADIO: 'radio',
|
||||
|
||||
// ARIA role for a group of connected radio button elements.
|
||||
RADIOGROUP: 'radiogroup',
|
||||
|
||||
// ARIA role for an important region of the page.
|
||||
REGION: 'region',
|
||||
|
||||
// ARIA role for a row of cells in a grid.
|
||||
ROW: 'row',
|
||||
|
||||
// ARIA role for a group of one or more rows in a grid.
|
||||
ROWGROUP: 'rowgroup',
|
||||
|
||||
// ARIA role for a row header of a table or grid.
|
||||
ROWHEADER: 'rowheader',
|
||||
|
||||
// ARIA role for a scrollbar element.
|
||||
SCROLLBAR: 'scrollbar',
|
||||
|
||||
// ARIA landmark role for a part of the page providing search functionality.
|
||||
SEARCH: 'search',
|
||||
|
||||
// ARIA role for a menu separator.
|
||||
SEPARATOR: 'separator',
|
||||
|
||||
// ARIA role for a slider.
|
||||
SLIDER: 'slider',
|
||||
|
||||
// ARIA role for a spin button.
|
||||
SPINBUTTON: 'spinbutton',
|
||||
|
||||
// ARIA role for a live region with advisory info less severe than an alert.
|
||||
STATUS: 'status',
|
||||
|
||||
// ARIA role for a tab button.
|
||||
TAB: 'tab',
|
||||
|
||||
// ARIA role for a tab bar (i.e. a list of tab buttons).
|
||||
TAB_LIST: 'tablist',
|
||||
|
||||
// ARIA role for a tab page (i.e. the element holding tab contents).
|
||||
TAB_PANEL: 'tabpanel',
|
||||
|
||||
// ARIA role for a textbox element.
|
||||
TEXTBOX: 'textbox',
|
||||
|
||||
// ARIA role for an element displaying elapsed time or time remaining.
|
||||
TIMER: 'timer',
|
||||
|
||||
// ARIA role for a toolbar element.
|
||||
TOOLBAR: 'toolbar',
|
||||
|
||||
// ARIA role for a tooltip element.
|
||||
TOOLTIP: 'tooltip',
|
||||
|
||||
// ARIA role for a tree.
|
||||
TREE: 'tree',
|
||||
|
||||
// ARIA role for a grid whose rows can be expanded and collapsed like a tree.
|
||||
TREEGRID: 'treegrid',
|
||||
|
||||
// ARIA role for a tree item that sometimes may be expanded or collapsed.
|
||||
TREEITEM: 'treeitem'
|
||||
};
|
||||
1507
float-no-zero/closure-library/closure/goog/array/array.js
Normal file
1507
float-no-zero/closure-library/closure/goog/array/array.js
Normal file
File diff suppressed because it is too large
Load Diff
293
float-no-zero/closure-library/closure/goog/asserts/asserts.js
Normal file
293
float-no-zero/closure-library/closure/goog/asserts/asserts.js
Normal file
@@ -0,0 +1,293 @@
|
||||
// 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 Utilities to check the preconditions, postconditions and
|
||||
* invariants runtime.
|
||||
*
|
||||
* Methods in this package should be given special treatment by the compiler
|
||||
* for type-inference. For example, <code>goog.asserts.assert(foo)</code>
|
||||
* will restrict <code>foo</code> to a truthy value.
|
||||
*
|
||||
* The compiler has an option to disable asserts. So code like:
|
||||
* <code>
|
||||
* var x = goog.asserts.assert(foo()); goog.asserts.assert(bar());
|
||||
* </code>
|
||||
* will be transformed into:
|
||||
* <code>
|
||||
* var x = foo();
|
||||
* </code>
|
||||
* The compiler will leave in foo() (because its return value is used),
|
||||
* but it will remove bar() because it assumes it does not have side-effects.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.asserts');
|
||||
goog.provide('goog.asserts.AssertionError');
|
||||
|
||||
goog.require('goog.debug.Error');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to strip out asserts or to leave them in.
|
||||
*/
|
||||
goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error object for failed assertions.
|
||||
* @param {string} messagePattern The pattern that was used to form message.
|
||||
* @param {!Array.<*>} messageArgs The items to substitute into the pattern.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.asserts.AssertionError = function(messagePattern, messageArgs) {
|
||||
messageArgs.unshift(messagePattern);
|
||||
goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
|
||||
// Remove the messagePattern afterwards to avoid permenantly modifying the
|
||||
// passed in array.
|
||||
messageArgs.shift();
|
||||
|
||||
/**
|
||||
* The message pattern used to format the error message. Error handlers can
|
||||
* use this to uniquely identify the assertion.
|
||||
* @type {string}
|
||||
*/
|
||||
this.messagePattern = messagePattern;
|
||||
};
|
||||
goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.asserts.AssertionError.prototype.name = 'AssertionError';
|
||||
|
||||
|
||||
/**
|
||||
* Throws an exception with the given message and "Assertion failed" prefixed
|
||||
* onto it.
|
||||
* @param {string} defaultMessage The message to use if givenMessage is empty.
|
||||
* @param {Array.<*>} defaultArgs The substitution arguments for defaultMessage.
|
||||
* @param {string|undefined} givenMessage Message supplied by the caller.
|
||||
* @param {Array.<*>} givenArgs The substitution arguments for givenMessage.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a number.
|
||||
* @private
|
||||
*/
|
||||
goog.asserts.doAssertFailure_ =
|
||||
function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
|
||||
var message = 'Assertion failed';
|
||||
if (givenMessage) {
|
||||
message += ': ' + givenMessage;
|
||||
var args = givenArgs;
|
||||
} else if (defaultMessage) {
|
||||
message += ': ' + defaultMessage;
|
||||
args = defaultArgs;
|
||||
}
|
||||
// The '' + works around an Opera 10 bug in the unit tests. Without it,
|
||||
// a stack trace is added to var message above. With this, a stack trace is
|
||||
// not added until this line (it causes the extra garbage to be added after
|
||||
// the assertion message instead of in the middle of it).
|
||||
throw new goog.asserts.AssertionError('' + message, args || []);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is
|
||||
* true.
|
||||
* @param {*} condition The condition to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {*} The value of the condition.
|
||||
* @throws {goog.asserts.AssertionError} When the condition evaluates to false.
|
||||
*/
|
||||
goog.asserts.assert = function(condition, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !condition) {
|
||||
goog.asserts.doAssertFailure_('', null, opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return condition;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case
|
||||
* when we want to add a check in the unreachable area like switch-case
|
||||
* statement:
|
||||
*
|
||||
* <pre>
|
||||
* switch(type) {
|
||||
* case FOO: doSomething(); break;
|
||||
* case BAR: doSomethingElse(); break;
|
||||
* default: goog.assert.fail('Unrecognized type: ' + type);
|
||||
* // We have only 2 types - "default:" section is unreachable code.
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @throws {goog.asserts.AssertionError} Failure.
|
||||
*/
|
||||
goog.asserts.fail = function(opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS) {
|
||||
throw new goog.asserts.AssertionError(
|
||||
'Failure' + (opt_message ? ': ' + opt_message : ''),
|
||||
Array.prototype.slice.call(arguments, 1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {number} The value, guaranteed to be a number when asserts enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a number.
|
||||
*/
|
||||
goog.asserts.assertNumber = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected number but got %s: %s.',
|
||||
[goog.typeOf(value), value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {number} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {string} The value, guaranteed to be a string when asserts enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a string.
|
||||
*/
|
||||
goog.asserts.assertString = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected string but got %s: %s.',
|
||||
[goog.typeOf(value), value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {string} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Function} The value, guaranteed to be a function when asserts
|
||||
* enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a function.
|
||||
*/
|
||||
goog.asserts.assertFunction = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected function but got %s: %s.',
|
||||
[goog.typeOf(value), value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Function} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Object} The value, guaranteed to be a non-null object.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an object.
|
||||
*/
|
||||
goog.asserts.assertObject = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected object but got %s: %s.',
|
||||
[goog.typeOf(value), value],
|
||||
opt_message, Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Object} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {!Array} The value, guaranteed to be a non-null array.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an array.
|
||||
*/
|
||||
goog.asserts.assertArray = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected array but got %s: %s.',
|
||||
[goog.typeOf(value), value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {!Array} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true.
|
||||
* @param {*} value The value to check.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @return {boolean} The value, guaranteed to be a boolean when asserts are
|
||||
* enabled.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not a boolean.
|
||||
*/
|
||||
goog.asserts.assertBoolean = function(value, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
|
||||
goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.',
|
||||
[goog.typeOf(value), value], opt_message,
|
||||
Array.prototype.slice.call(arguments, 2));
|
||||
}
|
||||
return /** @type {boolean} */ (value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the value is an instance of the user-defined type if
|
||||
* goog.asserts.ENABLE_ASSERTS is true.
|
||||
*
|
||||
* The compiler may tighten the type returned by this function.
|
||||
*
|
||||
* @param {*} value The value to check.
|
||||
* @param {function(new: T, ...)} type A user-defined constructor.
|
||||
* @param {string=} opt_message Error message in case of failure.
|
||||
* @param {...*} var_args The items to substitute into the failure message.
|
||||
* @throws {goog.asserts.AssertionError} When the value is not an instance of
|
||||
* type.
|
||||
* @return {!T}
|
||||
* @template T
|
||||
*/
|
||||
goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
|
||||
if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
|
||||
goog.asserts.doAssertFailure_('instanceof check failed.', null,
|
||||
opt_message, Array.prototype.slice.call(arguments, 3));
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks that no enumerable keys are present in Object.prototype. Such keys
|
||||
* would break most code that use {@code for (var ... in ...)} loops.
|
||||
*/
|
||||
goog.asserts.assertObjectPrototypeIsIntact = function() {
|
||||
for (var key in Object.prototype) {
|
||||
goog.asserts.fail(key + ' should not be enumerable in Object.prototype.');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,270 @@
|
||||
// Copyright 2012 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 A delayed callback that pegs to the next animation frame
|
||||
* instead of a user-configurable timeout.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.AnimationDelay');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.functions');
|
||||
|
||||
|
||||
|
||||
// TODO(nicksantos): Should we factor out the common code between this and
|
||||
// goog.async.Delay? I'm not sure if there's enough code for this to really
|
||||
// make sense. Subclassing seems like the wrong approach for a variety of
|
||||
// reasons. Maybe there should be a common interface?
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A delayed callback that pegs to the next animation frame
|
||||
* instead of a user configurable timeout. By design, this should have
|
||||
* the same interface as goog.async.Delay.
|
||||
*
|
||||
* Uses requestAnimationFrame and friends when available, but falls
|
||||
* back to a timeout of goog.async.AnimationDelay.TIMEOUT.
|
||||
*
|
||||
* For more on requestAnimationFrame and how you can use it to create smoother
|
||||
* animations, see:
|
||||
* @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||
*
|
||||
* @param {function(number)} listener Function to call when the delay completes.
|
||||
* Will be passed the timestamp when it's called, in unix ms.
|
||||
* @param {Window=} opt_window The window object to execute the delay in.
|
||||
* Defaults to the global object.
|
||||
* @param {Object=} opt_handler The object scope to invoke the function in.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
goog.async.AnimationDelay = function(listener, opt_window, opt_handler) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* The function that will be invoked after a delay.
|
||||
* @type {function(number)}
|
||||
* @private
|
||||
*/
|
||||
this.listener_ = listener;
|
||||
|
||||
/**
|
||||
* The object context to invoke the callback in.
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.handler_ = opt_handler;
|
||||
|
||||
/**
|
||||
* @type {Window}
|
||||
* @private
|
||||
*/
|
||||
this.win_ = opt_window || window;
|
||||
|
||||
/**
|
||||
* Cached callback function invoked when the delay finishes.
|
||||
* @type {function()}
|
||||
* @private
|
||||
*/
|
||||
this.callback_ = goog.bind(this.doAction_, this);
|
||||
};
|
||||
goog.inherits(goog.async.AnimationDelay, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* Identifier of the active delay timeout, or event listener,
|
||||
* or null when inactive.
|
||||
* @type {goog.events.Key|number|null}
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.id_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* If we're using dom listeners.
|
||||
* @type {?boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.usingListeners_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Default wait timeout for animations (in milliseconds). Only used for timed
|
||||
* animation, which uses a timer (setTimeout) to schedule animation.
|
||||
*
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
goog.async.AnimationDelay.TIMEOUT = 20;
|
||||
|
||||
|
||||
/**
|
||||
* Name of event received from the requestAnimationFrame in Firefox.
|
||||
*
|
||||
* @type {string}
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = 'MozBeforePaint';
|
||||
|
||||
|
||||
/**
|
||||
* Starts the delay timer. The provided listener function will be called
|
||||
* before the next animation frame.
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.start = function() {
|
||||
this.stop();
|
||||
this.usingListeners_ = false;
|
||||
|
||||
var raf = this.getRaf_();
|
||||
var cancelRaf = this.getCancelRaf_();
|
||||
if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
|
||||
// Because Firefox (Gecko) runs animation in separate threads, it also saves
|
||||
// time by running the requestAnimationFrame callbacks in that same thread.
|
||||
// Sadly this breaks the assumption of implicit thread-safety in JS, and can
|
||||
// thus create thread-based inconsistencies on counters etc.
|
||||
//
|
||||
// Calling cycleAnimations_ using the MozBeforePaint event instead of as
|
||||
// callback fixes this.
|
||||
//
|
||||
// Trigger this condition only if the mozRequestAnimationFrame is available,
|
||||
// but not the W3C requestAnimationFrame function (as in draft) or the
|
||||
// equivalent cancel functions.
|
||||
this.id_ = goog.events.listen(
|
||||
this.win_,
|
||||
goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_,
|
||||
this.callback_);
|
||||
this.win_.mozRequestAnimationFrame(null);
|
||||
this.usingListeners_ = true;
|
||||
} else if (raf && cancelRaf) {
|
||||
this.id_ = raf.call(this.win_, this.callback_);
|
||||
} else {
|
||||
this.id_ = this.win_.setTimeout(
|
||||
// Prior to Firefox 13, Gecko passed a non-standard parameter
|
||||
// to the callback that we want to ignore.
|
||||
goog.functions.lock(this.callback_),
|
||||
goog.async.AnimationDelay.TIMEOUT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops the delay timer if it is active. No action is taken if the timer is not
|
||||
* in use.
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.stop = function() {
|
||||
if (this.isActive()) {
|
||||
var raf = this.getRaf_();
|
||||
var cancelRaf = this.getCancelRaf_();
|
||||
if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
|
||||
goog.events.unlistenByKey(this.id_);
|
||||
} else if (raf && cancelRaf) {
|
||||
cancelRaf.call(this.win_, /** @type {number} */ (this.id_));
|
||||
} else {
|
||||
this.win_.clearTimeout(/** @type {number} */ (this.id_));
|
||||
}
|
||||
}
|
||||
this.id_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires delay's action even if timer has already gone off or has not been
|
||||
* started yet; guarantees action firing. Stops the delay timer.
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.fire = function() {
|
||||
this.stop();
|
||||
this.doAction_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires delay's action only if timer is currently active. Stops the delay
|
||||
* timer.
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.fireIfActive = function() {
|
||||
if (this.isActive()) {
|
||||
this.fire();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the delay is currently active, false otherwise.
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.isActive = function() {
|
||||
return this.id_ != null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Invokes the callback function after the delay successfully completes.
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.doAction_ = function() {
|
||||
if (this.usingListeners_ && this.id_) {
|
||||
goog.events.unlistenByKey(this.id_);
|
||||
}
|
||||
this.id_ = null;
|
||||
|
||||
// We are not using the timestamp returned by requestAnimationFrame
|
||||
// because it may be either a Date.now-style time or a
|
||||
// high-resolution time (depending on browser implementation). Using
|
||||
// goog.now() will ensure that the timestamp used is consistent and
|
||||
// compatible with goog.fx.Animation.
|
||||
this.listener_.call(this.handler_, goog.now());
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.AnimationDelay.prototype.disposeInternal = function() {
|
||||
this.stop();
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {?function(function(number)): number} The requestAnimationFrame
|
||||
* function, or null if not available on this browser.
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.getRaf_ = function() {
|
||||
var win = this.win_;
|
||||
return win.requestAnimationFrame ||
|
||||
win.webkitRequestAnimationFrame ||
|
||||
win.mozRequestAnimationFrame ||
|
||||
win.oRequestAnimationFrame ||
|
||||
win.msRequestAnimationFrame ||
|
||||
null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {?function(number): number} The cancelAnimationFrame function,
|
||||
* or null if not available on this browser.
|
||||
* @private
|
||||
*/
|
||||
goog.async.AnimationDelay.prototype.getCancelRaf_ = function() {
|
||||
var win = this.win_;
|
||||
return win.cancelRequestAnimationFrame ||
|
||||
win.webkitCancelRequestAnimationFrame ||
|
||||
win.mozCancelRequestAnimationFrame ||
|
||||
win.oCancelRequestAnimationFrame ||
|
||||
win.msCancelRequestAnimationFrame ||
|
||||
null;
|
||||
};
|
||||
@@ -0,0 +1,235 @@
|
||||
// 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 Defines a class useful for handling functions that must be
|
||||
* invoked later when some condition holds. Examples include deferred function
|
||||
* calls that return a boolean flag whether it succedeed or not.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* function deferred() {
|
||||
* var succeeded = false;
|
||||
* // ... custom code
|
||||
* return succeeded;
|
||||
* }
|
||||
*
|
||||
* var deferredCall = new goog.async.ConditionalDelay(deferred);
|
||||
* deferredCall.onSuccess = function() {
|
||||
* alert('Success: The deferred function has been successfully executed.');
|
||||
* }
|
||||
* deferredCall.onFailure = function() {
|
||||
* alert('Failure: Time limit exceeded.');
|
||||
* }
|
||||
*
|
||||
* // Call the deferred() every 100 msec until it returns true,
|
||||
* // or 5 seconds pass.
|
||||
* deferredCall.start(100, 5000);
|
||||
*
|
||||
* // Stop the deferred function call (does nothing if it's not active).
|
||||
* deferredCall.stop();
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.async.ConditionalDelay');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.async.Delay');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A ConditionalDelay object invokes the associated function after a specified
|
||||
* interval delay and checks its return value. If the function returns
|
||||
* {@code true} the conditional delay is cancelled and {@see #onSuccess}
|
||||
* is called. Otherwise this object keeps to invoke the deferred function until
|
||||
* either it returns {@code true} or the timeout is exceeded. In the latter case
|
||||
* the {@see #onFailure} method will be called.
|
||||
*
|
||||
* The interval duration and timeout can be specified each time the delay is
|
||||
* started. Calling start on an active delay will reset the timer.
|
||||
*
|
||||
* @param {function():boolean} listener Function to call when the delay
|
||||
* completes. Should return a value that type-converts to {@code true} if
|
||||
* the call succeeded and this delay should be stopped.
|
||||
* @param {Object=} opt_handler The object scope to invoke the function in.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
goog.async.ConditionalDelay = function(listener, opt_handler) {
|
||||
goog.Disposable.call(this);
|
||||
|
||||
/**
|
||||
* The function that will be invoked after a delay.
|
||||
* @type {function():boolean}
|
||||
* @private
|
||||
*/
|
||||
this.listener_ = listener;
|
||||
|
||||
/**
|
||||
* The object context to invoke the callback in.
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.handler_ = opt_handler;
|
||||
|
||||
/**
|
||||
* The underlying goog.async.Delay delegate object.
|
||||
* @type {goog.async.Delay}
|
||||
* @private
|
||||
*/
|
||||
this.delay_ = new goog.async.Delay(
|
||||
goog.bind(this.onTick_, this), 0 /*interval*/, this /*scope*/);
|
||||
};
|
||||
goog.inherits(goog.async.ConditionalDelay, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* The delay interval in milliseconds to between the calls to the callback.
|
||||
* Note, that the callback may be invoked earlier than this interval if the
|
||||
* timeout is exceeded.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.interval_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* The timeout timestamp until which the delay is to be executed.
|
||||
* A negative value means no timeout.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.runUntil_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* True if the listener has been executed, and it returned {@code true}.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.isDone_ = false;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.ConditionalDelay.prototype.disposeInternal = function() {
|
||||
this.delay_.dispose();
|
||||
delete this.listener_;
|
||||
delete this.handler_;
|
||||
goog.async.ConditionalDelay.superClass_.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Starts the delay timer. The provided listener function will be called
|
||||
* repeatedly after the specified interval until the function returns
|
||||
* {@code true} or the timeout is exceeded. Calling start on an active timer
|
||||
* will stop the timer first.
|
||||
* @param {number=} opt_interval The time interval between the function
|
||||
* invocations (in milliseconds). Default is 0.
|
||||
* @param {number=} opt_timeout The timeout interval (in milliseconds). Takes
|
||||
* precedence over the {@code opt_interval}, i.e. if the timeout is less
|
||||
* than the invocation interval, the function will be called when the
|
||||
* timeout is exceeded. A negative value means no timeout. Default is 0.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.start = function(opt_interval,
|
||||
opt_timeout) {
|
||||
this.stop();
|
||||
this.isDone_ = false;
|
||||
|
||||
var timeout = opt_timeout || 0;
|
||||
this.interval_ = Math.max(opt_interval || 0, 0);
|
||||
this.runUntil_ = timeout < 0 ? -1 : (goog.now() + timeout);
|
||||
this.delay_.start(
|
||||
timeout < 0 ? this.interval_ : Math.min(this.interval_, timeout));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops the delay timer if it is active. No action is taken if the timer is not
|
||||
* in use.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.stop = function() {
|
||||
this.delay_.stop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the delay is currently active, false otherwise.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.isActive = function() {
|
||||
return this.delay_.isActive();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the listener has been executed and returned
|
||||
* {@code true} since the last call to {@see #start}.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.isDone = function() {
|
||||
return this.isDone_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when the listener has been successfully executed and returned
|
||||
* {@code true}. The {@see #isDone} method should return {@code true} by now.
|
||||
* Designed for inheritance, should be overridden by subclasses or on the
|
||||
* instances if they care.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.onSuccess = function() {
|
||||
// Do nothing by default.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when this delayed call is cancelled because the timeout has been
|
||||
* exceeded, and the listener has never returned {@code true}.
|
||||
* Designed for inheritance, should be overridden by subclasses or on the
|
||||
* instances if they care.
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.onFailure = function() {
|
||||
// Do nothing by default.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A callback function for the underlying {@code goog.async.Delay} object. When
|
||||
* executed the listener function is called, and if it returns {@code true}
|
||||
* the delay is stopped and the {@see #onSuccess} method is invoked.
|
||||
* If the timeout is exceeded the delay is stopped and the
|
||||
* {@see #onFailure} method is called.
|
||||
* @private
|
||||
*/
|
||||
goog.async.ConditionalDelay.prototype.onTick_ = function() {
|
||||
var successful = this.listener_.call(this.handler_);
|
||||
if (successful) {
|
||||
this.isDone_ = true;
|
||||
this.onSuccess();
|
||||
} else {
|
||||
// Try to reschedule the task.
|
||||
if (this.runUntil_ < 0) {
|
||||
// No timeout.
|
||||
this.delay_.start(this.interval_);
|
||||
} else {
|
||||
var timeLeft = this.runUntil_ - goog.now();
|
||||
if (timeLeft <= 0) {
|
||||
this.onFailure();
|
||||
} else {
|
||||
this.delay_.start(Math.min(this.interval_, timeLeft));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
177
float-no-zero/closure-library/closure/goog/async/delay.js
Normal file
177
float-no-zero/closure-library/closure/goog/async/delay.js
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright 2007 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 Defines a class useful for handling functions that must be
|
||||
* invoked after a delay, especially when that delay is frequently restarted.
|
||||
* Examples include delaying before displaying a tooltip, menu hysteresis,
|
||||
* idle timers, etc.
|
||||
* @author brenneman@google.com (Shawn Brenneman)
|
||||
* @see ../demos/timers.html
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.Delay');
|
||||
goog.provide('goog.async.Delay');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.Timer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Delay object invokes the associated function after a specified delay. The
|
||||
* interval duration can be specified once in the constructor, or can be defined
|
||||
* each time the delay is started. Calling start on an active delay will reset
|
||||
* the timer.
|
||||
*
|
||||
* @param {Function} listener Function to call when the delay completes.
|
||||
* @param {number=} opt_interval The default length of the invocation delay (in
|
||||
* milliseconds).
|
||||
* @param {Object=} opt_handler The object scope to invoke the function in.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
goog.async.Delay = function(listener, opt_interval, opt_handler) {
|
||||
goog.Disposable.call(this);
|
||||
|
||||
/**
|
||||
* The function that will be invoked after a delay.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.listener_ = listener;
|
||||
|
||||
/**
|
||||
* The default amount of time to delay before invoking the callback.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.interval_ = opt_interval || 0;
|
||||
|
||||
/**
|
||||
* The object context to invoke the callback in.
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.handler_ = opt_handler;
|
||||
|
||||
|
||||
/**
|
||||
* Cached callback function invoked when the delay finishes.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.callback_ = goog.bind(this.doAction_, this);
|
||||
};
|
||||
goog.inherits(goog.async.Delay, goog.Disposable);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A deprecated alias.
|
||||
* @deprecated Use goog.async.Delay instead.
|
||||
* @constructor
|
||||
*/
|
||||
goog.Delay = goog.async.Delay;
|
||||
|
||||
|
||||
/**
|
||||
* Identifier of the active delay timeout, or 0 when inactive.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Delay.prototype.id_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the object, cancelling the timeout if it is still outstanding and
|
||||
* removing all object references.
|
||||
* @override
|
||||
* @protected
|
||||
*/
|
||||
goog.async.Delay.prototype.disposeInternal = function() {
|
||||
goog.async.Delay.superClass_.disposeInternal.call(this);
|
||||
this.stop();
|
||||
delete this.listener_;
|
||||
delete this.handler_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Starts the delay timer. The provided listener function will be called after
|
||||
* the specified interval. Calling start on an active timer will reset the
|
||||
* delay interval.
|
||||
* @param {number=} opt_interval If specified, overrides the object's default
|
||||
* interval with this one (in milliseconds).
|
||||
*/
|
||||
goog.async.Delay.prototype.start = function(opt_interval) {
|
||||
this.stop();
|
||||
this.id_ = goog.Timer.callOnce(
|
||||
this.callback_,
|
||||
goog.isDef(opt_interval) ? opt_interval : this.interval_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops the delay timer if it is active. No action is taken if the timer is not
|
||||
* in use.
|
||||
*/
|
||||
goog.async.Delay.prototype.stop = function() {
|
||||
if (this.isActive()) {
|
||||
goog.Timer.clear(this.id_);
|
||||
}
|
||||
this.id_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires delay's action even if timer has already gone off or has not been
|
||||
* started yet; guarantees action firing. Stops the delay timer.
|
||||
*/
|
||||
goog.async.Delay.prototype.fire = function() {
|
||||
this.stop();
|
||||
this.doAction_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires delay's action only if timer is currently active. Stops the delay
|
||||
* timer.
|
||||
*/
|
||||
goog.async.Delay.prototype.fireIfActive = function() {
|
||||
if (this.isActive()) {
|
||||
this.fire();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the delay is currently active, false otherwise.
|
||||
*/
|
||||
goog.async.Delay.prototype.isActive = function() {
|
||||
return this.id_ != 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Invokes the callback function after the delay successfully completes.
|
||||
* @private
|
||||
*/
|
||||
goog.async.Delay.prototype.doAction_ = function() {
|
||||
this.id_ = 0;
|
||||
if (this.listener_) {
|
||||
this.listener_.call(this.handler_);
|
||||
}
|
||||
};
|
||||
174
float-no-zero/closure-library/closure/goog/async/nexttick.js
Normal file
174
float-no-zero/closure-library/closure/goog/async/nexttick.js
Normal file
@@ -0,0 +1,174 @@
|
||||
// Copyright 2013 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 Provides a function to schedule running a function as soon
|
||||
* as possible after the current JS execution stops and yields to the event
|
||||
* loop.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.nextTick');
|
||||
|
||||
goog.require('goog.debug.entryPointRegistry');
|
||||
goog.require('goog.functions');
|
||||
|
||||
|
||||
/**
|
||||
* Fires the provided callbacks as soon as possible after the current JS
|
||||
* execution context. setTimeout(…, 0) always takes at least 5ms for legacy
|
||||
* reasons.
|
||||
* @param {function()} callback Callback function to fire as soon as possible.
|
||||
* @param {Object=} opt_context Object in whose scope to call the listener.
|
||||
*/
|
||||
goog.async.nextTick = function(callback, opt_context) {
|
||||
var cb = callback;
|
||||
if (opt_context) {
|
||||
cb = goog.bind(callback, opt_context);
|
||||
}
|
||||
cb = goog.async.nextTick.wrapCallback_(cb);
|
||||
// Introduced and currently only supported by IE10.
|
||||
if (goog.isFunction(goog.global.setImmediate)) {
|
||||
goog.global.setImmediate(cb);
|
||||
return;
|
||||
}
|
||||
// Look for and cache the custom fallback version of setImmediate.
|
||||
if (!goog.async.nextTick.setImmediate_) {
|
||||
goog.async.nextTick.setImmediate_ =
|
||||
goog.async.nextTick.getSetImmediateEmulator_();
|
||||
}
|
||||
goog.async.nextTick.setImmediate_(cb);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cache for the setImmediate implementation.
|
||||
* @type {function(function())}
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.setImmediate_;
|
||||
|
||||
|
||||
/**
|
||||
* Determines the best possible implementation to run a function as soon as
|
||||
* the JS event loop is idle.
|
||||
* @return {function(function())} The "setImmediate" implementation.
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.getSetImmediateEmulator_ = function() {
|
||||
// Create a private message channel and use it to postMessage empty messages
|
||||
// to ourselves.
|
||||
var Channel = goog.global['MessageChannel'];
|
||||
// If MessageChannel is not available and we are in a browser, implement
|
||||
// an iframe based polyfill in browsers that have postMessage and
|
||||
// document.addEventListener. The latter excludes IE8 because it has a
|
||||
// synchronous postMessage implementation.
|
||||
if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&
|
||||
window.postMessage && window.addEventListener) {
|
||||
/** @constructor */
|
||||
Channel = function() {
|
||||
// Make an empty, invisible iframe.
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.display = 'none';
|
||||
iframe.src = '';
|
||||
document.body.appendChild(iframe);
|
||||
var win = iframe.contentWindow;
|
||||
var doc = win.document;
|
||||
doc.open();
|
||||
doc.write('');
|
||||
doc.close();
|
||||
var message = 'callImmediate' + Math.random();
|
||||
var origin = win.location.protocol + '//' + win.location.host;
|
||||
var onmessage = goog.bind(function(e) {
|
||||
// Validate origin and message to make sure that this message was
|
||||
// intended for us.
|
||||
if (e.origin != origin && e.data != message) {
|
||||
return;
|
||||
}
|
||||
this['port1'].onmessage();
|
||||
}, this);
|
||||
win.addEventListener('message', onmessage, false);
|
||||
this['port1'] = {};
|
||||
this['port2'] = {
|
||||
postMessage: function() {
|
||||
win.postMessage(message, origin);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
if (typeof Channel !== 'undefined') {
|
||||
var channel = new Channel();
|
||||
// Use a fifo linked list to call callbacks in the right order.
|
||||
var head = {};
|
||||
var tail = head;
|
||||
channel['port1'].onmessage = function() {
|
||||
head = head.next;
|
||||
var cb = head.cb;
|
||||
head.cb = null;
|
||||
cb();
|
||||
};
|
||||
return function(cb) {
|
||||
tail.next = {
|
||||
cb: cb
|
||||
};
|
||||
tail = tail.next;
|
||||
channel['port2'].postMessage(0);
|
||||
};
|
||||
}
|
||||
// Implementation for IE6-8: Script elements fire an asynchronous
|
||||
// onreadystatechange event when inserted into the DOM.
|
||||
if (typeof document !== 'undefined' && 'onreadystatechange' in
|
||||
document.createElement('script')) {
|
||||
return function(cb) {
|
||||
var script = document.createElement('script');
|
||||
script.onreadystatechange = function() {
|
||||
// Clean up and call the callback.
|
||||
script.onreadystatechange = null;
|
||||
script.parentNode.removeChild(script);
|
||||
script = null;
|
||||
cb();
|
||||
cb = null;
|
||||
};
|
||||
document.documentElement.appendChild(script);
|
||||
};
|
||||
}
|
||||
// Fall back to setTimeout with 0. In browsers this creates a delay of 5ms
|
||||
// or more.
|
||||
return function(cb) {
|
||||
goog.global.setTimeout(cb, 0);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function that is overrided to protect callbacks with entry point
|
||||
* monitor if the application monitors entry points.
|
||||
* @param {function()} callback Callback function to fire as soon as possible.
|
||||
* @return {function()} The wrapped callback.
|
||||
* @private
|
||||
*/
|
||||
goog.async.nextTick.wrapCallback_ = goog.functions.identity;
|
||||
|
||||
|
||||
// Register the callback function as an entry point, so that it can be
|
||||
// monitored for exception handling, etc. This has to be done in this file
|
||||
// since it requires special code to handle all browsers.
|
||||
goog.debug.entryPointRegistry.register(
|
||||
/**
|
||||
* @param {function(!Function): !Function} transformer The transforming
|
||||
* function.
|
||||
*/
|
||||
function(transformer) {
|
||||
goog.async.nextTick.wrapCallback_ = transformer;
|
||||
});
|
||||
189
float-no-zero/closure-library/closure/goog/async/throttle.js
Normal file
189
float-no-zero/closure-library/closure/goog/async/throttle.js
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2007 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 Definition of the goog.async.Throttle class.
|
||||
*
|
||||
* @see ../demos/timers.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.Throttle');
|
||||
goog.provide('goog.async.Throttle');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.Timer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Throttle will perform an action that is passed in no more than once
|
||||
* per interval (specified in milliseconds). If it gets multiple signals
|
||||
* to perform the action while it is waiting, it will only perform the action
|
||||
* once at the end of the interval.
|
||||
* @param {Function} listener Function to callback when the action is triggered.
|
||||
* @param {number} interval Interval over which to throttle. The handler can
|
||||
* only be called once per interval.
|
||||
* @param {Object=} opt_handler Object in whose scope to call the listener.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
*/
|
||||
goog.async.Throttle = function(listener, interval, opt_handler) {
|
||||
goog.Disposable.call(this);
|
||||
|
||||
/**
|
||||
* Function to callback
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.listener_ = listener;
|
||||
|
||||
/**
|
||||
* Interval for the throttle time
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.interval_ = interval;
|
||||
|
||||
/**
|
||||
* "this" context for the listener
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.handler_ = opt_handler;
|
||||
|
||||
/**
|
||||
* Cached callback function invoked after the throttle timeout completes
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.callback_ = goog.bind(this.onTimer_, this);
|
||||
};
|
||||
goog.inherits(goog.async.Throttle, goog.Disposable);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A deprecated alias.
|
||||
* @deprecated Use goog.async.Throttle instead.
|
||||
* @constructor
|
||||
*/
|
||||
goog.Throttle = goog.async.Throttle;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that the action is pending and needs to be fired.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Throttle.prototype.shouldFire_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates the count of nested pauses currently in effect on the throttle.
|
||||
* When this count is not zero, fired actions will be postponed until the
|
||||
* throttle is resumed enough times to drop the pause count to zero.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Throttle.prototype.pauseCount_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Timer for scheduling the next callback
|
||||
* @type {?number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Throttle.prototype.timer_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the throttle that the action has happened. It will throttle the call
|
||||
* so that the callback is not called too often according to the interval
|
||||
* parameter passed to the constructor.
|
||||
*/
|
||||
goog.async.Throttle.prototype.fire = function() {
|
||||
if (!this.timer_ && !this.pauseCount_) {
|
||||
this.doAction_();
|
||||
} else {
|
||||
this.shouldFire_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cancels any pending action callback. The throttle can be restarted by
|
||||
* calling {@link #fire}.
|
||||
*/
|
||||
goog.async.Throttle.prototype.stop = function() {
|
||||
if (this.timer_) {
|
||||
goog.Timer.clear(this.timer_);
|
||||
this.timer_ = null;
|
||||
this.shouldFire_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pauses the throttle. All pending and future action callbacks will be
|
||||
* delayed until the throttle is resumed. Pauses can be nested.
|
||||
*/
|
||||
goog.async.Throttle.prototype.pause = function() {
|
||||
this.pauseCount_++;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resumes the throttle. If doing so drops the pausing count to zero, pending
|
||||
* action callbacks will be executed as soon as possible, but still no sooner
|
||||
* than an interval's delay after the previous call. Future action callbacks
|
||||
* will be executed as normal.
|
||||
*/
|
||||
goog.async.Throttle.prototype.resume = function() {
|
||||
this.pauseCount_--;
|
||||
if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) {
|
||||
this.shouldFire_ = false;
|
||||
this.doAction_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.Throttle.prototype.disposeInternal = function() {
|
||||
goog.async.Throttle.superClass_.disposeInternal.call(this);
|
||||
this.stop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the timer to fire the throttle
|
||||
* @private
|
||||
*/
|
||||
goog.async.Throttle.prototype.onTimer_ = function() {
|
||||
this.timer_ = null;
|
||||
|
||||
if (this.shouldFire_ && !this.pauseCount_) {
|
||||
this.shouldFire_ = false;
|
||||
this.doAction_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the callback
|
||||
* @private
|
||||
*/
|
||||
goog.async.Throttle.prototype.doAction_ = function() {
|
||||
this.timer_ = goog.Timer.callOnce(this.callback_, this.interval_);
|
||||
this.listener_.call(this.handler_);
|
||||
};
|
||||
1593
float-no-zero/closure-library/closure/goog/base.js
Normal file
1593
float-no-zero/closure-library/closure/goog/base.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
// Copyright 2013 The Closure Library Authors.
|
||||
//
|
||||
// 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 A nodejs script for dynamically requiring Closure within
|
||||
* nodejs.
|
||||
*
|
||||
* Example of usage:
|
||||
* <code>
|
||||
* require('./bootstrap/nodejs')
|
||||
* goog.require('goog.ui.Component')
|
||||
* </code>
|
||||
*
|
||||
* This loads goog.ui.Component in the global scope.
|
||||
*
|
||||
* If you want to load custom libraries, you can require the custom deps file
|
||||
* directly. If your custom libraries introduce new globals, you may
|
||||
* need to run goog.nodeGlobalRequire to get them to load correctly.
|
||||
*
|
||||
* <code>
|
||||
* require('./path/to/my/deps.js')
|
||||
* goog.bootstrap.nodeJs.nodeGlobalRequire('./path/to/my/base.js')
|
||||
* goog.require('my.Class')
|
||||
* </code>
|
||||
*
|
||||
* @author nick@medium.com (Nick Santos)
|
||||
*
|
||||
* @nocompile
|
||||
*/
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
|
||||
/**
|
||||
* The goog namespace in the global scope.
|
||||
*/
|
||||
global.goog = {};
|
||||
|
||||
|
||||
/**
|
||||
* Imports a script using Node's require() API.
|
||||
*
|
||||
* @param {string} src The script source.
|
||||
* @return {boolean} True if the script was imported, false otherwise.
|
||||
*/
|
||||
global.CLOSURE_IMPORT_SCRIPT = function(src) {
|
||||
// Sources are always expressed relative to closure's base.js, but
|
||||
// require() is always relative to the current source.
|
||||
require('./../' + src);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
// Declared here so it can be used to require base.js
|
||||
function nodeGlobalRequire(file) {
|
||||
process.binding('evals').NodeScript.runInThisContext.call(
|
||||
global, fs.readFileSync(file), file);
|
||||
}
|
||||
|
||||
|
||||
// Load Closure's base.js into memory. It is assumed base.js is in the
|
||||
// directory above this directory given this script's location in
|
||||
// bootstrap/nodejs.js.
|
||||
nodeGlobalRequire(path.resolve(__dirname, '..', 'base.js'));
|
||||
|
||||
|
||||
/**
|
||||
* Bootstraps a file into the global scope.
|
||||
*
|
||||
* This is strictly for cases where normal require() won't work,
|
||||
* because the file declares global symbols with 'var' that need to
|
||||
* be added to the global scope.
|
||||
* @suppress {missingProvide}
|
||||
*
|
||||
* @param {string} file The path to the file.
|
||||
*/
|
||||
goog.nodeGlobalRequire = nodeGlobalRequire;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2010 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 A bootstrap for dynamically requiring Closure within an HTML5
|
||||
* Web Worker context. To use this, first set CLOSURE_BASE_PATH to the directory
|
||||
* containing base.js (relative to the main script), then use importScripts to
|
||||
* load this file and base.js (in that order). After this you can use
|
||||
* goog.require for further imports.
|
||||
*
|
||||
* @nocompile
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Imports a script using the Web Worker importScript API.
|
||||
*
|
||||
* @param {string} src The script source.
|
||||
* @return {boolean} True if the script was imported, false otherwise.
|
||||
*/
|
||||
this.CLOSURE_IMPORT_SCRIPT = (function(global) {
|
||||
return function(src) {
|
||||
global['importScripts'](src);
|
||||
return true;
|
||||
};
|
||||
})(this);
|
||||
467
float-no-zero/closure-library/closure/goog/color/alpha.js
Normal file
467
float-no-zero/closure-library/closure/goog/color/alpha.js
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright 2006 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 Utilities related to alpha/transparent colors and alpha color
|
||||
* conversion.
|
||||
*/
|
||||
|
||||
goog.provide('goog.color.alpha');
|
||||
|
||||
goog.require('goog.color');
|
||||
|
||||
|
||||
/**
|
||||
* Parses an alpha color out of a string.
|
||||
* @param {string} str Color in some format.
|
||||
* @return {Object} Contains two properties: 'hex', which is a string containing
|
||||
* a hex representation of the color, as well as 'type', which is a string
|
||||
* containing the type of color format passed in ('hex', 'rgb', 'named').
|
||||
*/
|
||||
goog.color.alpha.parse = function(str) {
|
||||
var result = {};
|
||||
str = String(str);
|
||||
|
||||
var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
|
||||
if (goog.color.alpha.isValidAlphaHexColor_(maybeHex)) {
|
||||
result.hex = goog.color.alpha.normalizeAlphaHex_(maybeHex);
|
||||
result.type = 'hex';
|
||||
return result;
|
||||
} else {
|
||||
var rgba = goog.color.alpha.isValidRgbaColor_(str);
|
||||
if (rgba.length) {
|
||||
result.hex = goog.color.alpha.rgbaArrayToHex(rgba);
|
||||
result.type = 'rgba';
|
||||
return result;
|
||||
} else {
|
||||
var hsla = goog.color.alpha.isValidHslaColor_(str);
|
||||
if (hsla.length) {
|
||||
result.hex = goog.color.alpha.hslaArrayToHex(hsla);
|
||||
result.type = 'hsla';
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Error(str + ' is not a valid color string');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex representation of a color to RGBA.
|
||||
* @param {string} hexColor Color to convert.
|
||||
* @return {string} string of the form 'rgba(R,G,B,A)' which can be used in
|
||||
* styles.
|
||||
*/
|
||||
goog.color.alpha.hexToRgbaStyle = function(hexColor) {
|
||||
return goog.color.alpha.rgbaStyle_(goog.color.alpha.hexToRgba(hexColor));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the hex color part of an alpha hex color. For example, from '#abcdef55'
|
||||
* return '#abcdef'.
|
||||
* @param {string} colorWithAlpha The alpha hex color to get the hex color from.
|
||||
* @return {string} The hex color where the alpha part has been stripped off.
|
||||
*/
|
||||
goog.color.alpha.extractHexColor = function(colorWithAlpha) {
|
||||
if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
|
||||
var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
|
||||
var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
|
||||
return normalizedColor.substring(0, 7);
|
||||
} else {
|
||||
throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the alpha color part of an alpha hex color. For example, from
|
||||
* '#abcdef55' return '55'. The result is guaranteed to be two characters long.
|
||||
* @param {string} colorWithAlpha The alpha hex color to get the hex color from.
|
||||
* @return {string} The hex color where the alpha part has been stripped off.
|
||||
*/
|
||||
goog.color.alpha.extractAlpha = function(colorWithAlpha) {
|
||||
if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
|
||||
var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
|
||||
var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
|
||||
return normalizedColor.substring(7, 9);
|
||||
} else {
|
||||
throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for extracting the digits in a hex color quadruplet.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.hexQuadrupletRe_ = /#(.)(.)(.)(.)/;
|
||||
|
||||
|
||||
/**
|
||||
* Normalize a hex representation of an alpha color.
|
||||
* @param {string} hexColor an alpha hex color string.
|
||||
* @return {string} hex color in the format '#rrggbbaa' with all lowercase
|
||||
* literals.
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.normalizeAlphaHex_ = function(hexColor) {
|
||||
if (!goog.color.alpha.isValidAlphaHexColor_(hexColor)) {
|
||||
throw Error("'" + hexColor + "' is not a valid alpha hex color");
|
||||
}
|
||||
if (hexColor.length == 5) { // of the form #RGBA
|
||||
hexColor = hexColor.replace(goog.color.alpha.hexQuadrupletRe_,
|
||||
'#$1$1$2$2$3$3$4$4');
|
||||
}
|
||||
return hexColor.toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an 8-hex representation of a color to RGBA.
|
||||
* @param {string} hexColor Color to convert.
|
||||
* @return {Array} array containing [r, g, b] as ints in [0, 255].
|
||||
*/
|
||||
goog.color.alpha.hexToRgba = function(hexColor) {
|
||||
// TODO(user): Enhance code sharing with goog.color, for example by
|
||||
// adding a goog.color.genericHexToRgb method.
|
||||
hexColor = goog.color.alpha.normalizeAlphaHex_(hexColor);
|
||||
var r = parseInt(hexColor.substr(1, 2), 16);
|
||||
var g = parseInt(hexColor.substr(3, 2), 16);
|
||||
var b = parseInt(hexColor.substr(5, 2), 16);
|
||||
var a = parseInt(hexColor.substr(7, 2), 16);
|
||||
|
||||
return [r, g, b, a / 255];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA to hex representation.
|
||||
* @param {number} r Amount of red, int between 0 and 255.
|
||||
* @param {number} g Amount of green, int between 0 and 255.
|
||||
* @param {number} b Amount of blue, int between 0 and 255.
|
||||
* @param {number} a Amount of alpha, float between 0 and 1.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.alpha.rgbaToHex = function(r, g, b, a) {
|
||||
var intAlpha = Math.floor(a * 255);
|
||||
if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
|
||||
// TODO(user): The CSS spec says the value should be clamped.
|
||||
throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
|
||||
'") is not a valid RGBA color');
|
||||
}
|
||||
var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
|
||||
return goog.color.rgbToHex(r, g, b) + hexA;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSLA to hex representation.
|
||||
* @param {number} h Amount of hue, int between 0 and 360.
|
||||
* @param {number} s Amount of saturation, int between 0 and 100.
|
||||
* @param {number} l Amount of lightness, int between 0 and 100.
|
||||
* @param {number} a Amount of alpha, float between 0 and 1.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.alpha.hslaToHex = function(h, s, l, a) {
|
||||
var intAlpha = Math.floor(a * 255);
|
||||
if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
|
||||
// TODO(user): The CSS spec says the value should be clamped.
|
||||
throw Error('"(' + h + ',' + s + ',' + l + ',' + a +
|
||||
'") is not a valid HSLA color');
|
||||
}
|
||||
var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
|
||||
return goog.color.hslToHex(h, s / 100, l / 100) + hexA;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA to hex representation.
|
||||
* @param {Array.<number>} rgba Array of [r, g, b, a], with r, g, b in [0, 255]
|
||||
* and a in [0, 1].
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.alpha.rgbaArrayToHex = function(rgba) {
|
||||
return goog.color.alpha.rgbaToHex(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA to an RGBA style string.
|
||||
* @param {number} r Value of red, in [0, 255].
|
||||
* @param {number} g Value of green, in [0, 255].
|
||||
* @param {number} b Value of blue, in [0, 255].
|
||||
* @param {number} a Value of alpha, in [0, 1].
|
||||
* @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
|
||||
*/
|
||||
goog.color.alpha.rgbaToRgbaStyle = function(r, g, b, a) {
|
||||
if (isNaN(r) || r < 0 || r > 255 ||
|
||||
isNaN(g) || g < 0 || g > 255 ||
|
||||
isNaN(b) || b < 0 || b > 255 ||
|
||||
isNaN(a) || a < 0 || a > 1) {
|
||||
throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
|
||||
')" is not a valid RGBA color');
|
||||
}
|
||||
return goog.color.alpha.rgbaStyle_([r, g, b, a]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA to an RGBA style string.
|
||||
* @param {(Array.<number>|Float32Array)} rgba Array of [r, g, b, a],
|
||||
* with r, g, b in [0, 255] and a in [0, 1].
|
||||
* @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
|
||||
*/
|
||||
goog.color.alpha.rgbaArrayToRgbaStyle = function(rgba) {
|
||||
return goog.color.alpha.rgbaToRgbaStyle(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSLA to hex representation.
|
||||
* @param {Array.<number>} hsla Array of [h, s, l, a], where h is an integer in
|
||||
* [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
|
||||
* @return {string} hex representation of the color, such as '#af457eff'.
|
||||
*/
|
||||
goog.color.alpha.hslaArrayToHex = function(hsla) {
|
||||
return goog.color.alpha.hslaToHex(hsla[0], hsla[1], hsla[2], hsla[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSLA to an RGBA style string.
|
||||
* @param {Array.<number>} hsla Array of [h, s, l, a], where h is and integer in
|
||||
* [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
|
||||
* @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
|
||||
*/
|
||||
goog.color.alpha.hslaArrayToRgbaStyle = function(hsla) {
|
||||
return goog.color.alpha.hslaToRgbaStyle(hsla[0], hsla[1], hsla[2], hsla[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSLA to an RGBA style string.
|
||||
* @param {number} h Amount of hue, int between 0 and 360.
|
||||
* @param {number} s Amount of saturation, int between 0 and 100.
|
||||
* @param {number} l Amount of lightness, int between 0 and 100.
|
||||
* @param {number} a Amount of alpha, float between 0 and 1.
|
||||
* @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
|
||||
* styles.
|
||||
*/
|
||||
goog.color.alpha.hslaToRgbaStyle = function(h, s, l, a) {
|
||||
return goog.color.alpha.rgbaStyle_(goog.color.alpha.hslaToRgba(h, s, l, a));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSLA color space to RGBA color space.
|
||||
* @param {number} h Amount of hue, int between 0 and 360.
|
||||
* @param {number} s Amount of saturation, int between 0 and 100.
|
||||
* @param {number} l Amount of lightness, int between 0 and 100.
|
||||
* @param {number} a Amount of alpha, float between 0 and 1.
|
||||
* @return {Array.<number>} [r, g, b, a] values for the color, where r, g, b
|
||||
* are integers in [0, 255] and a is a float in [0, 1].
|
||||
*/
|
||||
goog.color.alpha.hslaToRgba = function(h, s, l, a) {
|
||||
return goog.color.hslToRgb(h, s / 100, l / 100).concat(a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA color space to HSLA color space.
|
||||
* Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
|
||||
* @param {number} r Value of red, in [0, 255].
|
||||
* @param {number} g Value of green, in [0, 255].
|
||||
* @param {number} b Value of blue, in [0, 255].
|
||||
* @param {number} a Value of alpha, in [0, 255].
|
||||
* @return {Array.<number>} [h, s, l, a] values for the color, with h an int in
|
||||
* [0, 360] and s, l and a in [0, 1].
|
||||
*/
|
||||
goog.color.alpha.rgbaToHsla = function(r, g, b, a) {
|
||||
return goog.color.rgbToHsl(r, g, b).concat(a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGBA color space to HSLA color space.
|
||||
* @param {Array.<number>} rgba [r, g, b, a] values for the color, each in
|
||||
* [0, 255].
|
||||
* @return {Array.<number>} [h, s, l, a] values for the color, with h in
|
||||
* [0, 360] and s, l and a in [0, 1].
|
||||
*/
|
||||
goog.color.alpha.rgbaArrayToHsla = function(rgba) {
|
||||
return goog.color.alpha.rgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for isValidAlphaHexColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.validAlphaHexColorRe_ = /^#(?:[0-9a-f]{4}){1,2}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a valid alpha hex color. We expect strings of the
|
||||
* format #RRGGBBAA (ex: #1b3d5f5b) or #RGBA (ex: #3CAF == #33CCAAFF).
|
||||
* @param {string} str String to check.
|
||||
* @return {boolean} Whether the string is a valid alpha hex color.
|
||||
* @private
|
||||
*/
|
||||
// TODO(user): Support percentages when goog.color also supports them.
|
||||
goog.color.alpha.isValidAlphaHexColor_ = function(str) {
|
||||
return goog.color.alpha.validAlphaHexColorRe_.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for isNormalizedAlphaHexColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.normalizedAlphaHexColorRe_ = /^#[0-9a-f]{8}$/;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a normalized alpha hex color.
|
||||
* We expect strings of the format #RRGGBBAA (ex: #1b3d5f5b)
|
||||
* using only lowercase letters.
|
||||
* @param {string} str String to check.
|
||||
* @return {boolean} Whether the string is a normalized hex color.
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.isNormalizedAlphaHexColor_ = function(str) {
|
||||
return goog.color.alpha.normalizedAlphaHexColorRe_.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for matching and capturing RGBA style strings. Helper for
|
||||
* isValidRgbaColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.rgbaColorRe_ =
|
||||
/^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for matching and capturing HSLA style strings. Helper for
|
||||
* isValidHslaColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.hslaColorRe_ =
|
||||
/^(?:hsla)\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\%,\s?(0|[1-9]\d{0,2})\%,\s?(0|1|0\.\d{0,10})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a valid rgba color. We expect strings of the format
|
||||
* '(r, g, b, a)', or 'rgba(r, g, b, a)', where r, g, b are ints in [0, 255]
|
||||
* and a is a float in [0, 1].
|
||||
* @param {string} str String to check.
|
||||
* @return {Array.<number>} the integers [r, g, b, a] for valid colors or the
|
||||
* empty array for invalid colors.
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.isValidRgbaColor_ = function(str) {
|
||||
// Each component is separate (rather than using a repeater) so we can
|
||||
// capture the match. Also, we explicitly set each component to be either 0,
|
||||
// or start with a non-zero, to prevent octal numbers from slipping through.
|
||||
var regExpResultArray = str.match(goog.color.alpha.rgbaColorRe_);
|
||||
if (regExpResultArray) {
|
||||
var r = Number(regExpResultArray[1]);
|
||||
var g = Number(regExpResultArray[2]);
|
||||
var b = Number(regExpResultArray[3]);
|
||||
var a = Number(regExpResultArray[4]);
|
||||
if (r >= 0 && r <= 255 &&
|
||||
g >= 0 && g <= 255 &&
|
||||
b >= 0 && b <= 255 &&
|
||||
a >= 0 && a <= 1) {
|
||||
return [r, g, b, a];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a valid hsla color. We expect strings of the format
|
||||
* 'hsla(h, s, l, a)', where s in an int in [0, 360], s and l are percentages
|
||||
* between 0 and 100 such as '50%' or '70%', and a is a float in [0, 1].
|
||||
* @param {string} str String to check.
|
||||
* @return {Array.<number>} the integers [h, s, l, a] for valid colors or the
|
||||
* empty array for invalid colors.
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.isValidHslaColor_ = function(str) {
|
||||
// Each component is separate (rather than using a repeater) so we can
|
||||
// capture the match. Also, we explicitly set each component to be either 0,
|
||||
// or start with a non-zero, to prevent octal numbers from slipping through.
|
||||
var regExpResultArray = str.match(goog.color.alpha.hslaColorRe_);
|
||||
if (regExpResultArray) {
|
||||
var h = Number(regExpResultArray[1]);
|
||||
var s = Number(regExpResultArray[2]);
|
||||
var l = Number(regExpResultArray[3]);
|
||||
var a = Number(regExpResultArray[4]);
|
||||
if (h >= 0 && h <= 360 &&
|
||||
s >= 0 && s <= 100 &&
|
||||
l >= 0 && l <= 100 &&
|
||||
a >= 0 && a <= 1) {
|
||||
return [h, s, l, a];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Takes an array of [r, g, b, a] and converts it into a string appropriate for
|
||||
* CSS styles.
|
||||
* @param {Array.<number>} rgba [r, g, b, a] with r, g, b in [0, 255] and a
|
||||
* in [0, 1].
|
||||
* @return {string} string of the form 'rgba(r,g,b,a)'.
|
||||
* @private
|
||||
*/
|
||||
goog.color.alpha.rgbaStyle_ = function(rgba) {
|
||||
return 'rgba(' + rgba.join(',') + ')';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from h,s,v,a values to a hex string
|
||||
* @param {number} h Hue, in [0, 1].
|
||||
* @param {number} s Saturation, in [0, 1].
|
||||
* @param {number} v Value, in [0, 255].
|
||||
* @param {number} a Alpha, in [0, 1].
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.alpha.hsvaToHex = function(h, s, v, a) {
|
||||
var alpha = Math.floor(a * 255);
|
||||
return goog.color.hsvArrayToHex([h, s, v]) +
|
||||
goog.color.prependZeroIfNecessaryHelper(alpha.toString(16));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from an HSVA array to a hex string
|
||||
* @param {Array} hsva Array of [h, s, v, a] in
|
||||
* [[0, 1], [0, 1], [0, 255], [0, 1]].
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.alpha.hsvaArrayToHex = function(hsva) {
|
||||
return goog.color.alpha.hsvaToHex(hsva[0], hsva[1], hsva[2], hsva[3]);
|
||||
};
|
||||
773
float-no-zero/closure-library/closure/goog/color/color.js
Normal file
773
float-no-zero/closure-library/closure/goog/color/color.js
Normal file
@@ -0,0 +1,773 @@
|
||||
// Copyright 2006 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 Utilities related to color and color conversion.
|
||||
*/
|
||||
|
||||
goog.provide('goog.color');
|
||||
|
||||
goog.require('goog.color.names');
|
||||
goog.require('goog.math');
|
||||
|
||||
|
||||
/**
|
||||
* RGB color representation. An array containing three elements [r, g, b],
|
||||
* each an integer in [0, 255], representing the red, green, and blue components
|
||||
* of the color respectively.
|
||||
* @typedef {Array.<number>}
|
||||
*/
|
||||
goog.color.Rgb;
|
||||
|
||||
|
||||
/**
|
||||
* HSV color representation. An array containing three elements [h, s, v]:
|
||||
* h (hue) must be an integer in [0, 360], cyclic.
|
||||
* s (saturation) must be a number in [0, 1].
|
||||
* v (value/brightness) must be an integer in [0, 255].
|
||||
* @typedef {Array.<number>}
|
||||
*/
|
||||
goog.color.Hsv;
|
||||
|
||||
|
||||
/**
|
||||
* HSL color representation. An array containing three elements [h, s, l]:
|
||||
* h (hue) must be an integer in [0, 360], cyclic.
|
||||
* s (saturation) must be a number in [0, 1].
|
||||
* l (lightness) must be a number in [0, 1].
|
||||
* @typedef {Array.<number>}
|
||||
*/
|
||||
goog.color.Hsl;
|
||||
|
||||
|
||||
/**
|
||||
* Parses a color out of a string.
|
||||
* @param {string} str Color in some format.
|
||||
* @return {Object} Contains two properties: 'hex', which is a string containing
|
||||
* a hex representation of the color, as well as 'type', which is a string
|
||||
* containing the type of color format passed in ('hex', 'rgb', 'named').
|
||||
*/
|
||||
goog.color.parse = function(str) {
|
||||
var result = {};
|
||||
str = String(str);
|
||||
|
||||
var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
|
||||
if (goog.color.isValidHexColor_(maybeHex)) {
|
||||
result.hex = goog.color.normalizeHex(maybeHex);
|
||||
result.type = 'hex';
|
||||
return result;
|
||||
} else {
|
||||
var rgb = goog.color.isValidRgbColor_(str);
|
||||
if (rgb.length) {
|
||||
result.hex = goog.color.rgbArrayToHex(rgb);
|
||||
result.type = 'rgb';
|
||||
return result;
|
||||
} else if (goog.color.names) {
|
||||
var hex = goog.color.names[str.toLowerCase()];
|
||||
if (hex) {
|
||||
result.hex = hex;
|
||||
result.type = 'named';
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Error(str + ' is not a valid color string');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines if the given string can be parsed as a color.
|
||||
* {@see goog.color.parse}.
|
||||
* @param {string} str Potential color string.
|
||||
* @return {boolean} True if str is in a format that can be parsed to a color.
|
||||
*/
|
||||
goog.color.isValidColor = function(str) {
|
||||
var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
|
||||
return !!(goog.color.isValidHexColor_(maybeHex) ||
|
||||
goog.color.isValidRgbColor_(str).length ||
|
||||
goog.color.names && goog.color.names[str.toLowerCase()]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parses red, green, blue components out of a valid rgb color string.
|
||||
* Throws Error if the color string is invalid.
|
||||
* @param {string} str RGB representation of a color.
|
||||
* {@see goog.color.isValidRgbColor_}.
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.parseRgb = function(str) {
|
||||
var rgb = goog.color.isValidRgbColor_(str);
|
||||
if (!rgb.length) {
|
||||
throw Error(str + ' is not a valid RGB color');
|
||||
}
|
||||
return rgb;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex representation of a color to RGB.
|
||||
* @param {string} hexColor Color to convert.
|
||||
* @return {string} string of the form 'rgb(R,G,B)' which can be used in
|
||||
* styles.
|
||||
*/
|
||||
goog.color.hexToRgbStyle = function(hexColor) {
|
||||
return goog.color.rgbStyle_(goog.color.hexToRgb(hexColor));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for extracting the digits in a hex color triplet.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.hexTripletRe_ = /#(.)(.)(.)/;
|
||||
|
||||
|
||||
/**
|
||||
* Normalize an hex representation of a color
|
||||
* @param {string} hexColor an hex color string.
|
||||
* @return {string} hex color in the format '#rrggbb' with all lowercase
|
||||
* literals.
|
||||
*/
|
||||
goog.color.normalizeHex = function(hexColor) {
|
||||
if (!goog.color.isValidHexColor_(hexColor)) {
|
||||
throw Error("'" + hexColor + "' is not a valid hex color");
|
||||
}
|
||||
if (hexColor.length == 4) { // of the form #RGB
|
||||
hexColor = hexColor.replace(goog.color.hexTripletRe_, '#$1$1$2$2$3$3');
|
||||
}
|
||||
return hexColor.toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex representation of a color to RGB.
|
||||
* @param {string} hexColor Color to convert.
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.hexToRgb = function(hexColor) {
|
||||
hexColor = goog.color.normalizeHex(hexColor);
|
||||
var r = parseInt(hexColor.substr(1, 2), 16);
|
||||
var g = parseInt(hexColor.substr(3, 2), 16);
|
||||
var b = parseInt(hexColor.substr(5, 2), 16);
|
||||
|
||||
return [r, g, b];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGB to hex representation.
|
||||
* @param {number} r Amount of red, int between 0 and 255.
|
||||
* @param {number} g Amount of green, int between 0 and 255.
|
||||
* @param {number} b Amount of blue, int between 0 and 255.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.rgbToHex = function(r, g, b) {
|
||||
r = Number(r);
|
||||
g = Number(g);
|
||||
b = Number(b);
|
||||
if (isNaN(r) || r < 0 || r > 255 ||
|
||||
isNaN(g) || g < 0 || g > 255 ||
|
||||
isNaN(b) || b < 0 || b > 255) {
|
||||
throw Error('"(' + r + ',' + g + ',' + b + '") is not a valid RGB color');
|
||||
}
|
||||
var hexR = goog.color.prependZeroIfNecessaryHelper(r.toString(16));
|
||||
var hexG = goog.color.prependZeroIfNecessaryHelper(g.toString(16));
|
||||
var hexB = goog.color.prependZeroIfNecessaryHelper(b.toString(16));
|
||||
return '#' + hexR + hexG + hexB;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGB to hex representation.
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.rgbArrayToHex = function(rgb) {
|
||||
return goog.color.rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGB color space to HSL color space.
|
||||
* Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
|
||||
* @param {number} r Value of red, in [0, 255].
|
||||
* @param {number} g Value of green, in [0, 255].
|
||||
* @param {number} b Value of blue, in [0, 255].
|
||||
* @return {!goog.color.Hsl} hsl representation of the color.
|
||||
*/
|
||||
goog.color.rgbToHsl = function(r, g, b) {
|
||||
// First must normalize r, g, b to be between 0 and 1.
|
||||
var normR = r / 255;
|
||||
var normG = g / 255;
|
||||
var normB = b / 255;
|
||||
var max = Math.max(normR, normG, normB);
|
||||
var min = Math.min(normR, normG, normB);
|
||||
var h = 0;
|
||||
var s = 0;
|
||||
|
||||
// Luminosity is the average of the max and min rgb color intensities.
|
||||
var l = 0.5 * (max + min);
|
||||
|
||||
// The hue and saturation are dependent on which color intensity is the max.
|
||||
// If max and min are equal, the color is gray and h and s should be 0.
|
||||
if (max != min) {
|
||||
if (max == normR) {
|
||||
h = 60 * (normG - normB) / (max - min);
|
||||
} else if (max == normG) {
|
||||
h = 60 * (normB - normR) / (max - min) + 120;
|
||||
} else if (max == normB) {
|
||||
h = 60 * (normR - normG) / (max - min) + 240;
|
||||
}
|
||||
|
||||
if (0 < l && l <= 0.5) {
|
||||
s = (max - min) / (2 * l);
|
||||
} else {
|
||||
s = (max - min) / (2 - 2 * l);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the hue falls between 0 and 360.
|
||||
return [Math.round(h + 360) % 360, s, l];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from RGB color space to HSL color space.
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @return {!goog.color.Hsl} hsl representation of the color.
|
||||
*/
|
||||
goog.color.rgbArrayToHsl = function(rgb) {
|
||||
return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for hslToRgb.
|
||||
* @param {number} v1 Helper variable 1.
|
||||
* @param {number} v2 Helper variable 2.
|
||||
* @param {number} vH Helper variable 3.
|
||||
* @return {number} Appropriate RGB value, given the above.
|
||||
* @private
|
||||
*/
|
||||
goog.color.hueToRgb_ = function(v1, v2, vH) {
|
||||
if (vH < 0) {
|
||||
vH += 1;
|
||||
} else if (vH > 1) {
|
||||
vH -= 1;
|
||||
}
|
||||
if ((6 * vH) < 1) {
|
||||
return (v1 + (v2 - v1) * 6 * vH);
|
||||
} else if (2 * vH < 1) {
|
||||
return v2;
|
||||
} else if (3 * vH < 2) {
|
||||
return (v1 + (v2 - v1) * ((2 / 3) - vH) * 6);
|
||||
}
|
||||
return v1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSL color space to RGB color space.
|
||||
* Modified from {@link http://www.easyrgb.com/math.html}
|
||||
* @param {number} h Hue, in [0, 360].
|
||||
* @param {number} s Saturation, in [0, 1].
|
||||
* @param {number} l Luminosity, in [0, 1].
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.hslToRgb = function(h, s, l) {
|
||||
var r = 0;
|
||||
var g = 0;
|
||||
var b = 0;
|
||||
var normH = h / 360; // normalize h to fall in [0, 1]
|
||||
|
||||
if (s == 0) {
|
||||
r = g = b = l * 255;
|
||||
} else {
|
||||
var temp1 = 0;
|
||||
var temp2 = 0;
|
||||
if (l < 0.5) {
|
||||
temp2 = l * (1 + s);
|
||||
} else {
|
||||
temp2 = l + s - (s * l);
|
||||
}
|
||||
temp1 = 2 * l - temp2;
|
||||
r = 255 * goog.color.hueToRgb_(temp1, temp2, normH + (1 / 3));
|
||||
g = 255 * goog.color.hueToRgb_(temp1, temp2, normH);
|
||||
b = 255 * goog.color.hueToRgb_(temp1, temp2, normH - (1 / 3));
|
||||
}
|
||||
|
||||
return [Math.round(r), Math.round(g), Math.round(b)];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a color from HSL color space to RGB color space.
|
||||
* @param {goog.color.Hsl} hsl hsl representation of the color.
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.hslArrayToRgb = function(hsl) {
|
||||
return goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for isValidHexColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.validHexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a valid hex color. We expect strings of the format
|
||||
* #RRGGBB (ex: #1b3d5f) or #RGB (ex: #3CA == #33CCAA).
|
||||
* @param {string} str String to check.
|
||||
* @return {boolean} Whether the string is a valid hex color.
|
||||
* @private
|
||||
*/
|
||||
goog.color.isValidHexColor_ = function(str) {
|
||||
return goog.color.validHexColorRe_.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for isNormalizedHexColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.normalizedHexColorRe_ = /^#[0-9a-f]{6}$/;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a normalized hex color.
|
||||
* We expect strings of the format #RRGGBB (ex: #1b3d5f)
|
||||
* using only lowercase letters.
|
||||
* @param {string} str String to check.
|
||||
* @return {boolean} Whether the string is a normalized hex color.
|
||||
* @private
|
||||
*/
|
||||
goog.color.isNormalizedHexColor_ = function(str) {
|
||||
return goog.color.normalizedHexColorRe_.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for matching and capturing RGB style strings. Helper for
|
||||
* isValidRgbColor_.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.color.rgbColorRe_ =
|
||||
/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a string is a valid rgb color. We expect strings of the format
|
||||
* '(r, g, b)', or 'rgb(r, g, b)', where each color component is an int in
|
||||
* [0, 255].
|
||||
* @param {string} str String to check.
|
||||
* @return {!goog.color.Rgb} the rgb representation of the color if it is
|
||||
* a valid color, or the empty array otherwise.
|
||||
* @private
|
||||
*/
|
||||
goog.color.isValidRgbColor_ = function(str) {
|
||||
// Each component is separate (rather than using a repeater) so we can
|
||||
// capture the match. Also, we explicitly set each component to be either 0,
|
||||
// or start with a non-zero, to prevent octal numbers from slipping through.
|
||||
var regExpResultArray = str.match(goog.color.rgbColorRe_);
|
||||
if (regExpResultArray) {
|
||||
var r = Number(regExpResultArray[1]);
|
||||
var g = Number(regExpResultArray[2]);
|
||||
var b = Number(regExpResultArray[3]);
|
||||
if (r >= 0 && r <= 255 &&
|
||||
g >= 0 && g <= 255 &&
|
||||
b >= 0 && b <= 255) {
|
||||
return [r, g, b];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Takes a hex value and prepends a zero if it's a single digit.
|
||||
* Small helper method for use by goog.color and friends.
|
||||
* @param {string} hex Hex value to prepend if single digit.
|
||||
* @return {string} hex value prepended with zero if it was single digit,
|
||||
* otherwise the same value that was passed in.
|
||||
*/
|
||||
goog.color.prependZeroIfNecessaryHelper = function(hex) {
|
||||
return hex.length == 1 ? '0' + hex : hex;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Takes a string a prepends a '#' sign if one doesn't exist.
|
||||
* Small helper method for use by goog.color and friends.
|
||||
* @param {string} str String to check.
|
||||
* @return {string} The value passed in, prepended with a '#' if it didn't
|
||||
* already have one.
|
||||
*/
|
||||
goog.color.prependHashIfNecessaryHelper = function(str) {
|
||||
return str.charAt(0) == '#' ? str : '#' + str;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Takes an array of [r, g, b] and converts it into a string appropriate for
|
||||
* CSS styles.
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @return {string} string of the form 'rgb(r,g,b)'.
|
||||
* @private
|
||||
*/
|
||||
goog.color.rgbStyle_ = function(rgb) {
|
||||
return 'rgb(' + rgb.join(',') + ')';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an HSV triplet to an RGB array. V is brightness because b is
|
||||
* reserved for blue in RGB.
|
||||
* @param {number} h Hue value in [0, 360].
|
||||
* @param {number} s Saturation value in [0, 1].
|
||||
* @param {number} brightness brightness in [0, 255].
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.hsvToRgb = function(h, s, brightness) {
|
||||
var red = 0;
|
||||
var green = 0;
|
||||
var blue = 0;
|
||||
if (s == 0) {
|
||||
red = brightness;
|
||||
green = brightness;
|
||||
blue = brightness;
|
||||
} else {
|
||||
var sextant = Math.floor(h / 60);
|
||||
var remainder = (h / 60) - sextant;
|
||||
var val1 = brightness * (1 - s);
|
||||
var val2 = brightness * (1 - (s * remainder));
|
||||
var val3 = brightness * (1 - (s * (1 - remainder)));
|
||||
switch (sextant) {
|
||||
case 1:
|
||||
red = val2;
|
||||
green = brightness;
|
||||
blue = val1;
|
||||
break;
|
||||
case 2:
|
||||
red = val1;
|
||||
green = brightness;
|
||||
blue = val3;
|
||||
break;
|
||||
case 3:
|
||||
red = val1;
|
||||
green = val2;
|
||||
blue = brightness;
|
||||
break;
|
||||
case 4:
|
||||
red = val3;
|
||||
green = val1;
|
||||
blue = brightness;
|
||||
break;
|
||||
case 5:
|
||||
red = brightness;
|
||||
green = val1;
|
||||
blue = val2;
|
||||
break;
|
||||
case 6:
|
||||
case 0:
|
||||
red = brightness;
|
||||
green = val3;
|
||||
blue = val1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [Math.floor(red), Math.floor(green), Math.floor(blue)];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from RGB values to an array of HSV values.
|
||||
* @param {number} red Red value in [0, 255].
|
||||
* @param {number} green Green value in [0, 255].
|
||||
* @param {number} blue Blue value in [0, 255].
|
||||
* @return {!goog.color.Hsv} hsv representation of the color.
|
||||
*/
|
||||
goog.color.rgbToHsv = function(red, green, blue) {
|
||||
|
||||
var max = Math.max(Math.max(red, green), blue);
|
||||
var min = Math.min(Math.min(red, green), blue);
|
||||
var hue;
|
||||
var saturation;
|
||||
var value = max;
|
||||
if (min == max) {
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
} else {
|
||||
var delta = (max - min);
|
||||
saturation = delta / max;
|
||||
|
||||
if (red == max) {
|
||||
hue = (green - blue) / delta;
|
||||
} else if (green == max) {
|
||||
hue = 2 + ((blue - red) / delta);
|
||||
} else {
|
||||
hue = 4 + ((red - green) / delta);
|
||||
}
|
||||
hue *= 60;
|
||||
if (hue < 0) {
|
||||
hue += 360;
|
||||
}
|
||||
if (hue > 360) {
|
||||
hue -= 360;
|
||||
}
|
||||
}
|
||||
|
||||
return [hue, saturation, value];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from an array of RGB values to an array of HSV values.
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @return {!goog.color.Hsv} hsv representation of the color.
|
||||
*/
|
||||
goog.color.rgbArrayToHsv = function(rgb) {
|
||||
return goog.color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an HSV triplet to an RGB array.
|
||||
* @param {goog.color.Hsv} hsv hsv representation of the color.
|
||||
* @return {!goog.color.Rgb} rgb representation of the color.
|
||||
*/
|
||||
goog.color.hsvArrayToRgb = function(hsv) {
|
||||
return goog.color.hsvToRgb(hsv[0], hsv[1], hsv[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex representation of a color to HSL.
|
||||
* @param {string} hex Color to convert.
|
||||
* @return {!goog.color.Hsv} hsv representation of the color.
|
||||
*/
|
||||
goog.color.hexToHsl = function(hex) {
|
||||
var rgb = goog.color.hexToRgb(hex);
|
||||
return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from h,s,l values to a hex string
|
||||
* @param {number} h Hue, in [0, 360].
|
||||
* @param {number} s Saturation, in [0, 1].
|
||||
* @param {number} l Luminosity, in [0, 1].
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.hslToHex = function(h, s, l) {
|
||||
return goog.color.rgbArrayToHex(goog.color.hslToRgb(h, s, l));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from an hsl array to a hex string
|
||||
* @param {goog.color.Hsl} hsl hsl representation of the color.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.hslArrayToHex = function(hsl) {
|
||||
return goog.color.rgbArrayToHex(goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex representation of a color to HSV
|
||||
* @param {string} hex Color to convert.
|
||||
* @return {!goog.color.Hsv} hsv representation of the color.
|
||||
*/
|
||||
goog.color.hexToHsv = function(hex) {
|
||||
return goog.color.rgbArrayToHsv(goog.color.hexToRgb(hex));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from h,s,v values to a hex string
|
||||
* @param {number} h Hue, in [0, 360].
|
||||
* @param {number} s Saturation, in [0, 1].
|
||||
* @param {number} v Value, in [0, 255].
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.hsvToHex = function(h, s, v) {
|
||||
return goog.color.rgbArrayToHex(goog.color.hsvToRgb(h, s, v));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts from an HSV array to a hex string
|
||||
* @param {goog.color.Hsv} hsv hsv representation of the color.
|
||||
* @return {string} hex representation of the color.
|
||||
*/
|
||||
goog.color.hsvArrayToHex = function(hsv) {
|
||||
return goog.color.hsvToHex(hsv[0], hsv[1], hsv[2]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Euclidean distance between two color vectors on an HSL sphere.
|
||||
* A demo of the sphere can be found at:
|
||||
* http://en.wikipedia.org/wiki/HSL_color_space
|
||||
* In short, a vector for color (H, S, L) in this system can be expressed as
|
||||
* (S*L'*cos(2*PI*H), S*L'*sin(2*PI*H), L), where L' = abs(L - 0.5), and we
|
||||
* simply calculate the 1-2 distance using these coordinates
|
||||
* @param {goog.color.Hsl} hsl1 First color in hsl representation.
|
||||
* @param {goog.color.Hsl} hsl2 Second color in hsl representation.
|
||||
* @return {number} Distance between the two colors, in the range [0, 1].
|
||||
*/
|
||||
goog.color.hslDistance = function(hsl1, hsl2) {
|
||||
var sl1, sl2;
|
||||
if (hsl1[2] <= 0.5) {
|
||||
sl1 = hsl1[1] * hsl1[2];
|
||||
} else {
|
||||
sl1 = hsl1[1] * (1.0 - hsl1[2]);
|
||||
}
|
||||
|
||||
if (hsl2[2] <= 0.5) {
|
||||
sl2 = hsl2[1] * hsl2[2];
|
||||
} else {
|
||||
sl2 = hsl2[1] * (1.0 - hsl2[2]);
|
||||
}
|
||||
|
||||
var h1 = hsl1[0] / 360.0;
|
||||
var h2 = hsl2[0] / 360.0;
|
||||
var dh = (h1 - h2) * 2.0 * Math.PI;
|
||||
return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) +
|
||||
sl1 * sl1 + sl2 * sl2 - 2 * sl1 * sl2 * Math.cos(dh);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Blend two colors together, using the specified factor to indicate the weight
|
||||
* given to the first color
|
||||
* @param {goog.color.Rgb} rgb1 First color represented in rgb.
|
||||
* @param {goog.color.Rgb} rgb2 Second color represented in rgb.
|
||||
* @param {number} factor The weight to be given to rgb1 over rgb2. Values
|
||||
* should be in the range [0, 1]. If less than 0, factor will be set to 0.
|
||||
* If greater than 1, factor will be set to 1.
|
||||
* @return {!goog.color.Rgb} Combined color represented in rgb.
|
||||
*/
|
||||
goog.color.blend = function(rgb1, rgb2, factor) {
|
||||
factor = goog.math.clamp(factor, 0, 1);
|
||||
|
||||
return [
|
||||
Math.round(factor * rgb1[0] + (1.0 - factor) * rgb2[0]),
|
||||
Math.round(factor * rgb1[1] + (1.0 - factor) * rgb2[1]),
|
||||
Math.round(factor * rgb1[2] + (1.0 - factor) * rgb2[2])
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds black to the specified color, darkening it
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @param {number} factor Number in the range [0, 1]. 0 will do nothing, while
|
||||
* 1 will return black. If less than 0, factor will be set to 0. If greater
|
||||
* than 1, factor will be set to 1.
|
||||
* @return {!goog.color.Rgb} Combined rgb color.
|
||||
*/
|
||||
goog.color.darken = function(rgb, factor) {
|
||||
var black = [0, 0, 0];
|
||||
return goog.color.blend(black, rgb, factor);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds white to the specified color, lightening it
|
||||
* @param {goog.color.Rgb} rgb rgb representation of the color.
|
||||
* @param {number} factor Number in the range [0, 1]. 0 will do nothing, while
|
||||
* 1 will return white. If less than 0, factor will be set to 0. If greater
|
||||
* than 1, factor will be set to 1.
|
||||
* @return {!goog.color.Rgb} Combined rgb color.
|
||||
*/
|
||||
goog.color.lighten = function(rgb, factor) {
|
||||
var white = [255, 255, 255];
|
||||
return goog.color.blend(white, rgb, factor);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find the "best" (highest-contrast) of the suggested colors for the prime
|
||||
* color. Uses W3C formula for judging readability and visual accessibility:
|
||||
* http://www.w3.org/TR/AERT#color-contrast
|
||||
* @param {goog.color.Rgb} prime Color represented as a rgb array.
|
||||
* @param {Array.<goog.color.Rgb>} suggestions Array of colors,
|
||||
* each representing a rgb array.
|
||||
* @return {!goog.color.Rgb} Highest-contrast color represented by an array..
|
||||
*/
|
||||
goog.color.highContrast = function(prime, suggestions) {
|
||||
var suggestionsWithDiff = [];
|
||||
for (var i = 0; i < suggestions.length; i++) {
|
||||
suggestionsWithDiff.push({
|
||||
color: suggestions[i],
|
||||
diff: goog.color.yiqBrightnessDiff_(suggestions[i], prime) +
|
||||
goog.color.colorDiff_(suggestions[i], prime)
|
||||
});
|
||||
}
|
||||
suggestionsWithDiff.sort(function(a, b) {
|
||||
return b.diff - a.diff;
|
||||
});
|
||||
return suggestionsWithDiff[0].color;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate brightness of a color according to YIQ formula (brightness is Y).
|
||||
* More info on YIQ here: http://en.wikipedia.org/wiki/YIQ. Helper method for
|
||||
* goog.color.highContrast()
|
||||
* @param {goog.color.Rgb} rgb Color represented by a rgb array.
|
||||
* @return {number} brightness (Y).
|
||||
* @private
|
||||
*/
|
||||
goog.color.yiqBrightness_ = function(rgb) {
|
||||
return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate difference in brightness of two colors. Helper method for
|
||||
* goog.color.highContrast()
|
||||
* @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
|
||||
* @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
|
||||
* @return {number} Brightness difference.
|
||||
* @private
|
||||
*/
|
||||
goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
|
||||
return Math.abs(goog.color.yiqBrightness_(rgb1) -
|
||||
goog.color.yiqBrightness_(rgb2));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate color difference between two colors. Helper method for
|
||||
* goog.color.highContrast()
|
||||
* @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
|
||||
* @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
|
||||
* @return {number} Color difference.
|
||||
* @private
|
||||
*/
|
||||
goog.color.colorDiff_ = function(rgb1, rgb2) {
|
||||
return Math.abs(rgb1[0] - rgb2[0]) + Math.abs(rgb1[1] - rgb2[1]) +
|
||||
Math.abs(rgb1[2] - rgb2[2]);
|
||||
};
|
||||
176
float-no-zero/closure-library/closure/goog/color/names.js
Normal file
176
float-no-zero/closure-library/closure/goog/color/names.js
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2006 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 Names of standard colors with their associated hex values.
|
||||
*/
|
||||
|
||||
goog.provide('goog.color.names');
|
||||
|
||||
|
||||
/**
|
||||
* A map that contains a lot of colors that are recognised by various browsers.
|
||||
* This list is way larger than the minimal one dictated by W3C.
|
||||
* The keys of this map are the lowercase "readable" names of the colors, while
|
||||
* the values are the "hex" values.
|
||||
*/
|
||||
goog.color.names = {
|
||||
'aliceblue': '#f0f8ff',
|
||||
'antiquewhite': '#faebd7',
|
||||
'aqua': '#00ffff',
|
||||
'aquamarine': '#7fffd4',
|
||||
'azure': '#f0ffff',
|
||||
'beige': '#f5f5dc',
|
||||
'bisque': '#ffe4c4',
|
||||
'black': '#000000',
|
||||
'blanchedalmond': '#ffebcd',
|
||||
'blue': '#0000ff',
|
||||
'blueviolet': '#8a2be2',
|
||||
'brown': '#a52a2a',
|
||||
'burlywood': '#deb887',
|
||||
'cadetblue': '#5f9ea0',
|
||||
'chartreuse': '#7fff00',
|
||||
'chocolate': '#d2691e',
|
||||
'coral': '#ff7f50',
|
||||
'cornflowerblue': '#6495ed',
|
||||
'cornsilk': '#fff8dc',
|
||||
'crimson': '#dc143c',
|
||||
'cyan': '#00ffff',
|
||||
'darkblue': '#00008b',
|
||||
'darkcyan': '#008b8b',
|
||||
'darkgoldenrod': '#b8860b',
|
||||
'darkgray': '#a9a9a9',
|
||||
'darkgreen': '#006400',
|
||||
'darkgrey': '#a9a9a9',
|
||||
'darkkhaki': '#bdb76b',
|
||||
'darkmagenta': '#8b008b',
|
||||
'darkolivegreen': '#556b2f',
|
||||
'darkorange': '#ff8c00',
|
||||
'darkorchid': '#9932cc',
|
||||
'darkred': '#8b0000',
|
||||
'darksalmon': '#e9967a',
|
||||
'darkseagreen': '#8fbc8f',
|
||||
'darkslateblue': '#483d8b',
|
||||
'darkslategray': '#2f4f4f',
|
||||
'darkslategrey': '#2f4f4f',
|
||||
'darkturquoise': '#00ced1',
|
||||
'darkviolet': '#9400d3',
|
||||
'deeppink': '#ff1493',
|
||||
'deepskyblue': '#00bfff',
|
||||
'dimgray': '#696969',
|
||||
'dimgrey': '#696969',
|
||||
'dodgerblue': '#1e90ff',
|
||||
'firebrick': '#b22222',
|
||||
'floralwhite': '#fffaf0',
|
||||
'forestgreen': '#228b22',
|
||||
'fuchsia': '#ff00ff',
|
||||
'gainsboro': '#dcdcdc',
|
||||
'ghostwhite': '#f8f8ff',
|
||||
'gold': '#ffd700',
|
||||
'goldenrod': '#daa520',
|
||||
'gray': '#808080',
|
||||
'green': '#008000',
|
||||
'greenyellow': '#adff2f',
|
||||
'grey': '#808080',
|
||||
'honeydew': '#f0fff0',
|
||||
'hotpink': '#ff69b4',
|
||||
'indianred': '#cd5c5c',
|
||||
'indigo': '#4b0082',
|
||||
'ivory': '#fffff0',
|
||||
'khaki': '#f0e68c',
|
||||
'lavender': '#e6e6fa',
|
||||
'lavenderblush': '#fff0f5',
|
||||
'lawngreen': '#7cfc00',
|
||||
'lemonchiffon': '#fffacd',
|
||||
'lightblue': '#add8e6',
|
||||
'lightcoral': '#f08080',
|
||||
'lightcyan': '#e0ffff',
|
||||
'lightgoldenrodyellow': '#fafad2',
|
||||
'lightgray': '#d3d3d3',
|
||||
'lightgreen': '#90ee90',
|
||||
'lightgrey': '#d3d3d3',
|
||||
'lightpink': '#ffb6c1',
|
||||
'lightsalmon': '#ffa07a',
|
||||
'lightseagreen': '#20b2aa',
|
||||
'lightskyblue': '#87cefa',
|
||||
'lightslategray': '#778899',
|
||||
'lightslategrey': '#778899',
|
||||
'lightsteelblue': '#b0c4de',
|
||||
'lightyellow': '#ffffe0',
|
||||
'lime': '#00ff00',
|
||||
'limegreen': '#32cd32',
|
||||
'linen': '#faf0e6',
|
||||
'magenta': '#ff00ff',
|
||||
'maroon': '#800000',
|
||||
'mediumaquamarine': '#66cdaa',
|
||||
'mediumblue': '#0000cd',
|
||||
'mediumorchid': '#ba55d3',
|
||||
'mediumpurple': '#9370db',
|
||||
'mediumseagreen': '#3cb371',
|
||||
'mediumslateblue': '#7b68ee',
|
||||
'mediumspringgreen': '#00fa9a',
|
||||
'mediumturquoise': '#48d1cc',
|
||||
'mediumvioletred': '#c71585',
|
||||
'midnightblue': '#191970',
|
||||
'mintcream': '#f5fffa',
|
||||
'mistyrose': '#ffe4e1',
|
||||
'moccasin': '#ffe4b5',
|
||||
'navajowhite': '#ffdead',
|
||||
'navy': '#000080',
|
||||
'oldlace': '#fdf5e6',
|
||||
'olive': '#808000',
|
||||
'olivedrab': '#6b8e23',
|
||||
'orange': '#ffa500',
|
||||
'orangered': '#ff4500',
|
||||
'orchid': '#da70d6',
|
||||
'palegoldenrod': '#eee8aa',
|
||||
'palegreen': '#98fb98',
|
||||
'paleturquoise': '#afeeee',
|
||||
'palevioletred': '#db7093',
|
||||
'papayawhip': '#ffefd5',
|
||||
'peachpuff': '#ffdab9',
|
||||
'peru': '#cd853f',
|
||||
'pink': '#ffc0cb',
|
||||
'plum': '#dda0dd',
|
||||
'powderblue': '#b0e0e6',
|
||||
'purple': '#800080',
|
||||
'red': '#ff0000',
|
||||
'rosybrown': '#bc8f8f',
|
||||
'royalblue': '#4169e1',
|
||||
'saddlebrown': '#8b4513',
|
||||
'salmon': '#fa8072',
|
||||
'sandybrown': '#f4a460',
|
||||
'seagreen': '#2e8b57',
|
||||
'seashell': '#fff5ee',
|
||||
'sienna': '#a0522d',
|
||||
'silver': '#c0c0c0',
|
||||
'skyblue': '#87ceeb',
|
||||
'slateblue': '#6a5acd',
|
||||
'slategray': '#708090',
|
||||
'slategrey': '#708090',
|
||||
'snow': '#fffafa',
|
||||
'springgreen': '#00ff7f',
|
||||
'steelblue': '#4682b4',
|
||||
'tan': '#d2b48c',
|
||||
'teal': '#008080',
|
||||
'thistle': '#d8bfd8',
|
||||
'tomato': '#ff6347',
|
||||
'turquoise': '#40e0d0',
|
||||
'violet': '#ee82ee',
|
||||
'wheat': '#f5deb3',
|
||||
'white': '#ffffff',
|
||||
'whitesmoke': '#f5f5f5',
|
||||
'yellow': '#ffff00',
|
||||
'yellowgreen': '#9acd32'
|
||||
};
|
||||
1027
float-no-zero/closure-library/closure/goog/crypt/aes.js
Normal file
1027
float-no-zero/closure-library/closure/goog/crypt/aes.js
Normal file
File diff suppressed because it is too large
Load Diff
162
float-no-zero/closure-library/closure/goog/crypt/arc4.js
Normal file
162
float-no-zero/closure-library/closure/goog/crypt/arc4.js
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright 2005 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 ARC4 streamcipher implementation. A description of the
|
||||
* algorithm can be found at:
|
||||
* http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt.
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* var arc4 = new goog.crypt.Arc4();
|
||||
* arc4.setKey(key);
|
||||
* arc4.discard(1536);
|
||||
* arc4.crypt(bytes);
|
||||
* </code>
|
||||
*
|
||||
* Note: For converting between strings and byte arrays, goog.crypt.base64 may
|
||||
* be useful.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Arc4');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ARC4 streamcipher implementation.
|
||||
* @constructor
|
||||
*/
|
||||
goog.crypt.Arc4 = function() {
|
||||
/**
|
||||
* A permutation of all 256 possible bytes.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.state_ = [];
|
||||
|
||||
/**
|
||||
* 8 bit index pointer into this.state_.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.index1_ = 0;
|
||||
|
||||
/**
|
||||
* 8 bit index pointer into this.state_.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.index2_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the cipher for use with new key.
|
||||
* @param {Array.<number>} key A byte array containing the key.
|
||||
* @param {number=} opt_length Indicates # of bytes to take from the key.
|
||||
*/
|
||||
goog.crypt.Arc4.prototype.setKey = function(key, opt_length) {
|
||||
goog.asserts.assertArray(key, 'Key parameter must be a byte array');
|
||||
|
||||
if (!opt_length) {
|
||||
opt_length = key.length;
|
||||
}
|
||||
|
||||
var state = this.state_;
|
||||
|
||||
for (var i = 0; i < 256; ++i) {
|
||||
state[i] = i;
|
||||
}
|
||||
|
||||
var j = 0;
|
||||
for (var i = 0; i < 256; ++i) {
|
||||
j = (j + state[i] + key[i % opt_length]) & 255;
|
||||
|
||||
var tmp = state[i];
|
||||
state[i] = state[j];
|
||||
state[j] = tmp;
|
||||
}
|
||||
|
||||
this.index1_ = 0;
|
||||
this.index2_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Discards n bytes of the keystream.
|
||||
* These days 1536 is considered a decent amount to drop to get the key state
|
||||
* warmed-up enough for secure usage. This is not done in the constructor to
|
||||
* preserve efficiency for use cases that do not need this.
|
||||
* NOTE: Discard is identical to crypt without actually xoring any data. It's
|
||||
* unfortunate to have this code duplicated, but this was done for performance
|
||||
* reasons. Alternatives which were attempted:
|
||||
* 1. Create a temp array of the correct length and pass it to crypt. This
|
||||
* works but needlessly allocates an array. But more importantly this
|
||||
* requires choosing an array type (Array or Uint8Array) in discard, and
|
||||
* choosing a different type than will be passed to crypt by the client
|
||||
* code hurts the javascript engines ability to optimize crypt (7x hit in
|
||||
* v8).
|
||||
* 2. Make data option in crypt so discard can pass null, this has a huge
|
||||
* perf hit for crypt.
|
||||
* @param {number} length Number of bytes to disregard from the stream.
|
||||
*/
|
||||
goog.crypt.Arc4.prototype.discard = function(length) {
|
||||
var i = this.index1_;
|
||||
var j = this.index2_;
|
||||
var state = this.state_;
|
||||
|
||||
for (var n = 0; n < length; ++n) {
|
||||
i = (i + 1) & 255;
|
||||
j = (j + state[i]) & 255;
|
||||
|
||||
var tmp = state[i];
|
||||
state[i] = state[j];
|
||||
state[j] = tmp;
|
||||
}
|
||||
|
||||
this.index1_ = i;
|
||||
this.index2_ = j;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* En- or decrypt (same operation for streamciphers like ARC4)
|
||||
* @param {Array.<number>|Uint8Array} data The data to be xor-ed in place.
|
||||
* @param {number=} opt_length The number of bytes to crypt.
|
||||
*/
|
||||
goog.crypt.Arc4.prototype.crypt = function(data, opt_length) {
|
||||
if (!opt_length) {
|
||||
opt_length = data.length;
|
||||
}
|
||||
var i = this.index1_;
|
||||
var j = this.index2_;
|
||||
var state = this.state_;
|
||||
|
||||
for (var n = 0; n < opt_length; ++n) {
|
||||
i = (i + 1) & 255;
|
||||
j = (j + state[i]) & 255;
|
||||
|
||||
var tmp = state[i];
|
||||
state[i] = state[j];
|
||||
state[j] = tmp;
|
||||
|
||||
data[n] ^= state[(state[i] + state[j]) & 255];
|
||||
}
|
||||
|
||||
this.index1_ = i;
|
||||
this.index2_ = j;
|
||||
};
|
||||
272
float-no-zero/closure-library/closure/goog/crypt/base64.js
Normal file
272
float-no-zero/closure-library/closure/goog/crypt/base64.js
Normal file
@@ -0,0 +1,272 @@
|
||||
// Copyright 2007 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 Base64 en/decoding. Not much to say here except that we
|
||||
* work with decoded values in arrays of bytes. By "byte" I mean a number
|
||||
* in [0, 255].
|
||||
*
|
||||
* @author doughtie@google.com (Gavin Doughtie)
|
||||
* @author fschneider@google.com (Fritz Schneider)
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.base64');
|
||||
goog.require('goog.crypt');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
// Static lookup maps, lazily populated by init_()
|
||||
|
||||
|
||||
/**
|
||||
* Maps bytes to characters.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.base64.byteToCharMap_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Maps characters to bytes.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.base64.charToByteMap_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Maps bytes to websafe characters.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.base64.byteToCharMapWebSafe_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Maps websafe characters to bytes.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.base64.charToByteMapWebSafe_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Our default alphabet, shared between
|
||||
* ENCODED_VALS and ENCODED_VALS_WEBSAFE
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.base64.ENCODED_VALS_BASE =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
|
||||
'abcdefghijklmnopqrstuvwxyz' +
|
||||
'0123456789';
|
||||
|
||||
|
||||
/**
|
||||
* Our default alphabet. Value 64 (=) is special; it means "nothing."
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.base64.ENCODED_VALS =
|
||||
goog.crypt.base64.ENCODED_VALS_BASE + '+/=';
|
||||
|
||||
|
||||
/**
|
||||
* Our websafe alphabet.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.base64.ENCODED_VALS_WEBSAFE =
|
||||
goog.crypt.base64.ENCODED_VALS_BASE + '-_.';
|
||||
|
||||
|
||||
/**
|
||||
* Whether this browser supports the atob and btoa functions. This extension
|
||||
* started at Mozilla but is now implemented by many browsers. We use the
|
||||
* ASSUME_* variables to avoid pulling in the full useragent detection library
|
||||
* but still allowing the standard per-browser compilations.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.crypt.base64.HAS_NATIVE_SUPPORT = goog.userAgent.GECKO ||
|
||||
goog.userAgent.WEBKIT ||
|
||||
goog.userAgent.OPERA ||
|
||||
typeof(goog.global.atob) == 'function';
|
||||
|
||||
|
||||
/**
|
||||
* Base64-encode an array of bytes.
|
||||
*
|
||||
* @param {Array.<number>|Uint8Array} input An array of bytes (numbers with
|
||||
* value in [0, 255]) to encode.
|
||||
* @param {boolean=} opt_webSafe Boolean indicating we should use the
|
||||
* alternative alphabet.
|
||||
* @return {string} The base64 encoded string.
|
||||
*/
|
||||
goog.crypt.base64.encodeByteArray = function(input, opt_webSafe) {
|
||||
if (!goog.isArrayLike(input)) {
|
||||
throw Error('encodeByteArray takes an array as a parameter');
|
||||
}
|
||||
|
||||
goog.crypt.base64.init_();
|
||||
|
||||
var byteToCharMap = opt_webSafe ?
|
||||
goog.crypt.base64.byteToCharMapWebSafe_ :
|
||||
goog.crypt.base64.byteToCharMap_;
|
||||
|
||||
var output = [];
|
||||
|
||||
for (var i = 0; i < input.length; i += 3) {
|
||||
var byte1 = input[i];
|
||||
var haveByte2 = i + 1 < input.length;
|
||||
var byte2 = haveByte2 ? input[i + 1] : 0;
|
||||
var haveByte3 = i + 2 < input.length;
|
||||
var byte3 = haveByte3 ? input[i + 2] : 0;
|
||||
|
||||
var outByte1 = byte1 >> 2;
|
||||
var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
|
||||
var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
|
||||
var outByte4 = byte3 & 0x3F;
|
||||
|
||||
if (!haveByte3) {
|
||||
outByte4 = 64;
|
||||
|
||||
if (!haveByte2) {
|
||||
outByte3 = 64;
|
||||
}
|
||||
}
|
||||
|
||||
output.push(byteToCharMap[outByte1],
|
||||
byteToCharMap[outByte2],
|
||||
byteToCharMap[outByte3],
|
||||
byteToCharMap[outByte4]);
|
||||
}
|
||||
|
||||
return output.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base64-encode a string.
|
||||
*
|
||||
* @param {string} input A string to encode.
|
||||
* @param {boolean=} opt_webSafe If true, we should use the
|
||||
* alternative alphabet.
|
||||
* @return {string} The base64 encoded string.
|
||||
*/
|
||||
goog.crypt.base64.encodeString = function(input, opt_webSafe) {
|
||||
// Shortcut for Mozilla browsers that implement
|
||||
// a native base64 encoder in the form of "btoa/atob"
|
||||
if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) {
|
||||
return goog.global.btoa(input);
|
||||
}
|
||||
return goog.crypt.base64.encodeByteArray(
|
||||
goog.crypt.stringToByteArray(input), opt_webSafe);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base64-decode a string.
|
||||
*
|
||||
* @param {string} input to decode.
|
||||
* @param {boolean=} opt_webSafe True if we should use the
|
||||
* alternative alphabet.
|
||||
* @return {string} string representing the decoded value.
|
||||
*/
|
||||
goog.crypt.base64.decodeString = function(input, opt_webSafe) {
|
||||
// Shortcut for Mozilla browsers that implement
|
||||
// a native base64 encoder in the form of "btoa/atob"
|
||||
if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) {
|
||||
return goog.global.atob(input);
|
||||
}
|
||||
return goog.crypt.byteArrayToString(
|
||||
goog.crypt.base64.decodeStringToByteArray(input, opt_webSafe));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base64-decode a string.
|
||||
*
|
||||
* @param {string} input to decode (length not required to be a multiple of 4).
|
||||
* @param {boolean=} opt_webSafe True if we should use the
|
||||
* alternative alphabet.
|
||||
* @return {Array} bytes representing the decoded value.
|
||||
*/
|
||||
goog.crypt.base64.decodeStringToByteArray = function(input, opt_webSafe) {
|
||||
goog.crypt.base64.init_();
|
||||
|
||||
var charToByteMap = opt_webSafe ?
|
||||
goog.crypt.base64.charToByteMapWebSafe_ :
|
||||
goog.crypt.base64.charToByteMap_;
|
||||
|
||||
var output = [];
|
||||
|
||||
for (var i = 0; i < input.length; ) {
|
||||
var byte1 = charToByteMap[input.charAt(i++)];
|
||||
|
||||
var haveByte2 = i < input.length;
|
||||
var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
|
||||
++i;
|
||||
|
||||
var haveByte3 = i < input.length;
|
||||
var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 0;
|
||||
++i;
|
||||
|
||||
var haveByte4 = i < input.length;
|
||||
var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 0;
|
||||
++i;
|
||||
|
||||
if (byte1 == null || byte2 == null ||
|
||||
byte3 == null || byte4 == null) {
|
||||
throw Error();
|
||||
}
|
||||
|
||||
var outByte1 = (byte1 << 2) | (byte2 >> 4);
|
||||
output.push(outByte1);
|
||||
|
||||
if (byte3 != 64) {
|
||||
var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2);
|
||||
output.push(outByte2);
|
||||
|
||||
if (byte4 != 64) {
|
||||
var outByte3 = ((byte3 << 6) & 0xC0) | byte4;
|
||||
output.push(outByte3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Lazy static initialization function. Called before
|
||||
* accessing any of the static map variables.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.base64.init_ = function() {
|
||||
if (!goog.crypt.base64.byteToCharMap_) {
|
||||
goog.crypt.base64.byteToCharMap_ = {};
|
||||
goog.crypt.base64.charToByteMap_ = {};
|
||||
goog.crypt.base64.byteToCharMapWebSafe_ = {};
|
||||
goog.crypt.base64.charToByteMapWebSafe_ = {};
|
||||
|
||||
// We want quick mappings back and forth, so we precompute two maps.
|
||||
for (var i = 0; i < goog.crypt.base64.ENCODED_VALS.length; i++) {
|
||||
goog.crypt.base64.byteToCharMap_[i] =
|
||||
goog.crypt.base64.ENCODED_VALS.charAt(i);
|
||||
goog.crypt.base64.charToByteMap_[goog.crypt.base64.byteToCharMap_[i]] = i;
|
||||
goog.crypt.base64.byteToCharMapWebSafe_[i] =
|
||||
goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i);
|
||||
goog.crypt.base64.charToByteMapWebSafe_[
|
||||
goog.crypt.base64.byteToCharMapWebSafe_[i]] = i;
|
||||
}
|
||||
}
|
||||
};
|
||||
242
float-no-zero/closure-library/closure/goog/crypt/basen.js
Normal file
242
float-no-zero/closure-library/closure/goog/crypt/basen.js
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright 2007 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 Numeric base conversion library. Works for arbitrary bases and
|
||||
* arbitrary length numbers.
|
||||
*
|
||||
* For base-64 conversion use base64.js because it is optimized for the specific
|
||||
* conversion to base-64 while this module is generic. Base-64 is defined here
|
||||
* mostly for demonstration purpose.
|
||||
*
|
||||
* TODO: Make base64 and baseN classes that have common interface. (Perhaps...)
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.baseN');
|
||||
|
||||
|
||||
/**
|
||||
* Base-2, i.e. '01'.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_BINARY = '01';
|
||||
|
||||
|
||||
/**
|
||||
* Base-8, i.e. '01234567'.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_OCTAL = '01234567';
|
||||
|
||||
|
||||
/**
|
||||
* Base-10, i.e. '0123456789'.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_DECIMAL = '0123456789';
|
||||
|
||||
|
||||
/**
|
||||
* Base-16 using lower case, i.e. '0123456789abcdef'.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL = '0123456789abcdef';
|
||||
|
||||
|
||||
/**
|
||||
* Base-16 using upper case, i.e. '0123456789ABCDEF'.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL = '0123456789ABCDEF';
|
||||
|
||||
|
||||
/**
|
||||
* The more-known version of the BASE-64 encoding. Uses + and / characters.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_64 =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
|
||||
/**
|
||||
* URL-safe version of the BASE-64 encoding.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.crypt.baseN.BASE_64_URL_SAFE =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
||||
|
||||
|
||||
/**
|
||||
* Converts a number from one numeric base to another.
|
||||
*
|
||||
* The bases are represented as strings, which list allowed digits. Each digit
|
||||
* should be unique. The bases can either be user defined, or any of
|
||||
* goog.crypt.baseN.BASE_xxx.
|
||||
*
|
||||
* The number is in human-readable format, most significant digit first, and is
|
||||
* a non-negative integer. Base designators such as $, 0x, d, b or h (at end)
|
||||
* will be interpreted as digits, so avoid them. Leading zeros will be trimmed.
|
||||
*
|
||||
* Note: for huge bases the result may be inaccurate because of overflowing
|
||||
* 64-bit doubles used by JavaScript for integer calculus. This may happen
|
||||
* if the product of the number of digits in the input and output bases comes
|
||||
* close to 10^16, which is VERY unlikely (100M digits in each base), but
|
||||
* may be possible in the future unicode world. (Unicode 3.2 has less than 100K
|
||||
* characters. However, it reserves some more, close to 1M.)
|
||||
*
|
||||
* @param {string} number The number to convert.
|
||||
* @param {string} inputBase The numeric base the number is in (all digits).
|
||||
* @param {string} outputBase Requested numeric base.
|
||||
* @return {string} The converted number.
|
||||
*/
|
||||
goog.crypt.baseN.recodeString = function(number, inputBase, outputBase) {
|
||||
if (outputBase == '') {
|
||||
throw Error('Empty output base');
|
||||
}
|
||||
|
||||
// Check if number is 0 (special case when we don't want to return '').
|
||||
var isZero = true;
|
||||
for (var i = 0, n = number.length; i < n; i++) {
|
||||
if (number.charAt(i) != inputBase.charAt(0)) {
|
||||
isZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isZero) {
|
||||
return outputBase.charAt(0);
|
||||
}
|
||||
|
||||
var numberDigits = goog.crypt.baseN.stringToArray_(number, inputBase);
|
||||
|
||||
var inputBaseSize = inputBase.length;
|
||||
var outputBaseSize = outputBase.length;
|
||||
|
||||
// result = 0.
|
||||
var result = [];
|
||||
|
||||
// For all digits of number, starting with the most significant ...
|
||||
for (var i = numberDigits.length - 1; i >= 0; i--) {
|
||||
|
||||
// result *= number.base.
|
||||
var carry = 0;
|
||||
for (var j = 0, n = result.length; j < n; j++) {
|
||||
var digit = result[j];
|
||||
// This may overflow for huge bases. See function comment.
|
||||
digit = digit * inputBaseSize + carry;
|
||||
if (digit >= outputBaseSize) {
|
||||
var remainder = digit % outputBaseSize;
|
||||
carry = (digit - remainder) / outputBaseSize;
|
||||
digit = remainder;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
result[j] = digit;
|
||||
}
|
||||
while (carry) {
|
||||
var remainder = carry % outputBaseSize;
|
||||
result.push(remainder);
|
||||
carry = (carry - remainder) / outputBaseSize;
|
||||
}
|
||||
|
||||
// result += number[i].
|
||||
carry = numberDigits[i];
|
||||
var j = 0;
|
||||
while (carry) {
|
||||
if (j >= result.length) {
|
||||
// Extend result with a leading zero which will be overwritten below.
|
||||
result.push(0);
|
||||
}
|
||||
var digit = result[j];
|
||||
digit += carry;
|
||||
if (digit >= outputBaseSize) {
|
||||
var remainder = digit % outputBaseSize;
|
||||
carry = (digit - remainder) / outputBaseSize;
|
||||
digit = remainder;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
result[j] = digit;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return goog.crypt.baseN.arrayToString_(result, outputBase);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string representation of a number to an array of digit values.
|
||||
*
|
||||
* More precisely, the digit values are indices into the number base, which
|
||||
* is represented as a string, which can either be user defined or one of the
|
||||
* BASE_xxx constants.
|
||||
*
|
||||
* Throws an Error if the number contains a digit not found in the base.
|
||||
*
|
||||
* @param {string} number The string to convert, most significant digit first.
|
||||
* @param {string} base Digits in the base.
|
||||
* @return {Array.<number>} Array of digit values, least significant digit
|
||||
* first.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.baseN.stringToArray_ = function(number, base) {
|
||||
var index = {};
|
||||
for (var i = 0, n = base.length; i < n; i++) {
|
||||
index[base.charAt(i)] = i;
|
||||
}
|
||||
var result = [];
|
||||
for (var i = number.length - 1; i >= 0; i--) {
|
||||
var character = number.charAt(i);
|
||||
var digit = index[character];
|
||||
if (typeof digit == 'undefined') {
|
||||
throw Error('Number ' + number +
|
||||
' contains a character not found in base ' +
|
||||
base + ', which is ' + character);
|
||||
}
|
||||
result.push(digit);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an array representation of a number to a string.
|
||||
*
|
||||
* More precisely, the elements of the input array are indices into the base,
|
||||
* which is represented as a string, which can either be user defined or one of
|
||||
* the BASE_xxx constants.
|
||||
*
|
||||
* Throws an Error if the number contains a digit which is outside the range
|
||||
* 0 ... base.length - 1.
|
||||
*
|
||||
* @param {Array.<number>} number Array of digit values, least significant
|
||||
* first.
|
||||
* @param {string} base Digits in the base.
|
||||
* @return {string} Number as a string, most significant digit first.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.baseN.arrayToString_ = function(number, base) {
|
||||
var n = number.length;
|
||||
var chars = [];
|
||||
var baseSize = base.length;
|
||||
for (var i = n - 1; i >= 0; i--) {
|
||||
var digit = number[i];
|
||||
if (digit >= baseSize || digit < 0) {
|
||||
throw Error('Number ' + number + ' contains an invalid digit: ' + digit);
|
||||
}
|
||||
chars.push(base.charAt(digit));
|
||||
}
|
||||
return chars.join('');
|
||||
};
|
||||
284
float-no-zero/closure-library/closure/goog/crypt/blobhasher.js
Normal file
284
float-no-zero/closure-library/closure/goog/crypt/blobhasher.js
Normal file
@@ -0,0 +1,284 @@
|
||||
// Copyright 2011 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 Asynchronous hash computer for the Blob interface.
|
||||
*
|
||||
* The Blob interface, part of the HTML5 File API, is supported on Chrome 7+,
|
||||
* Firefox 4.0 and Opera 11. No Blob interface implementation is expected on
|
||||
* Internet Explorer 10. Chrome 11, Firefox 5.0 and the subsequent release of
|
||||
* Opera are supposed to use vendor prefixes due to evolving API, see
|
||||
* http://dev.w3.org/2006/webapi/FileAPI/ for details.
|
||||
*
|
||||
* This implementation currently uses upcoming Chrome and Firefox prefixes,
|
||||
* plus the original Blob.slice specification, as implemented on Chrome 10
|
||||
* and Firefox 4.0.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.BlobHasher');
|
||||
goog.provide('goog.crypt.BlobHasher.EventType');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.crypt');
|
||||
goog.require('goog.crypt.Hash');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.fs');
|
||||
goog.require('goog.log');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Construct the hash computer.
|
||||
*
|
||||
* @param {!goog.crypt.Hash} hashFn The hash function to use.
|
||||
* @param {number=} opt_blockSize Processing block size.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.crypt.BlobHasher = function(hashFn, opt_blockSize) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* The actual hash function.
|
||||
* @type {!goog.crypt.Hash}
|
||||
* @private
|
||||
*/
|
||||
this.hashFn_ = hashFn;
|
||||
|
||||
/**
|
||||
* The blob being processed or null if no blob is being processed.
|
||||
* @type {Blob}
|
||||
* @private
|
||||
*/
|
||||
this.blob_ = null;
|
||||
|
||||
/**
|
||||
* Computed hash value.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.hashVal_ = null;
|
||||
|
||||
/**
|
||||
* Number of bytes already processed.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.bytesProcessed_ = 0;
|
||||
|
||||
/**
|
||||
* The number of bytes to hash or Infinity for no limit.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.hashingLimit_ = Infinity;
|
||||
|
||||
/**
|
||||
* Processing block size.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.blockSize_ = opt_blockSize || 5000000;
|
||||
|
||||
/**
|
||||
* File reader object. Will be null if no chunk is currently being read.
|
||||
* @type {FileReader}
|
||||
* @private
|
||||
*/
|
||||
this.fileReader_ = null;
|
||||
|
||||
/**
|
||||
* The logger used by this object.
|
||||
* @type {goog.log.Logger}
|
||||
* @private
|
||||
*/
|
||||
this.logger_ = goog.log.getLogger('goog.crypt.BlobHasher');
|
||||
};
|
||||
goog.inherits(goog.crypt.BlobHasher, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Event names for hash computation events
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.crypt.BlobHasher.EventType = {
|
||||
STARTED: 'started',
|
||||
PROGRESS: 'progress',
|
||||
THROTTLED: 'throttled',
|
||||
COMPLETE: 'complete',
|
||||
ABORT: 'abort',
|
||||
ERROR: 'error'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Start the hash computation.
|
||||
* @param {!Blob} blob The blob of data to compute the hash for.
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.hash = function(blob) {
|
||||
this.abort();
|
||||
this.hashFn_.reset();
|
||||
this.blob_ = blob;
|
||||
this.hashVal_ = null;
|
||||
this.bytesProcessed_ = 0;
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.STARTED);
|
||||
|
||||
this.processNextBlock_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the maximum number of bytes to hash or Infinity for no limit. Can be
|
||||
* called before hash() to throttle the hash computation. The hash computation
|
||||
* can then be continued by repeatedly calling setHashingLimit() with greater
|
||||
* byte offsets. This is useful if you don't need the hash until some time in
|
||||
* the future, for example when uploading a file and you don't need the hash
|
||||
* until the transfer is complete.
|
||||
* @param {number} byteOffset The byte offset to compute the hash up to.
|
||||
* Should be a non-negative integer or Infinity for no limit. Negative
|
||||
* values are not allowed.
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.setHashingLimit = function(byteOffset) {
|
||||
goog.asserts.assert(byteOffset >= 0, 'Hashing limit must be non-negative.');
|
||||
this.hashingLimit_ = byteOffset;
|
||||
|
||||
// Resume processing if a blob is currently being hashed, but no block read
|
||||
// is currently in progress.
|
||||
if (this.blob_ && !this.fileReader_) {
|
||||
this.processNextBlock_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abort hash computation.
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.abort = function() {
|
||||
if (this.fileReader_) {
|
||||
this.fileReader_.abort();
|
||||
this.fileReader_ = null;
|
||||
}
|
||||
|
||||
if (this.blob_) {
|
||||
this.blob_ = null;
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.ABORT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Number of bytes processed so far.
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.getBytesProcessed = function() {
|
||||
return this.bytesProcessed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} The computed hash value or null if not ready.
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.getHash = function() {
|
||||
return this.hashVal_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function setting up the processing for the next block, or finalizing
|
||||
* the computation if all blocks were processed.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.processNextBlock_ = function() {
|
||||
goog.asserts.assert(this.blob_, 'A hash computation must be in progress.');
|
||||
|
||||
if (this.bytesProcessed_ < this.blob_.size) {
|
||||
|
||||
if (this.hashingLimit_ <= this.bytesProcessed_) {
|
||||
// Throttle limit reached. Wait until we are allowed to hash more bytes.
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.THROTTLED);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have to reset the FileReader every time, otherwise it fails on
|
||||
// Chrome, including the latest Chrome 12 beta.
|
||||
// http://code.google.com/p/chromium/issues/detail?id=82346
|
||||
this.fileReader_ = new FileReader();
|
||||
this.fileReader_.onload = goog.bind(this.onLoad_, this);
|
||||
this.fileReader_.onerror = goog.bind(this.onError_, this);
|
||||
|
||||
var endOffset = Math.min(this.hashingLimit_, this.blob_.size);
|
||||
var size = Math.min(endOffset - this.bytesProcessed_, this.blockSize_);
|
||||
var chunk = goog.fs.sliceBlob(this.blob_, this.bytesProcessed_,
|
||||
this.bytesProcessed_ + size);
|
||||
if (!chunk || chunk.size != size) {
|
||||
goog.log.error(this.logger_, 'Failed slicing the blob');
|
||||
this.onError_();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.fileReader_.readAsArrayBuffer) {
|
||||
this.fileReader_.readAsArrayBuffer(chunk);
|
||||
} else if (this.fileReader_.readAsBinaryString) {
|
||||
this.fileReader_.readAsBinaryString(chunk);
|
||||
} else {
|
||||
goog.log.error(this.logger_, 'Failed calling the chunk reader');
|
||||
this.onError_();
|
||||
}
|
||||
} else {
|
||||
this.hashVal_ = this.hashFn_.digest();
|
||||
this.blob_ = null;
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.COMPLETE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle processing block loaded.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.onLoad_ = function() {
|
||||
goog.log.info(this.logger_, 'Successfully loaded a chunk');
|
||||
|
||||
var array = null;
|
||||
if (this.fileReader_.result instanceof Array ||
|
||||
goog.isString(this.fileReader_.result)) {
|
||||
array = this.fileReader_.result;
|
||||
} else if (goog.global['ArrayBuffer'] && goog.global['Uint8Array'] &&
|
||||
this.fileReader_.result instanceof ArrayBuffer) {
|
||||
array = new Uint8Array(this.fileReader_.result);
|
||||
}
|
||||
if (!array) {
|
||||
goog.log.error(this.logger_, 'Failed reading the chunk');
|
||||
this.onError_();
|
||||
return;
|
||||
}
|
||||
|
||||
this.hashFn_.update(array);
|
||||
this.bytesProcessed_ += array.length;
|
||||
this.fileReader_ = null;
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.PROGRESS);
|
||||
|
||||
this.processNextBlock_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles error.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.BlobHasher.prototype.onError_ = function() {
|
||||
this.fileReader_ = null;
|
||||
this.blob_ = null;
|
||||
this.dispatchEvent(goog.crypt.BlobHasher.EventType.ERROR);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2012 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 Interface definition of a block cipher. A block cipher is a
|
||||
* pair of algorithms that implement encryption and decryption of input bytes.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Block_cipher
|
||||
*
|
||||
* @author nnaze@google.com (Nathan Naze)
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.BlockCipher');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface definition for a block cipher.
|
||||
* @interface
|
||||
*/
|
||||
goog.crypt.BlockCipher = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt a plaintext block. The implementation may expect (and assert)
|
||||
* a particular block length.
|
||||
* @param {!Array.<number>} input Plaintext array of input bytes.
|
||||
* @return {!Array.<number>} Encrypted ciphertext array of bytes. Should be the
|
||||
* same length as input.
|
||||
*/
|
||||
goog.crypt.BlockCipher.prototype.encrypt;
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt a plaintext block. The implementation may expect (and assert)
|
||||
* a particular block length.
|
||||
* @param {!Array.<number>} input Ciphertext. Array of input bytes.
|
||||
* @return {!Array.<number>} Decrypted plaintext array of bytes. Should be the
|
||||
* same length as input.
|
||||
*/
|
||||
goog.crypt.BlockCipher.prototype.decrypt;
|
||||
150
float-no-zero/closure-library/closure/goog/crypt/cbc.js
Normal file
150
float-no-zero/closure-library/closure/goog/crypt/cbc.js
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2012 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 Implementation of CBC mode for block ciphers. See
|
||||
* http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
|
||||
* #Cipher-block_chaining_.28CBC.29. for description.
|
||||
*
|
||||
* @author nnaze@google.com (Nathan Naze)
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Cbc');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.crypt');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implements the CBC mode for block ciphers. See
|
||||
* http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
|
||||
* #Cipher-block_chaining_.28CBC.29
|
||||
*
|
||||
* @param {!goog.crypt.BlockCipher} cipher The block cipher to use.
|
||||
* @param {number=} opt_blockSize The block size of the cipher in bytes.
|
||||
* Defaults to 16 bytes.
|
||||
* @constructor
|
||||
*/
|
||||
goog.crypt.Cbc = function(cipher, opt_blockSize) {
|
||||
|
||||
/**
|
||||
* Block cipher.
|
||||
* @type {!goog.crypt.BlockCipher}
|
||||
* @private
|
||||
*/
|
||||
this.cipher_ = cipher;
|
||||
|
||||
/**
|
||||
* Block size in bytes.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.blockSize_ = opt_blockSize || 16;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt a message.
|
||||
*
|
||||
* @param {!Array.<number>} plainText Message to encrypt. An array of bytes.
|
||||
* The length should be a multiple of the block size.
|
||||
* @param {!Array.<number>} initialVector Initial vector for the CBC mode.
|
||||
* An array of bytes with the same length as the block size.
|
||||
* @return {!Array.<number>} Encrypted message.
|
||||
*/
|
||||
goog.crypt.Cbc.prototype.encrypt = function(plainText, initialVector) {
|
||||
|
||||
goog.asserts.assert(
|
||||
plainText.length % this.blockSize_ == 0,
|
||||
'Data\'s length must be multiple of block size.');
|
||||
|
||||
goog.asserts.assert(
|
||||
initialVector.length == this.blockSize_,
|
||||
'Initial vector must be size of one block.');
|
||||
|
||||
// Implementation of
|
||||
// http://en.wikipedia.org/wiki/File:Cbc_encryption.png
|
||||
|
||||
var cipherText = [];
|
||||
var vector = initialVector;
|
||||
|
||||
// Generate each block of the encrypted cypher text.
|
||||
for (var blockStartIndex = 0;
|
||||
blockStartIndex < plainText.length;
|
||||
blockStartIndex += this.blockSize_) {
|
||||
|
||||
// Takes one block from the input message.
|
||||
var plainTextBlock = goog.array.slice(
|
||||
plainText,
|
||||
blockStartIndex,
|
||||
blockStartIndex + this.blockSize_);
|
||||
|
||||
var input = goog.crypt.xorByteArray(plainTextBlock, vector);
|
||||
var resultBlock = this.cipher_.encrypt(input);
|
||||
|
||||
goog.array.extend(cipherText, resultBlock);
|
||||
vector = resultBlock;
|
||||
}
|
||||
|
||||
return cipherText;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt a message.
|
||||
*
|
||||
* @param {!Array.<number>} cipherText Message to decrypt. An array of bytes.
|
||||
* The length should be a multiple of the block size.
|
||||
* @param {!Array.<number>} initialVector Initial vector for the CBC mode.
|
||||
* An array of bytes with the same length as the block size.
|
||||
* @return {!Array.<number>} Decrypted message.
|
||||
*/
|
||||
goog.crypt.Cbc.prototype.decrypt = function(cipherText, initialVector) {
|
||||
|
||||
goog.asserts.assert(
|
||||
cipherText.length % this.blockSize_ == 0,
|
||||
'Data\'s length must be multiple of block size.');
|
||||
|
||||
goog.asserts.assert(
|
||||
initialVector.length == this.blockSize_,
|
||||
'Initial vector must be size of one block.');
|
||||
|
||||
// Implementation of
|
||||
// http://en.wikipedia.org/wiki/File:Cbc_decryption.png
|
||||
|
||||
var plainText = [];
|
||||
var blockStartIndex = 0;
|
||||
var vector = initialVector;
|
||||
|
||||
// Generate each block of the decrypted plain text.
|
||||
while (blockStartIndex < cipherText.length) {
|
||||
|
||||
// Takes one block.
|
||||
var cipherTextBlock = goog.array.slice(
|
||||
cipherText,
|
||||
blockStartIndex,
|
||||
blockStartIndex + this.blockSize_);
|
||||
|
||||
var resultBlock = this.cipher_.decrypt(cipherTextBlock);
|
||||
var plainTextBlock = goog.crypt.xorByteArray(vector, resultBlock);
|
||||
|
||||
goog.array.extend(plainText, plainTextBlock);
|
||||
vector = cipherTextBlock;
|
||||
|
||||
blockStartIndex += this.blockSize_;
|
||||
}
|
||||
|
||||
return plainText;
|
||||
};
|
||||
100
float-no-zero/closure-library/closure/goog/crypt/cbc_test.js
Normal file
100
float-no-zero/closure-library/closure/goog/crypt/cbc_test.js
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2012 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 Unit tests for CBC mode for block ciphers.
|
||||
*
|
||||
* @author nnaze@google.com (Nathan Naze)
|
||||
*/
|
||||
|
||||
/** @suppress {extraProvide} */
|
||||
goog.provide('goog.crypt.CbcTest');
|
||||
|
||||
goog.require('goog.crypt');
|
||||
goog.require('goog.crypt.Aes');
|
||||
goog.require('goog.crypt.Cbc');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
goog.setTestOnly('goog.crypt.CbcTest');
|
||||
|
||||
function stringToBytes(s) {
|
||||
var bytes = new Array(s.length);
|
||||
for (var i = 0; i < s.length; ++i)
|
||||
bytes[i] = s.charCodeAt(i) & 255;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function runCbcAesTest(keyBytes, initialVectorBytes, plainTextBytes,
|
||||
cipherTextBytes) {
|
||||
|
||||
var aes = new goog.crypt.Aes(keyBytes);
|
||||
var cbc = new goog.crypt.Cbc(aes);
|
||||
|
||||
var encryptedBytes = cbc.encrypt(plainTextBytes, initialVectorBytes);
|
||||
assertEquals('Encrypted bytes should match cipher text.',
|
||||
goog.crypt.byteArrayToHex(cipherTextBytes),
|
||||
goog.crypt.byteArrayToHex(encryptedBytes));
|
||||
|
||||
var decryptedBytes = cbc.decrypt(cipherTextBytes, initialVectorBytes);
|
||||
assertEquals('Decrypted bytes should match plain text.',
|
||||
goog.crypt.byteArrayToHex(plainTextBytes),
|
||||
goog.crypt.byteArrayToHex(decryptedBytes));
|
||||
}
|
||||
|
||||
function testAesCbcCipherAlgorithm() {
|
||||
// Test values from http://www.ietf.org/rfc/rfc3602.txt
|
||||
|
||||
// Case #1
|
||||
runCbcAesTest(
|
||||
goog.crypt.hexToByteArray('06a9214036b8a15b512e03d534120006'),
|
||||
goog.crypt.hexToByteArray('3dafba429d9eb430b422da802c9fac41'),
|
||||
stringToBytes('Single block msg'),
|
||||
goog.crypt.hexToByteArray('e353779c1079aeb82708942dbe77181a'));
|
||||
|
||||
// Case #2
|
||||
runCbcAesTest(
|
||||
goog.crypt.hexToByteArray('c286696d887c9aa0611bbb3e2025a45a'),
|
||||
goog.crypt.hexToByteArray('562e17996d093d28ddb3ba695a2e6f58'),
|
||||
goog.crypt.hexToByteArray(
|
||||
'000102030405060708090a0b0c0d0e0f' +
|
||||
'101112131415161718191a1b1c1d1e1f'),
|
||||
goog.crypt.hexToByteArray(
|
||||
'd296cd94c2cccf8a3a863028b5e1dc0a' +
|
||||
'7586602d253cfff91b8266bea6d61ab1'));
|
||||
|
||||
// Case #3
|
||||
runCbcAesTest(
|
||||
goog.crypt.hexToByteArray('6c3ea0477630ce21a2ce334aa746c2cd'),
|
||||
goog.crypt.hexToByteArray('c782dc4c098c66cbd9cd27d825682c81'),
|
||||
stringToBytes('This is a 48-byte message (exactly 3 AES blocks)'),
|
||||
goog.crypt.hexToByteArray(
|
||||
'd0a02b3836451753d493665d33f0e886' +
|
||||
'2dea54cdb293abc7506939276772f8d5' +
|
||||
'021c19216bad525c8579695d83ba2684'));
|
||||
|
||||
// Case #4
|
||||
runCbcAesTest(
|
||||
goog.crypt.hexToByteArray('56e47a38c5598974bc46903dba290349'),
|
||||
goog.crypt.hexToByteArray('8ce82eefbea0da3c44699ed7db51b7d9'),
|
||||
goog.crypt.hexToByteArray(
|
||||
'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf' +
|
||||
'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' +
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' +
|
||||
'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'),
|
||||
goog.crypt.hexToByteArray(
|
||||
'c30e32ffedc0774e6aff6af0869f71aa' +
|
||||
'0f3af07a9a31a9c684db207eb0ef8e4e' +
|
||||
'35907aa632c3ffdf868bb7b29d3d46ad' +
|
||||
'83ce9f9a102ee99d49a53e87f4c3da55'));
|
||||
}
|
||||
155
float-no-zero/closure-library/closure/goog/crypt/crypt.js
Normal file
155
float-no-zero/closure-library/closure/goog/crypt/crypt.js
Normal file
@@ -0,0 +1,155 @@
|
||||
// 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 Namespace with crypto related helper functions.
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt');
|
||||
|
||||
goog.require('goog.array');
|
||||
|
||||
|
||||
/**
|
||||
* Turns a string into an array of bytes; a "byte" being a JS number in the
|
||||
* range 0-255.
|
||||
* @param {string} str String value to arrify.
|
||||
* @return {!Array.<number>} Array of numbers corresponding to the
|
||||
* UCS character codes of each character in str.
|
||||
*/
|
||||
goog.crypt.stringToByteArray = function(str) {
|
||||
var output = [], p = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str.charCodeAt(i);
|
||||
while (c > 0xff) {
|
||||
output[p++] = c & 0xff;
|
||||
c >>= 8;
|
||||
}
|
||||
output[p++] = c;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Turns an array of numbers into the string given by the concatenation of the
|
||||
* characters to which the numbers correspond.
|
||||
* @param {Array} array Array of numbers representing characters.
|
||||
* @return {string} Stringification of the array.
|
||||
*/
|
||||
goog.crypt.byteArrayToString = function(array) {
|
||||
return String.fromCharCode.apply(null, array);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Turns an array of numbers into the hex string given by the concatenation of
|
||||
* the hex values to which the numbers correspond.
|
||||
* @param {Array} array Array of numbers representing characters.
|
||||
* @return {string} Hex string.
|
||||
*/
|
||||
goog.crypt.byteArrayToHex = function(array) {
|
||||
return goog.array.map(array, function(numByte) {
|
||||
var hexByte = numByte.toString(16);
|
||||
return hexByte.length > 1 ? hexByte : '0' + hexByte;
|
||||
}).join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex string into an integer array.
|
||||
* @param {string} hexString Hex string of 16-bit integers (two characters
|
||||
* per integer).
|
||||
* @return {!Array.<number>} Array of {0,255} integers for the given string.
|
||||
*/
|
||||
goog.crypt.hexToByteArray = function(hexString) {
|
||||
goog.asserts.assert(hexString.length % 2 == 0,
|
||||
'Key string length must be multiple of 2');
|
||||
var arr = [];
|
||||
for (var i = 0; i < hexString.length; i += 2) {
|
||||
arr.push(parseInt(hexString.substring(i, i + 2), 16));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a JS string to a UTF-8 "byte" array.
|
||||
* @param {string} str 16-bit unicode string.
|
||||
* @return {Array.<number>} UTF-8 byte array.
|
||||
*/
|
||||
goog.crypt.stringToUtf8ByteArray = function(str) {
|
||||
// TODO(user): Use native implementations if/when available
|
||||
str = str.replace(/\r\n/g, '\n');
|
||||
var out = [], p = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str.charCodeAt(i);
|
||||
if (c < 128) {
|
||||
out[p++] = c;
|
||||
} else if (c < 2048) {
|
||||
out[p++] = (c >> 6) | 192;
|
||||
out[p++] = (c & 63) | 128;
|
||||
} else {
|
||||
out[p++] = (c >> 12) | 224;
|
||||
out[p++] = ((c >> 6) & 63) | 128;
|
||||
out[p++] = (c & 63) | 128;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
|
||||
* @param {Array.<number>} bytes UTF-8 byte array.
|
||||
* @return {string} 16-bit Unicode string.
|
||||
*/
|
||||
goog.crypt.utf8ByteArrayToString = function(bytes) {
|
||||
// TODO(user): Use native implementations if/when available
|
||||
var out = [], pos = 0, c = 0;
|
||||
while (pos < bytes.length) {
|
||||
var c1 = bytes[pos++];
|
||||
if (c1 < 128) {
|
||||
out[c++] = String.fromCharCode(c1);
|
||||
} else if (c1 > 191 && c1 < 224) {
|
||||
var c2 = bytes[pos++];
|
||||
out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
|
||||
} else {
|
||||
var c2 = bytes[pos++];
|
||||
var c3 = bytes[pos++];
|
||||
out[c++] = String.fromCharCode(
|
||||
(c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
|
||||
}
|
||||
}
|
||||
return out.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* XOR two byte arrays.
|
||||
* @param {!Array.<number>} bytes1 Byte array 1.
|
||||
* @param {!Array.<number>} bytes2 Byte array 2.
|
||||
* @return {!Array.<number>} Resulting XOR of the two byte arrays.
|
||||
*/
|
||||
goog.crypt.xorByteArray = function(bytes1, bytes2) {
|
||||
goog.asserts.assert(
|
||||
bytes1.length == bytes2.length,
|
||||
'XOR array lengths must match');
|
||||
|
||||
var result = [];
|
||||
for (var i = 0; i < bytes1.length; i++) {
|
||||
result.push(bytes1[i] ^ bytes2[i]);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
62
float-no-zero/closure-library/closure/goog/crypt/hash.js
Normal file
62
float-no-zero/closure-library/closure/goog/crypt/hash.js
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2011 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 Abstract cryptographic hash interface.
|
||||
*
|
||||
* See goog.crypt.Sha1 and goog.crypt.Md5 for sample implementations.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Hash');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a cryptographic hash instance.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.crypt.Hash = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Resets the internal accumulator.
|
||||
*/
|
||||
goog.crypt.Hash.prototype.reset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Adds a byte array (array with values in [0-255] range) or a string (might
|
||||
* only contain 8-bit, i.e., Latin1 characters) to the internal accumulator.
|
||||
*
|
||||
* Many hash functions operate on blocks of data and implement optimizations
|
||||
* when a full chunk of data is readily available. Hence it is often preferable
|
||||
* to provide large chunks of data (a kilobyte or more) than to repeatedly
|
||||
* call the update method with few tens of bytes. If this is not possible, or
|
||||
* not feasible, it might be good to provide data in multiplies of hash block
|
||||
* size (often 64 bytes). Please see the implementation and performance tests
|
||||
* of your favourite hash.
|
||||
*
|
||||
* @param {Array.<number>|Uint8Array|string} bytes Data used for the update.
|
||||
* @param {number=} opt_length Number of bytes to use.
|
||||
*/
|
||||
goog.crypt.Hash.prototype.update = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<number>} The finalized hash computed
|
||||
* from the internal accumulator.
|
||||
*/
|
||||
goog.crypt.Hash.prototype.digest = goog.abstractMethod;
|
||||
184
float-no-zero/closure-library/closure/goog/crypt/hash32.js
Normal file
184
float-no-zero/closure-library/closure/goog/crypt/hash32.js
Normal file
@@ -0,0 +1,184 @@
|
||||
// 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 Implementation of 32-bit hashing functions.
|
||||
*
|
||||
* This is a direct port from the Google Java Hash class
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.hash32');
|
||||
|
||||
goog.require('goog.crypt');
|
||||
|
||||
|
||||
/**
|
||||
* Default seed used during hashing, digits of pie.
|
||||
* See SEED32 in http://go/base.hash.java
|
||||
* @type {number}
|
||||
*/
|
||||
goog.crypt.hash32.SEED32 = 314159265;
|
||||
|
||||
|
||||
/**
|
||||
* Arbitrary constant used during hashing.
|
||||
* See CONSTANT32 in http://go/base.hash.java
|
||||
* @type {number}
|
||||
*/
|
||||
goog.crypt.hash32.CONSTANT32 = -1640531527;
|
||||
|
||||
|
||||
/**
|
||||
* Hashes a string to a 32-bit value.
|
||||
* @param {string} str String to hash.
|
||||
* @return {number} 32-bit hash.
|
||||
*/
|
||||
goog.crypt.hash32.encodeString = function(str) {
|
||||
return goog.crypt.hash32.encodeByteArray(goog.crypt.stringToByteArray(str));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hashes a string to a 32-bit value, converting the string to UTF-8 before
|
||||
* doing the encoding.
|
||||
* @param {string} str String to hash.
|
||||
* @return {number} 32-bit hash.
|
||||
*/
|
||||
goog.crypt.hash32.encodeStringUtf8 = function(str) {
|
||||
return goog.crypt.hash32.encodeByteArray(
|
||||
goog.crypt.stringToUtf8ByteArray(str));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hashes an integer to a 32-bit value.
|
||||
* @param {number} value Number to hash.
|
||||
* @return {number} 32-bit hash.
|
||||
*/
|
||||
goog.crypt.hash32.encodeInteger = function(value) {
|
||||
// TODO(user): Does this make sense in JavaScript with doubles? Should we
|
||||
// force the value to be in the correct range?
|
||||
return goog.crypt.hash32.mix32_({
|
||||
a: value,
|
||||
b: goog.crypt.hash32.CONSTANT32,
|
||||
c: goog.crypt.hash32.SEED32
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hashes a "byte" array to a 32-bit value using the supplied seed.
|
||||
* @param {Array.<number>} bytes Array of bytes.
|
||||
* @param {number=} opt_offset The starting position to use for hash
|
||||
* computation.
|
||||
* @param {number=} opt_length Number of bytes that are used for hashing.
|
||||
* @param {number=} opt_seed The seed.
|
||||
* @return {number} 32-bit hash.
|
||||
*/
|
||||
goog.crypt.hash32.encodeByteArray = function(
|
||||
bytes, opt_offset, opt_length, opt_seed) {
|
||||
var offset = opt_offset || 0;
|
||||
var length = opt_length || bytes.length;
|
||||
var seed = opt_seed || goog.crypt.hash32.SEED32;
|
||||
|
||||
var mix = {
|
||||
a: goog.crypt.hash32.CONSTANT32,
|
||||
b: goog.crypt.hash32.CONSTANT32,
|
||||
c: seed
|
||||
};
|
||||
|
||||
var keylen;
|
||||
for (keylen = length; keylen >= 12; keylen -= 12, offset += 12) {
|
||||
mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
|
||||
mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4);
|
||||
mix.c += goog.crypt.hash32.wordAt_(bytes, offset + 8);
|
||||
goog.crypt.hash32.mix32_(mix);
|
||||
}
|
||||
// Hash any remaining bytes
|
||||
mix.c += length;
|
||||
switch (keylen) { // deal with rest. Some cases fall through
|
||||
case 11: mix.c += (bytes[offset + 10]) << 24;
|
||||
case 10: mix.c += (bytes[offset + 9] & 0xff) << 16;
|
||||
case 9 : mix.c += (bytes[offset + 8] & 0xff) << 8;
|
||||
// the first byte of c is reserved for the length
|
||||
case 8 :
|
||||
mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4);
|
||||
mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
|
||||
break;
|
||||
case 7 : mix.b += (bytes[offset + 6] & 0xff) << 16;
|
||||
case 6 : mix.b += (bytes[offset + 5] & 0xff) << 8;
|
||||
case 5 : mix.b += (bytes[offset + 4] & 0xff);
|
||||
case 4 :
|
||||
mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
|
||||
break;
|
||||
case 3 : mix.a += (bytes[offset + 2] & 0xff) << 16;
|
||||
case 2 : mix.a += (bytes[offset + 1] & 0xff) << 8;
|
||||
case 1 : mix.a += (bytes[offset + 0] & 0xff);
|
||||
// case 0 : nothing left to add
|
||||
}
|
||||
return goog.crypt.hash32.mix32_(mix);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Performs an inplace mix of an object with the integer properties (a, b, c)
|
||||
* and returns the final value of c.
|
||||
* @param {Object} mix Object with properties, a, b, and c.
|
||||
* @return {number} The end c-value for the mixing.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.hash32.mix32_ = function(mix) {
|
||||
var a = mix.a, b = mix.b, c = mix.c;
|
||||
a -= b; a -= c; a ^= c >>> 13;
|
||||
b -= c; b -= a; b ^= a << 8;
|
||||
c -= a; c -= b; c ^= b >>> 13;
|
||||
a -= b; a -= c; a ^= c >>> 12;
|
||||
b -= c; b -= a; b ^= a << 16;
|
||||
c -= a; c -= b; c ^= b >>> 5;
|
||||
a -= b; a -= c; a ^= c >>> 3;
|
||||
b -= c; b -= a; b ^= a << 10;
|
||||
c -= a; c -= b; c ^= b >>> 15;
|
||||
mix.a = a; mix.b = b; mix.c = c;
|
||||
return c;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the word at a given offset. Treating an array of bytes a word at a
|
||||
* time is far more efficient than byte-by-byte.
|
||||
* @param {Array.<number>} bytes Array of bytes.
|
||||
* @param {number} offset Offset in the byte array.
|
||||
* @return {number} Integer value for the word.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.hash32.wordAt_ = function(bytes, offset) {
|
||||
var a = goog.crypt.hash32.toSigned_(bytes[offset + 0]);
|
||||
var b = goog.crypt.hash32.toSigned_(bytes[offset + 1]);
|
||||
var c = goog.crypt.hash32.toSigned_(bytes[offset + 2]);
|
||||
var d = goog.crypt.hash32.toSigned_(bytes[offset + 3]);
|
||||
return a + (b << 8) + (c << 16) + (d << 24);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an unsigned "byte" to signed, that is, convert a value in the range
|
||||
* (0, 2^8-1) to (-2^7, 2^7-1) in order to be compatible with Java's byte type.
|
||||
* @param {number} n Unsigned "byte" value.
|
||||
* @return {number} Signed "byte" value.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.hash32.toSigned_ = function(n) {
|
||||
return n > 127 ? n - 256 : n;
|
||||
};
|
||||
243
float-no-zero/closure-library/closure/goog/crypt/hashtester.js
Normal file
243
float-no-zero/closure-library/closure/goog/crypt/hashtester.js
Normal file
@@ -0,0 +1,243 @@
|
||||
// Copyright 2011 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 Unit tests for the abstract cryptographic hash interface.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.hashTester');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.crypt');
|
||||
goog.require('goog.testing.PerformanceTable');
|
||||
goog.require('goog.testing.PseudoRandom');
|
||||
goog.require('goog.testing.asserts');
|
||||
goog.setTestOnly('hashTester');
|
||||
|
||||
|
||||
/**
|
||||
* Runs basic tests.
|
||||
*
|
||||
* @param {!goog.crypt.Hash} hash A hash instance.
|
||||
*/
|
||||
goog.crypt.hashTester.runBasicTests = function(hash) {
|
||||
// Compute first hash.
|
||||
hash.update([97, 158]);
|
||||
var golden1 = hash.digest();
|
||||
|
||||
// Compute second hash.
|
||||
hash.reset();
|
||||
hash.update('aB');
|
||||
var golden2 = hash.digest();
|
||||
assertTrue('Two different inputs resulted in a hash collision',
|
||||
!!goog.testing.asserts.findDifferences(golden1, golden2));
|
||||
|
||||
// Empty hash.
|
||||
hash.reset();
|
||||
var empty = hash.digest();
|
||||
assertTrue('Empty hash collided with a non-trivial one',
|
||||
!!goog.testing.asserts.findDifferences(golden1, empty) &&
|
||||
!!goog.testing.asserts.findDifferences(golden2, empty));
|
||||
|
||||
// Zero-length array update.
|
||||
hash.reset();
|
||||
hash.update([]);
|
||||
assertArrayEquals('Updating with an empty array did not give an empty hash',
|
||||
empty, hash.digest());
|
||||
|
||||
// Zero-length string update.
|
||||
hash.reset();
|
||||
hash.update('');
|
||||
assertArrayEquals('Updating with an empty string did not give an empty hash',
|
||||
empty, hash.digest());
|
||||
|
||||
// Recompute the first hash.
|
||||
hash.reset();
|
||||
hash.update([97, 158]);
|
||||
assertArrayEquals('The reset did not produce the initial state',
|
||||
golden1, hash.digest());
|
||||
|
||||
// Check for a trivial collision.
|
||||
hash.reset();
|
||||
hash.update([158, 97]);
|
||||
assertTrue('Swapping bytes resulted in a hash collision',
|
||||
!!goog.testing.asserts.findDifferences(golden1, hash.digest()));
|
||||
|
||||
// Compare array and string input.
|
||||
hash.reset();
|
||||
hash.update([97, 66]);
|
||||
assertArrayEquals('String and array inputs should give the same result',
|
||||
golden2, hash.digest());
|
||||
|
||||
// Compute in parts.
|
||||
hash.reset();
|
||||
hash.update('a');
|
||||
hash.update([158]);
|
||||
assertArrayEquals('Partial updates resulted in a different hash',
|
||||
golden1, hash.digest());
|
||||
|
||||
// Test update with specified length.
|
||||
hash.reset();
|
||||
hash.update('aB', 0);
|
||||
hash.update([97, 158, 32], 2);
|
||||
assertArrayEquals('Updating with an explicit buffer length did not work',
|
||||
golden1, hash.digest());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Runs block tests.
|
||||
*
|
||||
* @param {!goog.crypt.Hash} hash A hash instance.
|
||||
* @param {number} blockBytes Size of the hash block.
|
||||
*/
|
||||
goog.crypt.hashTester.runBlockTests = function(hash, blockBytes) {
|
||||
// Compute a message which is 1 byte shorter than hash block size.
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var message = '';
|
||||
for (var i = 0; i < blockBytes - 1; i++) {
|
||||
message += chars.charAt(i % chars.length);
|
||||
}
|
||||
|
||||
// Compute golden hash for 1 block + 2 bytes.
|
||||
hash.update(message + '123');
|
||||
var golden1 = hash.digest();
|
||||
|
||||
// Compute golden hash for 2 blocks + 1 byte.
|
||||
hash.reset();
|
||||
hash.update(message + message + '123');
|
||||
var golden2 = hash.digest();
|
||||
|
||||
// Almost fill a block, then overflow.
|
||||
hash.reset();
|
||||
hash.update(message);
|
||||
hash.update('123');
|
||||
assertArrayEquals(golden1, hash.digest());
|
||||
|
||||
// Fill a block.
|
||||
hash.reset();
|
||||
hash.update(message + '1');
|
||||
hash.update('23');
|
||||
assertArrayEquals(golden1, hash.digest());
|
||||
|
||||
// Overflow a block.
|
||||
hash.reset();
|
||||
hash.update(message + '12');
|
||||
hash.update('3');
|
||||
assertArrayEquals(golden1, hash.digest());
|
||||
|
||||
// Test single overflow with an array.
|
||||
hash.reset();
|
||||
hash.update(goog.crypt.stringToByteArray(message + '123'));
|
||||
assertArrayEquals(golden1, hash.digest());
|
||||
|
||||
// Almost fill a block, then overflow this and the next block.
|
||||
hash.reset();
|
||||
hash.update(message);
|
||||
hash.update(message + '123');
|
||||
assertArrayEquals(golden2, hash.digest());
|
||||
|
||||
// Fill two blocks.
|
||||
hash.reset();
|
||||
hash.update(message + message + '12');
|
||||
hash.update('3');
|
||||
assertArrayEquals(golden2, hash.digest());
|
||||
|
||||
// Test double overflow with an array.
|
||||
hash.reset();
|
||||
hash.update(goog.crypt.stringToByteArray(message));
|
||||
hash.update(goog.crypt.stringToByteArray(message + '123'));
|
||||
assertArrayEquals(golden2, hash.digest());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Runs performance tests.
|
||||
*
|
||||
* @param {function():!goog.crypt.Hash} hashFactory A hash factory.
|
||||
* @param {string} hashName Name of the hashing function.
|
||||
*/
|
||||
goog.crypt.hashTester.runPerfTests = function(hashFactory, hashName) {
|
||||
var body = goog.dom.getDocument().body;
|
||||
var perfTable = goog.dom.createElement('div');
|
||||
goog.dom.appendChild(body, perfTable);
|
||||
|
||||
var table = new goog.testing.PerformanceTable(perfTable);
|
||||
|
||||
function runPerfTest(byteLength, updateCount) {
|
||||
var label = (hashName + ': ' + updateCount + ' update(s) of ' + byteLength +
|
||||
' bytes');
|
||||
|
||||
function run(data, dataType) {
|
||||
table.run(function() {
|
||||
var hash = hashFactory();
|
||||
for (var i = 0; i < updateCount; i++) {
|
||||
hash.update(data, byteLength);
|
||||
}
|
||||
var digest = hash.digest();
|
||||
}, label + ' (' + dataType + ')');
|
||||
}
|
||||
|
||||
var byteArray = goog.crypt.hashTester.createRandomByteArray_(byteLength);
|
||||
var byteString = goog.crypt.hashTester.createByteString_(byteArray);
|
||||
|
||||
run(byteArray, 'byte array');
|
||||
run(byteString, 'byte string');
|
||||
}
|
||||
|
||||
var MESSAGE_LENGTH_LONG = 10000000; // 10 Mbytes
|
||||
var MESSAGE_LENGTH_SHORT = 10; // 10 bytes
|
||||
var MESSAGE_COUNT_SHORT = MESSAGE_LENGTH_LONG / MESSAGE_LENGTH_SHORT;
|
||||
|
||||
runPerfTest(MESSAGE_LENGTH_LONG, 1);
|
||||
runPerfTest(MESSAGE_LENGTH_SHORT, MESSAGE_COUNT_SHORT);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates and returns a random byte array.
|
||||
*
|
||||
* @param {number} length Length of the byte array.
|
||||
* @return {!Array.<number>} An array of bytes.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.hashTester.createRandomByteArray_ = function(length) {
|
||||
var random = new goog.testing.PseudoRandom(0);
|
||||
var bytes = [];
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
// Generates an integer from 0 to 255.
|
||||
var b = Math.floor(random.random() * 0x100);
|
||||
bytes.push(b);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string from an array of bytes.
|
||||
*
|
||||
* @param {!Array.<number>} bytes An array of bytes.
|
||||
* @return {string} The string encoded by the bytes.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.hashTester.createByteString_ = function(bytes) {
|
||||
var str = '';
|
||||
goog.array.forEach(bytes, function(b) {
|
||||
str += String.fromCharCode(b);
|
||||
});
|
||||
return str;
|
||||
};
|
||||
162
float-no-zero/closure-library/closure/goog/crypt/hmac.js
Normal file
162
float-no-zero/closure-library/closure/goog/crypt/hmac.js
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright 2011 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 Implementation of HMAC in JavaScript.
|
||||
*
|
||||
* Usage:
|
||||
* var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64);
|
||||
* var digest = hmac.getHmac(bytes);
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.crypt.Hmac');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.crypt.Hash');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {!goog.crypt.Hash} hasher An object to serve as a hash function.
|
||||
* @param {Array.<number>} key The secret key to use to calculate the hmac.
|
||||
* Should be an array of not more than {@code blockSize} integers in
|
||||
{0, 255}.
|
||||
* @param {number=} opt_blockSize Optional. The block size {@code hasher} uses.
|
||||
* If not specified, 16.
|
||||
* @extends {goog.crypt.Hash}
|
||||
*/
|
||||
goog.crypt.Hmac = function(hasher, key, opt_blockSize) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* The underlying hasher to calculate hash.
|
||||
*
|
||||
* @type {!goog.crypt.Hash}
|
||||
* @private
|
||||
*/
|
||||
this.hasher_ = hasher;
|
||||
|
||||
/**
|
||||
* The block size.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.blockSize_ = opt_blockSize || 16;
|
||||
|
||||
/**
|
||||
* The outer padding array of hmac
|
||||
*
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.keyO_ = new Array(this.blockSize_);
|
||||
|
||||
/**
|
||||
* The inner padding array of hmac
|
||||
*
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.keyI_ = new Array(this.blockSize_);
|
||||
|
||||
this.initialize_(key);
|
||||
};
|
||||
goog.inherits(goog.crypt.Hmac, goog.crypt.Hash);
|
||||
|
||||
|
||||
/**
|
||||
* Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Hmac.OPAD_ = 0x5c;
|
||||
|
||||
|
||||
/**
|
||||
* Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Hmac.IPAD_ = 0x36;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes Hmac by precalculating the inner and outer paddings.
|
||||
*
|
||||
* @param {Array.<number>} key The secret key to use to calculate the hmac.
|
||||
* Should be an array of not more than {@code blockSize} integers in
|
||||
{0, 255}.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Hmac.prototype.initialize_ = function(key) {
|
||||
if (key.length > this.blockSize_) {
|
||||
this.hasher_.update(key);
|
||||
key = this.hasher_.digest();
|
||||
}
|
||||
// Precalculate padded and xor'd keys.
|
||||
var keyByte;
|
||||
for (var i = 0; i < this.blockSize_; i++) {
|
||||
if (i < key.length) {
|
||||
keyByte = key[i];
|
||||
} else {
|
||||
keyByte = 0;
|
||||
}
|
||||
this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_;
|
||||
this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_;
|
||||
}
|
||||
// Be ready for an immediate update.
|
||||
this.hasher_.update(this.keyI_);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Hmac.prototype.reset = function() {
|
||||
this.hasher_.reset();
|
||||
this.hasher_.update(this.keyI_);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Hmac.prototype.update = function(bytes, opt_length) {
|
||||
this.hasher_.update(bytes, opt_length);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Hmac.prototype.digest = function() {
|
||||
var temp = this.hasher_.digest();
|
||||
this.hasher_.reset();
|
||||
this.hasher_.update(this.keyO_);
|
||||
this.hasher_.update(temp);
|
||||
return this.hasher_.digest();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates an HMAC for a given message.
|
||||
*
|
||||
* @param {Array.<number>} message An array of integers in {0, 255}.
|
||||
* @return {!Array.<number>} the digest of the given message.
|
||||
*/
|
||||
goog.crypt.Hmac.prototype.getHmac = function(message) {
|
||||
this.reset();
|
||||
this.update(message);
|
||||
return this.digest();
|
||||
};
|
||||
429
float-no-zero/closure-library/closure/goog/crypt/md5.js
Normal file
429
float-no-zero/closure-library/closure/goog/crypt/md5.js
Normal file
@@ -0,0 +1,429 @@
|
||||
// Copyright 2011 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 MD5 cryptographic hash.
|
||||
* Implementation of http://tools.ietf.org/html/rfc1321 with common
|
||||
* optimizations and tweaks (see http://en.wikipedia.org/wiki/MD5).
|
||||
*
|
||||
* Usage:
|
||||
* var md5 = new goog.crypt.Md5();
|
||||
* md5.update(bytes);
|
||||
* var hash = md5.digest();
|
||||
*
|
||||
* Performance:
|
||||
* Chrome 23 ~680 Mbit/s
|
||||
* Chrome 13 (in a VM) ~250 Mbit/s
|
||||
* Firefox 6.0 (in a VM) ~100 Mbit/s
|
||||
* IE9 (in a VM) ~27 Mbit/s
|
||||
* Firefox 3.6 ~15 Mbit/s
|
||||
* IE8 (in a VM) ~13 Mbit/s
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Md5');
|
||||
|
||||
goog.require('goog.crypt.Hash');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MD5 cryptographic hash constructor.
|
||||
* @constructor
|
||||
* @extends {goog.crypt.Hash}
|
||||
*/
|
||||
goog.crypt.Md5 = function() {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Holds the current values of accumulated A-D variables (MD buffer).
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.chain_ = new Array(4);
|
||||
|
||||
/**
|
||||
* A buffer holding the data until the whole block can be processed.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.block_ = new Array(64);
|
||||
|
||||
/**
|
||||
* The length of yet-unprocessed data as collected in the block.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.blockLength_ = 0;
|
||||
|
||||
/**
|
||||
* The total length of the message so far.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.totalLength_ = 0;
|
||||
|
||||
this.reset();
|
||||
};
|
||||
goog.inherits(goog.crypt.Md5, goog.crypt.Hash);
|
||||
|
||||
|
||||
/**
|
||||
* Integer rotation constants used by the abbreviated implementation.
|
||||
* They are hardcoded in the unrolled implementation, so it is left
|
||||
* here commented out.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*
|
||||
goog.crypt.Md5.S_ = [
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
|
||||
];
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sine function constants used by the abbreviated implementation.
|
||||
* They are hardcoded in the unrolled implementation, so it is left
|
||||
* here commented out.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*
|
||||
goog.crypt.Md5.T_ = [
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
];
|
||||
*/
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Md5.prototype.reset = function() {
|
||||
this.chain_[0] = 0x67452301;
|
||||
this.chain_[1] = 0xefcdab89;
|
||||
this.chain_[2] = 0x98badcfe;
|
||||
this.chain_[3] = 0x10325476;
|
||||
|
||||
this.blockLength_ = 0;
|
||||
this.totalLength_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal compress helper function. It takes a block of data (64 bytes)
|
||||
* and updates the accumulator.
|
||||
* @param {Array.<number>|Uint8Array|string} buf The block to compress.
|
||||
* @param {number=} opt_offset Offset of the block in the buffer.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) {
|
||||
if (!opt_offset) {
|
||||
opt_offset = 0;
|
||||
}
|
||||
|
||||
// We allocate the array every time, but it's cheap in practice.
|
||||
var X = new Array(16);
|
||||
|
||||
// Get 16 little endian words. It is not worth unrolling this for Chrome 11.
|
||||
if (goog.isString(buf)) {
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
X[i] = (buf.charCodeAt(opt_offset++)) |
|
||||
(buf.charCodeAt(opt_offset++) << 8) |
|
||||
(buf.charCodeAt(opt_offset++) << 16) |
|
||||
(buf.charCodeAt(opt_offset++) << 24);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < 16; ++i) {
|
||||
X[i] = (buf[opt_offset++]) |
|
||||
(buf[opt_offset++] << 8) |
|
||||
(buf[opt_offset++] << 16) |
|
||||
(buf[opt_offset++] << 24);
|
||||
}
|
||||
}
|
||||
|
||||
var A = this.chain_[0];
|
||||
var B = this.chain_[1];
|
||||
var C = this.chain_[2];
|
||||
var D = this.chain_[3];
|
||||
var sum = 0;
|
||||
|
||||
/*
|
||||
* This is an abbreviated implementation, it is left here commented out for
|
||||
* reference purposes. See below for an unrolled version in use.
|
||||
*
|
||||
var f, n, tmp;
|
||||
for (var i = 0; i < 64; ++i) {
|
||||
|
||||
if (i < 16) {
|
||||
f = (D ^ (B & (C ^ D)));
|
||||
n = i;
|
||||
} else if (i < 32) {
|
||||
f = (C ^ (D & (B ^ C)));
|
||||
n = (5 * i + 1) % 16;
|
||||
} else if (i < 48) {
|
||||
f = (B ^ C ^ D);
|
||||
n = (3 * i + 5) % 16;
|
||||
} else {
|
||||
f = (C ^ (B | (~D)));
|
||||
n = (7 * i) % 16;
|
||||
}
|
||||
|
||||
tmp = D;
|
||||
D = C;
|
||||
C = B;
|
||||
sum = (A + f + goog.crypt.Md5.T_[i] + X[n]) & 0xffffffff;
|
||||
B += ((sum << goog.crypt.Md5.S_[i]) & 0xffffffff) |
|
||||
(sum >>> (32 - goog.crypt.Md5.S_[i]));
|
||||
A = tmp;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an unrolled MD5 implementation, which gives ~30% speedup compared
|
||||
* to the abbreviated implementation above, as measured on Chrome 11. It is
|
||||
* important to keep 32-bit croppings to minimum and inline the integer
|
||||
* rotation.
|
||||
*/
|
||||
sum = (A + (D ^ (B & (C ^ D))) + X[0] + 0xd76aa478) & 0xffffffff;
|
||||
A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
|
||||
sum = (D + (C ^ (A & (B ^ C))) + X[1] + 0xe8c7b756) & 0xffffffff;
|
||||
D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
|
||||
sum = (C + (B ^ (D & (A ^ B))) + X[2] + 0x242070db) & 0xffffffff;
|
||||
C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
|
||||
sum = (B + (A ^ (C & (D ^ A))) + X[3] + 0xc1bdceee) & 0xffffffff;
|
||||
B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
|
||||
sum = (A + (D ^ (B & (C ^ D))) + X[4] + 0xf57c0faf) & 0xffffffff;
|
||||
A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
|
||||
sum = (D + (C ^ (A & (B ^ C))) + X[5] + 0x4787c62a) & 0xffffffff;
|
||||
D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
|
||||
sum = (C + (B ^ (D & (A ^ B))) + X[6] + 0xa8304613) & 0xffffffff;
|
||||
C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
|
||||
sum = (B + (A ^ (C & (D ^ A))) + X[7] + 0xfd469501) & 0xffffffff;
|
||||
B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
|
||||
sum = (A + (D ^ (B & (C ^ D))) + X[8] + 0x698098d8) & 0xffffffff;
|
||||
A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
|
||||
sum = (D + (C ^ (A & (B ^ C))) + X[9] + 0x8b44f7af) & 0xffffffff;
|
||||
D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
|
||||
sum = (C + (B ^ (D & (A ^ B))) + X[10] + 0xffff5bb1) & 0xffffffff;
|
||||
C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
|
||||
sum = (B + (A ^ (C & (D ^ A))) + X[11] + 0x895cd7be) & 0xffffffff;
|
||||
B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
|
||||
sum = (A + (D ^ (B & (C ^ D))) + X[12] + 0x6b901122) & 0xffffffff;
|
||||
A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
|
||||
sum = (D + (C ^ (A & (B ^ C))) + X[13] + 0xfd987193) & 0xffffffff;
|
||||
D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
|
||||
sum = (C + (B ^ (D & (A ^ B))) + X[14] + 0xa679438e) & 0xffffffff;
|
||||
C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
|
||||
sum = (B + (A ^ (C & (D ^ A))) + X[15] + 0x49b40821) & 0xffffffff;
|
||||
B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
|
||||
sum = (A + (C ^ (D & (B ^ C))) + X[1] + 0xf61e2562) & 0xffffffff;
|
||||
A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
|
||||
sum = (D + (B ^ (C & (A ^ B))) + X[6] + 0xc040b340) & 0xffffffff;
|
||||
D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
|
||||
sum = (C + (A ^ (B & (D ^ A))) + X[11] + 0x265e5a51) & 0xffffffff;
|
||||
C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
|
||||
sum = (B + (D ^ (A & (C ^ D))) + X[0] + 0xe9b6c7aa) & 0xffffffff;
|
||||
B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
|
||||
sum = (A + (C ^ (D & (B ^ C))) + X[5] + 0xd62f105d) & 0xffffffff;
|
||||
A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
|
||||
sum = (D + (B ^ (C & (A ^ B))) + X[10] + 0x02441453) & 0xffffffff;
|
||||
D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
|
||||
sum = (C + (A ^ (B & (D ^ A))) + X[15] + 0xd8a1e681) & 0xffffffff;
|
||||
C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
|
||||
sum = (B + (D ^ (A & (C ^ D))) + X[4] + 0xe7d3fbc8) & 0xffffffff;
|
||||
B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
|
||||
sum = (A + (C ^ (D & (B ^ C))) + X[9] + 0x21e1cde6) & 0xffffffff;
|
||||
A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
|
||||
sum = (D + (B ^ (C & (A ^ B))) + X[14] + 0xc33707d6) & 0xffffffff;
|
||||
D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
|
||||
sum = (C + (A ^ (B & (D ^ A))) + X[3] + 0xf4d50d87) & 0xffffffff;
|
||||
C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
|
||||
sum = (B + (D ^ (A & (C ^ D))) + X[8] + 0x455a14ed) & 0xffffffff;
|
||||
B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
|
||||
sum = (A + (C ^ (D & (B ^ C))) + X[13] + 0xa9e3e905) & 0xffffffff;
|
||||
A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
|
||||
sum = (D + (B ^ (C & (A ^ B))) + X[2] + 0xfcefa3f8) & 0xffffffff;
|
||||
D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
|
||||
sum = (C + (A ^ (B & (D ^ A))) + X[7] + 0x676f02d9) & 0xffffffff;
|
||||
C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
|
||||
sum = (B + (D ^ (A & (C ^ D))) + X[12] + 0x8d2a4c8a) & 0xffffffff;
|
||||
B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
|
||||
sum = (A + (B ^ C ^ D) + X[5] + 0xfffa3942) & 0xffffffff;
|
||||
A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
|
||||
sum = (D + (A ^ B ^ C) + X[8] + 0x8771f681) & 0xffffffff;
|
||||
D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
|
||||
sum = (C + (D ^ A ^ B) + X[11] + 0x6d9d6122) & 0xffffffff;
|
||||
C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
|
||||
sum = (B + (C ^ D ^ A) + X[14] + 0xfde5380c) & 0xffffffff;
|
||||
B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
|
||||
sum = (A + (B ^ C ^ D) + X[1] + 0xa4beea44) & 0xffffffff;
|
||||
A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
|
||||
sum = (D + (A ^ B ^ C) + X[4] + 0x4bdecfa9) & 0xffffffff;
|
||||
D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
|
||||
sum = (C + (D ^ A ^ B) + X[7] + 0xf6bb4b60) & 0xffffffff;
|
||||
C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
|
||||
sum = (B + (C ^ D ^ A) + X[10] + 0xbebfbc70) & 0xffffffff;
|
||||
B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
|
||||
sum = (A + (B ^ C ^ D) + X[13] + 0x289b7ec6) & 0xffffffff;
|
||||
A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
|
||||
sum = (D + (A ^ B ^ C) + X[0] + 0xeaa127fa) & 0xffffffff;
|
||||
D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
|
||||
sum = (C + (D ^ A ^ B) + X[3] + 0xd4ef3085) & 0xffffffff;
|
||||
C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
|
||||
sum = (B + (C ^ D ^ A) + X[6] + 0x04881d05) & 0xffffffff;
|
||||
B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
|
||||
sum = (A + (B ^ C ^ D) + X[9] + 0xd9d4d039) & 0xffffffff;
|
||||
A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
|
||||
sum = (D + (A ^ B ^ C) + X[12] + 0xe6db99e5) & 0xffffffff;
|
||||
D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
|
||||
sum = (C + (D ^ A ^ B) + X[15] + 0x1fa27cf8) & 0xffffffff;
|
||||
C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
|
||||
sum = (B + (C ^ D ^ A) + X[2] + 0xc4ac5665) & 0xffffffff;
|
||||
B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
|
||||
sum = (A + (C ^ (B | (~D))) + X[0] + 0xf4292244) & 0xffffffff;
|
||||
A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
|
||||
sum = (D + (B ^ (A | (~C))) + X[7] + 0x432aff97) & 0xffffffff;
|
||||
D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
|
||||
sum = (C + (A ^ (D | (~B))) + X[14] + 0xab9423a7) & 0xffffffff;
|
||||
C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
|
||||
sum = (B + (D ^ (C | (~A))) + X[5] + 0xfc93a039) & 0xffffffff;
|
||||
B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
|
||||
sum = (A + (C ^ (B | (~D))) + X[12] + 0x655b59c3) & 0xffffffff;
|
||||
A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
|
||||
sum = (D + (B ^ (A | (~C))) + X[3] + 0x8f0ccc92) & 0xffffffff;
|
||||
D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
|
||||
sum = (C + (A ^ (D | (~B))) + X[10] + 0xffeff47d) & 0xffffffff;
|
||||
C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
|
||||
sum = (B + (D ^ (C | (~A))) + X[1] + 0x85845dd1) & 0xffffffff;
|
||||
B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
|
||||
sum = (A + (C ^ (B | (~D))) + X[8] + 0x6fa87e4f) & 0xffffffff;
|
||||
A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
|
||||
sum = (D + (B ^ (A | (~C))) + X[15] + 0xfe2ce6e0) & 0xffffffff;
|
||||
D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
|
||||
sum = (C + (A ^ (D | (~B))) + X[6] + 0xa3014314) & 0xffffffff;
|
||||
C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
|
||||
sum = (B + (D ^ (C | (~A))) + X[13] + 0x4e0811a1) & 0xffffffff;
|
||||
B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
|
||||
sum = (A + (C ^ (B | (~D))) + X[4] + 0xf7537e82) & 0xffffffff;
|
||||
A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
|
||||
sum = (D + (B ^ (A | (~C))) + X[11] + 0xbd3af235) & 0xffffffff;
|
||||
D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
|
||||
sum = (C + (A ^ (D | (~B))) + X[2] + 0x2ad7d2bb) & 0xffffffff;
|
||||
C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
|
||||
sum = (B + (D ^ (C | (~A))) + X[9] + 0xeb86d391) & 0xffffffff;
|
||||
B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
|
||||
|
||||
this.chain_[0] = (this.chain_[0] + A) & 0xffffffff;
|
||||
this.chain_[1] = (this.chain_[1] + B) & 0xffffffff;
|
||||
this.chain_[2] = (this.chain_[2] + C) & 0xffffffff;
|
||||
this.chain_[3] = (this.chain_[3] + D) & 0xffffffff;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Md5.prototype.update = function(bytes, opt_length) {
|
||||
if (!goog.isDef(opt_length)) {
|
||||
opt_length = bytes.length;
|
||||
}
|
||||
var lengthMinusBlock = opt_length - 64;
|
||||
|
||||
// Copy some object properties to local variables in order to save on access
|
||||
// time from inside the loop (~10% speedup was observed on Chrome 11).
|
||||
var block = this.block_;
|
||||
var blockLength = this.blockLength_;
|
||||
var i = 0;
|
||||
|
||||
// The outer while loop should execute at most twice.
|
||||
while (i < opt_length) {
|
||||
// When we have no data in the block to top up, we can directly process the
|
||||
// input buffer (assuming it contains sufficient data). This gives ~30%
|
||||
// speedup on Chrome 14 and ~70% speedup on Firefox 6.0, but requires that
|
||||
// the data is provided in large chunks (or in multiples of 64 bytes).
|
||||
if (blockLength == 0) {
|
||||
while (i <= lengthMinusBlock) {
|
||||
this.compress_(bytes, i);
|
||||
i += 64;
|
||||
}
|
||||
}
|
||||
|
||||
if (goog.isString(bytes)) {
|
||||
while (i < opt_length) {
|
||||
block[blockLength++] = bytes.charCodeAt(i++);
|
||||
if (blockLength == 64) {
|
||||
this.compress_(block);
|
||||
blockLength = 0;
|
||||
// Jump to the outer loop so we use the full-block optimization.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (i < opt_length) {
|
||||
block[blockLength++] = bytes[i++];
|
||||
if (blockLength == 64) {
|
||||
this.compress_(block);
|
||||
blockLength = 0;
|
||||
// Jump to the outer loop so we use the full-block optimization.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.blockLength_ = blockLength;
|
||||
this.totalLength_ += opt_length;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Md5.prototype.digest = function() {
|
||||
// This must accommodate at least 1 padding byte (0x80), 8 bytes of
|
||||
// total bitlength, and must end at a 64-byte boundary.
|
||||
var pad = new Array((this.blockLength_ < 56 ? 64 : 128) - this.blockLength_);
|
||||
|
||||
// Add padding: 0x80 0x00*
|
||||
pad[0] = 0x80;
|
||||
for (var i = 1; i < pad.length - 8; ++i) {
|
||||
pad[i] = 0;
|
||||
}
|
||||
// Add the total number of bits, little endian 64-bit integer.
|
||||
var totalBits = this.totalLength_ * 8;
|
||||
for (var i = pad.length - 8; i < pad.length; ++i) {
|
||||
pad[i] = totalBits & 0xff;
|
||||
totalBits /= 0x100; // Don't use bit-shifting here!
|
||||
}
|
||||
this.update(pad);
|
||||
|
||||
var digest = new Array(16);
|
||||
var n = 0;
|
||||
for (var i = 0; i < 4; ++i) {
|
||||
for (var j = 0; j < 32; j += 8) {
|
||||
digest[n++] = (this.chain_[i] >>> j) & 0xff;
|
||||
}
|
||||
}
|
||||
return digest;
|
||||
};
|
||||
127
float-no-zero/closure-library/closure/goog/crypt/pbkdf2.js
Normal file
127
float-no-zero/closure-library/closure/goog/crypt/pbkdf2.js
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2012 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 Implementation of PBKDF2 in JavaScript.
|
||||
* @see http://en.wikipedia.org/wiki/PBKDF2
|
||||
*
|
||||
* Currently we only support HMAC-SHA1 as the underlying hash function. To add a
|
||||
* new hash function, add a static method similar to deriveKeyFromPasswordSha1()
|
||||
* and implement the specific computeBlockCallback() using the hash function.
|
||||
*
|
||||
* Usage:
|
||||
* var key = pbkdf2.deriveKeySha1(
|
||||
* stringToByteArray('password'), stringToByteArray('salt'), 1000, 128);
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.pbkdf2');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.crypt');
|
||||
goog.require('goog.crypt.Hmac');
|
||||
goog.require('goog.crypt.Sha1');
|
||||
|
||||
|
||||
/**
|
||||
* Derives key from password using PBKDF2-SHA1
|
||||
* @param {!Array.<number>} password Byte array representation of the password
|
||||
* from which the key is derived.
|
||||
* @param {!Array.<number>} initialSalt Byte array representation of the salt.
|
||||
* @param {number} iterations Number of interations when computing the key.
|
||||
* @param {number} keyLength Length of the output key in bits.
|
||||
* Must be multiple of 8.
|
||||
* @return {!Array.<number>} Byte array representation of the output key.
|
||||
*/
|
||||
goog.crypt.pbkdf2.deriveKeySha1 = function(
|
||||
password, initialSalt, iterations, keyLength) {
|
||||
// Length of the HMAC-SHA1 output in bits.
|
||||
var HASH_LENGTH = 160;
|
||||
|
||||
/**
|
||||
* Compute each block of the key using HMAC-SHA1.
|
||||
* @param {!Array.<number>} index Byte array representation of the index of
|
||||
* the block to be computed.
|
||||
* @return {!Array.<number>} Byte array representation of the output block.
|
||||
*/
|
||||
var computeBlock = function(index) {
|
||||
// Initialize the result to be array of 0 such that its xor with the first
|
||||
// block would be the first block.
|
||||
var result = goog.array.repeat(0, HASH_LENGTH / 8);
|
||||
// Initialize the salt of the first iteration to initialSalt || i.
|
||||
var salt = initialSalt.concat(index);
|
||||
var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), password, 64);
|
||||
// Compute and XOR each iteration.
|
||||
for (var i = 0; i < iterations; i++) {
|
||||
// The salt of the next iteration is the result of the current iteration.
|
||||
salt = hmac.getHmac(salt);
|
||||
result = goog.crypt.xorByteArray(result, salt);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
return goog.crypt.pbkdf2.deriveKeyFromPassword_(
|
||||
computeBlock, HASH_LENGTH, keyLength);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compute each block of the key using PBKDF2.
|
||||
* @param {Function} computeBlock Function to compute each block of the output
|
||||
* key.
|
||||
* @param {number} hashLength Length of each block in bits. This is determined
|
||||
* by the specific hash function used. Must be multiple of 8.
|
||||
* @param {number} keyLength Length of the output key in bits.
|
||||
* Must be multiple of 8.
|
||||
* @return {!Array.<number>} Byte array representation of the output key.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.pbkdf2.deriveKeyFromPassword_ =
|
||||
function(computeBlock, hashLength, keyLength) {
|
||||
goog.asserts.assert(keyLength % 8 == 0, 'invalid output key length');
|
||||
|
||||
// Compute and concactate each block of the output key.
|
||||
var numBlocks = Math.ceil(keyLength / hashLength);
|
||||
goog.asserts.assert(numBlocks >= 1, 'invalid number of blocks');
|
||||
var result = [];
|
||||
for (var i = 1; i <= numBlocks; i++) {
|
||||
var indexBytes = goog.crypt.pbkdf2.integerToByteArray_(i);
|
||||
result = result.concat(computeBlock(indexBytes));
|
||||
}
|
||||
|
||||
// Trim the last block if needed.
|
||||
var lastBlockSize = keyLength % hashLength;
|
||||
if (lastBlockSize != 0) {
|
||||
var desiredBytes = ((numBlocks - 1) * hashLength + lastBlockSize) / 8;
|
||||
result.splice(desiredBytes, (hashLength - lastBlockSize) / 8);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an integer number to a 32-bit big endian byte array.
|
||||
* @param {number} n Integer number to be converted.
|
||||
* @return {!Array.<number>} Byte Array representation of the 32-bit big endian
|
||||
* encoding of n.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.pbkdf2.integerToByteArray_ = function(n) {
|
||||
var result = new Array(4);
|
||||
result[0] = n >> 24 & 0xFF;
|
||||
result[1] = n >> 16 & 0xFF;
|
||||
result[2] = n >> 8 & 0xFF;
|
||||
result[3] = n & 0xFF;
|
||||
return result;
|
||||
};
|
||||
275
float-no-zero/closure-library/closure/goog/crypt/sha1.js
Normal file
275
float-no-zero/closure-library/closure/goog/crypt/sha1.js
Normal file
@@ -0,0 +1,275 @@
|
||||
// Copyright 2005 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 SHA-1 cryptographic hash.
|
||||
* Variable names follow the notation in FIPS PUB 180-3:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
|
||||
*
|
||||
* Usage:
|
||||
* var sha1 = new goog.crypt.sha1();
|
||||
* sha1.update(bytes);
|
||||
* var hash = sha1.digest();
|
||||
*
|
||||
* Performance:
|
||||
* Chrome 23: ~400 Mbit/s
|
||||
* Firefox 16: ~250 Mbit/s
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Sha1');
|
||||
|
||||
goog.require('goog.crypt.Hash');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SHA-1 cryptographic hash constructor.
|
||||
*
|
||||
* The properties declared here are discussed in the above algorithm document.
|
||||
* @constructor
|
||||
* @extends {goog.crypt.Hash}
|
||||
*/
|
||||
goog.crypt.Sha1 = function() {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Holds the previous values of accumulated variables a-e in the compress_
|
||||
* function.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.chain_ = [];
|
||||
|
||||
/**
|
||||
* A buffer holding the partially computed hash result.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.buf_ = [];
|
||||
|
||||
/**
|
||||
* An array of 80 bytes, each a part of the message to be hashed. Referred to
|
||||
* as the message schedule in the docs.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.W_ = [];
|
||||
|
||||
/**
|
||||
* Contains data needed to pad messages less than 64 bytes.
|
||||
* @type {Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.pad_ = [];
|
||||
|
||||
this.pad_[0] = 128;
|
||||
for (var i = 1; i < 64; ++i) {
|
||||
this.pad_[i] = 0;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
};
|
||||
goog.inherits(goog.crypt.Sha1, goog.crypt.Hash);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha1.prototype.reset = function() {
|
||||
this.chain_[0] = 0x67452301;
|
||||
this.chain_[1] = 0xefcdab89;
|
||||
this.chain_[2] = 0x98badcfe;
|
||||
this.chain_[3] = 0x10325476;
|
||||
this.chain_[4] = 0xc3d2e1f0;
|
||||
|
||||
this.inbuf_ = 0;
|
||||
this.total_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal compress helper function.
|
||||
* @param {Array.<number>|Uint8Array|string} buf Block to compress.
|
||||
* @param {number=} opt_offset Offset of the block in the buffer.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Sha1.prototype.compress_ = function(buf, opt_offset) {
|
||||
if (!opt_offset) {
|
||||
opt_offset = 0;
|
||||
}
|
||||
|
||||
var W = this.W_;
|
||||
|
||||
// get 16 big endian words
|
||||
if (goog.isString(buf)) {
|
||||
for (var i = 0; i < 16; i++) {
|
||||
// TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS
|
||||
// have a bug that turns the post-increment ++ operator into pre-increment
|
||||
// during JIT compilation. We have code that depends heavily on SHA-1 for
|
||||
// correctness and which is affected by this bug, so I've removed all uses
|
||||
// of post-increment ++ in which the result value is used. We can revert
|
||||
// this change once the Safari bug
|
||||
// (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and
|
||||
// most clients have been updated.
|
||||
W[i] = (buf.charCodeAt(opt_offset) << 24) |
|
||||
(buf.charCodeAt(opt_offset + 1) << 16) |
|
||||
(buf.charCodeAt(opt_offset + 2) << 8) |
|
||||
(buf.charCodeAt(opt_offset + 3));
|
||||
opt_offset += 4;
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < 16; i++) {
|
||||
W[i] = (buf[opt_offset] << 24) |
|
||||
(buf[opt_offset + 1] << 16) |
|
||||
(buf[opt_offset + 2] << 8) |
|
||||
(buf[opt_offset + 3]);
|
||||
opt_offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// expand to 80 words
|
||||
for (var i = 16; i < 80; i++) {
|
||||
var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
|
||||
W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;
|
||||
}
|
||||
|
||||
var a = this.chain_[0];
|
||||
var b = this.chain_[1];
|
||||
var c = this.chain_[2];
|
||||
var d = this.chain_[3];
|
||||
var e = this.chain_[4];
|
||||
var f, k;
|
||||
|
||||
// TODO(user): Try to unroll this loop to speed up the computation.
|
||||
for (var i = 0; i < 80; i++) {
|
||||
if (i < 40) {
|
||||
if (i < 20) {
|
||||
f = d ^ (b & (c ^ d));
|
||||
k = 0x5a827999;
|
||||
} else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ed9eba1;
|
||||
}
|
||||
} else {
|
||||
if (i < 60) {
|
||||
f = (b & c) | (d & (b | c));
|
||||
k = 0x8f1bbcdc;
|
||||
} else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xca62c1d6;
|
||||
}
|
||||
}
|
||||
|
||||
var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ((b << 30) | (b >>> 2)) & 0xffffffff;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
|
||||
this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
|
||||
this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
|
||||
this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
|
||||
this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha1.prototype.update = function(bytes, opt_length) {
|
||||
if (!goog.isDef(opt_length)) {
|
||||
opt_length = bytes.length;
|
||||
}
|
||||
|
||||
var lengthMinusBlock = opt_length - 64;
|
||||
var n = 0;
|
||||
// Using local instead of member variables gives ~5% speedup on Firefox 16.
|
||||
var buf = this.buf_;
|
||||
var inbuf = this.inbuf_;
|
||||
|
||||
// The outer while loop should execute at most twice.
|
||||
while (n < opt_length) {
|
||||
// When we have no data in the block to top up, we can directly process the
|
||||
// input buffer (assuming it contains sufficient data). This gives ~25%
|
||||
// speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that
|
||||
// the data is provided in large chunks (or in multiples of 64 bytes).
|
||||
if (inbuf == 0) {
|
||||
while (n <= lengthMinusBlock) {
|
||||
this.compress_(bytes, n);
|
||||
n += 64;
|
||||
}
|
||||
}
|
||||
|
||||
if (goog.isString(bytes)) {
|
||||
while (n < opt_length) {
|
||||
buf[inbuf] = bytes.charCodeAt(n);
|
||||
++inbuf;
|
||||
++n;
|
||||
if (inbuf == 64) {
|
||||
this.compress_(buf);
|
||||
inbuf = 0;
|
||||
// Jump to the outer loop so we use the full-block optimization.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (n < opt_length) {
|
||||
buf[inbuf] = bytes[n];
|
||||
++inbuf;
|
||||
++n;
|
||||
if (inbuf == 64) {
|
||||
this.compress_(buf);
|
||||
inbuf = 0;
|
||||
// Jump to the outer loop so we use the full-block optimization.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.inbuf_ = inbuf;
|
||||
this.total_ += opt_length;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha1.prototype.digest = function() {
|
||||
var digest = [];
|
||||
var totalBits = this.total_ * 8;
|
||||
|
||||
// Add pad 0x80 0x00*.
|
||||
if (this.inbuf_ < 56) {
|
||||
this.update(this.pad_, 56 - this.inbuf_);
|
||||
} else {
|
||||
this.update(this.pad_, 64 - (this.inbuf_ - 56));
|
||||
}
|
||||
|
||||
// Add # bits.
|
||||
for (var i = 63; i >= 56; i--) {
|
||||
this.buf_[i] = totalBits & 255;
|
||||
totalBits /= 256; // Don't use bit-shifting here!
|
||||
}
|
||||
|
||||
this.compress_(this.buf_);
|
||||
|
||||
var n = 0;
|
||||
for (var i = 0; i < 5; i++) {
|
||||
for (var j = 24; j >= 0; j -= 8) {
|
||||
digest[n] = (this.chain_[i] >> j) & 255;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
return digest;
|
||||
};
|
||||
275
float-no-zero/closure-library/closure/goog/crypt/sha2.js
Normal file
275
float-no-zero/closure-library/closure/goog/crypt/sha2.js
Normal file
@@ -0,0 +1,275 @@
|
||||
// Copyright 2012 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 Base class for SHA-2 cryptographic hash.
|
||||
*
|
||||
* Variable names follow the notation in FIPS PUB 180-3:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
|
||||
*
|
||||
* To implement specific SHA-2 such as SHA-256, create a sub-class with
|
||||
* overridded reset(). See sha256.js for an example.
|
||||
*
|
||||
* TODO(user): SHA-512/384 are not currently implemented. Could be added
|
||||
* if needed.
|
||||
*
|
||||
* Some code similar to SHA1 are borrowed from sha1.js written by mschilder@.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Sha2');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.crypt.Hash');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SHA-2 cryptographic hash constructor.
|
||||
* This constructor should not be used directly to create the object. Rather,
|
||||
* one should use the constructor of the sub-classes.
|
||||
* @constructor
|
||||
* @extends {goog.crypt.Hash}
|
||||
*/
|
||||
goog.crypt.Sha2 = function() {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* A chunk holding the currently processed message bytes. Once the chunk has
|
||||
* 64 bytes, we feed it into computeChunk_ function and reset this.chunk_.
|
||||
* Sub-class needs to reset it when overriding reset().
|
||||
* @type {!Array.<number>}
|
||||
* @protected
|
||||
*/
|
||||
this.chunk = [];
|
||||
|
||||
/**
|
||||
* Current number of bytes in this.chunk_.
|
||||
* Sub-class needs to reset it when overriding reset().
|
||||
* @type {number}
|
||||
* @protected
|
||||
*/
|
||||
this.inChunk = 0;
|
||||
|
||||
/**
|
||||
* Total number of bytes in currently processed message.
|
||||
* Sub-class needs to reset it when overriding reset().
|
||||
* @type {number}
|
||||
* @protected
|
||||
*/
|
||||
this.total = 0;
|
||||
|
||||
/**
|
||||
* Contains data needed to pad messages less than 64 bytes.
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.pad_ = goog.array.repeat(0, 64);
|
||||
this.pad_[0] = 128;
|
||||
|
||||
/**
|
||||
* Holds the previous values of accumulated hash a-h in the computeChunk_
|
||||
* function.
|
||||
* It is a subclass-dependent value. Sub-class needs to explicitly set it
|
||||
* when overriding reset().
|
||||
* @type {!Array.<number>}
|
||||
* @protected
|
||||
*/
|
||||
this.hash = [];
|
||||
|
||||
/**
|
||||
* The number of output hash blocks (each block is 4 bytes long).
|
||||
* It is a subclass-dependent value. Sub-class needs to explicitly set it
|
||||
* when overriding reset().
|
||||
* @type {number}
|
||||
* @protected
|
||||
*/
|
||||
this.numHashBlocks = 0;
|
||||
|
||||
this.reset();
|
||||
};
|
||||
goog.inherits(goog.crypt.Sha2, goog.crypt.Hash);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha2.prototype.reset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to compute the hashes for a given 512-bit message chunk.
|
||||
* @param {!Array.<number>} chunk A 512-bit message chunk to be processed.
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Sha2.prototype.computeChunk_ = function(chunk) {
|
||||
goog.asserts.assert(chunk.length == 64);
|
||||
|
||||
// Divide the chunk into 16 32-bit-words.
|
||||
var w = [];
|
||||
var index = 0;
|
||||
var offset = 0;
|
||||
while (offset < chunk.length) {
|
||||
w[index++] = (chunk[offset] << 24) |
|
||||
(chunk[offset + 1] << 16) |
|
||||
(chunk[offset + 2] << 8) |
|
||||
(chunk[offset + 3]);
|
||||
offset = index * 4;
|
||||
}
|
||||
|
||||
// Expand to 64 32-bit-words
|
||||
for (var i = 16; i < 64; i++) {
|
||||
var s0 = ((w[i - 15] >>> 7) | (w[i - 15] << 25)) ^
|
||||
((w[i - 15] >>> 18) | (w[i - 15] << 14)) ^
|
||||
(w[i - 15] >>> 3);
|
||||
var s1 = ((w[i - 2] >>> 17) | (w[i - 2] << 15)) ^
|
||||
((w[i - 2] >>> 19) | (w[i - 2] << 13)) ^
|
||||
(w[i - 2] >>> 10);
|
||||
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) & 0xffffffff;
|
||||
}
|
||||
|
||||
var a = this.hash[0];
|
||||
var b = this.hash[1];
|
||||
var c = this.hash[2];
|
||||
var d = this.hash[3];
|
||||
var e = this.hash[4];
|
||||
var f = this.hash[5];
|
||||
var g = this.hash[6];
|
||||
var h = this.hash[7];
|
||||
|
||||
for (var i = 0; i < 64; i++) {
|
||||
var S0 = ((a >>> 2) | (a << 30)) ^
|
||||
((a >>> 13) | (a << 19)) ^
|
||||
((a >>> 22) | (a << 10));
|
||||
var maj = ((a & b) ^ (a & c) ^ (b & c));
|
||||
var t2 = (S0 + maj) & 0xffffffff;
|
||||
var S1 = ((e >>> 6) | (e << 26)) ^
|
||||
((e >>> 11) | (e << 21)) ^
|
||||
((e >>> 25) | (e << 7));
|
||||
var ch = ((e & f) ^ ((~ e) & g));
|
||||
var t1 = (h + S1 + ch + this.K_[i] + w[i]) & 0xffffffff;
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = (d + t1) & 0xffffffff;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = (t1 + t2) & 0xffffffff;
|
||||
}
|
||||
|
||||
this.hash[0] = (this.hash[0] + a) & 0xffffffff;
|
||||
this.hash[1] = (this.hash[1] + b) & 0xffffffff;
|
||||
this.hash[2] = (this.hash[2] + c) & 0xffffffff;
|
||||
this.hash[3] = (this.hash[3] + d) & 0xffffffff;
|
||||
this.hash[4] = (this.hash[4] + e) & 0xffffffff;
|
||||
this.hash[5] = (this.hash[5] + f) & 0xffffffff;
|
||||
this.hash[6] = (this.hash[6] + g) & 0xffffffff;
|
||||
this.hash[7] = (this.hash[7] + h) & 0xffffffff;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha2.prototype.update = function(message, opt_length) {
|
||||
if (!goog.isDef(opt_length)) {
|
||||
opt_length = message.length;
|
||||
}
|
||||
// Process the message from left to right up to |opt_length| bytes.
|
||||
// When we get a 512-bit chunk, compute the hash of it and reset
|
||||
// this.chunk_. The message might not be multiple of 512 bits so we
|
||||
// might end up with a chunk that is less than 512 bits. We store
|
||||
// such partial chunk in this.chunk_ and it will be filled up later
|
||||
// in digest().
|
||||
var n = 0;
|
||||
var inChunk = this.inChunk;
|
||||
|
||||
// The input message could be either byte array of string.
|
||||
if (goog.isString(message)) {
|
||||
while (n < opt_length) {
|
||||
this.chunk[inChunk++] = message.charCodeAt(n++);
|
||||
if (inChunk == 64) {
|
||||
this.computeChunk_(this.chunk);
|
||||
inChunk = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (n < opt_length) {
|
||||
this.chunk[inChunk++] = message[n++];
|
||||
if (inChunk == 64) {
|
||||
this.computeChunk_(this.chunk);
|
||||
inChunk = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record the current bytes in chunk to support partial update.
|
||||
this.inChunk = inChunk;
|
||||
|
||||
// Record total message bytes we have processed so far.
|
||||
this.total += opt_length;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha2.prototype.digest = function() {
|
||||
var digest = [];
|
||||
var totalBits = this.total * 8;
|
||||
|
||||
// Append pad 0x80 0x00*.
|
||||
if (this.inChunk < 56) {
|
||||
this.update(this.pad_, 56 - this.inChunk);
|
||||
} else {
|
||||
this.update(this.pad_, 64 - (this.inChunk - 56));
|
||||
}
|
||||
|
||||
// Append # bits in the 64-bit big-endian format.
|
||||
for (var i = 63; i >= 56; i--) {
|
||||
this.chunk[i] = totalBits & 255;
|
||||
totalBits /= 256; // Don't use bit-shifting here!
|
||||
}
|
||||
this.computeChunk_(this.chunk);
|
||||
|
||||
// Finally, output the result digest.
|
||||
var n = 0;
|
||||
for (var i = 0; i < this.numHashBlocks; i++) {
|
||||
for (var j = 24; j >= 0; j -= 8) {
|
||||
digest[n++] = ((this.hash[i] >> j) & 255);
|
||||
}
|
||||
}
|
||||
return digest;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants used in SHA-2.
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
goog.crypt.Sha2.prototype.K_ = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
|
||||
53
float-no-zero/closure-library/closure/goog/crypt/sha224.js
Normal file
53
float-no-zero/closure-library/closure/goog/crypt/sha224.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2012 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 SHA-224 cryptographic hash.
|
||||
*
|
||||
* Usage:
|
||||
* var sha224 = new goog.crypt.Sha224();
|
||||
* sha224.update(bytes);
|
||||
* var hash = sha224.digest();
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Sha224');
|
||||
|
||||
goog.require('goog.crypt.Sha2');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SHA-224 cryptographic hash constructor.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.crypt.Sha2}
|
||||
*/
|
||||
goog.crypt.Sha224 = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(goog.crypt.Sha224, goog.crypt.Sha2);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha224.prototype.reset = function() {
|
||||
this.chunk = [];
|
||||
this.inChunk = 0;
|
||||
this.total = 0;
|
||||
|
||||
this.hash = [
|
||||
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||||
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4];
|
||||
this.numHashBlocks = 7;
|
||||
};
|
||||
53
float-no-zero/closure-library/closure/goog/crypt/sha256.js
Normal file
53
float-no-zero/closure-library/closure/goog/crypt/sha256.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2012 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 SHA-256 cryptographic hash.
|
||||
*
|
||||
* Usage:
|
||||
* var sha256 = new goog.crypt.Sha256();
|
||||
* sha256.update(bytes);
|
||||
* var hash = sha256.digest();
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.Sha256');
|
||||
|
||||
goog.require('goog.crypt.Sha2');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SHA-256 cryptographic hash constructor.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.crypt.Sha2}
|
||||
*/
|
||||
goog.crypt.Sha256 = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(goog.crypt.Sha256, goog.crypt.Sha2);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.crypt.Sha256.prototype.reset = function() {
|
||||
this.chunk = [];
|
||||
this.inChunk = 0;
|
||||
this.total = 0;
|
||||
|
||||
this.hash = [
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
|
||||
this.numHashBlocks = 8;
|
||||
};
|
||||
449
float-no-zero/closure-library/closure/goog/cssom/cssom.js
Normal file
449
float-no-zero/closure-library/closure/goog/cssom/cssom.js
Normal file
@@ -0,0 +1,449 @@
|
||||
// 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 CSS Object Model helper functions.
|
||||
* References:
|
||||
* - W3C: http://dev.w3.org/csswg/cssom/
|
||||
* - MSDN: http://msdn.microsoft.com/en-us/library/ms531209(VS.85).aspx.
|
||||
* @supported in FF3, IE6, IE7, Safari 3.1.2, Chrome
|
||||
* TODO(user): Fix in Opera.
|
||||
* TODO(user): Consider hacking page, media, etc.. to work.
|
||||
* This would be pretty challenging. IE returns the text for any rule
|
||||
* regardless of whether or not the media is correct or not. Firefox at
|
||||
* least supports CSSRule.type to figure out if it's a media type and then
|
||||
* we could do something interesting, but IE offers no way for us to tell.
|
||||
*/
|
||||
|
||||
goog.provide('goog.cssom');
|
||||
goog.provide('goog.cssom.CssRuleType');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of {@code CSSRule} types.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.cssom.CssRuleType = {
|
||||
STYLE: 1,
|
||||
IMPORT: 3,
|
||||
MEDIA: 4,
|
||||
FONT_FACE: 5,
|
||||
PAGE: 6,
|
||||
NAMESPACE: 7
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSS as text, optionally starting from a given
|
||||
* CSSStyleSheet.
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
|
||||
* @return {string} css text.
|
||||
*/
|
||||
goog.cssom.getAllCssText = function(opt_styleSheet) {
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
return /** @type {string} */ (goog.cssom.getAllCss_(styleSheet, true));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSSStyleRules, optionally starting from a given
|
||||
* CSSStyleSheet.
|
||||
* Note that this excludes any CSSImportRules, CSSMediaRules, etc..
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
|
||||
* @return {Array.<CSSStyleRule>} A list of CSSStyleRules.
|
||||
*/
|
||||
goog.cssom.getAllCssStyleRules = function(opt_styleSheet) {
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
return /** @type {Array.<CSSStyleRule>} */ (
|
||||
goog.cssom.getAllCss_(styleSheet, false));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the CSSRules from a styleSheet.
|
||||
* Worth noting here is that IE and FF differ in terms of what they will return.
|
||||
* Firefox will return styleSheet.cssRules, which includes ImportRules and
|
||||
* anything which implements the CSSRules interface. IE returns simply a list of
|
||||
* CSSRules.
|
||||
* @param {CSSStyleSheet} styleSheet The CSSStyleSheet.
|
||||
* @throws {Error} If we cannot access the rules on a stylesheet object - this
|
||||
* can happen if a stylesheet object's rules are accessed before the rules
|
||||
* have been downloaded and parsed and are "ready".
|
||||
* @return {CSSRuleList} An array of CSSRules or null.
|
||||
*/
|
||||
goog.cssom.getCssRulesFromStyleSheet = function(styleSheet) {
|
||||
var cssRuleList = null;
|
||||
try {
|
||||
// IE is .rules, W3c is cssRules.
|
||||
cssRuleList = styleSheet.rules || styleSheet.cssRules;
|
||||
} catch (e) {
|
||||
// This can happen if we try to access the CSSOM before it's "ready".
|
||||
if (e.code == 15) {
|
||||
// Firefox throws an NS_ERROR_DOM_INVALID_ACCESS_ERR error if a stylesheet
|
||||
// is read before it has been fully parsed. Let the caller know which
|
||||
// stylesheet failed.
|
||||
e.styleSheet = styleSheet;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return cssRuleList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all CSSStyleSheet objects starting from some CSSStyleSheet. Note that we
|
||||
* want to return the sheets in the order of the cascade, therefore if we
|
||||
* encounter an import, we will splice that CSSStyleSheet object in front of
|
||||
* the CSSStyleSheet that contains it in the returned array of CSSStyleSheets.
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet A CSSStyleSheet.
|
||||
* @param {boolean=} opt_includeDisabled If true, includes disabled stylesheets,
|
||||
* defaults to false.
|
||||
* @return {Array.<CSSStyleSheet>} A list of CSSStyleSheet objects.
|
||||
*/
|
||||
goog.cssom.getAllCssStyleSheets = function(opt_styleSheet,
|
||||
opt_includeDisabled) {
|
||||
var styleSheetsOutput = [];
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
var includeDisabled = goog.isDef(opt_includeDisabled) ? opt_includeDisabled :
|
||||
false;
|
||||
|
||||
// Imports need to go first.
|
||||
if (styleSheet.imports && styleSheet.imports.length) {
|
||||
for (var i = 0, n = styleSheet.imports.length; i < n; i++) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(styleSheet.imports[i]));
|
||||
}
|
||||
|
||||
} else if (styleSheet.length) {
|
||||
// In case we get a StyleSheetList object.
|
||||
// http://dev.w3.org/csswg/cssom/#the-stylesheetlist
|
||||
for (var i = 0, n = styleSheet.length; i < n; i++) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(styleSheet[i]));
|
||||
}
|
||||
} else {
|
||||
// We need to walk through rules in browsers which implement .cssRules
|
||||
// to see if there are styleSheets buried in there.
|
||||
// If we have a CSSStyleSheet within CssRules.
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(
|
||||
/** @type {CSSStyleSheet} */ (styleSheet));
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
// Chrome does not evaluate cssRuleList[i] to undefined when i >=n;
|
||||
// so we use a (i < n) check instead of cssRuleList[i] in the loop below
|
||||
// and in other places where we iterate over a rules list.
|
||||
// See issue # 5917 in Chromium.
|
||||
for (var i = 0, n = cssRuleList.length, cssRule; i < n; i++) {
|
||||
cssRule = cssRuleList[i];
|
||||
// There are more stylesheets to get on this object..
|
||||
if (cssRule.styleSheet) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(cssRule.styleSheet));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a CSSStyleSheet. (IE uses .rules, W3c and Opera cssRules.)
|
||||
if ((styleSheet.type || styleSheet.rules || styleSheet.cssRules) &&
|
||||
(!styleSheet.disabled || includeDisabled)) {
|
||||
styleSheetsOutput.push(styleSheet);
|
||||
}
|
||||
|
||||
return styleSheetsOutput;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the cssText from a CSSRule object cross-browserly.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @return {string} cssText The text for the rule, including the selector.
|
||||
*/
|
||||
goog.cssom.getCssTextFromCssRule = function(cssRule) {
|
||||
var cssText = '';
|
||||
|
||||
if (cssRule.cssText) {
|
||||
// W3C.
|
||||
cssText = cssRule.cssText;
|
||||
} else if (cssRule.style && cssRule.style.cssText && cssRule.selectorText) {
|
||||
// IE: The spacing here is intended to make the result consistent with
|
||||
// FF and Webkit.
|
||||
// We also remove the special properties that we may have added in
|
||||
// getAllCssStyleRules since IE includes those in the cssText.
|
||||
var styleCssText = cssRule.style.cssText.
|
||||
replace(/\s*-closure-parent-stylesheet:\s*\[object\];?\s*/gi, '').
|
||||
replace(/\s*-closure-rule-index:\s*[\d]+;?\s*/gi, '');
|
||||
var thisCssText = cssRule.selectorText + ' { ' + styleCssText + ' }';
|
||||
cssText = thisCssText;
|
||||
}
|
||||
|
||||
return cssText;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the index of the CSSRule in it's CSSStyleSheet.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
|
||||
* object this cssRule belongs to.
|
||||
* @throws {Error} When we cannot get the parentStyleSheet.
|
||||
* @return {number} The index of the CSSRule, or -1.
|
||||
*/
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet = function(cssRule,
|
||||
opt_parentStyleSheet) {
|
||||
// Look for our special style.ruleIndex property from getAllCss.
|
||||
if (cssRule.style && cssRule.style['-closure-rule-index']) {
|
||||
return cssRule.style['-closure-rule-index'];
|
||||
}
|
||||
|
||||
var parentStyleSheet = opt_parentStyleSheet ||
|
||||
goog.cssom.getParentStyleSheet(cssRule);
|
||||
|
||||
if (!parentStyleSheet) {
|
||||
// We could call getAllCssStyleRules() here to get our special indexes on
|
||||
// the style object, but that seems like it could be wasteful.
|
||||
throw Error('Cannot find a parentStyleSheet.');
|
||||
}
|
||||
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(parentStyleSheet);
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
for (var i = 0, n = cssRuleList.length, thisCssRule; i < n; i++) {
|
||||
thisCssRule = cssRuleList[i];
|
||||
if (thisCssRule == cssRule) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* We do some trickery in getAllCssStyleRules that hacks this in for IE.
|
||||
* If the cssRule object isn't coming from a result of that function call, this
|
||||
* method will return undefined in IE.
|
||||
* @param {CSSRule} cssRule The CSSRule.
|
||||
* @return {CSSStyleSheet} A styleSheet object.
|
||||
*/
|
||||
goog.cssom.getParentStyleSheet = function(cssRule) {
|
||||
return cssRule.parentStyleSheet ||
|
||||
cssRule.style &&
|
||||
cssRule.style['-closure-parent-stylesheet'];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replace a cssRule with some cssText for a new rule.
|
||||
* If the cssRule object is not one of objects returned by
|
||||
* getAllCssStyleRules, then you'll need to provide both the styleSheet and
|
||||
* possibly the index, since we can't infer them from the standard cssRule
|
||||
* object in IE. We do some trickery in getAllCssStyleRules to hack this in.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @param {string} cssText The text for the new CSSRule.
|
||||
* @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
|
||||
* object this cssRule belongs to.
|
||||
* @param {number=} opt_index The index of the cssRule in its parentStylesheet.
|
||||
* @throws {Error} If we cannot find a parentStyleSheet.
|
||||
* @throws {Error} If we cannot find a css rule index.
|
||||
*/
|
||||
goog.cssom.replaceCssRule = function(cssRule, cssText, opt_parentStyleSheet,
|
||||
opt_index) {
|
||||
var parentStyleSheet = opt_parentStyleSheet ||
|
||||
goog.cssom.getParentStyleSheet(cssRule);
|
||||
if (parentStyleSheet) {
|
||||
var index = opt_index >= 0 ? opt_index :
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, parentStyleSheet);
|
||||
if (index >= 0) {
|
||||
goog.cssom.removeCssRule(parentStyleSheet, index);
|
||||
goog.cssom.addCssRule(parentStyleSheet, cssText, index);
|
||||
} else {
|
||||
throw Error('Cannot proceed without the index of the cssRule.');
|
||||
}
|
||||
} else {
|
||||
throw Error('Cannot proceed without the parentStyleSheet.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser function to add a CSSRule into a CSSStyleSheet, optionally
|
||||
* at a given index.
|
||||
* @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
|
||||
* @param {string} cssText The text for the new CSSRule.
|
||||
* @param {number=} opt_index The index of the cssRule in its parentStylesheet.
|
||||
* @throws {Error} If the css rule text appears to be ill-formatted.
|
||||
* TODO(bowdidge): Inserting at index 0 fails on Firefox 2 and 3 with an
|
||||
* exception warning "Node cannot be inserted at the specified point in
|
||||
* the hierarchy."
|
||||
*/
|
||||
goog.cssom.addCssRule = function(cssStyleSheet, cssText, opt_index) {
|
||||
var index = opt_index;
|
||||
if (index < 0 || index == undefined) {
|
||||
// If no index specified, insert at the end of the current list
|
||||
// of rules.
|
||||
// If on IE, use rules property, otherwise use cssRules property.
|
||||
var rules = cssStyleSheet.rules || cssStyleSheet.cssRules;
|
||||
index = rules.length;
|
||||
}
|
||||
if (cssStyleSheet.insertRule) {
|
||||
// W3C.
|
||||
cssStyleSheet.insertRule(cssText, index);
|
||||
|
||||
} else {
|
||||
// IE: We have to parse the cssRule text to get the selector separated
|
||||
// from the style text.
|
||||
// aka Everything that isn't a colon, followed by a colon, then
|
||||
// the rest is the style part.
|
||||
var matches = /^([^\{]+)\{([^\{]+)\}/.exec(cssText);
|
||||
if (matches.length == 3) {
|
||||
var selector = matches[1];
|
||||
var style = matches[2];
|
||||
cssStyleSheet.addRule(selector, style, index);
|
||||
} else {
|
||||
throw Error('Your CSSRule appears to be ill-formatted.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser function to remove a CSSRule in a CSSStyleSheet at an index.
|
||||
* @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
|
||||
* @param {number} index The CSSRule's index in the parentStyleSheet.
|
||||
*/
|
||||
goog.cssom.removeCssRule = function(cssStyleSheet, index) {
|
||||
if (cssStyleSheet.deleteRule) {
|
||||
// W3C.
|
||||
cssStyleSheet.deleteRule(index);
|
||||
|
||||
} else {
|
||||
// IE.
|
||||
cssStyleSheet.removeRule(index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Appends a DOM node to HEAD containing the css text that's passed in.
|
||||
* @param {string} cssText CSS to add to the end of the document.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper user for
|
||||
* document interactions.
|
||||
* @return {Element} The newly created STYLE element.
|
||||
*/
|
||||
goog.cssom.addCssText = function(cssText, opt_domHelper) {
|
||||
var document = opt_domHelper ? opt_domHelper.getDocument() :
|
||||
goog.dom.getDocument();
|
||||
var cssNode = document.createElement('style');
|
||||
cssNode.type = 'text/css';
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.appendChild(cssNode);
|
||||
if (cssNode.styleSheet) {
|
||||
// IE.
|
||||
cssNode.styleSheet.cssText = cssText;
|
||||
} else {
|
||||
// W3C.
|
||||
var cssTextNode = document.createTextNode(cssText);
|
||||
cssNode.appendChild(cssTextNode);
|
||||
}
|
||||
return cssNode;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser method to get the filename from the StyleSheet's href.
|
||||
* Explorer only returns the filename in the href, while other agents return
|
||||
* the full path.
|
||||
* @param {!StyleSheet} styleSheet Any valid StyleSheet object with an href.
|
||||
* @throws {Error} When there's no href property found.
|
||||
* @return {?string} filename The filename, or null if not an external
|
||||
* styleSheet.
|
||||
*/
|
||||
goog.cssom.getFileNameFromStyleSheet = function(styleSheet) {
|
||||
var href = styleSheet.href;
|
||||
|
||||
// Another IE/FF difference. IE returns an empty string, while FF and others
|
||||
// return null for CSSStyleSheets not from an external file.
|
||||
if (!href) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need the regexp to ensure we get the filename minus any query params.
|
||||
var matches = /([^\/\?]+)[^\/]*$/.exec(href);
|
||||
var filename = matches[1];
|
||||
return filename;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSS text or rules.
|
||||
* @param {CSSStyleSheet|StyleSheetList} styleSheet The CSSStyleSheet.
|
||||
* @param {boolean} isTextOutput If true, output is cssText, otherwise cssRules.
|
||||
* @return {string|Array.<CSSRule>} cssText or cssRules.
|
||||
* @private
|
||||
*/
|
||||
goog.cssom.getAllCss_ = function(styleSheet, isTextOutput) {
|
||||
var cssOut = [];
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets(styleSheet);
|
||||
|
||||
for (var i = 0; styleSheet = styleSheets[i]; i++) {
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
|
||||
// We're going to track cssRule index if we want rule output.
|
||||
if (!isTextOutput) {
|
||||
var ruleIndex = 0;
|
||||
}
|
||||
|
||||
for (var j = 0, n = cssRuleList.length, cssRule; j < n; j++) {
|
||||
cssRule = cssRuleList[j];
|
||||
// Gets cssText output, ignoring CSSImportRules.
|
||||
if (isTextOutput && !cssRule.href) {
|
||||
var res = goog.cssom.getCssTextFromCssRule(cssRule);
|
||||
cssOut.push(res);
|
||||
|
||||
} else if (!cssRule.href) {
|
||||
// Gets cssRules output, ignoring CSSImportRules.
|
||||
if (cssRule.style) {
|
||||
// This is a fun little hack to get parentStyleSheet into the rule
|
||||
// object for IE since it failed to implement rule.parentStyleSheet.
|
||||
// We can later read this property when doing things like hunting
|
||||
// for indexes in order to delete a given CSSRule.
|
||||
// Unfortunately we have to use the style object to store these
|
||||
// pieces of info since the rule object is read-only.
|
||||
if (!cssRule.parentStyleSheet) {
|
||||
cssRule.style['-closure-parent-stylesheet'] = styleSheet;
|
||||
}
|
||||
|
||||
// This is a hack to help with possible removal of the rule later,
|
||||
// where we just append the rule's index in its parentStyleSheet
|
||||
// onto the style object as a property.
|
||||
// Unfortunately we have to use the style object to store these
|
||||
// pieces of info since the rule object is read-only.
|
||||
cssRule.style['-closure-rule-index'] = ruleIndex;
|
||||
}
|
||||
cssOut.push(cssRule);
|
||||
}
|
||||
|
||||
if (!isTextOutput) {
|
||||
ruleIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isTextOutput ? cssOut.join(' ') : cssOut;
|
||||
};
|
||||
|
||||
1023
float-no-zero/closure-library/closure/goog/cssom/iframe/style.js
Normal file
1023
float-no-zero/closure-library/closure/goog/cssom/iframe/style.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,559 @@
|
||||
// Copyright 2006 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
|
||||
* Central class for registering and accessing data sources
|
||||
* Also handles processing of data events.
|
||||
*
|
||||
* There is a shared global instance that most client code should access via
|
||||
* goog.ds.DataManager.getInstance(). However you can also create your own
|
||||
* DataManager using new
|
||||
*
|
||||
* Implements DataNode to provide the top element in a data registry
|
||||
* Prepends '$' to top level data names in path to denote they are root object
|
||||
*
|
||||
*/
|
||||
goog.provide('goog.ds.DataManager');
|
||||
|
||||
goog.require('goog.ds.BasicNodeList');
|
||||
goog.require('goog.ds.DataNode');
|
||||
goog.require('goog.ds.Expr');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.structs');
|
||||
goog.require('goog.structs.Map');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a DataManger
|
||||
* @extends {goog.ds.DataNode}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.DataManager = function() {
|
||||
this.dataSources_ = new goog.ds.BasicNodeList();
|
||||
this.autoloads_ = new goog.structs.Map();
|
||||
this.listenerMap_ = {};
|
||||
this.listenersByFunction_ = {};
|
||||
this.aliases_ = {};
|
||||
this.eventCount_ = 0;
|
||||
this.indexedListenersByFunction_ = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Global instance
|
||||
* @private
|
||||
*/
|
||||
goog.ds.DataManager.instance_ = null;
|
||||
goog.inherits(goog.ds.DataManager, goog.ds.DataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Get the global instance
|
||||
* @return {goog.ds.DataManager} The data manager singleton.
|
||||
*/
|
||||
goog.ds.DataManager.getInstance = function() {
|
||||
if (!goog.ds.DataManager.instance_) {
|
||||
goog.ds.DataManager.instance_ = new goog.ds.DataManager();
|
||||
}
|
||||
return goog.ds.DataManager.instance_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the global instance (for unit tests to reset state).
|
||||
*/
|
||||
goog.ds.DataManager.clearInstance = function() {
|
||||
goog.ds.DataManager.instance_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a data source
|
||||
* @param {goog.ds.DataNode} ds The data source.
|
||||
* @param {boolean=} opt_autoload Whether to automatically load the data,
|
||||
* defaults to false.
|
||||
* @param {string=} opt_name Optional name, can also get name
|
||||
* from the datasource.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.addDataSource = function(ds, opt_autoload,
|
||||
opt_name) {
|
||||
var autoload = !!opt_autoload;
|
||||
var name = opt_name || ds.getDataName();
|
||||
if (!goog.string.startsWith(name, '$')) {
|
||||
name = '$' + name;
|
||||
}
|
||||
ds.setDataName(name);
|
||||
this.dataSources_.add(ds);
|
||||
this.autoloads_.set(name, autoload);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an alias for a data path, very similar to assigning a variable.
|
||||
* For example, you can set $CurrentContact -> $Request/Contacts[5], and all
|
||||
* references to $CurrentContact will be procesed on $Request/Contacts[5].
|
||||
*
|
||||
* Aliases will hide datasources of the same name.
|
||||
*
|
||||
* @param {string} name Alias name, must be a top level path ($Foo).
|
||||
* @param {string} dataPath Data path being aliased.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.aliasDataSource = function(name, dataPath) {
|
||||
if (!this.aliasListener_) {
|
||||
this.aliasListener_ = goog.bind(this.listenForAlias_, this);
|
||||
}
|
||||
if (this.aliases_[name]) {
|
||||
var oldPath = this.aliases_[name].getSource();
|
||||
this.removeListeners(this.aliasListener_, oldPath + '/...', name);
|
||||
}
|
||||
this.aliases_[name] = goog.ds.Expr.create(dataPath);
|
||||
this.addListener(this.aliasListener_, dataPath + '/...', name);
|
||||
this.fireDataChange(name);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Listener function for matches of paths that have been aliased.
|
||||
* Fires a data change on the alias as well.
|
||||
*
|
||||
* @param {string} dataPath Path of data event fired.
|
||||
* @param {string} name Name of the alias.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.DataManager.prototype.listenForAlias_ = function(dataPath, name) {
|
||||
var aliasedExpr = this.aliases_[name];
|
||||
|
||||
if (aliasedExpr) {
|
||||
// If it's a subpath, appends the subpath to the alias name
|
||||
// otherwise just fires on the top level alias
|
||||
var aliasedPath = aliasedExpr.getSource();
|
||||
if (dataPath.indexOf(aliasedPath) == 0) {
|
||||
this.fireDataChange(name + dataPath.substring(aliasedPath.length));
|
||||
} else {
|
||||
this.fireDataChange(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node.
|
||||
*
|
||||
* @param {string} name The node name.
|
||||
* @return {goog.ds.DataNode} The child node,
|
||||
* or null if no node of this name exists.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getDataSource = function(name) {
|
||||
if (this.aliases_[name]) {
|
||||
return this.aliases_[name].getNode();
|
||||
} else {
|
||||
return this.dataSources_.get(name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the node
|
||||
* @return {Object} The value of the node, or null if no value.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.get = function() {
|
||||
return this.dataSources_;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.DataManager.prototype.set = function(value) {
|
||||
throw Error('Can\'t set on DataManager');
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.DataManager.prototype.getChildNodes = function(opt_selector) {
|
||||
if (opt_selector) {
|
||||
return new goog.ds.BasicNodeList(
|
||||
[this.getChildNode(/** @type {string} */(opt_selector))]);
|
||||
} else {
|
||||
return this.dataSources_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node
|
||||
* @param {string} name The node name.
|
||||
* @return {goog.ds.DataNode} The child node,
|
||||
* or null if no node of this name exists.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getChildNode = function(name) {
|
||||
return this.getDataSource(name);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.DataManager.prototype.getChildNodeValue = function(name) {
|
||||
var ds = this.getDataSource(name);
|
||||
return ds ? ds.get() : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getDataName = function() {
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the a qualified data path to this node
|
||||
* @return {string} The data path.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getDataPath = function() {
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node
|
||||
* only loads datasources flagged with autoload
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.load = function() {
|
||||
var len = this.dataSources_.getCount();
|
||||
for (var i = 0; i < len; i++) {
|
||||
var ds = this.dataSources_.getByIndex(i);
|
||||
var autoload = this.autoloads_.get(ds.getDataName());
|
||||
if (autoload) {
|
||||
ds.load();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getLoadState = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the value of this node is a homogeneous list of data
|
||||
* @return {boolean} True if a list.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataManager.prototype.isList = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the total count of events fired (mostly for debugging)
|
||||
* @return {number} Count of events.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getEventCount = function() {
|
||||
return this.eventCount_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a listener
|
||||
* Listeners should fire when any data with path that has dataPath as substring
|
||||
* is changed.
|
||||
* TODO(user) Look into better listener handling
|
||||
*
|
||||
* @param {Function} fn Callback function, signature function(dataPath, id).
|
||||
* @param {string} dataPath Fully qualified data path.
|
||||
* @param {string=} opt_id A value passed back to the listener when the dataPath
|
||||
* is matched.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.addListener = function(fn, dataPath, opt_id) {
|
||||
// maxAncestor sets how distant an ancestor you can be of the fired event
|
||||
// and still fire (you always fire if you are a descendant).
|
||||
// 0 means you don't fire if you are an ancestor
|
||||
// 1 means you only fire if you are parent
|
||||
// 1000 means you will fire if you are ancestor (effectively infinite)
|
||||
var maxAncestors = 0;
|
||||
if (goog.string.endsWith(dataPath, '/...')) {
|
||||
maxAncestors = 1000;
|
||||
dataPath = dataPath.substring(0, dataPath.length - 4);
|
||||
} else if (goog.string.endsWith(dataPath, '/*')) {
|
||||
maxAncestors = 1;
|
||||
dataPath = dataPath.substring(0, dataPath.length - 2);
|
||||
}
|
||||
|
||||
opt_id = opt_id || '';
|
||||
var key = dataPath + ':' + opt_id + ':' + goog.getUid(fn);
|
||||
var listener = {dataPath: dataPath, id: opt_id, fn: fn};
|
||||
var expr = goog.ds.Expr.create(dataPath);
|
||||
|
||||
var fnUid = goog.getUid(fn);
|
||||
if (!this.listenersByFunction_[fnUid]) {
|
||||
this.listenersByFunction_[fnUid] = {};
|
||||
}
|
||||
this.listenersByFunction_[fnUid][key] = {listener: listener, items: []};
|
||||
|
||||
while (expr) {
|
||||
var listenerSpec = {listener: listener, maxAncestors: maxAncestors};
|
||||
var matchingListeners = this.listenerMap_[expr.getSource()];
|
||||
if (matchingListeners == null) {
|
||||
matchingListeners = {};
|
||||
this.listenerMap_[expr.getSource()] = matchingListeners;
|
||||
}
|
||||
matchingListeners[key] = listenerSpec;
|
||||
maxAncestors = 0;
|
||||
expr = expr.getParent();
|
||||
this.listenersByFunction_[fnUid][key].items.push(
|
||||
{key: key, obj: matchingListeners});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an indexed listener.
|
||||
*
|
||||
* Indexed listeners allow for '*' in data paths. If a * exists, will match
|
||||
* all values and return the matched values in an array to the callback.
|
||||
*
|
||||
* Currently uses a promiscuous match algorithm: Matches everything before the
|
||||
* first '*', and then does a regex match for all of the returned events.
|
||||
* Although this isn't optimized, it is still an improvement as you can collapse
|
||||
* 100's of listeners into a single regex match
|
||||
*
|
||||
* @param {Function} fn Callback function, signature (dataPath, id, indexes).
|
||||
* @param {string} dataPath Fully qualified data path.
|
||||
* @param {string=} opt_id A value passed back to the listener when the dataPath
|
||||
* is matched.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.addIndexedListener = function(fn, dataPath,
|
||||
opt_id) {
|
||||
var firstStarPos = dataPath.indexOf('*');
|
||||
// Just need a regular listener
|
||||
if (firstStarPos == -1) {
|
||||
this.addListener(fn, dataPath, opt_id);
|
||||
return;
|
||||
}
|
||||
|
||||
var listenPath = dataPath.substring(0, firstStarPos) + '...';
|
||||
|
||||
// Create regex that matches * to any non '\' character
|
||||
var ext = '$';
|
||||
if (goog.string.endsWith(dataPath, '/...')) {
|
||||
dataPath = dataPath.substring(0, dataPath.length - 4);
|
||||
ext = '';
|
||||
}
|
||||
var regExpPath = goog.string.regExpEscape(dataPath);
|
||||
var matchRegExp = regExpPath.replace(/\\\*/g, '([^\\\/]+)') + ext;
|
||||
|
||||
// Matcher function applies the regex and calls back the original function
|
||||
// if the regex matches, passing in an array of the matched values
|
||||
var matchRegExpRe = new RegExp(matchRegExp);
|
||||
var matcher = function(path, id) {
|
||||
var match = matchRegExpRe.exec(path);
|
||||
if (match) {
|
||||
match.shift();
|
||||
fn(path, opt_id, match);
|
||||
}
|
||||
};
|
||||
this.addListener(matcher, listenPath, opt_id);
|
||||
|
||||
// Add the indexed listener to the map so that we can remove it later.
|
||||
var fnUid = goog.getUid(fn);
|
||||
if (!this.indexedListenersByFunction_[fnUid]) {
|
||||
this.indexedListenersByFunction_[fnUid] = {};
|
||||
}
|
||||
var key = dataPath + ':' + opt_id;
|
||||
this.indexedListenersByFunction_[fnUid][key] = {
|
||||
listener: {dataPath: listenPath, fn: matcher, id: opt_id}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes indexed listeners with a given callback function, and optional
|
||||
* matching datapath and matching id.
|
||||
*
|
||||
* @param {Function} fn Callback function, signature function(dataPath, id).
|
||||
* @param {string=} opt_dataPath Fully qualified data path.
|
||||
* @param {string=} opt_id A value passed back to the listener when the dataPath
|
||||
* is matched.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.removeIndexedListeners = function(
|
||||
fn, opt_dataPath, opt_id) {
|
||||
this.removeListenersByFunction_(
|
||||
this.indexedListenersByFunction_, true, fn, opt_dataPath, opt_id);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes listeners with a given callback function, and optional
|
||||
* matching dataPath and matching id
|
||||
*
|
||||
* @param {Function} fn Callback function, signature function(dataPath, id).
|
||||
* @param {string=} opt_dataPath Fully qualified data path.
|
||||
* @param {string=} opt_id A value passed back to the listener when the dataPath
|
||||
* is matched.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.removeListeners = function(fn, opt_dataPath,
|
||||
opt_id) {
|
||||
|
||||
// Normalize data path root
|
||||
if (opt_dataPath && goog.string.endsWith(opt_dataPath, '/...')) {
|
||||
opt_dataPath = opt_dataPath.substring(0, opt_dataPath.length - 4);
|
||||
} else if (opt_dataPath && goog.string.endsWith(opt_dataPath, '/*')) {
|
||||
opt_dataPath = opt_dataPath.substring(0, opt_dataPath.length - 2);
|
||||
}
|
||||
|
||||
this.removeListenersByFunction_(
|
||||
this.listenersByFunction_, false, fn, opt_dataPath, opt_id);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes listeners with a given callback function, and optional
|
||||
* matching dataPath and matching id from the given listenersByFunction
|
||||
* data structure.
|
||||
*
|
||||
* @param {Object} listenersByFunction The listeners by function.
|
||||
* @param {boolean} indexed Indicates whether the listenersByFunction are
|
||||
* indexed or not.
|
||||
* @param {Function} fn Callback function, signature function(dataPath, id).
|
||||
* @param {string=} opt_dataPath Fully qualified data path.
|
||||
* @param {string=} opt_id A value passed back to the listener when the dataPath
|
||||
* is matched.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.DataManager.prototype.removeListenersByFunction_ = function(
|
||||
listenersByFunction, indexed, fn, opt_dataPath, opt_id) {
|
||||
var fnUid = goog.getUid(fn);
|
||||
var functionMatches = listenersByFunction[fnUid];
|
||||
if (functionMatches != null) {
|
||||
for (var key in functionMatches) {
|
||||
var functionMatch = functionMatches[key];
|
||||
var listener = functionMatch.listener;
|
||||
if ((!opt_dataPath || opt_dataPath == listener.dataPath) &&
|
||||
(!opt_id || opt_id == listener.id)) {
|
||||
if (indexed) {
|
||||
this.removeListeners(
|
||||
listener.fn, listener.dataPath, listener.id);
|
||||
}
|
||||
if (functionMatch.items) {
|
||||
for (var i = 0; i < functionMatch.items.length; i++) {
|
||||
var item = functionMatch.items[i];
|
||||
delete item.obj[item.key];
|
||||
}
|
||||
}
|
||||
delete functionMatches[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the total number of listeners (per expression listened to, so may be
|
||||
* more than number of times addListener() has been called
|
||||
* @return {number} Number of listeners.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.getListenerCount = function() {
|
||||
var count = 0;
|
||||
goog.structs.forEach(this.listenerMap_, function(matchingListeners) {
|
||||
count += goog.structs.getCount(matchingListeners);
|
||||
});
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Disables the sending of all data events during the execution of the given
|
||||
* callback. This provides a way to avoid useless notifications of small changes
|
||||
* when you will eventually send a data event manually that encompasses them
|
||||
* all.
|
||||
*
|
||||
* Note that this function can not be called reentrantly.
|
||||
*
|
||||
* @param {Function} callback Zero-arg function to execute.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.runWithoutFiringDataChanges = function(callback) {
|
||||
if (this.disableFiring_) {
|
||||
throw Error('Can not nest calls to runWithoutFiringDataChanges');
|
||||
}
|
||||
|
||||
this.disableFiring_ = true;
|
||||
try {
|
||||
callback();
|
||||
} finally {
|
||||
this.disableFiring_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fire a data change event to all listeners
|
||||
*
|
||||
* If the path matches the path of a listener, the listener will fire
|
||||
*
|
||||
* If your path is the parent of a listener, the listener will fire. I.e.
|
||||
* if $Contacts/bob@bob.com changes, then we will fire listener for
|
||||
* $Contacts/bob@bob.com/Name as well, as the assumption is that when
|
||||
* a parent changes, all children are invalidated.
|
||||
*
|
||||
* If your path is the child of a listener, the listener may fire, depending
|
||||
* on the ancestor depth.
|
||||
*
|
||||
* A listener for $Contacts might only be interested if the contact name changes
|
||||
* (i.e. $Contacts doesn't fire on $Contacts/bob@bob.com/Name),
|
||||
* while a listener for a specific contact might
|
||||
* (i.e. $Contacts/bob@bob.com would fire on $Contacts/bob@bob.com/Name).
|
||||
* Adding "/..." to a lisetener path listens to all children, and adding "/*" to
|
||||
* a listener path listens only to direct children
|
||||
*
|
||||
* @param {string} dataPath Fully qualified data path.
|
||||
*/
|
||||
goog.ds.DataManager.prototype.fireDataChange = function(dataPath) {
|
||||
if (this.disableFiring_) {
|
||||
return;
|
||||
}
|
||||
|
||||
var expr = goog.ds.Expr.create(dataPath);
|
||||
var ancestorDepth = 0;
|
||||
|
||||
// Look for listeners for expression and all its parents.
|
||||
// Parents of listener expressions are all added to the listenerMap as well,
|
||||
// so this will evaluate inner loop every time the dataPath is a child or
|
||||
// an ancestor of the original listener path
|
||||
while (expr) {
|
||||
var matchingListeners = this.listenerMap_[expr.getSource()];
|
||||
if (matchingListeners) {
|
||||
for (var id in matchingListeners) {
|
||||
var match = matchingListeners[id];
|
||||
var listener = match.listener;
|
||||
if (ancestorDepth <= match.maxAncestors) {
|
||||
listener.fn(dataPath, listener.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
ancestorDepth++;
|
||||
expr = expr.getParent();
|
||||
}
|
||||
this.eventCount_++;
|
||||
};
|
||||
@@ -0,0 +1,656 @@
|
||||
// Copyright 2006 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 Generic rich data access API.
|
||||
*
|
||||
* Abstraction for data sources that allows listening for changes at different
|
||||
* levels of the data tree and updating the data via XHR requests
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.ds.BaseDataNode');
|
||||
goog.provide('goog.ds.BasicNodeList');
|
||||
goog.provide('goog.ds.DataNode');
|
||||
goog.provide('goog.ds.DataNodeList');
|
||||
goog.provide('goog.ds.EmptyNodeList');
|
||||
goog.provide('goog.ds.LoadState');
|
||||
goog.provide('goog.ds.SortedNodeList');
|
||||
goog.provide('goog.ds.Util');
|
||||
goog.provide('goog.ds.logger');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.log');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for node in rich data tree.
|
||||
*
|
||||
* Names that are reserved for system use and shouldn't be used for data node
|
||||
* names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
|
||||
* undefined if these names are used.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.DataNode = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the node
|
||||
* @param {...?} var_args Do not check arity of arguments, because
|
||||
* some subclasses require args.
|
||||
* @return {*} The value of the node, or null if no value.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.get = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the node
|
||||
* @param {*} value The new value of the node.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.set = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets all of the child nodes of the current node.
|
||||
* Should return an empty DataNode list if no child nodes.
|
||||
* @param {string=} opt_selector String selector to choose child nodes.
|
||||
* @return {goog.ds.DataNodeList} The child nodes.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getChildNodes = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node
|
||||
* @param {string} name The node name.
|
||||
* @param {boolean=} opt_canCreate Whether to create a child node if it does not
|
||||
* exist.
|
||||
* @return {goog.ds.DataNode} The child node, or null
|
||||
* if no node of this name exists.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getChildNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of a child node
|
||||
* @param {string} name The node name.
|
||||
* @return {*} The value of the node, or null if no value or the child node
|
||||
* doesn't exist.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getChildNodeValue = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Sets a named child node of the current node.
|
||||
*
|
||||
* @param {string} name The node name.
|
||||
* @param {Object} value The value to set, can be DataNode, object, property,
|
||||
* or null. If value is null, removes the child node.
|
||||
* @return {Object} The child node, if the node was set.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.setChildNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getDataName = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the node relative to the parent node
|
||||
* @param {string} name The name of the node.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.setDataName = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the a qualified data path to this node
|
||||
* @return {string} The data path.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getDataPath = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node
|
||||
*/
|
||||
goog.ds.DataNode.prototype.load = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.getLoadState = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the value of this node is a homogeneous list of data
|
||||
* @return {boolean} True if a list.
|
||||
*/
|
||||
goog.ds.DataNode.prototype.isList = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Enum for load state of a DataNode.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.ds.LoadState = {
|
||||
LOADED: 'LOADED',
|
||||
LOADING: 'LOADING',
|
||||
FAILED: 'FAILED',
|
||||
NOT_LOADED: 'NOT_LOADED'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for data node functionality, has default implementations for
|
||||
* many of the functions.
|
||||
*
|
||||
* implements {goog.ds.DataNode}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.BaseDataNode = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the node
|
||||
* @param {Object} value The new value of the node.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.set = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets all of the child nodes of the current node.
|
||||
* Should return an empty DataNode list if no child nodes.
|
||||
* @param {string=} opt_selector String selector to choose child nodes.
|
||||
* @return {goog.ds.DataNodeList} The child nodes.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getChildNodes = function(opt_selector) {
|
||||
return new goog.ds.EmptyNodeList();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node
|
||||
* @param {string} name The node name.
|
||||
* @param {boolean=} opt_canCreate Whether you can create the child node if
|
||||
* it doesn't exist already.
|
||||
* @return {goog.ds.DataNode} The child node, or null if no node of
|
||||
* this name exists and opt_create is false.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getChildNode = function(name, opt_canCreate) {
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of a child node
|
||||
* @param {string} name The node name.
|
||||
* @return {Object} The value of the node, or null if no value or the
|
||||
* child node doesn't exist.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getChildNodeValue = function(name) {
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getDataName = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the a qualified data path to this node
|
||||
* @return {string} The data path.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getDataPath = function() {
|
||||
var parentPath = '';
|
||||
var myName = this.getDataName();
|
||||
if (this.getParent && this.getParent()) {
|
||||
parentPath = this.getParent().getDataPath() +
|
||||
(myName.indexOf(goog.ds.STR_ARRAY_START) != -1 ? '' :
|
||||
goog.ds.STR_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
return parentPath + myName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.load = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getLoadState = function() {
|
||||
return goog.ds.LoadState.LOADED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent node. Subclasses implement this function
|
||||
* @type {Function}
|
||||
* @protected
|
||||
*/
|
||||
goog.ds.BaseDataNode.prototype.getParent = null;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for node list in rich data tree.
|
||||
*
|
||||
* Has both map and list-style accessors
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.ds.DataNode}
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available.
|
||||
goog.ds.DataNodeList = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Add a node to the node list.
|
||||
* If the node has a dataName, uses this for the key in the map.
|
||||
*
|
||||
* @param {goog.ds.DataNode} node The node to add.
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.add = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Get a node by string key.
|
||||
* Returns null if node doesn't exist.
|
||||
*
|
||||
* @param {string} key String lookup key.
|
||||
* @return {*} The node, or null if doesn't exist.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.get = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Get a node by index
|
||||
* Returns null if the index is out of range
|
||||
*
|
||||
* @param {number} index The index of the node.
|
||||
* @return {goog.ds.DataNode} The node, or null if doesn't exist.
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.getByIndex = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the size of the node list
|
||||
*
|
||||
* @return {number} The size of the list.
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.getCount = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Sets a node in the list of a given name
|
||||
* @param {string} name Name of the node.
|
||||
* @param {goog.ds.DataNode} node The node.
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.setNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Removes a node in the list of a given name
|
||||
* @param {string} name Name of the node.
|
||||
* @return {boolean} True if node existed and was deleted.
|
||||
*/
|
||||
goog.ds.DataNodeList.prototype.removeNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Simple node list implementation with underlying array and map
|
||||
* implements goog.ds.DataNodeList.
|
||||
*
|
||||
* Names that are reserved for system use and shouldn't be used for data node
|
||||
* names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
|
||||
* undefined if these names are used.
|
||||
*
|
||||
* @param {Array.<goog.ds.DataNode>=} opt_nodes optional nodes to add to list.
|
||||
* @constructor
|
||||
* @extends {goog.ds.DataNodeList}
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available.
|
||||
goog.ds.BasicNodeList = function(opt_nodes) {
|
||||
this.map_ = {};
|
||||
this.list_ = [];
|
||||
this.indexMap_ = {};
|
||||
if (opt_nodes) {
|
||||
for (var i = 0, node; node = opt_nodes[i]; i++) {
|
||||
this.add(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a node to the node list.
|
||||
* If the node has a dataName, uses this for the key in the map.
|
||||
* TODO(user) Remove function as well
|
||||
*
|
||||
* @param {goog.ds.DataNode} node The node to add.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.add = function(node) {
|
||||
this.list_.push(node);
|
||||
var dataName = node.getDataName();
|
||||
if (dataName) {
|
||||
this.map_[dataName] = node;
|
||||
this.indexMap_[dataName] = this.list_.length - 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a node by string key.
|
||||
* Returns null if node doesn't exist.
|
||||
*
|
||||
* @param {string} key String lookup key.
|
||||
* @return {goog.ds.DataNode} The node, or null if doesn't exist.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.get = function(key) {
|
||||
return this.map_[key] || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a node by index
|
||||
* Returns null if the index is out of range
|
||||
*
|
||||
* @param {number} index The index of the node.
|
||||
* @return {goog.ds.DataNode} The node, or null if doesn't exist.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.getByIndex = function(index) {
|
||||
return this.list_[index] || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the size of the node list
|
||||
*
|
||||
* @return {number} The size of the list.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.getCount = function() {
|
||||
return this.list_.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a node in the list of a given name
|
||||
* @param {string} name Name of the node.
|
||||
* @param {goog.ds.DataNode} node The node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.setNode = function(name, node) {
|
||||
if (node == null) {
|
||||
this.removeNode(name);
|
||||
} else {
|
||||
var existingNode = this.indexMap_[name];
|
||||
if (existingNode != null) {
|
||||
this.map_[name] = node;
|
||||
this.list_[existingNode] = node;
|
||||
} else {
|
||||
this.add(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a node in the list of a given name
|
||||
* @param {string} name Name of the node.
|
||||
* @return {boolean} True if node existed and was deleted.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.removeNode = function(name) {
|
||||
var existingNode = this.indexMap_[name];
|
||||
if (existingNode != null) {
|
||||
this.list_.splice(existingNode, 1);
|
||||
delete this.map_[name];
|
||||
delete this.indexMap_[name];
|
||||
for (var index in this.indexMap_) {
|
||||
if (this.indexMap_[index] > existingNode) {
|
||||
this.indexMap_[index]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return existingNode != null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the index of a named node
|
||||
* @param {string} name The name of the node to get the index of.
|
||||
* @return {number|undefined} The index.
|
||||
*/
|
||||
goog.ds.BasicNodeList.prototype.indexOf = function(name) {
|
||||
return this.indexMap_[name];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Immulatable empty node list
|
||||
* @extends {goog.ds.BasicNodeList}
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
goog.ds.EmptyNodeList = function() {
|
||||
goog.ds.BasicNodeList.call(this);
|
||||
};
|
||||
goog.inherits(goog.ds.EmptyNodeList, goog.ds.BasicNodeList);
|
||||
|
||||
|
||||
/**
|
||||
* Add a node to the node list.
|
||||
* If the node has a dataName, uses this for the key in the map.
|
||||
*
|
||||
* @param {goog.ds.DataNode} node The node to add.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.EmptyNodeList.prototype.add = function(node) {
|
||||
throw Error('Can\'t add to EmptyNodeList');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Node list implementation which maintains sort order during insertion and
|
||||
* modification operations based on a comparison function.
|
||||
*
|
||||
* The SortedNodeList does not guarantee sort order will be maintained if
|
||||
* the underlying data nodes are modified externally.
|
||||
*
|
||||
* Names that are reserved for system use and shouldn't be used for data node
|
||||
* names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
|
||||
* undefined if these names are used.
|
||||
*
|
||||
* @param {Function} compareFn Comparison function by which the
|
||||
* node list is sorted. Should take 2 arguments to compare, and return a
|
||||
* negative integer, zero, or a positive integer depending on whether the
|
||||
* first argument is less than, equal to, or greater than the second.
|
||||
* @param {Array.<goog.ds.DataNode>=} opt_nodes optional nodes to add to list;
|
||||
* these are assumed to be in sorted order.
|
||||
* @extends {goog.ds.BasicNodeList}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.SortedNodeList = function(compareFn, opt_nodes) {
|
||||
this.compareFn_ = compareFn;
|
||||
goog.ds.BasicNodeList.call(this, opt_nodes);
|
||||
};
|
||||
goog.inherits(goog.ds.SortedNodeList, goog.ds.BasicNodeList);
|
||||
|
||||
|
||||
/**
|
||||
* Add a node to the node list, maintaining sort order.
|
||||
* If the node has a dataName, uses this for the key in the map.
|
||||
*
|
||||
* @param {goog.ds.DataNode} node The node to add.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.SortedNodeList.prototype.add = function(node) {
|
||||
if (!this.compareFn_) {
|
||||
this.append(node);
|
||||
return;
|
||||
}
|
||||
|
||||
var searchLoc = goog.array.binarySearch(this.list_, node, this.compareFn_);
|
||||
|
||||
// if there is another node that is "equal" according to the comparison
|
||||
// function, insert before that one; otherwise insert at the location
|
||||
// goog.array.binarySearch indicated
|
||||
if (searchLoc < 0) {
|
||||
searchLoc = -(searchLoc + 1);
|
||||
}
|
||||
|
||||
// update any indexes that are after the insertion point
|
||||
for (var index in this.indexMap_) {
|
||||
if (this.indexMap_[index] >= searchLoc) {
|
||||
this.indexMap_[index]++;
|
||||
}
|
||||
}
|
||||
|
||||
goog.array.insertAt(this.list_, node, searchLoc);
|
||||
var dataName = node.getDataName();
|
||||
if (dataName) {
|
||||
this.map_[dataName] = node;
|
||||
this.indexMap_[dataName] = searchLoc;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds the given node to the end of the SortedNodeList. This should
|
||||
* only be used when the caller can guarantee that the sort order will
|
||||
* be maintained according to this SortedNodeList's compareFn (e.g.
|
||||
* when initializing a new SortedNodeList from a list of nodes that has
|
||||
* already been sorted).
|
||||
* @param {goog.ds.DataNode} node The node to append.
|
||||
*/
|
||||
goog.ds.SortedNodeList.prototype.append = function(node) {
|
||||
goog.ds.SortedNodeList.superClass_.add.call(this, node);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a node in the list of a given name, maintaining sort order.
|
||||
* @param {string} name Name of the node.
|
||||
* @param {goog.ds.DataNode} node The node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.SortedNodeList.prototype.setNode = function(name, node) {
|
||||
if (node == null) {
|
||||
this.removeNode(name);
|
||||
} else {
|
||||
var existingNode = this.indexMap_[name];
|
||||
if (existingNode != null) {
|
||||
if (this.compareFn_) {
|
||||
var compareResult = this.compareFn_(this.list_[existingNode], node);
|
||||
if (compareResult == 0) {
|
||||
// the new node can just replace the old one
|
||||
this.map_[name] = node;
|
||||
this.list_[existingNode] = node;
|
||||
} else {
|
||||
// remove the old node, then add the new one
|
||||
this.removeNode(name);
|
||||
this.add(node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.add(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The character denoting an attribute.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ds.STR_ATTRIBUTE_START = '@';
|
||||
|
||||
|
||||
/**
|
||||
* The character denoting all children.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ds.STR_ALL_CHILDREN_SELECTOR = '*';
|
||||
|
||||
|
||||
/**
|
||||
* The wildcard character.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ds.STR_WILDCARD = '*';
|
||||
|
||||
|
||||
/**
|
||||
* The character denoting path separation.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ds.STR_PATH_SEPARATOR = '/';
|
||||
|
||||
|
||||
/**
|
||||
* The character denoting the start of an array.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ds.STR_ARRAY_START = '[';
|
||||
|
||||
|
||||
/**
|
||||
* Shared logger instance for data package
|
||||
* @type {goog.log.Logger}
|
||||
*/
|
||||
goog.ds.logger = goog.log.getLogger('goog.ds');
|
||||
|
||||
|
||||
/**
|
||||
* Create a data node that references another data node,
|
||||
* useful for pointer-like functionality.
|
||||
* All functions will return same values as the original node except for
|
||||
* getDataName()
|
||||
* @param {!goog.ds.DataNode} node The original node.
|
||||
* @param {string} name The new name.
|
||||
* @return {!goog.ds.DataNode} The new data node.
|
||||
*/
|
||||
goog.ds.Util.makeReferenceNode = function(node, name) {
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.ds.DataNode}
|
||||
*/
|
||||
var nodeCreator = function() {};
|
||||
nodeCreator.prototype = node;
|
||||
var newNode = new nodeCreator();
|
||||
newNode.getDataName = function() {
|
||||
return name;
|
||||
};
|
||||
return newNode;
|
||||
};
|
||||
544
float-no-zero/closure-library/closure/goog/datasource/expr.js
Normal file
544
float-no-zero/closure-library/closure/goog/datasource/expr.js
Normal file
@@ -0,0 +1,544 @@
|
||||
// Copyright 2006 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
|
||||
* Expression evaluation utilities. Expression format is very similar to XPath.
|
||||
*
|
||||
* Expression details:
|
||||
* - Of format A/B/C, which will evaluate getChildNode('A').getChildNode('B').
|
||||
* getChildNodes('C')|getChildNodeValue('C')|getChildNode('C') depending on
|
||||
* call
|
||||
* - If expression ends with '/name()', will get the name() of the node
|
||||
* referenced by the preceding path.
|
||||
* - If expression ends with '/count()', will get the count() of the nodes that
|
||||
* match the expression referenced by the preceding path.
|
||||
* - If expression ends with '?', the value is OK to evaluate to null. This is
|
||||
* not enforced by the expression evaluation functions, instead it is
|
||||
* provided as a flag for client code which may ignore depending on usage
|
||||
* - If expression has [INDEX], will use getChildNodes().getByIndex(INDEX)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.ds.Expr');
|
||||
|
||||
goog.require('goog.ds.BasicNodeList');
|
||||
goog.require('goog.ds.EmptyNodeList');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new expression. An expression uses a string expression language, and
|
||||
* from this string and a passed in DataNode can evaluate to a value, DataNode,
|
||||
* or a DataNodeList.
|
||||
*
|
||||
* @param {string=} opt_expr The string expression.
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.Expr = function(opt_expr) {
|
||||
if (opt_expr) {
|
||||
this.setSource_(opt_expr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the source expression text & parse
|
||||
*
|
||||
* @param {string} expr The string expression source.
|
||||
* @param {Array=} opt_parts Array of the parts of an expression.
|
||||
* @param {goog.ds.Expr=} opt_childExpr Optional child of this expression,
|
||||
* passed in as a hint for processing.
|
||||
* @param {goog.ds.Expr=} opt_prevExpr Optional preceding expression
|
||||
* (i.e. $A/B/C is previous expression to B/C) passed in as a hint for
|
||||
* processing.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.setSource_ = function(expr, opt_parts,
|
||||
opt_childExpr, opt_prevExpr) {
|
||||
this.src_ = expr;
|
||||
|
||||
if (!opt_childExpr && !opt_prevExpr) {
|
||||
// Check whether it can be empty
|
||||
if (goog.string.endsWith(expr, goog.ds.Expr.String_.CAN_BE_EMPTY)) {
|
||||
this.canBeEmpty_ = true;
|
||||
expr = expr.substring(0, expr.length - 1);
|
||||
}
|
||||
|
||||
// Check whether this is an node function
|
||||
if (goog.string.endsWith(expr, '()')) {
|
||||
if (goog.string.endsWith(expr, goog.ds.Expr.String_.NAME_EXPR) ||
|
||||
goog.string.endsWith(expr, goog.ds.Expr.String_.COUNT_EXPR) ||
|
||||
goog.string.endsWith(expr, goog.ds.Expr.String_.POSITION_EXPR)) {
|
||||
var lastPos = expr.lastIndexOf(goog.ds.Expr.String_.SEPARATOR);
|
||||
if (lastPos != -1) {
|
||||
this.exprFn_ = expr.substring(lastPos + 1);
|
||||
expr = expr.substring(0, lastPos);
|
||||
} else {
|
||||
this.exprFn_ = expr;
|
||||
expr = goog.ds.Expr.String_.CURRENT_NODE_EXPR;
|
||||
}
|
||||
if (this.exprFn_ == goog.ds.Expr.String_.COUNT_EXPR) {
|
||||
this.isCount_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Split into component parts
|
||||
this.parts_ = opt_parts || expr.split('/');
|
||||
this.size_ = this.parts_.length;
|
||||
this.last_ = this.parts_[this.size_ - 1];
|
||||
this.root_ = this.parts_[0];
|
||||
|
||||
if (this.size_ == 1) {
|
||||
this.rootExpr_ = this;
|
||||
this.isAbsolute_ = goog.string.startsWith(expr, '$');
|
||||
} else {
|
||||
this.rootExpr_ = goog.ds.Expr.createInternal_(this.root_, null,
|
||||
this, null);
|
||||
this.isAbsolute_ = this.rootExpr_.isAbsolute_;
|
||||
this.root_ = this.rootExpr_.root_;
|
||||
}
|
||||
|
||||
if (this.size_ == 1 && !this.isAbsolute_) {
|
||||
// Check whether expression maps to current node, for convenience
|
||||
this.isCurrent_ = (expr == goog.ds.Expr.String_.CURRENT_NODE_EXPR ||
|
||||
expr == goog.ds.Expr.String_.EMPTY_EXPR);
|
||||
|
||||
// Whether this expression is just an attribute (i.e. '@foo')
|
||||
this.isJustAttribute_ =
|
||||
goog.string.startsWith(expr, goog.ds.Expr.String_.ATTRIBUTE_START);
|
||||
|
||||
// Check whether this is a common node expression
|
||||
this.isAllChildNodes_ = expr == goog.ds.Expr.String_.ALL_CHILD_NODES_EXPR;
|
||||
this.isAllAttributes_ = expr == goog.ds.Expr.String_.ALL_ATTRIBUTES_EXPR;
|
||||
this.isAllElements_ = expr == goog.ds.Expr.String_.ALL_ELEMENTS_EXPR;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the source data path for the expression
|
||||
* @return {string} The path.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getSource = function() {
|
||||
return this.src_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last part of the expression.
|
||||
* @return {?string} Last part of the expression.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getLast = function() {
|
||||
return this.last_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent expression of this expression, or null if this is top level
|
||||
* @return {goog.ds.Expr} The parent.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getParent = function() {
|
||||
if (!this.parentExprSet_) {
|
||||
if (this.size_ > 1) {
|
||||
this.parentExpr_ = goog.ds.Expr.createInternal_(null,
|
||||
this.parts_.slice(0, this.parts_.length - 1), this, null);
|
||||
}
|
||||
this.parentExprSet_ = true;
|
||||
}
|
||||
return this.parentExpr_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent expression of this expression, or null if this is top level
|
||||
* @return {goog.ds.Expr} The parent.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getNext = function() {
|
||||
if (!this.nextExprSet_) {
|
||||
if (this.size_ > 1) {
|
||||
this.nextExpr_ = goog.ds.Expr.createInternal_(null, this.parts_.slice(1),
|
||||
null, this);
|
||||
}
|
||||
this.nextExprSet_ = true;
|
||||
}
|
||||
return this.nextExpr_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate an expression on a data node, and return a value
|
||||
* Recursively walks through child nodes to evaluate
|
||||
* TODO(user) Support other expression functions
|
||||
*
|
||||
* @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
|
||||
* If not provided, evaluates against DataManager global root.
|
||||
* @return {*} Value of the node, or null if doesn't exist.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getValue = function(opt_ds) {
|
||||
if (opt_ds == null) {
|
||||
opt_ds = goog.ds.DataManager.getInstance();
|
||||
} else if (this.isAbsolute_) {
|
||||
opt_ds = opt_ds.getDataRoot ? opt_ds.getDataRoot() :
|
||||
goog.ds.DataManager.getInstance();
|
||||
}
|
||||
|
||||
if (this.isCount_) {
|
||||
var nodes = this.getNodes(opt_ds);
|
||||
return nodes.getCount();
|
||||
}
|
||||
|
||||
if (this.size_ == 1) {
|
||||
return opt_ds.getChildNodeValue(this.root_);
|
||||
} else if (this.size_ == 0) {
|
||||
return opt_ds.get();
|
||||
}
|
||||
|
||||
var nextDs = opt_ds.getChildNode(this.root_);
|
||||
|
||||
if (nextDs == null) {
|
||||
return null;
|
||||
} else {
|
||||
return this.getNext().getValue(nextDs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate an expression on a data node, and return matching nodes
|
||||
* Recursively walks through child nodes to evaluate
|
||||
*
|
||||
* @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
|
||||
* If not provided, evaluates against data root.
|
||||
* @param {boolean=} opt_canCreate If true, will try to create new nodes.
|
||||
* @return {goog.ds.DataNodeList} Matching nodes.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getNodes = function(opt_ds, opt_canCreate) {
|
||||
return /** @type {goog.ds.DataNodeList} */(this.getNodes_(opt_ds,
|
||||
false, opt_canCreate));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate an expression on a data node, and return the first matching node
|
||||
* Recursively walks through child nodes to evaluate
|
||||
*
|
||||
* @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
|
||||
* If not provided, evaluates against DataManager global root.
|
||||
* @param {boolean=} opt_canCreate If true, will try to create new nodes.
|
||||
* @return {goog.ds.DataNode} Matching nodes, or null if doesn't exist.
|
||||
*/
|
||||
goog.ds.Expr.prototype.getNode = function(opt_ds, opt_canCreate) {
|
||||
return /** @type {goog.ds.DataNode} */(this.getNodes_(opt_ds,
|
||||
true, opt_canCreate));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate an expression on a data node, and return the first matching node
|
||||
* Recursively walks through child nodes to evaluate
|
||||
*
|
||||
* @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
|
||||
* If not provided, evaluates against DataManager global root.
|
||||
* @param {boolean=} opt_selectOne Whether to return single matching DataNode
|
||||
* or matching nodes in DataNodeList.
|
||||
* @param {boolean=} opt_canCreate If true, will try to create new nodes.
|
||||
* @return {goog.ds.DataNode|goog.ds.DataNodeList} Matching node or nodes,
|
||||
* depending on value of opt_selectOne.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.getNodes_ = function(opt_ds, opt_selectOne,
|
||||
opt_canCreate) {
|
||||
if (opt_ds == null) {
|
||||
opt_ds = goog.ds.DataManager.getInstance();
|
||||
} else if (this.isAbsolute_) {
|
||||
opt_ds = opt_ds.getDataRoot ? opt_ds.getDataRoot() :
|
||||
goog.ds.DataManager.getInstance();
|
||||
}
|
||||
|
||||
if (this.size_ == 0 && opt_selectOne) {
|
||||
return opt_ds;
|
||||
} else if (this.size_ == 0 && !opt_selectOne) {
|
||||
return new goog.ds.BasicNodeList([opt_ds]);
|
||||
} else if (this.size_ == 1) {
|
||||
if (opt_selectOne) {
|
||||
return opt_ds.getChildNode(this.root_, opt_canCreate);
|
||||
}
|
||||
else {
|
||||
var possibleListChild = opt_ds.getChildNode(this.root_);
|
||||
if (possibleListChild && possibleListChild.isList()) {
|
||||
return possibleListChild.getChildNodes();
|
||||
} else {
|
||||
return opt_ds.getChildNodes(this.root_);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var nextDs = opt_ds.getChildNode(this.root_, opt_canCreate);
|
||||
if (nextDs == null && opt_selectOne) {
|
||||
return null;
|
||||
} else if (nextDs == null && !opt_selectOne) {
|
||||
return new goog.ds.EmptyNodeList();
|
||||
}
|
||||
return this.getNext().getNodes_(nextDs, opt_selectOne, opt_canCreate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the expression can be null.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.canBeEmpty_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* The parsed paths in the expression
|
||||
*
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.parts_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Number of paths in the expression
|
||||
*
|
||||
* @type {?number}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.size_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* The root node path in the expression
|
||||
*
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.root_;
|
||||
|
||||
|
||||
/**
|
||||
* The last path in the expression
|
||||
*
|
||||
* @type {?string}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.last_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the expression evaluates to current node
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.isCurrent_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the expression is just an attribute
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.isJustAttribute_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Does this expression select all DOM-style child nodes (element and text)
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.isAllChildNodes_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Does this expression select all DOM-style attribute nodes (starts with '@')
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.isAllAttributes_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Does this expression select all DOM-style element child nodes
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.isAllElements_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* The function used by this expression
|
||||
*
|
||||
* @type {?string}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.exprFn_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Cached value for the parent expression.
|
||||
* @type {goog.ds.Expr?}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.parentExpr_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Cached value for the next expression.
|
||||
* @type {goog.ds.Expr?}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.prototype.nextExpr_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Create an expression from a string, can use cached values
|
||||
*
|
||||
* @param {string} expr The expression string.
|
||||
* @return {goog.ds.Expr} The expression object.
|
||||
*/
|
||||
goog.ds.Expr.create = function(expr) {
|
||||
var result = goog.ds.Expr.cache_[expr];
|
||||
|
||||
if (result == null) {
|
||||
result = new goog.ds.Expr(expr);
|
||||
goog.ds.Expr.cache_[expr] = result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create an expression from a string, can use cached values
|
||||
* Uses hints from related expressions to help in creation
|
||||
*
|
||||
* @param {?string=} opt_expr The string expression source.
|
||||
* @param {Array=} opt_parts Array of the parts of an expression.
|
||||
* @param {goog.ds.Expr=} opt_childExpr Optional child of this expression,
|
||||
* passed in as a hint for processing.
|
||||
* @param {goog.ds.Expr=} opt_prevExpr Optional preceding expression
|
||||
* (i.e. $A/B/C is previous expression to B/C) passed in as a hint for
|
||||
* processing.
|
||||
* @return {goog.ds.Expr} The expression object.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.createInternal_ = function(opt_expr, opt_parts, opt_childExpr,
|
||||
opt_prevExpr) {
|
||||
var expr = opt_expr || opt_parts.join('/');
|
||||
var result = goog.ds.Expr.cache_[expr];
|
||||
|
||||
if (result == null) {
|
||||
result = new goog.ds.Expr();
|
||||
result.setSource_(expr, opt_parts, opt_childExpr, opt_prevExpr);
|
||||
goog.ds.Expr.cache_[expr] = result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cache of pre-parsed expressions
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.cache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Commonly used strings in expressions.
|
||||
* @enum {string}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.Expr.String_ = {
|
||||
SEPARATOR: '/',
|
||||
CURRENT_NODE_EXPR: '.',
|
||||
EMPTY_EXPR: '',
|
||||
ATTRIBUTE_START: '@',
|
||||
ALL_CHILD_NODES_EXPR: '*|text()',
|
||||
ALL_ATTRIBUTES_EXPR: '@*',
|
||||
ALL_ELEMENTS_EXPR: '*',
|
||||
NAME_EXPR: 'name()',
|
||||
COUNT_EXPR: 'count()',
|
||||
POSITION_EXPR: 'position()',
|
||||
INDEX_START: '[',
|
||||
INDEX_END: ']',
|
||||
CAN_BE_EMPTY: '?'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Standard expressions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The current node
|
||||
*/
|
||||
goog.ds.Expr.CURRENT = goog.ds.Expr.create(
|
||||
goog.ds.Expr.String_.CURRENT_NODE_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* For DOM interop - all DOM child nodes (text + element).
|
||||
* Text nodes have dataName #text
|
||||
*/
|
||||
goog.ds.Expr.ALL_CHILD_NODES =
|
||||
goog.ds.Expr.create(goog.ds.Expr.String_.ALL_CHILD_NODES_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* For DOM interop - all DOM element child nodes
|
||||
*/
|
||||
goog.ds.Expr.ALL_ELEMENTS =
|
||||
goog.ds.Expr.create(goog.ds.Expr.String_.ALL_ELEMENTS_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* For DOM interop - all DOM attribute nodes
|
||||
* Attribute nodes have dataName starting with "@"
|
||||
*/
|
||||
goog.ds.Expr.ALL_ATTRIBUTES =
|
||||
goog.ds.Expr.create(goog.ds.Expr.String_.ALL_ATTRIBUTES_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* Get the dataName of a node
|
||||
*/
|
||||
goog.ds.Expr.NAME = goog.ds.Expr.create(goog.ds.Expr.String_.NAME_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* Get the count of nodes matching an expression
|
||||
*/
|
||||
goog.ds.Expr.COUNT = goog.ds.Expr.create(goog.ds.Expr.String_.COUNT_EXPR);
|
||||
|
||||
|
||||
/**
|
||||
* Get the position of the "current" node in the current node list
|
||||
* This will only apply for datasources that support the concept of a current
|
||||
* node (none exist yet). This is similar to XPath position() and concept of
|
||||
* current node
|
||||
*/
|
||||
goog.ds.Expr.POSITION = goog.ds.Expr.create(goog.ds.Expr.String_.POSITION_EXPR);
|
||||
@@ -0,0 +1,811 @@
|
||||
// Copyright 2007 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
|
||||
* Efficient implementation of DataNode API.
|
||||
*
|
||||
* The implementation consists of three concrete classes for modelling
|
||||
* DataNodes with different characteristics: FastDataNode,
|
||||
* FastPrimitiveDataNode and FastListNode.
|
||||
*
|
||||
* FastDataNode is for bean-like or map-like objects that consists of
|
||||
* key/value mappings and where the primary access pattern is by key.
|
||||
*
|
||||
* FastPrimitiveDataNode wraps primitives like strings, boolean, and numbers.
|
||||
*
|
||||
* FastListNode is for array-like data nodes. It also supports key-based
|
||||
* lookups if the data nodes have an "id" property or if child nodes are
|
||||
* explicitly added by name. It is most efficient if these features are not
|
||||
* used.
|
||||
*
|
||||
* FastDataNodes can be constructed from JSON-like objects via the function
|
||||
* goog.ds.FastDataNode.fromJs.
|
||||
|
||||
*/
|
||||
|
||||
goog.provide('goog.ds.AbstractFastDataNode');
|
||||
goog.provide('goog.ds.FastDataNode');
|
||||
goog.provide('goog.ds.FastListNode');
|
||||
goog.provide('goog.ds.PrimitiveFastDataNode');
|
||||
|
||||
goog.require('goog.ds.DataManager');
|
||||
goog.require('goog.ds.EmptyNodeList');
|
||||
goog.require('goog.string');
|
||||
|
||||
/*
|
||||
* Implementation note: In order to reduce the number of objects,
|
||||
* FastDataNode stores its key/value mappings directly in the FastDataNode
|
||||
* object iself (instead of a separate map). To make this work we have to
|
||||
* sure that there are no name clashes with other attribute names used by
|
||||
* FastDataNode (like dataName and parent). This is especially difficult in
|
||||
* the light of automatic renaming by the JavaScript compiler. For this reason,
|
||||
* all internal attributes start with "__" so that they are not renamed
|
||||
* by the compiler.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new abstract data node.
|
||||
* @param {string} dataName Name of the datanode.
|
||||
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
|
||||
* @constructor
|
||||
* @extends {goog.ds.DataNodeList}
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available.
|
||||
goog.ds.AbstractFastDataNode = function(dataName, opt_parent) {
|
||||
if (!dataName) {
|
||||
throw Error('Cannot create a fast data node without a data name');
|
||||
}
|
||||
this['__dataName'] = dataName;
|
||||
this['__parent'] = opt_parent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of this data node.
|
||||
* @return {string} Name of this data noden.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.AbstractFastDataNode.prototype.getDataName = function() {
|
||||
return this['__dataName'];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of this data node.
|
||||
* @param {string} value Name.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.AbstractFastDataNode.prototype.setDataName = function(value) {
|
||||
this['__dataName'] = value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the path leading to this data node.
|
||||
* @return {string} Data path.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.AbstractFastDataNode.prototype.getDataPath = function() {
|
||||
var parentPath;
|
||||
if (this['__parent']) {
|
||||
parentPath = this['__parent'].getDataPath() + goog.ds.STR_PATH_SEPARATOR;
|
||||
} else {
|
||||
parentPath = '';
|
||||
}
|
||||
return parentPath + this.getDataName();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new fast data node, using the properties of root.
|
||||
* @param {Object} root JSON-like object to initialize data node from.
|
||||
* @param {string} dataName Name of this data node.
|
||||
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
|
||||
* @extends {goog.ds.AbstractFastDataNode}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.FastDataNode = function(root, dataName, opt_parent) {
|
||||
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
|
||||
this.extendWith(root);
|
||||
};
|
||||
goog.inherits(goog.ds.FastDataNode, goog.ds.AbstractFastDataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Add all attributes of object to this data node.
|
||||
* @param {Object} object Object to add attributes from.
|
||||
* @protected
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.extendWith = function(object) {
|
||||
for (var key in object) {
|
||||
this[key] = object[key];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new FastDataNode structure initialized from object. This will
|
||||
* return an instance of the most suitable sub-class of FastDataNode.
|
||||
*
|
||||
* You should not modify object after creating a fast data node from it
|
||||
* or assume that changing object changes the data node. Doing so results
|
||||
* in undefined behaviour.
|
||||
*
|
||||
* @param {Object|number|boolean|string} object Object to initialize data
|
||||
* node from.
|
||||
* @param {string} dataName Name of data node.
|
||||
* @param {goog.ds.DataNode=} opt_parent Parent of data node.
|
||||
* @return {goog.ds.AbstractFastDataNode} Data node representing object.
|
||||
*/
|
||||
goog.ds.FastDataNode.fromJs = function(object, dataName, opt_parent) {
|
||||
if (goog.isArray(object)) {
|
||||
return new goog.ds.FastListNode(object, dataName, opt_parent);
|
||||
} else if (goog.isObject(object)) {
|
||||
return new goog.ds.FastDataNode(object, dataName, opt_parent);
|
||||
} else {
|
||||
return new goog.ds.PrimitiveFastDataNode(object || !!object,
|
||||
dataName,
|
||||
opt_parent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Static instance of an empty list.
|
||||
* @type {goog.ds.EmptyNodeList}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.FastDataNode.emptyList_ = new goog.ds.EmptyNodeList();
|
||||
|
||||
|
||||
/**
|
||||
* Not supported for normal FastDataNodes.
|
||||
* @param {*} value Value to set data node to.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.set = function(value) {
|
||||
throw 'Not implemented yet';
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.FastDataNode.prototype.getChildNodes = function(opt_selector) {
|
||||
if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
|
||||
return this;
|
||||
} else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
|
||||
var child = this.getChildNode(opt_selector);
|
||||
return child ? new goog.ds.FastListNode([child], '') :
|
||||
new goog.ds.EmptyNodeList();
|
||||
} else {
|
||||
throw Error('Unsupported selector: ' + opt_selector);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes sure that a named child is wrapped in a data node structure.
|
||||
* @param {string} name Name of child to wrap.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.wrapChild_ = function(name) {
|
||||
var child = this[name];
|
||||
if (child != null && !child.getDataName) {
|
||||
this[name] = goog.ds.FastDataNode.fromJs(this[name], name, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a child node by name.
|
||||
* @param {string} name Name of child node.
|
||||
* @param {boolean=} opt_create Whether to create the child if it does not
|
||||
* exist.
|
||||
* @return {goog.ds.DataNode} Child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.getChildNode = function(name, opt_create) {
|
||||
this.wrapChild_(name);
|
||||
// this[name] always is a data node object, so using "||" is fine.
|
||||
var child = this[name] || null;
|
||||
if (child == null && opt_create) {
|
||||
child = new goog.ds.FastDataNode({}, name, this);
|
||||
this[name] = child;
|
||||
}
|
||||
return child;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a child node. Creates the child if it does not exist.
|
||||
*
|
||||
* Calling this function makes any child nodes previously obtained for name
|
||||
* invalid. You should not use these child nodes but instead obtain a new
|
||||
* instance by calling getChildNode.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.setChildNode = function(name, value) {
|
||||
if (value != null) {
|
||||
this[name] = value;
|
||||
} else {
|
||||
delete this[name];
|
||||
}
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath() +
|
||||
goog.ds.STR_PATH_SEPARATOR + name);
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a child node. By using this method you can avoid
|
||||
* the need to create PrimitiveFastData nodes.
|
||||
* @param {string} name Name of child node.
|
||||
* @return {Object} Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.getChildNodeValue = function(name) {
|
||||
var child = this[name];
|
||||
if (child != null) {
|
||||
return (child.getDataName ? child.get() : child);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this data node is a list. Always returns false for
|
||||
* instances of FastDataNode but may return true for subclasses.
|
||||
* @return {boolean} Whether this data node is array-like.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.isList = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a javascript object representation of this data node. You should
|
||||
* not modify the object returned by this function.
|
||||
* @return {Object} Javascript object representation of this data node.
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.getJsObject = function() {
|
||||
var result = {};
|
||||
for (var key in this) {
|
||||
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
|
||||
result[key] = (this[key]['__dataName'] ? this[key].getJsObject() :
|
||||
this[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a deep copy of this data node.
|
||||
* @return {goog.ds.FastDataNode} Clone of this data node.
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.clone = function() {
|
||||
return /** @type {goog.ds.FastDataNode} */(goog.ds.FastDataNode.fromJs(
|
||||
this.getJsObject(), this.getDataName()));
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of goog.ds.DataNodeList for FastDataNode.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Adds a child to this data node.
|
||||
* @param {goog.ds.DataNode} value Child node to add.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.add = function(value) {
|
||||
this.setChildNode(value.getDataName(), value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of this data node (if called without opt_key) or
|
||||
* gets a child node (if called with opt_key).
|
||||
* @param {string=} opt_key Name of child node.
|
||||
* @return {*} This data node or a child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.get = function(opt_key) {
|
||||
if (!goog.isDef(opt_key)) {
|
||||
// if there is no key, DataNode#get was called
|
||||
return this;
|
||||
} else {
|
||||
return this.getChildNode(opt_key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a child node by index. This method has a complexity of O(n) where
|
||||
* n is the number of children. If you need a faster implementation of this
|
||||
* method, you should use goog.ds.FastListNode.
|
||||
* @param {number} index Index of child node (starting from 0).
|
||||
* @return {goog.ds.DataNode} Child node at specified index.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.getByIndex = function(index) {
|
||||
var i = 0;
|
||||
for (var key in this) {
|
||||
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
|
||||
if (i == index) {
|
||||
this.wrapChild_(key);
|
||||
return this[key];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of child nodes. This method has a complexity of O(n) where
|
||||
* n is the number of children. If you need a faster implementation of this
|
||||
* method, you should use goog.ds.FastListNode.
|
||||
* @return {number} Number of child nodes.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.getCount = function() {
|
||||
var count = 0;
|
||||
for (var key in this) {
|
||||
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
// maybe cache this?
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a child node.
|
||||
* @param {string} name Name of child node.
|
||||
* @param {Object} value Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.setNode = function(name, value) {
|
||||
this.setChildNode(name, value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastDataNode.prototype.removeNode = function(name) {
|
||||
delete this[name];
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new data node wrapping a primitive value.
|
||||
* @param {number|boolean|string} value Value the value to wrap.
|
||||
* @param {string} dataName name Name of this data node.
|
||||
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
|
||||
* @extends {goog.ds.AbstractFastDataNode}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode = function(value, dataName, opt_parent) {
|
||||
this.value_ = value;
|
||||
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
|
||||
};
|
||||
goog.inherits(goog.ds.PrimitiveFastDataNode, goog.ds.AbstractFastDataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of this data node.
|
||||
* @return {(boolean|number|string)} Value of this data node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.get = function() {
|
||||
return this.value_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets this data node to a new value.
|
||||
* @param {*} value Value to set data node to.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.set = function(value) {
|
||||
if (goog.isArray(value) || goog.isObject(value)) {
|
||||
throw Error('can only set PrimitiveFastDataNode to primitive values');
|
||||
}
|
||||
this.value_ = value;
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns child nodes of this data node. Always returns an unmodifiable,
|
||||
* empty list.
|
||||
* @return {goog.ds.DataNodeList} (Empty) list of child nodes.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.getChildNodes = function() {
|
||||
return goog.ds.FastDataNode.emptyList_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a child node by name. Always returns null.
|
||||
* @param {string} name Name of child node.
|
||||
* @return {goog.ds.DataNode} Child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.getChildNode = function(name) {
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a child node. Always returns null.
|
||||
* @param {string} name Name of child node.
|
||||
* @return {Object} Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.getChildNodeValue = function(name) {
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Not supported by primitive data nodes.
|
||||
* @param {string} name Name of child node.
|
||||
* @param {Object} value Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.setChildNode =
|
||||
function(name, value) {
|
||||
throw Error('Cannot set a child node for a PrimitiveFastDataNode');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this data node is a list. Always returns false for
|
||||
* instances of PrimitiveFastDataNode.
|
||||
* @return {boolean} Whether this data node is array-like.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.isList = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a javascript object representation of this data node. You should
|
||||
* not modify the object returned by this function.
|
||||
* @return {*} Javascript object representation of this data node.
|
||||
*/
|
||||
goog.ds.PrimitiveFastDataNode.prototype.getJsObject = function() {
|
||||
return this.value_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new list node from an array.
|
||||
* @param {Array} values values hold by this list node.
|
||||
* @param {string} dataName name of this node.
|
||||
* @param {goog.ds.DataNode=} opt_parent parent of this node.
|
||||
* @extends {goog.ds.AbstractFastDataNode}
|
||||
* @constructor
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available. This implements DataNodeList
|
||||
// as well.
|
||||
goog.ds.FastListNode = function(values, dataName, opt_parent) {
|
||||
this.values_ = [];
|
||||
for (var i = 0; i < values.length; ++i) {
|
||||
var name = values[i].id || ('[' + i + ']');
|
||||
this.values_.push(goog.ds.FastDataNode.fromJs(values[i], name, this));
|
||||
if (values[i].id) {
|
||||
if (!this.map_) {
|
||||
this.map_ = {};
|
||||
}
|
||||
this.map_[values[i].id] = i;
|
||||
}
|
||||
}
|
||||
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
|
||||
};
|
||||
goog.inherits(goog.ds.FastListNode, goog.ds.AbstractFastDataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Not supported for FastListNodes.
|
||||
* @param {*} value Value to set data node to.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.set = function(value) {
|
||||
throw Error('Cannot set a FastListNode to a new value');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns child nodes of this data node. Currently, only supports
|
||||
* returning all children.
|
||||
* @return {goog.ds.DataNodeList} List of child nodes.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getChildNodes = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a child node by name.
|
||||
* @param {string} key Name of child node.
|
||||
* @param {boolean=} opt_create Whether to create the child if it does not
|
||||
* exist.
|
||||
* @return {goog.ds.DataNode} Child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getChildNode = function(key, opt_create) {
|
||||
var index = this.getKeyAsNumber_(key);
|
||||
if (index == null && this.map_) {
|
||||
index = this.map_[key];
|
||||
}
|
||||
if (index != null && this.values_[index]) {
|
||||
return this.values_[index];
|
||||
} else if (opt_create) {
|
||||
this.setChildNode(key, {});
|
||||
return this.getChildNode(key);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a child node.
|
||||
* @param {string} key Name of child node.
|
||||
* @return {*} Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getChildNodeValue = function(key) {
|
||||
var child = this.getChildNode(key);
|
||||
return (child ? child.get() : null);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tries to interpret key as a numeric index enclosed by square brakcets.
|
||||
* @param {string} key Key that should be interpreted as a number.
|
||||
* @return {?number} Numeric index or null if key is not of the form
|
||||
* described above.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getKeyAsNumber_ = function(key) {
|
||||
if (key.charAt(0) == '[' && key.charAt(key.length - 1) == ']') {
|
||||
return Number(key.substring(1, key.length - 1));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a child node. Creates the child if it does not exist. To set
|
||||
* children at a certain index, use a key of the form '[index]'. Note, that
|
||||
* you can only set values at existing numeric indices. To add a new node
|
||||
* to this list, you have to use the add method.
|
||||
*
|
||||
* Calling this function makes any child nodes previously obtained for name
|
||||
* invalid. You should not use these child nodes but instead obtain a new
|
||||
* instance by calling getChildNode.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.setChildNode = function(key, value) {
|
||||
var count = this.values_.length;
|
||||
if (value != null) {
|
||||
if (!value.getDataName) {
|
||||
value = goog.ds.FastDataNode.fromJs(value, key, this);
|
||||
}
|
||||
var index = this.getKeyAsNumber_(key);
|
||||
if (index != null) {
|
||||
if (index < 0 || index >= this.values_.length) {
|
||||
throw Error('List index out of bounds: ' + index);
|
||||
}
|
||||
this.values_[key] = value;
|
||||
} else {
|
||||
if (!this.map_) {
|
||||
this.map_ = {};
|
||||
}
|
||||
this.values_.push(value);
|
||||
this.map_[key] = this.values_.length - 1;
|
||||
}
|
||||
} else {
|
||||
this.removeNode(key);
|
||||
}
|
||||
var dm = goog.ds.DataManager.getInstance();
|
||||
dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + key);
|
||||
if (this.values_.length != count) {
|
||||
this.listSizeChanged_();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fire data changes that are appropriate when the size of this list changes.
|
||||
* Should be called whenever the list size has changed.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.listSizeChanged_ = function() {
|
||||
var dm = goog.ds.DataManager.getInstance();
|
||||
dm.fireDataChange(this.getDataPath());
|
||||
dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
|
||||
'count()');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this data node is a list. Always returns true.
|
||||
* @return {boolean} Whether this data node is array-like.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.isList = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a javascript object representation of this data node. You should
|
||||
* not modify the object returned by this function.
|
||||
* @return {Object} Javascript object representation of this data node.
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getJsObject = function() {
|
||||
var result = [];
|
||||
for (var i = 0; i < this.values_.length; ++i) {
|
||||
result.push(this.values_[i].getJsObject());
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of goog.ds.DataNodeList for FastListNode.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Adds a child to this data node
|
||||
* @param {goog.ds.DataNode} value Child node to add.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.add = function(value) {
|
||||
if (!value.getDataName) {
|
||||
value = goog.ds.FastDataNode.fromJs(value,
|
||||
String('[' + (this.values_.length) + ']'), this);
|
||||
}
|
||||
this.values_.push(value);
|
||||
var dm = goog.ds.DataManager.getInstance();
|
||||
dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
|
||||
'[' + (this.values_.length - 1) + ']');
|
||||
this.listSizeChanged_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of this data node (if called without opt_key) or
|
||||
* gets a child node (if called with opt_key).
|
||||
* @param {string=} opt_key Name of child node.
|
||||
* @return {Array|goog.ds.DataNode} Array of child nodes (if called without
|
||||
* opt_key), or a named child node otherwise.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.get = function(opt_key) {
|
||||
// if there are no arguments, DataNode.get was called
|
||||
if (!goog.isDef(opt_key)) {
|
||||
return this.values_;
|
||||
} else {
|
||||
return this.getChildNode(opt_key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a child node by (numeric) index.
|
||||
* @param {number} index Index of child node (starting from 0).
|
||||
* @return {goog.ds.DataNode} Child node at specified index.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getByIndex = function(index) {
|
||||
var child = this.values_[index];
|
||||
return (child != null ? child : null); // never return undefined
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of child nodes.
|
||||
* @return {number} Number of child nodes.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.getCount = function() {
|
||||
return this.values_.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a child node.
|
||||
* @param {string} name Name of child node.
|
||||
* @param {Object} value Value of child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.setNode = function(name, value) {
|
||||
throw Error('Setting child nodes of a FastListNode is not implemented, yet');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a child node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.removeNode = function(name) {
|
||||
var index = this.getKeyAsNumber_(name);
|
||||
if (index == null && this.map_) {
|
||||
index = this.map_[name];
|
||||
}
|
||||
if (index != null) {
|
||||
this.values_.splice(index, 1);
|
||||
if (this.map_) {
|
||||
var keyToDelete = null;
|
||||
for (var key in this.map_) {
|
||||
if (this.map_[key] == index) {
|
||||
keyToDelete = key;
|
||||
} else if (this.map_[key] > index) {
|
||||
--this.map_[key];
|
||||
}
|
||||
}
|
||||
if (keyToDelete) {
|
||||
delete this.map_[keyToDelete];
|
||||
}
|
||||
}
|
||||
var dm = goog.ds.DataManager.getInstance();
|
||||
dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
|
||||
'[' + index + ']');
|
||||
this.listSizeChanged_();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of a named child nodes. This method only works if
|
||||
* this list uses mixed name/indexed lookup, i.e. if its child node have
|
||||
* an 'id' attribute.
|
||||
* @param {string} name Name of child node to determine index of.
|
||||
* @return {number} Index of child node named name.
|
||||
*/
|
||||
goog.ds.FastListNode.prototype.indexOf = function(name) {
|
||||
var index = this.getKeyAsNumber_(name);
|
||||
if (index == null && this.map_) {
|
||||
index = this.map_[name];
|
||||
}
|
||||
if (index == null) {
|
||||
throw Error('Cannot determine index for: ' + name);
|
||||
}
|
||||
return /** @type {number} */(index);
|
||||
};
|
||||
@@ -0,0 +1,460 @@
|
||||
// Copyright 2006 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 implementation of DataNode for wrapping JS data.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.ds.JsDataSource');
|
||||
goog.provide('goog.ds.JsPropertyDataSource');
|
||||
|
||||
goog.require('goog.ds.BaseDataNode');
|
||||
goog.require('goog.ds.BasicNodeList');
|
||||
goog.require('goog.ds.DataManager');
|
||||
goog.require('goog.ds.EmptyNodeList');
|
||||
goog.require('goog.ds.LoadState');
|
||||
|
||||
|
||||
/**
|
||||
* Data source whose backing is JavaScript data
|
||||
*
|
||||
* Names that are reserved for system use and shouldn't be used for data node
|
||||
* names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
|
||||
* undefined if these names are used.
|
||||
*
|
||||
* @param {Object} root The root JS node.
|
||||
* @param {string} dataName The name of this node relative to the parent node.
|
||||
* @param {Object=} opt_parent Optional parent of this JsDataSource.
|
||||
*
|
||||
* implements goog.ds.DataNode.
|
||||
* @constructor
|
||||
* @extends {goog.ds.DataNode}
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available.
|
||||
goog.ds.JsDataSource = function(root, dataName, opt_parent) {
|
||||
this.parent_ = opt_parent;
|
||||
this.dataName_ = dataName;
|
||||
this.setRoot(root);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The root JS object. Can be null.
|
||||
* @type {*}
|
||||
* @protected
|
||||
* @suppress {underscore}
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.root_;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the root JS object
|
||||
* @param {Object} root The root JS object. Can be null.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.setRoot = function(root) {
|
||||
this.root_ = root;
|
||||
this.childNodeList_ = null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set this data source to use list semantics. List data sources:
|
||||
* - Are assumed to have child nodes of all of the same type of data
|
||||
* - Fire data changes on the root node of the list whenever children
|
||||
* are added or removed
|
||||
* @param {?boolean} isList True to use list semantics.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.setIsList_ = function(isList) {
|
||||
this.isList_ = isList;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.JsDataSource.prototype.get = function() {
|
||||
return !goog.isObject(this.root_) ? this.root_ : this.getChildNodes();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the node
|
||||
* @param {*} value The new value of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.set = function(value) {
|
||||
if (value && goog.isObject(this.root_)) {
|
||||
throw Error('Can\'t set group nodes to new values yet');
|
||||
}
|
||||
|
||||
if (this.parent_) {
|
||||
this.parent_.root_[this.dataName_] = value;
|
||||
}
|
||||
this.root_ = value;
|
||||
this.childNodeList_ = null;
|
||||
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO(user) revisit lazy creation.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getChildNodes = function(opt_selector) {
|
||||
if (!this.root_) {
|
||||
return new goog.ds.EmptyNodeList();
|
||||
}
|
||||
|
||||
if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
|
||||
this.createChildNodes_(false);
|
||||
return this.childNodeList_;
|
||||
} else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
|
||||
if (this.root_[opt_selector] != null) {
|
||||
return new goog.ds.BasicNodeList([this.getChildNode(opt_selector)]);
|
||||
} else {
|
||||
return new goog.ds.EmptyNodeList();
|
||||
}
|
||||
} else {
|
||||
throw Error('Selector not supported yet (' + opt_selector + ')');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the DataNodeList with the child nodes for this element.
|
||||
* Allows for only building list as needed.
|
||||
*
|
||||
* @param {boolean=} opt_force Whether to force recreating child nodes,
|
||||
* defaults to false.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.createChildNodes_ = function(opt_force) {
|
||||
if (this.childNodeList_ && !opt_force) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!goog.isObject(this.root_)) {
|
||||
this.childNodeList_ = new goog.ds.EmptyNodeList();
|
||||
return;
|
||||
}
|
||||
|
||||
var childNodeList = new goog.ds.BasicNodeList();
|
||||
var newNode;
|
||||
if (goog.isArray(this.root_)) {
|
||||
var len = this.root_.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
// "id" is reserved node name that will map to a named child node
|
||||
// TODO(user) Configurable logic for choosing id node
|
||||
var node = this.root_[i];
|
||||
var id = node.id;
|
||||
var name = id != null ? String(id) : '[' + i + ']';
|
||||
newNode = new goog.ds.JsDataSource(node, name, this);
|
||||
childNodeList.add(newNode);
|
||||
}
|
||||
} else {
|
||||
for (var name in this.root_) {
|
||||
var obj = this.root_[name];
|
||||
// If the node is already a datasource, then add it.
|
||||
if (obj.getDataName) {
|
||||
childNodeList.add(obj);
|
||||
} else if (!goog.isFunction(obj)) {
|
||||
newNode = new goog.ds.JsDataSource(obj, name, this);
|
||||
childNodeList.add(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.childNodeList_ = childNodeList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node
|
||||
* @param {string} name The node name.
|
||||
* @param {boolean=} opt_canCreate If true, can create child node.
|
||||
* @return {goog.ds.DataNode} The child node, or null if no node of
|
||||
* this name exists.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getChildNode = function(name, opt_canCreate) {
|
||||
if (!this.root_) {
|
||||
return null;
|
||||
}
|
||||
var node = /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
|
||||
if (!node && opt_canCreate) {
|
||||
var newObj = {};
|
||||
if (goog.isArray(this.root_)) {
|
||||
newObj['id'] = name;
|
||||
this.root_.push(newObj);
|
||||
} else {
|
||||
this.root_[name] = newObj;
|
||||
}
|
||||
node = new goog.ds.JsDataSource(newObj, name, this);
|
||||
if (this.childNodeList_) {
|
||||
this.childNodeList_.add(node);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of a child node
|
||||
* @param {string} name The node name.
|
||||
* @return {Object} The value of the node, or null if no value or the child
|
||||
* node doesn't exist.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getChildNodeValue = function(name) {
|
||||
if (this.childNodeList_) {
|
||||
var node = this.getChildNodes().get(name);
|
||||
return node ? node.get() : null;
|
||||
} else if (this.root_) {
|
||||
return this.root_[name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets a named child node of the current node.
|
||||
* If value is null, removes the child node.
|
||||
* @param {string} name The node name.
|
||||
* @param {Object} value The value to set, can be DataNode, object,
|
||||
* property, or null.
|
||||
* @return {Object} The child node, if set.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.setChildNode = function(name, value) {
|
||||
var removedPath = null;
|
||||
var node = null;
|
||||
var addedNode = false;
|
||||
|
||||
// Set node to the DataNode to add - if the value isn't already a DataNode,
|
||||
// creates a JsDataSource or JsPropertyDataSource wrapper
|
||||
if (value != null) {
|
||||
if (value.getDataName) {
|
||||
// The value is a DataNode. We must update its parent.
|
||||
node = value;
|
||||
node.parent_ = this;
|
||||
} else {
|
||||
if (goog.isArray(value) || goog.isObject(value)) {
|
||||
node = new goog.ds.JsDataSource(value, name, this);
|
||||
} else {
|
||||
node = new goog.ds.JsPropertyDataSource(
|
||||
/** @type {goog.ds.DataNode} */ (this.root_), name, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This logic will get cleaner once we can remove the backing array / object
|
||||
// and just rely on the childNodeList_. This is needed until dependent code
|
||||
// is cleaned up.
|
||||
// TODO(user) Remove backing array / object and just use childNodeList_
|
||||
|
||||
if (goog.isArray(this.root_)) {
|
||||
// To remove by name, need to create a map of the child nodes by ID
|
||||
this.createChildNodes_();
|
||||
var index = this.childNodeList_.indexOf(name);
|
||||
if (value == null) {
|
||||
// Remove the node
|
||||
var nodeToRemove = this.childNodeList_.get(name);
|
||||
if (nodeToRemove) {
|
||||
removedPath = nodeToRemove.getDataPath();
|
||||
}
|
||||
this.root_.splice(index, 1);
|
||||
} else {
|
||||
// Add the node
|
||||
if (index) {
|
||||
this.root_[index] = value;
|
||||
} else {
|
||||
this.root_.push(value);
|
||||
}
|
||||
}
|
||||
if (index == null) {
|
||||
addedNode = true;
|
||||
}
|
||||
this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
|
||||
} else if (goog.isObject(this.root_)) {
|
||||
if (value == null) {
|
||||
// Remove the node
|
||||
this.createChildNodes_();
|
||||
var nodeToRemove = this.childNodeList_.get(name);
|
||||
if (nodeToRemove) {
|
||||
removedPath = nodeToRemove.getDataPath();
|
||||
}
|
||||
delete this.root_[name];
|
||||
} else {
|
||||
// Add the node
|
||||
if (!this.root_[name]) {
|
||||
addedNode = true;
|
||||
}
|
||||
this.root_[name] = value;
|
||||
}
|
||||
// Only need to update childNodeList_ if has been created already
|
||||
if (this.childNodeList_) {
|
||||
this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
|
||||
}
|
||||
}
|
||||
|
||||
// Fire the event that the node changed
|
||||
var dm = goog.ds.DataManager.getInstance();
|
||||
if (node) {
|
||||
dm.fireDataChange(node.getDataPath());
|
||||
if (addedNode && this.isList()) {
|
||||
dm.fireDataChange(this.getDataPath());
|
||||
dm.fireDataChange(this.getDataPath() + '/count()');
|
||||
}
|
||||
} else if (removedPath) {
|
||||
dm.fireDataChange(removedPath);
|
||||
if (this.isList()) {
|
||||
dm.fireDataChange(this.getDataPath());
|
||||
dm.fireDataChange(this.getDataPath() + '/count()');
|
||||
}
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getDataName = function() {
|
||||
return this.dataName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setthe name of the node relative to the parent node
|
||||
* @param {string} dataName The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.setDataName = function(dataName) {
|
||||
this.dataName_ = dataName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the a qualified data path to this node
|
||||
* @return {string} The data path.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getDataPath = function() {
|
||||
var parentPath = '';
|
||||
if (this.parent_) {
|
||||
parentPath = this.parent_.getDataPath() + goog.ds.STR_PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
return parentPath + this.dataName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.load = function() {
|
||||
// Nothing to do
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* TODO(user) Discuss null value handling
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.getLoadState = function() {
|
||||
return (this.root_ == null) ? goog.ds.LoadState.NOT_LOADED :
|
||||
goog.ds.LoadState.LOADED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the value of this node is a homogeneous list of data
|
||||
* @return {boolean} True if a list.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsDataSource.prototype.isList = function() {
|
||||
return this.isList_ != null ? this.isList_ : goog.isArray(this.root_);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data source for JavaScript properties that arent objects. Contains reference
|
||||
* to parent object so that you can set the vaule
|
||||
*
|
||||
* @param {goog.ds.DataNode} parent Parent object.
|
||||
* @param {string} dataName Name of this property.
|
||||
* @param {goog.ds.DataNode=} opt_parentDataNode The parent data node. If
|
||||
* omitted, assumes that the parent object is the parent data node.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.ds.BaseDataNode}
|
||||
*/
|
||||
goog.ds.JsPropertyDataSource = function(parent, dataName, opt_parentDataNode) {
|
||||
goog.ds.BaseDataNode.call(this);
|
||||
this.dataName_ = dataName;
|
||||
this.parent_ = parent;
|
||||
this.parentDataNode_ = opt_parentDataNode || this.parent_;
|
||||
};
|
||||
goog.inherits(goog.ds.JsPropertyDataSource, goog.ds.BaseDataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the node
|
||||
* @return {Object} The value of the node, or null if no value.
|
||||
*/
|
||||
goog.ds.JsPropertyDataSource.prototype.get = function() {
|
||||
return this.parent_[this.dataName_];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the node
|
||||
* @param {Object} value The new value of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsPropertyDataSource.prototype.set = function(value) {
|
||||
var oldValue = this.parent_[this.dataName_];
|
||||
this.parent_[this.dataName_] = value;
|
||||
|
||||
if (oldValue != value) {
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsPropertyDataSource.prototype.getDataName = function() {
|
||||
return this.dataName_;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.JsPropertyDataSource.prototype.getParent = function() {
|
||||
return this.parentDataNode_;
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright 2006 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 Implementation of DataNode for wrapping JSON data.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.ds.JsonDataSource');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.ds.DataManager');
|
||||
goog.require('goog.ds.JsDataSource');
|
||||
goog.require('goog.ds.LoadState');
|
||||
goog.require('goog.ds.logger');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data source whose backing is a JSON-like service, in which
|
||||
* retreiving the resource specified by URL with the additional parameter
|
||||
* callback. The resource retreived is executable JavaScript that
|
||||
* makes a call to the named function with a JavaScript object literal
|
||||
* as the only parameter.
|
||||
*
|
||||
* Example URI could be:
|
||||
* http://www.google.com/data/search?q=monkey&callback=mycb
|
||||
* which might return the JS:
|
||||
* mycb({searchresults:
|
||||
* [{uri: 'http://www.monkey.com', title: 'Site About Monkeys'}]});
|
||||
*
|
||||
* TODO(user): Evaluate using goog.net.Jsonp here.
|
||||
*
|
||||
* A URI of an empty string will mean that no request is made
|
||||
* and the data source will be a data source with no child nodes
|
||||
*
|
||||
* @param {string|goog.Uri} uri URI for the request.
|
||||
* @param {string} name Name of the datasource.
|
||||
* @param {string=} opt_callbackParamName The parameter name that is used to
|
||||
* specify the callback. Defaults to 'callback'.
|
||||
*
|
||||
* @extends {goog.ds.JsDataSource}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.JsonDataSource = function(uri, name, opt_callbackParamName) {
|
||||
goog.ds.JsDataSource.call(this, null, name, null);
|
||||
if (uri) {
|
||||
this.uri_ = new goog.Uri(uri);
|
||||
} else {
|
||||
this.uri_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the callback parameter name that is added to the uri.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.callbackParamName_ = opt_callbackParamName || 'callback';
|
||||
|
||||
};
|
||||
goog.inherits(goog.ds.JsonDataSource, goog.ds.JsDataSource);
|
||||
|
||||
|
||||
/**
|
||||
* Default load state is NOT_LOADED
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsonDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
|
||||
|
||||
|
||||
/**
|
||||
* Map of all data sources, needed for callbacks
|
||||
* Doesn't work unless dataSources is exported (not renamed)
|
||||
*/
|
||||
goog.ds.JsonDataSource['dataSources'] = {};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node.
|
||||
* Fires the JsonDataSource
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsonDataSource.prototype.load = function() {
|
||||
if (this.uri_) {
|
||||
// NOTE: "dataSources" is expose above by name so that it will not be
|
||||
// renamed. It should therefore be accessed via array notation here so
|
||||
// that it also doesn't get renamed and stops the compiler from complaining
|
||||
goog.ds.JsonDataSource['dataSources'][this.dataName_] = this;
|
||||
goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
|
||||
this.getDataName() + ' to ' + this.uri_);
|
||||
|
||||
this.loadState_ = goog.ds.LoadState.LOADING;
|
||||
|
||||
var uriToCall = new goog.Uri(this.uri_);
|
||||
uriToCall.setParameterValue(this.callbackParamName_,
|
||||
'JsonReceive.' + this.dataName_);
|
||||
|
||||
goog.global['JsonReceive'][this.dataName_] =
|
||||
goog.bind(this.receiveData, this);
|
||||
|
||||
var scriptEl = goog.dom.createDom('script', {'src': uriToCall});
|
||||
goog.dom.getElementsByTagNameAndClass('head')[0].appendChild(scriptEl);
|
||||
} else {
|
||||
this.root_ = {};
|
||||
this.loadState_ = goog.ds.LoadState.NOT_LOADED;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsonDataSource.prototype.getLoadState = function() {
|
||||
return this.loadState_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receives data from a Json request
|
||||
* @param {Object} obj The JSON data.
|
||||
*/
|
||||
goog.ds.JsonDataSource.prototype.receiveData = function(obj) {
|
||||
this.setRoot(obj);
|
||||
this.loadState_ = goog.ds.LoadState.LOADED;
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Temp variable to hold callbacks
|
||||
* until BUILD supports multiple externs.js files
|
||||
*/
|
||||
goog.global['JsonReceive'] = {};
|
||||
@@ -0,0 +1,195 @@
|
||||
// Copyright 2006 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
|
||||
* DataSource implementation that uses XMLHttpRequest as transport, with
|
||||
* response as serialized JS object (not required to be JSON) that can
|
||||
* be evaluated and set to a variable.
|
||||
*
|
||||
* Response can have unexecutable starting/ending text to prevent inclusion
|
||||
* using <script src="...">
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.ds.JsXmlHttpDataSource');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.ds.DataManager');
|
||||
goog.require('goog.ds.FastDataNode');
|
||||
goog.require('goog.ds.LoadState');
|
||||
goog.require('goog.ds.logger');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.net.EventType');
|
||||
goog.require('goog.net.XhrIo');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Similar to JsonDataSource, with using XMLHttpRequest for transport
|
||||
* Currently requires the result be a JS object that can be evaluated and
|
||||
* set to a variable and doesn't require strict JSON notation.
|
||||
*
|
||||
* @param {string || goog.Uri} uri URI for the request.
|
||||
* @param {string} name Name of the datasource.
|
||||
* @param {string=} opt_startText Text to expect/strip before JS response.
|
||||
* @param {string=} opt_endText Text to expect/strip after JS response.
|
||||
* @param {boolean=} opt_usePost If true, use POST. Defaults to false (GET).
|
||||
*
|
||||
* @extends {goog.ds.FastDataNode}
|
||||
* @constructor
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource = function(uri, name, opt_startText, opt_endText,
|
||||
opt_usePost) {
|
||||
goog.ds.FastDataNode.call(this, {}, name, null);
|
||||
if (uri) {
|
||||
this.uri_ = new goog.Uri(uri);
|
||||
this.xhr_ = new goog.net.XhrIo();
|
||||
this.usePost_ = !!opt_usePost;
|
||||
|
||||
goog.events.listen(this.xhr_, goog.net.EventType.COMPLETE,
|
||||
this.completed_, false, this);
|
||||
} else {
|
||||
this.uri_ = null;
|
||||
}
|
||||
this.startText_ = opt_startText;
|
||||
this.endText_ = opt_endText;
|
||||
};
|
||||
goog.inherits(goog.ds.JsXmlHttpDataSource, goog.ds.FastDataNode);
|
||||
|
||||
|
||||
/**
|
||||
* Delimiter for start of JSON data in response.
|
||||
* null = starts at first character of response
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.startText_;
|
||||
|
||||
|
||||
/**
|
||||
* Delimiter for end of JSON data in response.
|
||||
* null = ends at last character of response
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.endText_;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.getLoadState = function() {
|
||||
return this.loadState_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the request data. This can be used if it is required to
|
||||
* send a specific body rather than build the body from the query
|
||||
* parameters. Only used in POST requests.
|
||||
* @param {string} data The data to send in the request body.
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.setQueryData = function(data) {
|
||||
this.queryData_ = data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node.
|
||||
* Fires the JsonDataSource
|
||||
* @override
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.load = function() {
|
||||
goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
|
||||
this.getDataName() + ' to ' + this.uri_);
|
||||
|
||||
if (this.uri_) {
|
||||
if (this.usePost_) {
|
||||
|
||||
var queryData;
|
||||
if (!this.queryData_) {
|
||||
queryData = this.uri_.getQueryData().toString();
|
||||
} else {
|
||||
queryData = this.queryData_;
|
||||
}
|
||||
|
||||
var uriNoQuery = this.uri_.clone();
|
||||
uriNoQuery.setQueryData(null);
|
||||
this.xhr_.send(String(uriNoQuery), 'POST', queryData);
|
||||
} else {
|
||||
this.xhr_.send(String(this.uri_));
|
||||
}
|
||||
} else {
|
||||
this.loadState_ = goog.ds.LoadState.NOT_LOADED;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called on successful request.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.success_ = function() {
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Completed callback. Loads data if successful, otherwise sets
|
||||
* state to FAILED
|
||||
* @param {goog.events.Event} e Event object, Xhr is target.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.JsXmlHttpDataSource.prototype.completed_ = function(e) {
|
||||
if (this.xhr_.isSuccess()) {
|
||||
goog.log.info(goog.ds.logger,
|
||||
'Got data for DataSource ' + this.getDataName());
|
||||
var text = this.xhr_.getResponseText();
|
||||
|
||||
// Look for start and end token and trim text
|
||||
if (this.startText_) {
|
||||
var startpos = text.indexOf(this.startText_);
|
||||
text = text.substring(startpos + this.startText_.length);
|
||||
}
|
||||
if (this.endText_) {
|
||||
var endpos = text.lastIndexOf(this.endText_);
|
||||
text = text.substring(0, endpos);
|
||||
}
|
||||
|
||||
// Eval result
|
||||
/** @preserveTry */
|
||||
try {
|
||||
var jsonObj = /** @type {Object} */ (eval('[' + text + '][0]'));
|
||||
this.extendWith(jsonObj);
|
||||
this.loadState_ = goog.ds.LoadState.LOADED;
|
||||
}
|
||||
catch (ex) {
|
||||
// Invalid JS
|
||||
this.loadState_ = goog.ds.LoadState.FAILED;
|
||||
goog.log.error(goog.ds.logger, 'Failed to parse data: ' + ex.message);
|
||||
}
|
||||
|
||||
// Call on a timer to avoid threading issues on IE.
|
||||
goog.global.setTimeout(goog.bind(this.success_, this), 0);
|
||||
} else {
|
||||
goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
|
||||
this.getDataName());
|
||||
this.loadState_ = goog.ds.LoadState.FAILED;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,415 @@
|
||||
// Copyright 2006 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
|
||||
* Implementations of DataNode for wrapping XML data.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.ds.XmlDataSource');
|
||||
goog.provide('goog.ds.XmlHttpDataSource');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.dom.xml');
|
||||
goog.require('goog.ds.BasicNodeList');
|
||||
goog.require('goog.ds.DataManager');
|
||||
goog.require('goog.ds.LoadState');
|
||||
goog.require('goog.ds.logger');
|
||||
goog.require('goog.net.XhrIo');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data source whose backing is an xml node
|
||||
*
|
||||
* @param {Node} node The XML node. Can be null.
|
||||
* @param {goog.ds.XmlDataSource} parent Parent of XML element. Can be null.
|
||||
* @param {string=} opt_name The name of this node relative to the parent node.
|
||||
*
|
||||
* @extends {goog.ds.DataNode}
|
||||
* @constructor
|
||||
*/
|
||||
// TODO(arv): Use interfaces when available.
|
||||
goog.ds.XmlDataSource = function(node, parent, opt_name) {
|
||||
this.parent_ = parent;
|
||||
this.dataName_ = opt_name || (node ? node.nodeName : '');
|
||||
this.setNode_(node);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constant to select XML attributes for getChildNodes
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_ = '@*';
|
||||
|
||||
|
||||
/**
|
||||
* Set the current root nodeof the data source.
|
||||
* Can be an attribute node, text node, or element node
|
||||
* @param {Node} node The node. Can be null.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.setNode_ = function(node) {
|
||||
this.node_ = node;
|
||||
if (node != null) {
|
||||
switch (node.nodeType) {
|
||||
case goog.dom.NodeType.ATTRIBUTE:
|
||||
case goog.dom.NodeType.TEXT:
|
||||
this.value_ = node.nodeValue;
|
||||
break;
|
||||
case goog.dom.NodeType.ELEMENT:
|
||||
if (node.childNodes.length == 1 &&
|
||||
node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
|
||||
this.value_ = node.firstChild.nodeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the DataNodeList with the child nodes for this element.
|
||||
* Allows for only building list as needed.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.createChildNodes_ = function() {
|
||||
if (this.childNodeList_) {
|
||||
return;
|
||||
}
|
||||
var childNodeList = new goog.ds.BasicNodeList();
|
||||
if (this.node_ != null) {
|
||||
var childNodes = this.node_.childNodes;
|
||||
for (var i = 0, childNode; childNode = childNodes[i]; i++) {
|
||||
if (childNode.nodeType != goog.dom.NodeType.TEXT ||
|
||||
!goog.ds.XmlDataSource.isEmptyTextNodeValue_(childNode.nodeValue)) {
|
||||
var newNode = new goog.ds.XmlDataSource(childNode,
|
||||
this, childNode.nodeName);
|
||||
childNodeList.add(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.childNodeList_ = childNodeList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the DataNodeList with the attributes for the element
|
||||
* Allows for only building list as needed.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.createAttributes_ = function() {
|
||||
if (this.attributes_) {
|
||||
return;
|
||||
}
|
||||
var attributes = new goog.ds.BasicNodeList();
|
||||
if (this.node_ != null && this.node_.attributes != null) {
|
||||
var atts = this.node_.attributes;
|
||||
for (var i = 0, att; att = atts[i]; i++) {
|
||||
var newNode = new goog.ds.XmlDataSource(att, this, att.nodeName);
|
||||
attributes.add(newNode);
|
||||
}
|
||||
}
|
||||
this.attributes_ = attributes;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the node
|
||||
* @return {Object} The value of the node, or null if no value.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.get = function() {
|
||||
this.createChildNodes_();
|
||||
return this.value_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the node
|
||||
* @param {*} value The new value of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.set = function(value) {
|
||||
throw Error('Can\'t set on XmlDataSource yet');
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ds.XmlDataSource.prototype.getChildNodes = function(opt_selector) {
|
||||
if (opt_selector && opt_selector ==
|
||||
goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_) {
|
||||
this.createAttributes_();
|
||||
return this.attributes_;
|
||||
} else if (opt_selector == null ||
|
||||
opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
|
||||
this.createChildNodes_();
|
||||
return this.childNodeList_;
|
||||
} else {
|
||||
throw Error('Unsupported selector');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a named child node of the current node
|
||||
* @param {string} name The node name.
|
||||
* @return {goog.ds.DataNode} The child node, or null if
|
||||
* no node of this name exists.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.getChildNode = function(name) {
|
||||
if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
|
||||
var att = this.node_.getAttributeNode(name.substring(1));
|
||||
return att ? new goog.ds.XmlDataSource(att, this) : null;
|
||||
} else {
|
||||
return /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of a child node
|
||||
* @param {string} name The node name.
|
||||
* @return {*} The value of the node, or null if no value or the child node
|
||||
* doesn't exist.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.getChildNodeValue = function(name) {
|
||||
if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
|
||||
var node = this.node_.getAttributeNode(name.substring(1));
|
||||
return node ? node.nodeValue : null;
|
||||
} else {
|
||||
var node = this.getChildNode(name);
|
||||
return node ? node.get() : null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the node relative to the parent node
|
||||
* @return {string} The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.getDataName = function() {
|
||||
return this.dataName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setthe name of the node relative to the parent node
|
||||
* @param {string} name The name of the node.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.setDataName = function(name) {
|
||||
this.dataName_ = name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the a qualified data path to this node
|
||||
* @return {string} The data path.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.getDataPath = function() {
|
||||
var parentPath = '';
|
||||
if (this.parent_) {
|
||||
parentPath = this.parent_.getDataPath() +
|
||||
(this.dataName_.indexOf(goog.ds.STR_ARRAY_START) != -1 ? '' :
|
||||
goog.ds.STR_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
return parentPath + this.dataName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.load = function() {
|
||||
// Nothing to do
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlDataSource.prototype.getLoadState = function() {
|
||||
return this.node_ ? goog.ds.LoadState.LOADED : goog.ds.LoadState.NOT_LOADED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether a node is an empty text node. Nodes consisting of only white
|
||||
* space (#x20, #xD, #xA, #x9) can generally be collapsed to a zero length
|
||||
* text string.
|
||||
* @param {string} str String to match.
|
||||
* @return {boolean} True if string equates to empty text node.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.isEmptyTextNodeValue_ = function(str) {
|
||||
return /^[\r\n\t ]*$/.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an XML document with one empty node.
|
||||
* Useful for places where you need a node that
|
||||
* can be queried against.
|
||||
*
|
||||
* @return {Document} Document with one empty node.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlDataSource.createChildlessDocument_ = function() {
|
||||
return goog.dom.xml.createDocument('nothing');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data source whose backing is an XMLHttpRequest,
|
||||
*
|
||||
* A URI of an empty string will mean that no request is made
|
||||
* and the data source will be a single, empty node.
|
||||
*
|
||||
* @param {(string,goog.Uri)} uri URL of the XMLHttpRequest.
|
||||
* @param {string} name Name of the datasource.
|
||||
*
|
||||
* implements goog.ds.XmlHttpDataSource.
|
||||
* @constructor
|
||||
* @extends {goog.ds.XmlDataSource}
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource = function(uri, name) {
|
||||
goog.ds.XmlDataSource.call(this, null, null, name);
|
||||
if (uri) {
|
||||
this.uri_ = new goog.Uri(uri);
|
||||
} else {
|
||||
this.uri_ = null;
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.ds.XmlHttpDataSource, goog.ds.XmlDataSource);
|
||||
|
||||
|
||||
/**
|
||||
* Default load state is NOT_LOADED
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
|
||||
|
||||
|
||||
/**
|
||||
* Load or reload the backing data for this node.
|
||||
* Fires the XMLHttpRequest
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.load = function() {
|
||||
if (this.uri_) {
|
||||
goog.log.info(goog.ds.logger, 'Sending XML request for DataSource ' +
|
||||
this.getDataName() + ' to ' + this.uri_);
|
||||
this.loadState_ = goog.ds.LoadState.LOADING;
|
||||
|
||||
goog.net.XhrIo.send(this.uri_, goog.bind(this.complete_, this));
|
||||
} else {
|
||||
this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
|
||||
this.loadState_ = goog.ds.LoadState.NOT_LOADED;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the state of the backing data for this node
|
||||
* @return {goog.ds.LoadState} The state.
|
||||
* @override
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.getLoadState = function() {
|
||||
return this.loadState_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the completion of an XhrIo request. Dispatches to success or load
|
||||
* based on the result.
|
||||
* @param {!goog.events.Event} e The XhrIo event object.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.complete_ = function(e) {
|
||||
var xhr = /** @type {goog.net.XhrIo} */ (e.target);
|
||||
if (xhr && xhr.isSuccess()) {
|
||||
this.success_(xhr);
|
||||
} else {
|
||||
this.failure_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Success result. Checks whether valid XML was returned
|
||||
* and sets the XML and loadstate.
|
||||
*
|
||||
* @param {!goog.net.XhrIo} xhr The successful XhrIo object.
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.success_ = function(xhr) {
|
||||
goog.log.info(goog.ds.logger,
|
||||
'Got data for DataSource ' + this.getDataName());
|
||||
var xml = xhr.getResponseXml();
|
||||
|
||||
// Fix for case where IE returns valid XML as text but
|
||||
// doesn't parse by default
|
||||
if (xml && !xml.hasChildNodes() &&
|
||||
goog.isObject(xhr.getResponseText())) {
|
||||
xml = goog.dom.xml.loadXml(xhr.getResponseText());
|
||||
}
|
||||
// Failure result
|
||||
if (!xml || !xml.hasChildNodes()) {
|
||||
this.loadState_ = goog.ds.LoadState.FAILED;
|
||||
this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
|
||||
} else {
|
||||
this.loadState_ = goog.ds.LoadState.LOADED;
|
||||
this.node_ = xml.documentElement;
|
||||
}
|
||||
|
||||
if (this.getDataName()) {
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Failure result
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.ds.XmlHttpDataSource.prototype.failure_ = function() {
|
||||
goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
|
||||
this.getDataName());
|
||||
|
||||
this.loadState_ = goog.ds.LoadState.FAILED;
|
||||
this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
|
||||
|
||||
if (this.getDataName()) {
|
||||
goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
|
||||
}
|
||||
};
|
||||
1718
float-no-zero/closure-library/closure/goog/date/date.js
Normal file
1718
float-no-zero/closure-library/closure/goog/date/date.js
Normal file
File diff suppressed because it is too large
Load Diff
27
float-no-zero/closure-library/closure/goog/date/datelike.js
Normal file
27
float-no-zero/closure-library/closure/goog/date/datelike.js
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2010 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 Typedefs for working with dates.
|
||||
*
|
||||
* @author nicksantos@google.com (Nick Santos)
|
||||
*/
|
||||
|
||||
goog.provide('goog.date.DateLike');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {(Date|goog.date.Date)}
|
||||
*/
|
||||
goog.date.DateLike;
|
||||
413
float-no-zero/closure-library/closure/goog/date/daterange.js
Normal file
413
float-no-zero/closure-library/closure/goog/date/daterange.js
Normal file
@@ -0,0 +1,413 @@
|
||||
// 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 Date range data structure. Based loosely on
|
||||
* com.google.common.util.DateRange.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.date.DateRange');
|
||||
goog.provide('goog.date.DateRange.Iterator');
|
||||
goog.provide('goog.date.DateRange.StandardDateRangeKeys');
|
||||
|
||||
goog.require('goog.date.Date');
|
||||
goog.require('goog.date.Interval');
|
||||
goog.require('goog.iter.Iterator');
|
||||
goog.require('goog.iter.StopIteration');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a date range.
|
||||
* @constructor
|
||||
* @param {goog.date.Date} startDate The first date in the range.
|
||||
* @param {goog.date.Date} endDate The last date in the range.
|
||||
*/
|
||||
goog.date.DateRange = function(startDate, endDate) {
|
||||
/**
|
||||
* The first date in the range.
|
||||
* @type {goog.date.Date}
|
||||
* @private
|
||||
*/
|
||||
this.startDate_ = startDate;
|
||||
|
||||
/**
|
||||
* The last date in the range.
|
||||
* @type {goog.date.Date}
|
||||
* @private
|
||||
*/
|
||||
this.endDate_ = endDate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The first possible day, as far as this class is concerned.
|
||||
* @type {goog.date.Date}
|
||||
*/
|
||||
goog.date.DateRange.MINIMUM_DATE = new goog.date.Date(0000, 0, 1);
|
||||
|
||||
|
||||
/**
|
||||
* The last possible day, as far as this class is concerned.
|
||||
* @type {goog.date.Date}
|
||||
*/
|
||||
goog.date.DateRange.MAXIMUM_DATE = new goog.date.Date(9999, 11, 31);
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.date.Date} The first date in the range.
|
||||
*/
|
||||
goog.date.DateRange.prototype.getStartDate = function() {
|
||||
return this.startDate_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.date.Date} The last date in the range.
|
||||
*/
|
||||
goog.date.DateRange.prototype.getEndDate = function() {
|
||||
return this.endDate_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.iter.Iterator} An iterator over the date range.
|
||||
*/
|
||||
goog.date.DateRange.prototype.iterator = function() {
|
||||
return new goog.date.DateRange.Iterator(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests two {@link goog.date.DateRange} objects for equality.
|
||||
* @param {goog.date.DateRange} a A date range.
|
||||
* @param {goog.date.DateRange} b A date range.
|
||||
* @return {boolean} Whether |a| is the same range as |b|.
|
||||
*/
|
||||
goog.date.DateRange.equals = function(a, b) {
|
||||
// Test for same object reference; type conversion is irrelevant.
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return a.startDate_.equals(b.startDate_) && a.endDate_.equals(b.endDate_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates a date that is a number of days after a date. Does not modify its
|
||||
* input.
|
||||
* @param {goog.date.Date} date The input date.
|
||||
* @param {number} offset Number of days.
|
||||
* @return {goog.date.Date} The date that is |offset| days after |date|.
|
||||
* @private
|
||||
*/
|
||||
goog.date.DateRange.offsetInDays_ = function(date, offset) {
|
||||
var newDate = date.clone();
|
||||
newDate.add(new goog.date.Interval(goog.date.Interval.DAYS, offset));
|
||||
return newDate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Monday before a date. If the input is a Monday, returns the
|
||||
* input. Does not modify its input.
|
||||
* @param {goog.date.Date} date The input date.
|
||||
* @return {goog.date.Date} If |date| is a Monday, return |date|; otherwise
|
||||
* return the Monday before |date|.
|
||||
* @private
|
||||
*/
|
||||
goog.date.DateRange.currentOrLastMonday_ = function(date) {
|
||||
var newDate = date.clone();
|
||||
newDate.add(new goog.date.Interval(goog.date.Interval.DAYS,
|
||||
-newDate.getIsoWeekday()));
|
||||
return newDate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates a date that is a number of months after the first day in the
|
||||
* month that contains its input. Does not modify its input.
|
||||
* @param {goog.date.Date} date The input date.
|
||||
* @param {number} offset Number of months.
|
||||
* @return {goog.date.Date} The date that is |offset| months after the first
|
||||
* day in the month that contains |date|.
|
||||
* @private
|
||||
*/
|
||||
goog.date.DateRange.offsetInMonths_ = function(date, offset) {
|
||||
var newDate = date.clone();
|
||||
newDate.setDate(1);
|
||||
newDate.add(new goog.date.Interval(goog.date.Interval.MONTHS, offset));
|
||||
return newDate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range from yesterday to yesterday.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that includes only yesterday.
|
||||
*/
|
||||
goog.date.DateRange.yesterday = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
var yesterday = goog.date.DateRange.offsetInDays_(today, -1);
|
||||
return new goog.date.DateRange(yesterday, yesterday);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range from today to today.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that includes only today.
|
||||
*/
|
||||
goog.date.DateRange.today = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
return new goog.date.DateRange(today, today);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range that includes the seven days that end yesterday.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that includes the seven days that
|
||||
* end yesterday.
|
||||
*/
|
||||
goog.date.DateRange.last7Days = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
var yesterday = goog.date.DateRange.offsetInDays_(today, -1);
|
||||
return new goog.date.DateRange(goog.date.DateRange.offsetInDays_(today, -7),
|
||||
yesterday);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range that starts the first of this month and ends the last day
|
||||
* of this month.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that starts the first of this month
|
||||
* and ends the last day of this month.
|
||||
*/
|
||||
goog.date.DateRange.thisMonth = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
return new goog.date.DateRange(
|
||||
goog.date.DateRange.offsetInMonths_(today, 0),
|
||||
goog.date.DateRange.offsetInDays_(
|
||||
goog.date.DateRange.offsetInMonths_(today, 1),
|
||||
-1));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range that starts the first of last month and ends the last day
|
||||
* of last month.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that starts the first of last month
|
||||
* and ends the last day of last month.
|
||||
*/
|
||||
goog.date.DateRange.lastMonth = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
return new goog.date.DateRange(
|
||||
goog.date.DateRange.offsetInMonths_(today, -1),
|
||||
goog.date.DateRange.offsetInDays_(
|
||||
goog.date.DateRange.offsetInMonths_(today, 0),
|
||||
-1));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the seven-day range that starts on the first day of the week
|
||||
* (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) on or before today.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that starts the Monday on or before
|
||||
* today and ends the Sunday on or after today.
|
||||
*/
|
||||
goog.date.DateRange.thisWeek = function(opt_today) {
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
var iso = today.getIsoWeekday();
|
||||
var firstDay = today.getFirstDayOfWeek();
|
||||
var i18nFirstDay = (iso >= firstDay) ? iso - firstDay : iso + (7 - firstDay);
|
||||
var start = goog.date.DateRange.offsetInDays_(today, -i18nFirstDay);
|
||||
var end = goog.date.DateRange.offsetInDays_(start, 6);
|
||||
return new goog.date.DateRange(start, end);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the seven-day range that ends the day before the first day of
|
||||
* the week (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) that
|
||||
* contains today.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that starts seven days before the
|
||||
* Monday on or before today and ends the Sunday on or before yesterday.
|
||||
*/
|
||||
goog.date.DateRange.lastWeek = function(opt_today) {
|
||||
var thisWeek = goog.date.DateRange.thisWeek(opt_today);
|
||||
var start = goog.date.DateRange.offsetInDays_(thisWeek.getStartDate(), -7);
|
||||
var end = goog.date.DateRange.offsetInDays_(thisWeek.getEndDate(), -7);
|
||||
return new goog.date.DateRange(start, end);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range that starts seven days before the Monday on or before
|
||||
* today and ends the Friday before today.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that starts seven days before the
|
||||
* Monday on or before today and ends the Friday before today.
|
||||
*/
|
||||
goog.date.DateRange.lastBusinessWeek = function(opt_today) {
|
||||
// TODO(user): should be i18nized.
|
||||
var today = goog.date.DateRange.cloneOrCreate_(opt_today);
|
||||
var start = goog.date.DateRange.offsetInDays_(today,
|
||||
- 7 - today.getIsoWeekday());
|
||||
var end = goog.date.DateRange.offsetInDays_(start, 4);
|
||||
return new goog.date.DateRange(start, end);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the range that includes all days between January 1, 1900 and
|
||||
* December 31, 9999.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The range that includes all days between
|
||||
* January 1, 1900 and December 31, 9999.
|
||||
*/
|
||||
goog.date.DateRange.allTime = function(opt_today) {
|
||||
return new goog.date.DateRange(
|
||||
goog.date.DateRange.MINIMUM_DATE,
|
||||
goog.date.DateRange.MAXIMUM_DATE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Standard date range keys. Equivalent to the enum IDs in
|
||||
* DateRange.java http://go/datarange.java
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.date.DateRange.StandardDateRangeKeys = {
|
||||
YESTERDAY: 'yesterday',
|
||||
TODAY: 'today',
|
||||
LAST_7_DAYS: 'last7days',
|
||||
THIS_MONTH: 'thismonth',
|
||||
LAST_MONTH: 'lastmonth',
|
||||
THIS_WEEK: 'thisweek',
|
||||
LAST_WEEK: 'lastweek',
|
||||
LAST_BUSINESS_WEEK: 'lastbusinessweek',
|
||||
ALL_TIME: 'alltime'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} dateRangeKey A standard date range key.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {goog.date.DateRange} The date range that corresponds to that key.
|
||||
* @throws {Error} If no standard date range with that key exists.
|
||||
*/
|
||||
goog.date.DateRange.standardDateRange = function(dateRangeKey, opt_today) {
|
||||
switch (dateRangeKey) {
|
||||
case goog.date.DateRange.StandardDateRangeKeys.YESTERDAY:
|
||||
return goog.date.DateRange.yesterday(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.TODAY:
|
||||
return goog.date.DateRange.today(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.LAST_7_DAYS:
|
||||
return goog.date.DateRange.last7Days(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.THIS_MONTH:
|
||||
return goog.date.DateRange.thisMonth(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.LAST_MONTH:
|
||||
return goog.date.DateRange.lastMonth(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.THIS_WEEK:
|
||||
return goog.date.DateRange.thisWeek(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.LAST_WEEK:
|
||||
return goog.date.DateRange.lastWeek(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.LAST_BUSINESS_WEEK:
|
||||
return goog.date.DateRange.lastBusinessWeek(opt_today);
|
||||
|
||||
case goog.date.DateRange.StandardDateRangeKeys.ALL_TIME:
|
||||
return goog.date.DateRange.allTime(opt_today);
|
||||
|
||||
default:
|
||||
throw Error('no such date range key: ' + dateRangeKey);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clones or creates new.
|
||||
* @param {goog.date.Date=} opt_today The date to consider today.
|
||||
* Defaults to today.
|
||||
* @return {!goog.date.Date} cloned or new.
|
||||
* @private
|
||||
*/
|
||||
goog.date.DateRange.cloneOrCreate_ = function(opt_today) {
|
||||
return opt_today ? opt_today.clone() : new goog.date.Date();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an iterator over the dates in a {@link goog.date.DateRange}.
|
||||
* @constructor
|
||||
* @extends {goog.iter.Iterator}
|
||||
* @param {goog.date.DateRange} dateRange The date range to iterate.
|
||||
*/
|
||||
goog.date.DateRange.Iterator = function(dateRange) {
|
||||
/**
|
||||
* The next date.
|
||||
* @type {goog.date.Date}
|
||||
* @private
|
||||
*/
|
||||
this.nextDate_ = dateRange.getStartDate().clone();
|
||||
|
||||
/**
|
||||
* The end date, expressed as an integer: YYYYMMDD.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.endDate_ = Number(dateRange.getEndDate().toIsoString());
|
||||
};
|
||||
goog.inherits(goog.date.DateRange.Iterator, goog.iter.Iterator);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.DateRange.Iterator.prototype.next = function() {
|
||||
if (Number(this.nextDate_.toIsoString()) > this.endDate_) {
|
||||
throw goog.iter.StopIteration;
|
||||
}
|
||||
|
||||
var rv = this.nextDate_.clone();
|
||||
this.nextDate_.add(new goog.date.Interval(goog.date.Interval.DAYS, 1));
|
||||
return rv;
|
||||
};
|
||||
465
float-no-zero/closure-library/closure/goog/date/relative.js
Normal file
465
float-no-zero/closure-library/closure/goog/date/relative.js
Normal file
@@ -0,0 +1,465 @@
|
||||
// Copyright 2009 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 Functions for formatting relative dates. Such as "3 days ago"
|
||||
* "3 hours ago", "14 minutes ago", "12 days ago", "Today", "Yesterday".
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.date.relative');
|
||||
|
||||
goog.require('goog.i18n.DateTimeFormat');
|
||||
|
||||
|
||||
/**
|
||||
* Number of milliseconds in a minute.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.MINUTE_MS_ = 60000;
|
||||
|
||||
|
||||
/**
|
||||
* Number of milliseconds in a day.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.DAY_MS_ = 86400000;
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration used to identify time units internally.
|
||||
* @enum {number}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.Unit_ = {
|
||||
MINUTES: 0,
|
||||
HOURS: 1,
|
||||
DAYS: 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Full date formatter.
|
||||
* @type {goog.i18n.DateTimeFormat}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.fullDateFormatter_;
|
||||
|
||||
|
||||
/**
|
||||
* Short time formatter.
|
||||
* @type {goog.i18n.DateTimeFormat}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.shortTimeFormatter_;
|
||||
|
||||
|
||||
/**
|
||||
* Month-date formatter.
|
||||
* @type {goog.i18n.DateTimeFormat}
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.monthDateFormatter_;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a date in month format, e.g. Mar 15.
|
||||
* @param {Date} date The date object.
|
||||
* @return {string} The formatted string.
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.formatMonth_ = function(date) {
|
||||
if (!goog.date.relative.monthDateFormatter_) {
|
||||
goog.date.relative.monthDateFormatter_ =
|
||||
new goog.i18n.DateTimeFormat('MMM dd');
|
||||
}
|
||||
return goog.date.relative.monthDateFormatter_.format(date);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a date in short-time format, e.g. 2:50 PM.
|
||||
* @param {Date|goog.date.DateTime} date The date object.
|
||||
* @return {string} The formatted string.
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.formatShortTime_ = function(date) {
|
||||
if (!goog.date.relative.shortTimeFormatter_) {
|
||||
goog.date.relative.shortTimeFormatter_ = new goog.i18n.DateTimeFormat(
|
||||
goog.i18n.DateTimeFormat.Format.SHORT_TIME);
|
||||
}
|
||||
return goog.date.relative.shortTimeFormatter_.format(date);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a date in full date format, e.g. Tuesday, March 24, 2009.
|
||||
* @param {Date|goog.date.DateTime} date The date object.
|
||||
* @return {string} The formatted string.
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.formatFullDate_ = function(date) {
|
||||
if (!goog.date.relative.fullDateFormatter_) {
|
||||
goog.date.relative.fullDateFormatter_ = new goog.i18n.DateTimeFormat(
|
||||
goog.i18n.DateTimeFormat.Format.FULL_DATE);
|
||||
}
|
||||
return goog.date.relative.fullDateFormatter_.format(date);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a timestamp in milliseconds and outputs a relative time in the form
|
||||
* of "1 hour ago", "1 day ago", "in 1 hour", "in 2 days" etc. If the date
|
||||
* delta is over 2 weeks, then the output string will be empty.
|
||||
* @param {number} dateMs Date in milliseconds.
|
||||
* @return {string} The formatted date.
|
||||
*/
|
||||
goog.date.relative.format = function(dateMs) {
|
||||
var now = goog.now();
|
||||
var delta = Math.floor((now - dateMs) / goog.date.relative.MINUTE_MS_);
|
||||
|
||||
var future = false;
|
||||
|
||||
if (delta < 0) {
|
||||
future = true;
|
||||
delta *= -1;
|
||||
}
|
||||
|
||||
if (delta < 60) { // Minutes.
|
||||
return goog.date.relative.getMessage_(
|
||||
delta, future, goog.date.relative.Unit_.MINUTES);
|
||||
|
||||
} else {
|
||||
delta = Math.floor(delta / 60);
|
||||
if (delta < 24) { // Hours.
|
||||
return goog.date.relative.getMessage_(
|
||||
delta, future, goog.date.relative.Unit_.HOURS);
|
||||
|
||||
} else {
|
||||
// We can be more than 24 hours apart but still only 1 day apart, so we
|
||||
// compare the closest time from today against the target time to find
|
||||
// the number of days in the delta.
|
||||
var midnight = new Date(goog.now());
|
||||
midnight.setHours(0);
|
||||
midnight.setMinutes(0);
|
||||
midnight.setSeconds(0);
|
||||
midnight.setMilliseconds(0);
|
||||
|
||||
// Convert to days ago.
|
||||
delta = Math.ceil(
|
||||
(midnight.getTime() - dateMs) / goog.date.relative.DAY_MS_);
|
||||
|
||||
if (future) {
|
||||
delta *= -1;
|
||||
}
|
||||
|
||||
// Uses days for less than 2-weeks.
|
||||
if (delta < 14) {
|
||||
return goog.date.relative.getMessage_(
|
||||
delta, future, goog.date.relative.Unit_.DAYS);
|
||||
|
||||
} else {
|
||||
// For messages older than 2 weeks do not show anything. The client
|
||||
// should decide the date format to show.
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a timestamp in milliseconds and outputs a relative time in the form
|
||||
* of "1 hour ago", "1 day ago". All future times will be returned as 0 minutes
|
||||
* ago.
|
||||
*
|
||||
* This is provided for compatibility with users of the previous incarnation of
|
||||
* the above {@see #format} method who relied on it protecting against
|
||||
* future dates.
|
||||
*
|
||||
* @param {number} dateMs Date in milliseconds.
|
||||
* @return {string} The formatted date.
|
||||
*/
|
||||
goog.date.relative.formatPast = function(dateMs) {
|
||||
var now = goog.now();
|
||||
if (now < dateMs) {
|
||||
dateMs = now;
|
||||
}
|
||||
return goog.date.relative.format(dateMs);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a timestamp in milliseconds and outputs a relative day. i.e. "Today",
|
||||
* "Yesterday", "Tomorrow", or "Sept 15".
|
||||
*
|
||||
* @param {number} dateMs Date in milliseconds.
|
||||
* @param {function(!Date):string=} opt_formatter Formatter for the date.
|
||||
* Defaults to form 'MMM dd'.
|
||||
* @return {string} The formatted date.
|
||||
*/
|
||||
goog.date.relative.formatDay = function(dateMs, opt_formatter) {
|
||||
var today = new Date(goog.now());
|
||||
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(0);
|
||||
today.setMilliseconds(0);
|
||||
|
||||
var yesterday = new Date(today.getTime() - goog.date.relative.DAY_MS_);
|
||||
var tomorrow = new Date(today.getTime() + goog.date.relative.DAY_MS_);
|
||||
var dayAfterTomorrow = new Date(today.getTime() +
|
||||
2 * goog.date.relative.DAY_MS_);
|
||||
|
||||
var message;
|
||||
if (dateMs >= tomorrow.getTime() && dateMs < dayAfterTomorrow.getTime()) {
|
||||
/** @desc Tomorrow. */
|
||||
var MSG_TOMORROW = goog.getMsg('Tomorrow');
|
||||
message = MSG_TOMORROW;
|
||||
} else if (dateMs >= today.getTime() && dateMs < tomorrow.getTime()) {
|
||||
/** @desc Today. */
|
||||
var MSG_TODAY = goog.getMsg('Today');
|
||||
message = MSG_TODAY;
|
||||
} else if (dateMs >= yesterday.getTime() && dateMs < today.getTime()) {
|
||||
/** @desc Yesterday. */
|
||||
var MSG_YESTERDAY = goog.getMsg('Yesterday');
|
||||
message = MSG_YESTERDAY;
|
||||
} else {
|
||||
// If we don't have a special relative term for this date, then return the
|
||||
// short date format (or a custom-formatted date).
|
||||
var formatFunction = opt_formatter || goog.date.relative.formatMonth_;
|
||||
message = formatFunction(new Date(dateMs));
|
||||
}
|
||||
return message;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Formats a date, adding the relative date in parenthesis. If the date is less
|
||||
* than 24 hours then the time will be printed, otherwise the full-date will be
|
||||
* used. Examples:
|
||||
* 2:20 PM (1 minute ago)
|
||||
* Monday, February 27, 2009 (4 days ago)
|
||||
* Tuesday, March 20, 2005 // Too long ago for a relative date.
|
||||
*
|
||||
* @param {Date|goog.date.DateTime} date A date object.
|
||||
* @param {string=} opt_shortTimeMsg An optional short time message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @param {string=} opt_fullDateMsg An optional date message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @return {string} The date string in the above form.
|
||||
*/
|
||||
goog.date.relative.getDateString = function(
|
||||
date, opt_shortTimeMsg, opt_fullDateMsg) {
|
||||
return goog.date.relative.getDateString_(
|
||||
date, goog.date.relative.format, opt_shortTimeMsg, opt_fullDateMsg);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Formats a date, adding the relative date in parenthesis. Functions the same
|
||||
* as #getDateString but ensures that the date is always seen to be in the past.
|
||||
* If the date is in the future, it will be shown as 0 minutes ago.
|
||||
*
|
||||
* This is provided for compatibility with users of the previous incarnation of
|
||||
* the above {@see #getDateString} method who relied on it protecting against
|
||||
* future dates.
|
||||
*
|
||||
* @param {Date|goog.date.DateTime} date A date object.
|
||||
* @param {string=} opt_shortTimeMsg An optional short time message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @param {string=} opt_fullDateMsg An optional date message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @return {string} The date string in the above form.
|
||||
*/
|
||||
goog.date.relative.getPastDateString = function(
|
||||
date, opt_shortTimeMsg, opt_fullDateMsg) {
|
||||
return goog.date.relative.getDateString_(
|
||||
date, goog.date.relative.formatPast, opt_shortTimeMsg, opt_fullDateMsg);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Formats a date, adding the relative date in parenthesis. If the date is less
|
||||
* than 24 hours then the time will be printed, otherwise the full-date will be
|
||||
* used. Examples:
|
||||
* 2:20 PM (1 minute ago)
|
||||
* Monday, February 27, 2009 (4 days ago)
|
||||
* Tuesday, March 20, 2005 // Too long ago for a relative date.
|
||||
*
|
||||
* @param {Date|goog.date.DateTime} date A date object.
|
||||
* @param {function(number) : string} relativeFormatter Function to use when
|
||||
* formatting the relative date.
|
||||
* @param {string=} opt_shortTimeMsg An optional short time message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @param {string=} opt_fullDateMsg An optional date message can be
|
||||
* provided if available, so that it's not recalculated in this function.
|
||||
* @return {string} The date string in the above form.
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.getDateString_ = function(
|
||||
date, relativeFormatter, opt_shortTimeMsg, opt_fullDateMsg) {
|
||||
var dateMs = date.getTime();
|
||||
|
||||
var relativeDate = relativeFormatter(dateMs);
|
||||
|
||||
if (relativeDate) {
|
||||
relativeDate = ' (' + relativeDate + ')';
|
||||
}
|
||||
|
||||
var delta = Math.floor((goog.now() - dateMs) / goog.date.relative.MINUTE_MS_);
|
||||
if (delta < 60 * 24) {
|
||||
// TODO(user): this call raises an exception if date is a goog.date.Date.
|
||||
return (opt_shortTimeMsg || goog.date.relative.formatShortTime_(date)) +
|
||||
relativeDate;
|
||||
} else {
|
||||
return (opt_fullDateMsg || goog.date.relative.formatFullDate_(date)) +
|
||||
relativeDate;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* TODO(user):
|
||||
*
|
||||
* I think that this whole relative formatting should move to DateTimeFormat,
|
||||
* make sure it treats plurals properly (now it does not), an so on.
|
||||
* But we would have to wait for the next version of CLDR, which is cleaning
|
||||
* the data for relative dates (even ICU has incomplete support for this).
|
||||
*
|
||||
* It also looks like this is not an object, and it does not save
|
||||
* DateTimeSymbols at the time of creation, but uses the current value,
|
||||
* whatever that is. So if one changes the global goog.i18n.DateTimeSymbols
|
||||
* in between calls, then we get different results.
|
||||
*/
|
||||
/**
|
||||
* Gets a localized relative date string for a given delta and unit.
|
||||
* @param {number} delta Number of minutes/hours/days.
|
||||
* @param {boolean} future Whether the delta is in the future.
|
||||
* @param {goog.date.relative.Unit_} unit The units the delta is in.
|
||||
* @return {string} The message.
|
||||
* @private
|
||||
*/
|
||||
goog.date.relative.getMessage_ = function(delta, future, unit) {
|
||||
// Convert to localized (native) digits
|
||||
var localizedDelta =
|
||||
goog.i18n.DateTimeFormat.prototype.localizeNumbers('' + delta);
|
||||
if (!future && unit == goog.date.relative.Unit_.MINUTES) {
|
||||
/**
|
||||
* @desc Relative date indicating how many minutes ago something happened
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_MINUTES_AGO_SINGULAR =
|
||||
goog.getMsg('{$num} minute ago', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating how many minutes ago something happened
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_MINUTES_AGO_PLURAL =
|
||||
goog.getMsg('{$num} minutes ago', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_MINUTES_AGO_SINGULAR : MSG_MINUTES_AGO_PLURAL;
|
||||
|
||||
} else if (future && unit == goog.date.relative.Unit_.MINUTES) {
|
||||
/**
|
||||
* @desc Relative date indicating in how many minutes something happens
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_IN_MINUTES_SINGULAR =
|
||||
goog.getMsg('in {$num} minute', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating in how many minutes something happens
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_IN_MINUTES_PLURAL =
|
||||
goog.getMsg('in {$num} minutes', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_IN_MINUTES_SINGULAR : MSG_IN_MINUTES_PLURAL;
|
||||
|
||||
} else if (!future && unit == goog.date.relative.Unit_.HOURS) {
|
||||
/**
|
||||
* @desc Relative date indicating how many hours ago something happened
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_HOURS_AGO_SINGULAR =
|
||||
goog.getMsg('{$num} hour ago', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating how many hours ago something happened
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_HOURS_AGO_PLURAL =
|
||||
goog.getMsg('{$num} hours ago', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_HOURS_AGO_SINGULAR : MSG_HOURS_AGO_PLURAL;
|
||||
|
||||
} else if (future && unit == goog.date.relative.Unit_.HOURS) {
|
||||
/**
|
||||
* @desc Relative date indicating in how many hours something happens
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_IN_HOURS_SINGULAR =
|
||||
goog.getMsg('in {$num} hour', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating in how many hours something happens
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_IN_HOURS_PLURAL =
|
||||
goog.getMsg('in {$num} hours', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_IN_HOURS_SINGULAR : MSG_IN_HOURS_PLURAL;
|
||||
|
||||
} else if (!future && unit == goog.date.relative.Unit_.DAYS) {
|
||||
/**
|
||||
* @desc Relative date indicating how many days ago something happened
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_DAYS_AGO_SINGULAR =
|
||||
goog.getMsg('{$num} day ago', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating how many days ago something happened
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_DAYS_AGO_PLURAL =
|
||||
goog.getMsg('{$num} days ago', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_DAYS_AGO_SINGULAR : MSG_DAYS_AGO_PLURAL;
|
||||
|
||||
} else if (future && unit == goog.date.relative.Unit_.DAYS) {
|
||||
/**
|
||||
* @desc Relative date indicating in how many days something happens
|
||||
* (singular).
|
||||
*/
|
||||
var MSG_IN_DAYS_SINGULAR =
|
||||
goog.getMsg('in {$num} day', {'num' : localizedDelta});
|
||||
|
||||
/**
|
||||
* @desc Relative date indicating in how many days something happens
|
||||
* (plural).
|
||||
*/
|
||||
var MSG_IN_DAYS_PLURAL =
|
||||
goog.getMsg('in {$num} days', {'num' : localizedDelta});
|
||||
|
||||
return delta == 1 ? MSG_IN_DAYS_SINGULAR : MSG_IN_DAYS_PLURAL;
|
||||
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
179
float-no-zero/closure-library/closure/goog/date/utcdatetime.js
Normal file
179
float-no-zero/closure-library/closure/goog/date/utcdatetime.js
Normal file
@@ -0,0 +1,179 @@
|
||||
// Copyright 2009 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 Locale independent date/time class.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.date.UtcDateTime');
|
||||
|
||||
goog.require('goog.date');
|
||||
goog.require('goog.date.Date');
|
||||
goog.require('goog.date.DateTime');
|
||||
goog.require('goog.date.Interval');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class representing a date/time in GMT+0 time zone, without daylight saving.
|
||||
* Defaults to current date and time if none is specified. The get... and the
|
||||
* getUTC... methods are equivalent.
|
||||
*
|
||||
* @param {number|Object=} opt_year Four digit UTC year or a date-like object.
|
||||
* If not set, the created object will contain the date determined by
|
||||
* goog.now().
|
||||
* @param {number=} opt_month UTC month, 0 = Jan, 11 = Dec.
|
||||
* @param {number=} opt_date UTC date of month, 1 - 31.
|
||||
* @param {number=} opt_hours UTC hours, 0 - 23.
|
||||
* @param {number=} opt_minutes UTC minutes, 0 - 59.
|
||||
* @param {number=} opt_seconds UTC seconds, 0 - 59.
|
||||
* @param {number=} opt_milliseconds UTC milliseconds, 0 - 999.
|
||||
* @constructor
|
||||
* @extends {goog.date.DateTime}
|
||||
*/
|
||||
goog.date.UtcDateTime = function(opt_year, opt_month, opt_date, opt_hours,
|
||||
opt_minutes, opt_seconds, opt_milliseconds) {
|
||||
var timestamp;
|
||||
if (goog.isNumber(opt_year)) {
|
||||
timestamp = Date.UTC(opt_year, opt_month || 0, opt_date || 1,
|
||||
opt_hours || 0, opt_minutes || 0, opt_seconds || 0,
|
||||
opt_milliseconds || 0);
|
||||
} else {
|
||||
timestamp = opt_year ? opt_year.getTime() : goog.now();
|
||||
}
|
||||
this.date_ = new Date(timestamp);
|
||||
};
|
||||
goog.inherits(goog.date.UtcDateTime, goog.date.DateTime);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a DateTime from a UTC datetime string expressed in ISO 8601 format.
|
||||
*
|
||||
* @param {string} formatted A date or datetime expressed in ISO 8601 format.
|
||||
* @return {goog.date.UtcDateTime} Parsed date or null if parse fails.
|
||||
*/
|
||||
goog.date.UtcDateTime.fromIsoString = function(formatted) {
|
||||
var ret = new goog.date.UtcDateTime(2000);
|
||||
return goog.date.setIso8601DateTime(ret, formatted) ? ret : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clones the UtcDateTime object.
|
||||
*
|
||||
* @return {!goog.date.UtcDateTime} A clone of the datetime object.
|
||||
* @override
|
||||
*/
|
||||
goog.date.UtcDateTime.prototype.clone = function() {
|
||||
var date = new goog.date.UtcDateTime(this.date_);
|
||||
date.setFirstDayOfWeek(this.getFirstDayOfWeek());
|
||||
date.setFirstWeekCutOffDay(this.getFirstWeekCutOffDay());
|
||||
return date;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.add = function(interval) {
|
||||
if (interval.years || interval.months) {
|
||||
var yearsMonths = new goog.date.Interval(interval.years, interval.months);
|
||||
goog.date.Date.prototype.add.call(this, yearsMonths);
|
||||
}
|
||||
var daysAndTimeMillis = 1000 * (
|
||||
interval.seconds + 60 * (
|
||||
interval.minutes + 60 * (
|
||||
interval.hours + 24 * interval.days)));
|
||||
this.date_ = new Date(this.date_.getTime() + daysAndTimeMillis);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getTimezoneOffset = function() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getFullYear =
|
||||
goog.date.DateTime.prototype.getUTCFullYear;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getMonth =
|
||||
goog.date.DateTime.prototype.getUTCMonth;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getDate =
|
||||
goog.date.DateTime.prototype.getUTCDate;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getHours =
|
||||
goog.date.DateTime.prototype.getUTCHours;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getMinutes =
|
||||
goog.date.DateTime.prototype.getUTCMinutes;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getSeconds =
|
||||
goog.date.DateTime.prototype.getUTCSeconds;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getMilliseconds =
|
||||
goog.date.DateTime.prototype.getUTCMilliseconds;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.getDay =
|
||||
goog.date.DateTime.prototype.getUTCDay;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setFullYear =
|
||||
goog.date.DateTime.prototype.setUTCFullYear;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setMonth =
|
||||
goog.date.DateTime.prototype.setUTCMonth;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setDate =
|
||||
goog.date.DateTime.prototype.setUTCDate;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setHours =
|
||||
goog.date.DateTime.prototype.setUTCHours;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setMinutes =
|
||||
goog.date.DateTime.prototype.setUTCMinutes;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setSeconds =
|
||||
goog.date.DateTime.prototype.setUTCSeconds;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.date.UtcDateTime.prototype.setMilliseconds =
|
||||
goog.date.DateTime.prototype.setUTCMilliseconds;
|
||||
214
float-no-zero/closure-library/closure/goog/db/cursor.js
Normal file
214
float-no-zero/closure-library/closure/goog/db/cursor.js
Normal file
@@ -0,0 +1,214 @@
|
||||
// Copyright 2012 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 Wrapper for a IndexedDB cursor.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.Cursor');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new IDBCursor wrapper object. Should not be created directly,
|
||||
* access cursor through object store.
|
||||
* @see goog.db.ObjectStore#openCursor
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.db.Cursor = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(goog.db.Cursor, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Underlying IndexedDB cursor object.
|
||||
*
|
||||
* @type {IDBCursor}
|
||||
* @private
|
||||
*/
|
||||
goog.db.Cursor.prototype.cursor_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Advances the cursor to the next position along its direction. When new data
|
||||
* is available, the NEW_DATA event will be fired. If the cursor has reached the
|
||||
* end of the range it will fire the COMPLETE event. If opt_key is specified it
|
||||
* will advance to the key it matches in its direction.
|
||||
*
|
||||
* This wraps the native #continue method on the underlying object.
|
||||
*
|
||||
* @param {IDBKeyType=} opt_key The optional key to advance to.
|
||||
*/
|
||||
goog.db.Cursor.prototype.next = function(opt_key) {
|
||||
if (opt_key) {
|
||||
this.cursor_['continue'](opt_key);
|
||||
} else {
|
||||
this.cursor_['continue']();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates the value at the current position of the cursor in the object store.
|
||||
* If the cursor points to a value that has just been deleted, a new value is
|
||||
* created.
|
||||
*
|
||||
* @param {*} value The value to be stored.
|
||||
* @return {!goog.async.Deferred} The resulting deferred request.
|
||||
*/
|
||||
goog.db.Cursor.prototype.update = function(value) {
|
||||
var msg = 'updating via cursor with value ';
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
|
||||
try {
|
||||
request = this.cursor_.update(value);
|
||||
} catch (err) {
|
||||
msg += goog.debug.deepExpose(value);
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
msg += goog.debug.deepExpose(value);
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the value at the cursor's position, without changing the cursor's
|
||||
* position. Once the value is deleted, the cursor's value is set to null.
|
||||
*
|
||||
* @return {!goog.async.Deferred} The resulting deferred request.
|
||||
*/
|
||||
goog.db.Cursor.prototype.remove = function() {
|
||||
var msg = 'deleting via cursor';
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
|
||||
try {
|
||||
request = this.cursor_['delete']();
|
||||
} catch (err) {
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {*} The value for the value at the cursor's position. Undefined
|
||||
* if no current value, or null if value has just been deleted.
|
||||
*/
|
||||
goog.db.Cursor.prototype.getValue = function() {
|
||||
return this.cursor_['value'];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {IDBKeyType} The key for the value at the cursor's position. If
|
||||
* the cursor is outside its range, this is undefined.
|
||||
*/
|
||||
goog.db.Cursor.prototype.getKey = function() {
|
||||
return this.cursor_.key;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens a value cursor from IDBObjectStore or IDBIndex over the specified key
|
||||
* range. Returns a cursor object which is able to iterate over the given range.
|
||||
* @param {!(IDBObjectStore|IDBIndex)} source Data source to open cursor.
|
||||
* @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
|
||||
* over the whole data source.
|
||||
* @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
|
||||
* moves in a forward direction with duplicates.
|
||||
* @return {!goog.db.Cursor} The cursor.
|
||||
* @throws {goog.db.Error} If there was a problem opening the cursor.
|
||||
*/
|
||||
goog.db.Cursor.openCursor = function(source, opt_range, opt_direction) {
|
||||
var cursor = new goog.db.Cursor();
|
||||
var request;
|
||||
|
||||
try {
|
||||
var range = opt_range ? opt_range.range() : null;
|
||||
if (opt_direction) {
|
||||
request = source.openCursor(range, opt_direction);
|
||||
} else {
|
||||
request = source.openCursor(range);
|
||||
}
|
||||
} catch (ex) {
|
||||
cursor.dispose();
|
||||
throw goog.db.Error.fromException(ex, source.name);
|
||||
}
|
||||
request.onsuccess = function(e) {
|
||||
cursor.cursor_ = e.target.result || null;
|
||||
if (cursor.cursor_) {
|
||||
cursor.dispatchEvent(goog.db.Cursor.EventType.NEW_DATA);
|
||||
} else {
|
||||
cursor.dispatchEvent(goog.db.Cursor.EventType.COMPLETE);
|
||||
}
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
cursor.dispatchEvent(goog.db.Cursor.EventType.ERROR);
|
||||
};
|
||||
return cursor;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Possible cursor directions.
|
||||
* @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursor
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.db.Cursor.Direction = {
|
||||
NEXT: 'next',
|
||||
NEXT_NO_DUPLICATE: 'nextunique',
|
||||
PREV: 'prev',
|
||||
PREV_NO_DUPLICATE: 'prevunique'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Event types that the cursor can dispatch. COMPLETE events are dispatched when
|
||||
* a cursor is depleted of values, a NEW_DATA event if there is new data
|
||||
* available, and ERROR if an error occurred.
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.db.Cursor.EventType = {
|
||||
COMPLETE: 'c',
|
||||
ERROR: 'e',
|
||||
NEW_DATA: 'n'
|
||||
};
|
||||
182
float-no-zero/closure-library/closure/goog/db/db.js
Normal file
182
float-no-zero/closure-library/closure/goog/db/db.js
Normal file
@@ -0,0 +1,182 @@
|
||||
// Copyright 2011 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 Wrappers for the HTML5 IndexedDB. The wrappers export nearly
|
||||
* the same interface as the standard API, but return goog.async.Deferred
|
||||
* objects instead of request objects and use Closure events. The wrapper works
|
||||
* and has been tested on Chrome version 22+. It may work on older Chrome
|
||||
* versions, but they aren't explicitly supported.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <code>
|
||||
* goog.db.openDatabase('mydb', 1, function(ev, db, tx) {
|
||||
* db.createObjectStore('mystore');
|
||||
* }).addCallback(function(db) {
|
||||
* var putTx = db.createTransaction(
|
||||
* [],
|
||||
* goog.db.Transaction.TransactionMode.READ_WRITE);
|
||||
* var store = putTx.objectStore('mystore');
|
||||
* store.put('value', 'key');
|
||||
* goog.listen(putTx, goog.db.Transaction.EventTypes.COMPLETE, function() {
|
||||
* var getTx = db.createTransaction([]);
|
||||
* var request = getTx.objectStore('mystore').get('key');
|
||||
* request.addCallback(function(result) {
|
||||
* ...
|
||||
* });
|
||||
* });
|
||||
* </code>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.db.IndexedDb');
|
||||
goog.require('goog.db.Transaction');
|
||||
|
||||
|
||||
/**
|
||||
* The IndexedDB factory object.
|
||||
*
|
||||
* @type {IDBFactory}
|
||||
* @private
|
||||
*/
|
||||
goog.db.indexedDb_ = goog.global.indexedDB || goog.global.mozIndexedDB ||
|
||||
goog.global.webkitIndexedDB || goog.global.moz_indexedDB;
|
||||
|
||||
|
||||
/**
|
||||
* A callback that's called if a blocked event is received. When a database is
|
||||
* supposed to be deleted or upgraded (i.e. versionchange), and there are open
|
||||
* connections to this database, a block event will be fired to prevent the
|
||||
* operations from going through until all such open connections are closed.
|
||||
* This callback can be used to notify users that they should close other tabs
|
||||
* that have open connections, or to close the connections manually. Databases
|
||||
* can also listen for the {@link goog.db.IndexedDb.EventType.VERSION_CHANGE}
|
||||
* event to automatically close themselves when they're blocking such
|
||||
* operations.
|
||||
*
|
||||
* This is passed a VersionChangeEvent that has the version of the database
|
||||
* before it was deleted, and "null" as the new version.
|
||||
*
|
||||
* @typedef {function(!goog.db.IndexedDb.VersionChangeEvent)}
|
||||
*/
|
||||
goog.db.BlockedCallback;
|
||||
|
||||
|
||||
/**
|
||||
* A callback that's called when opening a database whose internal version is
|
||||
* lower than the version passed to {@link goog.db.openDatabase}.
|
||||
*
|
||||
* This callback is passed three arguments: a VersionChangeEvent with both the
|
||||
* old version and the new version of the database; the database that's being
|
||||
* opened, for which you can create and delete object stores; and the version
|
||||
* change transaction, with which you can abort the version change.
|
||||
*
|
||||
* Note that the transaction is not active, which means that it can't be used to
|
||||
* make changes to the database. However, since there is a transaction running,
|
||||
* you can't create another one via {@link goog.db.IndexedDb.createTransaction}.
|
||||
* This means that it's not possible to manipulate the database other than
|
||||
* creating or removing object stores in this callback.
|
||||
*
|
||||
* @typedef {function(!goog.db.IndexedDb.VersionChangeEvent,
|
||||
* !goog.db.IndexedDb,
|
||||
* !goog.db.Transaction)}
|
||||
*/
|
||||
goog.db.UpgradeNeededCallback;
|
||||
|
||||
|
||||
/**
|
||||
* Opens a database connection and wraps it.
|
||||
*
|
||||
* @param {string} name The name of the database to open.
|
||||
* @param {number=} opt_version The expected version of the database. If this is
|
||||
* larger than the actual version, opt_onUpgradeNeeded will be called
|
||||
* (possibly after opt_onBlocked; see {@link goog.db.BlockedCallback}). If
|
||||
* this is passed, opt_onUpgradeNeeded must be passed as well.
|
||||
* @param {goog.db.UpgradeNeededCallback=} opt_onUpgradeNeeded Called if
|
||||
* opt_version is greater than the old version of the database. If
|
||||
* opt_version is passed, this must be passed as well.
|
||||
* @param {goog.db.BlockedCallback=} opt_onBlocked Called if there are active
|
||||
* connections to the database.
|
||||
* @return {!goog.async.Deferred} The deferred database object.
|
||||
*/
|
||||
goog.db.openDatabase = function(name, opt_version, opt_onUpgradeNeeded,
|
||||
opt_onBlocked) {
|
||||
goog.asserts.assert(
|
||||
goog.isDef(opt_version) == goog.isDef(opt_onUpgradeNeeded),
|
||||
'opt_version must be passed to goog.db.openDatabase if and only if ' +
|
||||
'opt_onUpgradeNeeded is also passed');
|
||||
|
||||
var d = new goog.async.Deferred();
|
||||
var openRequest = opt_version ?
|
||||
goog.db.indexedDb_.open(name, opt_version) :
|
||||
goog.db.indexedDb_.open(name);
|
||||
openRequest.onsuccess = function(ev) {
|
||||
var db = new goog.db.IndexedDb(ev.target.result);
|
||||
d.callback(db);
|
||||
};
|
||||
openRequest.onerror = function(ev) {
|
||||
var msg = 'opening database ' + name;
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
openRequest.onupgradeneeded = function(ev) {
|
||||
if (!opt_onUpgradeNeeded) return;
|
||||
var db = new goog.db.IndexedDb(ev.target.result);
|
||||
opt_onUpgradeNeeded(
|
||||
new goog.db.IndexedDb.VersionChangeEvent(ev.oldVersion, ev.newVersion),
|
||||
db,
|
||||
new goog.db.Transaction(ev.target.transaction, db));
|
||||
};
|
||||
openRequest.onblocked = function(ev) {
|
||||
if (opt_onBlocked) {
|
||||
opt_onBlocked(new goog.db.IndexedDb.VersionChangeEvent(
|
||||
ev.oldVersion, ev.newVersion));
|
||||
}
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a database once all open connections have been closed.
|
||||
*
|
||||
* @param {string} name The name of the database to delete.
|
||||
* @param {goog.db.BlockedCallback=} opt_onBlocked Called if there are active
|
||||
* connections to the database.
|
||||
* @return {goog.async.Deferred} A deferred object that will fire once the
|
||||
* database is deleted.
|
||||
*/
|
||||
goog.db.deleteDatabase = function(name, opt_onBlocked) {
|
||||
var d = new goog.async.Deferred();
|
||||
var deleteRequest = goog.db.indexedDb_.deleteDatabase(name);
|
||||
deleteRequest.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
deleteRequest.onerror = function(ev) {
|
||||
var msg = 'deleting database ' + name;
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
deleteRequest.onblocked = function(ev) {
|
||||
if (opt_onBlocked) {
|
||||
opt_onBlocked(new goog.db.IndexedDb.VersionChangeEvent(
|
||||
ev.oldVersion, ev.newVersion));
|
||||
}
|
||||
};
|
||||
return d;
|
||||
};
|
||||
359
float-no-zero/closure-library/closure/goog/db/error.js
Normal file
359
float-no-zero/closure-library/closure/goog/db/error.js
Normal file
@@ -0,0 +1,359 @@
|
||||
// Copyright 2011 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 Error classes for the IndexedDB wrapper.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.Error');
|
||||
goog.provide('goog.db.Error.ErrorCode');
|
||||
goog.provide('goog.db.Error.ErrorName');
|
||||
goog.provide('goog.db.Error.VersionChangeBlockedError');
|
||||
|
||||
goog.require('goog.debug.Error');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A database error. Since the stack trace can be unhelpful in an asynchronous
|
||||
* context, the error provides a message about where it was produced.
|
||||
*
|
||||
* @param {number|!DOMError} error The DOMError instance returned by the
|
||||
* browser for Chrome22+, or an error code for previous versions.
|
||||
* @param {string} context A description of where the error occured.
|
||||
* @param {string=} opt_message Additional message.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.db.Error = function(error, context, opt_message) {
|
||||
var errorCode = null;
|
||||
var internalError = null;
|
||||
if (goog.isNumber(error)) {
|
||||
errorCode = error;
|
||||
internalError = {name: goog.db.Error.getName(errorCode)};
|
||||
} else {
|
||||
internalError = error;
|
||||
errorCode = goog.db.Error.getCode(error.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The code for this error.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.code = errorCode;
|
||||
|
||||
/**
|
||||
* The DOMException as returned by the browser.
|
||||
*
|
||||
* @type {!DOMError}
|
||||
* @private
|
||||
*/
|
||||
this.error_ = /** @type {!DOMError} */ (internalError);
|
||||
|
||||
var msg = 'Error ' + context + ': ' + this.getName();
|
||||
if (opt_message) {
|
||||
msg += ', ' + opt_message;
|
||||
}
|
||||
goog.base(this, msg);
|
||||
};
|
||||
goog.inherits(goog.db.Error, goog.debug.Error);
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The name of the error.
|
||||
*/
|
||||
goog.db.Error.prototype.getName = function() {
|
||||
return this.error_.name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A specific kind of database error. If a Version Change is unable to proceed
|
||||
* due to other open database connections, it will block and this error will be
|
||||
* thrown.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.db.Error.VersionChangeBlockedError = function() {
|
||||
goog.base(this, 'Version change blocked');
|
||||
};
|
||||
goog.inherits(goog.db.Error.VersionChangeBlockedError, goog.debug.Error);
|
||||
|
||||
|
||||
/**
|
||||
* Synthetic error codes for database errors, for use when IndexedDB
|
||||
* support is not available. This numbering differs in practice
|
||||
* from the browser implementations, but it is not meant to be reliable:
|
||||
* this object merely ensures that goog.db.Error is loadable on platforms
|
||||
* that do not support IndexedDB.
|
||||
*
|
||||
* @enum {number}
|
||||
* @private
|
||||
*/
|
||||
goog.db.Error.DatabaseErrorCode_ = {
|
||||
UNKNOWN_ERR: 1,
|
||||
NON_TRANSIENT_ERR: 2,
|
||||
NOT_FOUND_ERR: 3,
|
||||
CONSTRAINT_ERR: 4,
|
||||
DATA_ERR: 5,
|
||||
NOT_ALLOWED_ERR: 6,
|
||||
TRANSACTION_INACTIVE_ERR: 7,
|
||||
ABORT_ERR: 8,
|
||||
READ_ONLY_ERR: 9,
|
||||
TRANSIENT_ERR: 11,
|
||||
TIMEOUT_ERR: 10,
|
||||
QUOTA_ERR: 11,
|
||||
INVALID_ACCESS_ERR: 12,
|
||||
INVALID_STATE_ERR: 13
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Error codes for database errors.
|
||||
* @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBDatabaseException
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.db.Error.ErrorCode = {
|
||||
UNKNOWN_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).UNKNOWN_ERR,
|
||||
NON_TRANSIENT_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).NON_TRANSIENT_ERR,
|
||||
NOT_FOUND_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).NOT_FOUND_ERR,
|
||||
CONSTRAINT_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).CONSTRAINT_ERR,
|
||||
DATA_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).DATA_ERR,
|
||||
NOT_ALLOWED_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).NOT_ALLOWED_ERR,
|
||||
TRANSACTION_INACTIVE_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).TRANSACTION_INACTIVE_ERR,
|
||||
ABORT_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).ABORT_ERR,
|
||||
READ_ONLY_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).READ_ONLY_ERR,
|
||||
TIMEOUT_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).TIMEOUT_ERR,
|
||||
QUOTA_ERR: (goog.global.IDBDatabaseException ||
|
||||
goog.global.webkitIDBDatabaseException ||
|
||||
goog.db.Error.DatabaseErrorCode_).QUOTA_ERR,
|
||||
INVALID_ACCESS_ERR: (goog.global.DOMException ||
|
||||
goog.db.Error.DatabaseErrorCode_).INVALID_ACCESS_ERR,
|
||||
INVALID_STATE_ERR: (goog.global.DOMException ||
|
||||
goog.db.Error.DatabaseErrorCode_).INVALID_STATE_ERR
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translates an error code into a more useful message.
|
||||
*
|
||||
* @param {number} code Error code.
|
||||
* @return {string} A debug message.
|
||||
*/
|
||||
goog.db.Error.getMessage = function(code) {
|
||||
switch (code) {
|
||||
case goog.db.Error.ErrorCode.UNKNOWN_ERR:
|
||||
return 'Unknown error';
|
||||
case goog.db.Error.ErrorCode.NON_TRANSIENT_ERR:
|
||||
return 'Invalid operation';
|
||||
case goog.db.Error.ErrorCode.NOT_FOUND_ERR:
|
||||
return 'Required database object not found';
|
||||
case goog.db.Error.ErrorCode.CONSTRAINT_ERR:
|
||||
return 'Constraint unsatisfied';
|
||||
case goog.db.Error.ErrorCode.DATA_ERR:
|
||||
return 'Invalid data';
|
||||
case goog.db.Error.ErrorCode.NOT_ALLOWED_ERR:
|
||||
return 'Operation disallowed';
|
||||
case goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR:
|
||||
return 'Transaction not active';
|
||||
case goog.db.Error.ErrorCode.ABORT_ERR:
|
||||
return 'Request aborted';
|
||||
case goog.db.Error.ErrorCode.READ_ONLY_ERR:
|
||||
return 'Modifying operation not allowed in a read-only transaction';
|
||||
case goog.db.Error.ErrorCode.TIMEOUT_ERR:
|
||||
return 'Transaction timed out';
|
||||
case goog.db.Error.ErrorCode.QUOTA_ERR:
|
||||
return 'Database storage space quota exceeded';
|
||||
case goog.db.Error.ErrorCode.INVALID_ACCESS_ERR:
|
||||
return 'Invalid operation';
|
||||
case goog.db.Error.ErrorCode.INVALID_STATE_ERR:
|
||||
return 'Invalid state';
|
||||
default:
|
||||
return 'Unrecognized exception with code ' + code;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Names of all possible errors as returned from the browser.
|
||||
* @see http://www.w3.org/TR/IndexedDB/#exceptions
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.db.Error.ErrorName = {
|
||||
ABORT_ERR: 'AbortError',
|
||||
CONSTRAINT_ERR: 'ConstraintError',
|
||||
DATA_CLONE_ERR: 'DataCloneError',
|
||||
DATA_ERR: 'DataError',
|
||||
INVALID_ACCESS_ERR: 'InvalidAccessError',
|
||||
INVALID_STATE_ERR: 'InvalidStateError',
|
||||
NOT_FOUND_ERR: 'NotFoundError',
|
||||
QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
|
||||
READ_ONLY_ERR: 'ReadOnlyError',
|
||||
SYNTAX_ERROR: 'SyntaxError',
|
||||
TIMEOUT_ERR: 'TimeoutError',
|
||||
TRANSACTION_INACTIVE_ERR: 'TransactionInactiveError',
|
||||
UNKNOWN_ERR: 'UnknownError',
|
||||
VERSION_ERR: 'VersionError'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translates an error name to an error code. This is purely kept for backwards
|
||||
* compatibility with Chrome21.
|
||||
*
|
||||
* @param {string} name The name of the erorr.
|
||||
* @return {number} The error code corresponding to the error.
|
||||
*/
|
||||
goog.db.Error.getCode = function(name) {
|
||||
switch (name) {
|
||||
case goog.db.Error.ErrorName.UNKNOWN_ERR:
|
||||
return goog.db.Error.ErrorCode.UNKNOWN_ERR;
|
||||
case goog.db.Error.ErrorName.NOT_FOUND_ERR:
|
||||
return goog.db.Error.ErrorCode.NOT_FOUND_ERR;
|
||||
case goog.db.Error.ErrorName.CONSTRAINT_ERR:
|
||||
return goog.db.Error.ErrorCode.CONSTRAINT_ERR;
|
||||
case goog.db.Error.ErrorName.DATA_ERR:
|
||||
return goog.db.Error.ErrorCode.DATA_ERR;
|
||||
case goog.db.Error.ErrorName.TRANSACTION_INACTIVE_ERR:
|
||||
return goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR;
|
||||
case goog.db.Error.ErrorName.ABORT_ERR:
|
||||
return goog.db.Error.ErrorCode.ABORT_ERR;
|
||||
case goog.db.Error.ErrorName.READ_ONLY_ERR:
|
||||
return goog.db.Error.ErrorCode.READ_ONLY_ERR;
|
||||
case goog.db.Error.ErrorName.TIMEOUT_ERR:
|
||||
return goog.db.Error.ErrorCode.TIMEOUT_ERR;
|
||||
case goog.db.Error.ErrorName.QUOTA_EXCEEDED_ERR:
|
||||
return goog.db.Error.ErrorCode.QUOTA_ERR;
|
||||
case goog.db.Error.ErrorName.INVALID_ACCESS_ERR:
|
||||
return goog.db.Error.ErrorCode.INVALID_ACCESS_ERR;
|
||||
case goog.db.Error.ErrorName.INVALID_STATE_ERR:
|
||||
return goog.db.Error.ErrorCode.INVALID_STATE_ERR;
|
||||
default:
|
||||
return goog.db.Error.ErrorCode.UNKNOWN_ERR;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an error code used by the old spec, to an error name used by the
|
||||
* latest spec.
|
||||
* @see http://www.w3.org/TR/IndexedDB/#exceptions
|
||||
*
|
||||
* @param {!goog.db.Error.ErrorCode|number} code The error code to convert.
|
||||
* @return {!goog.db.Error.ErrorName} The corresponding name of the error.
|
||||
*/
|
||||
goog.db.Error.getName = function(code) {
|
||||
switch (code) {
|
||||
case goog.db.Error.ErrorCode.UNKNOWN_ERR:
|
||||
return goog.db.Error.ErrorName.UNKNOWN_ERR;
|
||||
case goog.db.Error.ErrorCode.NOT_FOUND_ERR:
|
||||
return goog.db.Error.ErrorName.NOT_FOUND_ERR;
|
||||
case goog.db.Error.ErrorCode.CONSTRAINT_ERR:
|
||||
return goog.db.Error.ErrorName.CONSTRAINT_ERR;
|
||||
case goog.db.Error.ErrorCode.DATA_ERR:
|
||||
return goog.db.Error.ErrorName.DATA_ERR;
|
||||
case goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR:
|
||||
return goog.db.Error.ErrorName.TRANSACTION_INACTIVE_ERR;
|
||||
case goog.db.Error.ErrorCode.ABORT_ERR:
|
||||
return goog.db.Error.ErrorName.ABORT_ERR;
|
||||
case goog.db.Error.ErrorCode.READ_ONLY_ERR:
|
||||
return goog.db.Error.ErrorName.READ_ONLY_ERR;
|
||||
case goog.db.Error.ErrorCode.TIMEOUT_ERR:
|
||||
return goog.db.Error.ErrorName.TIMEOUT_ERR;
|
||||
case goog.db.Error.ErrorCode.QUOTA_ERR:
|
||||
return goog.db.Error.ErrorName.QUOTA_EXCEEDED_ERR;
|
||||
case goog.db.Error.ErrorCode.INVALID_ACCESS_ERR:
|
||||
return goog.db.Error.ErrorName.INVALID_ACCESS_ERR;
|
||||
case goog.db.Error.ErrorCode.INVALID_STATE_ERR:
|
||||
return goog.db.Error.ErrorName.INVALID_STATE_ERR;
|
||||
default:
|
||||
return goog.db.Error.ErrorName.UNKNOWN_ERR;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an goog.db.Error instance from an IDBRequest. This abstraction is
|
||||
* necessary to provide backwards compatibility with Chrome21.
|
||||
*
|
||||
* @param {!IDBRequest} request The request that failed.
|
||||
* @param {string} message The error message to add to err if it's wrapped.
|
||||
* @return {!goog.db.Error} The error that caused the failure.
|
||||
*/
|
||||
goog.db.Error.fromRequest = function(request, message) {
|
||||
if ('error' in request) {
|
||||
// Chrome 21 and before.
|
||||
return new goog.db.Error(request.error, message);
|
||||
} else if ('name' in request) {
|
||||
// Chrome 22+.
|
||||
var errorName = goog.db.Error.getName(request.errorCode);
|
||||
return new goog.db.Error(
|
||||
/**@type {!DOMError} */ ({name: errorName}), message);
|
||||
} else {
|
||||
return new goog.db.Error(/** @type {!DOMError} */ (
|
||||
{name: goog.db.Error.ErrorName.UNKNOWN_ERR}), message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an goog.db.Error instance from an DOMException. This abstraction
|
||||
* is necessary to provide backwards compatibility with Chrome21.
|
||||
*
|
||||
* @param {!IDBDatabaseException} ex The exception that was thrown.
|
||||
* @param {string} message The error message to add to err if it's wrapped.
|
||||
* @return {!goog.db.Error} The error that caused the failure.
|
||||
* @suppress {invalidCasts} The cast from IDBDatabaseException to DOMError
|
||||
* is invalid and will not compile.
|
||||
*/
|
||||
goog.db.Error.fromException = function(ex, message) {
|
||||
if ('name' in ex) {
|
||||
// Chrome 21 and before.
|
||||
return new goog.db.Error(/** @type {!DOMError} */ (ex), message);
|
||||
} else if ('code' in ex) {
|
||||
// Chrome 22+.
|
||||
var errorName = goog.db.Error.getName(ex.code);
|
||||
return new goog.db.Error(
|
||||
/** @type {!DOMError} */ ({name: errorName}), message);
|
||||
} else {
|
||||
return new goog.db.Error(/** @type {!DOMError} */ (
|
||||
{name: goog.db.Error.ErrorName.UNKNOWN_ERR}), message);
|
||||
}
|
||||
};
|
||||
245
float-no-zero/closure-library/closure/goog/db/index.js
Normal file
245
float-no-zero/closure-library/closure/goog/db/index.js
Normal file
@@ -0,0 +1,245 @@
|
||||
// Copyright 2011 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 Wrapper for an IndexedDB index.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.Index');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Cursor');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.debug');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an IDBIndex wrapper object. Indexes are associated with object
|
||||
* stores and provide methods for looking up objects based on their non-key
|
||||
* properties. Should not be created directly, access through the object store
|
||||
* it belongs to.
|
||||
* @see goog.db.ObjectStore#getIndex
|
||||
*
|
||||
* @param {!IDBIndex} index Underlying IDBIndex object.
|
||||
* @constructor
|
||||
*/
|
||||
goog.db.Index = function(index) {
|
||||
/**
|
||||
* Underlying IndexedDB index object.
|
||||
*
|
||||
* @type {!IDBIndex}
|
||||
* @private
|
||||
*/
|
||||
this.index_ = index;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Name of the index.
|
||||
*/
|
||||
goog.db.Index.prototype.getName = function() {
|
||||
return this.index_.name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} Key path of the index.
|
||||
*/
|
||||
goog.db.Index.prototype.getKeyPath = function() {
|
||||
return this.index_.keyPath;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the index enforces that there is only one object
|
||||
* for each unique value it indexes on.
|
||||
*/
|
||||
goog.db.Index.prototype.isUnique = function() {
|
||||
return this.index_.unique;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for get and getKey.
|
||||
*
|
||||
* @param {string} fn Function name to call on the index to get the request.
|
||||
* @param {string} msg Message to give to the error.
|
||||
* @param {IDBKeyType} key The key to look up in the index.
|
||||
* @return {!goog.async.Deferred} The resulting deferred object.
|
||||
* @private
|
||||
*/
|
||||
goog.db.Index.prototype.get_ = function(fn, msg, key) {
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
request = this.index_[fn](key);
|
||||
} catch (err) {
|
||||
msg += ' with key ' + goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback(ev.target.result);
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
msg += ' with key ' + goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fetches a single object from the object store. Even if there are multiple
|
||||
* objects that match the given key, this method will get only one of them.
|
||||
*
|
||||
* @param {IDBKeyType} key Key to look up in the index.
|
||||
* @return {!goog.async.Deferred} The deferred object for the given record.
|
||||
*/
|
||||
goog.db.Index.prototype.get = function(key) {
|
||||
return this.get_('get', 'getting from index ' + this.getName(), key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Looks up a single object from the object store and gives back the key that
|
||||
* it's listed under in the object store. Even if there are multiple records
|
||||
* that match the given key, this method returns the first.
|
||||
*
|
||||
* @param {IDBKeyType} key Key to look up in the index.
|
||||
* @return {!goog.async.Deferred} The deferred key for the record that matches
|
||||
* the key.
|
||||
*/
|
||||
goog.db.Index.prototype.getKey = function(key) {
|
||||
return this.get_('getKey', 'getting key from index ' + this.getName(), key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for getAll and getAllKeys.
|
||||
*
|
||||
* @param {string} fn Function name to call on the index to get the request.
|
||||
* @param {string} msg Message to give to the error.
|
||||
* @param {IDBKeyType=} opt_key Key to look up in the index.
|
||||
* @return {!goog.async.Deferred} The resulting deferred array of objects.
|
||||
* @private
|
||||
*/
|
||||
goog.db.Index.prototype.getAll_ = function(fn, msg, opt_key) {
|
||||
// This is the most common use of IDBKeyRange. If more specific uses of
|
||||
// cursors are needed then a full wrapper should be created.
|
||||
var IDBKeyRange = goog.global.IDBKeyRange || goog.global.webkitIDBKeyRange;
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
if (opt_key) {
|
||||
request = this.index_[fn](IDBKeyRange.only(opt_key));
|
||||
} else {
|
||||
request = this.index_[fn]();
|
||||
}
|
||||
} catch (err) {
|
||||
if (opt_key) {
|
||||
msg += ' for key ' + goog.debug.deepExpose(opt_key);
|
||||
}
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
var result = [];
|
||||
request.onsuccess = function(ev) {
|
||||
var cursor = ev.target.result;
|
||||
if (cursor) {
|
||||
result.push(cursor.value);
|
||||
cursor['continue']();
|
||||
} else {
|
||||
d.callback(result);
|
||||
}
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
if (opt_key) {
|
||||
msg += ' for key ' + goog.debug.deepExpose(opt_key);
|
||||
}
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all indexed objects. If the key is provided, gets all indexed objects
|
||||
* that match the key instead.
|
||||
*
|
||||
* @param {IDBKeyType=} opt_key Key to look up in the index.
|
||||
* @return {!goog.async.Deferred} A deferred array of objects that match the
|
||||
* key.
|
||||
*/
|
||||
goog.db.Index.prototype.getAll = function(opt_key) {
|
||||
return this.getAll_(
|
||||
'openCursor',
|
||||
'getting all from index ' + this.getName(),
|
||||
opt_key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the keys to look up all the indexed objects. If the key is provided,
|
||||
* gets all records for objects that match the key instead.
|
||||
*
|
||||
* @param {IDBKeyType=} opt_key Key to look up in the index.
|
||||
* @return {!goog.async.Deferred} A deferred array of keys for objects that
|
||||
* match the key.
|
||||
*/
|
||||
goog.db.Index.prototype.getAllKeys = function(opt_key) {
|
||||
return this.getAll_(
|
||||
'openKeyCursor',
|
||||
'getting all keys from index ' + this.getName(),
|
||||
opt_key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens a cursor over the specified key range. Returns a cursor object which is
|
||||
* able to iterate over the given range.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <code>
|
||||
* var cursor = index.openCursor(goog.db.Range.bound('a', 'c'));
|
||||
*
|
||||
* var key = goog.events.listen(
|
||||
* cursor, goog.db.Cursor.EventType.NEW_DATA,
|
||||
* function() {
|
||||
* // Do something with data.
|
||||
* cursor.next();
|
||||
* });
|
||||
*
|
||||
* goog.events.listenOnce(
|
||||
* cursor, goog.db.Cursor.EventType.COMPLETE,
|
||||
* function() {
|
||||
* // Clean up listener, and perform a finishing operation on the data.
|
||||
* goog.events.unlistenByKey(key);
|
||||
* });
|
||||
* </code>
|
||||
*
|
||||
* @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
|
||||
* over the whole object store.
|
||||
* @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
|
||||
* moves in a forward direction with duplicates.
|
||||
* @return {!goog.db.Cursor} The cursor.
|
||||
* @throws {goog.db.Error} If there was a problem opening the cursor.
|
||||
*/
|
||||
goog.db.Index.prototype.openCursor = function(opt_range, opt_direction) {
|
||||
return goog.db.Cursor.openCursor(this.index_, opt_range, opt_direction);
|
||||
};
|
||||
337
float-no-zero/closure-library/closure/goog/db/indexeddb.js
Normal file
337
float-no-zero/closure-library/closure/goog/db/indexeddb.js
Normal file
@@ -0,0 +1,337 @@
|
||||
// Copyright 2011 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 Wrapper for an IndexedDB database.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.IndexedDb');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.db.Error.VersionChangeBlockedError');
|
||||
goog.require('goog.db.ObjectStore');
|
||||
goog.require('goog.db.Transaction');
|
||||
goog.require('goog.db.Transaction.TransactionMode');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventHandler');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an IDBDatabase wrapper object. The database object has methods for
|
||||
* setting the version to change the structure of the database and for creating
|
||||
* transactions to get or modify the stored records. Should not be created
|
||||
* directly, call {@link goog.db.openDatabase} to set up the connection.
|
||||
*
|
||||
* @param {!IDBDatabase} db Underlying IndexedDB database object.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.db.IndexedDb = function(db) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Underlying IndexedDB database object.
|
||||
*
|
||||
* @type {!IDBDatabase}
|
||||
* @private
|
||||
*/
|
||||
this.db_ = db;
|
||||
|
||||
/**
|
||||
* Internal event handler that listens to IDBDatabase events.
|
||||
* @type {!goog.events.EventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.eventHandler_ = new goog.events.EventHandler(this);
|
||||
|
||||
this.eventHandler_.listen(
|
||||
this.db_,
|
||||
goog.db.IndexedDb.EventType.ABORT,
|
||||
goog.bind(
|
||||
this.dispatchEvent,
|
||||
this,
|
||||
goog.db.IndexedDb.EventType.ABORT));
|
||||
this.eventHandler_.listen(
|
||||
this.db_,
|
||||
goog.db.IndexedDb.EventType.ERROR,
|
||||
this.dispatchError_);
|
||||
this.eventHandler_.listen(
|
||||
this.db_,
|
||||
goog.db.IndexedDb.EventType.VERSION_CHANGE,
|
||||
this.dispatchVersionChange_);
|
||||
};
|
||||
goog.inherits(goog.db.IndexedDb, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* True iff the database connection is open.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.open_ = true;
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches a wrapped error event based on the given event.
|
||||
*
|
||||
* @param {Event} ev The error event given to the underlying IDBDatabase.
|
||||
* @private
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.dispatchError_ = function(ev) {
|
||||
this.dispatchEvent({
|
||||
type: goog.db.IndexedDb.EventType.ERROR,
|
||||
errorCode: /** @type {IDBRequest} */ (ev.target).errorCode
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches a wrapped version change event based on the given event.
|
||||
*
|
||||
* @param {Event} ev The version change event given to the underlying
|
||||
* IDBDatabase.
|
||||
* @private
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.dispatchVersionChange_ = function(ev) {
|
||||
this.dispatchEvent(new goog.db.IndexedDb.VersionChangeEvent(
|
||||
ev.oldVersion, ev.newVersion));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Closes the database connection. Metadata queries can still be made after this
|
||||
* method is called, but otherwise this wrapper should not be used further.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.close = function() {
|
||||
if (this.open_) {
|
||||
this.db_.close();
|
||||
this.open_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether a connection is open and the database can be used.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.isOpen = function() {
|
||||
return this.open_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The name of this database.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.getName = function() {
|
||||
return this.db_.name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The current database version.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.getVersion = function() {
|
||||
return this.db_.version;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {DOMStringList} List of object stores in this database.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.getObjectStoreNames = function() {
|
||||
return this.db_.objectStoreNames;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object store in this database. Can only be called inside a
|
||||
* {@link goog.db.UpgradeNeededCallback} or the callback for the Deferred
|
||||
* returned from #setVersion.
|
||||
*
|
||||
* @param {string} name Name for the new object store.
|
||||
* @param {Object=} opt_params Options object. The available options are:
|
||||
* keyPath, which is a string and determines what object attribute
|
||||
* to use as the key when storing objects in this object store; and
|
||||
* autoIncrement, which is a boolean, which defaults to false and determines
|
||||
* whether the object store should automatically generate keys for stored
|
||||
* objects. If keyPath is not provided and autoIncrement is false, then all
|
||||
* insert operations must provide a key as a parameter.
|
||||
* @return {goog.db.ObjectStore} The newly created object store.
|
||||
* @throws {goog.db.Error} If there's a problem creating the object store.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.createObjectStore = function(name, opt_params) {
|
||||
try {
|
||||
return new goog.db.ObjectStore(this.db_.createObjectStore(
|
||||
name, opt_params));
|
||||
} catch (ex) {
|
||||
throw goog.db.Error.fromException(ex, 'creating object store ' + name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an object store. Can only be called inside a
|
||||
* {@link goog.db.UpgradeNeededCallback} or the callback for the Deferred
|
||||
* returned from #setVersion.
|
||||
*
|
||||
* @param {string} name Name of the object store to delete.
|
||||
* @throws {goog.db.Error} If there's a problem deleting the object store.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.deleteObjectStore = function(name) {
|
||||
try {
|
||||
this.db_.deleteObjectStore(name);
|
||||
} catch (ex) {
|
||||
throw goog.db.Error.fromException(ex, 'deleting object store ' + name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates the version of the database and returns a Deferred transaction.
|
||||
* The database's structure can be changed inside this Deferred's callback, but
|
||||
* nowhere else. This means adding or deleting object stores, and adding or
|
||||
* deleting indexes. The version change will not succeed unless there are no
|
||||
* other connections active for this database anywhere. A new database
|
||||
* connection should be opened after the version change is finished to pick
|
||||
* up changes.
|
||||
*
|
||||
* This is deprecated, and only supported on Chrome prior to version 25. New
|
||||
* applications should use the version parameter to {@link goog.db.openDatabase}
|
||||
* instead.
|
||||
*
|
||||
* @param {string} version The new version of the database.
|
||||
* @return {!goog.async.Deferred} The deferred transaction for changing the
|
||||
* version.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.setVersion = function(version) {
|
||||
var self = this;
|
||||
var d = new goog.async.Deferred();
|
||||
var request = this.db_.setVersion(version);
|
||||
request.onsuccess = function(ev) {
|
||||
// the transaction is in the result field (the transaction field is null
|
||||
// for version change requests)
|
||||
d.callback(new goog.db.Transaction(ev.target.result, self));
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
// If a version change is blocked, onerror and onblocked may both fire.
|
||||
// Check d.hasFired() to avoid an AlreadyCalledError.
|
||||
if (!d.hasFired()) {
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, 'setting version'));
|
||||
}
|
||||
};
|
||||
request.onblocked = function(ev) {
|
||||
// If a version change is blocked, onerror and onblocked may both fire.
|
||||
// Check d.hasFired() to avoid an AlreadyCalledError.
|
||||
if (!d.hasFired()) {
|
||||
d.errback(new goog.db.Error.VersionChangeBlockedError());
|
||||
}
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new transaction.
|
||||
*
|
||||
* @param {!Array.<string>} storeNames A list of strings that contains the
|
||||
* transaction's scope, the object stores that this transaction can operate
|
||||
* on.
|
||||
* @param {goog.db.Transaction.TransactionMode=} opt_mode The mode of the
|
||||
* transaction. If not present, the default is READ_ONLY. For VERSION_CHANGE
|
||||
* transactions call {@link goog.db.IndexedDB#setVersion} instead.
|
||||
* @return {!goog.db.Transaction} The wrapper for the newly created transaction.
|
||||
* @throws {goog.db.Error} If there's a problem creating the transaction.
|
||||
*/
|
||||
goog.db.IndexedDb.prototype.createTransaction = function(storeNames, opt_mode) {
|
||||
try {
|
||||
// IndexedDB on Chrome 22+ requires that opt_mode not be passed rather than
|
||||
// be explicitly passed as undefined.
|
||||
var transaction = opt_mode ?
|
||||
this.db_.transaction(storeNames, opt_mode) :
|
||||
this.db_.transaction(storeNames);
|
||||
return new goog.db.Transaction(transaction, this);
|
||||
} catch (ex) {
|
||||
throw goog.db.Error.fromException(ex, 'creating transaction');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.db.IndexedDb.prototype.disposeInternal = function() {
|
||||
goog.base(this, 'disposeInternal');
|
||||
this.eventHandler_.dispose();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Event types fired by a database.
|
||||
*
|
||||
* @enum {string} The event types for the web socket.
|
||||
*/
|
||||
goog.db.IndexedDb.EventType = {
|
||||
|
||||
/**
|
||||
* Fired when a transaction is aborted and the event bubbles to its database.
|
||||
*/
|
||||
ABORT: 'abort',
|
||||
|
||||
/**
|
||||
* Fired when a transaction has an error.
|
||||
*/
|
||||
ERROR: 'error',
|
||||
|
||||
/**
|
||||
* Fired when someone (possibly in another window) is attempting to modify the
|
||||
* structure of the database. Since a change can only be made when there are
|
||||
* no active database connections, this usually means that the database should
|
||||
* be closed so that the other client can make its changes.
|
||||
*/
|
||||
VERSION_CHANGE: 'versionchange'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Event representing a (possibly attempted) change in the database structure.
|
||||
*
|
||||
* At time of writing, no Chrome versions support oldVersion or newVersion. See
|
||||
* http://crbug.com/153122.
|
||||
*
|
||||
* @param {number} oldVersion The previous version of the database.
|
||||
* @param {number} newVersion The version the database is being or has been
|
||||
* updated to.
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
*/
|
||||
goog.db.IndexedDb.VersionChangeEvent = function(oldVersion, newVersion) {
|
||||
goog.base(this, goog.db.IndexedDb.EventType.VERSION_CHANGE);
|
||||
|
||||
/**
|
||||
* The previous version of the database.
|
||||
* @type {number}
|
||||
*/
|
||||
this.oldVersion = oldVersion;
|
||||
|
||||
/**
|
||||
* The version the database is being or has been updated to.
|
||||
* @type {number}
|
||||
*/
|
||||
this.newVersion = newVersion;
|
||||
};
|
||||
goog.inherits(goog.db.IndexedDb.VersionChangeEvent, goog.events.Event);
|
||||
117
float-no-zero/closure-library/closure/goog/db/keyrange.js
Normal file
117
float-no-zero/closure-library/closure/goog/db/keyrange.js
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2012 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 Wrapper for a IndexedDB key range.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.KeyRange');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new IDBKeyRange wrapper object. Should not be created directly,
|
||||
* instead use one of the static factory methods. For example:
|
||||
* @see goog.db.KeyRange.bound
|
||||
* @see goog.db.KeyRange.lowerBound
|
||||
*
|
||||
* @param {!IDBKeyRange} range Underlying IDBKeyRange object.
|
||||
* @constructor
|
||||
*/
|
||||
goog.db.KeyRange = function(range) {
|
||||
/**
|
||||
* Underlying IDBKeyRange object.
|
||||
*
|
||||
* @type {!IDBKeyRange}
|
||||
* @private
|
||||
*/
|
||||
this.range_ = range;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The IDBKeyRange.
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
goog.db.KeyRange.IDB_KEY_RANGE_ = goog.global.IDBKeyRange ||
|
||||
goog.global.webkitIDBKeyRange;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new key range for a single value.
|
||||
*
|
||||
* @param {IDBKeyType} key The single value in the range.
|
||||
* @return {!goog.db.KeyRange} The key range.
|
||||
*/
|
||||
goog.db.KeyRange.only = function(key) {
|
||||
return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.only(key));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a key range with upper and lower bounds.
|
||||
*
|
||||
* @param {IDBKeyType} lower The value of the lower bound.
|
||||
* @param {IDBKeyType} upper The value of the upper bound.
|
||||
* @param {boolean=} opt_lowerOpen If true, the range excludes the lower bound
|
||||
* value.
|
||||
* @param {boolean=} opt_upperOpen If true, the range excludes the upper bound
|
||||
* value.
|
||||
* @return {!goog.db.KeyRange} The key range.
|
||||
*/
|
||||
goog.db.KeyRange.bound = function(lower, upper, opt_lowerOpen, opt_upperOpen) {
|
||||
return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.bound(
|
||||
lower, upper, opt_lowerOpen, opt_upperOpen));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a key range with a lower bound only, finishes at the last record.
|
||||
*
|
||||
* @param {IDBKeyType} lower The value of the lower bound.
|
||||
* @param {boolean=} opt_lowerOpen If true, the range excludes the lower bound
|
||||
* value.
|
||||
* @return {!goog.db.KeyRange} The key range.
|
||||
*/
|
||||
goog.db.KeyRange.lowerBound = function(lower, opt_lowerOpen) {
|
||||
return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.lowerBound(
|
||||
lower, opt_lowerOpen));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a key range with a upper bound only, starts at the first record.
|
||||
*
|
||||
* @param {IDBKeyType} upper The value of the upper bound.
|
||||
* @param {boolean=} opt_upperOpen If true, the range excludes the upper bound
|
||||
* value.
|
||||
* @return {!goog.db.KeyRange} The key range.
|
||||
*/
|
||||
goog.db.KeyRange.upperBound = function(upper, opt_upperOpen) {
|
||||
return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.upperBound(
|
||||
upper, opt_upperOpen));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns underlying key range object. This is used in ObjectStore's openCursor
|
||||
* and count methods.
|
||||
* @return {!IDBKeyRange}
|
||||
*/
|
||||
goog.db.KeyRange.prototype.range = function() {
|
||||
return this.range_;
|
||||
};
|
||||
399
float-no-zero/closure-library/closure/goog/db/objectstore.js
Normal file
399
float-no-zero/closure-library/closure/goog/db/objectstore.js
Normal file
@@ -0,0 +1,399 @@
|
||||
// Copyright 2011 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 Wrapper for an IndexedDB object store.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.ObjectStore');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Cursor');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.db.Index');
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.events');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an IDBObjectStore wrapper object. Object stores have methods for
|
||||
* storing and retrieving records, and are accessed through a transaction
|
||||
* object. They also have methods for creating indexes associated with the
|
||||
* object store. They can only be created when setting the version of the
|
||||
* database. Should not be created directly, access object stores through
|
||||
* transactions.
|
||||
* @see goog.db.IndexedDb#setVersion
|
||||
* @see goog.db.Transaction#objectStore
|
||||
*
|
||||
* @param {!IDBObjectStore} store The backing IndexedDb object.
|
||||
* @constructor
|
||||
*
|
||||
* TODO(user): revisit msg in exception and errors in this class. In newer
|
||||
* Chrome (v22+) the error/request come with a DOM error string that is
|
||||
* already very descriptive.
|
||||
*/
|
||||
goog.db.ObjectStore = function(store) {
|
||||
/**
|
||||
* Underlying IndexedDB object store object.
|
||||
*
|
||||
* @type {!IDBObjectStore}
|
||||
* @private
|
||||
*/
|
||||
this.store_ = store;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The name of the object store.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.getName = function() {
|
||||
return this.store_.name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for put and add.
|
||||
*
|
||||
* @param {string} fn Function name to call on the object store.
|
||||
* @param {string} msg Message to give to the error.
|
||||
* @param {*} value Value to insert into the object store.
|
||||
* @param {IDBKeyType=} opt_key The key to use.
|
||||
* @return {!goog.async.Deferred} The resulting deferred request.
|
||||
* @private
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.insert_ = function(fn, msg, value, opt_key) {
|
||||
// TODO(user): refactor wrapping an IndexedDB request in a Deferred by
|
||||
// creating a higher-level abstraction for it (mostly affects here and
|
||||
// goog.db.Index)
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
// put or add with (value, undefined) throws an error, so we need to check
|
||||
// for undefined ourselves
|
||||
if (opt_key) {
|
||||
request = this.store_[fn](value, opt_key);
|
||||
} else {
|
||||
request = this.store_[fn](value);
|
||||
}
|
||||
} catch (ex) {
|
||||
msg += goog.debug.deepExpose(value);
|
||||
if (opt_key) {
|
||||
msg += ', with key ' + goog.debug.deepExpose(opt_key);
|
||||
}
|
||||
d.errback(goog.db.Error.fromException(ex, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
var self = this;
|
||||
request.onerror = function(ev) {
|
||||
msg += goog.debug.deepExpose(value);
|
||||
if (opt_key) {
|
||||
msg += ', with key ' + goog.debug.deepExpose(opt_key);
|
||||
}
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an object to the object store. Replaces existing objects with the
|
||||
* same key.
|
||||
*
|
||||
* @param {*} value The value to put.
|
||||
* @param {IDBKeyType=} opt_key The key to use. Cannot be used if the
|
||||
* keyPath was specified for the object store. If the keyPath was not
|
||||
* specified but autoIncrement was not enabled, it must be used.
|
||||
* @return {!goog.async.Deferred} The deferred put request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.put = function(value, opt_key) {
|
||||
return this.insert_(
|
||||
'put',
|
||||
'putting into ' + this.getName() + ' with value',
|
||||
value,
|
||||
opt_key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds an object to the object store. Requires that there is no object with
|
||||
* the same key already present.
|
||||
*
|
||||
* @param {*} value The value to add.
|
||||
* @param {IDBKeyType=} opt_key The key to use. Cannot be used if the
|
||||
* keyPath was specified for the object store. If the keyPath was not
|
||||
* specified but autoIncrement was not enabled, it must be used.
|
||||
* @return {!goog.async.Deferred} The deferred add request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.add = function(value, opt_key) {
|
||||
return this.insert_(
|
||||
'add',
|
||||
'adding into ' + this.getName() + ' with value ',
|
||||
value,
|
||||
opt_key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes an object from the store. No-op if there is no object present with
|
||||
* the given key.
|
||||
*
|
||||
* @param {IDBKeyType} key The key to remove objects under.
|
||||
* @return {!goog.async.Deferred} The deferred remove request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.remove = function(key) {
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
request = this.store_['delete'](key);
|
||||
} catch (err) {
|
||||
var msg = 'removing from ' + this.getName() + ' with key ' +
|
||||
goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
var self = this;
|
||||
request.onerror = function(ev) {
|
||||
var msg = 'removing from ' + self.getName() + ' with key ' +
|
||||
goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets an object from the store. If no object is present with that key
|
||||
* the result is {@code undefined}.
|
||||
*
|
||||
* @param {IDBKeyType} key The key to look up.
|
||||
* @return {!goog.async.Deferred} The deferred get request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.get = function(key) {
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
request = this.store_.get(key);
|
||||
} catch (err) {
|
||||
var msg = 'getting from ' + this.getName() + ' with key ' +
|
||||
goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback(ev.target.result);
|
||||
};
|
||||
var self = this;
|
||||
request.onerror = function(ev) {
|
||||
var msg = 'getting from ' + self.getName() + ' with key ' +
|
||||
goog.debug.deepExpose(key);
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all objects from the store and returns them as an array.
|
||||
*
|
||||
* @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
|
||||
* over the whole object store.
|
||||
* @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
|
||||
* moves in a forward direction with duplicates.
|
||||
* @return {!goog.async.Deferred} The deferred getAll request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.getAll = function(opt_range, opt_direction) {
|
||||
var d = new goog.async.Deferred();
|
||||
var cursor;
|
||||
try {
|
||||
cursor = this.openCursor(opt_range, opt_direction);
|
||||
} catch (err) {
|
||||
d.errback(err);
|
||||
return d;
|
||||
}
|
||||
|
||||
var result = [];
|
||||
var key = goog.events.listen(
|
||||
cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
|
||||
result.push(cursor.getValue());
|
||||
cursor.next();
|
||||
});
|
||||
|
||||
goog.events.listenOnce(cursor, [
|
||||
goog.db.Cursor.EventType.ERROR,
|
||||
goog.db.Cursor.EventType.COMPLETE
|
||||
], function(evt) {
|
||||
cursor.dispose();
|
||||
if (evt.type == goog.db.Cursor.EventType.COMPLETE) {
|
||||
d.callback(result);
|
||||
} else {
|
||||
d.errback();
|
||||
}
|
||||
});
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens a cursor over the specified key range. Returns a cursor object which is
|
||||
* able to iterate over the given range.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <code>
|
||||
* var cursor = objectStore.openCursor(goog.db.Range.bound('a', 'c'));
|
||||
*
|
||||
* var key = goog.events.listen(
|
||||
* cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
|
||||
* // Do something with data.
|
||||
* cursor.next();
|
||||
* });
|
||||
*
|
||||
* goog.events.listenOnce(
|
||||
* cursor, goog.db.Cursor.EventType.COMPLETE, function() {
|
||||
* // Clean up listener, and perform a finishing operation on the data.
|
||||
* goog.events.unlistenByKey(key);
|
||||
* });
|
||||
* </code>
|
||||
*
|
||||
* @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
|
||||
* over the whole object store.
|
||||
* @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
|
||||
* moves in a forward direction with duplicates.
|
||||
* @return {!goog.db.Cursor} The cursor.
|
||||
* @throws {goog.db.Error} If there was a problem opening the cursor.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.openCursor = function(opt_range, opt_direction) {
|
||||
return goog.db.Cursor.openCursor(this.store_, opt_range, opt_direction);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all objects from the store.
|
||||
*
|
||||
* @return {!goog.async.Deferred} The deferred clear request.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.clear = function() {
|
||||
var msg = 'clearing store ' + this.getName();
|
||||
var d = new goog.async.Deferred();
|
||||
var request;
|
||||
try {
|
||||
request = this.store_.clear();
|
||||
} catch (err) {
|
||||
d.errback(goog.db.Error.fromException(err, msg));
|
||||
return d;
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback();
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, msg));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an index in this object store. Can only be called inside the callback
|
||||
* for the Deferred returned from goog.db.IndexedDb#setVersion.
|
||||
*
|
||||
* @param {string} name Name of the index to create.
|
||||
* @param {string} keyPath Attribute to index on.
|
||||
* @param {!Object=} opt_parameters Optional parameters object. The only
|
||||
* available option is unique, which defaults to false. If unique is true,
|
||||
* the index will enforce that there is only ever one object in the object
|
||||
* store for each unique value it indexes on.
|
||||
* @return {goog.db.Index} The newly created, wrapped index.
|
||||
* @throws {goog.db.Error} In case of an error creating the index.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.createIndex = function(
|
||||
name, keyPath, opt_parameters) {
|
||||
try {
|
||||
return new goog.db.Index(this.store_.createIndex(
|
||||
name, keyPath, opt_parameters));
|
||||
} catch (ex) {
|
||||
var msg = 'creating new index ' + name + ' with key path ' + keyPath;
|
||||
throw goog.db.Error.fromException(ex, msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets an index.
|
||||
*
|
||||
* @param {string} name Name of the index to fetch.
|
||||
* @return {goog.db.Index} The requested wrapped index.
|
||||
* @throws {goog.db.Error} In case of an error getting the index.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.getIndex = function(name) {
|
||||
try {
|
||||
return new goog.db.Index(this.store_.index(name));
|
||||
} catch (ex) {
|
||||
var msg = 'getting index ' + name;
|
||||
throw goog.db.Error.fromException(ex, msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an index from the object store. Can only be called inside the
|
||||
* callback for the Deferred returned from goog.db.IndexedDb#setVersion.
|
||||
*
|
||||
* @param {string} name Name of the index to delete.
|
||||
* @throws {goog.db.Error} In case of an error deleting the index.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.deleteIndex = function(name) {
|
||||
try {
|
||||
this.store_.deleteIndex(name);
|
||||
} catch (ex) {
|
||||
var msg = 'deleting index ' + name;
|
||||
throw goog.db.Error.fromException(ex, msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets number of records within a key range.
|
||||
*
|
||||
* @param {!goog.db.KeyRange=} opt_range The key range. If undefined, this will
|
||||
* count all records in the object store.
|
||||
* @return {!goog.async.Deferred} The deferred number of records.
|
||||
*/
|
||||
goog.db.ObjectStore.prototype.count = function(opt_range) {
|
||||
var request;
|
||||
var d = new goog.async.Deferred();
|
||||
|
||||
try {
|
||||
var range = opt_range ? opt_range.range() : null;
|
||||
request = this.store_.count(range);
|
||||
} catch (ex) {
|
||||
d.errback(goog.db.Error.fromException(ex, this.getName()));
|
||||
}
|
||||
request.onsuccess = function(ev) {
|
||||
d.callback(ev.target.result);
|
||||
};
|
||||
request.onerror = function(ev) {
|
||||
d.errback(goog.db.Error.fromRequest(ev.target, this.getName()));
|
||||
};
|
||||
return d;
|
||||
};
|
||||
|
||||
218
float-no-zero/closure-library/closure/goog/db/transaction.js
Normal file
218
float-no-zero/closure-library/closure/goog/db/transaction.js
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright 2011 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 Wrapper for an IndexedDB transaction.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.db.Transaction');
|
||||
goog.provide('goog.db.Transaction.TransactionMode');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.db.Error');
|
||||
goog.require('goog.db.ObjectStore');
|
||||
goog.require('goog.events.EventHandler');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new transaction. Transactions contain methods for accessing object
|
||||
* stores and are created from the database object. Should not be created
|
||||
* directly, open a database and call createTransaction on it.
|
||||
* @see goog.db.IndexedDb#createTransaction
|
||||
*
|
||||
* @param {!IDBTransaction} tx IndexedDB transaction to back this wrapper.
|
||||
* @param {!goog.db.IndexedDb} db The database that this transaction modifies.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.db.Transaction = function(tx, db) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Underlying IndexedDB transaction object.
|
||||
*
|
||||
* @type {!IDBTransaction}
|
||||
* @private
|
||||
*/
|
||||
this.tx_ = tx;
|
||||
|
||||
/**
|
||||
* The database that this transaction modifies.
|
||||
*
|
||||
* @type {!goog.db.IndexedDb}
|
||||
* @private
|
||||
*/
|
||||
this.db_ = db;
|
||||
|
||||
/**
|
||||
* Event handler for this transaction.
|
||||
*
|
||||
* @type {!goog.events.EventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.eventHandler_ = new goog.events.EventHandler(this);
|
||||
|
||||
// TODO(user): remove these casts once the externs file is updated to
|
||||
// correctly reflect that IDBTransaction extends EventTarget
|
||||
this.eventHandler_.listen(
|
||||
/** @type {EventTarget} */ (this.tx_),
|
||||
'complete',
|
||||
goog.bind(
|
||||
this.dispatchEvent,
|
||||
this,
|
||||
goog.db.Transaction.EventTypes.COMPLETE));
|
||||
this.eventHandler_.listen(
|
||||
/** @type {EventTarget} */ (this.tx_),
|
||||
'abort',
|
||||
goog.bind(
|
||||
this.dispatchEvent,
|
||||
this,
|
||||
goog.db.Transaction.EventTypes.ABORT));
|
||||
this.eventHandler_.listen(
|
||||
/** @type {EventTarget} */ (this.tx_),
|
||||
'error',
|
||||
this.dispatchError_);
|
||||
};
|
||||
goog.inherits(goog.db.Transaction, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches an error event based on the given event, wrapping the error
|
||||
* if necessary.
|
||||
*
|
||||
* @param {Event} ev The error event given to the underlying IDBTransaction.
|
||||
* @private
|
||||
*/
|
||||
goog.db.Transaction.prototype.dispatchError_ = function(ev) {
|
||||
if (ev.target instanceof goog.db.Error) {
|
||||
this.dispatchEvent({
|
||||
type: goog.db.Transaction.EventTypes.ERROR,
|
||||
target: ev.target
|
||||
});
|
||||
} else {
|
||||
this.dispatchEvent({
|
||||
type: goog.db.Transaction.EventTypes.ERROR,
|
||||
target: goog.db.Error.fromRequest(
|
||||
/** @type {!IDBRequest} */ (ev.target), 'in transaction')
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Event types the Transaction can dispatch. COMPLETE events are dispatched
|
||||
* when the transaction is committed. If a transaction is aborted it dispatches
|
||||
* both an ABORT event and an ERROR event with the ABORT_ERR code. Error events
|
||||
* are dispatched on any error.
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.db.Transaction.EventTypes = {
|
||||
COMPLETE: 'complete',
|
||||
ABORT: 'abort',
|
||||
ERROR: 'error'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.db.Transaction.TransactionMode} The transaction's mode.
|
||||
*/
|
||||
goog.db.Transaction.prototype.getMode = function() {
|
||||
return /** @type {goog.db.Transaction.TransactionMode} */ (this.tx_.mode);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.db.IndexedDb} The database that this transaction modifies.
|
||||
*/
|
||||
goog.db.Transaction.prototype.getDatabase = function() {
|
||||
return this.db_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens an object store to do operations on in this transaction. The requested
|
||||
* object store must be one that is in this transaction's scope.
|
||||
* @see goog.db.IndexedDb#createTransaction
|
||||
*
|
||||
* @param {string} name The name of the requested object store.
|
||||
* @return {!goog.db.ObjectStore} The wrapped object store.
|
||||
* @throws {goog.db.Error} In case of error getting the object store.
|
||||
*/
|
||||
goog.db.Transaction.prototype.objectStore = function(name) {
|
||||
try {
|
||||
return new goog.db.ObjectStore(this.tx_.objectStore(name));
|
||||
} catch (ex) {
|
||||
throw goog.db.Error.fromException(ex, 'getting object store ' + name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.async.Deferred} A deferred that will fire once the
|
||||
* transaction is complete. It fires the errback chain if an error occurs
|
||||
* in the transaction, or if it is aborted.
|
||||
*/
|
||||
goog.db.Transaction.prototype.wait = function() {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(
|
||||
this, goog.db.Transaction.EventTypes.COMPLETE, goog.bind(d.callback, d));
|
||||
goog.events.listenOnce(
|
||||
this, goog.db.Transaction.EventTypes.ABORT, function() {
|
||||
d.errback(new goog.db.Error(goog.db.Error.ErrorCode.ABORT_ERR,
|
||||
'waiting for transaction to complete'));
|
||||
});
|
||||
goog.events.listenOnce(
|
||||
this, goog.db.Transaction.EventTypes.ERROR, function(e) {
|
||||
d.errback(e.target);
|
||||
});
|
||||
|
||||
var db = this.getDatabase();
|
||||
return d.addCallback(function() {
|
||||
return db;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Aborts this transaction. No pending operations will be applied to the
|
||||
* database. Dispatches an ABORT event.
|
||||
*/
|
||||
goog.db.Transaction.prototype.abort = function() {
|
||||
this.tx_.abort();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.db.Transaction.prototype.disposeInternal = function() {
|
||||
goog.base(this, 'disposeInternal');
|
||||
this.eventHandler_.dispose();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The three possible transaction modes.
|
||||
* @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBTransaction
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.db.Transaction.TransactionMode = {
|
||||
READ_ONLY: 'readonly',
|
||||
READ_WRITE: 'readwrite',
|
||||
VERSION_CHANGE: 'versionchange'
|
||||
};
|
||||
207
float-no-zero/closure-library/closure/goog/debug/console.js
Normal file
207
float-no-zero/closure-library/closure/goog/debug/console.js
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright 2006 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 Simple logger that logs to the window console if available.
|
||||
*
|
||||
* Has an autoInstall option which can be put into initialization code, which
|
||||
* will start logging if "Debug=true" is in document.location.href
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.Console');
|
||||
|
||||
goog.require('goog.debug.LogManager');
|
||||
goog.require('goog.debug.Logger.Level');
|
||||
goog.require('goog.debug.TextFormatter');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create and install a log handler that logs to window.console if available
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.Console = function() {
|
||||
this.publishHandler_ = goog.bind(this.addLogRecord, this);
|
||||
|
||||
/**
|
||||
* Formatter for formatted output.
|
||||
* @type {!goog.debug.TextFormatter}
|
||||
* @private
|
||||
*/
|
||||
this.formatter_ = new goog.debug.TextFormatter();
|
||||
this.formatter_.showAbsoluteTime = false;
|
||||
this.formatter_.showExceptionText = false;
|
||||
|
||||
this.isCapturing_ = false;
|
||||
this.logBuffer_ = '';
|
||||
|
||||
/**
|
||||
* Loggers that we shouldn't output.
|
||||
* @type {!Object.<boolean>}
|
||||
* @private
|
||||
*/
|
||||
this.filteredLoggers_ = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the text formatter used by this console
|
||||
* @return {!goog.debug.TextFormatter} The text formatter.
|
||||
*/
|
||||
goog.debug.Console.prototype.getFormatter = function() {
|
||||
return this.formatter_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether we are currently capturing logger output.
|
||||
* @param {boolean} capturing Whether to capture logger output.
|
||||
*/
|
||||
goog.debug.Console.prototype.setCapturing = function(capturing) {
|
||||
if (capturing == this.isCapturing_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// attach or detach handler from the root logger
|
||||
var rootLogger = goog.debug.LogManager.getRoot();
|
||||
if (capturing) {
|
||||
rootLogger.addHandler(this.publishHandler_);
|
||||
} else {
|
||||
rootLogger.removeHandler(this.publishHandler_);
|
||||
this.logBuffer = '';
|
||||
}
|
||||
this.isCapturing_ = capturing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a log record.
|
||||
* @param {goog.debug.LogRecord} logRecord The log entry.
|
||||
*/
|
||||
goog.debug.Console.prototype.addLogRecord = function(logRecord) {
|
||||
|
||||
// Check to see if the log record is filtered or not.
|
||||
if (this.filteredLoggers_[logRecord.getLoggerName()]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var record = this.formatter_.formatRecord(logRecord);
|
||||
var console = goog.debug.Console.console_;
|
||||
if (console) {
|
||||
switch (logRecord.getLevel()) {
|
||||
case goog.debug.Logger.Level.SHOUT:
|
||||
goog.debug.Console.logToConsole_(console, 'info', record);
|
||||
break;
|
||||
case goog.debug.Logger.Level.SEVERE:
|
||||
goog.debug.Console.logToConsole_(console, 'error', record);
|
||||
break;
|
||||
case goog.debug.Logger.Level.WARNING:
|
||||
goog.debug.Console.logToConsole_(console, 'warn', record);
|
||||
break;
|
||||
default:
|
||||
goog.debug.Console.logToConsole_(console, 'debug', record);
|
||||
break;
|
||||
}
|
||||
} else if (window.opera) {
|
||||
// window.opera.postError is considered an undefined property reference
|
||||
// by JSCompiler, so it has to be referenced using array notation instead.
|
||||
window.opera['postError'](record);
|
||||
} else {
|
||||
this.logBuffer_ += record;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a logger name to be filtered.
|
||||
* @param {string} loggerName the logger name to add.
|
||||
*/
|
||||
goog.debug.Console.prototype.addFilter = function(loggerName) {
|
||||
this.filteredLoggers_[loggerName] = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a logger name to be filtered.
|
||||
* @param {string} loggerName the logger name to remove.
|
||||
*/
|
||||
goog.debug.Console.prototype.removeFilter = function(loggerName) {
|
||||
delete this.filteredLoggers_[loggerName];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Global console logger instance
|
||||
* @type {goog.debug.Console}
|
||||
*/
|
||||
goog.debug.Console.instance = null;
|
||||
|
||||
|
||||
/**
|
||||
* The console to which to log. This is a property so it can be mocked out in
|
||||
* this unit test for goog.debug.Console.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Console.console_ = window.console;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the console to which to log.
|
||||
* @param {!Object} console The console to which to log.
|
||||
*/
|
||||
goog.debug.Console.setConsole = function(console) {
|
||||
goog.debug.Console.console_ = console;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install the console and start capturing if "Debug=true" is in the page URL
|
||||
*/
|
||||
goog.debug.Console.autoInstall = function() {
|
||||
if (!goog.debug.Console.instance) {
|
||||
goog.debug.Console.instance = new goog.debug.Console();
|
||||
}
|
||||
|
||||
if (window.location.href.indexOf('Debug=true') != -1) {
|
||||
goog.debug.Console.instance.setCapturing(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Show an alert with all of the captured debug information.
|
||||
* Information is only captured if console is not available
|
||||
*/
|
||||
goog.debug.Console.show = function() {
|
||||
alert(goog.debug.Console.instance.logBuffer_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs the record to the console using the given function. If the function is
|
||||
* not available on the console object, the log function is used instead.
|
||||
* @param {!Object} console The console object.
|
||||
* @param {string} fnName The name of the function to use.
|
||||
* @param {string} record The record to log.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Console.logToConsole_ = function(console, fnName, record) {
|
||||
if (console[fnName]) {
|
||||
console[fnName](record);
|
||||
} else {
|
||||
console.log(record);
|
||||
}
|
||||
};
|
||||
501
float-no-zero/closure-library/closure/goog/debug/debug.js
Normal file
501
float-no-zero/closure-library/closure/goog/debug/debug.js
Normal file
@@ -0,0 +1,501 @@
|
||||
// Copyright 2006 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 Logging and debugging utilities.
|
||||
*
|
||||
* @see ../demos/debug.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.structs.Set');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/** @define {boolean} Whether logging should be enabled. */
|
||||
goog.define('goog.debug.LOGGING_ENABLED', goog.DEBUG);
|
||||
|
||||
|
||||
/**
|
||||
* Catches onerror events fired by windows and similar objects.
|
||||
* @param {function(Object)} logFunc The function to call with the error
|
||||
* information.
|
||||
* @param {boolean=} opt_cancel Whether to stop the error from reaching the
|
||||
* browser.
|
||||
* @param {Object=} opt_target Object that fires onerror events.
|
||||
*/
|
||||
goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
|
||||
var target = opt_target || goog.global;
|
||||
var oldErrorHandler = target.onerror;
|
||||
var retVal = !!opt_cancel;
|
||||
|
||||
// Chrome interprets onerror return value backwards (http://crbug.com/92062)
|
||||
// until it was fixed in webkit revision r94061 (Webkit 535.3). This
|
||||
// workaround still needs to be skipped in Safari after the webkit change
|
||||
// gets pushed out in Safari.
|
||||
// See https://bugs.webkit.org/show_bug.cgi?id=67119
|
||||
if (goog.userAgent.WEBKIT &&
|
||||
!goog.userAgent.isVersionOrHigher('535.3')) {
|
||||
retVal = !retVal;
|
||||
}
|
||||
target.onerror = function(message, url, line) {
|
||||
if (oldErrorHandler) {
|
||||
oldErrorHandler(message, url, line);
|
||||
}
|
||||
logFunc({
|
||||
message: message,
|
||||
fileName: url,
|
||||
line: line
|
||||
});
|
||||
return retVal;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string representing an object and all its properties.
|
||||
* @param {Object|null|undefined} obj Object to expose.
|
||||
* @param {boolean=} opt_showFn Show the functions as well as the properties,
|
||||
* default is false.
|
||||
* @return {string} The string representation of {@code obj}.
|
||||
*/
|
||||
goog.debug.expose = function(obj, opt_showFn) {
|
||||
if (typeof obj == 'undefined') {
|
||||
return 'undefined';
|
||||
}
|
||||
if (obj == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
var str = [];
|
||||
|
||||
for (var x in obj) {
|
||||
if (!opt_showFn && goog.isFunction(obj[x])) {
|
||||
continue;
|
||||
}
|
||||
var s = x + ' = ';
|
||||
/** @preserveTry */
|
||||
try {
|
||||
s += obj[x];
|
||||
} catch (e) {
|
||||
s += '*** ' + e + ' ***';
|
||||
}
|
||||
str.push(s);
|
||||
}
|
||||
return str.join('\n');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a string representing a given primitive or object, and for an
|
||||
* object, all its properties and nested objects. WARNING: If an object is
|
||||
* given, it and all its nested objects will be modified. To detect reference
|
||||
* cycles, this method identifies objects using goog.getUid() which mutates the
|
||||
* object.
|
||||
* @param {*} obj Object to expose.
|
||||
* @param {boolean=} opt_showFn Also show properties that are functions (by
|
||||
* default, functions are omitted).
|
||||
* @return {string} A string representation of {@code obj}.
|
||||
*/
|
||||
goog.debug.deepExpose = function(obj, opt_showFn) {
|
||||
var previous = new goog.structs.Set();
|
||||
var str = [];
|
||||
|
||||
var helper = function(obj, space) {
|
||||
var nestspace = space + ' ';
|
||||
|
||||
var indentMultiline = function(str) {
|
||||
return str.replace(/\n/g, '\n' + space);
|
||||
};
|
||||
|
||||
/** @preserveTry */
|
||||
try {
|
||||
if (!goog.isDef(obj)) {
|
||||
str.push('undefined');
|
||||
} else if (goog.isNull(obj)) {
|
||||
str.push('NULL');
|
||||
} else if (goog.isString(obj)) {
|
||||
str.push('"' + indentMultiline(obj) + '"');
|
||||
} else if (goog.isFunction(obj)) {
|
||||
str.push(indentMultiline(String(obj)));
|
||||
} else if (goog.isObject(obj)) {
|
||||
if (previous.contains(obj)) {
|
||||
// TODO(user): This is a bug; it falsely detects non-loops as loops
|
||||
// when the reference tree contains two references to the same object.
|
||||
str.push('*** reference loop detected ***');
|
||||
} else {
|
||||
previous.add(obj);
|
||||
str.push('{');
|
||||
for (var x in obj) {
|
||||
if (!opt_showFn && goog.isFunction(obj[x])) {
|
||||
continue;
|
||||
}
|
||||
str.push('\n');
|
||||
str.push(nestspace);
|
||||
str.push(x + ' = ');
|
||||
helper(obj[x], nestspace);
|
||||
}
|
||||
str.push('\n' + space + '}');
|
||||
}
|
||||
} else {
|
||||
str.push(obj);
|
||||
}
|
||||
} catch (e) {
|
||||
str.push('*** ' + e + ' ***');
|
||||
}
|
||||
};
|
||||
|
||||
helper(obj, '');
|
||||
return str.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively outputs a nested array as a string.
|
||||
* @param {Array} arr The array.
|
||||
* @return {string} String representing nested array.
|
||||
*/
|
||||
goog.debug.exposeArray = function(arr) {
|
||||
var str = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (goog.isArray(arr[i])) {
|
||||
str.push(goog.debug.exposeArray(arr[i]));
|
||||
} else {
|
||||
str.push(arr[i]);
|
||||
}
|
||||
}
|
||||
return '[ ' + str.join(', ') + ' ]';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exposes an exception that has been caught by a try...catch and outputs the
|
||||
* error with a stack trace.
|
||||
* @param {Object} err Error object or string.
|
||||
* @param {Function=} opt_fn Optional function to start stack trace from.
|
||||
* @return {string} Details of exception.
|
||||
*/
|
||||
goog.debug.exposeException = function(err, opt_fn) {
|
||||
/** @preserveTry */
|
||||
try {
|
||||
var e = goog.debug.normalizeErrorObject(err);
|
||||
|
||||
// Create the error message
|
||||
var error = 'Message: ' + goog.string.htmlEscape(e.message) +
|
||||
'\nUrl: <a href="view-source:' + e.fileName + '" target="_new">' +
|
||||
e.fileName + '</a>\nLine: ' + e.lineNumber + '\n\nBrowser stack:\n' +
|
||||
goog.string.htmlEscape(e.stack + '-> ') +
|
||||
'[end]\n\nJS stack traversal:\n' + goog.string.htmlEscape(
|
||||
goog.debug.getStacktrace(opt_fn) + '-> ');
|
||||
return error;
|
||||
} catch (e2) {
|
||||
return 'Exception trying to expose exception! You win, we lose. ' + e2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the error/exception object between browsers.
|
||||
* @param {Object} err Raw error object.
|
||||
* @return {Object} Normalized error object.
|
||||
*/
|
||||
goog.debug.normalizeErrorObject = function(err) {
|
||||
var href = goog.getObjectByName('window.location.href');
|
||||
if (goog.isString(err)) {
|
||||
return {
|
||||
'message': err,
|
||||
'name': 'Unknown error',
|
||||
'lineNumber': 'Not available',
|
||||
'fileName': href,
|
||||
'stack': 'Not available'
|
||||
};
|
||||
}
|
||||
|
||||
var lineNumber, fileName;
|
||||
var threwError = false;
|
||||
|
||||
try {
|
||||
lineNumber = err.lineNumber || err.line || 'Not available';
|
||||
} catch (e) {
|
||||
// Firefox 2 sometimes throws an error when accessing 'lineNumber':
|
||||
// Message: Permission denied to get property UnnamedClass.lineNumber
|
||||
lineNumber = 'Not available';
|
||||
threwError = true;
|
||||
}
|
||||
|
||||
try {
|
||||
fileName = err.fileName || err.filename || err.sourceURL ||
|
||||
// $googDebugFname may be set before a call to eval to set the filename
|
||||
// that the eval is supposed to present.
|
||||
goog.global['$googDebugFname'] || href;
|
||||
} catch (e) {
|
||||
// Firefox 2 may also throw an error when accessing 'filename'.
|
||||
fileName = 'Not available';
|
||||
threwError = true;
|
||||
}
|
||||
|
||||
// The IE Error object contains only the name and the message.
|
||||
// The Safari Error object uses the line and sourceURL fields.
|
||||
if (threwError || !err.lineNumber || !err.fileName || !err.stack ||
|
||||
!err.message || !err.name) {
|
||||
return {
|
||||
'message': err.message || 'Not available',
|
||||
'name': err.name || 'UnknownError',
|
||||
'lineNumber': lineNumber,
|
||||
'fileName': fileName,
|
||||
'stack': err.stack || 'Not available'
|
||||
};
|
||||
}
|
||||
|
||||
// Standards error object
|
||||
return err;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an object to an Error if it's a String,
|
||||
* adds a stacktrace if there isn't one,
|
||||
* and optionally adds an extra message.
|
||||
* @param {Error|string} err the original thrown object or string.
|
||||
* @param {string=} opt_message optional additional message to add to the
|
||||
* error.
|
||||
* @return {Error} If err is a string, it is used to create a new Error,
|
||||
* which is enhanced and returned. Otherwise err itself is enhanced
|
||||
* and returned.
|
||||
*/
|
||||
goog.debug.enhanceError = function(err, opt_message) {
|
||||
var error = typeof err == 'string' ? Error(err) : err;
|
||||
if (!error.stack) {
|
||||
error.stack = goog.debug.getStacktrace(arguments.callee.caller);
|
||||
}
|
||||
if (opt_message) {
|
||||
// find the first unoccupied 'messageX' property
|
||||
var x = 0;
|
||||
while (error['message' + x]) {
|
||||
++x;
|
||||
}
|
||||
error['message' + x] = String(opt_message);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current stack trace. Simple and iterative - doesn't worry about
|
||||
* catching circular references or getting the args.
|
||||
* @param {number=} opt_depth Optional maximum depth to trace back to.
|
||||
* @return {string} A string with the function names of all functions in the
|
||||
* stack, separated by \n.
|
||||
*/
|
||||
goog.debug.getStacktraceSimple = function(opt_depth) {
|
||||
var sb = [];
|
||||
var fn = arguments.callee.caller;
|
||||
var depth = 0;
|
||||
|
||||
while (fn && (!opt_depth || depth < opt_depth)) {
|
||||
sb.push(goog.debug.getFunctionName(fn));
|
||||
sb.push('()\n');
|
||||
/** @preserveTry */
|
||||
try {
|
||||
fn = fn.caller;
|
||||
} catch (e) {
|
||||
sb.push('[exception trying to get caller]\n');
|
||||
break;
|
||||
}
|
||||
depth++;
|
||||
if (depth >= goog.debug.MAX_STACK_DEPTH) {
|
||||
sb.push('[...long stack...]');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt_depth && depth >= opt_depth) {
|
||||
sb.push('[...reached max depth limit...]');
|
||||
} else {
|
||||
sb.push('[end]');
|
||||
}
|
||||
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Max length of stack to try and output
|
||||
* @type {number}
|
||||
*/
|
||||
goog.debug.MAX_STACK_DEPTH = 50;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current stack trace, either starting from the caller or starting
|
||||
* from a specified function that's currently on the call stack.
|
||||
* @param {Function=} opt_fn Optional function to start getting the trace from.
|
||||
* If not provided, defaults to the function that called this.
|
||||
* @return {string} Stack trace.
|
||||
*/
|
||||
goog.debug.getStacktrace = function(opt_fn) {
|
||||
return goog.debug.getStacktraceHelper_(opt_fn || arguments.callee.caller, []);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private helper for getStacktrace().
|
||||
* @param {Function} fn Function to start getting the trace from.
|
||||
* @param {Array} visited List of functions visited so far.
|
||||
* @return {string} Stack trace starting from function fn.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.getStacktraceHelper_ = function(fn, visited) {
|
||||
var sb = [];
|
||||
|
||||
// Circular reference, certain functions like bind seem to cause a recursive
|
||||
// loop so we need to catch circular references
|
||||
if (goog.array.contains(visited, fn)) {
|
||||
sb.push('[...circular reference...]');
|
||||
|
||||
// Traverse the call stack until function not found or max depth is reached
|
||||
} else if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
|
||||
sb.push(goog.debug.getFunctionName(fn) + '(');
|
||||
var args = fn.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.push(', ');
|
||||
}
|
||||
var argDesc;
|
||||
var arg = args[i];
|
||||
switch (typeof arg) {
|
||||
case 'object':
|
||||
argDesc = arg ? 'object' : 'null';
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
argDesc = arg;
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
argDesc = String(arg);
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
argDesc = arg ? 'true' : 'false';
|
||||
break;
|
||||
|
||||
case 'function':
|
||||
argDesc = goog.debug.getFunctionName(arg);
|
||||
argDesc = argDesc ? argDesc : '[fn]';
|
||||
break;
|
||||
|
||||
case 'undefined':
|
||||
default:
|
||||
argDesc = typeof arg;
|
||||
break;
|
||||
}
|
||||
|
||||
if (argDesc.length > 40) {
|
||||
argDesc = argDesc.substr(0, 40) + '...';
|
||||
}
|
||||
sb.push(argDesc);
|
||||
}
|
||||
visited.push(fn);
|
||||
sb.push(')\n');
|
||||
/** @preserveTry */
|
||||
try {
|
||||
sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited));
|
||||
} catch (e) {
|
||||
sb.push('[exception trying to get caller]\n');
|
||||
}
|
||||
|
||||
} else if (fn) {
|
||||
sb.push('[...long stack...]');
|
||||
} else {
|
||||
sb.push('[end]');
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set a custom function name resolver.
|
||||
* @param {function(Function): string} resolver Resolves functions to their
|
||||
* names.
|
||||
*/
|
||||
goog.debug.setFunctionResolver = function(resolver) {
|
||||
goog.debug.fnNameResolver_ = resolver;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a function name
|
||||
* @param {Function} fn Function to get name of.
|
||||
* @return {string} Function's name.
|
||||
*/
|
||||
goog.debug.getFunctionName = function(fn) {
|
||||
if (goog.debug.fnNameCache_[fn]) {
|
||||
return goog.debug.fnNameCache_[fn];
|
||||
}
|
||||
if (goog.debug.fnNameResolver_) {
|
||||
var name = goog.debug.fnNameResolver_(fn);
|
||||
if (name) {
|
||||
goog.debug.fnNameCache_[fn] = name;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
// Heuristically determine function name based on code.
|
||||
var functionSource = String(fn);
|
||||
if (!goog.debug.fnNameCache_[functionSource]) {
|
||||
var matches = /function ([^\(]+)/.exec(functionSource);
|
||||
if (matches) {
|
||||
var method = matches[1];
|
||||
goog.debug.fnNameCache_[functionSource] = method;
|
||||
} else {
|
||||
goog.debug.fnNameCache_[functionSource] = '[Anonymous]';
|
||||
}
|
||||
}
|
||||
|
||||
return goog.debug.fnNameCache_[functionSource];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes whitespace visible by replacing it with printable characters.
|
||||
* This is useful in finding diffrences between the expected and the actual
|
||||
* output strings of a testcase.
|
||||
* @param {string} string whose whitespace needs to be made visible.
|
||||
* @return {string} string whose whitespace is made visible.
|
||||
*/
|
||||
goog.debug.makeWhitespaceVisible = function(string) {
|
||||
return string.replace(/ /g, '[_]')
|
||||
.replace(/\f/g, '[f]')
|
||||
.replace(/\n/g, '[n]\n')
|
||||
.replace(/\r/g, '[r]')
|
||||
.replace(/\t/g, '[t]');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hash map for storing function names that have already been looked up.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.fnNameCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Resolves functions to their names. Resolved function names will be cached.
|
||||
* @type {function(Function):string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.fnNameResolver_;
|
||||
615
float-no-zero/closure-library/closure/goog/debug/debugwindow.js
Normal file
615
float-no-zero/closure-library/closure/goog/debug/debugwindow.js
Normal file
@@ -0,0 +1,615 @@
|
||||
// Copyright 2006 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 Definition of the DebugWindow class. Please minimize
|
||||
* dependencies this file has on other closure classes as any dependency it
|
||||
* takes won't be able to use the logging infrastructure.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.DebugWindow');
|
||||
|
||||
goog.require('goog.debug.HtmlFormatter');
|
||||
goog.require('goog.debug.LogManager');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.structs.CircularBuffer');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Provides a debug DebugWindow that is bound to the goog.debug.Logger.
|
||||
* It handles log messages and writes them to the DebugWindow. This doesn't
|
||||
* provide a lot of functionality that the old Gmail logging infrastructure
|
||||
* provided like saving debug logs for exporting to the server. Now that we
|
||||
* have an event-based logging infrastructure, we can encapsulate that
|
||||
* functionality in a separate class.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string=} opt_identifier Identifier for this logging class.
|
||||
* @param {string=} opt_prefix Prefix prepended to messages.
|
||||
*/
|
||||
goog.debug.DebugWindow = function(opt_identifier, opt_prefix) {
|
||||
/**
|
||||
* Identifier for this logging class
|
||||
* @protected {string}
|
||||
*/
|
||||
this.identifier = opt_identifier || '';
|
||||
|
||||
/**
|
||||
* Array used to buffer log output
|
||||
* @protected {!Array}
|
||||
*/
|
||||
this.outputBuffer = [];
|
||||
|
||||
/**
|
||||
* Optional prefix to be prepended to error strings
|
||||
* @private {string}
|
||||
*/
|
||||
this.prefix_ = opt_prefix || '';
|
||||
|
||||
/**
|
||||
* Buffer for saving the last 1000 messages
|
||||
* @private {!goog.structs.CircularBuffer}
|
||||
*/
|
||||
this.savedMessages_ =
|
||||
new goog.structs.CircularBuffer(goog.debug.DebugWindow.MAX_SAVED);
|
||||
|
||||
/**
|
||||
* Save the publish handler so it can be removed
|
||||
* @private {!Function}
|
||||
*/
|
||||
this.publishHandler_ = goog.bind(this.addLogRecord, this);
|
||||
|
||||
/**
|
||||
* Formatter for formatted output
|
||||
* @private {goog.debug.Formatter}
|
||||
*/
|
||||
this.formatter_ = new goog.debug.HtmlFormatter(this.prefix_);
|
||||
|
||||
/**
|
||||
* Loggers that we shouldn't output
|
||||
* @private {!Object}
|
||||
*/
|
||||
this.filteredLoggers_ = {};
|
||||
|
||||
// enable by default
|
||||
this.setCapturing(true);
|
||||
|
||||
/**
|
||||
* Whether we are currently enabled. When the DebugWindow is enabled, it tries
|
||||
* to keep its window open. When it's disabled, it can still be capturing log
|
||||
* output if, but it won't try to write them to the DebugWindow window until
|
||||
* it's enabled.
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.enabled_ = goog.debug.DebugWindow.isEnabled(this.identifier);
|
||||
|
||||
// timer to save the DebugWindow's window position in a cookie
|
||||
goog.global.setInterval(goog.bind(this.saveWindowPositionSize_, this), 7500);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Max number of messages to be saved
|
||||
* @type {number}
|
||||
*/
|
||||
goog.debug.DebugWindow.MAX_SAVED = 500;
|
||||
|
||||
|
||||
/**
|
||||
* How long to keep the cookies for in milliseconds
|
||||
* @type {number}
|
||||
*/
|
||||
goog.debug.DebugWindow.COOKIE_TIME = 30 * 24 * 60 * 60 * 1000; // 30-days
|
||||
|
||||
|
||||
/**
|
||||
* HTML string printed when the debug window opens
|
||||
* @type {string}
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.welcomeMessage = 'LOGGING';
|
||||
|
||||
|
||||
/**
|
||||
* Whether to force enable the window on a severe log.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.enableOnSevere_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Reference to debug window
|
||||
* @type {Window}
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.win = null;
|
||||
|
||||
|
||||
/**
|
||||
* In the process of opening the window
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.winOpening_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether we are currently capturing logger output.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.isCapturing_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether we already showed an alert that the DebugWindow was blocked.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.showedBlockedAlert_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Reference to timeout used to buffer the output stream.
|
||||
* @type {?number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.bufferTimeout_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Timestamp for the last time the log was written to.
|
||||
* @protected {number}
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.lastCall = goog.now();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the welcome message shown when the window is first opened or reset.
|
||||
*
|
||||
* @param {string} msg An HTML string.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setWelcomeMessage = function(msg) {
|
||||
this.welcomeMessage = msg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the debug window.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.init = function() {
|
||||
if (this.enabled_) {
|
||||
this.openWindow_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the DebugWindow is enabled. When the DebugWindow is enabled, it
|
||||
* tries to keep its window open and logs all messages to the window. When the
|
||||
* DebugWindow is disabled, it stops logging messages to its window.
|
||||
*
|
||||
* @return {boolean} Whether the DebugWindow is enabled.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.isEnabled = function() {
|
||||
return this.enabled_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether the DebugWindow is enabled. When the DebugWindow is enabled, it
|
||||
* tries to keep its window open and log all messages to the window. When the
|
||||
* DebugWindow is disabled, it stops logging messages to its window. The
|
||||
* DebugWindow also saves this state to a cookie so that it's persisted across
|
||||
* application refreshes.
|
||||
* @param {boolean} enable Whether the DebugWindow is enabled.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setEnabled = function(enable) {
|
||||
this.enabled_ = enable;
|
||||
|
||||
if (this.enabled_) {
|
||||
this.openWindow_();
|
||||
}
|
||||
|
||||
this.setCookie_('enabled', enable ? '1' : '0');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether the debug window should be force enabled when a severe log is
|
||||
* encountered.
|
||||
* @param {boolean} enableOnSevere Whether to enable on severe logs..
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setForceEnableOnSevere =
|
||||
function(enableOnSevere) {
|
||||
this.enableOnSevere_ = enableOnSevere;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether we are currently capturing logger output.
|
||||
* @return {boolean} whether we are currently capturing logger output.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.isCapturing = function() {
|
||||
return this.isCapturing_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether we are currently capturing logger output.
|
||||
* @param {boolean} capturing Whether to capture logger output.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setCapturing = function(capturing) {
|
||||
if (capturing == this.isCapturing_) {
|
||||
return;
|
||||
}
|
||||
this.isCapturing_ = capturing;
|
||||
|
||||
// attach or detach handler from the root logger
|
||||
var rootLogger = goog.debug.LogManager.getRoot();
|
||||
if (capturing) {
|
||||
rootLogger.addHandler(this.publishHandler_);
|
||||
} else {
|
||||
rootLogger.removeHandler(this.publishHandler_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the formatter for outputting to the debug window. The default formatter
|
||||
* is an instance of goog.debug.HtmlFormatter
|
||||
* @return {goog.debug.Formatter} The formatter in use.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.getFormatter = function() {
|
||||
return this.formatter_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the formatter for outputting to the debug window.
|
||||
* @param {goog.debug.Formatter} formatter The formatter to use.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setFormatter = function(formatter) {
|
||||
this.formatter_ = formatter;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a separator to the debug window.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.addSeparator = function() {
|
||||
this.write_('<hr>');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether there is an active window.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.hasActiveWindow = function() {
|
||||
return !!this.win && !this.win.closed;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the contents of the debug window
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.clear = function() {
|
||||
this.savedMessages_.clear();
|
||||
if (this.hasActiveWindow()) {
|
||||
this.writeInitialDocument();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a log record.
|
||||
* @param {goog.debug.LogRecord} logRecord the LogRecord.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.addLogRecord = function(logRecord) {
|
||||
if (this.filteredLoggers_[logRecord.getLoggerName()]) {
|
||||
return;
|
||||
}
|
||||
var html = this.formatter_.formatRecord(logRecord);
|
||||
this.write_(html);
|
||||
if (this.enableOnSevere_ &&
|
||||
logRecord.getLevel().value >= goog.debug.Logger.Level.SEVERE.value) {
|
||||
this.setEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Writes a message to the log, possibly opening up the window if it's enabled,
|
||||
* or saving it if it's disabled.
|
||||
* @param {string} html The HTML to write.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.write_ = function(html) {
|
||||
// If the logger is enabled, open window and write html message to log
|
||||
// otherwise save it
|
||||
if (this.enabled_) {
|
||||
this.openWindow_();
|
||||
this.savedMessages_.add(html);
|
||||
this.writeToLog_(html);
|
||||
} else {
|
||||
this.savedMessages_.add(html);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write to the buffer. If a message hasn't been sent for more than 750ms just
|
||||
* write, otherwise delay for a minimum of 250ms.
|
||||
* @param {string} html HTML to post to the log.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.writeToLog_ = function(html) {
|
||||
this.outputBuffer.push(html);
|
||||
goog.global.clearTimeout(this.bufferTimeout_);
|
||||
|
||||
if (goog.now() - this.lastCall > 750) {
|
||||
this.writeBufferToLog();
|
||||
} else {
|
||||
this.bufferTimeout_ =
|
||||
goog.global.setTimeout(goog.bind(this.writeBufferToLog, this), 250);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write to the log and maybe scroll into view.
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.writeBufferToLog = function() {
|
||||
this.lastCall = goog.now();
|
||||
if (this.hasActiveWindow()) {
|
||||
var body = this.win.document.body;
|
||||
var scroll = body &&
|
||||
body.scrollHeight - (body.scrollTop + body.clientHeight) <= 100;
|
||||
|
||||
this.win.document.write(this.outputBuffer.join(''));
|
||||
this.outputBuffer.length = 0;
|
||||
|
||||
if (scroll) {
|
||||
this.win.scrollTo(0, 1000000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Writes all saved messages to the DebugWindow.
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.writeSavedMessages = function() {
|
||||
var messages = this.savedMessages_.getValues();
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
this.writeToLog_(messages[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens the debug window if it is not already referenced
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.openWindow_ = function() {
|
||||
if (this.hasActiveWindow() || this.winOpening_) {
|
||||
return;
|
||||
}
|
||||
|
||||
var winpos = this.getCookie_('dbg', '0,0,800,500').split(',');
|
||||
var x = Number(winpos[0]);
|
||||
var y = Number(winpos[1]);
|
||||
var w = Number(winpos[2]);
|
||||
var h = Number(winpos[3]);
|
||||
|
||||
this.winOpening_ = true;
|
||||
this.win = window.open('', this.getWindowName_(), 'width=' + w +
|
||||
',height=' + h + ',toolbar=no,resizable=yes,' +
|
||||
'scrollbars=yes,left=' + x + ',top=' + y +
|
||||
',status=no,screenx=' + x + ',screeny=' + y);
|
||||
|
||||
if (!this.win) {
|
||||
if (!this.showedBlockedAlert_) {
|
||||
// only show this once
|
||||
alert('Logger popup was blocked');
|
||||
this.showedBlockedAlert_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.winOpening_ = false;
|
||||
|
||||
if (this.win) {
|
||||
this.writeInitialDocument();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a valid window name for the debug window. Replaces invalid characters in
|
||||
* IE.
|
||||
* @return {string} Valid window name.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.getWindowName_ = function() {
|
||||
return goog.userAgent.IE ?
|
||||
this.identifier.replace(/[\s\-\.\,]/g, '_') : this.identifier;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The style rule text, for inclusion in the initial HTML.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.getStyleRules = function() {
|
||||
return '*{font:normal 14px monospace;}' +
|
||||
'.dbg-sev{color:#F00}' +
|
||||
'.dbg-w{color:#E92}' +
|
||||
'.dbg-sh{background-color:#fd4;font-weight:bold;color:#000}' +
|
||||
'.dbg-i{color:#666}' +
|
||||
'.dbg-f{color:#999}' +
|
||||
'.dbg-ev{color:#0A0}' +
|
||||
'.dbg-m{color:#990}';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Writes the initial HTML of the debug window.
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.writeInitialDocument = function() {
|
||||
if (!this.hasActiveWindow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.win.document.open();
|
||||
|
||||
var html = '<style>' + this.getStyleRules() + '</style>' +
|
||||
'<hr><div class="dbg-ev" style="text-align:center">' +
|
||||
this.welcomeMessage + '<br><small>Logger: ' +
|
||||
this.identifier + '</small></div><hr>';
|
||||
|
||||
this.writeToLog_(html);
|
||||
this.writeSavedMessages();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Save persistent data (using cookies) for 1 month (cookie specific to this
|
||||
* logger object).
|
||||
* @param {string} key Data name.
|
||||
* @param {string} value Data value.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.setCookie_ = function(key, value) {
|
||||
var fullKey = goog.debug.DebugWindow.getCookieKey_(this.identifier, key);
|
||||
document.cookie = fullKey + '=' + encodeURIComponent(value) +
|
||||
';path=/;expires=' +
|
||||
(new Date(goog.now() + goog.debug.DebugWindow.COOKIE_TIME)).toUTCString();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve data (using cookies).
|
||||
* @param {string} key Data name.
|
||||
* @param {string=} opt_default Optional default value if cookie doesn't exist.
|
||||
* @return {string} Cookie value.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.getCookie_ = function(key, opt_default) {
|
||||
return goog.debug.DebugWindow.getCookieValue_(
|
||||
this.identifier, key, opt_default);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a valid cookie key name which is scoped to the given identifier.
|
||||
* Substitutes all occurences of invalid cookie name characters (whitespace,
|
||||
* ';', and '=') with '_', which is a valid and readable alternative.
|
||||
* @see goog.net.Cookies#isValidName
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
|
||||
* @param {string} identifier Identifier for logging class.
|
||||
* @param {string} key Data name.
|
||||
* @return {string} Cookie key name.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.getCookieKey_ = function(identifier, key) {
|
||||
var fullKey = key + identifier;
|
||||
return fullKey.replace(/[;=\s]/g, '_');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve data (using cookies).
|
||||
* @param {string} identifier Identifier for logging class.
|
||||
* @param {string} key Data name.
|
||||
* @param {string=} opt_default Optional default value if cookie doesn't exist.
|
||||
* @return {string} Cookie value.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.getCookieValue_ = function(
|
||||
identifier, key, opt_default) {
|
||||
var fullKey = goog.debug.DebugWindow.getCookieKey_(identifier, key);
|
||||
var cookie = String(document.cookie);
|
||||
var start = cookie.indexOf(fullKey + '=');
|
||||
if (start != -1) {
|
||||
var end = cookie.indexOf(';', start);
|
||||
return decodeURIComponent(cookie.substring(start + fullKey.length + 1,
|
||||
end == -1 ? cookie.length : end));
|
||||
} else {
|
||||
return opt_default || '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} identifier Identifier for logging class.
|
||||
* @return {boolean} Whether the DebugWindow is enabled.
|
||||
*/
|
||||
goog.debug.DebugWindow.isEnabled = function(identifier) {
|
||||
return goog.debug.DebugWindow.getCookieValue_(identifier, 'enabled') == '1';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Saves the window position size to a cookie
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.saveWindowPositionSize_ = function() {
|
||||
if (!this.hasActiveWindow()) {
|
||||
return;
|
||||
}
|
||||
var x = this.win.screenX || this.win.screenLeft || 0;
|
||||
var y = this.win.screenY || this.win.screenTop || 0;
|
||||
var w = this.win.outerWidth || 800;
|
||||
var h = this.win.outerHeight || 500;
|
||||
this.setCookie_('dbg', x + ',' + y + ',' + w + ',' + h);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a logger name to be filtered.
|
||||
* @param {string} loggerName the logger name to add.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.addFilter = function(loggerName) {
|
||||
this.filteredLoggers_[loggerName] = 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a logger name to be filtered.
|
||||
* @param {string} loggerName the logger name to remove.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.removeFilter = function(loggerName) {
|
||||
delete this.filteredLoggers_[loggerName];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Modify the size of the circular buffer. Allows the log to retain more
|
||||
* information while the window is closed.
|
||||
* @param {number} size New size of the circular buffer.
|
||||
*/
|
||||
goog.debug.DebugWindow.prototype.resetBufferWithNewSize = function(size) {
|
||||
if (size > 0 && size < 50000) {
|
||||
this.clear();
|
||||
this.savedMessages_ = new goog.structs.CircularBuffer(size);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,444 @@
|
||||
// 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 Runtime development CSS Compiler emulation, via javascript.
|
||||
* This class provides an approximation to CSSCompiler's functionality by
|
||||
* hacking the live CSSOM.
|
||||
* This code is designed to be inserted in the DOM immediately after the last
|
||||
* style block in HEAD when in development mode, i.e. you are not using a
|
||||
* running instance of a CSS Compiler to pass your CSS through.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.debug.DevCss');
|
||||
goog.provide('goog.debug.DevCss.UserAgent');
|
||||
|
||||
goog.require('goog.cssom');
|
||||
goog.require('goog.dom.classes');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A class for solving development CSS issues/emulating the CSS Compiler.
|
||||
* @param {goog.debug.DevCss.UserAgent=} opt_userAgent The user agent, if not
|
||||
* passed in, will be determined using goog.userAgent.
|
||||
* @param {number|string=} opt_userAgentVersion The user agent's version.
|
||||
* If not passed in, will be determined using goog.userAgent.
|
||||
* @throws {Error} When userAgent detection fails.
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.DevCss = function(opt_userAgent, opt_userAgentVersion) {
|
||||
if (!opt_userAgent) {
|
||||
// Walks through the known goog.userAgents.
|
||||
if (goog.userAgent.IE) {
|
||||
opt_userAgent = goog.debug.DevCss.UserAgent.IE;
|
||||
} else if (goog.userAgent.GECKO) {
|
||||
opt_userAgent = goog.debug.DevCss.UserAgent.GECKO;
|
||||
} else if (goog.userAgent.WEBKIT) {
|
||||
opt_userAgent = goog.debug.DevCss.UserAgent.WEBKIT;
|
||||
} else if (goog.userAgent.MOBILE) {
|
||||
opt_userAgent = goog.debug.DevCss.UserAgent.MOBILE;
|
||||
} else if (goog.userAgent.OPERA) {
|
||||
opt_userAgent = goog.debug.DevCss.UserAgent.OPERA;
|
||||
}
|
||||
}
|
||||
switch (opt_userAgent) {
|
||||
case goog.debug.DevCss.UserAgent.OPERA:
|
||||
case goog.debug.DevCss.UserAgent.IE:
|
||||
case goog.debug.DevCss.UserAgent.GECKO:
|
||||
case goog.debug.DevCss.UserAgent.FIREFOX:
|
||||
case goog.debug.DevCss.UserAgent.WEBKIT:
|
||||
case goog.debug.DevCss.UserAgent.SAFARI:
|
||||
case goog.debug.DevCss.UserAgent.MOBILE:
|
||||
break;
|
||||
default:
|
||||
throw Error('Could not determine the user agent from known UserAgents');
|
||||
}
|
||||
|
||||
/**
|
||||
* One of goog.debug.DevCss.UserAgent.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.userAgent_ = opt_userAgent;
|
||||
|
||||
/**
|
||||
* @type {number|string}
|
||||
* @private
|
||||
*/
|
||||
this.userAgentVersion_ = opt_userAgentVersion || goog.userAgent.VERSION;
|
||||
this.generateUserAgentTokens_();
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isIe6OrLess_ = this.userAgent_ == goog.debug.DevCss.UserAgent.IE &&
|
||||
goog.string.compareVersions('7', this.userAgentVersion_) > 0;
|
||||
|
||||
if (this.isIe6OrLess_) {
|
||||
/**
|
||||
* @type {Array.<{classNames,combinedClassName,els}>}
|
||||
* @private
|
||||
*/
|
||||
this.ie6CombinedMatches_ = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rewrites the CSSOM as needed to activate any useragent-specific selectors.
|
||||
* @param {boolean=} opt_enableIe6ReadyHandler If true(the default), and the
|
||||
* userAgent is ie6, we set a document "ready" event handler to walk the DOM
|
||||
* and make combined selector className changes. Having this parameter also
|
||||
* aids unit testing.
|
||||
*/
|
||||
goog.debug.DevCss.prototype.activateBrowserSpecificCssRules = function(
|
||||
opt_enableIe6ReadyHandler) {
|
||||
var enableIe6EventHandler = goog.isDef(opt_enableIe6ReadyHandler) ?
|
||||
opt_enableIe6ReadyHandler : true;
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
|
||||
for (var i = 0, cssRule; cssRule = cssRules[i]; i++) {
|
||||
this.replaceBrowserSpecificClassNames_(cssRule);
|
||||
}
|
||||
|
||||
// Since we may have manipulated the rules above, we'll have to do a
|
||||
// complete sweep again if we're in IE6. Luckily performance doesn't
|
||||
// matter for this tool.
|
||||
if (this.isIe6OrLess_) {
|
||||
cssRules = goog.cssom.getAllCssStyleRules();
|
||||
for (var i = 0, cssRule; cssRule = cssRules[i]; i++) {
|
||||
this.replaceIe6CombinedSelectors_(cssRule);
|
||||
}
|
||||
}
|
||||
|
||||
// Add an event listener for document ready to rewrite any necessary
|
||||
// combined classnames in IE6.
|
||||
if (this.isIe6OrLess_ && enableIe6EventHandler) {
|
||||
goog.events.listen(document, goog.events.EventType.LOAD, goog.bind(
|
||||
this.addIe6CombinedClassNames_, this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.userAgentTokens_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* A list of possible user agent strings.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.debug.DevCss.UserAgent = {
|
||||
OPERA: 'OPERA',
|
||||
IE: 'IE',
|
||||
GECKO: 'GECKO',
|
||||
FIREFOX: 'GECKO',
|
||||
WEBKIT: 'WEBKIT',
|
||||
SAFARI: 'WEBKIT',
|
||||
MOBILE: 'MOBILE'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A list of strings that may be used for matching in CSS files/development.
|
||||
* @enum {string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.CssToken_ = {
|
||||
USERAGENT: 'USERAGENT',
|
||||
SEPARATOR: '-',
|
||||
LESS_THAN: 'LT',
|
||||
GREATER_THAN: 'GT',
|
||||
LESS_THAN_OR_EQUAL: 'LTE',
|
||||
GREATER_THAN_OR_EQUAL: 'GTE',
|
||||
IE6_SELECTOR_TEXT: 'goog-ie6-selector',
|
||||
IE6_COMBINED_GLUE: '_'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates user agent token match strings with comparison and version bits.
|
||||
* For example:
|
||||
* userAgentTokens_.ANY will be like 'GECKO'
|
||||
* userAgentTokens_.LESS_THAN will be like 'GECKO-LT3' etc...
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.generateUserAgentTokens_ = function() {
|
||||
this.userAgentTokens_.ANY = goog.debug.DevCss.CssToken_.USERAGENT +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR + this.userAgent_;
|
||||
this.userAgentTokens_.EQUALS = this.userAgentTokens_.ANY +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR;
|
||||
this.userAgentTokens_.LESS_THAN = this.userAgentTokens_.ANY +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR +
|
||||
goog.debug.DevCss.CssToken_.LESS_THAN;
|
||||
this.userAgentTokens_.LESS_THAN_OR_EQUAL = this.userAgentTokens_.ANY +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR +
|
||||
goog.debug.DevCss.CssToken_.LESS_THAN_OR_EQUAL;
|
||||
this.userAgentTokens_.GREATER_THAN = this.userAgentTokens_.ANY +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR +
|
||||
goog.debug.DevCss.CssToken_.GREATER_THAN;
|
||||
this.userAgentTokens_.GREATER_THAN_OR_EQUAL = this.userAgentTokens_.ANY +
|
||||
goog.debug.DevCss.CssToken_.SEPARATOR +
|
||||
goog.debug.DevCss.CssToken_.GREATER_THAN_OR_EQUAL;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the version number bit from a selector matching userAgentToken.
|
||||
* @param {string} selectorText The selector text of a CSS rule.
|
||||
* @param {string} userAgentToken Includes the LTE/GTE bit to see if it matches.
|
||||
* @return {string|undefined} The version number.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.getVersionNumberFromSelectorText_ = function(
|
||||
selectorText, userAgentToken) {
|
||||
var regex = new RegExp(userAgentToken + '([\\d\\.]+)');
|
||||
var matches = regex.exec(selectorText);
|
||||
if (matches && matches.length == 2) {
|
||||
return matches[1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a rule version from the selector text, and if it finds one, calls
|
||||
* compareVersions against it and the passed in token string to provide the
|
||||
* value needed to determine if we have a match or not.
|
||||
* @param {CSSRule} cssRule The rule to test against.
|
||||
* @param {string} token The match token to test against the rule.
|
||||
* @return {Array|undefined} A tuple with the result of the compareVersions call
|
||||
* and the matched ruleVersion.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.getRuleVersionAndCompare_ = function(cssRule,
|
||||
token) {
|
||||
if (!cssRule.selectorText.match(token)) {
|
||||
return;
|
||||
}
|
||||
var ruleVersion = this.getVersionNumberFromSelectorText_(
|
||||
cssRule.selectorText, token);
|
||||
if (!ruleVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
var comparison = goog.string.compareVersions(this.userAgentVersion_,
|
||||
ruleVersion);
|
||||
return [comparison, ruleVersion];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replaces a CSS selector if we have matches based on our useragent/version.
|
||||
* Example: With a selector like ".USERAGENT-IE-LTE6 .class { prop: value }" if
|
||||
* we are running IE6 we'll end up with ".class { prop: value }", thereby
|
||||
* "activating" the selector.
|
||||
* @param {CSSRule} cssRule The cssRule to potentially replace.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.replaceBrowserSpecificClassNames_ = function(
|
||||
cssRule) {
|
||||
|
||||
// If we don't match the browser token, we can stop now.
|
||||
if (!cssRule.selectorText.match(this.userAgentTokens_.ANY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We know it will begin as a classname.
|
||||
var additionalRegexString;
|
||||
|
||||
// Tests "Less than or equals".
|
||||
var compared = this.getRuleVersionAndCompare_(cssRule,
|
||||
this.userAgentTokens_.LESS_THAN_OR_EQUAL);
|
||||
if (compared && compared.length) {
|
||||
if (compared[0] > 0) {
|
||||
return;
|
||||
}
|
||||
additionalRegexString = this.userAgentTokens_.LESS_THAN_OR_EQUAL +
|
||||
compared[1];
|
||||
}
|
||||
|
||||
// Tests "Less than".
|
||||
compared = this.getRuleVersionAndCompare_(cssRule,
|
||||
this.userAgentTokens_.LESS_THAN);
|
||||
if (compared && compared.length) {
|
||||
if (compared[0] > -1) {
|
||||
return;
|
||||
}
|
||||
additionalRegexString = this.userAgentTokens_.LESS_THAN + compared[1];
|
||||
}
|
||||
|
||||
// Tests "Greater than or equals".
|
||||
compared = this.getRuleVersionAndCompare_(cssRule,
|
||||
this.userAgentTokens_.GREATER_THAN_OR_EQUAL);
|
||||
if (compared && compared.length) {
|
||||
if (compared[0] < 0) {
|
||||
return;
|
||||
}
|
||||
additionalRegexString = this.userAgentTokens_.GREATER_THAN_OR_EQUAL +
|
||||
compared[1];
|
||||
}
|
||||
|
||||
// Tests "Greater than".
|
||||
compared = this.getRuleVersionAndCompare_(cssRule,
|
||||
this.userAgentTokens_.GREATER_THAN);
|
||||
if (compared && compared.length) {
|
||||
if (compared[0] < 1) {
|
||||
return;
|
||||
}
|
||||
additionalRegexString = this.userAgentTokens_.GREATER_THAN + compared[1];
|
||||
}
|
||||
|
||||
// Tests "Equals".
|
||||
compared = this.getRuleVersionAndCompare_(cssRule,
|
||||
this.userAgentTokens_.EQUALS);
|
||||
if (compared && compared.length) {
|
||||
if (compared[0] != 0) {
|
||||
return;
|
||||
}
|
||||
additionalRegexString = this.userAgentTokens_.EQUALS + compared[1];
|
||||
}
|
||||
|
||||
// If we got to here without generating the additionalRegexString, then
|
||||
// we did not match any of our comparison token strings, and we want a
|
||||
// general browser token replacement.
|
||||
if (!additionalRegexString) {
|
||||
additionalRegexString = this.userAgentTokens_.ANY;
|
||||
}
|
||||
|
||||
// We need to match at least a single whitespace character to know that
|
||||
// we are matching the entire useragent string token.
|
||||
var regexString = '\\.' + additionalRegexString + '\\s+';
|
||||
var re = new RegExp(regexString, 'g');
|
||||
|
||||
var currentCssText = goog.cssom.getCssTextFromCssRule(cssRule);
|
||||
|
||||
// Replacing the token with '' activates the selector for this useragent.
|
||||
var newCssText = currentCssText.replace(re, '');
|
||||
|
||||
if (newCssText != currentCssText) {
|
||||
goog.cssom.replaceCssRule(cssRule, newCssText);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replaces IE6 combined selector rules with a workable development alternative.
|
||||
* IE6 actually parses .class1.class2 {} to simply .class2 {} which is nasty.
|
||||
* To fully support combined selectors in IE6 this function needs to be paired
|
||||
* with a call to replace the relevant DOM elements classNames as well.
|
||||
* @see {this.addIe6CombinedClassNames_}
|
||||
* @param {CSSRule} cssRule The rule to potentially fix.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.replaceIe6CombinedSelectors_ = function(cssRule) {
|
||||
// This match only ever works in IE because other UA's won't have our
|
||||
// IE6_SELECTOR_TEXT in the cssText property.
|
||||
if (cssRule.style.cssText &&
|
||||
cssRule.style.cssText.match(
|
||||
goog.debug.DevCss.CssToken_.IE6_SELECTOR_TEXT)) {
|
||||
var cssText = goog.cssom.getCssTextFromCssRule(cssRule);
|
||||
var combinedSelectorText = this.getIe6CombinedSelectorText_(cssText);
|
||||
if (combinedSelectorText) {
|
||||
var newCssText = combinedSelectorText + '{' + cssRule.style.cssText + '}';
|
||||
goog.cssom.replaceCssRule(cssRule, newCssText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the appropriate new combined selector text for IE6.
|
||||
* Also adds an entry onto ie6CombinedMatches_ with relevant info for the
|
||||
* likely following call to walk the DOM and rewrite the class attribute.
|
||||
* Example: With a selector like
|
||||
* ".class2 { -goog-ie6-selector: .class1.class2; prop: value }".
|
||||
* this function will return:
|
||||
* ".class1_class2 { prop: value }".
|
||||
* @param {string} cssText The CSS selector text and css rule text combined.
|
||||
* @return {?string} The rewritten css rule text.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.getIe6CombinedSelectorText_ = function(cssText) {
|
||||
var regex = new RegExp(goog.debug.DevCss.CssToken_.IE6_SELECTOR_TEXT +
|
||||
'\\s*:\\s*\\"([^\\"]+)\\"', 'gi');
|
||||
var matches = regex.exec(cssText);
|
||||
if (matches) {
|
||||
var combinedSelectorText = matches[1];
|
||||
// To aid in later fixing the DOM, we need to split up the possible
|
||||
// selector groups by commas.
|
||||
var groupedSelectors = combinedSelectorText.split(/\s*\,\s*/);
|
||||
for (var i = 0, selector; selector = groupedSelectors[i]; i++) {
|
||||
// Strips off the leading ".".
|
||||
var combinedClassName = selector.substr(1);
|
||||
var classNames = combinedClassName.split(
|
||||
goog.debug.DevCss.CssToken_.IE6_COMBINED_GLUE);
|
||||
var entry = {
|
||||
classNames: classNames,
|
||||
combinedClassName: combinedClassName,
|
||||
els: []
|
||||
};
|
||||
this.ie6CombinedMatches_.push(entry);
|
||||
}
|
||||
return combinedSelectorText;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds combined selectors with underscores to make them "work" in IE6.
|
||||
* @see {this.replaceIe6CombinedSelectors_}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.DevCss.prototype.addIe6CombinedClassNames_ = function() {
|
||||
if (!this.ie6CombinedMatches_.length) {
|
||||
return;
|
||||
}
|
||||
var allEls = document.getElementsByTagName('*');
|
||||
var matches = [];
|
||||
// Match nodes for all classNames.
|
||||
for (var i = 0, classNameEntry; classNameEntry =
|
||||
this.ie6CombinedMatches_[i]; i++) {
|
||||
for (var j = 0, el; el = allEls[j]; j++) {
|
||||
var classNamesLength = classNameEntry.classNames.length;
|
||||
for (var k = 0, className; className = classNameEntry.classNames[k];
|
||||
k++) {
|
||||
if (!goog.dom.classes.has(el, className)) {
|
||||
break;
|
||||
}
|
||||
if (k == classNamesLength - 1) {
|
||||
classNameEntry.els.push(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Walks over our matching nodes and fixes them.
|
||||
if (classNameEntry.els.length) {
|
||||
for (var j = 0, el; el = classNameEntry.els[j]; j++) {
|
||||
if (!goog.dom.classes.has(el, classNameEntry.combinedClassName)) {
|
||||
goog.dom.classes.add(el, classNameEntry.combinedClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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 Development CSS Compiler runtime execution.
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.devCssRunner');
|
||||
|
||||
goog.require('goog.debug.DevCss');
|
||||
|
||||
(function() {
|
||||
var devCssInstance = new goog.debug.DevCss();
|
||||
devCssInstance.activateBrowserSpecificCssRules();
|
||||
})();
|
||||
141
float-no-zero/closure-library/closure/goog/debug/divconsole.js
Normal file
141
float-no-zero/closure-library/closure/goog/debug/divconsole.js
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright 2006 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 Simple logger that logs a Div Element.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.DivConsole');
|
||||
|
||||
goog.require('goog.debug.HtmlFormatter');
|
||||
goog.require('goog.debug.LogManager');
|
||||
goog.require('goog.style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A class for visualising logger calls in a div element.
|
||||
* @param {Element} element The element to append to.
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.DivConsole = function(element) {
|
||||
this.publishHandler_ = goog.bind(this.addLogRecord, this);
|
||||
this.formatter_ = new goog.debug.HtmlFormatter();
|
||||
this.formatter_.showAbsoluteTime = false;
|
||||
this.isCapturing_ = false;
|
||||
this.element_ = element;
|
||||
this.elementOwnerDocument_ =
|
||||
this.element_.ownerDocument || this.element_.document;
|
||||
|
||||
this.installStyles();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Installs styles for the log messages and its div
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.installStyles = function() {
|
||||
goog.style.installStyles(
|
||||
'.dbg-sev{color:#F00}' +
|
||||
'.dbg-w{color:#C40}' +
|
||||
'.dbg-sh{font-weight:bold;color:#000}' +
|
||||
'.dbg-i{color:#444}' +
|
||||
'.dbg-f{color:#999}' +
|
||||
'.dbg-ev{color:#0A0}' +
|
||||
'.dbg-m{color:#990}' +
|
||||
'.logmsg{border-bottom:1px solid #CCC;padding:2px}' +
|
||||
'.logsep{background-color: #8C8;}' +
|
||||
'.logdiv{border:1px solid #CCC;background-color:#FCFCFC;' +
|
||||
'font:medium monospace}',
|
||||
this.element_);
|
||||
this.element_.className += ' logdiv';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether we are currently capturing logger output.
|
||||
* @param {boolean} capturing Whether to capture logger output.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.setCapturing = function(capturing) {
|
||||
if (capturing == this.isCapturing_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// attach or detach handler from the root logger
|
||||
var rootLogger = goog.debug.LogManager.getRoot();
|
||||
if (capturing) {
|
||||
rootLogger.addHandler(this.publishHandler_);
|
||||
} else {
|
||||
rootLogger.removeHandler(this.publishHandler_);
|
||||
this.logBuffer = '';
|
||||
}
|
||||
this.isCapturing_ = capturing;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a log record.
|
||||
* @param {goog.debug.LogRecord} logRecord The log entry.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.addLogRecord = function(logRecord) {
|
||||
var scroll = this.element_.scrollHeight - this.element_.scrollTop -
|
||||
this.element_.clientHeight <= 100;
|
||||
|
||||
var div = this.elementOwnerDocument_.createElement('div');
|
||||
div.className = 'logmsg';
|
||||
div.innerHTML = this.formatter_.formatRecord(logRecord);
|
||||
this.element_.appendChild(div);
|
||||
|
||||
if (scroll) {
|
||||
this.element_.scrollTop = this.element_.scrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the formatter for outputting to the console. The default formatter
|
||||
* is an instance of goog.debug.HtmlFormatter
|
||||
* @return {goog.debug.Formatter} The formatter in use.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.getFormatter = function() {
|
||||
return this.formatter_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the formatter for outputting to the console.
|
||||
* @param {goog.debug.Formatter} formatter The formatter to use.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.setFormatter = function(formatter) {
|
||||
this.formatter_ = formatter;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a separator to the debug window.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.addSeparator = function() {
|
||||
var div = this.elementOwnerDocument_.createElement('div');
|
||||
div.className = 'logmsg logsep';
|
||||
this.element_.appendChild(div);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the console.
|
||||
*/
|
||||
goog.debug.DivConsole.prototype.clear = function() {
|
||||
this.element_.innerHTML = '';
|
||||
};
|
||||
@@ -0,0 +1,158 @@
|
||||
// Copyright 2010 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 A global registry for entry points into a program,
|
||||
* so that they can be instrumented. Each module should register their
|
||||
* entry points with this registry. Designed to be compiled out
|
||||
* if no instrumentation is requested.
|
||||
*
|
||||
* Entry points may be registered before or after a call to
|
||||
* goog.debug.entryPointRegistry.monitorAll. If an entry point is registered
|
||||
* later, the existing monitor will instrument the new entry point.
|
||||
*
|
||||
* @author nicksantos@google.com (Nick Santos)
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.EntryPointMonitor');
|
||||
goog.provide('goog.debug.entryPointRegistry');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
goog.debug.EntryPointMonitor = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Instruments a function.
|
||||
*
|
||||
* @param {!Function} fn A function to instrument.
|
||||
* @return {!Function} The instrumented function.
|
||||
*/
|
||||
goog.debug.EntryPointMonitor.prototype.wrap;
|
||||
|
||||
|
||||
/**
|
||||
* Try to remove an instrumentation wrapper created by this monitor.
|
||||
* If the function passed to unwrap is not a wrapper created by this
|
||||
* monitor, then we will do nothing.
|
||||
*
|
||||
* Notice that some wrappers may not be unwrappable. For example, if other
|
||||
* monitors have applied their own wrappers, then it will be impossible to
|
||||
* unwrap them because their wrappers will have captured our wrapper.
|
||||
*
|
||||
* So it is important that entry points are unwrapped in the reverse
|
||||
* order that they were wrapped.
|
||||
*
|
||||
* @param {!Function} fn A function to unwrap.
|
||||
* @return {!Function} The unwrapped function, or {@code fn} if it was not
|
||||
* a wrapped function created by this monitor.
|
||||
*/
|
||||
goog.debug.EntryPointMonitor.prototype.unwrap;
|
||||
|
||||
|
||||
/**
|
||||
* An array of entry point callbacks.
|
||||
* @type {!Array.<function(!Function)>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.refList_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Monitors that should wrap all the entry points.
|
||||
* @type {!Array.<!goog.debug.EntryPointMonitor>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitors_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Whether goog.debug.entryPointRegistry.monitorAll has ever been called.
|
||||
* Checking this allows the compiler to optimize out the registrations.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitorsMayExist_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Register an entry point with this module.
|
||||
*
|
||||
* The entry point will be instrumented when a monitor is passed to
|
||||
* goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the
|
||||
* entry point is instrumented immediately.
|
||||
*
|
||||
* @param {function(!Function)} callback A callback function which is called
|
||||
* with a transforming function to instrument the entry point. The callback
|
||||
* is responsible for wrapping the relevant entry point with the
|
||||
* transforming function.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.register = function(callback) {
|
||||
// Don't use push(), so that this can be compiled out.
|
||||
goog.debug.entryPointRegistry.refList_[
|
||||
goog.debug.entryPointRegistry.refList_.length] = callback;
|
||||
// If no one calls monitorAll, this can be compiled out.
|
||||
if (goog.debug.entryPointRegistry.monitorsMayExist_) {
|
||||
var monitors = goog.debug.entryPointRegistry.monitors_;
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
callback(goog.bind(monitors[i].wrap, monitors[i]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Configures a monitor to wrap all entry points.
|
||||
*
|
||||
* Entry points that have already been registered are immediately wrapped by
|
||||
* the monitor. When an entry point is registered in the future, it will also
|
||||
* be wrapped by the monitor when it is registered.
|
||||
*
|
||||
* @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.monitorAll = function(monitor) {
|
||||
goog.debug.entryPointRegistry.monitorsMayExist_ = true;
|
||||
var transformer = goog.bind(monitor.wrap, monitor);
|
||||
for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
|
||||
goog.debug.entryPointRegistry.refList_[i](transformer);
|
||||
}
|
||||
goog.debug.entryPointRegistry.monitors_.push(monitor);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Try to unmonitor all the entry points that have already been registered. If
|
||||
* an entry point is registered in the future, it will not be wrapped by the
|
||||
* monitor when it is registered. Note that this may fail if the entry points
|
||||
* have additional wrapping.
|
||||
*
|
||||
* @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap
|
||||
* the entry points.
|
||||
* @throws {Error} If the monitor is not the most recently configured monitor.
|
||||
*/
|
||||
goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) {
|
||||
var monitors = goog.debug.entryPointRegistry.monitors_;
|
||||
goog.asserts.assert(monitor == monitors[monitors.length - 1],
|
||||
'Only the most recent monitor can be unwrapped.');
|
||||
var transformer = goog.bind(monitor.unwrap, monitor);
|
||||
for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
|
||||
goog.debug.entryPointRegistry.refList_[i](transformer);
|
||||
}
|
||||
monitors.length--;
|
||||
};
|
||||
51
float-no-zero/closure-library/closure/goog/debug/error.js
Normal file
51
float-no-zero/closure-library/closure/goog/debug/error.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2009 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 Provides a base class for custom Error objects such that the
|
||||
* stack is correctly maintained.
|
||||
*
|
||||
* You should never need to throw goog.debug.Error(msg) directly, Error(msg) is
|
||||
* sufficient.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.Error');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for custom error objects.
|
||||
* @param {*=} opt_msg The message associated with the error.
|
||||
* @constructor
|
||||
* @extends {Error}
|
||||
*/
|
||||
goog.debug.Error = function(opt_msg) {
|
||||
|
||||
// Ensure there is a stack trace.
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, goog.debug.Error);
|
||||
} else {
|
||||
this.stack = new Error().stack || '';
|
||||
}
|
||||
|
||||
if (opt_msg) {
|
||||
this.message = String(opt_msg);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.debug.Error, Error);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.Error.prototype.name = 'CustomError';
|
||||
363
float-no-zero/closure-library/closure/goog/debug/errorhandler.js
Normal file
363
float-no-zero/closure-library/closure/goog/debug/errorhandler.js
Normal file
@@ -0,0 +1,363 @@
|
||||
// Copyright 2007 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 Error handling utilities.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.ErrorHandler');
|
||||
goog.provide('goog.debug.ErrorHandler.ProtectedFunctionError');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.debug.EntryPointMonitor');
|
||||
goog.require('goog.debug.Trace');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The ErrorHandler can be used to to wrap functions with a try/catch
|
||||
* statement. If an exception is thrown, the given error handler function will
|
||||
* be called.
|
||||
*
|
||||
* When this object is disposed, it will stop handling exceptions and tracing.
|
||||
* It will also try to restore window.setTimeout and window.setInterval
|
||||
* if it wrapped them. Notice that in the general case, it is not technically
|
||||
* possible to remove the wrapper, because functions have no knowledge of
|
||||
* what they have been assigned to. So the app is responsible for other
|
||||
* forms of unwrapping.
|
||||
*
|
||||
* @param {Function} handler Handler for exceptions.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @implements {goog.debug.EntryPointMonitor}
|
||||
*/
|
||||
goog.debug.ErrorHandler = function(handler) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Handler for exceptions, which can do logging, reporting, etc.
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.errorHandlerFn_ = handler;
|
||||
|
||||
/**
|
||||
* Whether errors should be wrapped in
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError before rethrowing.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.wrapErrors_ = true; // TODO(user) Change default.
|
||||
|
||||
/**
|
||||
* Whether to add a prefix to all error messages. The prefix is
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX. This option
|
||||
* only has an effect if this.wrapErrors_ is set to false.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.prefixErrorMessages_ = false;
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorHandler, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* Whether to add tracers when instrumenting entry points.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.addTracersToProtectedFunctions_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Enable tracers when instrumenting entry points.
|
||||
* @param {boolean} newVal See above.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.setAddTracersToProtectedFunctions =
|
||||
function(newVal) {
|
||||
this.addTracersToProtectedFunctions_ = newVal;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.wrap = function(fn) {
|
||||
return this.protectEntryPoint(goog.asserts.assertFunction(fn));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.unwrap = function(fn) {
|
||||
goog.asserts.assertFunction(fn);
|
||||
return fn[this.getFunctionIndex_(false)] || fn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private helper function to return a span that can be clicked on to display
|
||||
* an alert with the current stack trace. Newlines are replaced with a
|
||||
* placeholder so that they will not be html-escaped.
|
||||
* @param {string} stackTrace The stack trace to create a span for.
|
||||
* @return {string} A span which can be clicked on to show the stack trace.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.getStackTraceHolder_ = function(stackTrace) {
|
||||
var buffer = [];
|
||||
buffer.push('##PE_STACK_START##');
|
||||
buffer.push(stackTrace.replace(/(\r\n|\r|\n)/g, '##STACK_BR##'));
|
||||
buffer.push('##PE_STACK_END##');
|
||||
return buffer.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the index for a function. Used for internal indexing.
|
||||
* @param {boolean} wrapper True for the wrapper; false for the wrapped.
|
||||
* @return {string} The index where we should store the function in its
|
||||
* wrapper/wrapped function.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.getFunctionIndex_ = function(wrapper) {
|
||||
return (wrapper ? '__wrapper_' : '__protected_') + goog.getUid(this) + '__';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Installs exception protection for an entry point function. When an exception
|
||||
* is thrown from a protected function, a handler will be invoked to handle it.
|
||||
*
|
||||
* @param {Function} fn An entry point function to be protected.
|
||||
* @return {!Function} A protected wrapper function that calls the entry point
|
||||
* function.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectEntryPoint = function(fn) {
|
||||
var protectedFnName = this.getFunctionIndex_(true);
|
||||
if (!fn[protectedFnName]) {
|
||||
var wrapper = fn[protectedFnName] = this.getProtectedFunction(fn);
|
||||
wrapper[this.getFunctionIndex_(false)] = fn;
|
||||
}
|
||||
return fn[protectedFnName];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helps {@link #protectEntryPoint} by actually creating the protected
|
||||
* wrapper function, after {@link #protectEntryPoint} determines that one does
|
||||
* not already exist for the given function. Can be overriden by subclasses
|
||||
* that may want to implement different error handling, or add additional
|
||||
* entry point hooks.
|
||||
* @param {!Function} fn An entry point function to be protected.
|
||||
* @return {!Function} protected wrapper function.
|
||||
* @protected
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.getProtectedFunction = function(fn) {
|
||||
var that = this;
|
||||
var tracers = this.addTracersToProtectedFunctions_;
|
||||
if (tracers) {
|
||||
var stackTrace = goog.debug.getStacktraceSimple(15);
|
||||
}
|
||||
var googDebugErrorHandlerProtectedFunction = function() {
|
||||
if (that.isDisposed()) {
|
||||
return fn.apply(this, arguments);
|
||||
}
|
||||
|
||||
if (tracers) {
|
||||
var tracer = goog.debug.Trace.startTracer('protectedEntryPoint: ' +
|
||||
that.getStackTraceHolder_(stackTrace));
|
||||
}
|
||||
try {
|
||||
return fn.apply(this, arguments);
|
||||
} catch (e) {
|
||||
that.errorHandlerFn_(e);
|
||||
if (!that.wrapErrors_) {
|
||||
// Add the prefix to the existing message.
|
||||
if (that.prefixErrorMessages_) {
|
||||
if (typeof e === 'object') {
|
||||
e.message =
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
|
||||
e.message;
|
||||
} else {
|
||||
e = goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
|
||||
e;
|
||||
}
|
||||
}
|
||||
if (goog.DEBUG) {
|
||||
// Work around for https://code.google.com/p/v8/issues/detail?id=2625
|
||||
// and https://code.google.com/p/chromium/issues/detail?id=237059
|
||||
// Custom errors and errors with custom stack traces show the wrong
|
||||
// stack trace
|
||||
// If it has a stack and Error.captureStackTrace is supported (only
|
||||
// supported in V8 as of May 2013) log the stack to the console.
|
||||
if (e && e.stack && Error.captureStackTrace &&
|
||||
goog.global['console']) {
|
||||
goog.global['console']['error'](e.message, e.stack);
|
||||
}
|
||||
}
|
||||
// Re-throw original error. This is great for debugging as it makes
|
||||
// browser JS dev consoles show the correct error and stack trace.
|
||||
throw e;
|
||||
}
|
||||
// Re-throw it since this may be expected by the caller.
|
||||
throw new goog.debug.ErrorHandler.ProtectedFunctionError(e);
|
||||
} finally {
|
||||
if (tracers) {
|
||||
goog.debug.Trace.stopTracer(tracer);
|
||||
}
|
||||
}
|
||||
};
|
||||
googDebugErrorHandlerProtectedFunction[this.getFunctionIndex_(false)] = fn;
|
||||
return googDebugErrorHandlerProtectedFunction;
|
||||
};
|
||||
|
||||
|
||||
// TODO(user): Allow these functions to take in the window to protect.
|
||||
/**
|
||||
* Installs exception protection for window.setTimeout to handle exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowSetTimeout =
|
||||
function() {
|
||||
this.protectWindowFunctionsHelper_('setTimeout');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install exception protection for window.setInterval to handle exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowSetInterval =
|
||||
function() {
|
||||
this.protectWindowFunctionsHelper_('setInterval');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Install exception protection for window.requestAnimationFrame to handle
|
||||
* exceptions.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowRequestAnimationFrame =
|
||||
function() {
|
||||
var win = goog.getObjectByName('window');
|
||||
var fnNames = [
|
||||
'requestAnimationFrame',
|
||||
'mozRequestAnimationFrame',
|
||||
'webkitAnimationFrame',
|
||||
'msRequestAnimationFrame'
|
||||
];
|
||||
for (var i = 0; i < fnNames.length; i++) {
|
||||
var fnName = fnNames[i];
|
||||
if (fnNames[i] in win) {
|
||||
win[fnName] = this.protectEntryPoint(win[fnName]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for protecting setTimeout/setInterval.
|
||||
* @param {string} fnName The name of the function we're protecting. Must
|
||||
* be setTimeout or setInterval.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.protectWindowFunctionsHelper_ =
|
||||
function(fnName) {
|
||||
var win = goog.getObjectByName('window');
|
||||
var originalFn = win[fnName];
|
||||
var that = this;
|
||||
win[fnName] = function(fn, time) {
|
||||
// Don't try to protect strings. In theory, we could try to globalEval
|
||||
// the string, but this seems to lead to permission errors on IE6.
|
||||
if (goog.isString(fn)) {
|
||||
fn = goog.partial(goog.globalEval, fn);
|
||||
}
|
||||
fn = that.protectEntryPoint(fn);
|
||||
|
||||
// IE doesn't support .call for setInterval/setTimeout, but it
|
||||
// also doesn't care what "this" is, so we can just call the
|
||||
// original function directly
|
||||
if (originalFn.call) {
|
||||
return originalFn.call(this, fn, time);
|
||||
} else {
|
||||
return originalFn(fn, time);
|
||||
}
|
||||
};
|
||||
win[fnName][this.getFunctionIndex_(false)] = originalFn;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to wrap errors that occur in protected functions in a
|
||||
* goog.debug.ErrorHandler.ProtectedFunctionError.
|
||||
* @param {boolean} wrapErrors Whether to wrap errors.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.setWrapErrors = function(wrapErrors) {
|
||||
this.wrapErrors_ = wrapErrors;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to add a prefix to all error messages that occur in protected
|
||||
* functions.
|
||||
* @param {boolean} prefixErrorMessages Whether to add a prefix to error
|
||||
* messages.
|
||||
*/
|
||||
goog.debug.ErrorHandler.prototype.setPrefixErrorMessages =
|
||||
function(prefixErrorMessages) {
|
||||
this.prefixErrorMessages_ = prefixErrorMessages;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorHandler.prototype.disposeInternal = function() {
|
||||
// Try to unwrap window.setTimeout and window.setInterval.
|
||||
var win = goog.getObjectByName('window');
|
||||
win.setTimeout = this.unwrap(win.setTimeout);
|
||||
win.setInterval = this.unwrap(win.setInterval);
|
||||
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error thrown to the caller of a protected entry point if the entry point
|
||||
* throws an error.
|
||||
* @param {*} cause The error thrown by the entry point.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError = function(cause) {
|
||||
var message = goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
|
||||
(cause && cause.message ? String(cause.message) : String(cause));
|
||||
goog.base(this, message);
|
||||
|
||||
/**
|
||||
* The error thrown by the entry point.
|
||||
* @type {*}
|
||||
*/
|
||||
this.cause = cause;
|
||||
|
||||
var stack = cause && cause.stack;
|
||||
if (stack && goog.isString(stack)) {
|
||||
this.stack = /** @type {string} */ (stack);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorHandler.ProtectedFunctionError, goog.debug.Error);
|
||||
|
||||
|
||||
/**
|
||||
* Text to prefix the message with.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX =
|
||||
'Error in protected function: ';
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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 File which defines dummy object to work around undefined
|
||||
* properties compiler warning for weak dependencies on
|
||||
* {@link goog.debug.ErrorHandler#protectEntryPoint}.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.errorHandlerWeakDep');
|
||||
|
||||
|
||||
/**
|
||||
* Dummy object to work around undefined properties compiler warning.
|
||||
* @type {Object}
|
||||
*/
|
||||
goog.debug.errorHandlerWeakDep = {
|
||||
/**
|
||||
* @param {Function} fn An entry point function to be protected.
|
||||
* @param {boolean=} opt_tracers Whether to install tracers around the
|
||||
* fn.
|
||||
* @return {Function} A protected wrapper function that calls the
|
||||
* entry point function.
|
||||
*/
|
||||
protectEntryPoint: function(fn, opt_tracers) { return fn; }
|
||||
};
|
||||
@@ -0,0 +1,376 @@
|
||||
// Copyright 2009 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 Definition of the ErrorReporter class, which creates an error
|
||||
* handler that reports any errors raised to a URL.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.ErrorReporter');
|
||||
goog.provide('goog.debug.ErrorReporter.ExceptionEvent');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.debug.ErrorHandler');
|
||||
goog.require('goog.debug.entryPointRegistry');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.net.XhrIo');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.uri.utils');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an error reporter. Internal Use Only. To install an error
|
||||
* reporter see the {@see #install} method below.
|
||||
*
|
||||
* @param {string} handlerUrl The URL to which all errors will be reported.
|
||||
* @param {function(!Error, !Object.<string, string>)=}
|
||||
* opt_contextProvider When a report is to be sent to the server,
|
||||
* this method will be called, and given an opportunity to modify the
|
||||
* context object before submission to the server.
|
||||
* @param {boolean=} opt_noAutoProtect Whether to automatically add handlers for
|
||||
* onerror and to protect entry points. If apps have other error reporting
|
||||
* facilities, it may make sense for them to set these up themselves and use
|
||||
* the ErrorReporter just for transmission of reports.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*/
|
||||
goog.debug.ErrorReporter = function(
|
||||
handlerUrl, opt_contextProvider, opt_noAutoProtect) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* Context provider, if one was provided.
|
||||
* @type {?function(!Error, !Object.<string, string>)}
|
||||
* @private
|
||||
*/
|
||||
this.contextProvider_ = opt_contextProvider || null;
|
||||
|
||||
/**
|
||||
* The string prefix of any optional context parameters logged with the error.
|
||||
* @private {string}
|
||||
*/
|
||||
this.contextPrefix_ = 'context.';
|
||||
|
||||
/**
|
||||
* The number of bytes after which the ErrorReporter truncates the POST body.
|
||||
* If null, the ErrorReporter won't truncate the body.
|
||||
* @private {?number}
|
||||
*/
|
||||
this.truncationLimit_ = null;
|
||||
|
||||
/**
|
||||
* XHR sender.
|
||||
* @type {function(string, string, string, (Object|goog.structs.Map)=)}
|
||||
* @private
|
||||
*/
|
||||
this.xhrSender_ = goog.debug.ErrorReporter.defaultXhrSender;
|
||||
|
||||
/**
|
||||
* The URL at which all errors caught by this handler will be logged.
|
||||
*
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.handlerUrl_ = handlerUrl;
|
||||
|
||||
if (!opt_noAutoProtect) {
|
||||
this.setup_();
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorReporter, goog.events.EventTarget);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Event broadcast when an exception is logged.
|
||||
* @param {Error} error The exception that was was reported.
|
||||
* @param {!Object.<string, string>} context The context values sent to the
|
||||
* server alongside this error.
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
*/
|
||||
goog.debug.ErrorReporter.ExceptionEvent = function(error, context) {
|
||||
goog.events.Event.call(this, goog.debug.ErrorReporter.ExceptionEvent.TYPE);
|
||||
|
||||
/**
|
||||
* The error that was reported.
|
||||
* @type {Error}
|
||||
*/
|
||||
this.error = error;
|
||||
|
||||
/**
|
||||
* Context values sent to the server alongside this report.
|
||||
* @type {!Object.<string, string>}
|
||||
*/
|
||||
this.context = context;
|
||||
};
|
||||
goog.inherits(goog.debug.ErrorReporter.ExceptionEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* Event type for notifying of a logged exception.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.debug.ErrorReporter.ExceptionEvent.TYPE =
|
||||
goog.events.getUniqueId('exception');
|
||||
|
||||
|
||||
/**
|
||||
* The internal error handler used to catch all errors.
|
||||
*
|
||||
* @type {goog.debug.ErrorHandler}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.errorHandler_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Extra headers for the error-reporting XHR.
|
||||
* @type {Object|goog.structs.Map|undefined}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.extraHeaders_;
|
||||
|
||||
|
||||
/**
|
||||
* Logging object.
|
||||
*
|
||||
* @type {goog.log.Logger}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorReporter.logger_ =
|
||||
goog.log.getLogger('goog.debug.ErrorReporter');
|
||||
|
||||
|
||||
/**
|
||||
* Installs an error reporter to catch all JavaScript errors raised.
|
||||
*
|
||||
* @param {string} loggingUrl The URL to which the errors caught will be
|
||||
* reported.
|
||||
* @param {function(!Error, !Object.<string, string>)=}
|
||||
* opt_contextProvider When a report is to be sent to the server,
|
||||
* this method will be called, and given an opportunity to modify the
|
||||
* context object before submission to the server.
|
||||
* @param {boolean=} opt_noAutoProtect Whether to automatically add handlers for
|
||||
* onerror and to protect entry points. If apps have other error reporting
|
||||
* facilities, it may make sense for them to set these up themselves and use
|
||||
* the ErrorReporter just for transmission of reports.
|
||||
* @return {goog.debug.ErrorReporter} The error reporter.
|
||||
*/
|
||||
goog.debug.ErrorReporter.install = function(
|
||||
loggingUrl, opt_contextProvider, opt_noAutoProtect) {
|
||||
var instance = new goog.debug.ErrorReporter(
|
||||
loggingUrl, opt_contextProvider, opt_noAutoProtect);
|
||||
return instance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default implemntation of XHR sender interface.
|
||||
*
|
||||
* @param {string} uri URI to make request to.
|
||||
* @param {string} method Send method.
|
||||
* @param {string} content Post data.
|
||||
* @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
|
||||
* request.
|
||||
*/
|
||||
goog.debug.ErrorReporter.defaultXhrSender = function(uri, method, content,
|
||||
opt_headers) {
|
||||
goog.net.XhrIo.send(uri, null, method, content, opt_headers);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Installs exception protection for an entry point function in addition
|
||||
* to those that are protected by default.
|
||||
* Has no effect in IE because window.onerror is used for reporting
|
||||
* exceptions in that case.
|
||||
*
|
||||
* @param {Function} fn An entry point function to be protected.
|
||||
* @return {Function} A protected wrapper function that calls the entry point
|
||||
* function or null if the entry point could not be protected.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.protectAdditionalEntryPoint = function(fn) {
|
||||
if (this.errorHandler_) {
|
||||
return this.errorHandler_.protectEntryPoint(fn);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add headers to the logging url.
|
||||
* @param {Object|goog.structs.Map} loggingHeaders Extra headers to send
|
||||
* to the logging URL.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.setLoggingHeaders =
|
||||
function(loggingHeaders) {
|
||||
this.extraHeaders_ = loggingHeaders;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the function used to send error reports to the server.
|
||||
* @param {function(string, string, string, (Object|goog.structs.Map)=)}
|
||||
* xhrSender If provided, this will be used to send a report to the
|
||||
* server instead of the default method. The function will be given the URI,
|
||||
* HTTP method request content, and (optionally) request headers to be
|
||||
* added.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.setXhrSender = function(xhrSender) {
|
||||
this.xhrSender_ = xhrSender;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets up the error reporter.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.setup_ = function() {
|
||||
if (goog.userAgent.IE) {
|
||||
// Use "onerror" because caught exceptions in IE don't provide line number.
|
||||
goog.debug.catchErrors(
|
||||
goog.bind(this.handleException, this), false, null);
|
||||
} else {
|
||||
// "onerror" doesn't work with FF2 or Chrome
|
||||
this.errorHandler_ = new goog.debug.ErrorHandler(
|
||||
goog.bind(this.handleException, this));
|
||||
|
||||
this.errorHandler_.protectWindowSetTimeout();
|
||||
this.errorHandler_.protectWindowSetInterval();
|
||||
goog.debug.entryPointRegistry.monitorAll(this.errorHandler_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for caught exceptions. Sends report to the LoggingServlet and
|
||||
* notifies any listeners.
|
||||
*
|
||||
* @param {Object} e The exception.
|
||||
* @param {!Object.<string, string>=} opt_context Context values to optionally
|
||||
* include in the error report.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.handleException = function(e,
|
||||
opt_context) {
|
||||
var error = /** @type {!Error} */ (goog.debug.normalizeErrorObject(e));
|
||||
|
||||
// Construct the context, possibly from the one provided in the argument, and
|
||||
// pass it to the context provider if there is one.
|
||||
var context = opt_context ? goog.object.clone(opt_context) : {};
|
||||
if (this.contextProvider_) {
|
||||
try {
|
||||
this.contextProvider_(error, context);
|
||||
} catch (err) {
|
||||
goog.log.error(goog.debug.ErrorReporter.logger_,
|
||||
'Context provider threw an exception: ' + err.message);
|
||||
}
|
||||
}
|
||||
// Truncate message to a reasonable length, since it will be sent in the URL.
|
||||
var message = error.message.substring(0, 2000);
|
||||
this.sendErrorReport(message, error.fileName, error.lineNumber, error.stack,
|
||||
context);
|
||||
|
||||
try {
|
||||
this.dispatchEvent(
|
||||
new goog.debug.ErrorReporter.ExceptionEvent(error, context));
|
||||
} catch (ex) {
|
||||
// Swallow exception to avoid infinite recursion.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends an error report to the logging URL. This will not consult the context
|
||||
* provider, the report will be sent exactly as specified.
|
||||
*
|
||||
* @param {string} message Error description.
|
||||
* @param {string} fileName URL of the JavaScript file with the error.
|
||||
* @param {number} line Line number of the error.
|
||||
* @param {string=} opt_trace Call stack trace of the error.
|
||||
* @param {!Object.<string, string>=} opt_context Context information to include
|
||||
* in the request.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.sendErrorReport =
|
||||
function(message, fileName, line, opt_trace, opt_context) {
|
||||
try {
|
||||
// Create the logging URL.
|
||||
var requestUrl = goog.uri.utils.appendParams(this.handlerUrl_,
|
||||
'script', fileName, 'error', message, 'line', line);
|
||||
var queryMap = {};
|
||||
queryMap['trace'] = opt_trace;
|
||||
|
||||
// Copy context into query data map
|
||||
if (opt_context) {
|
||||
for (var entry in opt_context) {
|
||||
queryMap[this.contextPrefix_ + entry] = opt_context[entry];
|
||||
}
|
||||
}
|
||||
|
||||
// Copy query data map into request.
|
||||
var queryData = goog.uri.utils.buildQueryDataFromMap(queryMap);
|
||||
|
||||
// Truncate if truncationLimit set.
|
||||
if (goog.isNumber(this.truncationLimit_)) {
|
||||
queryData = queryData.substring(0, this.truncationLimit_);
|
||||
}
|
||||
|
||||
// Send the request with the contents of the error.
|
||||
this.xhrSender_(requestUrl, 'POST', queryData, this.extraHeaders_);
|
||||
} catch (e) {
|
||||
var logMessage = goog.string.buildString(
|
||||
'Error occurred in sending an error report.\n\n',
|
||||
'script:', fileName, '\n',
|
||||
'line:', line, '\n',
|
||||
'error:', message, '\n',
|
||||
'trace:', opt_trace);
|
||||
goog.log.info(goog.debug.ErrorReporter.logger_, logMessage);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} prefix The prefix to appear prepended to all context
|
||||
* variables in the error report body.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.setContextPrefix = function(prefix) {
|
||||
this.contextPrefix_ = prefix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {?number} limit Size in bytes to begin truncating POST body. Set to
|
||||
* null to prevent truncation. The limit must be >= 0.
|
||||
*/
|
||||
goog.debug.ErrorReporter.prototype.setTruncationLimit = function(limit) {
|
||||
goog.asserts.assert(!goog.isNumber(limit) || limit >= 0,
|
||||
'Body limit must be valid number >= 0 or null');
|
||||
this.truncationLimit_ = limit;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.ErrorReporter.prototype.disposeInternal = function() {
|
||||
goog.dispose(this.errorHandler_);
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
362
float-no-zero/closure-library/closure/goog/debug/fancywindow.js
Normal file
362
float-no-zero/closure-library/closure/goog/debug/fancywindow.js
Normal file
@@ -0,0 +1,362 @@
|
||||
// Copyright 2006 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 Definition of the FancyWindow class. Please minimize
|
||||
* dependencies this file has on other closure classes as any dependency it
|
||||
* takes won't be able to use the logging infrastructure.
|
||||
*
|
||||
* This is a pretty hacky implementation, aimed at making debugging of large
|
||||
* applications more manageable.
|
||||
*
|
||||
* @see ../demos/debug.html
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.debug.FancyWindow');
|
||||
|
||||
goog.require('goog.debug.DebugWindow');
|
||||
goog.require('goog.debug.LogManager');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dom.DomHelper');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Provides a Fancy extension to the DebugWindow class. Allows filtering based
|
||||
* on loggers and levels.
|
||||
*
|
||||
* @param {string=} opt_identifier Idenitifier for this logging class.
|
||||
* @param {string=} opt_prefix Prefix pre-pended to messages.
|
||||
* @constructor
|
||||
* @extends {goog.debug.DebugWindow}
|
||||
*/
|
||||
goog.debug.FancyWindow = function(opt_identifier, opt_prefix) {
|
||||
this.readOptionsFromLocalStorage_();
|
||||
goog.base(this, opt_identifier, opt_prefix);
|
||||
};
|
||||
goog.inherits(goog.debug.FancyWindow, goog.debug.DebugWindow);
|
||||
|
||||
|
||||
/**
|
||||
* Constant indicating if we are able to use localStorage to persist filters
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.FancyWindow.HAS_LOCAL_STORE = (function() {
|
||||
/** @preserveTry */
|
||||
try {
|
||||
return !!window['localStorage'].getItem;
|
||||
} catch (e) {}
|
||||
return false;
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* Constant defining the prefix to use when storing log levels
|
||||
* @type {string}
|
||||
*/
|
||||
goog.debug.FancyWindow.LOCAL_STORE_PREFIX = 'fancywindow.sel.';
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FancyWindow.prototype.writeBufferToLog = function() {
|
||||
this.lastCall = goog.now();
|
||||
if (this.hasActiveWindow()) {
|
||||
var logel = this.dh_.getElement('log');
|
||||
|
||||
// Work out if scrolling is needed before we add the content
|
||||
var scroll =
|
||||
logel.scrollHeight - (logel.scrollTop + logel.offsetHeight) <= 100;
|
||||
|
||||
for (var i = 0; i < this.outputBuffer.length; i++) {
|
||||
var div = this.dh_.createDom('div', 'logmsg');
|
||||
div.innerHTML = this.outputBuffer[i];
|
||||
logel.appendChild(div);
|
||||
}
|
||||
this.outputBuffer.length = 0;
|
||||
this.resizeStuff_();
|
||||
|
||||
if (scroll) {
|
||||
logel.scrollTop = logel.scrollHeight;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FancyWindow.prototype.writeInitialDocument = function() {
|
||||
if (!this.hasActiveWindow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = this.win.document;
|
||||
doc.open();
|
||||
doc.write(this.getHtml_());
|
||||
doc.close();
|
||||
|
||||
(goog.userAgent.IE ? doc.body : this.win).onresize =
|
||||
goog.bind(this.resizeStuff_, this);
|
||||
|
||||
// Create a dom helper for the logging window
|
||||
this.dh_ = new goog.dom.DomHelper(doc);
|
||||
|
||||
// Don't use events system to reduce dependencies
|
||||
this.dh_.getElement('openbutton').onclick =
|
||||
goog.bind(this.openOptions_, this);
|
||||
this.dh_.getElement('closebutton').onclick =
|
||||
goog.bind(this.closeOptions_, this);
|
||||
this.dh_.getElement('clearbutton').onclick =
|
||||
goog.bind(this.clear, this);
|
||||
this.dh_.getElement('exitbutton').onclick =
|
||||
goog.bind(this.exit_, this);
|
||||
|
||||
this.writeSavedMessages();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Show the options menu.
|
||||
* @return {boolean} false.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.openOptions_ = function() {
|
||||
var el = this.dh_.getElement('optionsarea');
|
||||
el.innerHTML = '';
|
||||
|
||||
var loggers = goog.debug.FancyWindow.getLoggers_();
|
||||
var dh = this.dh_;
|
||||
for (var i = 0; i < loggers.length; i++) {
|
||||
var logger = goog.debug.Logger.getLogger(loggers[i]);
|
||||
var curlevel = logger.getLevel() ? logger.getLevel().name : 'INHERIT';
|
||||
var div = dh.createDom('div', {},
|
||||
this.getDropDown_('sel' + loggers[i], curlevel),
|
||||
dh.createDom('span', {}, loggers[i] || '(root)'));
|
||||
el.appendChild(div);
|
||||
}
|
||||
|
||||
this.dh_.getElement('options').style.display = 'block';
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make a drop down for the log levels.
|
||||
* @param {string} id Logger id.
|
||||
* @param {string} selected What log level is currently selected.
|
||||
* @return {Element} The newly created 'select' DOM element.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.getDropDown_ = function(id, selected) {
|
||||
var dh = this.dh_;
|
||||
var sel = dh.createDom('select', {'id': id});
|
||||
var levels = goog.debug.Logger.Level.PREDEFINED_LEVELS;
|
||||
for (var i = 0; i < levels.length; i++) {
|
||||
var level = levels[i];
|
||||
var option = dh.createDom('option', {}, level.name);
|
||||
if (selected == level.name) {
|
||||
option.selected = true;
|
||||
}
|
||||
sel.appendChild(option);
|
||||
}
|
||||
sel.appendChild(dh.createDom('option',
|
||||
{'selected': selected == 'INHERIT'}, 'INHERIT'));
|
||||
return sel;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Close the options menu.
|
||||
* @return {boolean} The value false.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.closeOptions_ = function() {
|
||||
this.dh_.getElement('options').style.display = 'none';
|
||||
var loggers = goog.debug.FancyWindow.getLoggers_();
|
||||
var dh = this.dh_;
|
||||
for (var i = 0; i < loggers.length; i++) {
|
||||
var logger = goog.debug.Logger.getLogger(loggers[i]);
|
||||
var sel = dh.getElement('sel' + loggers[i]);
|
||||
var level = sel.options[sel.selectedIndex].text;
|
||||
if (level == 'INHERIT') {
|
||||
logger.setLevel(null);
|
||||
} else {
|
||||
logger.setLevel(goog.debug.Logger.Level.getPredefinedLevel(level));
|
||||
}
|
||||
}
|
||||
this.writeOptionsToLocalStorage_();
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resize the lof elements
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.resizeStuff_ = function() {
|
||||
var dh = this.dh_;
|
||||
var logel = dh.getElement('log');
|
||||
var headel = dh.getElement('head');
|
||||
logel.style.top = headel.offsetHeight + 'px';
|
||||
logel.style.height = (dh.getDocument().body.offsetHeight -
|
||||
headel.offsetHeight - (goog.userAgent.IE ? 4 : 0)) + 'px';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles the user clicking the exit button, disabled the debug window and
|
||||
* closes the popup.
|
||||
* @param {Event} e Event object.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.exit_ = function(e) {
|
||||
this.setEnabled(false);
|
||||
if (this.win) {
|
||||
this.win.close();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FancyWindow.prototype.getStyleRules = function() {
|
||||
return goog.base(this, 'getStyleRules') +
|
||||
'html,body{height:100%;width:100%;margin:0px;padding:0px;' +
|
||||
'background-color:#FFF;overflow:hidden}' +
|
||||
'*{}' +
|
||||
'.logmsg{border-bottom:1px solid #CCC;padding:2px;font:90% monospace}' +
|
||||
'#head{position:absolute;width:100%;font:x-small arial;' +
|
||||
'border-bottom:2px solid #999;background-color:#EEE;}' +
|
||||
'#head p{margin:0px 5px;}' +
|
||||
'#log{position:absolute;width:100%;background-color:#FFF;}' +
|
||||
'#options{position:absolute;right:0px;width:50%;height:100%;' +
|
||||
'border-left:1px solid #999;background-color:#DDD;display:none;' +
|
||||
'padding-left: 5px;font:normal small arial;overflow:auto;}' +
|
||||
'#openbutton,#closebutton{text-decoration:underline;color:#00F;cursor:' +
|
||||
'pointer;position:absolute;top:0px;right:5px;font:x-small arial;}' +
|
||||
'#clearbutton{text-decoration:underline;color:#00F;cursor:' +
|
||||
'pointer;position:absolute;top:0px;right:80px;font:x-small arial;}' +
|
||||
'#exitbutton{text-decoration:underline;color:#00F;cursor:' +
|
||||
'pointer;position:absolute;top:0px;right:50px;font:x-small arial;}' +
|
||||
'select{font:x-small arial;margin-right:10px;}' +
|
||||
'hr{border:0;height:5px;background-color:#8c8;color:#8c8;}';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the default HTML for the debug window
|
||||
* @return {string} Html.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.getHtml_ = function() {
|
||||
return '' +
|
||||
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"' +
|
||||
'"http://www.w3.org/TR/html4/loose.dtd">' +
|
||||
'<html><head><title>Logging: ' + this.identifier + '</title>' +
|
||||
'<style>' + this.getStyleRules() + '</style>' +
|
||||
'</head><body>' +
|
||||
'<div id="log" style="overflow:auto"></div>' +
|
||||
'<div id="head">' +
|
||||
'<p><b>Logging: ' + this.identifier + '</b></p><p>' +
|
||||
this.welcomeMessage + '</p>' +
|
||||
'<span id="clearbutton">clear</span>' +
|
||||
'<span id="exitbutton">exit</span>' +
|
||||
'<span id="openbutton">options</span>' +
|
||||
'</div>' +
|
||||
'<div id="options">' +
|
||||
'<big><b>Options:</b></big>' +
|
||||
'<div id="optionsarea"></div>' +
|
||||
'<span id="closebutton">save and close</span>' +
|
||||
'</div>' +
|
||||
'</body></html>';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Write logger levels to localStorage if possible.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.writeOptionsToLocalStorage_ = function() {
|
||||
if (!goog.debug.FancyWindow.HAS_LOCAL_STORE) {
|
||||
return;
|
||||
}
|
||||
var loggers = goog.debug.FancyWindow.getLoggers_();
|
||||
var storedKeys = goog.debug.FancyWindow.getStoredKeys_();
|
||||
for (var i = 0; i < loggers.length; i++) {
|
||||
var key = goog.debug.FancyWindow.LOCAL_STORE_PREFIX + loggers[i];
|
||||
var level = goog.debug.Logger.getLogger(loggers[i]).getLevel();
|
||||
if (key in storedKeys) {
|
||||
if (!level) {
|
||||
window.localStorage.removeItem(key);
|
||||
} else if (window.localStorage.getItem(key) != level.name) {
|
||||
window.localStorage.setItem(key, level.name);
|
||||
}
|
||||
} else if (level) {
|
||||
window.localStorage.setItem(key, level.name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sync logger levels with any values stored in localStorage.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.prototype.readOptionsFromLocalStorage_ = function() {
|
||||
if (!goog.debug.FancyWindow.HAS_LOCAL_STORE) {
|
||||
return;
|
||||
}
|
||||
var storedKeys = goog.debug.FancyWindow.getStoredKeys_();
|
||||
for (var key in storedKeys) {
|
||||
var loggerName = key.replace(goog.debug.FancyWindow.LOCAL_STORE_PREFIX, '');
|
||||
var logger = goog.debug.Logger.getLogger(loggerName);
|
||||
var curLevel = logger.getLevel();
|
||||
var storedLevel = window.localStorage.getItem(key).toString();
|
||||
if (!curLevel || curLevel.toString() != storedLevel) {
|
||||
logger.setLevel(goog.debug.Logger.Level.getPredefinedLevel(storedLevel));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to create a list of locally stored keys. Used to avoid
|
||||
* expensive localStorage.getItem() calls.
|
||||
* @return {Object} List of keys.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.getStoredKeys_ = function() {
|
||||
var storedKeys = {};
|
||||
for (var i = 0, len = window.localStorage.length; i < len; i++) {
|
||||
var key = window.localStorage.key(i);
|
||||
if (key != null && goog.string.startsWith(
|
||||
key, goog.debug.FancyWindow.LOCAL_STORE_PREFIX)) {
|
||||
storedKeys[key] = true;
|
||||
}
|
||||
}
|
||||
return storedKeys;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a sorted array of all the loggers registered
|
||||
* @return {Array} Array of logger idents, e.g. goog.net.XhrIo.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FancyWindow.getLoggers_ = function() {
|
||||
var loggers = goog.object.getKeys(goog.debug.LogManager.getLoggers());
|
||||
loggers.sort();
|
||||
return loggers;
|
||||
};
|
||||
316
float-no-zero/closure-library/closure/goog/debug/formatter.js
Normal file
316
float-no-zero/closure-library/closure/goog/debug/formatter.js
Normal file
@@ -0,0 +1,316 @@
|
||||
// Copyright 2006 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 Definition of various formatters for logging. Please minimize
|
||||
* dependencies this file has on other closure classes as any dependency it
|
||||
* takes won't be able to use the logging infrastructure.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.Formatter');
|
||||
goog.provide('goog.debug.HtmlFormatter');
|
||||
goog.provide('goog.debug.TextFormatter');
|
||||
|
||||
goog.require('goog.debug.RelativeTimeProvider');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for Formatters. A Formatter is used to format a LogRecord into
|
||||
* something that can be displayed to the user.
|
||||
*
|
||||
* @param {string=} opt_prefix The prefix to place before text records.
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.Formatter = function(opt_prefix) {
|
||||
this.prefix_ = opt_prefix || '';
|
||||
|
||||
/**
|
||||
* A provider that returns the relative start time.
|
||||
* @type {goog.debug.RelativeTimeProvider}
|
||||
* @private
|
||||
*/
|
||||
this.startTimeProvider_ =
|
||||
goog.debug.RelativeTimeProvider.getDefaultInstance();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show absolute time in the DebugWindow.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.Formatter.prototype.showAbsoluteTime = true;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show relative time in the DebugWindow.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.Formatter.prototype.showRelativeTime = true;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show the logger name in the DebugWindow.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.Formatter.prototype.showLoggerName = true;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show the logger exception text.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.Formatter.prototype.showExceptionText = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show the severity level.
|
||||
* @type {boolean}
|
||||
*/
|
||||
goog.debug.Formatter.prototype.showSeverityLevel = false;
|
||||
|
||||
|
||||
/**
|
||||
* Formats a record.
|
||||
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
|
||||
* @return {string} The formatted string.
|
||||
*/
|
||||
goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the start time provider. By default, this is the default instance
|
||||
* but can be changed.
|
||||
* @param {goog.debug.RelativeTimeProvider} provider The provider to use.
|
||||
*/
|
||||
goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
|
||||
this.startTimeProvider_ = provider;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start time provider. By default, this is the default instance
|
||||
* but can be changed.
|
||||
* @return {goog.debug.RelativeTimeProvider} The start time provider.
|
||||
*/
|
||||
goog.debug.Formatter.prototype.getStartTimeProvider = function() {
|
||||
return this.startTimeProvider_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resets the start relative time.
|
||||
*/
|
||||
goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
|
||||
this.startTimeProvider_.reset();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string for the time/date of the LogRecord.
|
||||
* @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
|
||||
* @return {string} A string representation of the time/date of the LogRecord.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
|
||||
var time = new Date(logRecord.getMillis());
|
||||
return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
|
||||
goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
|
||||
goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
|
||||
goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
|
||||
goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
|
||||
goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
|
||||
goog.debug.Formatter.getTwoDigitString_(
|
||||
Math.floor(time.getMilliseconds() / 10));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number as a two-digit string, meaning it prepends a 0 if the
|
||||
* number if less than 10.
|
||||
* @param {number} n The number to format.
|
||||
* @return {string} A two-digit string representation of {@code n}.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Formatter.getTwoDigitString_ = function(n) {
|
||||
if (n < 10) {
|
||||
return '0' + n;
|
||||
}
|
||||
return String(n);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string for the number of seconds relative to the start time.
|
||||
* Prepads with spaces so that anything less than 1000 seconds takes up the
|
||||
* same number of characters for better formatting.
|
||||
* @param {goog.debug.LogRecord} logRecord The log to compare time to.
|
||||
* @param {number} relativeTimeStart The start time to compare to.
|
||||
* @return {string} The number of seconds of the LogRecord relative to the
|
||||
* start time.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Formatter.getRelativeTime_ = function(logRecord,
|
||||
relativeTimeStart) {
|
||||
var ms = logRecord.getMillis() - relativeTimeStart;
|
||||
var sec = ms / 1000;
|
||||
var str = sec.toFixed(3);
|
||||
|
||||
var spacesToPrepend = 0;
|
||||
if (sec < 1) {
|
||||
spacesToPrepend = 2;
|
||||
} else {
|
||||
while (sec < 100) {
|
||||
spacesToPrepend++;
|
||||
sec *= 10;
|
||||
}
|
||||
}
|
||||
while (spacesToPrepend-- > 0) {
|
||||
str = ' ' + str;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Formatter that returns formatted html. See formatRecord for the classes
|
||||
* it uses for various types of formatted output.
|
||||
*
|
||||
* @param {string=} opt_prefix The prefix to place before text records.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Formatter}
|
||||
*/
|
||||
goog.debug.HtmlFormatter = function(opt_prefix) {
|
||||
goog.debug.Formatter.call(this, opt_prefix);
|
||||
};
|
||||
goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
|
||||
|
||||
|
||||
/**
|
||||
* Whether to show the logger exception text
|
||||
* @type {boolean}
|
||||
* @override
|
||||
*/
|
||||
goog.debug.HtmlFormatter.prototype.showExceptionText = true;
|
||||
|
||||
|
||||
/**
|
||||
* Formats a record
|
||||
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
|
||||
* @return {string} The formatted string as html.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
|
||||
var className;
|
||||
switch (logRecord.getLevel().value) {
|
||||
case goog.debug.Logger.Level.SHOUT.value:
|
||||
className = 'dbg-sh';
|
||||
break;
|
||||
case goog.debug.Logger.Level.SEVERE.value:
|
||||
className = 'dbg-sev';
|
||||
break;
|
||||
case goog.debug.Logger.Level.WARNING.value:
|
||||
className = 'dbg-w';
|
||||
break;
|
||||
case goog.debug.Logger.Level.INFO.value:
|
||||
className = 'dbg-i';
|
||||
break;
|
||||
case goog.debug.Logger.Level.FINE.value:
|
||||
default:
|
||||
className = 'dbg-f';
|
||||
break;
|
||||
}
|
||||
|
||||
// Build message html
|
||||
var sb = [];
|
||||
sb.push(this.prefix_, ' ');
|
||||
if (this.showAbsoluteTime) {
|
||||
sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
|
||||
}
|
||||
if (this.showRelativeTime) {
|
||||
sb.push('[',
|
||||
goog.string.whitespaceEscape(
|
||||
goog.debug.Formatter.getRelativeTime_(logRecord,
|
||||
this.startTimeProvider_.get())),
|
||||
's] ');
|
||||
}
|
||||
|
||||
if (this.showLoggerName) {
|
||||
sb.push('[', goog.string.htmlEscape(logRecord.getLoggerName()), '] ');
|
||||
}
|
||||
if (this.showSeverityLevel) {
|
||||
sb.push('[', goog.string.htmlEscape(logRecord.getLevel().name), '] ');
|
||||
}
|
||||
sb.push('<span class="', className, '">',
|
||||
goog.string.newLineToBr(goog.string.whitespaceEscape(
|
||||
goog.string.htmlEscape(logRecord.getMessage()))));
|
||||
|
||||
if (this.showExceptionText && logRecord.getException()) {
|
||||
sb.push('<br>',
|
||||
goog.string.newLineToBr(goog.string.whitespaceEscape(
|
||||
logRecord.getExceptionText() || '')));
|
||||
}
|
||||
sb.push('</span><br>');
|
||||
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Formatter that returns formatted plain text
|
||||
*
|
||||
* @param {string=} opt_prefix The prefix to place before text records.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Formatter}
|
||||
*/
|
||||
goog.debug.TextFormatter = function(opt_prefix) {
|
||||
goog.debug.Formatter.call(this, opt_prefix);
|
||||
};
|
||||
goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
|
||||
|
||||
|
||||
/**
|
||||
* Formats a record as text
|
||||
* @param {goog.debug.LogRecord} logRecord the logRecord to format.
|
||||
* @return {string} The formatted string.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
|
||||
// Build message html
|
||||
var sb = [];
|
||||
sb.push(this.prefix_, ' ');
|
||||
if (this.showAbsoluteTime) {
|
||||
sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
|
||||
}
|
||||
if (this.showRelativeTime) {
|
||||
sb.push('[', goog.debug.Formatter.getRelativeTime_(logRecord,
|
||||
this.startTimeProvider_.get()), 's] ');
|
||||
}
|
||||
|
||||
if (this.showLoggerName) {
|
||||
sb.push('[', logRecord.getLoggerName(), '] ');
|
||||
}
|
||||
if (this.showSeverityLevel) {
|
||||
sb.push('[', logRecord.getLevel().name, '] ');
|
||||
}
|
||||
sb.push(logRecord.getMessage(), '\n');
|
||||
if (this.showExceptionText && logRecord.getException()) {
|
||||
sb.push(logRecord.getExceptionText(), '\n');
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
162
float-no-zero/closure-library/closure/goog/debug/fpsdisplay.js
Normal file
162
float-no-zero/closure-library/closure/goog/debug/fpsdisplay.js
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright 2011 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 Displays frames per second (FPS) for the current window.
|
||||
* Only supported in browsers that support requestAnimationFrame.
|
||||
* See: https://developer.mozilla.org/en/DOM/window.requestAnimationFrame.
|
||||
*
|
||||
* @see ../demos/fpsdisplay.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.FpsDisplay');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.async.AnimationDelay');
|
||||
goog.require('goog.ui.Component');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Displays frames per seconds that the window this component is
|
||||
* rendered in is animating at.
|
||||
*
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper An optional dom helper.
|
||||
* @constructor
|
||||
* @extends {goog.ui.Component}
|
||||
*/
|
||||
goog.debug.FpsDisplay = function(opt_domHelper) {
|
||||
goog.base(this, opt_domHelper);
|
||||
};
|
||||
goog.inherits(goog.debug.FpsDisplay, goog.ui.Component);
|
||||
|
||||
|
||||
/**
|
||||
* CSS class for the FPS display.
|
||||
*/
|
||||
goog.debug.FpsDisplay.CSS = goog.getCssName('goog-fps-display');
|
||||
|
||||
|
||||
/**
|
||||
* The number of samples per FPS report.
|
||||
*/
|
||||
goog.debug.FpsDisplay.SAMPLES = 10;
|
||||
|
||||
|
||||
/**
|
||||
* The current animation.
|
||||
* @type {goog.debug.FpsDisplay.FpsAnimation_}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FpsDisplay.prototype.animation_ = null;
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FpsDisplay.prototype.createDom = function() {
|
||||
this.setElementInternal(
|
||||
this.getDomHelper().createDom('div', goog.debug.FpsDisplay.CSS));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FpsDisplay.prototype.enterDocument = function() {
|
||||
goog.base(this, 'enterDocument');
|
||||
this.animation_ = new goog.debug.FpsDisplay.FpsAnimation_(this.getElement());
|
||||
this.delay_ = new goog.async.AnimationDelay(
|
||||
this.handleDelay_, this.getDomHelper().getWindow(), this);
|
||||
this.delay_.start();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} now The current time.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FpsDisplay.prototype.handleDelay_ = function(now) {
|
||||
if (this.isInDocument()) {
|
||||
this.animation_.onAnimationFrame(now);
|
||||
this.delay_.start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.debug.FpsDisplay.prototype.exitDocument = function() {
|
||||
goog.base(this, 'exitDocument');
|
||||
this.animation_ = null;
|
||||
goog.dispose(this.delay_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The average frames per second.
|
||||
*/
|
||||
goog.debug.FpsDisplay.prototype.getFps = function() {
|
||||
goog.asserts.assert(
|
||||
this.isInDocument(), 'Render the FPS display before querying FPS');
|
||||
return this.animation_.lastFps_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} elem An element to hold the FPS count.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FpsDisplay.FpsAnimation_ = function(elem) {
|
||||
/**
|
||||
* An element to hold the current FPS rate.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.element_ = elem;
|
||||
|
||||
/**
|
||||
* The number of frames observed so far.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.frameNumber_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The last time which we reported FPS at.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FpsDisplay.FpsAnimation_.prototype.lastTime_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* The last average FPS.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.FpsDisplay.FpsAnimation_.prototype.lastFps_ = -1;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} now The current time.
|
||||
*/
|
||||
goog.debug.FpsDisplay.FpsAnimation_.prototype.onAnimationFrame = function(now) {
|
||||
var SAMPLES = goog.debug.FpsDisplay.SAMPLES;
|
||||
if (this.frameNumber_ % SAMPLES == 0) {
|
||||
this.lastFps_ = Math.round((1000 * SAMPLES) / (now - this.lastTime_));
|
||||
this.element_.innerHTML = this.lastFps_;
|
||||
this.lastTime_ = now;
|
||||
}
|
||||
this.frameNumber_++;
|
||||
};
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright 2007 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 Definition of the GcDiagnostics class.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.GcDiagnostics');
|
||||
|
||||
goog.require('goog.debug.Trace');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class used for singleton goog.debug.GcDiagnostics. Used to hook into
|
||||
* the L2 ActiveX controller to profile garbage collection information in IE.
|
||||
* Can be used in combination with tracers (goog.debug.Trace), to provide object
|
||||
* allocation counts from within the tracers or used alone by invoking start and
|
||||
* stop.
|
||||
*
|
||||
* See http://go/l2binary for the install.
|
||||
* TODO(user): Move the L2 installer somewhere more general.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
goog.debug.GcDiagnostics_ = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Install the GcDiagnostics tool.
|
||||
*/
|
||||
goog.debug.GcDiagnostics_.prototype.install = function() {
|
||||
if (goog.userAgent.IE) {
|
||||
/** @preserveTry */
|
||||
try {
|
||||
var l2Helper = new ActiveXObject('L2.NativeHelper');
|
||||
|
||||
// If using tracers, use the higher precision timer provided by L2.
|
||||
if (goog.debug.Trace_) {
|
||||
goog.debug.Trace_.now = function() {
|
||||
return l2Helper['getMilliSeconds']();
|
||||
};
|
||||
}
|
||||
|
||||
if (l2Helper['gcTracer']) {
|
||||
l2Helper['gcTracer']['installGcTracing']();
|
||||
this.gcTracer_ = l2Helper['gcTracer'];
|
||||
if (goog.debug.Trace) {
|
||||
// If tracers are in use, register the gcTracer so that per tracer
|
||||
// allocations are recorded.
|
||||
goog.debug.Trace.setGcTracer(this.gcTracer_);
|
||||
}
|
||||
}
|
||||
goog.log.info(this.logger_, 'Installed L2 native helper');
|
||||
} catch (e) {
|
||||
goog.log.info(this.logger_, 'Failed to install L2 native helper: ' + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logger for the gcDiagnotics
|
||||
* @type {goog.log.Logger}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.GcDiagnostics_.prototype.logger_ =
|
||||
goog.log.getLogger('goog.debug.GcDiagnostics');
|
||||
|
||||
|
||||
/**
|
||||
* Starts recording garbage collection information. If a trace is already in
|
||||
* progress, it is ended.
|
||||
*/
|
||||
goog.debug.GcDiagnostics_.prototype.start = function() {
|
||||
if (this.gcTracer_) {
|
||||
if (this.gcTracer_['isTracing']()) {
|
||||
this.gcTracer_['endGcTracing']();
|
||||
}
|
||||
this.gcTracer_['startGcTracing']();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops recording garbage collection information. Logs details on the garbage
|
||||
* collections that occurred between start and stop. If tracers are in use,
|
||||
* adds comments where each GC occurs.
|
||||
*/
|
||||
goog.debug.GcDiagnostics_.prototype.stop = function() {
|
||||
if (this.gcTracer_ && this.gcTracer_['isTracing']()) {
|
||||
var gcTracer = this.gcTracer_;
|
||||
this.gcTracer_['endGcTracing']();
|
||||
|
||||
var numGCs = gcTracer['getNumTraces']();
|
||||
goog.log.info(this.logger_, '*********GC TRACE*********');
|
||||
goog.log.info(this.logger_, 'GC ran ' + numGCs + ' times.');
|
||||
var totalTime = 0;
|
||||
for (var i = 0; i < numGCs; i++) {
|
||||
var trace = gcTracer['getTrace'](i);
|
||||
|
||||
var msStart = trace['gcStartTime'];
|
||||
var msElapsed = trace['gcElapsedTime'];
|
||||
|
||||
var msRounded = Math.round(msElapsed * 10) / 10;
|
||||
var s = 'GC ' + i + ': ' + msRounded + ' ms, ' +
|
||||
'numVValAlloc=' + trace['numVValAlloc'] + ', ' +
|
||||
'numVarAlloc=' + trace['numVarAlloc'] + ', ' +
|
||||
'numBytesSysAlloc=' + trace['numBytesSysAlloc'];
|
||||
if (goog.debug.Trace) {
|
||||
goog.debug.Trace.addComment(s, null, msStart);
|
||||
}
|
||||
goog.log.info(this.logger_, s);
|
||||
totalTime += msElapsed;
|
||||
}
|
||||
if (goog.debug.Trace) {
|
||||
goog.debug.Trace.addComment('Total GC time was ' + totalTime + ' ms.');
|
||||
}
|
||||
goog.log.info(this.logger_, 'Total GC time was ' + totalTime + ' ms.');
|
||||
goog.log.info(this.logger_, '*********GC TRACE*********');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Singleton GcDiagnostics object
|
||||
* @type {goog.debug.GcDiagnostics_}
|
||||
*/
|
||||
goog.debug.GcDiagnostics = new goog.debug.GcDiagnostics_();
|
||||
147
float-no-zero/closure-library/closure/goog/debug/logbuffer.js
Normal file
147
float-no-zero/closure-library/closure/goog/debug/logbuffer.js
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2010 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 A buffer for log records. The purpose of this is to improve
|
||||
* logging performance by re-using old objects when the buffer becomes full and
|
||||
* to eliminate the need for each app to implement their own log buffer. The
|
||||
* disadvantage to doing this is that log handlers cannot maintain references to
|
||||
* log records and expect that they are not overwriten at a later point.
|
||||
*
|
||||
* @author agrieve@google.com (Andrew Grieve)
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.LogBuffer');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.LogRecord');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates the log buffer.
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.LogBuffer = function() {
|
||||
goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(),
|
||||
'Cannot use goog.debug.LogBuffer without defining ' +
|
||||
'goog.debug.LogBuffer.CAPACITY.');
|
||||
this.clear();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A static method that always returns the same instance of LogBuffer.
|
||||
* @return {!goog.debug.LogBuffer} The LogBuffer singleton instance.
|
||||
*/
|
||||
goog.debug.LogBuffer.getInstance = function() {
|
||||
if (!goog.debug.LogBuffer.instance_) {
|
||||
// This function is written with the return statement after the assignment
|
||||
// to avoid the jscompiler StripCode bug described in http://b/2608064.
|
||||
// After that bug is fixed this can be refactored.
|
||||
goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer();
|
||||
}
|
||||
return goog.debug.LogBuffer.instance_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} The number of log records to buffer. 0 means disable
|
||||
* buffering.
|
||||
*/
|
||||
goog.define('goog.debug.LogBuffer.CAPACITY', 0);
|
||||
|
||||
|
||||
/**
|
||||
* The array to store the records.
|
||||
* @type {!Array.<!goog.debug.LogRecord|undefined>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.buffer_;
|
||||
|
||||
|
||||
/**
|
||||
* The index of the most recently added record or -1 if there are no records.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.curIndex_;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the buffer is at capacity.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.isFull_;
|
||||
|
||||
|
||||
/**
|
||||
* Adds a log record to the buffer, possibly overwriting the oldest record.
|
||||
* @param {goog.debug.Logger.Level} level One of the level identifiers.
|
||||
* @param {string} msg The string message.
|
||||
* @param {string} loggerName The name of the source logger.
|
||||
* @return {!goog.debug.LogRecord} The log record.
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) {
|
||||
var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY;
|
||||
this.curIndex_ = curIndex;
|
||||
if (this.isFull_) {
|
||||
var ret = this.buffer_[curIndex];
|
||||
ret.reset(level, msg, loggerName);
|
||||
return ret;
|
||||
}
|
||||
this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1;
|
||||
return this.buffer_[curIndex] =
|
||||
new goog.debug.LogRecord(level, msg, loggerName);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the log buffer is enabled.
|
||||
*/
|
||||
goog.debug.LogBuffer.isBufferingEnabled = function() {
|
||||
return goog.debug.LogBuffer.CAPACITY > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all buffered log records.
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.clear = function() {
|
||||
this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);
|
||||
this.curIndex_ = -1;
|
||||
this.isFull_ = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the given function for each buffered log record, starting with the
|
||||
* oldest one.
|
||||
* @param {function(!goog.debug.LogRecord)} func The function to call.
|
||||
*/
|
||||
goog.debug.LogBuffer.prototype.forEachRecord = function(func) {
|
||||
var buffer = this.buffer_;
|
||||
// Corner case: no records.
|
||||
if (!buffer[0]) {
|
||||
return;
|
||||
}
|
||||
var curIndex = this.curIndex_;
|
||||
var i = this.isFull_ ? curIndex : -1;
|
||||
do {
|
||||
i = (i + 1) % goog.debug.LogBuffer.CAPACITY;
|
||||
func(/** @type {!goog.debug.LogRecord} */ (buffer[i]));
|
||||
} while (i != curIndex);
|
||||
};
|
||||
|
||||
853
float-no-zero/closure-library/closure/goog/debug/logger.js
Normal file
853
float-no-zero/closure-library/closure/goog/debug/logger.js
Normal file
@@ -0,0 +1,853 @@
|
||||
// Copyright 2006 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 Definition of the Logger class. Please minimize dependencies
|
||||
* this file has on other closure classes as any dependency it takes won't be
|
||||
* able to use the logging infrastructure.
|
||||
*
|
||||
* @see ../demos/debug.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.LogManager');
|
||||
goog.provide('goog.debug.Logger');
|
||||
goog.provide('goog.debug.Logger.Level');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug');
|
||||
goog.require('goog.debug.LogBuffer');
|
||||
goog.require('goog.debug.LogRecord');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The Logger is an object used for logging debug messages. Loggers are
|
||||
* normally named, using a hierarchical dot-separated namespace. Logger names
|
||||
* can be arbitrary strings, but they should normally be based on the package
|
||||
* name or class name of the logged component, such as goog.net.BrowserChannel.
|
||||
*
|
||||
* The Logger object is loosely based on the java class
|
||||
* java.util.logging.Logger. It supports different levels of filtering for
|
||||
* different loggers.
|
||||
*
|
||||
* The logger object should never be instantiated by application code. It
|
||||
* should always use the goog.debug.Logger.getLogger function.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} name The name of the Logger.
|
||||
*/
|
||||
goog.debug.Logger = function(name) {
|
||||
/**
|
||||
* Name of the Logger. Generally a dot-separated namespace
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.name_ = name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parent Logger.
|
||||
* @type {goog.debug.Logger}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.parent_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Level that this logger only filters above. Null indicates it should
|
||||
* inherit from the parent.
|
||||
* @type {goog.debug.Logger.Level}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.level_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Map of children loggers. The keys are the leaf names of the children and
|
||||
* the values are the child loggers.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.children_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Handlers that are listening to this logger.
|
||||
* @type {Array.<Function>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.handlers_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Toggles whether loggers other than the root logger can have
|
||||
* log handlers attached to them and whether they can have their log level
|
||||
* set. Logging is a bit faster when this is set to false.
|
||||
*/
|
||||
goog.define('goog.debug.Logger.ENABLE_HIERARCHY', true);
|
||||
|
||||
|
||||
if (!goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
/**
|
||||
* @type {!Array.<Function>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.rootHandlers_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* @type {goog.debug.Logger.Level}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.rootLevel_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The Level class defines a set of standard logging levels that
|
||||
* can be used to control logging output. The logging Level objects
|
||||
* are ordered and are specified by ordered integers. Enabling logging
|
||||
* at a given level also enables logging at all higher levels.
|
||||
* <p>
|
||||
* Clients should normally use the predefined Level constants such
|
||||
* as Level.SEVERE.
|
||||
* <p>
|
||||
* The levels in descending order are:
|
||||
* <ul>
|
||||
* <li>SEVERE (highest value)
|
||||
* <li>WARNING
|
||||
* <li>INFO
|
||||
* <li>CONFIG
|
||||
* <li>FINE
|
||||
* <li>FINER
|
||||
* <li>FINEST (lowest value)
|
||||
* </ul>
|
||||
* In addition there is a level OFF that can be used to turn
|
||||
* off logging, and a level ALL that can be used to enable
|
||||
* logging of all messages.
|
||||
*
|
||||
* @param {string} name The name of the level.
|
||||
* @param {number} value The numeric value of the level.
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.Logger.Level = function(name, value) {
|
||||
/**
|
||||
* The name of the level
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The numeric value of the level
|
||||
* @type {number}
|
||||
*/
|
||||
this.value = value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} String representation of the logger level.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.Logger.Level.prototype.toString = function() {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* OFF is a special level that can be used to turn off logging.
|
||||
* This level is initialized to <CODE>Infinity</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.OFF =
|
||||
new goog.debug.Logger.Level('OFF', Infinity);
|
||||
|
||||
|
||||
/**
|
||||
* SHOUT is a message level for extra debugging loudness.
|
||||
* This level is initialized to <CODE>1200</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level('SHOUT', 1200);
|
||||
|
||||
|
||||
/**
|
||||
* SEVERE is a message level indicating a serious failure.
|
||||
* This level is initialized to <CODE>1000</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level('SEVERE', 1000);
|
||||
|
||||
|
||||
/**
|
||||
* WARNING is a message level indicating a potential problem.
|
||||
* This level is initialized to <CODE>900</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level('WARNING', 900);
|
||||
|
||||
|
||||
/**
|
||||
* INFO is a message level for informational messages.
|
||||
* This level is initialized to <CODE>800</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level('INFO', 800);
|
||||
|
||||
|
||||
/**
|
||||
* CONFIG is a message level for static configuration messages.
|
||||
* This level is initialized to <CODE>700</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level('CONFIG', 700);
|
||||
|
||||
|
||||
/**
|
||||
* FINE is a message level providing tracing information.
|
||||
* This level is initialized to <CODE>500</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level('FINE', 500);
|
||||
|
||||
|
||||
/**
|
||||
* FINER indicates a fairly detailed tracing message.
|
||||
* This level is initialized to <CODE>400</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level('FINER', 400);
|
||||
|
||||
/**
|
||||
* FINEST indicates a highly detailed tracing message.
|
||||
* This level is initialized to <CODE>300</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
|
||||
goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level('FINEST', 300);
|
||||
|
||||
|
||||
/**
|
||||
* ALL indicates that all messages should be logged.
|
||||
* This level is initialized to <CODE>0</CODE>.
|
||||
* @type {!goog.debug.Logger.Level}
|
||||
*/
|
||||
goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level('ALL', 0);
|
||||
|
||||
|
||||
/**
|
||||
* The predefined levels.
|
||||
* @type {!Array.<!goog.debug.Logger.Level>}
|
||||
* @final
|
||||
*/
|
||||
goog.debug.Logger.Level.PREDEFINED_LEVELS = [
|
||||
goog.debug.Logger.Level.OFF,
|
||||
goog.debug.Logger.Level.SHOUT,
|
||||
goog.debug.Logger.Level.SEVERE,
|
||||
goog.debug.Logger.Level.WARNING,
|
||||
goog.debug.Logger.Level.INFO,
|
||||
goog.debug.Logger.Level.CONFIG,
|
||||
goog.debug.Logger.Level.FINE,
|
||||
goog.debug.Logger.Level.FINER,
|
||||
goog.debug.Logger.Level.FINEST,
|
||||
goog.debug.Logger.Level.ALL];
|
||||
|
||||
|
||||
/**
|
||||
* A lookup map used to find the level object based on the name or value of
|
||||
* the level object.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.Level.predefinedLevelsCache_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Creates the predefined levels cache and populates it.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {
|
||||
goog.debug.Logger.Level.predefinedLevelsCache_ = {};
|
||||
for (var i = 0, level; level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
|
||||
i++) {
|
||||
goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;
|
||||
goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the predefined level with the given name.
|
||||
* @param {string} name The name of the level.
|
||||
* @return {goog.debug.Logger.Level} The level, or null if none found.
|
||||
*/
|
||||
goog.debug.Logger.Level.getPredefinedLevel = function(name) {
|
||||
if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
|
||||
goog.debug.Logger.Level.createPredefinedLevelsCache_();
|
||||
}
|
||||
|
||||
return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the highest predefined level <= #value.
|
||||
* @param {number} value Level value.
|
||||
* @return {goog.debug.Logger.Level} The level, or null if none found.
|
||||
*/
|
||||
goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {
|
||||
if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
|
||||
goog.debug.Logger.Level.createPredefinedLevelsCache_();
|
||||
}
|
||||
|
||||
if (value in goog.debug.Logger.Level.predefinedLevelsCache_) {
|
||||
return goog.debug.Logger.Level.predefinedLevelsCache_[value];
|
||||
}
|
||||
|
||||
for (var i = 0; i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length; ++i) {
|
||||
var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
|
||||
if (level.value <= value) {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Finds or creates a logger for a named subsystem. If a logger has already been
|
||||
* created with the given name it is returned. Otherwise a new logger is
|
||||
* created. If a new logger is created its log level will be configured based
|
||||
* on the LogManager configuration and it will configured to also send logging
|
||||
* output to its parent's handlers. It will be registered in the LogManager
|
||||
* global namespace.
|
||||
*
|
||||
* @param {string} name A name for the logger. This should be a dot-separated
|
||||
* name and should normally be based on the package name or class name of the
|
||||
* subsystem, such as goog.net.BrowserChannel.
|
||||
* @return {!goog.debug.Logger} The named logger.
|
||||
*/
|
||||
goog.debug.Logger.getLogger = function(name) {
|
||||
return goog.debug.LogManager.getLogger(name);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message to profiling tools, if available.
|
||||
* {@see http://code.google.com/webtoolkit/speedtracer/logging-api.html}
|
||||
* {@see http://msdn.microsoft.com/en-us/library/dd433074(VS.85).aspx}
|
||||
* @param {string} msg The message to log.
|
||||
*/
|
||||
goog.debug.Logger.logToProfilers = function(msg) {
|
||||
// Using goog.global, as loggers might be used in window-less contexts.
|
||||
if (goog.global['console']) {
|
||||
if (goog.global['console']['timeStamp']) {
|
||||
// Logs a message to Firebug, Web Inspector, SpeedTracer, etc.
|
||||
goog.global['console']['timeStamp'](msg);
|
||||
} else if (goog.global['console']['markTimeline']) {
|
||||
// TODO(user): markTimeline is deprecated. Drop this else clause entirely
|
||||
// after Chrome M14 hits stable.
|
||||
goog.global['console']['markTimeline'](msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (goog.global['msWriteProfilerMark']) {
|
||||
// Logs a message to the Microsoft profiler
|
||||
goog.global['msWriteProfilerMark'](msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of this logger.
|
||||
* @return {string} The name of this logger.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getName = function() {
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a handler to the logger. This doesn't use the event system because
|
||||
* we want to be able to add logging to the event system.
|
||||
* @param {Function} handler Handler function to add.
|
||||
*/
|
||||
goog.debug.Logger.prototype.addHandler = function(handler) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
if (goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
if (!this.handlers_) {
|
||||
this.handlers_ = [];
|
||||
}
|
||||
this.handlers_.push(handler);
|
||||
} else {
|
||||
goog.asserts.assert(!this.name_,
|
||||
'Cannot call addHandler on a non-root logger when ' +
|
||||
'goog.debug.Logger.ENABLE_HIERARCHY is false.');
|
||||
goog.debug.Logger.rootHandlers_.push(handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a handler from the logger. This doesn't use the event system because
|
||||
* we want to be able to add logging to the event system.
|
||||
* @param {Function} handler Handler function to remove.
|
||||
* @return {boolean} Whether the handler was removed.
|
||||
*/
|
||||
goog.debug.Logger.prototype.removeHandler = function(handler) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
var handlers = goog.debug.Logger.ENABLE_HIERARCHY ? this.handlers_ :
|
||||
goog.debug.Logger.rootHandlers_;
|
||||
return !!handlers && goog.array.remove(handlers, handler);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parent of this logger.
|
||||
* @return {goog.debug.Logger} The parent logger or null if this is the root.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getParent = function() {
|
||||
return this.parent_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the children of this logger as a map of the child name to the logger.
|
||||
* @return {!Object} The map where the keys are the child leaf names and the
|
||||
* values are the Logger objects.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getChildren = function() {
|
||||
if (!this.children_) {
|
||||
this.children_ = {};
|
||||
}
|
||||
return this.children_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the log level specifying which message levels will be logged by this
|
||||
* logger. Message levels lower than this value will be discarded.
|
||||
* The level value Level.OFF can be used to turn off logging. If the new level
|
||||
* is null, it means that this node should inherit its level from its nearest
|
||||
* ancestor with a specific (non-null) level value.
|
||||
*
|
||||
* @param {goog.debug.Logger.Level} level The new level.
|
||||
*/
|
||||
goog.debug.Logger.prototype.setLevel = function(level) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
if (goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
this.level_ = level;
|
||||
} else {
|
||||
goog.asserts.assert(!this.name_,
|
||||
'Cannot call setLevel() on a non-root logger when ' +
|
||||
'goog.debug.Logger.ENABLE_HIERARCHY is false.');
|
||||
goog.debug.Logger.rootLevel_ = level;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the log level specifying which message levels will be logged by this
|
||||
* logger. Message levels lower than this value will be discarded.
|
||||
* The level value Level.OFF can be used to turn off logging. If the level
|
||||
* is null, it means that this node should inherit its level from its nearest
|
||||
* ancestor with a specific (non-null) level value.
|
||||
*
|
||||
* @return {goog.debug.Logger.Level} The level.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getLevel = function() {
|
||||
return goog.debug.LOGGING_ENABLED ?
|
||||
this.level_ : goog.debug.Logger.Level.OFF;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the effective level of the logger based on its ancestors' levels.
|
||||
* @return {goog.debug.Logger.Level} The level.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getEffectiveLevel = function() {
|
||||
if (!goog.debug.LOGGING_ENABLED) {
|
||||
return goog.debug.Logger.Level.OFF;
|
||||
}
|
||||
|
||||
if (!goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
return goog.debug.Logger.rootLevel_;
|
||||
}
|
||||
if (this.level_) {
|
||||
return this.level_;
|
||||
}
|
||||
if (this.parent_) {
|
||||
return this.parent_.getEffectiveLevel();
|
||||
}
|
||||
goog.asserts.fail('Root logger has no level set.');
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a message of the given level would actually be logged by this
|
||||
* logger. This check is based on the Loggers effective level, which may be
|
||||
* inherited from its parent.
|
||||
* @param {goog.debug.Logger.Level} level The level to check.
|
||||
* @return {boolean} Whether the message would be logged.
|
||||
*/
|
||||
goog.debug.Logger.prototype.isLoggable = function(level) {
|
||||
return goog.debug.LOGGING_ENABLED &&
|
||||
level.value >= this.getEffectiveLevel().value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message. If the logger is currently enabled for the
|
||||
* given message level then the given message is forwarded to all the
|
||||
* registered output Handler objects.
|
||||
* @param {goog.debug.Logger.Level} level One of the level identifiers.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error|Object=} opt_exception An exception associated with the
|
||||
* message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
|
||||
// java caches the effective level, not sure it's necessary here
|
||||
if (goog.debug.LOGGING_ENABLED && this.isLoggable(level)) {
|
||||
this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new log record and adds the exception (if present) to it.
|
||||
* @param {goog.debug.Logger.Level} level One of the level identifiers.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error|Object=} opt_exception An exception associated with the
|
||||
* message.
|
||||
* @return {!goog.debug.LogRecord} A log record.
|
||||
*/
|
||||
goog.debug.Logger.prototype.getLogRecord = function(level, msg, opt_exception) {
|
||||
if (goog.debug.LogBuffer.isBufferingEnabled()) {
|
||||
var logRecord =
|
||||
goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_);
|
||||
} else {
|
||||
logRecord = new goog.debug.LogRecord(level, String(msg), this.name_);
|
||||
}
|
||||
if (opt_exception) {
|
||||
logRecord.setException(opt_exception);
|
||||
logRecord.setExceptionText(
|
||||
goog.debug.exposeException(opt_exception, arguments.callee.caller));
|
||||
}
|
||||
return logRecord;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.SHOUT level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.SEVERE level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.WARNING level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.INFO level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.info = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.CONFIG level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.config = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.FINE level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.FINER level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a message at the Logger.Level.FINEST level.
|
||||
* If the logger is currently enabled for the given message level then the
|
||||
* given message is forwarded to all the registered output Handler objects.
|
||||
* @param {string} msg The string message.
|
||||
* @param {Error=} opt_exception An exception associated with the message.
|
||||
*/
|
||||
goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
|
||||
if (goog.debug.LOGGING_ENABLED) {
|
||||
this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a LogRecord. If the logger is currently enabled for the
|
||||
* given message level then the given message is forwarded to all the
|
||||
* registered output Handler objects.
|
||||
* @param {goog.debug.LogRecord} logRecord A log record to log.
|
||||
*/
|
||||
goog.debug.Logger.prototype.logRecord = function(logRecord) {
|
||||
if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) {
|
||||
this.doLogRecord_(logRecord);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logs a LogRecord.
|
||||
* @param {goog.debug.LogRecord} logRecord A log record to log.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {
|
||||
goog.debug.Logger.logToProfilers('log:' + logRecord.getMessage());
|
||||
if (goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
var target = this;
|
||||
while (target) {
|
||||
target.callPublish_(logRecord);
|
||||
target = target.getParent();
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++]; ) {
|
||||
handler(logRecord);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the handlers for publish.
|
||||
* @param {goog.debug.LogRecord} logRecord The log record to publish.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
|
||||
if (this.handlers_) {
|
||||
for (var i = 0, handler; handler = this.handlers_[i]; i++) {
|
||||
handler(logRecord);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the parent of this logger. This is used for setting up the logger tree.
|
||||
* @param {goog.debug.Logger} parent The parent logger.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.setParent_ = function(parent) {
|
||||
this.parent_ = parent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a child to this logger. This is used for setting up the logger tree.
|
||||
* @param {string} name The leaf name of the child.
|
||||
* @param {goog.debug.Logger} logger The child logger.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Logger.prototype.addChild_ = function(name, logger) {
|
||||
this.getChildren()[name] = logger;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* There is a single global LogManager object that is used to maintain a set of
|
||||
* shared state about Loggers and log services. This is loosely based on the
|
||||
* java class java.util.logging.LogManager.
|
||||
*/
|
||||
goog.debug.LogManager = {};
|
||||
|
||||
|
||||
/**
|
||||
* Map of logger names to logger objects.
|
||||
*
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogManager.loggers_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* The root logger which is the root of the logger tree.
|
||||
* @type {goog.debug.Logger}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogManager.rootLogger_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the LogManager if not already initialized.
|
||||
*/
|
||||
goog.debug.LogManager.initialize = function() {
|
||||
if (!goog.debug.LogManager.rootLogger_) {
|
||||
goog.debug.LogManager.rootLogger_ = new goog.debug.Logger('');
|
||||
goog.debug.LogManager.loggers_[''] = goog.debug.LogManager.rootLogger_;
|
||||
goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns all the loggers.
|
||||
* @return {!Object} Map of logger names to logger objects.
|
||||
*/
|
||||
goog.debug.LogManager.getLoggers = function() {
|
||||
return goog.debug.LogManager.loggers_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the root of the logger tree namespace, the logger with the empty
|
||||
* string as its name.
|
||||
*
|
||||
* @return {!goog.debug.Logger} The root logger.
|
||||
*/
|
||||
goog.debug.LogManager.getRoot = function() {
|
||||
goog.debug.LogManager.initialize();
|
||||
return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Finds a named logger.
|
||||
*
|
||||
* @param {string} name A name for the logger. This should be a dot-separated
|
||||
* name and should normally be based on the package name or class name of the
|
||||
* subsystem, such as goog.net.BrowserChannel.
|
||||
* @return {!goog.debug.Logger} The named logger.
|
||||
*/
|
||||
goog.debug.LogManager.getLogger = function(name) {
|
||||
goog.debug.LogManager.initialize();
|
||||
var ret = goog.debug.LogManager.loggers_[name];
|
||||
return ret || goog.debug.LogManager.createLogger_(name);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a function that can be passed to goog.debug.catchErrors. The function
|
||||
* will log all reported errors using the given logger.
|
||||
* @param {goog.debug.Logger=} opt_logger The logger to log the errors to.
|
||||
* Defaults to the root logger.
|
||||
* @return {function(Object)} The created function.
|
||||
*/
|
||||
goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {
|
||||
return function(info) {
|
||||
var logger = opt_logger || goog.debug.LogManager.getRoot();
|
||||
logger.severe('Error: ' + info.message + ' (' + info.fileName +
|
||||
' @ Line: ' + info.line + ')');
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the named logger. Will also create the parents of the named logger
|
||||
* if they don't yet exist.
|
||||
* @param {string} name The name of the logger.
|
||||
* @return {!goog.debug.Logger} The named logger.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogManager.createLogger_ = function(name) {
|
||||
// find parent logger
|
||||
var logger = new goog.debug.Logger(name);
|
||||
if (goog.debug.Logger.ENABLE_HIERARCHY) {
|
||||
var lastDotIndex = name.lastIndexOf('.');
|
||||
var parentName = name.substr(0, lastDotIndex);
|
||||
var leafName = name.substr(lastDotIndex + 1);
|
||||
var parentLogger = goog.debug.LogManager.getLogger(parentName);
|
||||
|
||||
// tell the parent about the child and the child about the parent
|
||||
parentLogger.addChild_(leafName, logger);
|
||||
logger.setParent_(parentLogger);
|
||||
}
|
||||
|
||||
goog.debug.LogManager.loggers_[name] = logger;
|
||||
return logger;
|
||||
};
|
||||
271
float-no-zero/closure-library/closure/goog/debug/logrecord.js
Normal file
271
float-no-zero/closure-library/closure/goog/debug/logrecord.js
Normal file
@@ -0,0 +1,271 @@
|
||||
// Copyright 2006 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 Definition of the LogRecord class. Please minimize
|
||||
* dependencies this file has on other closure classes as any dependency it
|
||||
* takes won't be able to use the logging infrastructure.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.LogRecord');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* LogRecord objects are used to pass logging requests between
|
||||
* the logging framework and individual log Handlers.
|
||||
* @constructor
|
||||
* @param {goog.debug.Logger.Level} level One of the level identifiers.
|
||||
* @param {string} msg The string message.
|
||||
* @param {string} loggerName The name of the source logger.
|
||||
* @param {number=} opt_time Time this log record was created if other than now.
|
||||
* If 0, we use #goog.now.
|
||||
* @param {number=} opt_sequenceNumber Sequence number of this log record. This
|
||||
* should only be passed in when restoring a log record from persistence.
|
||||
*/
|
||||
goog.debug.LogRecord = function(level, msg, loggerName,
|
||||
opt_time, opt_sequenceNumber) {
|
||||
this.reset(level, msg, loggerName, opt_time, opt_sequenceNumber);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Time the LogRecord was created.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.time_;
|
||||
|
||||
|
||||
/**
|
||||
* Level of the LogRecord
|
||||
* @type {goog.debug.Logger.Level}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.level_;
|
||||
|
||||
|
||||
/**
|
||||
* Message associated with the record
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.msg_;
|
||||
|
||||
|
||||
/**
|
||||
* Name of the logger that created the record.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.loggerName_;
|
||||
|
||||
|
||||
/**
|
||||
* Sequence number for the LogRecord. Each record has a unique sequence number
|
||||
* that is greater than all log records created before it.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.sequenceNumber_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Exception associated with the record
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.exception_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Exception text associated with the record
|
||||
* @type {?string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.exceptionText_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable log sequence numbers.
|
||||
*/
|
||||
goog.define('goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS', true);
|
||||
|
||||
|
||||
/**
|
||||
* A sequence counter for assigning increasing sequence numbers to LogRecord
|
||||
* objects.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.LogRecord.nextSequenceNumber_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Sets all fields of the log record.
|
||||
* @param {goog.debug.Logger.Level} level One of the level identifiers.
|
||||
* @param {string} msg The string message.
|
||||
* @param {string} loggerName The name of the source logger.
|
||||
* @param {number=} opt_time Time this log record was created if other than now.
|
||||
* If 0, we use #goog.now.
|
||||
* @param {number=} opt_sequenceNumber Sequence number of this log record. This
|
||||
* should only be passed in when restoring a log record from persistence.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.reset = function(level, msg, loggerName,
|
||||
opt_time, opt_sequenceNumber) {
|
||||
if (goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS) {
|
||||
this.sequenceNumber_ = typeof opt_sequenceNumber == 'number' ?
|
||||
opt_sequenceNumber : goog.debug.LogRecord.nextSequenceNumber_++;
|
||||
}
|
||||
|
||||
this.time_ = opt_time || goog.now();
|
||||
this.level_ = level;
|
||||
this.msg_ = msg;
|
||||
this.loggerName_ = loggerName;
|
||||
delete this.exception_;
|
||||
delete this.exceptionText_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the source Logger's name.
|
||||
*
|
||||
* @return {string} source logger name (may be null).
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getLoggerName = function() {
|
||||
return this.loggerName_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the exception that is part of the log record.
|
||||
*
|
||||
* @return {Object} the exception.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getException = function() {
|
||||
return this.exception_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the exception that is part of the log record.
|
||||
*
|
||||
* @param {Object} exception the exception.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setException = function(exception) {
|
||||
this.exception_ = exception;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the exception text that is part of the log record.
|
||||
*
|
||||
* @return {?string} Exception text.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getExceptionText = function() {
|
||||
return this.exceptionText_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the exception text that is part of the log record.
|
||||
*
|
||||
* @param {string} text The exception text.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setExceptionText = function(text) {
|
||||
this.exceptionText_ = text;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the source Logger's name.
|
||||
*
|
||||
* @param {string} loggerName source logger name (may be null).
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setLoggerName = function(loggerName) {
|
||||
this.loggerName_ = loggerName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the logging message level, for example Level.SEVERE.
|
||||
* @return {goog.debug.Logger.Level} the logging message level.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getLevel = function() {
|
||||
return this.level_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the logging message level, for example Level.SEVERE.
|
||||
* @param {goog.debug.Logger.Level} level the logging message level.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setLevel = function(level) {
|
||||
this.level_ = level;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the "raw" log message, before localization or formatting.
|
||||
*
|
||||
* @return {string} the raw message string.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getMessage = function() {
|
||||
return this.msg_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the "raw" log message, before localization or formatting.
|
||||
*
|
||||
* @param {string} msg the raw message string.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setMessage = function(msg) {
|
||||
this.msg_ = msg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get event time in milliseconds since 1970.
|
||||
*
|
||||
* @return {number} event time in millis since 1970.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getMillis = function() {
|
||||
return this.time_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set event time in milliseconds since 1970.
|
||||
*
|
||||
* @param {number} time event time in millis since 1970.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.setMillis = function(time) {
|
||||
this.time_ = time;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the sequence number.
|
||||
* <p>
|
||||
* Sequence numbers are normally assigned in the LogRecord
|
||||
* constructor, which assigns unique sequence numbers to
|
||||
* each new LogRecord in increasing order.
|
||||
* @return {number} the sequence number.
|
||||
*/
|
||||
goog.debug.LogRecord.prototype.getSequenceNumber = function() {
|
||||
return this.sequenceNumber_;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright 2011 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 Static methods for serializing and deserializing log
|
||||
* messages. These methods are deliberately kept separate from logrecord.js
|
||||
* and logger.js because they add dependencies on goog.json and goog.object.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.logRecordSerializer');
|
||||
|
||||
goog.require('goog.debug.LogRecord');
|
||||
goog.require('goog.debug.Logger.Level');
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of object keys used when serializing a log message.
|
||||
* @enum {string}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.logRecordSerializer.Param_ = {
|
||||
TIME: 't',
|
||||
LEVEL_NAME: 'ln',
|
||||
LEVEL_VALUE: 'lv',
|
||||
MSG: 'm',
|
||||
LOGGER_NAME: 'n',
|
||||
SEQUENCE_NUMBER: 's',
|
||||
EXCEPTION: 'e',
|
||||
EXCEPTION_TEXT: 'et'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a LogRecord to a JSON string. Note that any associated
|
||||
* exception is likely to be lost.
|
||||
* @param {goog.debug.LogRecord} record The record to serialize.
|
||||
* @return {string} Serialized JSON string of the log message.
|
||||
*/
|
||||
goog.debug.logRecordSerializer.serialize = function(record) {
|
||||
var param = goog.debug.logRecordSerializer.Param_;
|
||||
return goog.json.serialize(goog.object.create(
|
||||
param.TIME, record.getMillis(),
|
||||
param.LEVEL_NAME, record.getLevel().name,
|
||||
param.LEVEL_VALUE, record.getLevel().value,
|
||||
param.MSG, record.getMessage(),
|
||||
param.LOGGER_NAME, record.getLoggerName(),
|
||||
param.SEQUENCE_NUMBER, record.getSequenceNumber(),
|
||||
param.EXCEPTION, record.getException(),
|
||||
param.EXCEPTION_TEXT, record.getExceptionText()));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes a JSON-serialized LogRecord.
|
||||
* @param {string} s The JSON serialized record.
|
||||
* @return {!goog.debug.LogRecord} The deserialized record.
|
||||
*/
|
||||
goog.debug.logRecordSerializer.parse = function(s) {
|
||||
return goog.debug.logRecordSerializer.reconstitute_(goog.json.parse(s));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes a JSON-serialized LogRecord. Use this only if you're
|
||||
* naive enough to blindly trust any JSON formatted input that comes
|
||||
* your way.
|
||||
* @param {string} s The JSON serialized record.
|
||||
* @return {!goog.debug.LogRecord} The deserialized record.
|
||||
*/
|
||||
goog.debug.logRecordSerializer.unsafeParse = function(s) {
|
||||
return goog.debug.logRecordSerializer.reconstitute_(goog.json.unsafeParse(s));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Common reconsitution method for for parse and unsafeParse.
|
||||
* @param {Object} o The JSON object.
|
||||
* @return {!goog.debug.LogRecord} The reconstituted record.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.logRecordSerializer.reconstitute_ = function(o) {
|
||||
var param = goog.debug.logRecordSerializer.Param_;
|
||||
var level = goog.debug.logRecordSerializer.getLevel_(
|
||||
o[param.LEVEL_NAME], o[param.LEVEL_VALUE]);
|
||||
|
||||
var ret = new goog.debug.LogRecord(level, o[param.MSG],
|
||||
o[param.LOGGER_NAME], o[param.TIME], o[param.SEQUENCE_NUMBER]);
|
||||
ret.setException(o[param.EXCEPTION]);
|
||||
ret.setExceptionText(o[param.EXCEPTION_TEXT]);
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} name The name of the log level to return.
|
||||
* @param {number} value The numeric value of the log level to return.
|
||||
* @return {goog.debug.Logger.Level} Returns a goog.debug.Logger.Level with
|
||||
* the specified name and value. If the name and value match a predefined
|
||||
* log level, that instance will be returned, otherwise a new one will be
|
||||
* created.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.logRecordSerializer.getLevel_ = function(name, value) {
|
||||
var level = goog.debug.Logger.Level.getPredefinedLevel(name);
|
||||
return level && level.value == value ?
|
||||
level : new goog.debug.Logger.Level(name, value);
|
||||
};
|
||||
178
float-no-zero/closure-library/closure/goog/debug/reflect.js
Normal file
178
float-no-zero/closure-library/closure/goog/debug/reflect.js
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2011 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 JavaScript reflection tools. They should only be used for
|
||||
* debugging non-compiled code or tests, because there is no guarantee that
|
||||
* they work consistently in all browsers.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.reflect');
|
||||
|
||||
|
||||
/**
|
||||
* Maps the unique id of the known constructors to their full names.
|
||||
* Initialized lazily.
|
||||
* @type {Object.<number, string>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.reflect.typeMap_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* List of all known constructors. Initialized lazily.
|
||||
* @type {Array.<!Function>}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.reflect.constructors_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* Copy of {@code Object.prototype.toString} to use if it is overridden later.
|
||||
* Although saving the original {@code toString} somewhat protects against
|
||||
* third-party libraries which touch {@code Object.prototype}, the actual goal
|
||||
* of this assignment is to allow overriding that method, thus more debug
|
||||
* information can be exposed about objects.
|
||||
* See {@link goog.debug.reflect.typeOf}.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.reflect.toString_ = Object.prototype.toString;
|
||||
|
||||
|
||||
/**
|
||||
* Registers a type which will be recognized by goog.debug.reflect.typeOf.
|
||||
* @param {string} name Full name of the type.
|
||||
* @param {!Function} ctor The constructor.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.reflect.registerType_ = function(name, ctor) {
|
||||
goog.debug.reflect.constructors_.push(ctor);
|
||||
goog.debug.reflect.typeMap_[goog.getUid(ctor)] = name;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds all known constructors to the type registry.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.reflect.init_ = function() {
|
||||
if (goog.debug.reflect.typeMap_) {
|
||||
return;
|
||||
}
|
||||
|
||||
goog.debug.reflect.typeMap_ = {};
|
||||
goog.debug.reflect.constructors_ = [];
|
||||
var implicitNs = goog.getObjectByName('goog.implicitNamespaces_') || {};
|
||||
|
||||
for (var ns in implicitNs) {
|
||||
if (implicitNs.hasOwnProperty(ns)) {
|
||||
var nsObj = goog.getObjectByName(ns);
|
||||
for (var name in nsObj) {
|
||||
if (nsObj.hasOwnProperty(name) && goog.isFunction(nsObj[name])) {
|
||||
goog.debug.reflect.registerType_(ns + '.' + name, nsObj[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goog.debug.reflect.registerType_('Array', Array);
|
||||
goog.debug.reflect.registerType_('Boolean', Boolean);
|
||||
goog.debug.reflect.registerType_('Date', Date);
|
||||
goog.debug.reflect.registerType_('Error', Error);
|
||||
goog.debug.reflect.registerType_('Function', Function);
|
||||
goog.debug.reflect.registerType_('Number', Number);
|
||||
goog.debug.reflect.registerType_('Object', Object);
|
||||
goog.debug.reflect.registerType_('String', String);
|
||||
|
||||
// The compiler gets upset if we alias regexp directly, because
|
||||
// then it can't optimize regexps as well. Just be sneaky about it,
|
||||
// because this is only for debugging.
|
||||
goog.debug.reflect.registerType_('RegExp', goog.global['RegExp']);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of a type of object.
|
||||
* @param {!Function} classConstructor A object constructor to get the name of.
|
||||
* @return {string|undefined} The string name of the class.
|
||||
*/
|
||||
goog.debug.reflect.className = function(classConstructor) {
|
||||
goog.debug.reflect.init_();
|
||||
if (goog.isDefAndNotNull(classConstructor)) {
|
||||
return goog.debug.reflect.typeMap_[goog.getUid(classConstructor)];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Guesses the real type of the object, even if its {@code toString} method is
|
||||
* overridden. Gives exact result for all goog.provided classes in non-compiled
|
||||
* code, and some often used native classes in compiled code too. Not tested in
|
||||
* multi-frame environment.
|
||||
*
|
||||
* Example use case to get better type information in the Watch tab of FireBug:
|
||||
* <pre>
|
||||
* Object.prototype.toString = function() {
|
||||
* return goog.debug.reflect.typeOf(this);
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @param {*} obj An arbitrary variable to get the type of.
|
||||
* @return {string} The namespaced type of the argument or 'Object' if didn't
|
||||
* manage to determine it. Warning: in IE7 ActiveX (including DOM) objects
|
||||
* don't expose their type to JavaScript. Their {@code constructor}
|
||||
* property is undefined and they are not even the instances of the
|
||||
* {@code Object} type. This method will recognize them as 'ActiveXObject'.
|
||||
*/
|
||||
goog.debug.reflect.typeOf = function(obj) {
|
||||
// Check primitive types.
|
||||
if (!obj || goog.isNumber(obj) || goog.isString(obj) || goog.isBoolean(obj)) {
|
||||
return goog.typeOf(obj);
|
||||
}
|
||||
|
||||
// Check if the type is present in the registry.
|
||||
goog.debug.reflect.init_();
|
||||
if (obj.constructor) {
|
||||
// Some DOM objects such as document don't have constructor in IE7.
|
||||
var type = goog.debug.reflect.typeMap_[goog.getUid(obj.constructor)];
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// In IE8 the internal 'class' property of ActiveXObjects is Object, but
|
||||
// String(obj) tells their real type.
|
||||
var isActiveXObject = goog.global.ActiveXObject &&
|
||||
obj instanceof ActiveXObject;
|
||||
var typeString = isActiveXObject ? String(obj) :
|
||||
goog.debug.reflect.toString_.call(/** @type {Object} */ (obj));
|
||||
var match = typeString.match(/^\[object (\w+)\]$/);
|
||||
if (match) {
|
||||
var name = match[1];
|
||||
var ctor = goog.global[name];
|
||||
try {
|
||||
if (obj instanceof ctor) {
|
||||
return name;
|
||||
}
|
||||
} catch (e) {
|
||||
// instanceof may fail if the guessed name is not a real type.
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to Object or ActiveXObject.
|
||||
return isActiveXObject ? 'ActiveXObject' : 'Object';
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2007 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 Definition the goog.debug.RelativeTimeProvider class.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.RelativeTimeProvider');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A simple object to keep track of a timestamp considered the start of
|
||||
* something. The main use is for the logger system to maintain a start time
|
||||
* that is occasionally reset. For example, in Gmail, we reset this relative
|
||||
* time at the start of a user action so that timings are offset from the
|
||||
* beginning of the action. This class also provides a singleton as the default
|
||||
* behavior for most use cases is to share the same start time.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider = function() {
|
||||
/**
|
||||
* The start time.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.relativeTimeStart_ = goog.now();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default instance.
|
||||
* @type {goog.debug.RelativeTimeProvider}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider.defaultInstance_ =
|
||||
new goog.debug.RelativeTimeProvider();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the start time to the specified time.
|
||||
* @param {number} timeStamp The start time.
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider.prototype.set = function(timeStamp) {
|
||||
this.relativeTimeStart_ = timeStamp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resets the start time to now.
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider.prototype.reset = function() {
|
||||
this.set(goog.now());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The start time.
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider.prototype.get = function() {
|
||||
return this.relativeTimeStart_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.debug.RelativeTimeProvider} The default instance.
|
||||
*/
|
||||
goog.debug.RelativeTimeProvider.getDefaultInstance = function() {
|
||||
return goog.debug.RelativeTimeProvider.defaultInstance_;
|
||||
};
|
||||
724
float-no-zero/closure-library/closure/goog/debug/tracer.js
Normal file
724
float-no-zero/closure-library/closure/goog/debug/tracer.js
Normal file
@@ -0,0 +1,724 @@
|
||||
// Copyright 2006 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 Definition of the Tracer class and associated classes.
|
||||
*
|
||||
* @see ../demos/tracer.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.debug.Trace');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.iter');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.structs.Map');
|
||||
goog.require('goog.structs.SimplePool');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class used for singleton goog.debug.Trace. Used for timing slow points in
|
||||
* the code. Based on the java Tracer class but optimized for javascript.
|
||||
* See com.google.common.tracing.Tracer.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_ = function() {
|
||||
|
||||
/**
|
||||
* Events in order.
|
||||
* @type {Array.<goog.debug.Trace_.Event_>}
|
||||
* @private
|
||||
*/
|
||||
this.events_ = [];
|
||||
|
||||
/**
|
||||
* Outstanding events that have started but haven't yet ended. The keys are
|
||||
* numeric ids and the values are goog.debug.Trace_.Event_ objects.
|
||||
* @type {goog.structs.Map}
|
||||
* @private
|
||||
*/
|
||||
this.outstandingEvents_ = new goog.structs.Map();
|
||||
|
||||
/**
|
||||
* Start time of the event trace
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.startTime_ = 0;
|
||||
|
||||
/**
|
||||
* Cummulative overhead of calls to startTracer
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tracerOverheadStart_ = 0;
|
||||
|
||||
/**
|
||||
* Cummulative overhead of calls to endTracer
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tracerOverheadEnd_ = 0;
|
||||
|
||||
/**
|
||||
* Cummulative overhead of calls to addComment
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tracerOverheadComment_ = 0;
|
||||
|
||||
/**
|
||||
* Keeps stats on different types of tracers. The keys are strings and the
|
||||
* values are goog.debug.Stat
|
||||
* @type {goog.structs.Map}
|
||||
* @private
|
||||
*/
|
||||
this.stats_ = new goog.structs.Map();
|
||||
|
||||
/**
|
||||
* Total number of traces created in the trace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.tracerCount_ = 0;
|
||||
|
||||
/**
|
||||
* Total number of comments created in the trace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.commentCount_ = 0;
|
||||
|
||||
/**
|
||||
* Next id to use for the trace.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.nextId_ = 1;
|
||||
|
||||
/**
|
||||
* A pool for goog.debug.Trace_.Event_ objects so we don't keep creating and
|
||||
* garbage collecting these (which is very expensive in IE6).
|
||||
* @type {goog.structs.SimplePool}
|
||||
* @private
|
||||
*/
|
||||
this.eventPool_ = new goog.structs.SimplePool(0, 4000);
|
||||
this.eventPool_.createObject = function() {
|
||||
return new goog.debug.Trace_.Event_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A pool for goog.debug.Trace_.Stat_ objects so we don't keep creating and
|
||||
* garbage collecting these (which is very expensive in IE6).
|
||||
* @type {goog.structs.SimplePool}
|
||||
* @private
|
||||
*/
|
||||
this.statPool_ = new goog.structs.SimplePool(0, 50);
|
||||
this.statPool_.createObject = function() {
|
||||
return new goog.debug.Trace_.Stat_();
|
||||
};
|
||||
|
||||
var that = this;
|
||||
this.idPool_ = new goog.structs.SimplePool(0, 2000);
|
||||
|
||||
// TODO(nicksantos): SimplePool is supposed to only return objects.
|
||||
// Reconcile this so that we don't have to cast to number below.
|
||||
this.idPool_.createObject = function() {
|
||||
return String(that.nextId_++);
|
||||
};
|
||||
this.idPool_.disposeObject = function(obj) {};
|
||||
|
||||
/**
|
||||
* Default threshold below which a tracer shouldn't be reported
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.defaultThreshold_ = 3;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logger for the tracer
|
||||
* @type {goog.log.Logger}
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.prototype.logger_ =
|
||||
goog.log.getLogger('goog.debug.Trace');
|
||||
|
||||
|
||||
/**
|
||||
* Maximum size of the trace before we discard events
|
||||
* @type {number}
|
||||
*/
|
||||
goog.debug.Trace_.prototype.MAX_TRACE_SIZE = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* Event type supported by tracer
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.debug.Trace_.EventType = {
|
||||
/**
|
||||
* Start event type
|
||||
*/
|
||||
START: 0,
|
||||
|
||||
/**
|
||||
* Stop event type
|
||||
*/
|
||||
STOP: 1,
|
||||
|
||||
/**
|
||||
* Comment event type
|
||||
*/
|
||||
COMMENT: 2
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class to keep track of a stat of a single tracer type. Stores the count
|
||||
* and cumulative time.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.Stat_ = function() {
|
||||
/**
|
||||
* Number of tracers
|
||||
* @type {number}
|
||||
*/
|
||||
this.count = 0;
|
||||
|
||||
/**
|
||||
* Cumulative time of traces
|
||||
* @type {number}
|
||||
*/
|
||||
this.time = 0;
|
||||
|
||||
/**
|
||||
* Total number of allocations for this tracer type
|
||||
* @type {number}
|
||||
*/
|
||||
this.varAlloc = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {string|null|undefined}
|
||||
*/
|
||||
goog.debug.Trace_.Stat_.prototype.type;
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} A string describing the tracer stat.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.Trace_.Stat_.prototype.toString = function() {
|
||||
var sb = [];
|
||||
sb.push(this.type, ' ', this.count, ' (', Math.round(this.time * 10) / 10,
|
||||
' ms)');
|
||||
if (this.varAlloc) {
|
||||
sb.push(' [VarAlloc = ', this.varAlloc, ']');
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Private class used to encapsulate a single event, either the start or stop
|
||||
* of a tracer.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.Event_ = function() {
|
||||
// the fields are different for different events - see usage in code
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {string|null|undefined}
|
||||
*/
|
||||
goog.debug.Trace_.Event_.prototype.type;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string for the event.
|
||||
* @param {number} startTime The start time of the trace to generate relative
|
||||
* times.
|
||||
* @param {number} prevTime The completion time of the previous event or -1.
|
||||
* @param {string} indent Extra indent for the message
|
||||
* if there was no previous event.
|
||||
* @return {string} The formatted tracer string.
|
||||
*/
|
||||
goog.debug.Trace_.Event_.prototype.toTraceString = function(startTime, prevTime,
|
||||
indent) {
|
||||
var sb = [];
|
||||
|
||||
if (prevTime == -1) {
|
||||
sb.push(' ');
|
||||
} else {
|
||||
sb.push(goog.debug.Trace_.longToPaddedString_(this.eventTime - prevTime));
|
||||
}
|
||||
|
||||
sb.push(' ', goog.debug.Trace_.formatTime_(this.eventTime - startTime));
|
||||
if (this.eventType == goog.debug.Trace_.EventType.START) {
|
||||
sb.push(' Start ');
|
||||
} else if (this.eventType == goog.debug.Trace_.EventType.STOP) {
|
||||
sb.push(' Done ');
|
||||
var delta = this.stopTime - this.startTime;
|
||||
sb.push(goog.debug.Trace_.longToPaddedString_(delta), ' ms ');
|
||||
} else {
|
||||
sb.push(' Comment ');
|
||||
}
|
||||
|
||||
sb.push(indent, this);
|
||||
if (this.totalVarAlloc > 0) {
|
||||
sb.push('[VarAlloc ', this.totalVarAlloc, '] ');
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} A string describing the tracer event.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.Trace_.Event_.prototype.toString = function() {
|
||||
if (this.type == null) {
|
||||
return this.comment;
|
||||
} else {
|
||||
return '[' + this.type + '] ' + this.comment;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add the ability to explicitly set the start time. This is useful for example
|
||||
* for measuring initial load time where you can set a variable as soon as the
|
||||
* main page of the app is loaded and then later call this function when the
|
||||
* Tracer code has been loaded.
|
||||
* @param {number} startTime The start time to set.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.setStartTime = function(startTime) {
|
||||
this.startTime_ = startTime;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes and resets the current trace
|
||||
* @param {number} defaultThreshold The default threshold below which the
|
||||
* tracer output will be supressed. Can be overridden on a per-Tracer basis.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.initCurrentTrace = function(defaultThreshold) {
|
||||
this.reset(defaultThreshold);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the current trace
|
||||
*/
|
||||
goog.debug.Trace_.prototype.clearCurrentTrace = function() {
|
||||
this.reset(0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Resets the trace.
|
||||
* @param {number} defaultThreshold The default threshold below which the
|
||||
* tracer output will be supressed. Can be overridden on a per-Tracer basis.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.reset = function(defaultThreshold) {
|
||||
this.defaultThreshold_ = defaultThreshold;
|
||||
|
||||
for (var i = 0; i < this.events_.length; i++) {
|
||||
var id = /** @type {Object} */ (this.eventPool_).id;
|
||||
if (id) {
|
||||
this.idPool_.releaseObject(id);
|
||||
}
|
||||
this.eventPool_.releaseObject(this.events_[i]);
|
||||
}
|
||||
|
||||
this.events_.length = 0;
|
||||
this.outstandingEvents_.clear();
|
||||
this.startTime_ = goog.debug.Trace_.now();
|
||||
this.tracerOverheadStart_ = 0;
|
||||
this.tracerOverheadEnd_ = 0;
|
||||
this.tracerOverheadComment_ = 0;
|
||||
this.tracerCount_ = 0;
|
||||
this.commentCount_ = 0;
|
||||
|
||||
var keys = this.stats_.getKeys();
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var stat = this.stats_.get(key);
|
||||
stat.count = 0;
|
||||
stat.time = 0;
|
||||
stat.varAlloc = 0;
|
||||
this.statPool_.releaseObject(/** @type {Object} */ (stat));
|
||||
}
|
||||
this.stats_.clear();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Starts a tracer
|
||||
* @param {string} comment A comment used to identify the tracer. Does not
|
||||
* need to be unique.
|
||||
* @param {string=} opt_type Type used to identify the tracer. If a Trace is
|
||||
* given a type (the first argument to the constructor) and multiple Traces
|
||||
* are done on that type then a "TOTAL line will be produced showing the
|
||||
* total number of traces and the sum of the time
|
||||
* ("TOTAL Database 2 (37 ms)" in our example). These traces should be
|
||||
* mutually exclusive or else the sum won't make sense (the time will
|
||||
* be double counted if the second starts before the first ends).
|
||||
* @return {number} The identifier for the tracer that should be passed to the
|
||||
* the stopTracer method.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.startTracer = function(comment, opt_type) {
|
||||
var tracerStartTime = goog.debug.Trace_.now();
|
||||
var varAlloc = this.getTotalVarAlloc();
|
||||
var outstandingEventCount = this.outstandingEvents_.getCount();
|
||||
if (this.events_.length + outstandingEventCount > this.MAX_TRACE_SIZE) {
|
||||
goog.log.warning(this.logger_,
|
||||
'Giant thread trace. Clearing to avoid memory leak.');
|
||||
// This is the more likely case. This usually means that we
|
||||
// either forgot to clear the trace or else we are performing a
|
||||
// very large number of events
|
||||
if (this.events_.length > this.MAX_TRACE_SIZE / 2) {
|
||||
for (var i = 0; i < this.events_.length; i++) {
|
||||
var event = this.events_[i];
|
||||
if (event.id) {
|
||||
this.idPool_.releaseObject(event.id);
|
||||
}
|
||||
this.eventPool_.releaseObject(event);
|
||||
}
|
||||
this.events_.length = 0;
|
||||
}
|
||||
|
||||
// This is less likely and probably indicates that a lot of traces
|
||||
// aren't being closed. We want to avoid unnecessarily clearing
|
||||
// this though in case the events do eventually finish.
|
||||
if (outstandingEventCount > this.MAX_TRACE_SIZE / 2) {
|
||||
this.outstandingEvents_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
goog.debug.Logger.logToProfilers('Start : ' + comment);
|
||||
|
||||
var event = /** @type {goog.debug.Trace_.Event_} */ (
|
||||
this.eventPool_.getObject());
|
||||
event.totalVarAlloc = varAlloc;
|
||||
event.eventType = goog.debug.Trace_.EventType.START;
|
||||
event.id = Number(this.idPool_.getObject());
|
||||
event.comment = comment;
|
||||
event.type = opt_type;
|
||||
this.events_.push(event);
|
||||
this.outstandingEvents_.set(String(event.id), event);
|
||||
this.tracerCount_++;
|
||||
var now = goog.debug.Trace_.now();
|
||||
event.startTime = event.eventTime = now;
|
||||
this.tracerOverheadStart_ += now - tracerStartTime;
|
||||
return event.id;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops a tracer
|
||||
* @param {number|undefined|null} id The id of the tracer that is ending.
|
||||
* @param {number=} opt_silenceThreshold Threshold below which the tracer is
|
||||
* silenced.
|
||||
* @return {?number} The elapsed time for the tracer or null if the tracer
|
||||
* identitifer was not recognized.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.stopTracer = function(id, opt_silenceThreshold) {
|
||||
// this used to call goog.isDef(opt_silenceThreshold) but that causes an
|
||||
// object allocation in IE for some reason (doh!). The following code doesn't
|
||||
// cause an allocation
|
||||
var now = goog.debug.Trace_.now();
|
||||
var silenceThreshold;
|
||||
if (opt_silenceThreshold === 0) {
|
||||
silenceThreshold = 0;
|
||||
} else if (opt_silenceThreshold) {
|
||||
silenceThreshold = opt_silenceThreshold;
|
||||
} else {
|
||||
silenceThreshold = this.defaultThreshold_;
|
||||
}
|
||||
|
||||
var startEvent = this.outstandingEvents_.get(String(id));
|
||||
if (startEvent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.outstandingEvents_.remove(String(id));
|
||||
|
||||
var stopEvent;
|
||||
var elapsed = now - startEvent.startTime;
|
||||
if (elapsed < silenceThreshold) {
|
||||
var count = this.events_.length;
|
||||
for (var i = count - 1; i >= 0; i--) {
|
||||
var nextEvent = this.events_[i];
|
||||
if (nextEvent == startEvent) {
|
||||
this.events_.splice(i, 1);
|
||||
this.idPool_.releaseObject(startEvent.id);
|
||||
this.eventPool_.releaseObject(/** @type {Object} */ (startEvent));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
stopEvent = /** @type {goog.debug.Trace_.Event_} */ (
|
||||
this.eventPool_.getObject());
|
||||
stopEvent.eventType = goog.debug.Trace_.EventType.STOP;
|
||||
stopEvent.startTime = startEvent.startTime;
|
||||
stopEvent.comment = startEvent.comment;
|
||||
stopEvent.type = startEvent.type;
|
||||
stopEvent.stopTime = stopEvent.eventTime = now;
|
||||
|
||||
this.events_.push(stopEvent);
|
||||
}
|
||||
|
||||
var type = startEvent.type;
|
||||
var stat = null;
|
||||
if (type) {
|
||||
stat = this.getStat_(type);
|
||||
stat.count++;
|
||||
stat.time += elapsed;
|
||||
}
|
||||
if (stopEvent) {
|
||||
goog.debug.Logger.logToProfilers('Stop : ' + stopEvent.comment);
|
||||
|
||||
stopEvent.totalVarAlloc = this.getTotalVarAlloc();
|
||||
|
||||
if (stat) {
|
||||
stat.varAlloc += (stopEvent.totalVarAlloc - startEvent.totalVarAlloc);
|
||||
}
|
||||
}
|
||||
var tracerFinishTime = goog.debug.Trace_.now();
|
||||
this.tracerOverheadEnd_ += tracerFinishTime - now;
|
||||
return elapsed;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the ActiveX object that can be used to get GC tracing in IE6.
|
||||
* @param {Object} gcTracer GCTracer ActiveX object.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.setGcTracer = function(gcTracer) {
|
||||
this.gcTracer_ = gcTracer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the total number of allocations since the GC stats were reset. Only
|
||||
* works in IE.
|
||||
* @return {number} The number of allocaitons or -1 if not supported.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.getTotalVarAlloc = function() {
|
||||
var gcTracer = this.gcTracer_;
|
||||
// isTracing is defined on the ActiveX object.
|
||||
if (gcTracer && gcTracer['isTracing']()) {
|
||||
return gcTracer['totalVarAlloc'];
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a comment to the trace. Makes it possible to see when a specific event
|
||||
* happened in relation to the traces.
|
||||
* @param {string} comment A comment that is inserted into the trace.
|
||||
* @param {?string=} opt_type Type used to identify the tracer. If a comment is
|
||||
* given a type and multiple comments are done on that type then a "TOTAL
|
||||
* line will be produced showing the total number of comments of that type.
|
||||
* @param {?number=} opt_timeStamp The timestamp to insert the comment. If not
|
||||
* specified, the current time wil be used.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.addComment = function(comment, opt_type,
|
||||
opt_timeStamp) {
|
||||
var now = goog.debug.Trace_.now();
|
||||
var timeStamp = opt_timeStamp ? opt_timeStamp : now;
|
||||
|
||||
var eventComment = /** @type {goog.debug.Trace_.Event_} */ (
|
||||
this.eventPool_.getObject());
|
||||
eventComment.eventType = goog.debug.Trace_.EventType.COMMENT;
|
||||
eventComment.eventTime = timeStamp;
|
||||
eventComment.type = opt_type;
|
||||
eventComment.comment = comment;
|
||||
eventComment.totalVarAlloc = this.getTotalVarAlloc();
|
||||
this.commentCount_++;
|
||||
|
||||
if (opt_timeStamp) {
|
||||
var numEvents = this.events_.length;
|
||||
for (var i = 0; i < numEvents; i++) {
|
||||
var event = this.events_[i];
|
||||
var eventTime = event.eventTime;
|
||||
|
||||
if (eventTime > timeStamp) {
|
||||
goog.array.insertAt(this.events_, eventComment, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == numEvents) {
|
||||
this.events_.push(eventComment);
|
||||
}
|
||||
} else {
|
||||
this.events_.push(eventComment);
|
||||
}
|
||||
|
||||
var type = eventComment.type;
|
||||
if (type) {
|
||||
var stat = this.getStat_(type);
|
||||
stat.count++;
|
||||
}
|
||||
|
||||
this.tracerOverheadComment_ += goog.debug.Trace_.now() - now;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets a stat object for a particular type. The stat object is created if it
|
||||
* hasn't yet been.
|
||||
* @param {string} type The type of stat.
|
||||
* @return {goog.debug.Trace_.Stat_} The stat object.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.prototype.getStat_ = function(type) {
|
||||
var stat = this.stats_.get(type);
|
||||
if (!stat) {
|
||||
stat = /** @type {goog.debug.Trace_.Event_} */ (
|
||||
this.statPool_.getObject());
|
||||
stat.type = type;
|
||||
this.stats_.set(type, stat);
|
||||
}
|
||||
return /** @type {goog.debug.Trace_.Stat_} */(stat);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string for the current trace
|
||||
* @return {string} A formatted string that shows the timings of the current
|
||||
* trace.
|
||||
*/
|
||||
goog.debug.Trace_.prototype.getFormattedTrace = function() {
|
||||
return this.toString();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string that describes the thread trace.
|
||||
* @return {string} A formatted string.
|
||||
* @override
|
||||
*/
|
||||
goog.debug.Trace_.prototype.toString = function() {
|
||||
var sb = [];
|
||||
var etime = -1;
|
||||
var indent = [];
|
||||
for (var i = 0; i < this.events_.length; i++) {
|
||||
var e = this.events_[i];
|
||||
if (e.eventType == goog.debug.Trace_.EventType.STOP) {
|
||||
indent.pop();
|
||||
}
|
||||
sb.push(' ', e.toTraceString(this.startTime_, etime, indent.join('')));
|
||||
etime = e.eventTime;
|
||||
sb.push('\n');
|
||||
if (e.eventType == goog.debug.Trace_.EventType.START) {
|
||||
indent.push('| ');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.outstandingEvents_.getCount() != 0) {
|
||||
var now = goog.debug.Trace_.now();
|
||||
|
||||
sb.push(' Unstopped timers:\n');
|
||||
goog.iter.forEach(this.outstandingEvents_, function(startEvent) {
|
||||
sb.push(' ', startEvent, ' (', now - startEvent.startTime,
|
||||
' ms, started at ',
|
||||
goog.debug.Trace_.formatTime_(startEvent.startTime),
|
||||
')\n');
|
||||
});
|
||||
}
|
||||
|
||||
var statKeys = this.stats_.getKeys();
|
||||
for (var i = 0; i < statKeys.length; i++) {
|
||||
var stat = this.stats_.get(statKeys[i]);
|
||||
if (stat.count > 1) {
|
||||
sb.push(' TOTAL ', stat, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
sb.push('Total tracers created ', this.tracerCount_, '\n',
|
||||
'Total comments created ', this.commentCount_, '\n',
|
||||
'Overhead start: ', this.tracerOverheadStart_, ' ms\n',
|
||||
'Overhead end: ', this.tracerOverheadEnd_, ' ms\n',
|
||||
'Overhead comment: ', this.tracerOverheadComment_, ' ms\n');
|
||||
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts 'v' to a string and pads it with up to 3 spaces for
|
||||
* improved alignment. TODO there must be a better way
|
||||
* @param {number} v A number.
|
||||
* @return {string} A padded string.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.longToPaddedString_ = function(v) {
|
||||
v = Math.round(v);
|
||||
// todo (pupius) - there should be a generic string in goog.string for this
|
||||
var space = '';
|
||||
if (v < 1000) space = ' ';
|
||||
if (v < 100) space = ' ';
|
||||
if (v < 10) space = ' ';
|
||||
return space + v;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the sec.ms part of time (if time = "20:06:11.566", "11.566
|
||||
* @param {number} time The time in MS.
|
||||
* @return {string} A formatted string as sec.ms'.
|
||||
* @private
|
||||
*/
|
||||
goog.debug.Trace_.formatTime_ = function(time) {
|
||||
time = Math.round(time);
|
||||
var sec = (time / 1000) % 60;
|
||||
var ms = time % 1000;
|
||||
|
||||
// TODO their must be a nicer way to get zero padded integers
|
||||
return String(100 + sec).substring(1, 3) + '.' +
|
||||
String(1000 + ms).substring(1, 4);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current time. Done through a wrapper function so it can be
|
||||
* overridden by application code. Gmail has an ActiveX extension that provides
|
||||
* higher precision timing info.
|
||||
* @return {number} The current time in milliseconds.
|
||||
*/
|
||||
goog.debug.Trace_.now = function() {
|
||||
return goog.now();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Singleton trace object
|
||||
* @type {goog.debug.Trace_}
|
||||
*/
|
||||
goog.debug.Trace = new goog.debug.Trace_();
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
/** @nocompile */
|
||||
|
||||
['Big Table', 'Googlebot', 'Instant Indexing', 'Mustang', 'Page Rank',
|
||||
'Proto Buffer']
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
/** @nocompile */
|
||||
|
||||
[
|
||||
['apple',
|
||||
{name: 'Fuji', url: 'http://www.google.com/images?q=fuji+apple'},
|
||||
{name: 'Gala', url: 'http://www.google.com/images?q=gala+apple'},
|
||||
{name: 'Golden Delicious',
|
||||
url: 'http://www.google.com/images?q=golden delicious+apple'}
|
||||
],
|
||||
['citrus',
|
||||
{name: 'Lemon', url: 'http://www.google.com/images?q=lemon+fruit'},
|
||||
{name: 'Orange', url: 'http://www.google.com/images?q=orange+fruit'}
|
||||
],
|
||||
['berry',
|
||||
{name: 'Strawberry', url: 'http://www.google.com/images?q=strawberry+fruit'},
|
||||
{name: 'Blueberry', url: 'http://www.google.com/images?q=blueberry+fruit'},
|
||||
{name: 'Blackberry', url: 'http://www.google.com/images?q=blackberry+fruit'}
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2009 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.
|
||||
//
|
||||
// This file has been auto-generated by GenJsDeps, please do not edit.
|
||||
|
||||
goog.addDependency('demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'], ['goog.ui.equation.EquationEditorDialog']);
|
||||
goog.addDependency('demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);
|
||||
goog.addDependency('demos/editor/helloworlddialog.js', ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType']);
|
||||
goog.addDependency('demos/editor/helloworlddialogplugin.js', ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType']);
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @see equationeditor.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.demos.editor.EquationEditor');
|
||||
|
||||
goog.require('goog.ui.equation.EquationEditorDialog');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
goog.demos.editor.EquationEditor = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new editor and opens the dialog.
|
||||
* @param {string} initialEquation The initial equation value to use.
|
||||
*/
|
||||
goog.demos.editor.EquationEditor.prototype.openEditor = function(
|
||||
initialEquation) {
|
||||
var editorDialog = new goog.ui.equation.EquationEditorDialog(initialEquation);
|
||||
editorDialog.setVisible(true);
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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 A simple plugin that inserts 'Hello World!' on command. This
|
||||
* plugin is intended to be an example of a very simple plugin for plugin
|
||||
* developers.
|
||||
*
|
||||
* @author gak@google.com (Gregory Kick)
|
||||
* @see helloworld.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.demos.editor.HelloWorld');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.editor.Plugin');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Plugin to insert 'Hello World!' into an editable field.
|
||||
* @constructor
|
||||
* @extends {goog.editor.Plugin}
|
||||
*/
|
||||
goog.demos.editor.HelloWorld = function() {
|
||||
goog.editor.Plugin.call(this);
|
||||
};
|
||||
goog.inherits(goog.demos.editor.HelloWorld, goog.editor.Plugin);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.demos.editor.HelloWorld.prototype.getTrogClassId = function() {
|
||||
return 'HelloWorld';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Commands implemented by this plugin.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.demos.editor.HelloWorld.COMMAND = {
|
||||
HELLO_WORLD: '+helloWorld'
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.demos.editor.HelloWorld.prototype.isSupportedCommand = function(
|
||||
command) {
|
||||
return command == goog.demos.editor.HelloWorld.COMMAND.HELLO_WORLD;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Executes a command. Does not fire any BEFORECHANGE, CHANGE, or
|
||||
* SELECTIONCHANGE events (these are handled by the super class implementation
|
||||
* of {@code execCommand}.
|
||||
* @param {string} command Command to execute.
|
||||
* @override
|
||||
* @protected
|
||||
*/
|
||||
goog.demos.editor.HelloWorld.prototype.execCommandInternal = function(
|
||||
command) {
|
||||
var domHelper = this.getFieldObject().getEditableDomHelper();
|
||||
var range = this.getFieldObject().getRange();
|
||||
range.removeContents();
|
||||
var newNode =
|
||||
domHelper.createDom(goog.dom.TagName.SPAN, null, 'Hello World!');
|
||||
range.insertNode(newNode, false);
|
||||
};
|
||||
@@ -0,0 +1,171 @@
|
||||
// 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 example of how to write a dialog to be opened by a plugin.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.demos.editor.HelloWorldDialog');
|
||||
goog.provide('goog.demos.editor.HelloWorldDialog.OkEvent');
|
||||
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.ui.editor.AbstractDialog');
|
||||
|
||||
|
||||
// *** Public interface ***************************************************** //
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a dialog to let the user enter a customized hello world message.
|
||||
* @param {goog.dom.DomHelper} domHelper DomHelper to be used to create the
|
||||
* dialog's dom structure.
|
||||
* @constructor
|
||||
* @extends {goog.ui.editor.AbstractDialog}
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog = function(domHelper) {
|
||||
goog.ui.editor.AbstractDialog.call(this, domHelper);
|
||||
};
|
||||
goog.inherits(goog.demos.editor.HelloWorldDialog,
|
||||
goog.ui.editor.AbstractDialog);
|
||||
|
||||
|
||||
// *** Event **************************************************************** //
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OK event object for the hello world dialog.
|
||||
* @param {string} message Customized hello world message chosen by the user.
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.OkEvent = function(message) {
|
||||
this.message = message;
|
||||
};
|
||||
goog.inherits(goog.demos.editor.HelloWorldDialog.OkEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* Event type.
|
||||
* @type {goog.ui.editor.AbstractDialog.EventType}
|
||||
* @override
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.OkEvent.prototype.type =
|
||||
goog.ui.editor.AbstractDialog.EventType.OK;
|
||||
|
||||
|
||||
/**
|
||||
* Customized hello world message chosen by the user.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.OkEvent.prototype.message;
|
||||
|
||||
|
||||
// *** Protected interface ************************************************** //
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.demos.editor.HelloWorldDialog.prototype.createDialogControl = function() {
|
||||
var builder = new goog.ui.editor.AbstractDialog.Builder(this);
|
||||
/** @desc Title of the hello world dialog. */
|
||||
var MSG_HELLO_WORLD_DIALOG_TITLE = goog.getMsg('Add a Hello World message');
|
||||
builder.setTitle(MSG_HELLO_WORLD_DIALOG_TITLE).
|
||||
setContent(this.createContent_());
|
||||
return builder.build();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates and returns the event object to be used when dispatching the OK
|
||||
* event to listeners, or returns null to prevent the dialog from closing.
|
||||
* @param {goog.events.Event} e The event object dispatched by the wrapped
|
||||
* dialog.
|
||||
* @return {goog.demos.editor.HelloWorldDialog.OkEvent} The event object to be
|
||||
* used when dispatching the OK event to listeners.
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.prototype.createOkEvent = function(e) {
|
||||
var message = this.getMessage_();
|
||||
if (message &&
|
||||
goog.demos.editor.HelloWorldDialog.isValidHelloWorld_(message)) {
|
||||
return new goog.demos.editor.HelloWorldDialog.OkEvent(message);
|
||||
} else {
|
||||
/** @desc Error message telling the user why their message was rejected. */
|
||||
var MSG_HELLO_WORLD_DIALOG_ERROR =
|
||||
goog.getMsg('Your message must contain the words "hello" and "world".');
|
||||
this.dom.getWindow().alert(MSG_HELLO_WORLD_DIALOG_ERROR);
|
||||
return null; // Prevents the dialog from closing.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// *** Private implementation *********************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* Input element where the user will type their hello world message.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.prototype.input_;
|
||||
|
||||
|
||||
/**
|
||||
* Creates the DOM structure that makes up the dialog's content area.
|
||||
* @return {Element} The DOM structure that makes up the dialog's content area.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.prototype.createContent_ = function() {
|
||||
/** @desc Sample hello world message to prepopulate the dialog with. */
|
||||
var MSG_HELLO_WORLD_DIALOG_SAMPLE = goog.getMsg('Hello, world!');
|
||||
this.input_ = this.dom.createDom(goog.dom.TagName.INPUT,
|
||||
{size: 25, value: MSG_HELLO_WORLD_DIALOG_SAMPLE});
|
||||
/** @desc Prompt telling the user to enter a hello world message. */
|
||||
var MSG_HELLO_WORLD_DIALOG_PROMPT =
|
||||
goog.getMsg('Enter your Hello World message');
|
||||
return this.dom.createDom(goog.dom.TagName.DIV,
|
||||
null,
|
||||
[MSG_HELLO_WORLD_DIALOG_PROMPT, this.input_]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hello world message currently typed into the dialog's input.
|
||||
* @return {?string} The hello world message currently typed into the dialog's
|
||||
* input, or null if called before the input is created.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.prototype.getMessage_ = function() {
|
||||
return this.input_ && this.input_.value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether or not the given message contains the strings "hello" and
|
||||
* "world". Case-insensitive and order doesn't matter.
|
||||
* @param {string} message The message to be checked.
|
||||
* @return {boolean} Whether or not the given message contains the strings
|
||||
* "hello" and "world".
|
||||
* @private
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialog.isValidHelloWorld_ = function(message) {
|
||||
message = message.toLowerCase();
|
||||
return goog.string.contains(message, 'hello') &&
|
||||
goog.string.contains(message, 'world');
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
// 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 example of how to write a dialog plugin.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.demos.editor.HelloWorldDialogPlugin');
|
||||
goog.provide('goog.demos.editor.HelloWorldDialogPlugin.Command');
|
||||
|
||||
goog.require('goog.demos.editor.HelloWorldDialog');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.editor.plugins.AbstractDialogPlugin');
|
||||
goog.require('goog.editor.range');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.ui.editor.AbstractDialog');
|
||||
|
||||
|
||||
// *** Public interface ***************************************************** //
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A plugin that opens the hello world dialog.
|
||||
* @constructor
|
||||
* @extends {goog.editor.plugins.AbstractDialogPlugin}
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialogPlugin = function() {
|
||||
goog.editor.plugins.AbstractDialogPlugin.call(this,
|
||||
goog.demos.editor.HelloWorldDialogPlugin.Command.HELLO_WORLD_DIALOG);
|
||||
};
|
||||
goog.inherits(goog.demos.editor.HelloWorldDialogPlugin,
|
||||
goog.editor.plugins.AbstractDialogPlugin);
|
||||
|
||||
|
||||
/**
|
||||
* Commands implemented by this plugin.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialogPlugin.Command = {
|
||||
HELLO_WORLD_DIALOG: 'helloWorldDialog'
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.demos.editor.HelloWorldDialogPlugin.prototype.getTrogClassId =
|
||||
goog.functions.constant('HelloWorldDialog');
|
||||
|
||||
|
||||
// *** Protected interface ************************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the dialog and registers for the relevant events.
|
||||
* @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to
|
||||
* create the dialog.
|
||||
* @return {goog.demos.editor.HelloWorldDialog} The dialog.
|
||||
* @override
|
||||
* @protected
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialogPlugin.prototype.createDialog = function(
|
||||
dialogDomHelper) {
|
||||
var dialog = new goog.demos.editor.HelloWorldDialog(dialogDomHelper);
|
||||
dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
|
||||
this.handleOk_,
|
||||
false,
|
||||
this);
|
||||
return dialog;
|
||||
};
|
||||
|
||||
|
||||
// *** Private implementation *********************************************** //
|
||||
|
||||
|
||||
/**
|
||||
* Handles the OK event from the dialog by inserting the hello world message
|
||||
* into the field.
|
||||
* @param {goog.demos.editor.HelloWorldDialog.OkEvent} e OK event object.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.editor.HelloWorldDialogPlugin.prototype.handleOk_ = function(e) {
|
||||
// First restore the selection so we can manipulate the field's content
|
||||
// according to what was selected.
|
||||
this.restoreOriginalSelection();
|
||||
|
||||
// Notify listeners that the field's contents are about to change.
|
||||
this.getFieldObject().dispatchBeforeChange();
|
||||
|
||||
// Now we can clear out what was previously selected (if anything).
|
||||
var range = this.getFieldObject().getRange();
|
||||
range.removeContents();
|
||||
// And replace it with a span containing our hello world message.
|
||||
var createdNode = this.getFieldDomHelper().createDom(goog.dom.TagName.SPAN,
|
||||
null,
|
||||
e.message);
|
||||
createdNode = range.insertNode(createdNode, false);
|
||||
// Place the cursor at the end of the new text node (false == to the right).
|
||||
goog.editor.range.placeCursorNextTo(createdNode, false);
|
||||
|
||||
// Notify listeners that the field's selection has changed.
|
||||
this.getFieldObject().dispatchSelectionChangeEvent();
|
||||
// Notify listeners that the field's contents have changed.
|
||||
this.getFieldObject().dispatchChange();
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,197 @@
|
||||
// Copyright 2007 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 A simple, sample component.
|
||||
*
|
||||
*/
|
||||
goog.provide('goog.demos.SampleComponent');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.classes');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.events.KeyCodes');
|
||||
goog.require('goog.events.KeyHandler');
|
||||
goog.require('goog.ui.Component');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A simple box that changes colour when clicked. This class demonstrates the
|
||||
* goog.ui.Component API, and is keyboard accessible, as per
|
||||
* http://wiki/Main/ClosureKeyboardAccessible
|
||||
*
|
||||
* @param {string=} opt_label A label to display. Defaults to "Click Me" if none
|
||||
* provided.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper DOM helper to use.
|
||||
*
|
||||
* @extends {goog.ui.Component}
|
||||
* @constructor
|
||||
*/
|
||||
goog.demos.SampleComponent = function(opt_label, opt_domHelper) {
|
||||
goog.base(this, opt_domHelper);
|
||||
|
||||
/**
|
||||
* The label to display.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.initialLabel_ = opt_label || 'Click Me';
|
||||
|
||||
/**
|
||||
* The current color.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.color_ = 'red';
|
||||
|
||||
/**
|
||||
* Keyboard handler for this object. This object is created once the
|
||||
* component's DOM element is known.
|
||||
*
|
||||
* @type {goog.events.KeyHandler?}
|
||||
* @private
|
||||
*/
|
||||
this.kh_ = null;
|
||||
};
|
||||
goog.inherits(goog.demos.SampleComponent, goog.ui.Component);
|
||||
|
||||
|
||||
/**
|
||||
* Changes the color of the element.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.changeColor_ = function() {
|
||||
if (this.color_ == 'red') {
|
||||
this.color_ = 'green';
|
||||
} else if (this.color_ == 'green') {
|
||||
this.color_ = 'blue';
|
||||
} else {
|
||||
this.color_ = 'red';
|
||||
}
|
||||
this.getElement().style.backgroundColor = this.color_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an initial DOM representation for the component.
|
||||
* @override
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.createDom = function() {
|
||||
this.decorateInternal(this.dom_.createElement('div'));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decorates an existing HTML DIV element as a SampleComponent.
|
||||
*
|
||||
* @param {Element} element The DIV element to decorate. The element's
|
||||
* text, if any will be used as the component's label.
|
||||
* @override
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.decorateInternal = function(element) {
|
||||
goog.base(this, 'decorateInternal', element);
|
||||
if (!this.getLabelText()) {
|
||||
this.setLabelText(this.initialLabel_);
|
||||
}
|
||||
|
||||
var elem = this.getElement();
|
||||
goog.dom.classes.add(elem, goog.getCssName('goog-sample-component'));
|
||||
elem.style.backgroundColor = this.color_;
|
||||
elem.tabIndex = 0;
|
||||
|
||||
this.kh_ = new goog.events.KeyHandler(elem);
|
||||
this.getHandler().listen(this.kh_, goog.events.KeyHandler.EventType.KEY,
|
||||
this.onKey_);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.demos.SampleComponent.prototype.disposeInternal = function() {
|
||||
goog.base(this, 'disposeInternal');
|
||||
if (this.kh_) {
|
||||
this.kh_.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when component's element is known to be in the document.
|
||||
* @override
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.enterDocument = function() {
|
||||
goog.base(this, 'enterDocument');
|
||||
this.getHandler().listen(this.getElement(), goog.events.EventType.CLICK,
|
||||
this.onDivClicked_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called when component's element is known to have been removed from the
|
||||
* document.
|
||||
* @override
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.exitDocument = function() {
|
||||
goog.base(this, 'exitDocument');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current label text.
|
||||
*
|
||||
* @return {string} The current text set into the label, or empty string if
|
||||
* none set.
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.getLabelText = function() {
|
||||
if (!this.getElement()) {
|
||||
return '';
|
||||
}
|
||||
return goog.dom.getTextContent(this.getElement());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles DIV element clicks, causing the DIV's colour to change.
|
||||
* @param {goog.events.Event} event The click event.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.onDivClicked_ = function(event) {
|
||||
this.changeColor_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fired when user presses a key while the DIV has focus. If the user presses
|
||||
* space or enter, the color will be changed.
|
||||
* @param {goog.events.Event} event The key event.
|
||||
* @private
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.onKey_ = function(event) {
|
||||
var keyCodes = goog.events.KeyCodes;
|
||||
if (event.keyCode == keyCodes.SPACE || event.keyCode == keyCodes.ENTER) {
|
||||
this.changeColor_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current label text. Has no effect if component is not rendered.
|
||||
*
|
||||
* @param {string} text The text to set as the label.
|
||||
*/
|
||||
goog.demos.SampleComponent.prototype.setLabelText = function(text) {
|
||||
if (this.getElement()) {
|
||||
goog.dom.setTextContent(this.getElement(), text);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,260 @@
|
||||
// Copyright 2010 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.
|
||||
var testData =
|
||||
['Countries', [['A', [['Afghanistan'],
|
||||
['Albania'],
|
||||
['Algeria'],
|
||||
['American Samoa'],
|
||||
['Andorra'],
|
||||
['Angola'],
|
||||
['Anguilla'],
|
||||
['Antarctica'],
|
||||
['Antigua and Barbuda'],
|
||||
['Argentina'],
|
||||
['Armenia'],
|
||||
['Aruba'],
|
||||
['Australia'],
|
||||
['Austria'],
|
||||
['Azerbaijan']]],
|
||||
['B', [['Bahamas'],
|
||||
['Bahrain'],
|
||||
['Bangladesh'],
|
||||
['Barbados'],
|
||||
['Belarus'],
|
||||
['Belgium'],
|
||||
['Belize'],
|
||||
['Benin'],
|
||||
['Bermuda'],
|
||||
['Bhutan'],
|
||||
['Bolivia'],
|
||||
['Bosnia and Herzegovina'],
|
||||
['Botswana'],
|
||||
['Bouvet Island'],
|
||||
['Brazil'],
|
||||
['British Indian Ocean Territory'],
|
||||
['Brunei Darussalam'],
|
||||
['Bulgaria'],
|
||||
['Burkina Faso'],
|
||||
['Burundi']]],
|
||||
['C', [['Cambodia'],
|
||||
['Cameroon'],
|
||||
['Canada'],
|
||||
['Cape Verde'],
|
||||
['Cayman Islands'],
|
||||
['Central African Republic'],
|
||||
['Chad'],
|
||||
['Chile'],
|
||||
['China'],
|
||||
['Christmas Island'],
|
||||
['Cocos (Keeling) Islands'],
|
||||
['Colombia'],
|
||||
['Comoros'],
|
||||
['Congo'],
|
||||
['Congo, the Democratic Republic of the'],
|
||||
['Cook Islands'],
|
||||
['Costa Rica'],
|
||||
['Croatia'],
|
||||
['Cuba'],
|
||||
['Cyprus'],
|
||||
['Czech Republic'],
|
||||
['C\u00f4te d\u2019Ivoire']]],
|
||||
['D', [['Denmark'],
|
||||
['Djibouti'],
|
||||
['Dominica'],
|
||||
['Dominican Republic']]],
|
||||
['E', [['Ecuador'],
|
||||
['Egypt'],
|
||||
['El Salvador'],
|
||||
['Equatorial Guinea'],
|
||||
['Eritrea'],
|
||||
['Estonia'],
|
||||
['Ethiopia']]],
|
||||
['F', [['Falkland Islands (Malvinas)'],
|
||||
['Faroe Islands'],
|
||||
['Fiji'],
|
||||
['Finland'],
|
||||
['France'],
|
||||
['French Guiana'],
|
||||
['French Polynesia'],
|
||||
['French Southern Territories']]],
|
||||
['G', [['Gabon'],
|
||||
['Gambia'],
|
||||
['Georgia'],
|
||||
['Germany'],
|
||||
['Ghana'],
|
||||
['Gibraltar'],
|
||||
['Greece'],
|
||||
['Greenland'],
|
||||
['Grenada'],
|
||||
['Guadeloupe'],
|
||||
['Guam'],
|
||||
['Guatemala'],
|
||||
['Guernsey'],
|
||||
['Guinea'],
|
||||
['Guinea-Bissau'],
|
||||
['Guyana']]],
|
||||
['H', [['Haiti'],
|
||||
['Heard Island and McDonald Islands'],
|
||||
['Holy See (Vatican City State)'],
|
||||
['Honduras'],
|
||||
['Hong Kong'],
|
||||
['Hungary']]],
|
||||
['I', [['Iceland'],
|
||||
['India'],
|
||||
['Indonesia'],
|
||||
['Iran, Islamic Republic of'],
|
||||
['Iraq'],
|
||||
['Ireland'],
|
||||
['Isle of Man'],
|
||||
['Israel'],
|
||||
['Italy']]],
|
||||
['J', [['Jamaica'],
|
||||
['Japan'],
|
||||
['Jersey'],
|
||||
['Jordan']]],
|
||||
['K', [['Kazakhstan'],
|
||||
['Kenya'],
|
||||
['Kiribati'],
|
||||
['Korea, Democratic People\u2019s Republic of'],
|
||||
['Korea, Republic of'],
|
||||
['Kuwait'],
|
||||
['Kyrgyzstan']]],
|
||||
['L', [['Lao People\u2019s Democratic Republic'],
|
||||
['Latvia'],
|
||||
['Lebanon'],
|
||||
['Lesotho'],
|
||||
['Liberia'],
|
||||
['Libyan Arab Jamahiriya'],
|
||||
['Liechtenstein'],
|
||||
['Lithuania'],
|
||||
['Luxembourg']]],
|
||||
['M', [['Macao'],
|
||||
['Macedonia, the former Yugoslav Republic of'],
|
||||
['Madagascar'],
|
||||
['Malawi'],
|
||||
['Malaysia'],
|
||||
['Maldives'],
|
||||
['Mali'],
|
||||
['Malta'],
|
||||
['Marshall Islands'],
|
||||
['Martinique'],
|
||||
['Mauritania'],
|
||||
['Mauritius'],
|
||||
['Mayotte'],
|
||||
['Mexico'],
|
||||
['Micronesia, Federated States of'],
|
||||
['Moldova, Republic of'],
|
||||
['Monaco'],
|
||||
['Mongolia'],
|
||||
['Montenegro'],
|
||||
['Montserrat'],
|
||||
['Morocco'],
|
||||
['Mozambique'],
|
||||
['Myanmar']]],
|
||||
['N', [['Namibia'],
|
||||
['Nauru'],
|
||||
['Nepal'],
|
||||
['Netherlands'],
|
||||
['Netherlands Antilles'],
|
||||
['New Caledonia'],
|
||||
['New Zealand'],
|
||||
['Nicaragua'],
|
||||
['Niger'],
|
||||
['Nigeria'],
|
||||
['Niue'],
|
||||
['Norfolk Island'],
|
||||
['Northern Mariana Islands'],
|
||||
['Norway']]],
|
||||
['O', [['Oman']]],
|
||||
['P', [['Pakistan'],
|
||||
['Palau'],
|
||||
['Palestinian Territory, Occupied'],
|
||||
['Panama'],
|
||||
['Papua New Guinea'],
|
||||
['Paraguay'],
|
||||
['Peru'],
|
||||
['Philippines'],
|
||||
['Pitcairn'],
|
||||
['Poland'],
|
||||
['Portugal'],
|
||||
['Puerto Rico']]],
|
||||
['Q', [['Qatar']]],
|
||||
['R', [['Romania'],
|
||||
['Russian Federation'],
|
||||
['Rwanda'],
|
||||
['R\u00e9union']]],
|
||||
['S', [['Saint Barth\u00e9lemy'],
|
||||
['Saint Helena'],
|
||||
['Saint Kitts and Nevis'],
|
||||
['Saint Lucia'],
|
||||
['Saint Martin (French part)'],
|
||||
['Saint Pierre and Miquelon'],
|
||||
['Saint Vincent and the Grenadines'],
|
||||
['Samoa'],
|
||||
['San Marino'],
|
||||
['Sao Tome and Principe'],
|
||||
['Saudi Arabia'],
|
||||
['Senegal'],
|
||||
['Serbia'],
|
||||
['Seychelles'],
|
||||
['Sierra Leone'],
|
||||
['Singapore'],
|
||||
['Slovakia'],
|
||||
['Slovenia'],
|
||||
['Solomon Islands'],
|
||||
['Somalia'],
|
||||
['South Africa'],
|
||||
['South Georgia and the South Sandwich Islands'],
|
||||
['Spain'],
|
||||
['Sri Lanka'],
|
||||
['Sudan'],
|
||||
['Suriname'],
|
||||
['Svalbard and Jan Mayen'],
|
||||
['Swaziland'],
|
||||
['Sweden'],
|
||||
['Switzerland'],
|
||||
['Syrian Arab Republic']]],
|
||||
['T', [['Taiwan, Province of China'],
|
||||
['Tajikistan'],
|
||||
['Tanzania, United Republic of'],
|
||||
['Thailand'],
|
||||
['Timor-Leste'],
|
||||
['Togo'],
|
||||
['Tokelau'],
|
||||
['Tonga'],
|
||||
['Trinidad and Tobago'],
|
||||
['Tunisia'],
|
||||
['Turkey'],
|
||||
['Turkmenistan'],
|
||||
['Turks and Caicos Islands'],
|
||||
['Tuvalu']]],
|
||||
['U', [['Uganda'],
|
||||
['Ukraine'],
|
||||
['United Arab Emirates'],
|
||||
['United Kingdom'],
|
||||
['United States'],
|
||||
['United States Minor Outlying Islands'],
|
||||
['Uruguay'],
|
||||
['Uzbekistan']]],
|
||||
['V', [['Vanuatu'],
|
||||
['Venezuela'],
|
||||
['Viet Nam'],
|
||||
['Virgin Islands, British'],
|
||||
['Virgin Islands, U.S.']]],
|
||||
['W', [['Wallis and Futuna'],
|
||||
['Western Sahara']]],
|
||||
['Y', [['Yemen']]],
|
||||
['Z', [['Zambia'],
|
||||
['Zimbabwe']]],
|
||||
['\u00c5', [['\u00c5land Islands']]]]]
|
||||
307
float-no-zero/closure-library/closure/goog/demos/xpc/xpcdemo.js
Normal file
307
float-no-zero/closure-library/closure/goog/demos/xpc/xpcdemo.js
Normal file
@@ -0,0 +1,307 @@
|
||||
// Copyright 2007 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 Contains application code for the XPC demo.
|
||||
* This script is used in both the container page and the iframe.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.net.xpc.CfgFields');
|
||||
goog.require('goog.net.xpc.CrossPageChannel');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Namespace for the demo. We don't use goog.provide here because it's not a
|
||||
* real module (cannot be required).
|
||||
*/
|
||||
var xpcdemo = {};
|
||||
|
||||
|
||||
/**
|
||||
* Global function to kick off initialization in the containing document.
|
||||
*/
|
||||
goog.global.initOuter = function() {
|
||||
goog.events.listen(window, 'load', function() { xpcdemo.initOuter(); });
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Global function to kick off initialization in the iframe.
|
||||
*/
|
||||
goog.global.initInner = function() {
|
||||
goog.events.listen(window, 'load', function() { xpcdemo.initInner(); });
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes XPC in the containing page.
|
||||
*/
|
||||
xpcdemo.initOuter = function() {
|
||||
// Build the configuration object.
|
||||
var cfg = {};
|
||||
|
||||
var ownUri = new goog.Uri(window.location.href);
|
||||
var relayUri = ownUri.resolve(new goog.Uri('relay.html'));
|
||||
var pollUri = ownUri.resolve(new goog.Uri('blank.html'));
|
||||
|
||||
// Determine the peer domain. Uses the value of the URI-parameter
|
||||
// 'peerdomain'. If that parameter is not present, it falls back to
|
||||
// the own domain so that the demo will work out of the box (but
|
||||
// communication will of course not cross domain-boundaries). For
|
||||
// real cross-domain communication, the easiest way is to point two
|
||||
// different host-names to the same webserver and then hit the
|
||||
// following URI:
|
||||
// http://host1.com/path/to/closure/demos/xpc/index.html?peerdomain=host2.com
|
||||
var peerDomain = ownUri.getParameterValue('peerdomain') || ownUri.getDomain();
|
||||
|
||||
cfg[goog.net.xpc.CfgFields.LOCAL_RELAY_URI] = relayUri.toString();
|
||||
cfg[goog.net.xpc.CfgFields.PEER_RELAY_URI] =
|
||||
relayUri.setDomain(peerDomain).toString();
|
||||
|
||||
cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = pollUri.toString();
|
||||
cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] =
|
||||
pollUri.setDomain(peerDomain).toString();
|
||||
|
||||
|
||||
// Force transport to be used if tp-parameter is set.
|
||||
var tp = ownUri.getParameterValue('tp');
|
||||
if (tp) {
|
||||
cfg[goog.net.xpc.CfgFields.TRANSPORT] = parseInt(tp, 10);
|
||||
}
|
||||
|
||||
|
||||
// Construct the URI of the peer page.
|
||||
|
||||
var peerUri = ownUri.resolve(
|
||||
new goog.Uri('inner.html')).setDomain(peerDomain);
|
||||
// Passthrough of verbose and compiled flags.
|
||||
if (goog.isDef(ownUri.getParameterValue('verbose'))) {
|
||||
peerUri.setParameterValue('verbose', '');
|
||||
}
|
||||
if (goog.isDef(ownUri.getParameterValue('compiled'))) {
|
||||
peerUri.setParameterValue('compiled', '');
|
||||
}
|
||||
|
||||
cfg[goog.net.xpc.CfgFields.PEER_URI] = peerUri;
|
||||
|
||||
// Instantiate the channel.
|
||||
xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg);
|
||||
|
||||
// Create the peer iframe.
|
||||
xpcdemo.peerIframe = xpcdemo.channel.createPeerIframe(
|
||||
goog.dom.getElement('iframeContainer'));
|
||||
|
||||
xpcdemo.initCommon_();
|
||||
|
||||
goog.dom.getElement('inactive').style.display = 'none';
|
||||
goog.dom.getElement('active').style.display = '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialization in the iframe.
|
||||
*/
|
||||
xpcdemo.initInner = function() {
|
||||
// Get the channel configuration passed by the containing document.
|
||||
var cfg = goog.json.parse(
|
||||
(new goog.Uri(window.location.href)).getParameterValue('xpc'));
|
||||
|
||||
xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg);
|
||||
|
||||
xpcdemo.initCommon_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the demo.
|
||||
* Registers service-handlers and connects the channel.
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.initCommon_ = function() {
|
||||
var xpcLogger = goog.log.getLogger('goog.net.xpc');
|
||||
goog.log.addHandler(xpcLogger, function(logRecord) {
|
||||
xpcdemo.log('[XPC] ' + logRecord.getMessage());
|
||||
});
|
||||
xpcLogger.setLevel(window.location.href.match(/verbose/) ?
|
||||
goog.log.Level.ALL : goog.log.Level.INFO);
|
||||
|
||||
// Register services.
|
||||
xpcdemo.channel.registerService('log', xpcdemo.log);
|
||||
xpcdemo.channel.registerService('ping', xpcdemo.pingHandler_);
|
||||
xpcdemo.channel.registerService('events', xpcdemo.eventsMsgHandler_);
|
||||
|
||||
// Connect the channel.
|
||||
xpcdemo.channel.connect(function() {
|
||||
xpcdemo.channel.send('log', 'Hi from ' + window.location.host);
|
||||
goog.events.listen(goog.dom.getElement('clickfwd'),
|
||||
'click', xpcdemo.mouseEventHandler_);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Kills the peer iframe and the disposes the channel.
|
||||
*/
|
||||
xpcdemo.teardown = function() {
|
||||
goog.events.unlisten(goog.dom.getElement('clickfwd'),
|
||||
goog.events.EventType.CLICK, xpcdemo.mouseEventHandler_);
|
||||
|
||||
xpcdemo.channel.dispose();
|
||||
delete xpcdemo.channel;
|
||||
|
||||
goog.dom.removeNode(xpcdemo.peerIframe);
|
||||
xpcdemo.peerIframe = null;
|
||||
|
||||
goog.dom.getElement('inactive').style.display = '';
|
||||
goog.dom.getElement('active').style.display = 'none';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logging function. Inserts log-message into element with it id 'console'.
|
||||
* @param {string} msgString The log-message.
|
||||
*/
|
||||
xpcdemo.log = function(msgString) {
|
||||
xpcdemo.consoleElm || (xpcdemo.consoleElm = goog.dom.getElement('console'));
|
||||
var msgElm = goog.dom.createDom('div');
|
||||
msgElm.innerHTML = msgString;
|
||||
xpcdemo.consoleElm.insertBefore(msgElm, xpcdemo.consoleElm.firstChild);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends a ping request to the peer.
|
||||
*/
|
||||
xpcdemo.ping = function() {
|
||||
// send current time
|
||||
xpcdemo.channel.send('ping', goog.now() + '');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The handler function for incoming pings (messages sent to the service
|
||||
* called 'ping');
|
||||
* @param {string} payload The message payload.
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.pingHandler_ = function(payload) {
|
||||
// is the incoming message a response to a ping we sent?
|
||||
if (payload.charAt(0) == '#') {
|
||||
// calculate roundtrip time and log
|
||||
var dt = goog.now() - parseInt(payload.substring(1), 10);
|
||||
xpcdemo.log('roundtrip: ' + dt + 'ms');
|
||||
} else {
|
||||
// incoming message is a ping initiated from peer
|
||||
// -> prepend with '#' and send back
|
||||
xpcdemo.channel.send('ping', '#' + payload);
|
||||
xpcdemo.log('ping reply sent');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Counter for mousemove events.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.mmCount_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Holds timestamp when the last mousemove rate has been logged.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.mmLastRateOutput_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Start mousemove event forwarding. Registers a listener on the document which
|
||||
* sends them over the channel.
|
||||
*/
|
||||
xpcdemo.startMousemoveForwarding = function() {
|
||||
goog.events.listen(document, goog.events.EventType.MOUSEMOVE,
|
||||
xpcdemo.mouseEventHandler_);
|
||||
xpcdemo.mmLastRateOutput_ = goog.now();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stop mousemove event forwarding.
|
||||
*/
|
||||
xpcdemo.stopMousemoveForwarding = function() {
|
||||
goog.events.unlisten(document, goog.events.EventType.MOUSEMOVE,
|
||||
xpcdemo.mouseEventHandler_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function to be used as handler for mouse-events.
|
||||
* @param {goog.events.BrowserEvent} e The mouse event.
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.mouseEventHandler_ = function(e) {
|
||||
xpcdemo.channel.send('events',
|
||||
[e.type, e.clientX, e.clientY, goog.now()].join(','));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the 'events' service.
|
||||
* @param {string} payload The string returned from the xpcdemo.
|
||||
* @private
|
||||
*/
|
||||
xpcdemo.eventsMsgHandler_ = function(payload) {
|
||||
var now = goog.now();
|
||||
var args = payload.split(',');
|
||||
var type = args[0];
|
||||
var pageX = args[1];
|
||||
var pageY = args[2];
|
||||
var time = parseInt(args[3], 10);
|
||||
|
||||
var msg = type + ': (' + pageX + ',' + pageY + '), latency: ' + (now - time);
|
||||
xpcdemo.log(msg);
|
||||
|
||||
if (type == goog.events.EventType.MOUSEMOVE) {
|
||||
xpcdemo.mmCount_++;
|
||||
var dt = now - xpcdemo.mmLastRateOutput_;
|
||||
if (dt > 1000) {
|
||||
msg = 'RATE (mousemove/s): ' + (1000 * xpcdemo.mmCount_ / dt);
|
||||
xpcdemo.log(msg);
|
||||
xpcdemo.mmLastRateOutput_ = now;
|
||||
xpcdemo.mmCount_ = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send multiple messages.
|
||||
* @param {number} n The number of messages to send.
|
||||
*/
|
||||
xpcdemo.sendN = function(n) {
|
||||
xpcdemo.count_ || (xpcdemo.count_ = 1);
|
||||
|
||||
for (var i = 0; i < n; i++) {
|
||||
xpcdemo.channel.send('log', '' + xpcdemo.count_++);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,294 @@
|
||||
// Copyright 2005 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 Implements the disposable interface. The dispose method is used
|
||||
* to clean up references and resources.
|
||||
* @author arv@google.com (Erik Arvidsson)
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.Disposable');
|
||||
goog.provide('goog.dispose');
|
||||
|
||||
goog.require('goog.disposable.IDisposable');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class that provides the basic implementation for disposable objects. If your
|
||||
* class holds one or more references to COM objects, DOM nodes, or other
|
||||
* disposable objects, it should extend this class or implement the disposable
|
||||
* interface (defined in goog.disposable.IDisposable).
|
||||
* @constructor
|
||||
* @implements {goog.disposable.IDisposable}
|
||||
*/
|
||||
goog.Disposable = function() {
|
||||
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
|
||||
if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {
|
||||
this.creationStack = new Error().stack;
|
||||
}
|
||||
goog.Disposable.instances_[goog.getUid(this)] = this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number} Different monitoring modes for Disposable.
|
||||
*/
|
||||
goog.Disposable.MonitoringMode = {
|
||||
/**
|
||||
* No monitoring.
|
||||
*/
|
||||
OFF: 0,
|
||||
/**
|
||||
* Creating and disposing the goog.Disposable instances is monitored. All
|
||||
* disposable objects need to call the {@code goog.Disposable} base
|
||||
* constructor. The PERMANENT mode must bet switched on before creating any
|
||||
* goog.Disposable instances.
|
||||
*/
|
||||
PERMANENT: 1,
|
||||
/**
|
||||
* INTERACTIVE mode can be switched on and off on the fly without producing
|
||||
* errors. It also doesn't warn if the disposable objects don't call the
|
||||
* {@code goog.Disposable} base constructor.
|
||||
*/
|
||||
INTERACTIVE: 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} The monitoring mode of the goog.Disposable
|
||||
* instances. Default is OFF. Switching on the monitoring is only
|
||||
* recommended for debugging because it has a significant impact on
|
||||
* performance and memory usage. If switched off, the monitoring code
|
||||
* compiles down to 0 bytes.
|
||||
*/
|
||||
goog.define('goog.Disposable.MONITORING_MODE', 0);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to attach creation stack to each created disposable
|
||||
* instance; This is only relevant for when MonitoringMode != OFF.
|
||||
*/
|
||||
goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);
|
||||
|
||||
|
||||
/**
|
||||
* Maps the unique ID of every undisposed {@code goog.Disposable} object to
|
||||
* the object itself.
|
||||
* @type {!Object.<number, !goog.Disposable>}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.instances_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!goog.Disposable>} All {@code goog.Disposable} objects that
|
||||
* haven't been disposed of.
|
||||
*/
|
||||
goog.Disposable.getUndisposedObjects = function() {
|
||||
var ret = [];
|
||||
for (var id in goog.Disposable.instances_) {
|
||||
if (goog.Disposable.instances_.hasOwnProperty(id)) {
|
||||
ret.push(goog.Disposable.instances_[Number(id)]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the registry of undisposed objects but doesn't dispose of them.
|
||||
*/
|
||||
goog.Disposable.clearUndisposedObjects = function() {
|
||||
goog.Disposable.instances_ = {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the object has been disposed of.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.prototype.disposed_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks to invoke when this object is disposed.
|
||||
* @type {Array.<!Function>}
|
||||
* @private
|
||||
*/
|
||||
goog.Disposable.prototype.onDisposeCallbacks_;
|
||||
|
||||
|
||||
/**
|
||||
* If monitoring the goog.Disposable instances is enabled, stores the creation
|
||||
* stack trace of the Disposable instance.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.Disposable.prototype.creationStack;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
* @override
|
||||
*/
|
||||
goog.Disposable.prototype.isDisposed = function() {
|
||||
return this.disposed_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
* @deprecated Use {@link #isDisposed} instead.
|
||||
*/
|
||||
goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the object. If the object hasn't already been disposed of, calls
|
||||
* {@link #disposeInternal}. Classes that extend {@code goog.Disposable} should
|
||||
* override {@link #disposeInternal} in order to delete references to COM
|
||||
* objects, DOM nodes, and other disposable objects. Reentrant.
|
||||
*
|
||||
* @return {void} Nothing.
|
||||
* @override
|
||||
*/
|
||||
goog.Disposable.prototype.dispose = function() {
|
||||
if (!this.disposed_) {
|
||||
// Set disposed_ to true first, in case during the chain of disposal this
|
||||
// gets disposed recursively.
|
||||
this.disposed_ = true;
|
||||
this.disposeInternal();
|
||||
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
|
||||
var uid = goog.getUid(this);
|
||||
if (goog.Disposable.MONITORING_MODE ==
|
||||
goog.Disposable.MonitoringMode.PERMANENT &&
|
||||
!goog.Disposable.instances_.hasOwnProperty(uid)) {
|
||||
throw Error(this + ' did not call the goog.Disposable base ' +
|
||||
'constructor or was disposed of after a clearUndisposedObjects ' +
|
||||
'call');
|
||||
}
|
||||
delete goog.Disposable.instances_[uid];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Associates a disposable object with this object so that they will be disposed
|
||||
* together.
|
||||
* @param {goog.disposable.IDisposable} disposable that will be disposed when
|
||||
* this object is disposed.
|
||||
*/
|
||||
goog.Disposable.prototype.registerDisposable = function(disposable) {
|
||||
this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Invokes a callback function when this object is disposed. Callbacks are
|
||||
* invoked in the order in which they were added.
|
||||
* @param {function(this:T):?} callback The callback function.
|
||||
* @param {T=} opt_scope An optional scope to call the callback in.
|
||||
* @template T
|
||||
*/
|
||||
goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {
|
||||
if (!this.onDisposeCallbacks_) {
|
||||
this.onDisposeCallbacks_ = [];
|
||||
}
|
||||
this.onDisposeCallbacks_.push(goog.bind(callback, opt_scope));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes or nulls out any references to COM objects, DOM nodes, or other
|
||||
* disposable objects. Classes that extend {@code goog.Disposable} should
|
||||
* override this method.
|
||||
* Not reentrant. To avoid calling it twice, it must only be called from the
|
||||
* subclass' {@code disposeInternal} method. Everywhere else the public
|
||||
* {@code dispose} method must be used.
|
||||
* For example:
|
||||
* <pre>
|
||||
* mypackage.MyClass = function() {
|
||||
* goog.base(this);
|
||||
* // Constructor logic specific to MyClass.
|
||||
* ...
|
||||
* };
|
||||
* goog.inherits(mypackage.MyClass, goog.Disposable);
|
||||
*
|
||||
* mypackage.MyClass.prototype.disposeInternal = function() {
|
||||
* // Dispose logic specific to MyClass.
|
||||
* ...
|
||||
* // Call superclass's disposeInternal at the end of the subclass's, like
|
||||
* // in C++, to avoid hard-to-catch issues.
|
||||
* goog.base(this, 'disposeInternal');
|
||||
* };
|
||||
* </pre>
|
||||
* @protected
|
||||
*/
|
||||
goog.Disposable.prototype.disposeInternal = function() {
|
||||
if (this.onDisposeCallbacks_) {
|
||||
while (this.onDisposeCallbacks_.length) {
|
||||
this.onDisposeCallbacks_.shift()();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns True if we can verify the object is disposed.
|
||||
* Calls {@code isDisposed} on the argument if it supports it. If obj
|
||||
* is not an object with an isDisposed() method, return false.
|
||||
* @param {*} obj The object to investigate.
|
||||
* @return {boolean} True if we can verify the object is disposed.
|
||||
*/
|
||||
goog.Disposable.isDisposed = function(obj) {
|
||||
if (obj && typeof obj.isDisposed == 'function') {
|
||||
return obj.isDisposed();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@code dispose} on the argument if it supports it. If obj is not an
|
||||
* object with a dispose() method, this is a no-op.
|
||||
* @param {*} obj The object to dispose of.
|
||||
*/
|
||||
goog.dispose = function(obj) {
|
||||
if (obj && typeof obj.dispose == 'function') {
|
||||
obj.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@code dispose} on each member of the list that supports it. (If the
|
||||
* member is an ArrayLike, then {@code goog.disposeAll()} will be called
|
||||
* recursively on each of its members.) If the member is not an object with a
|
||||
* {@code dispose()} method, then it is ignored.
|
||||
* @param {...*} var_args The list.
|
||||
*/
|
||||
goog.disposeAll = function(var_args) {
|
||||
for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
var disposable = arguments[i];
|
||||
if (goog.isArrayLike(disposable)) {
|
||||
goog.disposeAll.apply(null, disposable);
|
||||
} else {
|
||||
goog.dispose(disposable);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2011 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 Definition of the disposable interface. A disposable object
|
||||
* has a dispose method to to clean up references and resources.
|
||||
* @author nnaze@google.com (Nathan Naze)
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.disposable.IDisposable');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a disposable object. If a instance requires cleanup
|
||||
* (references COM objects, DOM notes, or other disposable objects), it should
|
||||
* implement this interface (it may subclass goog.Disposable).
|
||||
* @interface
|
||||
*/
|
||||
goog.disposable.IDisposable = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Disposes of the object and its resources.
|
||||
* @return {void} Nothing.
|
||||
*/
|
||||
goog.disposable.IDisposable.prototype.dispose;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the object has been disposed of.
|
||||
*/
|
||||
goog.disposable.IDisposable.prototype.isDisposed;
|
||||
169
float-no-zero/closure-library/closure/goog/dom/a11y.js
Normal file
169
float-no-zero/closure-library/closure/goog/dom/a11y.js
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright 2007 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 Utilities for adding, removing and setting ARIA roles
|
||||
* as defined by W3C ARIA Working Draft:
|
||||
* http://www.w3.org/TR/2010/WD-wai-aria-20100916/
|
||||
* All modern browsers have some form of ARIA support, so no browser checks are
|
||||
* performed when adding ARIA to components.
|
||||
*
|
||||
*
|
||||
* @deprecated Use {@link goog.a11y.aria} instead.
|
||||
* This file will be removed on 1 Apr 2013.
|
||||
*
|
||||
*/
|
||||
goog.provide('goog.dom.a11y');
|
||||
goog.provide('goog.dom.a11y.Announcer');
|
||||
goog.provide('goog.dom.a11y.LivePriority');
|
||||
goog.provide('goog.dom.a11y.Role');
|
||||
goog.provide('goog.dom.a11y.State');
|
||||
|
||||
goog.require('goog.a11y.aria');
|
||||
goog.require('goog.a11y.aria.Announcer');
|
||||
goog.require('goog.a11y.aria.LivePriority');
|
||||
goog.require('goog.a11y.aria.Role');
|
||||
goog.require('goog.a11y.aria.State');
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of ARIA states and properties.
|
||||
* @enum {string}
|
||||
* @deprecated Use {@link goog.a11y.aria.State} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.State = goog.a11y.aria.State;
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of ARIA roles.
|
||||
* @enum {string}
|
||||
* @deprecated Use {@link goog.a11y.aria.Role} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.Role = goog.a11y.aria.Role;
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of ARIA state values for live regions.
|
||||
*
|
||||
* See http://www.w3.org/TR/wai-aria/states_and_properties#aria-live
|
||||
* for more information.
|
||||
* @enum {string}
|
||||
* @deprecated Use {@link goog.a11y.aria.LivePriority} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.LivePriority = goog.a11y.aria.LivePriority;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the role of an element.
|
||||
* @param {Element} element DOM node to set role of.
|
||||
* @param {goog.dom.a11y.Role|string} roleName role name(s).
|
||||
* @deprecated Use {@link goog.a11y.aria.setRole} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.setRole = function(element, roleName) {
|
||||
goog.a11y.aria.setRole(
|
||||
/** @type {!Element} */ (element),
|
||||
/** @type {!goog.dom.a11y.Role} */ (roleName));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets role of an element.
|
||||
* @param {Element} element DOM node to get role of.
|
||||
* @return {?(goog.dom.a11y.Role|string)} rolename.
|
||||
* @deprecated Use {@link goog.a11y.aria.getRole} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.getRole = function(element) {
|
||||
return /** @type {?(goog.dom.a11y.Role|string)} */ (
|
||||
goog.a11y.aria.getRole(/** @type {!Element} */ (element)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the state or property of an element.
|
||||
* @param {Element} element DOM node where we set state.
|
||||
* @param {goog.dom.a11y.State|string} state State attribute being set.
|
||||
* Automatically adds prefix 'aria-' to the state name.
|
||||
* @param {boolean|number|string} value Value for the
|
||||
* state attribute.
|
||||
* @deprecated Use {@link goog.a11y.aria.setState} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.setState = function(element, state, value) {
|
||||
goog.a11y.aria.setState(
|
||||
/** @type {!Element} */ (element),
|
||||
/** @type {!goog.dom.a11y.State} */ (state),
|
||||
/** @type {boolean|number|string} */ (value));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets value of specified state or property.
|
||||
* @param {Element} element DOM node to get state from.
|
||||
* @param {goog.dom.a11y.State|string} stateName State name.
|
||||
* @return {string} Value of the state attribute.
|
||||
* @deprecated Use {@link goog.a11y.aria.getState} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.getState = function(element, stateName) {
|
||||
return goog.a11y.aria.getState(
|
||||
/** @type {!Element} */ (element),
|
||||
/** @type {!goog.dom.a11y.State} */ (stateName));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the activedescendant of the given element.
|
||||
* @param {Element} element DOM node to get activedescendant from.
|
||||
* @return {Element} DOM node of the activedescendant.
|
||||
* @deprecated Use {@link goog.a11y.aria.getActiveDescendant} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.getActiveDescendant = function(element) {
|
||||
return goog.a11y.aria.getActiveDescendant(
|
||||
/** @type {!Element} */ (element));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the activedescendant value for an element.
|
||||
* @param {Element} element DOM node to set activedescendant to.
|
||||
* @param {Element} activeElement DOM node being set as activedescendant.
|
||||
* @deprecated Use {@link goog.a11y.aria.setActiveDescendant} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.setActiveDescendant = function(element, activeElement) {
|
||||
goog.a11y.aria.setActiveDescendant(
|
||||
/** @type {!Element} */ (element),
|
||||
activeElement);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class that allows messages to be spoken by assistive technologies that the
|
||||
* user may have active.
|
||||
*
|
||||
* @param {goog.dom.DomHelper} domHelper DOM helper.
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @deprecated Use {@link goog.a11y.aria.Announcer} instead.
|
||||
* This alias will be removed on 1 Apr 2013.
|
||||
*/
|
||||
goog.dom.a11y.Announcer = goog.a11y.aria.Announcer;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// 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 Utilities for working with ranges comprised of multiple
|
||||
* sub-ranges.
|
||||
*
|
||||
* @author robbyw@google.com (Robby Walker)
|
||||
* @author jparent@google.com (Julie Parent)
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.dom.AbstractMultiRange');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.AbstractRange');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new multi range with no properties. Do not use this
|
||||
* constructor: use one of the goog.dom.Range.createFrom* methods instead.
|
||||
* @constructor
|
||||
* @extends {goog.dom.AbstractRange}
|
||||
*/
|
||||
goog.dom.AbstractMultiRange = function() {
|
||||
};
|
||||
goog.inherits(goog.dom.AbstractMultiRange, goog.dom.AbstractRange);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.dom.AbstractMultiRange.prototype.containsRange = function(
|
||||
otherRange, opt_allowPartial) {
|
||||
// TODO(user): This will incorrectly return false if two (or more) adjacent
|
||||
// elements are both in the control range, and are also in the text range
|
||||
// being compared to.
|
||||
var ranges = this.getTextRanges();
|
||||
var otherRanges = otherRange.getTextRanges();
|
||||
|
||||
var fn = opt_allowPartial ? goog.array.some : goog.array.every;
|
||||
return fn(otherRanges, function(otherRange) {
|
||||
return goog.array.some(ranges, function(range) {
|
||||
return range.containsRange(otherRange, opt_allowPartial);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.dom.AbstractMultiRange.prototype.insertNode = function(node, before) {
|
||||
if (before) {
|
||||
goog.dom.insertSiblingBefore(node, this.getStartNode());
|
||||
} else {
|
||||
goog.dom.insertSiblingAfter(node, this.getEndNode());
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.dom.AbstractMultiRange.prototype.surroundWithNodes = function(startNode,
|
||||
endNode) {
|
||||
this.insertNode(startNode, true);
|
||||
this.insertNode(endNode, false);
|
||||
};
|
||||
528
float-no-zero/closure-library/closure/goog/dom/abstractrange.js
Normal file
528
float-no-zero/closure-library/closure/goog/dom/abstractrange.js
Normal file
@@ -0,0 +1,528 @@
|
||||
// Copyright 2007 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 Interface definitions for working with ranges
|
||||
* in HTML documents.
|
||||
*
|
||||
* @author robbyw@google.com (Robby Walker)
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.dom.AbstractRange');
|
||||
goog.provide('goog.dom.RangeIterator');
|
||||
goog.provide('goog.dom.RangeType');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.dom.SavedCaretRange');
|
||||
goog.require('goog.dom.TagIterator');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Types of ranges.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.dom.RangeType = {
|
||||
TEXT: 'text',
|
||||
CONTROL: 'control',
|
||||
MULTI: 'mutli'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new selection with no properties. Do not use this constructor -
|
||||
* use one of the goog.dom.Range.from* methods instead.
|
||||
* @constructor
|
||||
*/
|
||||
goog.dom.AbstractRange = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the browser native selection object from the given window.
|
||||
* @param {Window} win The window to get the selection object from.
|
||||
* @return {Object} The browser native selection object, or null if it could
|
||||
* not be retrieved.
|
||||
*/
|
||||
goog.dom.AbstractRange.getBrowserSelectionForWindow = function(win) {
|
||||
if (win.getSelection) {
|
||||
// W3C
|
||||
return win.getSelection();
|
||||
} else {
|
||||
// IE
|
||||
var doc = win.document;
|
||||
var sel = doc.selection;
|
||||
if (sel) {
|
||||
// IE has a bug where it sometimes returns a selection from the wrong
|
||||
// document. Catching these cases now helps us avoid problems later.
|
||||
try {
|
||||
var range = sel.createRange();
|
||||
// Only TextRanges have a parentElement method.
|
||||
if (range.parentElement) {
|
||||
if (range.parentElement().document != doc) {
|
||||
return null;
|
||||
}
|
||||
} else if (!range.length || range.item(0).document != doc) {
|
||||
// For ControlRanges, check that the range has items, and that
|
||||
// the first item in the range is in the correct document.
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
// If the selection is in the wrong document, and the wrong document is
|
||||
// in a different domain, IE will throw an exception.
|
||||
return null;
|
||||
}
|
||||
// TODO(user|robbyw) Sometimes IE 6 returns a selection instance
|
||||
// when there is no selection. This object has a 'type' property equals
|
||||
// to 'None' and a typeDetail property bound to undefined. Ideally this
|
||||
// function should not return this instance.
|
||||
return sel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests if the given Object is a controlRange.
|
||||
* @param {Object} range The range object to test.
|
||||
* @return {boolean} Whether the given Object is a controlRange.
|
||||
*/
|
||||
goog.dom.AbstractRange.isNativeControlRange = function(range) {
|
||||
// For now, tests for presence of a control range function.
|
||||
return !!range && !!range.addElement;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.dom.AbstractRange} A clone of this range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.clone = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.dom.RangeType} The type of range represented by this object.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getType = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Range|TextRange} The native browser range object.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getBrowserRangeObject = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the native browser range object, overwriting any state this range was
|
||||
* storing.
|
||||
* @param {Range|TextRange} nativeRange The native browser range object.
|
||||
* @return {boolean} Whether the given range was accepted. If not, the caller
|
||||
* will need to call goog.dom.Range.createFromBrowserRange to create a new
|
||||
* range object.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.setBrowserRangeObject = function(nativeRange) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The number of text ranges in this range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getTextRangeCount = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Get the i-th text range in this range. The behavior is undefined if
|
||||
* i >= getTextRangeCount or i < 0.
|
||||
* @param {number} i The range number to retrieve.
|
||||
* @return {goog.dom.TextRange} The i-th text range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getTextRange = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Gets an array of all text ranges this range is comprised of. For non-multi
|
||||
* ranges, returns a single element array containing this.
|
||||
* @return {Array.<goog.dom.TextRange>} Array of text ranges.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getTextRanges = function() {
|
||||
var output = [];
|
||||
for (var i = 0, len = this.getTextRangeCount(); i < len; i++) {
|
||||
output.push(this.getTextRange(i));
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The deepest node that contains the entire range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getContainer = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the deepest element in the tree that contains the entire range.
|
||||
* @return {Element} The deepest element that contains the entire range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getContainerElement = function() {
|
||||
var node = this.getContainer();
|
||||
return /** @type {Element} */ (
|
||||
node.nodeType == goog.dom.NodeType.ELEMENT ? node : node.parentNode);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The element or text node the range starts in. For text
|
||||
* ranges, the range comprises all text between the start and end position.
|
||||
* For other types of range, start and end give bounds of the range but
|
||||
* do not imply all nodes in those bounds are selected.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getStartNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The offset into the node the range starts in. For text
|
||||
* nodes, this is an offset into the node value. For elements, this is
|
||||
* an offset into the childNodes array.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getStartOffset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.math.Coordinate} The coordinate of the selection start node
|
||||
* and offset.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getStartPosition = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The element or text node the range ends in.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getEndNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The offset into the node the range ends in. For text
|
||||
* nodes, this is an offset into the node value. For elements, this is
|
||||
* an offset into the childNodes array.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getEndOffset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.math.Coordinate} The coordinate of the selection end
|
||||
* node and offset.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getEndPosition = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The element or text node the range is anchored at.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getAnchorNode = function() {
|
||||
return this.isReversed() ? this.getEndNode() : this.getStartNode();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The offset into the node the range is anchored at. For
|
||||
* text nodes, this is an offset into the node value. For elements, this
|
||||
* is an offset into the childNodes array.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getAnchorOffset = function() {
|
||||
return this.isReversed() ? this.getEndOffset() : this.getStartOffset();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The element or text node the range is focused at - i.e. where
|
||||
* the cursor is.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getFocusNode = function() {
|
||||
return this.isReversed() ? this.getStartNode() : this.getEndNode();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The offset into the node the range is focused at - i.e.
|
||||
* where the cursor is. For text nodes, this is an offset into the node
|
||||
* value. For elements, this is an offset into the childNodes array.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getFocusOffset = function() {
|
||||
return this.isReversed() ? this.getStartOffset() : this.getEndOffset();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the selection is reversed.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.isReversed = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Document} The document this selection is a part of.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getDocument = function() {
|
||||
// Using start node in IE was crashing the browser in some cases so use
|
||||
// getContainer for that browser. It's also faster for IE, but still slower
|
||||
// than start node for other browsers so we continue to use getStartNode when
|
||||
// it is not problematic. See bug 1687309.
|
||||
return goog.dom.getOwnerDocument(goog.userAgent.IE ?
|
||||
this.getContainer() : this.getStartNode());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Window} The window this selection is a part of.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getWindow = function() {
|
||||
return goog.dom.getWindow(this.getDocument());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests if this range contains the given range.
|
||||
* @param {goog.dom.AbstractRange} range The range to test.
|
||||
* @param {boolean=} opt_allowPartial If true, the range can be partially
|
||||
* contained in the selection, otherwise the range must be entirely
|
||||
* contained.
|
||||
* @return {boolean} Whether this range contains the given range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.containsRange = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Tests if this range contains the given node.
|
||||
* @param {Node} node The node to test for.
|
||||
* @param {boolean=} opt_allowPartial If not set or false, the node must be
|
||||
* entirely contained in the selection for this function to return true.
|
||||
* @return {boolean} Whether this range contains the given node.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.containsNode = function(node,
|
||||
opt_allowPartial) {
|
||||
return this.containsRange(goog.dom.Range.createFromNodeContents(node),
|
||||
opt_allowPartial);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether this range is valid (i.e. whether its endpoints are still in
|
||||
* the document). A range becomes invalid when, after this object was created,
|
||||
* either one or both of its endpoints are removed from the document. Use of
|
||||
* an invalid range can lead to runtime errors, particularly in IE.
|
||||
* @return {boolean} Whether the range is valid.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.isRangeInDocument = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the range is collapsed.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The text content of the range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getText = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the HTML fragment this range selects. This is slow on all browsers.
|
||||
* The HTML fragment may not be valid HTML, for instance if the user selects
|
||||
* from a to b inclusively in the following html:
|
||||
*
|
||||
* >div<a>/div<b
|
||||
*
|
||||
* This method will return
|
||||
*
|
||||
* a</div>b
|
||||
*
|
||||
* If you need valid HTML, use {@link #getValidHtml} instead.
|
||||
*
|
||||
* @return {string} HTML fragment of the range, does not include context
|
||||
* containing elements.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getHtmlFragment = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns valid HTML for this range. This is fast on IE, and semi-fast on
|
||||
* other browsers.
|
||||
* @return {string} Valid HTML of the range, including context containing
|
||||
* elements.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getValidHtml = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns pastable HTML for this range. This guarantees that any child items
|
||||
* that must have specific ancestors will have them, for instance all TDs will
|
||||
* be contained in a TR in a TBODY in a TABLE and all LIs will be contained in
|
||||
* a UL or OL as appropriate. This is semi-fast on all browsers.
|
||||
* @return {string} Pastable HTML of the range, including context containing
|
||||
* elements.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.getPastableHtml = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a RangeIterator over the contents of the range. Regardless of the
|
||||
* direction of the range, the iterator will move in document order.
|
||||
* @param {boolean=} opt_keys Unused for this iterator.
|
||||
* @return {goog.dom.RangeIterator} An iterator over tags in the range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.__iterator__ = goog.abstractMethod;
|
||||
|
||||
|
||||
// RANGE ACTIONS
|
||||
|
||||
|
||||
/**
|
||||
* Sets this range as the selection in its window.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.select = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Removes the contents of the range from the document.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.removeContents = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Inserts a node before (or after) the range. The range may be disrupted
|
||||
* beyond recovery because of the way this splits nodes.
|
||||
* @param {Node} node The node to insert.
|
||||
* @param {boolean} before True to insert before, false to insert after.
|
||||
* @return {Node} The node added to the document. This may be different
|
||||
* than the node parameter because on IE we have to clone it.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.insertNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the range contents with (possibly a copy of) the given node. The
|
||||
* range may be disrupted beyond recovery because of the way this splits nodes.
|
||||
* @param {Node} node The node to insert.
|
||||
* @return {Node} The node added to the document. This may be different
|
||||
* than the node parameter because on IE we have to clone it.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.replaceContentsWithNode = function(node) {
|
||||
if (!this.isCollapsed()) {
|
||||
this.removeContents();
|
||||
}
|
||||
|
||||
return this.insertNode(node, true);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Surrounds this range with the two given nodes. The range may be disrupted
|
||||
* beyond recovery because of the way this splits nodes.
|
||||
* @param {Element} startNode The node to insert at the start.
|
||||
* @param {Element} endNode The node to insert at the end.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod;
|
||||
|
||||
|
||||
// SAVE/RESTORE
|
||||
|
||||
|
||||
/**
|
||||
* Saves the range so that if the start and end nodes are left alone, it can
|
||||
* be restored.
|
||||
* @return {goog.dom.SavedRange} A range representation that can be restored
|
||||
* as long as the endpoint nodes of the selection are not modified.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.saveUsingDom = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Saves the range using HTML carets. As long as the carets remained in the
|
||||
* HTML, the range can be restored...even when the HTML is copied across
|
||||
* documents.
|
||||
* @return {goog.dom.SavedCaretRange?} A range representation that can be
|
||||
* restored as long as carets are not removed. Returns null if carets
|
||||
* could not be created.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.saveUsingCarets = function() {
|
||||
return (this.getStartNode() && this.getEndNode()) ?
|
||||
new goog.dom.SavedCaretRange(this) : null;
|
||||
};
|
||||
|
||||
|
||||
// RANGE MODIFICATION
|
||||
|
||||
|
||||
/**
|
||||
* Collapses the range to one of its boundary points.
|
||||
* @param {boolean} toAnchor Whether to collapse to the anchor of the range.
|
||||
*/
|
||||
goog.dom.AbstractRange.prototype.collapse = goog.abstractMethod;
|
||||
|
||||
// RANGE ITERATION
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of goog.dom.TagIterator that iterates over a DOM range. It
|
||||
* adds functions to determine the portion of each text node that is selected.
|
||||
* @param {Node} node The node to start traversal at. When null, creates an
|
||||
* empty iterator.
|
||||
* @param {boolean=} opt_reverse Whether to traverse nodes in reverse.
|
||||
* @constructor
|
||||
* @extends {goog.dom.TagIterator}
|
||||
*/
|
||||
goog.dom.RangeIterator = function(node, opt_reverse) {
|
||||
goog.dom.TagIterator.call(this, node, opt_reverse, true);
|
||||
};
|
||||
goog.inherits(goog.dom.RangeIterator, goog.dom.TagIterator);
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The offset into the current node, or -1 if the current node
|
||||
* is not a text node.
|
||||
*/
|
||||
goog.dom.RangeIterator.prototype.getStartTextOffset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The end offset into the current node, or -1 if the current
|
||||
* node is not a text node.
|
||||
*/
|
||||
goog.dom.RangeIterator.prototype.getEndTextOffset = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} node The iterator's start node.
|
||||
*/
|
||||
goog.dom.RangeIterator.prototype.getStartNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {Node} The iterator's end node.
|
||||
*/
|
||||
goog.dom.RangeIterator.prototype.getEndNode = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether a call to next will fail.
|
||||
*/
|
||||
goog.dom.RangeIterator.prototype.isLast = goog.abstractMethod;
|
||||
355
float-no-zero/closure-library/closure/goog/dom/annotate.js
Normal file
355
float-no-zero/closure-library/closure/goog/dom/annotate.js
Normal file
@@ -0,0 +1,355 @@
|
||||
// Copyright 2006 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 Methods for annotating occurrences of query terms in text or
|
||||
* in a DOM tree. Adapted from Gmail code.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.dom.annotate');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@code annotateFn} for each occurrence of a search term in text nodes
|
||||
* under {@code node}. Returns the number of hits.
|
||||
*
|
||||
* @param {Node} node A DOM node.
|
||||
* @param {Array} terms An array of [searchTerm, matchWholeWordOnly] tuples.
|
||||
* The matchWholeWordOnly value is a per-term attribute because some terms
|
||||
* may be CJK, while others are not. (For correctness, matchWholeWordOnly
|
||||
* should always be false for CJK terms.).
|
||||
* @param {Function} annotateFn A function that takes
|
||||
* (1) the number of the term that is "hit",
|
||||
* (2) the HTML string (search term) to be annotated,
|
||||
* and returns the annotated term as an HTML string.
|
||||
* @param {*=} opt_ignoreCase Whether to ignore the case of the query
|
||||
* terms when looking for matches.
|
||||
* @param {Array.<string>=} opt_classesToSkip Nodes with one of these CSS class
|
||||
* names (and its descendants) will be skipped.
|
||||
* @param {number=} opt_maxMs Number of milliseconds after which this function,
|
||||
* if still annotating, should stop and return.
|
||||
*
|
||||
* @return {boolean} Whether any terms were annotated.
|
||||
*/
|
||||
goog.dom.annotate.annotateTerms = function(node, terms, annotateFn,
|
||||
opt_ignoreCase,
|
||||
opt_classesToSkip,
|
||||
opt_maxMs) {
|
||||
if (opt_ignoreCase) {
|
||||
terms = goog.dom.annotate.lowercaseTerms_(terms);
|
||||
}
|
||||
var stopTime = opt_maxMs > 0 ? goog.now() + opt_maxMs : 0;
|
||||
|
||||
return goog.dom.annotate.annotateTermsInNode_(
|
||||
node, terms, annotateFn, opt_ignoreCase, opt_classesToSkip || [],
|
||||
stopTime, 0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The maximum recursion depth allowed. Any DOM nodes deeper than this are
|
||||
* ignored.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.MAX_RECURSION_ = 200;
|
||||
|
||||
|
||||
/**
|
||||
* The node types whose descendants should not be affected by annotation.
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.NODES_TO_SKIP_ = ['SCRIPT', 'STYLE', 'TEXTAREA'];
|
||||
|
||||
|
||||
/**
|
||||
* Recursive helper function.
|
||||
*
|
||||
* @param {Node} node A DOM node.
|
||||
* @param {Array} terms An array of [searchTerm, matchWholeWordOnly] tuples.
|
||||
* The matchWholeWordOnly value is a per-term attribute because some terms
|
||||
* may be CJK, while others are not. (For correctness, matchWholeWordOnly
|
||||
* should always be false for CJK terms.).
|
||||
* @param {Function} annotateFn function(number, string) : string A function
|
||||
* that takes :
|
||||
* (1) the number of the term that is "hit",
|
||||
* (2) the HTML string (search term) to be annotated,
|
||||
* and returns the annotated term as an HTML string.
|
||||
* @param {*} ignoreCase Whether to ignore the case of the query terms
|
||||
* when looking for matches.
|
||||
* @param {Array.<string>} classesToSkip Nodes with one of these CSS class
|
||||
* names will be skipped (as will their descendants).
|
||||
* @param {number} stopTime Deadline for annotation operation (ignored if 0).
|
||||
* @param {number} recursionLevel How deep this recursive call is; pass the
|
||||
* value 0 in the initial call.
|
||||
* @return {boolean} Whether any terms were annotated.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.annotateTermsInNode_ =
|
||||
function(node, terms, annotateFn, ignoreCase, classesToSkip,
|
||||
stopTime, recursionLevel) {
|
||||
if ((stopTime > 0 && goog.now() >= stopTime) ||
|
||||
recursionLevel > goog.dom.annotate.MAX_RECURSION_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var annotated = false;
|
||||
|
||||
if (node.nodeType == goog.dom.NodeType.TEXT) {
|
||||
var html = goog.dom.annotate.helpAnnotateText_(node.nodeValue, terms,
|
||||
annotateFn, ignoreCase);
|
||||
if (html != null) {
|
||||
// Replace the text with the annotated html. First we put the html into
|
||||
// a temporary node, to get its DOM structure. To avoid adding a wrapper
|
||||
// element as a side effect, we'll only actually use the temporary node's
|
||||
// children.
|
||||
var tempNode = goog.dom.getOwnerDocument(node).createElement('SPAN');
|
||||
tempNode.innerHTML = html;
|
||||
|
||||
var parentNode = node.parentNode;
|
||||
var nodeToInsert;
|
||||
while ((nodeToInsert = tempNode.firstChild) != null) {
|
||||
// Each parentNode.insertBefore call removes the inserted node from
|
||||
// tempNode's list of children.
|
||||
parentNode.insertBefore(nodeToInsert, node);
|
||||
}
|
||||
|
||||
parentNode.removeChild(node);
|
||||
annotated = true;
|
||||
}
|
||||
} else if (node.hasChildNodes() &&
|
||||
!goog.array.contains(goog.dom.annotate.NODES_TO_SKIP_,
|
||||
node.tagName)) {
|
||||
var classes = node.className.split(/\s+/);
|
||||
var skip = goog.array.some(classes, function(className) {
|
||||
return goog.array.contains(classesToSkip, className);
|
||||
});
|
||||
|
||||
if (!skip) {
|
||||
++recursionLevel;
|
||||
var curNode = node.firstChild;
|
||||
var numTermsAnnotated = 0;
|
||||
while (curNode) {
|
||||
var nextNode = curNode.nextSibling;
|
||||
var curNodeAnnotated = goog.dom.annotate.annotateTermsInNode_(
|
||||
curNode, terms, annotateFn, ignoreCase, classesToSkip,
|
||||
stopTime, recursionLevel);
|
||||
annotated = annotated || curNodeAnnotated;
|
||||
curNode = nextNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return annotated;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches non-word characters.
|
||||
*
|
||||
* Performance note: Testing a one-character string using this regex is as fast
|
||||
* as the equivalent string test ("a-zA-Z0-9_".indexOf(c) < 0), give or take a
|
||||
* few percent. (The regex is about 5% faster in IE 6 and about 4% slower in
|
||||
* Firefox 1.5.) If performance becomes critical, it may be better to convert
|
||||
* the character to a numerical char code and check whether it falls in the
|
||||
* word character ranges. A quick test suggests that could be 33% faster.
|
||||
*
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.NONWORD_RE_ = /\W/;
|
||||
|
||||
|
||||
/**
|
||||
* Annotates occurrences of query terms in plain text. This process consists of
|
||||
* identifying all occurrences of all query terms, calling a provided function
|
||||
* to get the appropriate replacement HTML for each occurrence, and
|
||||
* HTML-escaping all the text.
|
||||
*
|
||||
* @param {string} text The plain text to be searched.
|
||||
* @param {Array} terms An array of
|
||||
* [{string} searchTerm, {boolean} matchWholeWordOnly] tuples.
|
||||
* The matchWholeWordOnly value is a per-term attribute because some terms
|
||||
* may be CJK, while others are not. (For correctness, matchWholeWordOnly
|
||||
* should always be false for CJK terms.).
|
||||
* @param {Function} annotateFn {function(number, string) : string} A function
|
||||
* that takes
|
||||
* (1) the number of the term that is "hit",
|
||||
* (2) the HTML string (search term) to be annotated,
|
||||
* and returns the annotated term as an HTML string.
|
||||
* @param {*=} opt_ignoreCase Whether to ignore the case of the query
|
||||
* terms when looking for matches.
|
||||
* @return {?string} The HTML equivalent of {@code text} with terms
|
||||
* annotated, or null if the text did not contain any of the terms.
|
||||
*/
|
||||
goog.dom.annotate.annotateText = function(text, terms, annotateFn,
|
||||
opt_ignoreCase) {
|
||||
if (opt_ignoreCase) {
|
||||
terms = goog.dom.annotate.lowercaseTerms_(terms);
|
||||
}
|
||||
return goog.dom.annotate.helpAnnotateText_(text, terms, annotateFn,
|
||||
opt_ignoreCase);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Annotates occurrences of query terms in plain text. This process consists of
|
||||
* identifying all occurrences of all query terms, calling a provided function
|
||||
* to get the appropriate replacement HTML for each occurrence, and
|
||||
* HTML-escaping all the text.
|
||||
*
|
||||
* @param {string} text The plain text to be searched.
|
||||
* @param {Array} terms An array of
|
||||
* [{string} searchTerm, {boolean} matchWholeWordOnly] tuples.
|
||||
* If {@code ignoreCase} is true, each search term must already be lowercase.
|
||||
* The matchWholeWordOnly value is a per-term attribute because some terms
|
||||
* may be CJK, while others are not. (For correctness, matchWholeWordOnly
|
||||
* should always be false for CJK terms.).
|
||||
* @param {Function} annotateFn {function(number, string) : string} A function
|
||||
* that takes
|
||||
* (1) the number of the term that is "hit",
|
||||
* (2) the HTML string (search term) to be annotated,
|
||||
* and returns the annotated term as an HTML string.
|
||||
* @param {*} ignoreCase Whether to ignore the case of the query terms
|
||||
* when looking for matches.
|
||||
* @return {?string} The HTML equivalent of {@code text} with terms
|
||||
* annotated, or null if the text did not contain any of the terms.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.helpAnnotateText_ = function(text, terms, annotateFn,
|
||||
ignoreCase) {
|
||||
var hit = false;
|
||||
var resultHtml = null;
|
||||
var textToSearch = ignoreCase ? text.toLowerCase() : text;
|
||||
var textLen = textToSearch.length;
|
||||
var numTerms = terms.length;
|
||||
|
||||
// Each element will be an array of hit positions for the term.
|
||||
var termHits = new Array(numTerms);
|
||||
|
||||
// First collect all the hits into allHits.
|
||||
for (var i = 0; i < numTerms; i++) {
|
||||
var term = terms[i];
|
||||
var hits = [];
|
||||
var termText = term[0];
|
||||
if (termText != '') {
|
||||
var matchWholeWordOnly = term[1];
|
||||
var termLen = termText.length;
|
||||
var pos = 0;
|
||||
// Find each hit for term t and append to termHits.
|
||||
while (pos < textLen) {
|
||||
var hitPos = textToSearch.indexOf(termText, pos);
|
||||
if (hitPos == -1) {
|
||||
break;
|
||||
} else {
|
||||
var prevCharPos = hitPos - 1;
|
||||
var nextCharPos = hitPos + termLen;
|
||||
if (!matchWholeWordOnly ||
|
||||
((prevCharPos < 0 ||
|
||||
goog.dom.annotate.NONWORD_RE_.test(
|
||||
textToSearch.charAt(prevCharPos))) &&
|
||||
(nextCharPos >= textLen ||
|
||||
goog.dom.annotate.NONWORD_RE_.test(
|
||||
textToSearch.charAt(nextCharPos))))) {
|
||||
hits.push(hitPos);
|
||||
hit = true;
|
||||
}
|
||||
pos = hitPos + termLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
termHits[i] = hits;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
var html = [];
|
||||
var pos = 0;
|
||||
|
||||
while (true) {
|
||||
// First determine which of the n terms is the next hit.
|
||||
var termIndexOfNextHit;
|
||||
var posOfNextHit = -1;
|
||||
|
||||
for (var i = 0; i < numTerms; i++) {
|
||||
var hits = termHits[i];
|
||||
// pull off the position of the next hit of term t
|
||||
// (it's always the first in the array because we're shifting
|
||||
// hits off the front of the array as we process them)
|
||||
// this is the next candidate to consider for the next overall hit
|
||||
if (!goog.array.isEmpty(hits)) {
|
||||
var hitPos = hits[0];
|
||||
|
||||
// Discard any hits embedded in the previous hit.
|
||||
while (hitPos >= 0 && hitPos < pos) {
|
||||
hits.shift();
|
||||
hitPos = goog.array.isEmpty(hits) ? -1 : hits[0];
|
||||
}
|
||||
|
||||
if (hitPos >= 0 && (posOfNextHit < 0 || hitPos < posOfNextHit)) {
|
||||
termIndexOfNextHit = i;
|
||||
posOfNextHit = hitPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quit if there are no more hits.
|
||||
if (posOfNextHit < 0) break;
|
||||
|
||||
// Remove the next hit from our hit list.
|
||||
termHits[termIndexOfNextHit].shift();
|
||||
|
||||
// Append everything from the end of the last hit up to this one.
|
||||
html.push(goog.string.htmlEscape(text.substr(pos, posOfNextHit - pos)));
|
||||
|
||||
// Append the annotated term.
|
||||
var termLen = terms[termIndexOfNextHit][0].length;
|
||||
var termHtml = goog.string.htmlEscape(text.substr(posOfNextHit, termLen));
|
||||
html.push(annotateFn(termIndexOfNextHit, termHtml));
|
||||
|
||||
pos = posOfNextHit + termLen;
|
||||
}
|
||||
|
||||
// Append everything after the last hit.
|
||||
html.push(goog.string.htmlEscape(text.substr(pos)));
|
||||
return html.join('');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts terms to lowercase.
|
||||
*
|
||||
* @param {Array} terms An array of
|
||||
* [{string} searchTerm, {boolean} matchWholeWordOnly] tuples.
|
||||
* @return {Array} An array of
|
||||
* [{string} searchTerm, {boolean} matchWholeWordOnly] tuples.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.annotate.lowercaseTerms_ = function(terms) {
|
||||
var lowercaseTerms = [];
|
||||
for (var i = 0; i < terms.length; ++i) {
|
||||
var term = terms[i];
|
||||
lowercaseTerms[i] = [term[0].toLowerCase(), term[1]];
|
||||
}
|
||||
return lowercaseTerms;
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2010 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 Browser capability checks for the dom package.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.dom.BrowserFeature');
|
||||
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Enum of browser capabilities.
|
||||
* @enum {boolean}
|
||||
*/
|
||||
goog.dom.BrowserFeature = {
|
||||
/**
|
||||
* Whether attributes 'name' and 'type' can be added to an element after it's
|
||||
* created. False in Internet Explorer prior to version 9.
|
||||
*/
|
||||
CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: !goog.userAgent.IE ||
|
||||
goog.userAgent.isDocumentModeOrHigher(9),
|
||||
|
||||
/**
|
||||
* Whether we can use element.children to access an element's Element
|
||||
* children. Available since Gecko 1.9.1, IE 9. (IE<9 also includes comment
|
||||
* nodes in the collection.)
|
||||
*/
|
||||
CAN_USE_CHILDREN_ATTRIBUTE: !goog.userAgent.GECKO && !goog.userAgent.IE ||
|
||||
goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9) ||
|
||||
goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1'),
|
||||
|
||||
/**
|
||||
* Opera, Safari 3, and Internet Explorer 9 all support innerText but they
|
||||
* include text nodes in script and style tags. Not document-mode-dependent.
|
||||
*/
|
||||
CAN_USE_INNER_TEXT: (
|
||||
goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')),
|
||||
|
||||
/**
|
||||
* MSIE, Opera, and Safari>=4 support element.parentElement to access an
|
||||
* element's parent if it is an Element.
|
||||
*/
|
||||
CAN_USE_PARENT_ELEMENT_PROPERTY: goog.userAgent.IE || goog.userAgent.OPERA ||
|
||||
goog.userAgent.WEBKIT,
|
||||
|
||||
/**
|
||||
* Whether NoScope elements need a scoped element written before them in
|
||||
* innerHTML.
|
||||
* MSDN: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx#1
|
||||
*/
|
||||
INNER_HTML_NEEDS_SCOPED_ELEMENT: goog.userAgent.IE
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user