Update wmts-hidpi, add nicer-api-docs
This commit is contained in:
2
nicer-api-docs/closure-library/third_party/closure/goog/base.js
vendored
Normal file
2
nicer-api-docs/closure-library/third_party/closure/goog/base.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// This is a dummy file to trick genjsdeps into doing the right thing.
|
||||
// TODO(nicksantos): fix this
|
||||
611
nicer-api-docs/closure-library/third_party/closure/goog/caja/string/html/htmlparser.js
vendored
Normal file
611
nicer-api-docs/closure-library/third_party/closure/goog/caja/string/html/htmlparser.js
vendored
Normal file
@@ -0,0 +1,611 @@
|
||||
// Copyright 2006-2008, The Google Caja project.
|
||||
// Modifications Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
// All Rights Reserved
|
||||
|
||||
/**
|
||||
* @license Portions of this code are from the google-caja project, received by
|
||||
* Google under the Apache license (http://code.google.com/p/google-caja/).
|
||||
* All other code is Copyright 2009 Google, Inc. All Rights Reserved.
|
||||
|
||||
// Copyright (C) 2006 Google Inc.
|
||||
//
|
||||
// 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 Html SAX parser.
|
||||
*
|
||||
* Examples of usage of the {@code goog.string.html.HtmlParser}:
|
||||
* <pre>
|
||||
* var handler = new MyCustomHtmlVisitorHandlerThatExtendsHtmlSaxHandler();
|
||||
* var parser = new goog.string.html.HtmlParser();
|
||||
* parser.parse(handler, '<html><a href="google.com">link found!</a></html>');
|
||||
* </pre>
|
||||
*
|
||||
* TODO(user, msamuel): validate sanitizer regex against the HTML5 grammar at
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html
|
||||
*
|
||||
* @supported IE6, IE7, IE8, FF1.5, FF2, FF3, Chrome 3.0, Safari and Opera 10.
|
||||
*/
|
||||
|
||||
goog.provide('goog.string.html.HtmlParser');
|
||||
goog.provide('goog.string.html.HtmlParser.EFlags');
|
||||
goog.provide('goog.string.html.HtmlParser.Elements');
|
||||
goog.provide('goog.string.html.HtmlParser.Entities');
|
||||
goog.provide('goog.string.html.HtmlSaxHandler');
|
||||
|
||||
|
||||
/**
|
||||
* An Html parser: {@code parse} takes a string and calls methods on
|
||||
* {@code goog.string.html.HtmlSaxHandler} while it is visiting it.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.string.html.HtmlParser = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HTML entities that are encoded/decoded.
|
||||
* TODO(user): use {@code goog.string.htmlEncode} instead.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.string.html.HtmlParser.Entities = {
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
amp: '&',
|
||||
nbsp: '\240',
|
||||
quot: '"',
|
||||
apos: '\''
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The html eflags, used internally on the parser.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.string.html.HtmlParser.EFlags = {
|
||||
OPTIONAL_ENDTAG: 1,
|
||||
EMPTY: 2,
|
||||
CDATA: 4,
|
||||
RCDATA: 8,
|
||||
UNSAFE: 16,
|
||||
FOLDABLE: 32
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map of element to a bitmap of flags it has, used internally on the parser.
|
||||
* @type {Object}
|
||||
*/
|
||||
goog.string.html.HtmlParser.Elements = {
|
||||
'a': 0,
|
||||
'abbr': 0,
|
||||
'acronym': 0,
|
||||
'address': 0,
|
||||
'applet': goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'area': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'b': 0,
|
||||
'base': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'basefont': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'bdo': 0,
|
||||
'big': 0,
|
||||
'blockquote': 0,
|
||||
'body': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.FOLDABLE,
|
||||
'br': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'button': 0,
|
||||
'caption': 0,
|
||||
'center': 0,
|
||||
'cite': 0,
|
||||
'code': 0,
|
||||
'col': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'colgroup': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'dd': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'del': 0,
|
||||
'dfn': 0,
|
||||
'dir': 0,
|
||||
'div': 0,
|
||||
'dl': 0,
|
||||
'dt': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'em': 0,
|
||||
'fieldset': 0,
|
||||
'font': 0,
|
||||
'form': 0,
|
||||
'frame': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'frameset': goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'h1': 0,
|
||||
'h2': 0,
|
||||
'h3': 0,
|
||||
'h4': 0,
|
||||
'h5': 0,
|
||||
'h6': 0,
|
||||
'head': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.FOLDABLE,
|
||||
'hr': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'html': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.FOLDABLE,
|
||||
'i': 0,
|
||||
'iframe': goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.CDATA,
|
||||
'img': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'input': goog.string.html.HtmlParser.EFlags.EMPTY,
|
||||
'ins': 0,
|
||||
'isindex': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'kbd': 0,
|
||||
'label': 0,
|
||||
'legend': 0,
|
||||
'li': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'link': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'map': 0,
|
||||
'menu': 0,
|
||||
'meta': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'noframes': goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.CDATA,
|
||||
'noscript': goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.CDATA,
|
||||
'object': goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'ol': 0,
|
||||
'optgroup': 0,
|
||||
'option': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'p': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'param': goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'pre': 0,
|
||||
'q': 0,
|
||||
's': 0,
|
||||
'samp': 0,
|
||||
'script': goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.CDATA,
|
||||
'select': 0,
|
||||
'small': 0,
|
||||
'span': 0,
|
||||
'strike': 0,
|
||||
'strong': 0,
|
||||
'style': goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.CDATA,
|
||||
'sub': 0,
|
||||
'sup': 0,
|
||||
'table': 0,
|
||||
'tbody': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'td': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'textarea': goog.string.html.HtmlParser.EFlags.RCDATA,
|
||||
'tfoot': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'th': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'thead': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'title': goog.string.html.HtmlParser.EFlags.RCDATA |
|
||||
goog.string.html.HtmlParser.EFlags.UNSAFE,
|
||||
'tr': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
|
||||
'tt': 0,
|
||||
'u': 0,
|
||||
'ul': 0,
|
||||
'var': 0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches &s.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.AMP_RE_ = /&/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches loose &s.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.LOOSE_AMP_RE_ =
|
||||
/&([^a-z#]|#(?:[^0-9x]|x(?:[^0-9a-f]|$)|$)|$)/gi;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches <.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.LT_RE_ = /</g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches >.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.GT_RE_ = />/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches ".
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.QUOTE_RE_ = /\"/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches =.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.EQUALS_RE_ = /=/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches null characters.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.NULL_RE_ = /\0/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches entities.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.ENTITY_RE_ = /&(#\d+|#x[0-9A-Fa-f]+|\w+);/g;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches decimal numbers.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_ = /^#(\d+)$/;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches hexadecimal numbers.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.HEX_ESCAPE_RE_ = /^#x([0-9A-Fa-f]+)$/;
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches the next token to be processed.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ = new RegExp(
|
||||
// Don't capture space.
|
||||
'^\\s*(?:' +
|
||||
// Capture an attribute name in group 1, and value in group 3.
|
||||
// We capture the fact that there was an attribute in group 2, since
|
||||
// interpreters are inconsistent in whether a group that matches nothing
|
||||
// is null, undefined, or the empty string.
|
||||
('(?:' +
|
||||
'([a-z][a-z-]*)' + // attribute name
|
||||
('(' + // optionally followed
|
||||
'\\s*=\\s*' +
|
||||
('(' +
|
||||
// A double quoted string.
|
||||
'\"[^\"]*\"' +
|
||||
// A single quoted string.
|
||||
'|\'[^\']*\'' +
|
||||
// The positive lookahead is used to make sure that in
|
||||
// <foo bar= baz=boo>, the value for bar is blank, not "baz=boo".
|
||||
'|(?=[a-z][a-z-]*\\s*=)' +
|
||||
// An unquoted value that is not an attribute name.
|
||||
// We know it is not an attribute name because the previous
|
||||
// zero-width match would've eliminated that possibility.
|
||||
'|[^>\"\'\\s]*' +
|
||||
')'
|
||||
) +
|
||||
')'
|
||||
) + '?' +
|
||||
')'
|
||||
) +
|
||||
// End of tag captured in group 3.
|
||||
'|(/?>)' +
|
||||
// Don't capture cruft
|
||||
'|[^a-z\\s>]+)',
|
||||
'i');
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression that matches the next token to be processed when we are
|
||||
* outside a tag.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_ = new RegExp(
|
||||
'^(?:' +
|
||||
// Entity captured in group 1.
|
||||
'&(\\#[0-9]+|\\#[x][0-9a-f]+|\\w+);' +
|
||||
// Comment, doctypes, and processing instructions not captured.
|
||||
'|<[!]--[\\s\\S]*?-->|<!\\w[^>]*>|<\\?[^>*]*>' +
|
||||
// '/' captured in group 2 for close tags, and name captured in group 3.
|
||||
'|<(/)?([a-z][a-z0-9]*)' +
|
||||
// Text captured in group 4.
|
||||
'|([^<&>]+)' +
|
||||
// Cruft captured in group 5.
|
||||
'|([<&>]))',
|
||||
'i');
|
||||
|
||||
|
||||
/**
|
||||
* Given a SAX-like {@code goog.string.html.HtmlSaxHandler} parses a
|
||||
* {@code htmlText} and lets the {@code handler} know the structure while
|
||||
* visiting the nodes.
|
||||
*
|
||||
* @param {goog.string.html.HtmlSaxHandler} handler The HtmlSaxHandler that will
|
||||
* receive the events.
|
||||
* @param {string} htmlText The html text.
|
||||
*/
|
||||
goog.string.html.HtmlParser.prototype.parse = function(handler, htmlText) {
|
||||
var htmlLower = null;
|
||||
var inTag = false; // True iff we're currently processing a tag.
|
||||
var attribs = []; // Accumulates attribute names and values.
|
||||
var tagName; // The name of the tag currently being processed.
|
||||
var eflags; // The element flags for the current tag.
|
||||
var openTag; // True if the current tag is an open tag.
|
||||
|
||||
// Lets the handler know that we are starting to parse the document.
|
||||
handler.startDoc();
|
||||
|
||||
// Consumes tokens from the htmlText and stops once all tokens are processed.
|
||||
while (htmlText) {
|
||||
var regex = inTag ?
|
||||
goog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ :
|
||||
goog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_;
|
||||
// Gets the next token
|
||||
var m = htmlText.match(regex);
|
||||
// And removes it from the string
|
||||
htmlText = htmlText.substring(m[0].length);
|
||||
|
||||
// TODO(goto): cleanup this code breaking it into separate methods.
|
||||
if (inTag) {
|
||||
if (m[1]) { // Attribute.
|
||||
// SetAttribute with uppercase names doesn't work on IE6.
|
||||
var attribName = goog.string.html.toLowerCase(m[1]);
|
||||
var decodedValue;
|
||||
if (m[2]) {
|
||||
var encodedValue = m[3];
|
||||
switch (encodedValue.charCodeAt(0)) { // Strip quotes.
|
||||
case 34: case 39:
|
||||
encodedValue = encodedValue.substring(
|
||||
1, encodedValue.length - 1);
|
||||
break;
|
||||
}
|
||||
decodedValue = this.unescapeEntities_(this.stripNULs_(encodedValue));
|
||||
} else {
|
||||
// Use name as value for valueless attribs, so
|
||||
// <input type=checkbox checked>
|
||||
// gets attributes ['type', 'checkbox', 'checked', 'checked']
|
||||
decodedValue = attribName;
|
||||
}
|
||||
attribs.push(attribName, decodedValue);
|
||||
} else if (m[4]) {
|
||||
if (eflags !== void 0) { // False if not in whitelist.
|
||||
if (openTag) {
|
||||
if (handler.startTag) {
|
||||
handler.startTag(/** @type {string} */ (tagName), attribs);
|
||||
}
|
||||
} else {
|
||||
if (handler.endTag) {
|
||||
handler.endTag(/** @type {string} */ (tagName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openTag && (eflags &
|
||||
(goog.string.html.HtmlParser.EFlags.CDATA |
|
||||
goog.string.html.HtmlParser.EFlags.RCDATA))) {
|
||||
if (htmlLower === null) {
|
||||
htmlLower = goog.string.html.toLowerCase (htmlText);
|
||||
} else {
|
||||
htmlLower = htmlLower.substring(
|
||||
htmlLower.length - htmlText.length);
|
||||
}
|
||||
var dataEnd = htmlLower.indexOf('</' + tagName);
|
||||
if (dataEnd < 0) {
|
||||
dataEnd = htmlText.length;
|
||||
}
|
||||
if (eflags & goog.string.html.HtmlParser.EFlags.CDATA) {
|
||||
if (handler.cdata) {
|
||||
handler.cdata(htmlText.substring(0, dataEnd));
|
||||
}
|
||||
} else if (handler.rcdata) {
|
||||
handler.rcdata(
|
||||
this.normalizeRCData_(htmlText.substring(0, dataEnd)));
|
||||
}
|
||||
htmlText = htmlText.substring(dataEnd);
|
||||
}
|
||||
|
||||
tagName = eflags = openTag = void 0;
|
||||
attribs.length = 0;
|
||||
inTag = false;
|
||||
}
|
||||
} else {
|
||||
if (m[1]) { // Entity.
|
||||
handler.pcdata(m[0]);
|
||||
} else if (m[3]) { // Tag.
|
||||
openTag = !m[2];
|
||||
inTag = true;
|
||||
tagName = goog.string.html.toLowerCase (m[3]);
|
||||
eflags = goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName) ?
|
||||
goog.string.html.HtmlParser.Elements[tagName] : void 0;
|
||||
} else if (m[4]) { // Text.
|
||||
handler.pcdata(m[4]);
|
||||
} else if (m[5]) { // Cruft.
|
||||
switch (m[5]) {
|
||||
case '<': handler.pcdata('<'); break;
|
||||
case '>': handler.pcdata('>'); break;
|
||||
default: handler.pcdata('&'); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lets the handler know that we are done parsing the document.
|
||||
handler.endDoc();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decodes an HTML entity.
|
||||
*
|
||||
* @param {string} name The content between the '&' and the ';'.
|
||||
* @return {string} A single unicode code-point as a string.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.prototype.lookupEntity_ = function(name) {
|
||||
// TODO(goto): use {goog.string.htmlDecode} instead ?
|
||||
// TODO(goto): π is different from Π
|
||||
name = goog.string.html.toLowerCase(name);
|
||||
if (goog.string.html.HtmlParser.Entities.hasOwnProperty(name)) {
|
||||
return goog.string.html.HtmlParser.Entities[name];
|
||||
}
|
||||
var m = name.match(goog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_);
|
||||
if (m) {
|
||||
return String.fromCharCode(parseInt(m[1], 10));
|
||||
} else if (
|
||||
!!(m = name.match(goog.string.html.HtmlParser.HEX_ESCAPE_RE_))) {
|
||||
return String.fromCharCode(parseInt(m[1], 16));
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes null characters on the string.
|
||||
* @param {string} s The string to have the null characters removed.
|
||||
* @return {string} A string without null characters.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.prototype.stripNULs_ = function(s) {
|
||||
return s.replace(goog.string.html.HtmlParser.NULL_RE_, '');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The plain text of a chunk of HTML CDATA which possibly containing.
|
||||
*
|
||||
* TODO(goto): use {@code goog.string.unescapeEntities} instead ?
|
||||
* @param {string} s A chunk of HTML CDATA. It must not start or end inside
|
||||
* an HTML entity.
|
||||
* @return {string} The unescaped entities.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.prototype.unescapeEntities_ = function(s) {
|
||||
return s.replace(
|
||||
goog.string.html.HtmlParser.ENTITY_RE_,
|
||||
goog.bind(this.lookupEntity_, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escape entities in RCDATA that can be escaped without changing the meaning.
|
||||
* @param {string} rcdata The RCDATA string we want to normalize.
|
||||
* @return {string} A normalized version of RCDATA.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlParser.prototype.normalizeRCData_ = function(rcdata) {
|
||||
return rcdata.
|
||||
replace(goog.string.html.HtmlParser.LOOSE_AMP_RE_, '&$1').
|
||||
replace(goog.string.html.HtmlParser.LT_RE_, '<').
|
||||
replace(goog.string.html.HtmlParser.GT_RE_, '>');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO(goto): why isn't this in the string package ? does this solves any
|
||||
* real problem ? move it to the goog.string package if it does.
|
||||
*
|
||||
* @param {string} str The string to lower case.
|
||||
* @return {string} The str in lower case format.
|
||||
*/
|
||||
goog.string.html.toLowerCase = function(str) {
|
||||
// The below may not be true on browsers in the Turkish locale.
|
||||
if ('script' === 'SCRIPT'.toLowerCase()) {
|
||||
return str.toLowerCase();
|
||||
} else {
|
||||
return str.replace(/[A-Z]/g, function(ch) {
|
||||
return String.fromCharCode(ch.charCodeAt(0) | 32);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An interface to the {@code goog.string.html.HtmlParser} visitor, that gets
|
||||
* called while the HTML is being parsed.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when the parser found a new tag.
|
||||
* @param {string} name The name of the tag that is starting.
|
||||
* @param {Array.<string>} attributes The attributes of the tag.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.startTag = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when the parser found a closing tag.
|
||||
* @param {string} name The name of the tag that is ending.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.endTag = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when PCDATA is found.
|
||||
* @param {string} text The PCDATA text found.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.pcdata = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when RCDATA is found.
|
||||
* @param {string} text The RCDATA text found.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.rcdata = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when CDATA is found.
|
||||
* @param {string} text The CDATA text found.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.cdata = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when the parser is starting to parse the document.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.startDoc = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Handler called when the parsing is done.
|
||||
*/
|
||||
goog.string.html.HtmlSaxHandler.prototype.endDoc = goog.abstractMethod;
|
||||
605
nicer-api-docs/closure-library/third_party/closure/goog/caja/string/html/htmlsanitizer.js
vendored
Normal file
605
nicer-api-docs/closure-library/third_party/closure/goog/caja/string/html/htmlsanitizer.js
vendored
Normal file
@@ -0,0 +1,605 @@
|
||||
// Copyright 2006-2008, The Google Caja project.
|
||||
// Modifications Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
// All Rights Reserved
|
||||
|
||||
/**
|
||||
* @license Portions of this code are from the google-caja project, received by
|
||||
* Google under the Apache license (http://code.google.com/p/google-caja/).
|
||||
* All other code is Copyright 2009 Google, Inc. All Rights Reserved.
|
||||
|
||||
// Copyright (C) 2006 Google Inc.
|
||||
//
|
||||
// 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 HTML sanitizer that can satisfy a variety of security
|
||||
* policies. The HTML sanitizer is built around a SAX parser and HTML element
|
||||
* and attributes schemas.
|
||||
*
|
||||
* This package provides html sanitizing and parsing functions.
|
||||
* {@code goog.string.htmlSanitize} is basically just using a custom written
|
||||
* {@code goog.string.HtmlSaxHandler} that outputs safe html as the unsafe
|
||||
* html content is parsed by {@code goog.string.HtmlParser}.
|
||||
*
|
||||
* Examples of usage of the static {@code goog.string.htmlSanitize}:
|
||||
* <pre>
|
||||
* var safeHtml = goog.string.html.htmlSanitize('<script src="xss.js" />');
|
||||
* el.innerHTML = safeHtml;
|
||||
* </pre>
|
||||
*
|
||||
* We use {@code goog.string.StringBuffer} for fast string concatenation, since
|
||||
* htmlSanitize is relatively heavy considering that it is designed to parse
|
||||
* large html files.
|
||||
*
|
||||
* @supported IE6, IE7, IE8, FF1.5, FF2, FF3, Chrome 4.0, Safari and Opera 10.
|
||||
*/
|
||||
|
||||
goog.provide('goog.string.html.HtmlSanitizer');
|
||||
goog.provide('goog.string.html.HtmlSanitizer.AttributeType');
|
||||
goog.provide('goog.string.html.HtmlSanitizer.Attributes');
|
||||
goog.provide('goog.string.html.htmlSanitize');
|
||||
|
||||
goog.require('goog.string.StringBuffer');
|
||||
goog.require('goog.string.html.HtmlParser');
|
||||
goog.require('goog.string.html.HtmlParser.EFlags');
|
||||
goog.require('goog.string.html.HtmlParser.Elements');
|
||||
goog.require('goog.string.html.HtmlSaxHandler');
|
||||
|
||||
|
||||
/**
|
||||
* Strips unsafe tags and attributes from HTML.
|
||||
*
|
||||
* @param {string} htmlText The HTML text to sanitize.
|
||||
* @param {function(string) : string} opt_urlPolicy A transform to apply to URL
|
||||
* attribute values.
|
||||
* @param {function(string) : string} opt_nmTokenPolicy A transform to apply to
|
||||
* names, IDs, and classes.
|
||||
* @return {string} A sanitized HTML, safe to be embedded on the page.
|
||||
*/
|
||||
goog.string.html.htmlSanitize = function(
|
||||
htmlText, opt_urlPolicy, opt_nmTokenPolicy) {
|
||||
var stringBuffer = new goog.string.StringBuffer();
|
||||
var handler = new goog.string.html.HtmlSanitizer(
|
||||
stringBuffer, opt_urlPolicy, opt_nmTokenPolicy);
|
||||
var parser = new goog.string.html.HtmlParser();
|
||||
parser.parse(handler, htmlText);
|
||||
return stringBuffer.toString();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of the {@code goog.string.HtmlSaxHandler} interface that
|
||||
* will take each of the html tags and sanitize it.
|
||||
*
|
||||
* @param {goog.string.StringBuffer} stringBuffer A string buffer, used to
|
||||
* output the html as we sanitize it.
|
||||
* @param {?function(string):string} opt_urlPolicy An optional function to be
|
||||
* applied in URLs.
|
||||
* @param {?function(string):string} opt_nmTokenPolicy An optional function to
|
||||
* be applied in names.
|
||||
* @constructor
|
||||
* @extends {goog.string.html.HtmlSaxHandler}
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer = function(
|
||||
stringBuffer, opt_urlPolicy, opt_nmTokenPolicy) {
|
||||
goog.string.html.HtmlSaxHandler.call(this);
|
||||
|
||||
/**
|
||||
* The string buffer that holds the sanitized version of the html. Used
|
||||
* during the parse time.
|
||||
* @type {goog.string.StringBuffer}
|
||||
* @private
|
||||
*/
|
||||
this.stringBuffer_ = stringBuffer;
|
||||
|
||||
/**
|
||||
* A stack that holds how the handler is being called.
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
this.stack_ = [];
|
||||
|
||||
/**
|
||||
* Whether we are ignoring what is being processed or not.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.ignoring_ = false;
|
||||
|
||||
/**
|
||||
* A function to be applied to urls found on the parsing process.
|
||||
* @type {?function(string):string}
|
||||
* @private
|
||||
*/
|
||||
this.urlPolicy_ = opt_urlPolicy;
|
||||
|
||||
/**
|
||||
* A function to be applied to names fround on the parsing process.
|
||||
* @type {?function(string):string}
|
||||
* @private
|
||||
*/
|
||||
this.nmTokenPolicy_ = opt_nmTokenPolicy;
|
||||
};
|
||||
goog.inherits(
|
||||
goog.string.html.HtmlSanitizer,
|
||||
goog.string.html.HtmlSaxHandler);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The HTML types the parser supports.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.AttributeType = {
|
||||
NONE: 0,
|
||||
URI: 1,
|
||||
URI_FRAGMENT: 11,
|
||||
SCRIPT: 2,
|
||||
STYLE: 3,
|
||||
ID: 4,
|
||||
IDREF: 5,
|
||||
IDREFS: 6,
|
||||
GLOBAL_NAME: 7,
|
||||
LOCAL_NAME: 8,
|
||||
CLASSES: 9,
|
||||
FRAME_TARGET: 10
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A map of attributes to types it has.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.Attributes = {
|
||||
'*::class': goog.string.html.HtmlSanitizer.AttributeType.CLASSES,
|
||||
'*::dir': 0,
|
||||
'*::id': goog.string.html.HtmlSanitizer.AttributeType.ID,
|
||||
'*::lang': 0,
|
||||
'*::onclick': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::ondblclick': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onkeydown': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onkeypress': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onkeyup': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onload': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onmousedown': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onmousemove': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onmouseout': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onmouseover': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onmouseup': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::style': goog.string.html.HtmlSanitizer.AttributeType.STYLE,
|
||||
'*::title': 0,
|
||||
'*::accesskey': 0,
|
||||
'*::tabindex': 0,
|
||||
'*::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'*::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'a::coords': 0,
|
||||
'a::href': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'a::hreflang': 0,
|
||||
'a::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
|
||||
'a::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'a::rel': 0,
|
||||
'a::rev': 0,
|
||||
'a::shape': 0,
|
||||
'a::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
|
||||
'a::type': 0,
|
||||
'area::accesskey': 0,
|
||||
'area::alt': 0,
|
||||
'area::coords': 0,
|
||||
'area::href': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'area::nohref': 0,
|
||||
'area::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'area::shape': 0,
|
||||
'area::tabindex': 0,
|
||||
'area::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
|
||||
'bdo::dir': 0,
|
||||
'blockquote::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'br::clear': 0,
|
||||
'button::accesskey': 0,
|
||||
'button::disabled': 0,
|
||||
'button::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
|
||||
'button::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'button::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'button::tabindex': 0,
|
||||
'button::type': 0,
|
||||
'button::value': 0,
|
||||
'caption::align': 0,
|
||||
'col::align': 0,
|
||||
'col::char': 0,
|
||||
'col::charoff': 0,
|
||||
'col::span': 0,
|
||||
'col::valign': 0,
|
||||
'col::width': 0,
|
||||
'colgroup::align': 0,
|
||||
'colgroup::char': 0,
|
||||
'colgroup::charoff': 0,
|
||||
'colgroup::span': 0,
|
||||
'colgroup::valign': 0,
|
||||
'colgroup::width': 0,
|
||||
'del::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'del::datetime': 0,
|
||||
'dir::compact': 0,
|
||||
'div::align': 0,
|
||||
'dl::compact': 0,
|
||||
'font::color': 0,
|
||||
'font::face': 0,
|
||||
'font::size': 0,
|
||||
'form::accept': 0,
|
||||
'form::action': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'form::autocomplete': 0,
|
||||
'form::enctype': 0,
|
||||
'form::method': 0,
|
||||
'form::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
|
||||
'form::onreset': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'form::onsubmit': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'form::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
|
||||
'h1::align': 0,
|
||||
'h2::align': 0,
|
||||
'h3::align': 0,
|
||||
'h4::align': 0,
|
||||
'h5::align': 0,
|
||||
'h6::align': 0,
|
||||
'hr::align': 0,
|
||||
'hr::noshade': 0,
|
||||
'hr::size': 0,
|
||||
'hr::width': 0,
|
||||
'img::align': 0,
|
||||
'img::alt': 0,
|
||||
'img::border': 0,
|
||||
'img::height': 0,
|
||||
'img::hspace': 0,
|
||||
'img::ismap': 0,
|
||||
'img::longdesc': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'img::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
|
||||
'img::src': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'img::usemap': goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT,
|
||||
'img::vspace': 0,
|
||||
'img::width': 0,
|
||||
'input::accept': 0,
|
||||
'input::accesskey': 0,
|
||||
'input::autocomplete': 0,
|
||||
'input::align': 0,
|
||||
'input::alt': 0,
|
||||
'input::checked': 0,
|
||||
'input::disabled': 0,
|
||||
'input::ismap': 0,
|
||||
'input::maxlength': 0,
|
||||
'input::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
|
||||
'input::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'input::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'input::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'input::onselect': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'input::readonly': 0,
|
||||
'input::size': 0,
|
||||
'input::src': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'input::tabindex': 0,
|
||||
'input::type': 0,
|
||||
'input::usemap': goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT,
|
||||
'input::value': 0,
|
||||
'ins::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'ins::datetime': 0,
|
||||
'label::accesskey': 0,
|
||||
'label::for': goog.string.html.HtmlSanitizer.AttributeType.IDREF,
|
||||
'label::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'label::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'legend::accesskey': 0,
|
||||
'legend::align': 0,
|
||||
'li::type': 0,
|
||||
'li::value': 0,
|
||||
'map::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
|
||||
'menu::compact': 0,
|
||||
'ol::compact': 0,
|
||||
'ol::start': 0,
|
||||
'ol::type': 0,
|
||||
'optgroup::disabled': 0,
|
||||
'optgroup::label': 0,
|
||||
'option::disabled': 0,
|
||||
'option::label': 0,
|
||||
'option::selected': 0,
|
||||
'option::value': 0,
|
||||
'p::align': 0,
|
||||
'pre::width': 0,
|
||||
'q::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
|
||||
'select::disabled': 0,
|
||||
'select::multiple': 0,
|
||||
'select::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
|
||||
'select::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'select::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'select::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'select::size': 0,
|
||||
'select::tabindex': 0,
|
||||
'table::align': 0,
|
||||
'table::bgcolor': 0,
|
||||
'table::border': 0,
|
||||
'table::cellpadding': 0,
|
||||
'table::cellspacing': 0,
|
||||
'table::frame': 0,
|
||||
'table::rules': 0,
|
||||
'table::summary': 0,
|
||||
'table::width': 0,
|
||||
'tbody::align': 0,
|
||||
'tbody::char': 0,
|
||||
'tbody::charoff': 0,
|
||||
'tbody::valign': 0,
|
||||
'td::abbr': 0,
|
||||
'td::align': 0,
|
||||
'td::axis': 0,
|
||||
'td::bgcolor': 0,
|
||||
'td::char': 0,
|
||||
'td::charoff': 0,
|
||||
'td::colspan': 0,
|
||||
'td::headers': goog.string.html.HtmlSanitizer.AttributeType.IDREFS,
|
||||
'td::height': 0,
|
||||
'td::nowrap': 0,
|
||||
'td::rowspan': 0,
|
||||
'td::scope': 0,
|
||||
'td::valign': 0,
|
||||
'td::width': 0,
|
||||
'textarea::accesskey': 0,
|
||||
'textarea::cols': 0,
|
||||
'textarea::disabled': 0,
|
||||
'textarea::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
|
||||
'textarea::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'textarea::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'textarea::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'textarea::onselect': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
|
||||
'textarea::readonly': 0,
|
||||
'textarea::rows': 0,
|
||||
'textarea::tabindex': 0,
|
||||
'tfoot::align': 0,
|
||||
'tfoot::char': 0,
|
||||
'tfoot::charoff': 0,
|
||||
'tfoot::valign': 0,
|
||||
'th::abbr': 0,
|
||||
'th::align': 0,
|
||||
'th::axis': 0,
|
||||
'th::bgcolor': 0,
|
||||
'th::char': 0,
|
||||
'th::charoff': 0,
|
||||
'th::colspan': 0,
|
||||
'th::headers': goog.string.html.HtmlSanitizer.AttributeType.IDREFS,
|
||||
'th::height': 0,
|
||||
'th::nowrap': 0,
|
||||
'th::rowspan': 0,
|
||||
'th::scope': 0,
|
||||
'th::valign': 0,
|
||||
'th::width': 0,
|
||||
'thead::align': 0,
|
||||
'thead::char': 0,
|
||||
'thead::charoff': 0,
|
||||
'thead::valign': 0,
|
||||
'tr::align': 0,
|
||||
'tr::bgcolor': 0,
|
||||
'tr::char': 0,
|
||||
'tr::charoff': 0,
|
||||
'tr::valign': 0,
|
||||
'ul::compact': 0,
|
||||
'ul::type': 0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.startTag =
|
||||
function(tagName, attribs) {
|
||||
if (this.ignoring_) {
|
||||
return;
|
||||
}
|
||||
if (!goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName)) {
|
||||
return;
|
||||
}
|
||||
var eflags = goog.string.html.HtmlParser.Elements[tagName];
|
||||
if (eflags & goog.string.html.HtmlParser.EFlags.FOLDABLE) {
|
||||
return;
|
||||
} else if (eflags & goog.string.html.HtmlParser.EFlags.UNSAFE) {
|
||||
this.ignoring_ = !(eflags & goog.string.html.HtmlParser.EFlags.EMPTY);
|
||||
return;
|
||||
}
|
||||
attribs = this.sanitizeAttributes_(tagName, attribs);
|
||||
if (attribs) {
|
||||
if (!(eflags & goog.string.html.HtmlParser.EFlags.EMPTY)) {
|
||||
this.stack_.push(tagName);
|
||||
}
|
||||
|
||||
this.stringBuffer_.append('<', tagName);
|
||||
for (var i = 0, n = attribs.length; i < n; i += 2) {
|
||||
var attribName = attribs[i],
|
||||
value = attribs[i + 1];
|
||||
if (value !== null && value !== void 0) {
|
||||
this.stringBuffer_.append(' ', attribName, '="',
|
||||
this.escapeAttrib_(value), '"');
|
||||
}
|
||||
}
|
||||
this.stringBuffer_.append('>');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.endTag = function(tagName) {
|
||||
if (this.ignoring_) {
|
||||
this.ignoring_ = false;
|
||||
return;
|
||||
}
|
||||
if (!goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName)) {
|
||||
return;
|
||||
}
|
||||
var eflags = goog.string.html.HtmlParser.Elements[tagName];
|
||||
if (!(eflags & (goog.string.html.HtmlParser.EFlags.UNSAFE |
|
||||
goog.string.html.HtmlParser.EFlags.EMPTY |
|
||||
goog.string.html.HtmlParser.EFlags.FOLDABLE))) {
|
||||
var index;
|
||||
if (eflags & goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG) {
|
||||
for (index = this.stack_.length; --index >= 0;) {
|
||||
var stackEl = this.stack_[index];
|
||||
if (stackEl === tagName) {
|
||||
break;
|
||||
}
|
||||
if (!(goog.string.html.HtmlParser.Elements[stackEl] &
|
||||
goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG)) {
|
||||
// Don't pop non optional end tags looking for a match.
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (index = this.stack_.length; --index >= 0;) {
|
||||
if (this.stack_[index] === tagName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index < 0) { return; } // Not opened.
|
||||
for (var i = this.stack_.length; --i > index;) {
|
||||
var stackEl = this.stack_[i];
|
||||
if (!(goog.string.html.HtmlParser.Elements[stackEl] &
|
||||
goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG)) {
|
||||
this.stringBuffer_.append('</', stackEl, '>');
|
||||
}
|
||||
}
|
||||
this.stack_.length = index;
|
||||
this.stringBuffer_.append('</', tagName, '>');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.pcdata = function(text) {
|
||||
if (!this.ignoring_) {
|
||||
this.stringBuffer_.append(text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.rcdata = function(text) {
|
||||
if (!this.ignoring_) {
|
||||
this.stringBuffer_.append(text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.cdata = function(text) {
|
||||
if (!this.ignoring_) {
|
||||
this.stringBuffer_.append(text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.startDoc = function() {
|
||||
this.stack_ = [];
|
||||
this.ignoring_ = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.endDoc = function() {
|
||||
for (var i = this.stack_.length; --i >= 0;) {
|
||||
this.stringBuffer_.append('</', this.stack_[i], '>');
|
||||
}
|
||||
this.stack_.length = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escapes HTML special characters in attribute values as HTML entities.
|
||||
*
|
||||
* TODO(user): use {@code goog.string.htmlEscape} instead ?
|
||||
* @param {string} s The string to be escaped.
|
||||
* @return {string} An escaped version of {@code s}.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.escapeAttrib_ = function(s) {
|
||||
// Escaping '=' defangs many UTF-7 and SGML short-tag attacks.
|
||||
return s.replace(goog.string.html.HtmlParser.AMP_RE_, '&').
|
||||
replace(goog.string.html.HtmlParser.LT_RE_, '<').
|
||||
replace(goog.string.html.HtmlParser.GT_RE_, '>').
|
||||
replace(goog.string.html.HtmlParser.QUOTE_RE_, '"').
|
||||
replace(goog.string.html.HtmlParser.EQUALS_RE_, '=');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes attributes found on html entities.
|
||||
* @param {string} tagName The name of the tag in which the {@code attribs} were
|
||||
* found.
|
||||
* @param {Array.<?string>} attribs An array of attributes.
|
||||
* @return {Array.<?string>} A sanitized version of the {@code attribs}.
|
||||
* @private
|
||||
*/
|
||||
goog.string.html.HtmlSanitizer.prototype.sanitizeAttributes_ =
|
||||
function(tagName, attribs) {
|
||||
for (var i = 0; i < attribs.length; i += 2) {
|
||||
var attribName = attribs[i];
|
||||
var value = attribs[i + 1];
|
||||
var atype = null, attribKey;
|
||||
if ((attribKey = tagName + '::' + attribName,
|
||||
goog.string.html.HtmlSanitizer.Attributes.hasOwnProperty(attribKey)) ||
|
||||
(attribKey = '*::' + attribName,
|
||||
goog.string.html.HtmlSanitizer.Attributes.hasOwnProperty(attribKey))) {
|
||||
atype = goog.string.html.HtmlSanitizer.Attributes[attribKey];
|
||||
}
|
||||
if (atype !== null) {
|
||||
switch (atype) {
|
||||
case 0: break;
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.SCRIPT:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.STYLE:
|
||||
value = null;
|
||||
break;
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.ID:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.IDREF:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.IDREFS:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME:
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.CLASSES:
|
||||
value = this.nmTokenPolicy_ ?
|
||||
this.nmTokenPolicy_(/** @type {string} */ (value)) : value;
|
||||
break;
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.URI:
|
||||
value = this.urlPolicy_ && this.urlPolicy_(
|
||||
/** @type {string} */ (value));
|
||||
break;
|
||||
case goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT:
|
||||
if (value && '#' === value.charAt(0)) {
|
||||
value = this.nmTokenPolicy_ ? this.nmTokenPolicy_(value) : value;
|
||||
if (value) { value = '#' + value; }
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
value = null;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
attribs[i + 1] = value;
|
||||
}
|
||||
return attribs;
|
||||
};
|
||||
1543
nicer-api-docs/closure-library/third_party/closure/goog/dojo/dom/query.js
vendored
Normal file
1543
nicer-api-docs/closure-library/third_party/closure/goog/dojo/dom/query.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
158
nicer-api-docs/closure-library/third_party/closure/goog/dojo/dom/query_test.js
vendored
Normal file
158
nicer-api-docs/closure-library/third_party/closure/goog/dojo/dom/query_test.js
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
goog.setTestOnly('query_test');
|
||||
|
||||
function testBasicSelectors() {
|
||||
assertQuery(4, 'h3');
|
||||
assertQuery(1, 'h1:first-child');
|
||||
assertQuery(2, 'h3:first-child');
|
||||
assertQuery(1, '#t');
|
||||
assertQuery(1, '#bug');
|
||||
assertQuery(4, '#t h3');
|
||||
assertQuery(1, 'div#t');
|
||||
assertQuery(4, 'div#t h3');
|
||||
assertQuery(0, 'span#t');
|
||||
assertQuery(1, '#t div > h3');
|
||||
assertQuery(2, '.foo');
|
||||
assertQuery(1, '.foo.bar');
|
||||
assertQuery(2, '.baz');
|
||||
assertQuery(3, '#t > h3');
|
||||
}
|
||||
|
||||
function testSyntacticEquivalents() {
|
||||
// syntactic equivalents
|
||||
assertQuery(12, '#t > *');
|
||||
assertQuery(12, '#t >');
|
||||
assertQuery(3, '.foo > *');
|
||||
assertQuery(3, '.foo >');
|
||||
}
|
||||
|
||||
function testWithARootById() {
|
||||
// with a root, by ID
|
||||
assertQuery(3, '> *', 'container');
|
||||
assertQuery(3, '> h3', 't');
|
||||
}
|
||||
|
||||
function testCompoundQueries() {
|
||||
// compound queries
|
||||
assertQuery(2, '.foo, .bar');
|
||||
assertQuery(2, '.foo,.bar');
|
||||
}
|
||||
|
||||
function testMultipleClassAttributes() {
|
||||
// multiple class attribute
|
||||
assertQuery(1, '.foo.bar');
|
||||
assertQuery(2, '.foo');
|
||||
assertQuery(2, '.baz');
|
||||
}
|
||||
|
||||
function testCaseSensitivity() {
|
||||
// case sensitivity
|
||||
assertQuery(1, 'span.baz');
|
||||
assertQuery(1, 'sPaN.baz');
|
||||
assertQuery(1, 'SPAN.baz');
|
||||
assertQuery(1, '[class = \"foo bar\"]');
|
||||
assertQuery(2, '[foo~=\"bar\"]');
|
||||
assertQuery(2, '[ foo ~= \"bar\" ]');
|
||||
}
|
||||
|
||||
function testAttributes() {
|
||||
assertQuery(3, '[foo]');
|
||||
assertQuery(1, '[foo$=\"thud\"]');
|
||||
assertQuery(1, '[foo$=thud]');
|
||||
assertQuery(1, '[foo$=\"thudish\"]');
|
||||
assertQuery(1, '#t [foo$=thud]');
|
||||
assertQuery(1, '#t [ title $= thud ]');
|
||||
assertQuery(0, '#t span[ title $= thud ]');
|
||||
assertQuery(2, '[foo|=\"bar\"]');
|
||||
assertQuery(1, '[foo|=\"bar-baz\"]');
|
||||
assertQuery(0, '[foo|=\"baz\"]');
|
||||
}
|
||||
|
||||
function testDescendantSelectors() {
|
||||
assertQuery(3, '>', 'container');
|
||||
assertQuery(3, '> *', 'container');
|
||||
assertQuery(2, '> [qux]', 'container');
|
||||
assertEquals('child1', goog.dom.query('> [qux]', 'container')[0].id);
|
||||
assertEquals('child3', goog.dom.query('> [qux]', 'container')[1].id);
|
||||
assertQuery(3, '>', 'container');
|
||||
assertQuery(3, '> *', 'container');
|
||||
}
|
||||
|
||||
function testSiblingSelectors() {
|
||||
assertQuery(1, '+', 'container');
|
||||
assertQuery(3, '~', 'container');
|
||||
assertQuery(1, '.foo + span');
|
||||
assertQuery(4, '.foo ~ span');
|
||||
assertQuery(1, '#foo ~ *');
|
||||
assertQuery(1, '#foo ~');
|
||||
}
|
||||
|
||||
function testSubSelectors() {
|
||||
// sub-selector parsing
|
||||
assertQuery(1, '#t span.foo:not(span:first-child)');
|
||||
assertQuery(1, '#t span.foo:not(:first-child)');
|
||||
}
|
||||
|
||||
function testNthChild() {
|
||||
assertEquals(goog.dom.$('_foo'), goog.dom.query('.foo:nth-child(2)')[0]);
|
||||
assertQuery(2, '#t > h3:nth-child(odd)');
|
||||
assertQuery(3, '#t h3:nth-child(odd)');
|
||||
assertQuery(3, '#t h3:nth-child(2n+1)');
|
||||
assertQuery(1, '#t h3:nth-child(even)');
|
||||
assertQuery(1, '#t h3:nth-child(2n)');
|
||||
assertQuery(1, '#t h3:nth-child(2n+3)');
|
||||
assertQuery(2, '#t h3:nth-child(1)');
|
||||
assertQuery(1, '#t > h3:nth-child(1)');
|
||||
assertQuery(3, '#t :nth-child(3)');
|
||||
assertQuery(0, '#t > div:nth-child(1)');
|
||||
assertQuery(7, '#t span');
|
||||
assertQuery(3, '#t > *:nth-child(n+10)');
|
||||
assertQuery(1, '#t > *:nth-child(n+12)');
|
||||
assertQuery(10, '#t > *:nth-child(-n+10)');
|
||||
assertQuery(5, '#t > *:nth-child(-2n+10)');
|
||||
assertQuery(6, '#t > *:nth-child(2n+2)');
|
||||
assertQuery(5, '#t > *:nth-child(2n+4)');
|
||||
assertQuery(5, '#t > *:nth-child(2n+4)');
|
||||
assertQuery(12, '#t > *:nth-child(n-5)');
|
||||
assertQuery(6, '#t > *:nth-child(2n-5)');
|
||||
}
|
||||
|
||||
function testEmptyPseudoSelector() {
|
||||
assertQuery(4, '#t > span:empty');
|
||||
assertQuery(6, '#t span:empty');
|
||||
assertQuery(0, 'h3 span:empty');
|
||||
assertQuery(1, 'h3 :not(:empty)');
|
||||
}
|
||||
|
||||
function testIdsWithColons() {
|
||||
assertQuery(1, '#silly\\:id\\:\\:with\\:colons');
|
||||
}
|
||||
|
||||
function testOrder() {
|
||||
var els = goog.dom.query('.myupperclass .myclass input');
|
||||
assertEquals('myid1', els[0].id);
|
||||
assertEquals('myid2', els[1].id);
|
||||
}
|
||||
|
||||
function testCorrectDocumentInFrame() {
|
||||
var frameDocument = window.frames['ifr'].document;
|
||||
frameDocument.body.innerHTML =
|
||||
document.getElementById('iframe-test').innerHTML;
|
||||
|
||||
var els = goog.dom.query('#if1 .if2 div', document);
|
||||
var frameEls = goog.dom.query('#if1 .if2 div', frameDocument);
|
||||
|
||||
assertEquals(els.length, frameEls.length);
|
||||
assertEquals(1, frameEls.length);
|
||||
assertNotEquals(document.getElementById('if3'),
|
||||
frameDocument.getElementById('if3'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} expectedNumberOfNodes
|
||||
* @param {...*} var_args
|
||||
*/
|
||||
function assertQuery(expectedNumberOfNodes, var_args) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
assertEquals(expectedNumberOfNodes,
|
||||
goog.dom.query.apply(null, args).length);
|
||||
}
|
||||
751
nicer-api-docs/closure-library/third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js
vendored
Normal file
751
nicer-api-docs/closure-library/third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js
vendored
Normal file
@@ -0,0 +1,751 @@
|
||||
/**
|
||||
* @license
|
||||
Copyright (c) 2008, Adobe Systems Incorporated
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Adobe Systems Incorporated nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* @license
|
||||
JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
|
||||
|
||||
Basic GUI blocking jpeg encoder
|
||||
|
||||
v 0.9
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview This code was ported from
|
||||
* http://www.bytestrom.eu/blog/2009/1120a_jpeg_encoder_for_javascript and
|
||||
* modified slightly for Closure.
|
||||
*/
|
||||
|
||||
goog.provide('goog.crypt.JpegEncoder');
|
||||
|
||||
goog.require('goog.crypt.base64');
|
||||
|
||||
/**
|
||||
* Initializes the JpegEncoder.
|
||||
*
|
||||
* @constructor
|
||||
* @param {number=} opt_quality The compression quality. Default 50.
|
||||
*/
|
||||
goog.crypt.JpegEncoder = function(opt_quality) {
|
||||
var self = this;
|
||||
var fround = Math.round;
|
||||
var ffloor = Math.floor;
|
||||
var YTable = new Array(64);
|
||||
var UVTable = new Array(64);
|
||||
var fdtbl_Y = new Array(64);
|
||||
var fdtbl_UV = new Array(64);
|
||||
var YDC_HT;
|
||||
var UVDC_HT;
|
||||
var YAC_HT;
|
||||
var UVAC_HT;
|
||||
|
||||
var bitcode = new Array(65535);
|
||||
var category = new Array(65535);
|
||||
var outputfDCTQuant = new Array(64);
|
||||
var DU = new Array(64);
|
||||
var byteout = [];
|
||||
var bytenew = 0;
|
||||
var bytepos = 7;
|
||||
|
||||
var YDU = new Array(64);
|
||||
var UDU = new Array(64);
|
||||
var VDU = new Array(64);
|
||||
var clt = new Array(256);
|
||||
var RGB_YUV_TABLE = new Array(2048);
|
||||
var currentQuality;
|
||||
|
||||
var ZigZag = [
|
||||
0, 1, 5, 6,14,15,27,28,
|
||||
2, 4, 7,13,16,26,29,42,
|
||||
3, 8,12,17,25,30,41,43,
|
||||
9,11,18,24,31,40,44,53,
|
||||
10,19,23,32,39,45,52,54,
|
||||
20,22,33,38,46,51,55,60,
|
||||
21,34,37,47,50,56,59,61,
|
||||
35,36,48,49,57,58,62,63
|
||||
];
|
||||
|
||||
var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];
|
||||
var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
|
||||
var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];
|
||||
var std_ac_luminance_values = [
|
||||
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
|
||||
0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
|
||||
0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
|
||||
0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
|
||||
0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
|
||||
0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
|
||||
0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
|
||||
0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
|
||||
0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
|
||||
0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
||||
0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
|
||||
0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
|
||||
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
|
||||
0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
|
||||
0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
|
||||
0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
|
||||
0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
|
||||
0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
|
||||
0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
|
||||
0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
|
||||
0xf9,0xfa
|
||||
];
|
||||
|
||||
var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];
|
||||
var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
|
||||
var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];
|
||||
var std_ac_chrominance_values = [
|
||||
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
|
||||
0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
|
||||
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
|
||||
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
|
||||
0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
|
||||
0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
|
||||
0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
|
||||
0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
|
||||
0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
|
||||
0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
|
||||
0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
|
||||
0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
|
||||
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
|
||||
0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
|
||||
0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
|
||||
0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
|
||||
0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
|
||||
0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
|
||||
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
|
||||
0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
|
||||
0xf9,0xfa
|
||||
];
|
||||
|
||||
function initQuantTables(sf){
|
||||
var YQT = [
|
||||
16, 11, 10, 16, 24, 40, 51, 61,
|
||||
12, 12, 14, 19, 26, 58, 60, 55,
|
||||
14, 13, 16, 24, 40, 57, 69, 56,
|
||||
14, 17, 22, 29, 51, 87, 80, 62,
|
||||
18, 22, 37, 56, 68,109,103, 77,
|
||||
24, 35, 55, 64, 81,104,113, 92,
|
||||
49, 64, 78, 87,103,121,120,101,
|
||||
72, 92, 95, 98,112,100,103, 99
|
||||
];
|
||||
|
||||
for (var i = 0; i < 64; i++) {
|
||||
var t = ffloor((YQT[i]*sf+50)/100);
|
||||
if (t < 1) {
|
||||
t = 1;
|
||||
} else if (t > 255) {
|
||||
t = 255;
|
||||
}
|
||||
YTable[ZigZag[i]] = t;
|
||||
}
|
||||
var UVQT = [
|
||||
17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
];
|
||||
for (var j = 0; j < 64; j++) {
|
||||
var u = ffloor((UVQT[j]*sf+50)/100);
|
||||
if (u < 1) {
|
||||
u = 1;
|
||||
} else if (u > 255) {
|
||||
u = 255;
|
||||
}
|
||||
UVTable[ZigZag[j]] = u;
|
||||
}
|
||||
var aasf = [
|
||||
1.0, 1.387039845, 1.306562965, 1.175875602,
|
||||
1.0, 0.785694958, 0.541196100, 0.275899379
|
||||
];
|
||||
var k = 0;
|
||||
for (var row = 0; row < 8; row++)
|
||||
{
|
||||
for (var col = 0; col < 8; col++)
|
||||
{
|
||||
fdtbl_Y[k] = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
|
||||
fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function computeHuffmanTbl(nrcodes, std_table){
|
||||
var codevalue = 0;
|
||||
var pos_in_table = 0;
|
||||
var HT = new Array();
|
||||
for (var k = 1; k <= 16; k++) {
|
||||
for (var j = 1; j <= nrcodes[k]; j++) {
|
||||
HT[std_table[pos_in_table]] = [];
|
||||
HT[std_table[pos_in_table]][0] = codevalue;
|
||||
HT[std_table[pos_in_table]][1] = k;
|
||||
pos_in_table++;
|
||||
codevalue++;
|
||||
}
|
||||
codevalue*=2;
|
||||
}
|
||||
return HT;
|
||||
}
|
||||
|
||||
function initHuffmanTbl()
|
||||
{
|
||||
YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);
|
||||
UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);
|
||||
YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);
|
||||
UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);
|
||||
}
|
||||
|
||||
function initCategoryNumber()
|
||||
{
|
||||
var nrlower = 1;
|
||||
var nrupper = 2;
|
||||
for (var cat = 1; cat <= 15; cat++) {
|
||||
//Positive numbers
|
||||
for (var nr = nrlower; nr<nrupper; nr++) {
|
||||
category[32767+nr] = cat;
|
||||
bitcode[32767+nr] = [];
|
||||
bitcode[32767+nr][1] = cat;
|
||||
bitcode[32767+nr][0] = nr;
|
||||
}
|
||||
//Negative numbers
|
||||
for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {
|
||||
category[32767+nrneg] = cat;
|
||||
bitcode[32767+nrneg] = [];
|
||||
bitcode[32767+nrneg][1] = cat;
|
||||
bitcode[32767+nrneg][0] = nrupper-1+nrneg;
|
||||
}
|
||||
nrlower <<= 1;
|
||||
nrupper <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
function initRGBYUVTable() {
|
||||
for(var i = 0; i < 256;i++) {
|
||||
RGB_YUV_TABLE[i] = 19595 * i;
|
||||
RGB_YUV_TABLE[(i+ 256)>>0] = 38470 * i;
|
||||
RGB_YUV_TABLE[(i+ 512)>>0] = 7471 * i + 0x8000;
|
||||
RGB_YUV_TABLE[(i+ 768)>>0] = -11059 * i;
|
||||
RGB_YUV_TABLE[(i+1024)>>0] = -21709 * i;
|
||||
RGB_YUV_TABLE[(i+1280)>>0] = 32768 * i + 0x807FFF;
|
||||
RGB_YUV_TABLE[(i+1536)>>0] = -27439 * i;
|
||||
RGB_YUV_TABLE[(i+1792)>>0] = - 5329 * i;
|
||||
}
|
||||
}
|
||||
|
||||
// IO functions
|
||||
function writeBits(bs)
|
||||
{
|
||||
var value = bs[0];
|
||||
var posval = bs[1]-1;
|
||||
while ( posval >= 0 ) {
|
||||
if (value & (1 << posval) ) {
|
||||
bytenew |= (1 << bytepos);
|
||||
}
|
||||
posval--;
|
||||
bytepos--;
|
||||
if (bytepos < 0) {
|
||||
if (bytenew == 0xFF) {
|
||||
writeByte(0xFF);
|
||||
writeByte(0);
|
||||
}
|
||||
else {
|
||||
writeByte(bytenew);
|
||||
}
|
||||
bytepos=7;
|
||||
bytenew=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeByte(value)
|
||||
{
|
||||
byteout.push(clt[value]); // write char directly instead of converting later
|
||||
}
|
||||
|
||||
function writeWord(value)
|
||||
{
|
||||
writeByte((value>>8)&0xFF);
|
||||
writeByte((value )&0xFF);
|
||||
}
|
||||
|
||||
// DCT & quantization core
|
||||
function fDCTQuant(data, fdtbl)
|
||||
{
|
||||
var d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
/* Pass 1: process rows. */
|
||||
var dataOff=0;
|
||||
var i;
|
||||
var I8 = 8;
|
||||
var I64 = 64;
|
||||
for (i=0; i<I8; ++i)
|
||||
{
|
||||
d0 = data[dataOff];
|
||||
d1 = data[dataOff+1];
|
||||
d2 = data[dataOff+2];
|
||||
d3 = data[dataOff+3];
|
||||
d4 = data[dataOff+4];
|
||||
d5 = data[dataOff+5];
|
||||
d6 = data[dataOff+6];
|
||||
d7 = data[dataOff+7];
|
||||
|
||||
var tmp0 = d0 + d7;
|
||||
var tmp7 = d0 - d7;
|
||||
var tmp1 = d1 + d6;
|
||||
var tmp6 = d1 - d6;
|
||||
var tmp2 = d2 + d5;
|
||||
var tmp5 = d2 - d5;
|
||||
var tmp3 = d3 + d4;
|
||||
var tmp4 = d3 - d4;
|
||||
|
||||
/* Even part */
|
||||
var tmp10 = tmp0 + tmp3; /* phase 2 */
|
||||
var tmp13 = tmp0 - tmp3;
|
||||
var tmp11 = tmp1 + tmp2;
|
||||
var tmp12 = tmp1 - tmp2;
|
||||
|
||||
data[dataOff] = tmp10 + tmp11; /* phase 3 */
|
||||
data[dataOff+4] = tmp10 - tmp11;
|
||||
|
||||
var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
|
||||
data[dataOff+2] = tmp13 + z1; /* phase 5 */
|
||||
data[dataOff+6] = tmp13 - z1;
|
||||
|
||||
/* Odd part */
|
||||
tmp10 = tmp4 + tmp5; /* phase 2 */
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp6 + tmp7;
|
||||
|
||||
/* The rotator is modified from fig 4-8 to avoid extra negations. */
|
||||
var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
|
||||
var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */
|
||||
var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
|
||||
var z3 = tmp11 * 0.707106781; /* c4 */
|
||||
|
||||
var z11 = tmp7 + z3; /* phase 5 */
|
||||
var z13 = tmp7 - z3;
|
||||
|
||||
data[dataOff+5] = z13 + z2; /* phase 6 */
|
||||
data[dataOff+3] = z13 - z2;
|
||||
data[dataOff+1] = z11 + z4;
|
||||
data[dataOff+7] = z11 - z4;
|
||||
|
||||
dataOff += 8; /* advance pointer to next row */
|
||||
}
|
||||
|
||||
/* Pass 2: process columns. */
|
||||
dataOff = 0;
|
||||
for (i=0; i<I8; ++i)
|
||||
{
|
||||
d0 = data[dataOff];
|
||||
d1 = data[dataOff + 8];
|
||||
d2 = data[dataOff + 16];
|
||||
d3 = data[dataOff + 24];
|
||||
d4 = data[dataOff + 32];
|
||||
d5 = data[dataOff + 40];
|
||||
d6 = data[dataOff + 48];
|
||||
d7 = data[dataOff + 56];
|
||||
|
||||
var tmp0p2 = d0 + d7;
|
||||
var tmp7p2 = d0 - d7;
|
||||
var tmp1p2 = d1 + d6;
|
||||
var tmp6p2 = d1 - d6;
|
||||
var tmp2p2 = d2 + d5;
|
||||
var tmp5p2 = d2 - d5;
|
||||
var tmp3p2 = d3 + d4;
|
||||
var tmp4p2 = d3 - d4;
|
||||
|
||||
/* Even part */
|
||||
var tmp10p2 = tmp0p2 + tmp3p2; /* phase 2 */
|
||||
var tmp13p2 = tmp0p2 - tmp3p2;
|
||||
var tmp11p2 = tmp1p2 + tmp2p2;
|
||||
var tmp12p2 = tmp1p2 - tmp2p2;
|
||||
|
||||
data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */
|
||||
data[dataOff+32] = tmp10p2 - tmp11p2;
|
||||
|
||||
var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */
|
||||
data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */
|
||||
data[dataOff+48] = tmp13p2 - z1p2;
|
||||
|
||||
/* Odd part */
|
||||
tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */
|
||||
tmp11p2 = tmp5p2 + tmp6p2;
|
||||
tmp12p2 = tmp6p2 + tmp7p2;
|
||||
|
||||
/* The rotator is modified from fig 4-8 to avoid extra negations. */
|
||||
var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */
|
||||
var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */
|
||||
var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */
|
||||
var z3p2 = tmp11p2 * 0.707106781; /* c4 */
|
||||
|
||||
var z11p2 = tmp7p2 + z3p2; /* phase 5 */
|
||||
var z13p2 = tmp7p2 - z3p2;
|
||||
|
||||
data[dataOff+40] = z13p2 + z2p2; /* phase 6 */
|
||||
data[dataOff+24] = z13p2 - z2p2;
|
||||
data[dataOff+ 8] = z11p2 + z4p2;
|
||||
data[dataOff+56] = z11p2 - z4p2;
|
||||
|
||||
dataOff++; /* advance pointer to next column */
|
||||
}
|
||||
|
||||
// Quantize/descale the coefficients
|
||||
var fDCTQuant;
|
||||
for (i=0; i<I64; ++i)
|
||||
{
|
||||
// Apply the quantization and scaling factor & Round to nearest integer
|
||||
fDCTQuant = data[i]*fdtbl[i];
|
||||
outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);
|
||||
//outputfDCTQuant[i] = fround(fDCTQuant);
|
||||
|
||||
}
|
||||
return outputfDCTQuant;
|
||||
}
|
||||
|
||||
function writeAPP0()
|
||||
{
|
||||
writeWord(0xFFE0); // marker
|
||||
writeWord(16); // length
|
||||
writeByte(0x4A); // J
|
||||
writeByte(0x46); // F
|
||||
writeByte(0x49); // I
|
||||
writeByte(0x46); // F
|
||||
writeByte(0); // = "JFIF",'\0'
|
||||
writeByte(1); // versionhi
|
||||
writeByte(1); // versionlo
|
||||
writeByte(0); // xyunits
|
||||
writeWord(1); // xdensity
|
||||
writeWord(1); // ydensity
|
||||
writeByte(0); // thumbnwidth
|
||||
writeByte(0); // thumbnheight
|
||||
}
|
||||
|
||||
function writeSOF0(width, height)
|
||||
{
|
||||
writeWord(0xFFC0); // marker
|
||||
writeWord(17); // length, truecolor YUV JPG
|
||||
writeByte(8); // precision
|
||||
writeWord(height);
|
||||
writeWord(width);
|
||||
writeByte(3); // nrofcomponents
|
||||
writeByte(1); // IdY
|
||||
writeByte(0x11); // HVY
|
||||
writeByte(0); // QTY
|
||||
writeByte(2); // IdU
|
||||
writeByte(0x11); // HVU
|
||||
writeByte(1); // QTU
|
||||
writeByte(3); // IdV
|
||||
writeByte(0x11); // HVV
|
||||
writeByte(1); // QTV
|
||||
}
|
||||
|
||||
function writeDQT()
|
||||
{
|
||||
writeWord(0xFFDB); // marker
|
||||
writeWord(132); // length
|
||||
writeByte(0);
|
||||
for (var i=0; i<64; i++) {
|
||||
writeByte(YTable[i]);
|
||||
}
|
||||
writeByte(1);
|
||||
for (var j=0; j<64; j++) {
|
||||
writeByte(UVTable[j]);
|
||||
}
|
||||
}
|
||||
|
||||
function writeDHT()
|
||||
{
|
||||
writeWord(0xFFC4); // marker
|
||||
writeWord(0x01A2); // length
|
||||
|
||||
writeByte(0); // HTYDCinfo
|
||||
for (var i=0; i<16; i++) {
|
||||
writeByte(std_dc_luminance_nrcodes[i+1]);
|
||||
}
|
||||
for (var j=0; j<=11; j++) {
|
||||
writeByte(std_dc_luminance_values[j]);
|
||||
}
|
||||
|
||||
writeByte(0x10); // HTYACinfo
|
||||
for (var k=0; k<16; k++) {
|
||||
writeByte(std_ac_luminance_nrcodes[k+1]);
|
||||
}
|
||||
for (var l=0; l<=161; l++) {
|
||||
writeByte(std_ac_luminance_values[l]);
|
||||
}
|
||||
|
||||
writeByte(1); // HTUDCinfo
|
||||
for (var m=0; m<16; m++) {
|
||||
writeByte(std_dc_chrominance_nrcodes[m+1]);
|
||||
}
|
||||
for (var n=0; n<=11; n++) {
|
||||
writeByte(std_dc_chrominance_values[n]);
|
||||
}
|
||||
|
||||
writeByte(0x11); // HTUACinfo
|
||||
for (var o=0; o<16; o++) {
|
||||
writeByte(std_ac_chrominance_nrcodes[o+1]);
|
||||
}
|
||||
for (var p=0; p<=161; p++) {
|
||||
writeByte(std_ac_chrominance_values[p]);
|
||||
}
|
||||
}
|
||||
|
||||
function writeSOS()
|
||||
{
|
||||
writeWord(0xFFDA); // marker
|
||||
writeWord(12); // length
|
||||
writeByte(3); // nrofcomponents
|
||||
writeByte(1); // IdY
|
||||
writeByte(0); // HTY
|
||||
writeByte(2); // IdU
|
||||
writeByte(0x11); // HTU
|
||||
writeByte(3); // IdV
|
||||
writeByte(0x11); // HTV
|
||||
writeByte(0); // Ss
|
||||
writeByte(0x3f); // Se
|
||||
writeByte(0); // Bf
|
||||
}
|
||||
|
||||
function processDU(CDU, fdtbl, DC, HTDC, HTAC){
|
||||
var EOB = HTAC[0x00];
|
||||
var M16zeroes = HTAC[0xF0];
|
||||
var pos;
|
||||
var I16 = 16;
|
||||
var I63 = 63;
|
||||
var I64 = 64;
|
||||
var DU_DCT = fDCTQuant(CDU, fdtbl);
|
||||
//ZigZag reorder
|
||||
for (var j=0;j<I64;++j) {
|
||||
DU[ZigZag[j]]=DU_DCT[j];
|
||||
}
|
||||
var Diff = DU[0] - DC; DC = DU[0];
|
||||
//Encode DC
|
||||
if (Diff==0) {
|
||||
writeBits(HTDC[0]); // Diff might be 0
|
||||
} else {
|
||||
pos = 32767+Diff;
|
||||
writeBits(HTDC[category[pos]]);
|
||||
writeBits(bitcode[pos]);
|
||||
}
|
||||
//Encode ACs
|
||||
var end0pos = 63; // was const... which is crazy
|
||||
for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};
|
||||
//end0pos = first element in reverse order !=0
|
||||
if ( end0pos == 0) {
|
||||
writeBits(EOB);
|
||||
return DC;
|
||||
}
|
||||
var i = 1;
|
||||
var lng;
|
||||
while ( i <= end0pos ) {
|
||||
var startpos = i;
|
||||
for (; (DU[i]==0) && (i<=end0pos); ++i) {}
|
||||
var nrzeroes = i-startpos;
|
||||
if ( nrzeroes >= I16 ) {
|
||||
lng = nrzeroes>>4;
|
||||
for (var nrmarker=1; nrmarker <= lng; ++nrmarker)
|
||||
writeBits(M16zeroes);
|
||||
nrzeroes = nrzeroes&0xF;
|
||||
}
|
||||
pos = 32767+DU[i];
|
||||
writeBits(HTAC[(nrzeroes<<4)+category[pos]]);
|
||||
writeBits(bitcode[pos]);
|
||||
i++;
|
||||
}
|
||||
if ( end0pos != I63 ) {
|
||||
writeBits(EOB);
|
||||
}
|
||||
return DC;
|
||||
}
|
||||
|
||||
function initCharLookupTable(){
|
||||
var sfcc = String.fromCharCode;
|
||||
for(var i=0; i < 256; i++){ ///// ACHTUNG // 255
|
||||
clt[i] = sfcc(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes ImageData to JPEG.
|
||||
*
|
||||
* @param {ImageData} image
|
||||
* @param {number=} opt_quality The compression quality.
|
||||
* @return {string} base64-encoded JPEG data.
|
||||
*/
|
||||
this.encode = function(image,opt_quality) // image data object
|
||||
{
|
||||
if(opt_quality) setQuality(opt_quality);
|
||||
|
||||
// Initialize bit writer
|
||||
byteout = new Array();
|
||||
bytenew=0;
|
||||
bytepos=7;
|
||||
|
||||
// Add JPEG headers
|
||||
writeWord(0xFFD8); // SOI
|
||||
writeAPP0();
|
||||
writeDQT();
|
||||
writeSOF0(image.width,image.height);
|
||||
writeDHT();
|
||||
writeSOS();
|
||||
|
||||
|
||||
// Encode 8x8 macroblocks
|
||||
var _DCY=0;
|
||||
var _DCU=0;
|
||||
var _DCV=0;
|
||||
|
||||
bytenew=0;
|
||||
bytepos=7;
|
||||
|
||||
|
||||
this.encode.displayName = "_encode_";
|
||||
|
||||
var imageData = image.data;
|
||||
var width = image.width;
|
||||
var height = image.height;
|
||||
|
||||
var quadWidth = width*4;
|
||||
var tripleWidth = width*3;
|
||||
|
||||
var x, y = 0;
|
||||
var r, g, b;
|
||||
var start,p, col,row,pos;
|
||||
while(y < height){
|
||||
x = 0;
|
||||
while(x < quadWidth){
|
||||
start = quadWidth * y + x;
|
||||
p = start;
|
||||
col = -1;
|
||||
row = 0;
|
||||
|
||||
for(pos=0; pos < 64; pos++){
|
||||
row = pos >> 3;// /8
|
||||
col = ( pos & 7 ) * 4; // %8
|
||||
p = start + ( row * quadWidth ) + col;
|
||||
|
||||
if(y+row >= height){ // padding bottom
|
||||
p-= (quadWidth*(y+1+row-height));
|
||||
}
|
||||
|
||||
if(x+col >= quadWidth){ // padding right
|
||||
p-= ((x+col) - quadWidth +4)
|
||||
}
|
||||
|
||||
r = imageData[ p++ ];
|
||||
g = imageData[ p++ ];
|
||||
b = imageData[ p++ ];
|
||||
|
||||
|
||||
/* // calculate YUV values dynamically
|
||||
YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
|
||||
UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
|
||||
VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
|
||||
*/
|
||||
|
||||
// use lookup table (slightly faster)
|
||||
YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256)>>0] + RGB_YUV_TABLE[(b + 512)>>0]) >> 16)-128;
|
||||
UDU[pos] = ((RGB_YUV_TABLE[(r + 768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;
|
||||
VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;
|
||||
|
||||
}
|
||||
|
||||
_DCY = processDU(YDU, fdtbl_Y, _DCY, YDC_HT, YAC_HT);
|
||||
_DCU = processDU(UDU, fdtbl_UV, _DCU, UVDC_HT, UVAC_HT);
|
||||
_DCV = processDU(VDU, fdtbl_UV, _DCV, UVDC_HT, UVAC_HT);
|
||||
x+=32;
|
||||
}
|
||||
y+=8;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Do the bit alignment of the EOI marker
|
||||
if ( bytepos >= 0 ) {
|
||||
var fillbits = [];
|
||||
fillbits[1] = bytepos+1;
|
||||
fillbits[0] = (1<<(bytepos+1))-1;
|
||||
writeBits(fillbits);
|
||||
}
|
||||
|
||||
writeWord(0xFFD9); //EOI
|
||||
|
||||
var jpegDataUri = 'data:image/jpeg;base64,'
|
||||
+ goog.crypt.base64.encodeString(byteout.join(''));
|
||||
|
||||
byteout = [];
|
||||
|
||||
return jpegDataUri
|
||||
}
|
||||
|
||||
function setQuality(quality){
|
||||
if (quality <= 0) {
|
||||
quality = 1;
|
||||
}
|
||||
if (quality > 100) {
|
||||
quality = 100;
|
||||
}
|
||||
|
||||
if(currentQuality == quality) return // don't recalc if unchanged
|
||||
|
||||
var sf = 0;
|
||||
if (quality < 50) {
|
||||
sf = Math.floor(5000 / quality);
|
||||
} else {
|
||||
sf = Math.floor(200 - quality*2);
|
||||
}
|
||||
|
||||
initQuantTables(sf);
|
||||
currentQuality = quality;
|
||||
}
|
||||
|
||||
function init(){
|
||||
if(!opt_quality) opt_quality = 50;
|
||||
// Create tables
|
||||
initCharLookupTable()
|
||||
initHuffmanTbl();
|
||||
initCategoryNumber();
|
||||
initRGBYUVTable();
|
||||
|
||||
setQuality(opt_quality);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
};
|
||||
712
nicer-api-docs/closure-library/third_party/closure/goog/loremipsum/text/loremipsum.js
vendored
Normal file
712
nicer-api-docs/closure-library/third_party/closure/goog/loremipsum/text/loremipsum.js
vendored
Normal file
@@ -0,0 +1,712 @@
|
||||
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
/**
|
||||
* @fileoverview A generator of lorem ipsum text based on the python
|
||||
* implementation at http://code.google.com/p/lorem-ipsum-generator/.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.text.LoremIpsum');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.structs.Map');
|
||||
goog.require('goog.structs.Set');
|
||||
|
||||
|
||||
/**
|
||||
* Generates random strings of "lorem ipsum" text, based on the word
|
||||
* distribution of a sample text, using the words in a dictionary.
|
||||
* @constructor
|
||||
*/
|
||||
goog.text.LoremIpsum = function() {
|
||||
this.generateChains_(this.sample_);
|
||||
this.generateStatistics_(this.sample_);
|
||||
|
||||
this.initializeDictionary_(this.dictionary_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Delimiters that end sentences.
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.DELIMITERS_SENTENCES_ = ['.', '?', '!'];
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for spliting a text into sentences.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_ = /[\.\?\!]/;
|
||||
|
||||
|
||||
/**
|
||||
* Delimiters that end words.
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.DELIMITERS_WORDS_ = [',', '.', '?', '!'];
|
||||
|
||||
|
||||
/**
|
||||
* Regular expression for spliting text into words.
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.WORD_SPLIT_REGEX_ = /\s/;
|
||||
|
||||
|
||||
/**
|
||||
* Words that can be used in the generated output.
|
||||
* Maps a word-length to a list of words of that length.
|
||||
* @type {goog.structs.Map}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.words_;
|
||||
|
||||
|
||||
/**
|
||||
* Chains of three words that appear in the sample text
|
||||
* Maps a pair of word-lengths to a third word-length and an optional
|
||||
* piece of trailing punctuation (for example, a period, comma, etc.).
|
||||
* @type {goog.structs.Map}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.chains_;
|
||||
|
||||
|
||||
/**
|
||||
* Pairs of word-lengths that can appear at the beginning of sentences.
|
||||
* @type {Array}
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.starts_;
|
||||
|
||||
|
||||
/**
|
||||
* Averange sentence length in words.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.sentenceMean_;
|
||||
|
||||
|
||||
/**
|
||||
* Sigma (sqrt of variance) for the sentence length in words.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.sentenceSigma_;
|
||||
|
||||
|
||||
/**
|
||||
* Averange paragraph length in sentences.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.paragraphMean_;
|
||||
|
||||
|
||||
/**
|
||||
* Sigma (sqrt of variance) for the paragraph length in sentences.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.paragraphSigma_;
|
||||
|
||||
|
||||
/**
|
||||
* Generates the chains and starts values required for sentence generation.
|
||||
* @param {string} sample The same text.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateChains_ = function(sample) {
|
||||
var words = goog.text.LoremIpsum.splitWords_(sample);
|
||||
var wordInfo = goog.array.map(words, goog.text.LoremIpsum.getWordInfo_);
|
||||
|
||||
var previous = [0, 0];
|
||||
var previousKey = previous.join('-');
|
||||
var chains = new goog.structs.Map();
|
||||
var starts = [previousKey];
|
||||
var chainKeys = {};
|
||||
|
||||
goog.array.forEach(wordInfo, function(pair) {
|
||||
var chain = chains.get(previousKey);
|
||||
if (chain) {
|
||||
chain.push(pair);
|
||||
} else {
|
||||
chain = [pair];
|
||||
chains.set(previousKey, chain);
|
||||
}
|
||||
|
||||
if (goog.array.contains(
|
||||
goog.text.LoremIpsum.DELIMITERS_SENTENCES_, pair[1])) {
|
||||
starts.push(previousKey);
|
||||
}
|
||||
chainKeys[previousKey] = previous;
|
||||
previous = [previous[1], pair[0]];
|
||||
previousKey = previous.join('-');
|
||||
});
|
||||
|
||||
if (chains.getCount() > 0) {
|
||||
this.chains_ = chains;
|
||||
this.starts_ = starts;
|
||||
this.chainKeys_ = chainKeys;
|
||||
} else {
|
||||
throw Error('Could not generate chains from sample text.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the mean and standard deviation of sentence and paragraph lengths.
|
||||
* @param {string} sample The same text.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateStatistics_ = function(sample) {
|
||||
this.generateSentenceStatistics_(sample);
|
||||
this.generateParagraphStatistics_(sample);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the mean and standard deviation of the lengths of sentences
|
||||
* (in words) in a sample text.
|
||||
* @param {string} sample The same text.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateSentenceStatistics_ = function(sample) {
|
||||
var sentences = goog.array.filter(
|
||||
goog.text.LoremIpsum.splitSentences_(sample),
|
||||
goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
|
||||
|
||||
var sentenceLengths = goog.array.map(
|
||||
goog.array.map(sentences, goog.text.LoremIpsum.splitWords_),
|
||||
goog.text.LoremIpsum.arrayLength_);
|
||||
this.sentenceMean_ = goog.math.average.apply(null, sentenceLengths);
|
||||
this.sentenceSigma_ = goog.math.standardDeviation.apply(
|
||||
null, sentenceLengths);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the mean and standard deviation of the lengths of paragraphs
|
||||
* (in sentences) in a sample text.
|
||||
* @param {string} sample The same text.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateParagraphStatistics_ = function(sample) {
|
||||
var paragraphs = goog.array.filter(
|
||||
goog.text.LoremIpsum.splitParagraphs_(sample),
|
||||
goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
|
||||
|
||||
var paragraphLengths = goog.array.map(
|
||||
goog.array.map(paragraphs, goog.text.LoremIpsum.splitSentences_),
|
||||
goog.text.LoremIpsum.arrayLength_);
|
||||
|
||||
this.paragraphMean_ = goog.math.average.apply(null, paragraphLengths);
|
||||
this.paragraphSigma_ = goog.math.standardDeviation.apply(
|
||||
null, paragraphLengths);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the generator to use a given selection of words for generating
|
||||
* sentences with.
|
||||
* @param {string} dictionary The dictionary to use.
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.initializeDictionary_ = function(dictionary) {
|
||||
var dictionaryWords = goog.text.LoremIpsum.splitWords_(dictionary);
|
||||
|
||||
var words = new goog.structs.Map();
|
||||
goog.array.forEach(dictionaryWords, function(word) {
|
||||
var set = words.get(word.length);
|
||||
if (!set) {
|
||||
set = new goog.structs.Set();
|
||||
words.set(word.length, set);
|
||||
}
|
||||
set.add(word);
|
||||
});
|
||||
|
||||
this.words_ = words;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Picks a random starting chain.
|
||||
* @return {Array.<string>} The starting key.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.chooseRandomStart_ = function() {
|
||||
var key = goog.text.LoremIpsum.randomChoice_(this.starts_);
|
||||
return this.chainKeys_[key];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a single sentence, of random length.
|
||||
* @param {boolean} opt_startWithLorem Whether to start the setnence with the
|
||||
* standard "Lorem ipsum..." first sentence.
|
||||
* @return {string} The generated sentence.
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateSentence = function(opt_startWithLorem) {
|
||||
if (this.chains_.getCount() == 0 || this.starts_.length == 0) {
|
||||
throw Error('No chains created');
|
||||
}
|
||||
|
||||
if (this.words_.getCount() == 0) {
|
||||
throw Error('No dictionary');
|
||||
}
|
||||
|
||||
// The length of the sentence is a normally distributed random variable.
|
||||
var sentenceLength = goog.text.LoremIpsum.randomNormal_(
|
||||
this.sentenceMean_, this.sentenceSigma_)
|
||||
sentenceLength = Math.max(Math.floor(sentenceLength), 1);
|
||||
|
||||
var wordDelimiter = ''; // Defined here in case while loop doesn't run
|
||||
|
||||
// Start the sentence with "Lorem ipsum...", if desired
|
||||
var sentence;
|
||||
if (opt_startWithLorem) {
|
||||
var lorem = 'lorem ipsum dolor sit amet, consecteteur adipiscing elit';
|
||||
sentence = goog.text.LoremIpsum.splitWords_(lorem);
|
||||
if (sentence.length > sentenceLength) {
|
||||
sentence.length = sentenceLength;
|
||||
}
|
||||
var lastWord = sentence[sentence.length - 1];
|
||||
var lastChar = lastWord.substring(lastWord.length - 1);
|
||||
if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_WORDS_, lastChar)) {
|
||||
wordDelimiter = lastChar;
|
||||
}
|
||||
} else {
|
||||
sentence = [];
|
||||
}
|
||||
|
||||
var previous = [];
|
||||
var previousKey = '';
|
||||
// Generate a sentence from the "chains"
|
||||
while (sentence.length < sentenceLength) {
|
||||
// If the current starting point is invalid, choose another randomly
|
||||
if (!this.chains_.containsKey(previousKey)) {
|
||||
previous = this.chooseRandomStart_();
|
||||
previousKey = previous.join('-');
|
||||
}
|
||||
|
||||
// Choose the next "chain" to go to. This determines the next word
|
||||
// length we'll use, and whether there is e.g. a comma at the end of
|
||||
// the word.
|
||||
var chain = /** @type {Array} */ (goog.text.LoremIpsum.randomChoice_(
|
||||
/** @type {Array} */ (this.chains_.get(previousKey))));
|
||||
var wordLength = chain[0];
|
||||
|
||||
// If the word delimiter contained in the chain is also a sentence
|
||||
// delimiter, then we don't include it because we don't want the
|
||||
// sentence to end prematurely (we want the length to match the
|
||||
// sentence_length value).
|
||||
//debugger;
|
||||
if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_SENTENCES_,
|
||||
chain[1])) {
|
||||
wordDelimiter = '';
|
||||
} else {
|
||||
wordDelimiter = chain[1];
|
||||
}
|
||||
|
||||
// Choose a word randomly that matches (or closely matches) the
|
||||
// length we're after.
|
||||
var closestLength = goog.text.LoremIpsum.chooseClosest(
|
||||
this.words_.getKeys(), wordLength);
|
||||
var word = goog.text.LoremIpsum.randomChoice_(
|
||||
this.words_.get(closestLength).getValues());
|
||||
|
||||
sentence.push(word + wordDelimiter);
|
||||
previous = [previous[1], wordLength];
|
||||
previousKey = previous.join('-');
|
||||
}
|
||||
|
||||
// Finish the sentence off with capitalisation, a period and
|
||||
// form it into a string
|
||||
sentence = sentence.join(' ');
|
||||
sentence = sentence.slice(0, 1).toUpperCase() + sentence.slice(1);
|
||||
if (sentence.substring(sentence.length - 1) == wordDelimiter) {
|
||||
sentence = sentence.slice(0, sentence.length - 1);
|
||||
}
|
||||
return sentence + '.';
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a single lorem ipsum paragraph, of random length.
|
||||
* @param {boolean} opt_startWithLorem Whether to start the sentence with the
|
||||
* standard "Lorem ipsum..." first sentence.
|
||||
* @return {string} The generated sentence.
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.generateParagraph = function(
|
||||
opt_startWithLorem) {
|
||||
// The length of the paragraph is a normally distributed random variable.
|
||||
var paragraphLength = goog.text.LoremIpsum.randomNormal_(
|
||||
this.paragraphMean_, this.paragraphSigma_);
|
||||
paragraphLength = Math.max(Math.floor(paragraphLength), 1);
|
||||
|
||||
// Construct a paragraph from a number of sentences.
|
||||
var paragraph = []
|
||||
var startWithLorem = opt_startWithLorem;
|
||||
while (paragraph.length < paragraphLength) {
|
||||
var sentence = this.generateSentence(startWithLorem);
|
||||
paragraph.push(sentence);
|
||||
startWithLorem = false;
|
||||
}
|
||||
|
||||
// Form the paragraph into a string.
|
||||
paragraph = paragraph.join(' ')
|
||||
return paragraph
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Splits a piece of text into paragraphs.
|
||||
* @param {string} text The text to split.
|
||||
* @return {Array.<string>} An array of paragraphs.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.splitParagraphs_ = function(text) {
|
||||
return text.split('\n')
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Splits a piece of text into sentences.
|
||||
* @param {string} text The text to split.
|
||||
* @return {Array.<string>} An array of sentences.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.splitSentences_ = function(text) {
|
||||
return goog.array.filter(
|
||||
text.split(goog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_),
|
||||
goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Splits a piece of text into words..
|
||||
* @param {string} text The text to split.
|
||||
* @return {Array.<string>} An array of words.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.splitWords_ = function(text) {
|
||||
return goog.array.filter(
|
||||
text.split(goog.text.LoremIpsum.WORD_SPLIT_REGEX_),
|
||||
goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the text is not empty or just whitespace.
|
||||
* @param {string} text The text to check.
|
||||
* @return {boolean} Whether the text is nether empty nor whitespace.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.isNotEmptyOrWhitepace_ = function(text) {
|
||||
return goog.string.trim(text).length > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the length of an array. Written as a function so it can be used
|
||||
* as a function parameter.
|
||||
* @param {Array} array The array to check.
|
||||
* @return {number} The length of the array.
|
||||
*/
|
||||
goog.text.LoremIpsum.arrayLength_ = function(array) {
|
||||
return array.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find the number in the list of values that is closest to the target.
|
||||
* @param {Array.<number>} values The values.
|
||||
* @param {number} target The target value.
|
||||
* @return {number} The closest value.
|
||||
*/
|
||||
goog.text.LoremIpsum.chooseClosest = function(values, target) {
|
||||
var closest = values[0];
|
||||
goog.array.forEach(values, function(value) {
|
||||
if (Math.abs(target - value) < Math.abs(target - closest)) {
|
||||
closest = value;
|
||||
}
|
||||
});
|
||||
|
||||
return closest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets info about a word used as part of the lorem ipsum algorithm.
|
||||
* @param {string} word The word to check.
|
||||
* @return {Array} A two element array. The first element is the size of the
|
||||
* word. The second element is the delimter used in the word.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.getWordInfo_ = function(word) {
|
||||
var ret;
|
||||
goog.array.some(goog.text.LoremIpsum.DELIMITERS_WORDS_,
|
||||
function (delimiter) {
|
||||
if (goog.string.endsWith(word, delimiter)) {
|
||||
ret = [word.length - delimiter.length, delimiter];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
return ret || [word.length, ''];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constant used for {@link #randomNormal_}.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.NV_MAGICCONST_ = 4 * Math.exp(-0.5) / Math.sqrt(2.0);
|
||||
|
||||
|
||||
/**
|
||||
* Generates a random number for a normal distribution with the specified
|
||||
* mean and sigma.
|
||||
* @param {number} mu The mean of the distribution.
|
||||
* @param {number} sigma The sigma of the distribution.
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.randomNormal_ = function(mu, sigma) {
|
||||
while (true) {
|
||||
var u1 = Math.random();
|
||||
var u2 = 1.0 - Math.random();
|
||||
var z = goog.text.LoremIpsum.NV_MAGICCONST_ * (u1 - 0.5) / u2;
|
||||
var zz = z * z / 4.0;
|
||||
if (zz <= -Math.log(u2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mu + z * sigma;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Picks a random element of the array.
|
||||
* @param {Array} array The array to pick from.
|
||||
* @return {*} An element from the array.
|
||||
*/
|
||||
goog.text.LoremIpsum.randomChoice_ = function(array) {
|
||||
return array[goog.math.randomInt(array.length)];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dictionary of words for lorem ipsum.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.DICT_ =
|
||||
'a ac accumsan ad adipiscing aenean aliquam aliquet amet ante ' +
|
||||
'aptent arcu at auctor augue bibendum blandit class commodo ' +
|
||||
'condimentum congue consectetuer consequat conubia convallis cras ' +
|
||||
'cubilia cum curabitur curae cursus dapibus diam dictum dictumst ' +
|
||||
'dignissim dis dolor donec dui duis egestas eget eleifend elementum ' +
|
||||
'elit eni enim erat eros est et etiam eu euismod facilisi facilisis ' +
|
||||
'fames faucibus felis fermentum feugiat fringilla fusce gravida ' +
|
||||
'habitant habitasse hac hendrerit hymenaeos iaculis id imperdiet ' +
|
||||
'in inceptos integer interdum ipsum justo lacinia lacus laoreet ' +
|
||||
'lectus leo libero ligula litora lobortis lorem luctus maecenas ' +
|
||||
'magna magnis malesuada massa mattis mauris metus mi molestie ' +
|
||||
'mollis montes morbi mus nam nascetur natoque nec neque netus ' +
|
||||
'nibh nisi nisl non nonummy nostra nulla nullam nunc odio orci ' +
|
||||
'ornare parturient pede pellentesque penatibus per pharetra ' +
|
||||
'phasellus placerat platea porta porttitor posuere potenti praesent ' +
|
||||
'pretium primis proin pulvinar purus quam quis quisque rhoncus ' +
|
||||
'ridiculus risus rutrum sagittis sapien scelerisque sed sem semper ' +
|
||||
'senectus sit sociis sociosqu sodales sollicitudin suscipit ' +
|
||||
'suspendisse taciti tellus tempor tempus tincidunt torquent tortor ' +
|
||||
'tristique turpis ullamcorper ultrices ultricies urna ut varius ve ' +
|
||||
'vehicula vel velit venenatis vestibulum vitae vivamus viverra ' +
|
||||
'volutpat vulputate';
|
||||
|
||||
|
||||
/**
|
||||
* A sample to use for generating the distribution of word and sentence lengths
|
||||
* in lorem ipsum.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
goog.text.LoremIpsum.SAMPLE_ =
|
||||
'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean ' +
|
||||
'commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus ' +
|
||||
'et magnis dis parturient montes, nascetur ridiculus mus. Donec quam ' +
|
||||
'felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla ' +
|
||||
'consequat massa quis enim. Donec pede justo, fringilla vel, aliquet ' +
|
||||
'nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, ' +
|
||||
'venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. ' +
|
||||
'Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean ' +
|
||||
'vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat ' +
|
||||
'vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra ' +
|
||||
'quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius ' +
|
||||
'laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel ' +
|
||||
'augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.\n\n' +
|
||||
|
||||
'Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem ' +
|
||||
'quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam ' +
|
||||
'nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec ' +
|
||||
'odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis ' +
|
||||
'faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus ' +
|
||||
'tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales ' +
|
||||
'sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit ' +
|
||||
'cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend ' +
|
||||
'sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, ' +
|
||||
'metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis ' +
|
||||
'hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci ' +
|
||||
'luctus et ultrices posuere cubilia Curae; In ac dui quis mi ' +
|
||||
'consectetuer lacinia.\n\n' +
|
||||
|
||||
'Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet ' +
|
||||
'nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ' +
|
||||
'ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent ' +
|
||||
'adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy ' +
|
||||
'metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros ' +
|
||||
'et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, ' +
|
||||
'nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit ' +
|
||||
'risus. Phasellus nec sem in justo pellentesque facilisis. Etiam ' +
|
||||
'imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus ' +
|
||||
'non, auctor et, hendrerit quis, nisi.\n\n' +
|
||||
|
||||
'Curabitur ligula sapien, tincidunt non, euismod vitae, posuere ' +
|
||||
'imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed ' +
|
||||
'cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus ' +
|
||||
'accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci ' +
|
||||
'luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis ' +
|
||||
'porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis ' +
|
||||
'orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, ' +
|
||||
'bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede ' +
|
||||
'sit amet augue. In turpis. Pellentesque posuere. Praesent turpis.\n\n' +
|
||||
|
||||
'Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu ' +
|
||||
'sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales ' +
|
||||
'nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse ' +
|
||||
'pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, ' +
|
||||
'nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in ' +
|
||||
'faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id ' +
|
||||
'purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum ' +
|
||||
'mollis diam. Pellentesque ut neque. Pellentesque habitant morbi ' +
|
||||
'tristique senectus et netus et malesuada fames ac turpis egestas.\n\n' +
|
||||
|
||||
'In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac ' +
|
||||
'felis quis tortor malesuada pretium. Pellentesque auctor neque nec ' +
|
||||
'urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean ' +
|
||||
'viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et ' +
|
||||
'netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis ' +
|
||||
'pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna.\n\n' +
|
||||
|
||||
'In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare ' +
|
||||
'lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ' +
|
||||
'ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. ' +
|
||||
'Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, ' +
|
||||
'quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at ' +
|
||||
'pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo ' +
|
||||
'quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam ' +
|
||||
'sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce ' +
|
||||
'risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis ' +
|
||||
'vulputate lorem.\n\n' +
|
||||
|
||||
'Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, ' +
|
||||
'dui et placerat feugiat, eros pede varius nisi, condimentum viverra ' +
|
||||
'felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, ' +
|
||||
'varius ut, felis. In auctor lobortis lacus. Quisque libero metus, ' +
|
||||
'condimentum nec, tempor a, commodo mollis, magna. Vestibulum ' +
|
||||
'ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia ' +
|
||||
'erat. Praesent blandit laoreet nibh.\n\n' +
|
||||
|
||||
'Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, ' +
|
||||
'neque sit amet convallis pulvinar, justo nulla eleifend augue, ac ' +
|
||||
'auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. ' +
|
||||
'Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. ' +
|
||||
'Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In ' +
|
||||
'hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis ' +
|
||||
'mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat ' +
|
||||
'nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, ' +
|
||||
'lacus.\n\n' +
|
||||
|
||||
'Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, ' +
|
||||
'dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi ' +
|
||||
'congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin ' +
|
||||
'fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit ' +
|
||||
'amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam ' +
|
||||
'gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac ' +
|
||||
'sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus ' +
|
||||
'blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in ' +
|
||||
'libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In ' +
|
||||
'consectetuer turpis ut velit. Nulla sit amet est. Praesent metus ' +
|
||||
'tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ' +
|
||||
'ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse ' +
|
||||
'feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum ' +
|
||||
'nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac ' +
|
||||
'massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, ' +
|
||||
'iaculis quis, molestie non, velit.\n\n' +
|
||||
|
||||
'Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. ' +
|
||||
'Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus ' +
|
||||
'at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet ' +
|
||||
'velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. ' +
|
||||
'Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, ' +
|
||||
'sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla ' +
|
||||
'facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere ' +
|
||||
'iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. ' +
|
||||
'Curabitur suscipit suscipit tellus.\n\n' +
|
||||
|
||||
'Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id ' +
|
||||
'nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu ' +
|
||||
'pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante ' +
|
||||
'odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque ' +
|
||||
'suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ' +
|
||||
'ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu ' +
|
||||
'quis ligula mattis placerat. Duis lobortis massa imperdiet quam. ' +
|
||||
'Suspendisse potenti.\n\n' +
|
||||
|
||||
'Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, ' +
|
||||
'lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat ' +
|
||||
'volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam ' +
|
||||
'eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ' +
|
||||
'ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta ' +
|
||||
'dolor. Class aptent taciti sociosqu ad litora torquent per conubia ' +
|
||||
'nostra, per inceptos hymenaeos.\n\n' +
|
||||
|
||||
'Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. ' +
|
||||
'Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. ' +
|
||||
'Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, ' +
|
||||
'elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum ' +
|
||||
'sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus ' +
|
||||
'non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. ' +
|
||||
'Vestibulum eu odio.\n\n' +
|
||||
|
||||
'Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. ' +
|
||||
'Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique ' +
|
||||
'sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse ' +
|
||||
'faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, ' +
|
||||
'vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce ' +
|
||||
'fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae ' +
|
||||
'odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. ' +
|
||||
'Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus ' +
|
||||
'consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna ' +
|
||||
'cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit ' +
|
||||
'quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar ' +
|
||||
'varius.\n\n';
|
||||
|
||||
/**
|
||||
* Sample that the generated text is based on .
|
||||
* @type {string}
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.sample_ = goog.text.LoremIpsum.SAMPLE_;
|
||||
|
||||
|
||||
/**
|
||||
* Dictionary of words.
|
||||
* @type {string}
|
||||
*/
|
||||
goog.text.LoremIpsum.prototype.dictionary_ = goog.text.LoremIpsum.DICT_;
|
||||
764
nicer-api-docs/closure-library/third_party/closure/goog/mochikit/async/deferred.js
vendored
Normal file
764
nicer-api-docs/closure-library/third_party/closure/goog/mochikit/async/deferred.js
vendored
Normal file
@@ -0,0 +1,764 @@
|
||||
// Copyright 2007 Bob Ippolito. All Rights Reserved.
|
||||
// Modifications Copyright 2009 The Closure Library Authors. All Rights
|
||||
// Reserved.
|
||||
|
||||
/**
|
||||
* @license Portions of this code are from MochiKit, received by
|
||||
* The Closure Authors under the MIT license. All other code is Copyright
|
||||
* 2005-2009 The Closure Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Classes for tracking asynchronous operations and handling the
|
||||
* results. The Deferred object here is patterned after the Deferred object in
|
||||
* the Twisted python networking framework.
|
||||
*
|
||||
* See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
|
||||
*
|
||||
* Based on the Dojo code which in turn is based on the MochiKit code.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.Deferred');
|
||||
goog.provide('goog.async.Deferred.AlreadyCalledError');
|
||||
goog.provide('goog.async.Deferred.CanceledError');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.Error');
|
||||
goog.require('goog.functions');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Deferred represents the result of an asynchronous operation. A Deferred
|
||||
* instance has no result when it is created, and is "fired" (given an initial
|
||||
* result) by calling {@code callback} or {@code errback}.
|
||||
*
|
||||
* Once fired, the result is passed through a sequence of callback functions
|
||||
* registered with {@code addCallback} or {@code addErrback}. The functions may
|
||||
* mutate the result before it is passed to the next function in the sequence.
|
||||
*
|
||||
* Callbacks and errbacks may be added at any time, including after the Deferred
|
||||
* has been "fired". If there are no pending actions in the execution sequence
|
||||
* of a fired Deferred, any new callback functions will be called with the last
|
||||
* computed result. Adding a callback function is the only way to access the
|
||||
* result of the Deferred.
|
||||
*
|
||||
* If a Deferred operation is canceled, an optional user-provided cancellation
|
||||
* function is invoked which may perform any special cleanup, followed by firing
|
||||
* the Deferred's errback sequence with a {@code CanceledError}. If the
|
||||
* Deferred has already fired, cancellation is ignored.
|
||||
*
|
||||
* @param {Function=} opt_onCancelFunction A function that will be called if the
|
||||
* Deferred is canceled. If provided, this function runs before the
|
||||
* Deferred is fired with a {@code CanceledError}.
|
||||
* @param {Object=} opt_defaultScope The default object context to call
|
||||
* callbacks and errbacks in.
|
||||
* @constructor
|
||||
*/
|
||||
goog.async.Deferred = function(opt_onCancelFunction, opt_defaultScope) {
|
||||
/**
|
||||
* Entries in the sequence are arrays containing a callback, an errback, and
|
||||
* an optional scope. The callback or errback in an entry may be null.
|
||||
* @type {!Array.<!Array>}
|
||||
* @private
|
||||
*/
|
||||
this.sequence_ = [];
|
||||
|
||||
/**
|
||||
* Optional function that will be called if the Deferred is canceled.
|
||||
* @type {Function|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.onCancelFunction_ = opt_onCancelFunction;
|
||||
|
||||
/**
|
||||
* The default scope to execute callbacks and errbacks in.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
this.defaultScope_ = opt_defaultScope || null;
|
||||
|
||||
if (goog.async.Deferred.LONG_STACK_TRACES) {
|
||||
/**
|
||||
* Holds the stack trace at time of deferred creation if the JS engine
|
||||
* provides the Error.captureStackTrace API.
|
||||
* @private {?string}
|
||||
*/
|
||||
this.constructorStack_ = null;
|
||||
if (Error.captureStackTrace) {
|
||||
var target = { stack: '' };
|
||||
Error.captureStackTrace(target, goog.async.Deferred);
|
||||
// Check if Error.captureStackTrace worked. It fails in gjstest.
|
||||
if (typeof target.stack == 'string') {
|
||||
// Remove first line and force stringify to prevent memory leak due to
|
||||
// holding on to actual stack frames.
|
||||
this.constructorStack_ = target.stack.replace(/^[^\n]*\n/, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the Deferred has been fired.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.fired_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the last result in the execution sequence was an error.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.hadError_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* The current Deferred result, updated as callbacks and errbacks are executed.
|
||||
* @type {*}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.result_;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the Deferred is blocked waiting on another Deferred to fire. If a
|
||||
* callback or errback returns a Deferred as a result, the execution sequence is
|
||||
* blocked until that Deferred result becomes available.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.blocked_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether this Deferred is blocking execution of another Deferred. If this
|
||||
* instance was returned as a result in another Deferred's execution sequence,
|
||||
* that other Deferred becomes blocked until this instance's execution sequence
|
||||
* completes. No additional callbacks may be added to a Deferred once it
|
||||
* is blocking another instance.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.blocking_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the Deferred has been canceled without having a custom cancel
|
||||
* function.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.silentlyCanceled_ = false;
|
||||
|
||||
|
||||
/**
|
||||
* If an error is thrown during Deferred execution with no errback to catch it,
|
||||
* the error is rethrown after a timeout. Reporting the error after a timeout
|
||||
* allows execution to continue in the calling context.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.unhandledExceptionTimeoutId_;
|
||||
|
||||
|
||||
/**
|
||||
* If this Deferred was created by branch(), this will be the "parent" Deferred.
|
||||
* @type {goog.async.Deferred}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.parent_;
|
||||
|
||||
|
||||
/**
|
||||
* The number of Deferred objects that have been branched off this one. This
|
||||
* will be decremented whenever a branch is fired or canceled.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.branches_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether unhandled errors should always get rethrown to the
|
||||
* global scope. Defaults to the value of goog.DEBUG.
|
||||
*/
|
||||
goog.define('goog.async.Deferred.STRICT_ERRORS', false);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to attempt to make stack traces long. Defaults to
|
||||
* the value of goog.DEBUG.
|
||||
*/
|
||||
goog.define('goog.async.Deferred.LONG_STACK_TRACES', goog.DEBUG);
|
||||
|
||||
|
||||
/**
|
||||
* Cancels a Deferred that has not yet been fired, or is blocked on another
|
||||
* deferred operation. If this Deferred is waiting for a blocking Deferred to
|
||||
* fire, the blocking Deferred will also be canceled.
|
||||
*
|
||||
* If this Deferred was created by calling branch() on a parent Deferred with
|
||||
* opt_propagateCancel set to true, the parent may also be canceled. If
|
||||
* opt_deepCancel is set, cancel() will be called on the parent (as well as any
|
||||
* other ancestors if the parent is also a branch). If one or more branches were
|
||||
* created with opt_propagateCancel set to true, the parent will be canceled if
|
||||
* cancel() is called on all of those branches.
|
||||
*
|
||||
* @param {boolean=} opt_deepCancel If true, cancels this Deferred's parent even
|
||||
* if cancel() hasn't been called on some of the parent's branches. Has no
|
||||
* effect on a branch without opt_propagateCancel set to true.
|
||||
*/
|
||||
goog.async.Deferred.prototype.cancel = function(opt_deepCancel) {
|
||||
if (!this.hasFired()) {
|
||||
if (this.parent_) {
|
||||
// Get rid of the parent reference before potentially running the parent's
|
||||
// canceler function to ensure that this cancellation isn't
|
||||
// double-counted.
|
||||
var parent = this.parent_;
|
||||
delete this.parent_;
|
||||
if (opt_deepCancel) {
|
||||
parent.cancel(opt_deepCancel);
|
||||
} else {
|
||||
parent.branchCancel_();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.onCancelFunction_) {
|
||||
// Call in user-specified scope.
|
||||
this.onCancelFunction_.call(this.defaultScope_, this);
|
||||
} else {
|
||||
this.silentlyCanceled_ = true;
|
||||
}
|
||||
if (!this.hasFired()) {
|
||||
this.errback(new goog.async.Deferred.CanceledError(this));
|
||||
}
|
||||
} else if (this.result_ instanceof goog.async.Deferred) {
|
||||
this.result_.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle a single branch being canceled. Once all branches are canceled, this
|
||||
* Deferred will be canceled as well.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.branchCancel_ = function() {
|
||||
this.branches_--;
|
||||
if (this.branches_ <= 0) {
|
||||
this.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called after a blocking Deferred fires. Unblocks this Deferred and resumes
|
||||
* its execution sequence.
|
||||
*
|
||||
* @param {boolean} isSuccess Whether the result is a success or an error.
|
||||
* @param {*} res The result of the blocking Deferred.
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.continue_ = function(isSuccess, res) {
|
||||
this.blocked_ = false;
|
||||
this.updateResult_(isSuccess, res);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates the current result based on the success or failure of the last action
|
||||
* in the execution sequence.
|
||||
*
|
||||
* @param {boolean} isSuccess Whether the new result is a success or an error.
|
||||
* @param {*} res The result.
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.updateResult_ = function(isSuccess, res) {
|
||||
this.fired_ = true;
|
||||
this.result_ = res;
|
||||
this.hadError_ = !isSuccess;
|
||||
this.fire_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the Deferred has not yet been fired.
|
||||
*
|
||||
* @private
|
||||
* @throws {Error} If this has already been fired.
|
||||
*/
|
||||
goog.async.Deferred.prototype.check_ = function() {
|
||||
if (this.hasFired()) {
|
||||
if (!this.silentlyCanceled_) {
|
||||
throw new goog.async.Deferred.AlreadyCalledError(this);
|
||||
}
|
||||
this.silentlyCanceled_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fire the execution sequence for this Deferred by passing the starting result
|
||||
* to the first registered callback.
|
||||
* @param {*=} opt_result The starting result.
|
||||
*/
|
||||
goog.async.Deferred.prototype.callback = function(opt_result) {
|
||||
this.check_();
|
||||
this.assertNotDeferred_(opt_result);
|
||||
this.updateResult_(true /* isSuccess */, opt_result);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fire the execution sequence for this Deferred by passing the starting error
|
||||
* result to the first registered errback.
|
||||
* @param {*=} opt_result The starting error.
|
||||
*/
|
||||
goog.async.Deferred.prototype.errback = function(opt_result) {
|
||||
this.check_();
|
||||
this.assertNotDeferred_(opt_result);
|
||||
this.makeStackTraceLong_(opt_result);
|
||||
this.updateResult_(false /* isSuccess */, opt_result);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attempt to make the error's stack trace be long in that it contains the
|
||||
* stack trace from the point where the deferred was created on top of the
|
||||
* current stack trace to give additional context.
|
||||
* @param {*} error
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.makeStackTraceLong_ = function(error) {
|
||||
if (!goog.async.Deferred.LONG_STACK_TRACES) {
|
||||
return;
|
||||
}
|
||||
if (this.constructorStack_ && goog.isObject(error) && error.stack &&
|
||||
// Stack looks like it was system generated. See
|
||||
// https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
|
||||
(/^[^\n]+(\n [^\n]+)+/).test(error.stack)) {
|
||||
error.stack = error.stack + '\nDEFERRED OPERATION:\n' +
|
||||
this.constructorStack_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that an object is not a Deferred.
|
||||
* @param {*} obj The object to test.
|
||||
* @throws {Error} Throws an exception if the object is a Deferred.
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.assertNotDeferred_ = function(obj) {
|
||||
goog.asserts.assert(
|
||||
!(obj instanceof goog.async.Deferred),
|
||||
'An execution sequence may not be initiated with a blocking Deferred.');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Register a callback function to be called with a successful result. If no
|
||||
* value is returned by the callback function, the result value is unchanged. If
|
||||
* a new value is returned, it becomes the Deferred result and will be passed to
|
||||
* the next callback in the execution sequence.
|
||||
*
|
||||
* If the function throws an error, the error becomes the new result and will be
|
||||
* passed to the next errback in the execution chain.
|
||||
*
|
||||
* If the function returns a Deferred, the execution sequence will be blocked
|
||||
* until that Deferred fires. Its result will be passed to the next callback (or
|
||||
* errback if it is an error result) in this Deferred's execution sequence.
|
||||
*
|
||||
* @param {!function(this:T,?):?} cb The function to be called with a successful
|
||||
* result.
|
||||
* @param {T=} opt_scope An optional scope to call the callback in.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
* @template T
|
||||
*/
|
||||
goog.async.Deferred.prototype.addCallback = function(cb, opt_scope) {
|
||||
return this.addCallbacks(cb, null, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Register a callback function to be called with an error result. If no value
|
||||
* is returned by the function, the error result is unchanged. If a new error
|
||||
* value is returned or thrown, that error becomes the Deferred result and will
|
||||
* be passed to the next errback in the execution sequence.
|
||||
*
|
||||
* If the errback function handles the error by returning a non-error value,
|
||||
* that result will be passed to the next normal callback in the sequence.
|
||||
*
|
||||
* If the function returns a Deferred, the execution sequence will be blocked
|
||||
* until that Deferred fires. Its result will be passed to the next callback (or
|
||||
* errback if it is an error result) in this Deferred's execution sequence.
|
||||
*
|
||||
* @param {!function(this:T,?):?} eb The function to be called on an
|
||||
* unsuccessful result.
|
||||
* @param {T=} opt_scope An optional scope to call the errback in.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
* @template T
|
||||
*/
|
||||
goog.async.Deferred.prototype.addErrback = function(eb, opt_scope) {
|
||||
return this.addCallbacks(null, eb, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Registers one function as both a callback and errback.
|
||||
*
|
||||
* @param {!function(this:T,?):?} f The function to be called on any result.
|
||||
* @param {T=} opt_scope An optional scope to call the function in.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
* @template T
|
||||
*/
|
||||
goog.async.Deferred.prototype.addBoth = function(f, opt_scope) {
|
||||
return this.addCallbacks(f, f, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Registers a callback function and an errback function at the same position
|
||||
* in the execution sequence. Only one of these functions will execute,
|
||||
* depending on the error state during the execution sequence.
|
||||
*
|
||||
* NOTE: This is not equivalent to {@code def.addCallback().addErrback()}! If
|
||||
* the callback is invoked, the errback will be skipped, and vice versa.
|
||||
*
|
||||
* @param {(function(this:T,?):?)|null} cb The function to be called on a
|
||||
* successful result.
|
||||
* @param {(function(this:T,?):?)|null} eb The function to be called on an
|
||||
* unsuccessful result.
|
||||
* @param {T=} opt_scope An optional scope to call the functions in.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
* @template T
|
||||
*/
|
||||
goog.async.Deferred.prototype.addCallbacks = function(cb, eb, opt_scope) {
|
||||
goog.asserts.assert(!this.blocking_, 'Blocking Deferreds can not be re-used');
|
||||
this.sequence_.push([cb, eb, opt_scope]);
|
||||
if (this.hasFired()) {
|
||||
this.fire_();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Links another Deferred to the end of this Deferred's execution sequence. The
|
||||
* result of this execution sequence will be passed as the starting result for
|
||||
* the chained Deferred, invoking either its first callback or errback.
|
||||
*
|
||||
* @param {!goog.async.Deferred} otherDeferred The Deferred to chain.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
*/
|
||||
goog.async.Deferred.prototype.chainDeferred = function(otherDeferred) {
|
||||
this.addCallbacks(
|
||||
otherDeferred.callback, otherDeferred.errback, otherDeferred);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes this Deferred wait for another Deferred's execution sequence to
|
||||
* complete before continuing.
|
||||
*
|
||||
* This is equivalent to adding a callback that returns {@code otherDeferred},
|
||||
* but doesn't prevent additional callbacks from being added to
|
||||
* {@code otherDeferred}.
|
||||
*
|
||||
* @param {!goog.async.Deferred} otherDeferred The Deferred to wait for.
|
||||
* @return {!goog.async.Deferred} This Deferred.
|
||||
*/
|
||||
goog.async.Deferred.prototype.awaitDeferred = function(otherDeferred) {
|
||||
return this.addCallback(goog.bind(otherDeferred.branch, otherDeferred));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a branch off this Deferred's execution sequence, and returns it as a
|
||||
* new Deferred. The branched Deferred's starting result will be shared with the
|
||||
* parent at the point of the branch, even if further callbacks are added to the
|
||||
* parent.
|
||||
*
|
||||
* All branches at the same stage in the execution sequence will receive the
|
||||
* same starting value.
|
||||
*
|
||||
* @param {boolean=} opt_propagateCancel If cancel() is called on every child
|
||||
* branch created with opt_propagateCancel, the parent will be canceled as
|
||||
* well.
|
||||
* @return {!goog.async.Deferred} A Deferred that will be started with the
|
||||
* computed result from this stage in the execution sequence.
|
||||
*/
|
||||
goog.async.Deferred.prototype.branch = function(opt_propagateCancel) {
|
||||
var d = new goog.async.Deferred();
|
||||
this.chainDeferred(d);
|
||||
if (opt_propagateCancel) {
|
||||
d.parent_ = this;
|
||||
this.branches_++;
|
||||
}
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the execution sequence has been started on this
|
||||
* Deferred by invoking {@code callback} or {@code errback}.
|
||||
*/
|
||||
goog.async.Deferred.prototype.hasFired = function() {
|
||||
return this.fired_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {*} res The latest result in the execution sequence.
|
||||
* @return {boolean} Whether the current result is an error that should cause
|
||||
* the next errback to fire. May be overridden by subclasses to handle
|
||||
* special error types.
|
||||
* @protected
|
||||
*/
|
||||
goog.async.Deferred.prototype.isError = function(res) {
|
||||
return res instanceof Error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether an errback exists in the remaining sequence.
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.hasErrback_ = function() {
|
||||
return goog.array.some(this.sequence_, function(sequenceRow) {
|
||||
// The errback is the second element in the array.
|
||||
return goog.isFunction(sequenceRow[1]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exhausts the execution sequence while a result is available. The result may
|
||||
* be modified by callbacks or errbacks, and execution will block if the
|
||||
* returned result is an incomplete Deferred.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.async.Deferred.prototype.fire_ = function() {
|
||||
if (this.unhandledExceptionTimeoutId_ && this.hasFired() &&
|
||||
this.hasErrback_()) {
|
||||
// It is possible to add errbacks after the Deferred has fired. If a new
|
||||
// errback is added immediately after the Deferred encountered an unhandled
|
||||
// error, but before that error is rethrown, cancel the rethrow.
|
||||
goog.global.clearTimeout(this.unhandledExceptionTimeoutId_);
|
||||
delete this.unhandledExceptionTimeoutId_;
|
||||
}
|
||||
|
||||
if (this.parent_) {
|
||||
this.parent_.branches_--;
|
||||
delete this.parent_;
|
||||
}
|
||||
|
||||
var res = this.result_;
|
||||
var unhandledException = false;
|
||||
var isNewlyBlocked = false;
|
||||
|
||||
while (this.sequence_.length && !this.blocked_) {
|
||||
var sequenceEntry = this.sequence_.shift();
|
||||
|
||||
var callback = sequenceEntry[0];
|
||||
var errback = sequenceEntry[1];
|
||||
var scope = sequenceEntry[2];
|
||||
|
||||
var f = this.hadError_ ? errback : callback;
|
||||
if (f) {
|
||||
/** @preserveTry */
|
||||
try {
|
||||
var ret = f.call(scope || this.defaultScope_, res);
|
||||
|
||||
// If no result, then use previous result.
|
||||
if (goog.isDef(ret)) {
|
||||
// Bubble up the error as long as the return value hasn't changed.
|
||||
this.hadError_ = this.hadError_ && (ret == res || this.isError(ret));
|
||||
this.result_ = res = ret;
|
||||
}
|
||||
|
||||
if (res instanceof goog.async.Deferred) {
|
||||
isNewlyBlocked = true;
|
||||
this.blocked_ = true;
|
||||
}
|
||||
|
||||
} catch (ex) {
|
||||
res = ex;
|
||||
this.hadError_ = true;
|
||||
this.makeStackTraceLong_(res);
|
||||
|
||||
if (!this.hasErrback_()) {
|
||||
// If an error is thrown with no additional errbacks in the queue,
|
||||
// prepare to rethrow the error.
|
||||
unhandledException = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.result_ = res;
|
||||
|
||||
if (isNewlyBlocked) {
|
||||
res.addCallbacks(
|
||||
goog.bind(this.continue_, this, true /* isSuccess */),
|
||||
goog.bind(this.continue_, this, false /* isSuccess */));
|
||||
res.blocking_ = true;
|
||||
} else if (goog.async.Deferred.STRICT_ERRORS && this.isError(res) &&
|
||||
!(res instanceof goog.async.Deferred.CanceledError)) {
|
||||
this.hadError_ = true;
|
||||
unhandledException = true;
|
||||
}
|
||||
|
||||
if (unhandledException) {
|
||||
// Rethrow the unhandled error after a timeout. Execution will continue, but
|
||||
// the error will be seen by global handlers and the user. The throw will
|
||||
// be canceled if another errback is appended before the timeout executes.
|
||||
// The error's original stack trace is preserved where available.
|
||||
this.unhandledExceptionTimeoutId_ = goog.global.setTimeout(
|
||||
goog.functions.fail(res), 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Deferred that has an initial result.
|
||||
*
|
||||
* @param {*=} opt_result The result.
|
||||
* @return {!goog.async.Deferred} The new Deferred.
|
||||
*/
|
||||
goog.async.Deferred.succeed = function(opt_result) {
|
||||
var d = new goog.async.Deferred();
|
||||
d.callback(opt_result);
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Deferred that has an initial error result.
|
||||
*
|
||||
* @param {*} res The error result.
|
||||
* @return {!goog.async.Deferred} The new Deferred.
|
||||
*/
|
||||
goog.async.Deferred.fail = function(res) {
|
||||
var d = new goog.async.Deferred();
|
||||
d.errback(res);
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Deferred that has already been canceled.
|
||||
*
|
||||
* @return {!goog.async.Deferred} The new Deferred.
|
||||
*/
|
||||
goog.async.Deferred.canceled = function() {
|
||||
var d = new goog.async.Deferred();
|
||||
d.cancel();
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes values that may or may not be Deferreds.
|
||||
*
|
||||
* If the input value is a Deferred, the Deferred is branched (so the original
|
||||
* execution sequence is not modified) and the input callback added to the new
|
||||
* branch. The branch is returned to the caller.
|
||||
*
|
||||
* If the input value is not a Deferred, the callback will be executed
|
||||
* immediately and an already firing Deferred will be returned to the caller.
|
||||
*
|
||||
* In the following (contrived) example, if <code>isImmediate</code> is true
|
||||
* then 3 is alerted immediately, otherwise 6 is alerted after a 2-second delay.
|
||||
*
|
||||
* <pre>
|
||||
* var value;
|
||||
* if (isImmediate) {
|
||||
* value = 3;
|
||||
* } else {
|
||||
* value = new goog.async.Deferred();
|
||||
* setTimeout(function() { value.callback(6); }, 2000);
|
||||
* }
|
||||
*
|
||||
* var d = goog.async.Deferred.when(value, alert);
|
||||
* </pre>
|
||||
*
|
||||
* @param {*} value Deferred or normal value to pass to the callback.
|
||||
* @param {!function(this:T, ?):?} callback The callback to execute.
|
||||
* @param {T=} opt_scope An optional scope to call the callback in.
|
||||
* @return {!goog.async.Deferred} A new Deferred that will call the input
|
||||
* callback with the input value.
|
||||
* @template T
|
||||
*/
|
||||
goog.async.Deferred.when = function(value, callback, opt_scope) {
|
||||
if (value instanceof goog.async.Deferred) {
|
||||
return value.branch(true).addCallback(callback, opt_scope);
|
||||
} else {
|
||||
return goog.async.Deferred.succeed(value).addCallback(callback, opt_scope);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An error sub class that is used when a Deferred has already been called.
|
||||
* @param {!goog.async.Deferred} deferred The Deferred.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.async.Deferred.AlreadyCalledError = function(deferred) {
|
||||
goog.debug.Error.call(this);
|
||||
|
||||
/**
|
||||
* The Deferred that raised this error.
|
||||
* @type {goog.async.Deferred}
|
||||
*/
|
||||
this.deferred = deferred;
|
||||
};
|
||||
goog.inherits(goog.async.Deferred.AlreadyCalledError, goog.debug.Error);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.Deferred.AlreadyCalledError.prototype.message =
|
||||
'Deferred has already fired';
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.Deferred.AlreadyCalledError.prototype.name = 'AlreadyCalledError';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An error sub class that is used when a Deferred is canceled.
|
||||
*
|
||||
* @param {!goog.async.Deferred} deferred The Deferred object.
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
*/
|
||||
goog.async.Deferred.CanceledError = function(deferred) {
|
||||
goog.debug.Error.call(this);
|
||||
|
||||
/**
|
||||
* The Deferred that raised this error.
|
||||
* @type {goog.async.Deferred}
|
||||
*/
|
||||
this.deferred = deferred;
|
||||
};
|
||||
goog.inherits(goog.async.Deferred.CanceledError, goog.debug.Error);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.Deferred.CanceledError.prototype.message = 'Deferred was canceled';
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.Deferred.CanceledError.prototype.name = 'CanceledError';
|
||||
205
nicer-api-docs/closure-library/third_party/closure/goog/mochikit/async/deferredlist.js
vendored
Normal file
205
nicer-api-docs/closure-library/third_party/closure/goog/mochikit/async/deferredlist.js
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
// Copyright 2005 Bob Ippolito. All Rights Reserved.
|
||||
// Modifications Copyright 2009 The Closure Library Authors.
|
||||
// All Rights Reserved.
|
||||
|
||||
/**
|
||||
* Portions of this code are from MochiKit, received by The Closure
|
||||
* Library Authors under the MIT license. All other code is Copyright
|
||||
* 2005-2009 The Closure Library Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Class for tracking multiple asynchronous operations and
|
||||
* handling the results. The DeferredList object here is patterned after the
|
||||
* DeferredList object in the Twisted python networking framework.
|
||||
*
|
||||
* Based on the MochiKit code.
|
||||
*
|
||||
* See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
|
||||
*
|
||||
* @author brenneman@google.com (Shawn Brenneman)
|
||||
*/
|
||||
|
||||
goog.provide('goog.async.DeferredList');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object that waits on the results of multiple asynchronous
|
||||
* operations and marshals the results. It is itself a <code>Deferred</code>,
|
||||
* and may have an execution sequence of callback functions added to it. Each
|
||||
* <code>DeferredList</code> instance is single use and may be fired only once.
|
||||
*
|
||||
* The default behavior of a <code>DeferredList</code> is to wait for a success
|
||||
* or error result from every <code>Deferred</code> in its input list. Once
|
||||
* every result is available, the <code>DeferredList</code>'s execution sequence
|
||||
* is fired with a list of <code>[success, result]</code> array pairs, where
|
||||
* <code>success</code> is a boolean indicating whether <code>result</code> was
|
||||
* the product of a callback or errback. The list's completion criteria and
|
||||
* result list may be modified by setting one or more of the boolean options
|
||||
* documented below.
|
||||
*
|
||||
* <code>Deferred</code> instances passed into a <code>DeferredList</code> are
|
||||
* independent, and may have additional callbacks and errbacks added to their
|
||||
* execution sequences after they are passed as inputs to the list.
|
||||
*
|
||||
* @param {!Array.<!goog.async.Deferred>} list An array of deferred results to
|
||||
* wait for.
|
||||
* @param {boolean=} opt_fireOnOneCallback Whether to stop waiting as soon as
|
||||
* one input completes successfully. In this case, the
|
||||
* <code>DeferredList</code>'s callback chain will be called with a two
|
||||
* element array, <code>[index, result]</code>, where <code>index</code>
|
||||
* identifies which input <code>Deferred</code> produced the successful
|
||||
* <code>result</code>.
|
||||
* @param {boolean=} opt_fireOnOneErrback Whether to stop waiting as soon as one
|
||||
* input reports an error. The failing result is passed to the
|
||||
* <code>DeferredList</code>'s errback sequence.
|
||||
* @param {boolean=} opt_consumeErrors When true, any errors fired by a
|
||||
* <code>Deferred</code> in the input list will be captured and replaced
|
||||
* with a succeeding null result. Any callbacks added to the
|
||||
* <code>Deferred</code> after its use in the <code>DeferredList</code> will
|
||||
* receive null instead of the error.
|
||||
* @param {Function=} opt_canceler A function that will be called if the
|
||||
* <code>DeferredList</code> is canceled. @see goog.async.Deferred#cancel
|
||||
* @param {Object=} opt_defaultScope The default scope to invoke callbacks or
|
||||
* errbacks in.
|
||||
* @constructor
|
||||
* @extends {goog.async.Deferred}
|
||||
*/
|
||||
goog.async.DeferredList = function(
|
||||
list, opt_fireOnOneCallback, opt_fireOnOneErrback, opt_consumeErrors,
|
||||
opt_canceler, opt_defaultScope) {
|
||||
|
||||
goog.base(this, opt_canceler, opt_defaultScope);
|
||||
|
||||
/**
|
||||
* The list of Deferred objects to wait for.
|
||||
* @const {!Array.<!goog.async.Deferred>}
|
||||
* @private
|
||||
*/
|
||||
this.list_ = list;
|
||||
|
||||
/**
|
||||
* The stored return values of the Deferred objects.
|
||||
* @const {!Array}
|
||||
* @private
|
||||
*/
|
||||
this.deferredResults_ = [];
|
||||
|
||||
/**
|
||||
* Whether to fire on the first successful callback instead of waiting for
|
||||
* every Deferred to complete.
|
||||
* @const {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.fireOnOneCallback_ = !!opt_fireOnOneCallback;
|
||||
|
||||
/**
|
||||
* Whether to fire on the first error result received instead of waiting for
|
||||
* every Deferred to complete.
|
||||
* @const {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.fireOnOneErrback_ = !!opt_fireOnOneErrback;
|
||||
|
||||
/**
|
||||
* Whether to stop error propagation on the input Deferred objects. If the
|
||||
* DeferredList sees an error from one of the Deferred inputs, the error will
|
||||
* be captured, and the Deferred will be returned to success state with a null
|
||||
* return value.
|
||||
* @const {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.consumeErrors_ = !!opt_consumeErrors;
|
||||
|
||||
/**
|
||||
* The number of input deferred objects that have fired.
|
||||
* @private {number}
|
||||
*/
|
||||
this.numFinished_ = 0;
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var d = list[i];
|
||||
d.addCallbacks(goog.bind(this.handleCallback_, this, i, true),
|
||||
goog.bind(this.handleCallback_, this, i, false));
|
||||
}
|
||||
|
||||
if (list.length == 0 && !this.fireOnOneCallback_) {
|
||||
this.callback(this.deferredResults_);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.async.DeferredList, goog.async.Deferred);
|
||||
|
||||
|
||||
/**
|
||||
* Registers the result from an input deferred callback or errback. The result
|
||||
* is returned and may be passed to additional handlers in the callback chain.
|
||||
*
|
||||
* @param {number} index The index of the firing deferred object in the input
|
||||
* list.
|
||||
* @param {boolean} success Whether the result is from a callback or errback.
|
||||
* @param {*} result The result of the callback or errback.
|
||||
* @return {*} The result, to be handled by the next handler in the deferred's
|
||||
* callback chain (if any). If consumeErrors is set, an error result is
|
||||
* replaced with null.
|
||||
* @private
|
||||
*/
|
||||
goog.async.DeferredList.prototype.handleCallback_ = function(
|
||||
index, success, result) {
|
||||
|
||||
this.numFinished_++;
|
||||
this.deferredResults_[index] = [success, result];
|
||||
|
||||
if (!this.hasFired()) {
|
||||
if (this.fireOnOneCallback_ && success) {
|
||||
this.callback([index, result]);
|
||||
} else if (this.fireOnOneErrback_ && !success) {
|
||||
this.errback(result);
|
||||
} else if (this.numFinished_ == this.list_.length) {
|
||||
this.callback(this.deferredResults_);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.consumeErrors_ && !success) {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.async.DeferredList.prototype.errback = function(res) {
|
||||
goog.base(this, 'errback', res);
|
||||
|
||||
// On error, cancel any pending requests.
|
||||
for (var i = 0; i < this.list_.length; i++) {
|
||||
this.list_[i].cancel();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a <code>DeferredList</code> that gathers results from multiple
|
||||
* <code>Deferred</code> inputs. If all inputs succeed, the callback is fired
|
||||
* with the list of results as a flat array. If any input fails, the list's
|
||||
* errback is fired immediately with the offending error, and all other pending
|
||||
* inputs are canceled.
|
||||
*
|
||||
* @param {!Array.<!goog.async.Deferred>} list The list of <code>Deferred</code>
|
||||
* inputs to wait for.
|
||||
* @return {!goog.async.Deferred} The deferred list of results from the inputs
|
||||
* if they all succeed, or the error result of the first input to fail.
|
||||
*/
|
||||
goog.async.DeferredList.gatherResults = function(list) {
|
||||
return new goog.async.DeferredList(list, false, true).
|
||||
addCallback(function(results) {
|
||||
var output = [];
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
output[i] = results[i][1];
|
||||
}
|
||||
return output;
|
||||
});
|
||||
};
|
||||
95
nicer-api-docs/closure-library/third_party/closure/goog/osapi/osapi.js
vendored
Normal file
95
nicer-api-docs/closure-library/third_party/closure/goog/osapi/osapi.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @license
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 OSAPI binding.
|
||||
* This file was copied from
|
||||
* http://svn.apache.org/repos/asf/shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js
|
||||
* and it's slightly modified for Closure.
|
||||
*/
|
||||
|
||||
goog.provide('goog.osapi');
|
||||
|
||||
|
||||
// Expose osapi from container side.
|
||||
var osapi = osapi || {};
|
||||
goog.exportSymbol('osapi', osapi);
|
||||
|
||||
|
||||
/** @type {Function} */
|
||||
osapi.callback;
|
||||
|
||||
|
||||
/**
|
||||
* Dispatch a JSON-RPC batch request to services defined in the osapi namespace
|
||||
* @param {Array.<Object>} requests an array of rpc requests.
|
||||
*/
|
||||
goog.osapi.handleGadgetRpcMethod = function(requests) {
|
||||
var responses = new Array(requests.length);
|
||||
var callCount = 0;
|
||||
var callback = osapi.callback;
|
||||
var dummy = function(params, apiCallback) {
|
||||
apiCallback({});
|
||||
};
|
||||
for (var i = 0; i < requests.length; i++) {
|
||||
// Don't allow underscores in any part of the method name as a
|
||||
// convention for restricted methods
|
||||
var current = osapi;
|
||||
if (requests[i]['method'].indexOf('_') == -1) {
|
||||
var path = requests[i]['method'].split('.');
|
||||
for (var j = 0; j < path.length; j++) {
|
||||
if (current.hasOwnProperty(path[j])) {
|
||||
current = current[path[j]];
|
||||
} else {
|
||||
// No matching api
|
||||
current = dummy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current = dummy;
|
||||
}
|
||||
|
||||
// Execute the call and latch the rpc callback until all
|
||||
// complete
|
||||
current(requests[i]['params'], function(i) {
|
||||
return function(response) {
|
||||
// Put back in json-rpc format
|
||||
responses[i] = {'id': requests[i].id, 'data': response};
|
||||
callCount++;
|
||||
if (callCount == requests.length) {
|
||||
callback(responses);
|
||||
}
|
||||
};
|
||||
}(i));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes container side osapi binding.
|
||||
*/
|
||||
goog.osapi.init = function() {
|
||||
// Container-side binding for the gadgetsrpctransport used by osapi.
|
||||
// Containers add services to the client-side osapi implementation by
|
||||
// defining them in the osapi namespace
|
||||
if (gadgets && gadgets.rpc) { // Only define if gadgets rpc exists.
|
||||
// Register the osapi RPC dispatcher.
|
||||
gadgets.rpc.register('osapi._handleGadgetRpcMethod',
|
||||
/** @type {!Function} */ (goog.osapi.handleGadgetRpcMethod));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user