tbody");
+ for (var i=0, ii = tbodys.length; i < ii; i++) {
+ AJS.$(tbodys[i]).find('> tr').filter(':odd').addClass("aui-zebra");
+ }
+ };
+ AJS.$(AJS.tables.rowStriping);
+})();
+
+AJS.setUpToolbars = function () {
+ if (AJS.$.browser.msie) {
+
+ var toolbarGroups = AJS.$(".aui-toolbar .toolbar-group");
+
+ // Fix left,right borders on first, last toolbar items
+ toolbarGroups.each(function (i, group) {
+ AJS.$(group).children(":first").addClass("first");
+ AJS.$(group).children(":last").addClass("last");
+ });
+
+ // IE7 spoon feeding zone.
+ if (parseInt(AJS.$.browser.version, 10) == 7) {
+
+ // Add a class so we can style button containers
+ function markItemsWithButtons () {
+ AJS.$(".aui-toolbar button").closest(".toolbar-item").addClass("contains-button");
+ }
+
+ // force right toolbar to new row when it will fit without wrapping
+ function forceRightSplitToRow() {
+ AJS.$(".aui-toolbar .toolbar-split-right").each(function(i, right) {
+
+ var splitRight = AJS.$(right),
+ splitToolbar = splitRight.closest(".aui-toolbar"),
+ splitLeft = splitToolbar.find(".toolbar-split-left"),
+ leftWidth = splitToolbar.data("leftWidth"),
+ rightWidth = splitToolbar.data("rightWidth");
+
+ if(!leftWidth) {
+ leftWidth = splitLeft.outerWidth();
+ splitToolbar.data("leftWidth", leftWidth);
+ }
+ if (!rightWidth) {
+ rightWidth = 0;
+ AJS.$(".toolbar-item", right).each(function (i, item) {
+ rightWidth += AJS.$(item).outerWidth();
+ });
+ splitToolbar.data("rightWidth", rightWidth);
+ }
+ var toolbarWidth = splitToolbar.width(),
+ spaceAvailable = toolbarWidth - leftWidth;
+
+ if ( toolbarWidth > rightWidth && rightWidth > spaceAvailable ) {
+ splitLeft.addClass("force-split");
+ } else {
+ splitLeft.removeClass("force-split");
+ }
+ });
+ }
+
+ // simulate white-space:nowrap because IE7 is refusing to do it right
+ function simulateNowrapOnGroups () {
+ toolbarGroups.each(function (i, group) {
+ var groupWidth = 0;
+ AJS.$(group).children(".toolbar-item").each(function (i, items) {
+ groupWidth += AJS.$(this).outerWidth();
+ });
+ AJS.$(this).width(groupWidth);
+ });
+ }
+
+ // IE7 inits
+ simulateNowrapOnGroups();
+ markItemsWithButtons();
+
+ // fire forceRightSplitToRow after reload
+ var TO = false;
+ AJS.$(window).resize(function(){
+ if(TO !== false)
+ clearTimeout(TO);
+ TO = setTimeout(forceRightSplitToRow, 200);
+ });
+ }
+ }
+};
+
+AJS.toInit(function() {
+ AJS.setUpToolbars();
+});
diff --git a/ajax/libs/aui/5.6.4/aui-next/js/aui-ie.min.js b/ajax/libs/aui/5.6.4/aui-next/js/aui-ie.min.js
new file mode 100755
index 000000000..9d10cb3f7
--- /dev/null
+++ b/ajax/libs/aui/5.6.4/aui-next/js/aui-ie.min.js
@@ -0,0 +1 @@
+!function(a,b){function c(){var a=p.elements;return"string"==typeof a?a.split(" "):a}function d(a){var b=o[a[m]];return b||(b={},n++,a[m]=n,o[n]=b),b}function e(a,c,e){return c||(c=b),i?c.createElement(a):(e||(e=d(c)),c=e.cache[a]?e.cache[a].cloneNode():l.test(a)?(e.cache[a]=e.createElem(a)).cloneNode():e.createElem(a),c.canHaveChildren&&!k.test(a)?e.frag.appendChild(c):c)}function f(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return p.shivMethods?e(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+c().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(p,b.frag)}function g(a){a||(a=b);var c=d(a);if(p.shivCSS&&!h&&!c.hasCSS){var e,g=a;e=g.createElement("p"),g=g.getElementsByTagName("head")[0]||g.documentElement,e.innerHTML="x",e=g.insertBefore(e.lastChild,g.firstChild),c.hasCSS=!!e}return i||f(a,c),a}var h,i,j=a.html5||{},k=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,l=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,m="_html5shiv",n=0,o={};!function(){try{var a=b.createElement("a");a.innerHTML="",h="hidden"in a;var c;if(!(c=1==a.childNodes.length)){b.createElement("a");var d=b.createDocumentFragment();c="undefined"==typeof d.cloneNode||"undefined"==typeof d.createDocumentFragment||"undefined"==typeof d.createElement}i=c}catch(e){i=h=!0}}();var p={elements:j.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==j.shivCSS,supportsUnknownElements:i,shivMethods:!1!==j.shivMethods,type:"default",shivDocument:g,createElement:e,createDocumentFragment:function(a,e){if(a||(a=b),i)return a.createDocumentFragment();for(var e=e||d(a),f=e.frag.cloneNode(),g=0,h=c(),j=h.length;j>g;g++)f.createElement(h[g]);return f}};a.html5=p,g(b)}(this,document),function(){AJS.tables=AJS.tables||{},AJS.tables.rowStriping=function(){for(var a=AJS.$("table.aui-zebra > tbody"),b=0,c=a.length;c>b;b++)AJS.$(a[b]).find("> tr").filter(":odd").addClass("aui-zebra")},AJS.$(AJS.tables.rowStriping)}(),AJS.setUpToolbars=function(){function a(){AJS.$(".aui-toolbar button").closest(".toolbar-item").addClass("contains-button")}function b(){AJS.$(".aui-toolbar .toolbar-split-right").each(function(a,b){var c=AJS.$(b),d=c.closest(".aui-toolbar"),e=d.find(".toolbar-split-left"),f=d.data("leftWidth"),g=d.data("rightWidth");f||(f=e.outerWidth(),d.data("leftWidth",f)),g||(g=0,AJS.$(".toolbar-item",b).each(function(a,b){g+=AJS.$(b).outerWidth()}),d.data("rightWidth",g));var h=d.width(),i=h-f;h>g&&g>i?e.addClass("force-split"):e.removeClass("force-split")})}function c(){d.each(function(a,b){var c=0;AJS.$(b).children(".toolbar-item").each(function(){c+=AJS.$(this).outerWidth()}),AJS.$(this).width(c)})}if(AJS.$.browser.msie){var d=AJS.$(".aui-toolbar .toolbar-group");if(d.each(function(a,b){AJS.$(b).children(":first").addClass("first"),AJS.$(b).children(":last").addClass("last")}),7==parseInt(AJS.$.browser.version,10)){c(),a();var e=!1;AJS.$(window).resize(function(){e!==!1&&clearTimeout(e),e=setTimeout(b,200)})}}},AJS.toInit(function(){AJS.setUpToolbars()});
\ No newline at end of file
diff --git a/ajax/libs/aui/5.6.4/aui-next/js/aui-soy.js b/ajax/libs/aui/5.6.4/aui-next/js/aui-soy.js
new file mode 100755
index 000000000..69e5d9590
--- /dev/null
+++ b/ajax/libs/aui/5.6.4/aui-next/js/aui-soy.js
@@ -0,0 +1,3586 @@
+;
+/*!
+ * Copyright 2008 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
+ * Utility functions and classes for Soy.
+ *
+ *
+ * The top portion of this file contains utilities for Soy users:
+ * - soy.StringBuilder: Compatible with the 'stringbuilder' code style.
+ *
- soy.renderElement: Render template and set as innerHTML of an element.
+ *
- soy.renderAsFragment: Render template and return as HTML fragment.
+ *
+ *
+ *
+ * The bottom portion of this file contains utilities that should only be called
+ * by Soy-generated JS code. Please do not use these functions directly from
+ * your hand-writen code. Their names all start with '$$'.
+ *
+ */
+
+
+// COPIED FROM nogoog_shim.js
+
+// Create closure namespaces.
+var goog = goog || {};
+
+
+goog.inherits = function(childCtor, parentCtor) {
+ /** @constructor */
+ function tempCtor() {}
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ childCtor.prototype.constructor = childCtor;
+};
+
+
+// Just enough browser detection for this file.
+if (!goog.userAgent) {
+ goog.userAgent = (function() {
+ var userAgent = "";
+ if ("undefined" !== typeof navigator && navigator
+ && "string" == typeof navigator.userAgent) {
+ userAgent = navigator.userAgent;
+ }
+ var isOpera = userAgent.indexOf('Opera') == 0;
+ return {
+ /**
+ * @type {boolean}
+ */
+ HAS_JSCRIPT: typeof 'ScriptEngine' in this,
+ /**
+ * @type {boolean}
+ */
+ IS_OPERA: isOpera,
+ /**
+ * @type {boolean}
+ */
+ IS_IE: !isOpera && userAgent.indexOf('MSIE') != -1,
+ /**
+ * @type {boolean}
+ */
+ IS_WEBKIT: !isOpera && userAgent.indexOf('WebKit') != -1
+ };
+ })();
+}
+
+if (!goog.asserts) {
+ goog.asserts = {
+ /**
+ * @param {...*} var_args
+ */
+ fail: function (var_args) {}
+ };
+}
+
+
+// Stub out the document wrapper used by renderAs*.
+if (!goog.dom) {
+ goog.dom = {};
+ /**
+ * @param {Document=} d
+ * @constructor
+ */
+ goog.dom.DomHelper = function(d) {
+ this.document_ = d || document;
+ };
+ /**
+ * @return {!Document}
+ */
+ goog.dom.DomHelper.prototype.getDocument = function() {
+ return this.document_;
+ };
+ /**
+ * Creates a new element.
+ * @param {string} name Tag name.
+ * @return {!Element}
+ */
+ goog.dom.DomHelper.prototype.createElement = function(name) {
+ return this.document_.createElement(name);
+ };
+ /**
+ * Creates a new document fragment.
+ * @return {!DocumentFragment}
+ */
+ goog.dom.DomHelper.prototype.createDocumentFragment = function() {
+ return this.document_.createDocumentFragment();
+ };
+}
+
+
+if (!goog.format) {
+ goog.format = {
+ insertWordBreaks: function(str, maxCharsBetweenWordBreaks) {
+ str = String(str);
+
+ var resultArr = [];
+ var resultArrLen = 0;
+
+ // These variables keep track of important state inside str.
+ var isInTag = false; // whether we're inside an HTML tag
+ var isMaybeInEntity = false; // whether we might be inside an HTML entity
+ var numCharsWithoutBreak = 0; // number of chars since last word break
+ var flushIndex = 0; // index of first char not yet flushed to resultArr
+
+ for (var i = 0, n = str.length; i < n; ++i) {
+ var charCode = str.charCodeAt(i);
+
+ // If hit maxCharsBetweenWordBreaks, and not space next, then add .
+ if (numCharsWithoutBreak >= maxCharsBetweenWordBreaks &&
+ // space
+ charCode != 32) {
+ resultArr[resultArrLen++] = str.substring(flushIndex, i);
+ flushIndex = i;
+ resultArr[resultArrLen++] = goog.format.WORD_BREAK;
+ numCharsWithoutBreak = 0;
+ }
+
+ if (isInTag) {
+ // If inside an HTML tag and we see '>', it's the end of the tag.
+ if (charCode == 62) {
+ isInTag = false;
+ }
+
+ } else if (isMaybeInEntity) {
+ switch (charCode) {
+ // Inside an entity, a ';' is the end of the entity.
+ // The entity that just ended counts as one char, so increment
+ // numCharsWithoutBreak.
+ case 59: // ';'
+ isMaybeInEntity = false;
+ ++numCharsWithoutBreak;
+ break;
+ // If maybe inside an entity and we see '<', we weren't actually in
+ // an entity. But now we're inside and HTML tag.
+ case 60: // '<'
+ isMaybeInEntity = false;
+ isInTag = true;
+ break;
+ // If maybe inside an entity and we see ' ', we weren't actually in
+ // an entity. Just correct the state and reset the
+ // numCharsWithoutBreak since we just saw a space.
+ case 32: // ' '
+ isMaybeInEntity = false;
+ numCharsWithoutBreak = 0;
+ break;
+ }
+
+ } else { // !isInTag && !isInEntity
+ switch (charCode) {
+ // When not within a tag or an entity and we see '<', we're now
+ // inside an HTML tag.
+ case 60: // '<'
+ isInTag = true;
+ break;
+ // When not within a tag or an entity and we see '&', we might be
+ // inside an entity.
+ case 38: // '&'
+ isMaybeInEntity = true;
+ break;
+ // When we see a space, reset the numCharsWithoutBreak count.
+ case 32: // ' '
+ numCharsWithoutBreak = 0;
+ break;
+ // When we see a non-space, increment the numCharsWithoutBreak.
+ default:
+ ++numCharsWithoutBreak;
+ break;
+ }
+ }
+ }
+
+ // Flush the remaining chars at the end of the string.
+ resultArr[resultArrLen++] = str.substring(flushIndex);
+
+ return resultArr.join('');
+ },
+ /**
+ * String inserted as a word break by insertWordBreaks(). Safari requires
+ * , Opera needs the 'shy' entity, though this will give a
+ * visible hyphen at breaks. Other browsers just use .
+ * @type {string}
+ * @private
+ */
+ WORD_BREAK: goog.userAgent.IS_WEBKIT
+ ? '' : goog.userAgent.IS_OPERA ? '' : ''
+ };
+}
+
+
+if (!goog.i18n) {
+ goog.i18n = {
+ bidi: {
+ /**
+ * Check the directionality of a piece of text, return true if the piece
+ * of text should be laid out in RTL direction.
+ * @param {string} text The piece of text that need to be detected.
+ * @param {boolean=} opt_isHtml Whether {@code text} is HTML/HTML-escaped.
+ * Default: false.
+ * @return {boolean}
+ * @private
+ */
+ detectRtlDirectionality: function(text, opt_isHtml) {
+ text = soyshim.$$bidiStripHtmlIfNecessary_(text, opt_isHtml);
+ return soyshim.$$bidiRtlWordRatio_(text)
+ > soyshim.$$bidiRtlDetectionThreshold_;
+ }
+ }
+ };
+}
+
+/**
+ * Directionality enum.
+ * @enum {number}
+ */
+goog.i18n.bidi.Dir = {
+ RTL: -1,
+ UNKNOWN: 0,
+ LTR: 1
+};
+
+
+/**
+ * Convert a directionality given in various formats to a goog.i18n.bidi.Dir
+ * constant. Useful for interaction with different standards of directionality
+ * representation.
+ *
+ * @param {goog.i18n.bidi.Dir|number|boolean} givenDir Directionality given in
+ * one of the following formats:
+ * 1. A goog.i18n.bidi.Dir constant.
+ * 2. A number (positive = LRT, negative = RTL, 0 = unknown).
+ * 3. A boolean (true = RTL, false = LTR).
+ * @return {goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the given
+ * directionality.
+ */
+goog.i18n.bidi.toDir = function(givenDir) {
+ if (typeof givenDir == 'number') {
+ return givenDir > 0 ? goog.i18n.bidi.Dir.LTR :
+ givenDir < 0 ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.UNKNOWN;
+ } else {
+ return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR;
+ }
+};
+
+
+/**
+ * Utility class for formatting text for display in a potentially
+ * opposite-directionality context without garbling. Provides the following
+ * functionality:
+ *
+ * @param {goog.i18n.bidi.Dir|number|boolean} dir The context
+ * directionality as a number
+ * (positive = LRT, negative = RTL, 0 = unknown).
+ * @constructor
+ */
+goog.i18n.BidiFormatter = function(dir) {
+ this.dir_ = goog.i18n.bidi.toDir(dir);
+};
+
+
+/**
+ * Returns "dir=ltr" or "dir=rtl", depending on {@code text}'s estimated
+ * directionality, if it is not the same as the context directionality.
+ * Otherwise, returns the empty string.
+ *
+ * @param {string} text Text whose directionality is to be estimated.
+ * @param {boolean=} opt_isHtml Whether {@code text} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR
+ * text in non-LTR context; else, the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.dirAttr = function (text, opt_isHtml) {
+ var dir = soy.$$bidiTextDir(text, opt_isHtml);
+ return dir && dir != this.dir_ ? dir < 0 ? 'dir=rtl' : 'dir=ltr' : '';
+};
+
+/**
+ * Returns the trailing horizontal edge, i.e. "right" or "left", depending on
+ * the global bidi directionality.
+ * @return {string} "left" for RTL context and "right" otherwise.
+ */
+goog.i18n.BidiFormatter.prototype.endEdge = function () {
+ return this.dir_ < 0 ? 'left' : 'right';
+};
+
+/**
+ * Returns the Unicode BiDi mark matching the context directionality (LRM for
+ * LTR context directionality, RLM for RTL context directionality), or the
+ * empty string for neutral / unknown context directionality.
+ *
+ * @return {string} LRM for LTR context directionality and RLM for RTL context
+ * directionality.
+ */
+goog.i18n.BidiFormatter.prototype.mark = function () {
+ return (
+ (this.dir_ > 0) ? '\u200E' /*LRM*/ :
+ (this.dir_ < 0) ? '\u200F' /*RLM*/ :
+ '');
+};
+
+/**
+ * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM)
+ * if the directionality or the exit directionality of {@code text} are opposite
+ * to the context directionality. Otherwise returns the empty string.
+ *
+ * @param {string} text The input text.
+ * @param {boolean=} opt_isHtml Whether {@code text} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} A Unicode bidi mark matching the global directionality or
+ * the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.markAfter = function (text, opt_isHtml) {
+ var dir = soy.$$bidiTextDir(text, opt_isHtml);
+ return soyshim.$$bidiMarkAfterKnownDir_(this.dir_, dir, text, opt_isHtml);
+};
+
+/**
+ * Formats a string of unknown directionality for use in HTML output of the
+ * context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} placeholder This argument exists for consistency with the
+ * Closure Library. Specifying it has no effect.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.spanWrap = function(str, placeholder) {
+ str = String(str);
+ var textDir = soy.$$bidiTextDir(str, true);
+ var reset = soyshim.$$bidiMarkAfterKnownDir_(this.dir_, textDir, str, true);
+ if (textDir > 0 && this.dir_ <= 0) {
+ str = '' + str + '';
+ } else if (textDir < 0 && this.dir_ >= 0) {
+ str = '' + str + '';
+ }
+ return str + reset;
+};
+
+/**
+ * Returns the leading horizontal edge, i.e. "left" or "right", depending on
+ * the global bidi directionality.
+ * @return {string} "right" for RTL context and "left" otherwise.
+ */
+goog.i18n.BidiFormatter.prototype.startEdge = function () {
+ return this.dir_ < 0 ? 'right' : 'left';
+};
+
+/**
+ * Formats a string of unknown directionality for use in plain-text output of
+ * the context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ * As opposed to {@link #spanWrap}, this makes use of unicode BiDi formatting
+ * characters. In HTML, its *only* valid use is inside of elements that do not
+ * allow mark-up, e.g. an 'option' tag.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} placeholder This argument exists for consistency with the
+ * Closure Library. Specifying it has no effect.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.unicodeWrap = function(str, placeholder) {
+ str = String(str);
+ var textDir = soy.$$bidiTextDir(str, true);
+ var reset = soyshim.$$bidiMarkAfterKnownDir_(this.dir_, textDir, str, true);
+ if (textDir > 0 && this.dir_ <= 0) {
+ str = '\u202A' + str + '\u202C';
+ } else if (textDir < 0 && this.dir_ >= 0) {
+ str = '\u202B' + str + '\u202C';
+ }
+ return str + reset;
+};
+
+
+goog.string = {
+
+ /**
+ * Converts \r\n, \r, and \n to
s
+ * @param {*} str The string in which to convert newlines.
+ * @param {boolean=} opt_xml Whether to use XML compatible tags.
+ * @return {string} A copy of {@code str} with converted newlines.
+ */
+ newLineToBr: function(str, opt_xml) {
+
+ str = String(str);
+
+ // This quick test helps in the case when there are no chars to replace,
+ // in the worst case this makes barely a difference to the time taken.
+ if (!goog.string.NEWLINE_TO_BR_RE_.test(str)) {
+ return str;
+ }
+
+ return str.replace(/(\r\n|\r|\n)/g, opt_xml ? '
' : '
');
+ },
+ urlEncode: encodeURIComponent,
+ /**
+ * Regular expression used within newlineToBr().
+ * @type {RegExp}
+ * @private
+ */
+ NEWLINE_TO_BR_RE_: /[\r\n]/
+};
+
+
+/**
+ * Utility class to facilitate much faster string concatenation in IE,
+ * using Array.join() rather than the '+' operator. For other browsers
+ * we simply use the '+' operator.
+ *
+ * @param {Object|number|string|boolean=} opt_a1 Optional first initial item
+ * to append.
+ * @param {...Object|number|string|boolean} var_args Other initial items to
+ * append, e.g., new goog.string.StringBuffer('foo', 'bar').
+ * @constructor
+ */
+goog.string.StringBuffer = function(opt_a1, var_args) {
+ /**
+ * Internal buffer for the string to be concatenated.
+ * @type {string|Array}
+ * @private
+ */
+ this.buffer_ = goog.userAgent.HAS_JSCRIPT ? [] : '';
+
+ if (opt_a1 != null) {
+ this.append.apply(this, arguments);
+ }
+};
+
+
+/**
+ * Length of internal buffer (faster than calling buffer_.length).
+ * Only used for IE.
+ * @type {number}
+ * @private
+ */
+goog.string.StringBuffer.prototype.bufferLength_ = 0;
+
+/**
+ * Appends one or more items to the string.
+ *
+ * Calling this with null, undefined, or empty arguments is an error.
+ *
+ * @param {Object|number|string|boolean} a1 Required first string.
+ * @param {Object|number|string|boolean=} opt_a2 Optional second string.
+ * @param {...Object|number|string|boolean} var_args Other items to append,
+ * e.g., sb.append('foo', 'bar', 'baz').
+ * @return {goog.string.StringBuffer} This same StringBuilder object.
+ */
+goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) {
+
+ if (goog.userAgent.HAS_JSCRIPT) {
+ if (opt_a2 == null) { // no second argument (note: undefined == null)
+ // Array assignment is 2x faster than Array push. Also, use a1
+ // directly to avoid arguments instantiation, another 2x improvement.
+ this.buffer_[this.bufferLength_++] = a1;
+ } else {
+ var arr = /**@type {Array.}*/this.buffer_;
+ arr.push.apply(arr, arguments);
+ this.bufferLength_ = this.buffer_.length;
+ }
+
+ } else {
+
+ // Use a1 directly to avoid arguments instantiation for single-arg case.
+ this.buffer_ += a1;
+ if (opt_a2 != null) { // no second argument (note: undefined == null)
+ for (var i = 1; i < arguments.length; i++) {
+ this.buffer_ += arguments[i];
+ }
+ }
+ }
+
+ return this;
+};
+
+
+/**
+ * Clears the string.
+ */
+goog.string.StringBuffer.prototype.clear = function() {
+
+ if (goog.userAgent.HAS_JSCRIPT) {
+ this.buffer_.length = 0; // reuse array to avoid creating new object
+ this.bufferLength_ = 0;
+
+ } else {
+ this.buffer_ = '';
+ }
+};
+
+
+/**
+ * Returns the concatenated string.
+ *
+ * @return {string} The concatenated string.
+ */
+goog.string.StringBuffer.prototype.toString = function() {
+
+ if (goog.userAgent.HAS_JSCRIPT) {
+ var str = this.buffer_.join('');
+ // Given a string with the entire contents, simplify the StringBuilder by
+ // setting its contents to only be this string, rather than many fragments.
+ this.clear();
+ if (str) {
+ this.append(str);
+ }
+ return str;
+
+ } else {
+ return /** @type {string} */ (this.buffer_);
+ }
+};
+
+
+if (!goog.soy) goog.soy = {
+ /**
+ * Helper function to render a Soy template and then set the
+ * output string as the innerHTML of an element. It is recommended
+ * to use this helper function instead of directly setting
+ * innerHTML in your hand-written code, so that it will be easier
+ * to audit the code for cross-site scripting vulnerabilities.
+ *
+ * @param {Function} template The Soy template defining element's content.
+ * @param {Object=} opt_templateData The data for the template.
+ * @param {Object=} opt_injectedData The injected data for the template.
+ * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM
+ * nodes will be created.
+ */
+ renderAsElement: function(
+ template, opt_templateData, opt_injectedData, opt_dom) {
+ return /** @type {!Element} */ (soyshim.$$renderWithWrapper_(
+ template, opt_templateData, opt_dom, true /* asElement */,
+ opt_injectedData));
+ },
+ /**
+ * Helper function to render a Soy template into a single node or
+ * a document fragment. If the rendered HTML string represents a
+ * single node, then that node is returned (note that this is
+ * *not* a fragment, despite them name of the method). Otherwise a
+ * document fragment is returned containing the rendered nodes.
+ *
+ * @param {Function} template The Soy template defining element's content.
+ * @param {Object=} opt_templateData The data for the template.
+ * @param {Object=} opt_injectedData The injected data for the template.
+ * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM
+ * nodes will be created.
+ * @return {!Node} The resulting node or document fragment.
+ */
+ renderAsFragment: function(
+ template, opt_templateData, opt_injectedData, opt_dom) {
+ return soyshim.$$renderWithWrapper_(
+ template, opt_templateData, opt_dom, false /* asElement */,
+ opt_injectedData);
+ },
+ /**
+ * Helper function to render a Soy template and then set the output string as
+ * the innerHTML of an element. It is recommended to use this helper function
+ * instead of directly setting innerHTML in your hand-written code, so that it
+ * will be easier to audit the code for cross-site scripting vulnerabilities.
+ *
+ * NOTE: New code should consider using goog.soy.renderElement instead.
+ *
+ * @param {Element} element The element whose content we are rendering.
+ * @param {Function} template The Soy template defining the element's content.
+ * @param {Object=} opt_templateData The data for the template.
+ * @param {Object=} opt_injectedData The injected data for the template.
+ */
+ renderElement: function(
+ element, template, opt_templateData, opt_injectedData) {
+ element.innerHTML = template(opt_templateData, null, opt_injectedData);
+ }
+};
+
+
+var soy = { esc: {} };
+var soydata = {};
+var soyshim = { $$DEFAULT_TEMPLATE_DATA_: {} };
+/**
+ * Helper function to render a Soy template into a single node or a document
+ * fragment. If the rendered HTML string represents a single node, then that
+ * node is returned. Otherwise a document fragment is created and returned
+ * (wrapped in a DIV element if #opt_singleNode is true).
+ *
+ * @param {Function} template The Soy template defining the element's content.
+ * @param {Object=} opt_templateData The data for the template.
+ * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM
+ * nodes will be created.
+ * @param {boolean=} opt_asElement Whether to wrap the fragment in an
+ * element if the template does not render a single element. If true,
+ * result is always an Element.
+ * @param {Object=} opt_injectedData The injected data for the template.
+ * @return {!Node} The resulting node or document fragment.
+ * @private
+ */
+soyshim.$$renderWithWrapper_ = function(
+ template, opt_templateData, opt_dom, opt_asElement, opt_injectedData) {
+
+ var dom = opt_dom || document;
+ var wrapper = dom.createElement('div');
+ wrapper.innerHTML = template(
+ opt_templateData || soyshim.$$DEFAULT_TEMPLATE_DATA_, undefined,
+ opt_injectedData);
+
+ // If the template renders as a single element, return it.
+ if (wrapper.childNodes.length == 1) {
+ var firstChild = wrapper.firstChild;
+ if (!opt_asElement || firstChild.nodeType == 1 /* Element */) {
+ return /** @type {!Node} */ (firstChild);
+ }
+ }
+
+ // If we're forcing it to be a single element, return the wrapper DIV.
+ if (opt_asElement) {
+ return wrapper;
+ }
+
+ // Otherwise, create and return a fragment.
+ var fragment = dom.createDocumentFragment();
+ while (wrapper.firstChild) {
+ fragment.appendChild(wrapper.firstChild);
+ }
+ return fragment;
+};
+
+
+/**
+ * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM) if the
+ * directionality or the exit directionality of text are opposite to
+ * bidiGlobalDir. Otherwise returns the empty string.
+ * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes
+ * in text, making the logic suitable for HTML and HTML-escaped text.
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
+ * if rtl, 0 if unknown.
+ * @param {number} dir text's directionality: 1 if ltr, -1 if rtl, 0 if unknown.
+ * @param {string} text The text whose directionality is to be estimated.
+ * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
+ * Default: false.
+ * @return {string} A Unicode bidi mark matching bidiGlobalDir, or
+ * the empty string when text's overall and exit directionalities both match
+ * bidiGlobalDir, or bidiGlobalDir is 0 (unknown).
+ * @private
+ */
+soyshim.$$bidiMarkAfterKnownDir_ = function(
+ bidiGlobalDir, dir, text, opt_isHtml) {
+ return (
+ bidiGlobalDir > 0 && (dir < 0 ||
+ soyshim.$$bidiIsRtlExitText_(text, opt_isHtml)) ? '\u200E' : // LRM
+ bidiGlobalDir < 0 && (dir > 0 ||
+ soyshim.$$bidiIsLtrExitText_(text, opt_isHtml)) ? '\u200F' : // RLM
+ '');
+};
+
+
+/**
+ * Strips str of any HTML mark-up and escapes. Imprecise in several ways, but
+ * precision is not very important, since the result is only meant to be used
+ * for directionality detection.
+ * @param {string} str The string to be stripped.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} The stripped string.
+ * @private
+ */
+soyshim.$$bidiStripHtmlIfNecessary_ = function(str, opt_isHtml) {
+ return opt_isHtml ? str.replace(soyshim.$$BIDI_HTML_SKIP_RE_, ' ') : str;
+};
+
+
+/**
+ * Simplified regular expression for am HTML tag (opening or closing) or an HTML
+ * escape - the things we want to skip over in order to ignore their ltr
+ * characters.
+ * @type {RegExp}
+ * @private
+ */
+soyshim.$$BIDI_HTML_SKIP_RE_ = /<[^>]*>|&[^;]+;/g;
+
+
+/**
+ * A practical pattern to identify strong LTR character. This pattern is not
+ * theoretically correct according to unicode standard. It is simplified for
+ * performance and small code size.
+ * @type {string}
+ * @private
+ */
+soyshim.$$bidiLtrChars_ =
+ 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' +
+ '\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF';
+
+
+/**
+ * A practical pattern to identify strong neutral and weak character. This
+ * pattern is not theoretically correct according to unicode standard. It is
+ * simplified for performance and small code size.
+ * @type {string}
+ * @private
+ */
+soyshim.$$bidiNeutralChars_ =
+ '\u0000-\u0020!-@[-`{-\u00BF\u00D7\u00F7\u02B9-\u02FF\u2000-\u2BFF';
+
+
+/**
+ * A practical pattern to identify strong RTL character. This pattern is not
+ * theoretically correct according to unicode standard. It is simplified for
+ * performance and small code size.
+ * @type {string}
+ * @private
+ */
+soyshim.$$bidiRtlChars_ = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC';
+
+
+/**
+ * Regular expressions to check if a piece of text is of RTL directionality
+ * on first character with strong directionality.
+ * @type {RegExp}
+ * @private
+ */
+soyshim.$$bidiRtlDirCheckRe_ = new RegExp(
+ '^[^' + soyshim.$$bidiLtrChars_ + ']*[' + soyshim.$$bidiRtlChars_ + ']');
+
+
+/**
+ * Regular expressions to check if a piece of text is of neutral directionality.
+ * Url are considered as neutral.
+ * @type {RegExp}
+ * @private
+ */
+soyshim.$$bidiNeutralDirCheckRe_ = new RegExp(
+ '^[' + soyshim.$$bidiNeutralChars_ + ']*$|^http://');
+
+
+/**
+ * Check the directionality of the a piece of text based on the first character
+ * with strong directionality.
+ * @param {string} str string being checked.
+ * @return {boolean} return true if rtl directionality is being detected.
+ * @private
+ */
+soyshim.$$bidiIsRtlText_ = function(str) {
+ return soyshim.$$bidiRtlDirCheckRe_.test(str);
+};
+
+
+/**
+ * Check the directionality of the a piece of text based on the first character
+ * with strong directionality.
+ * @param {string} str string being checked.
+ * @return {boolean} true if all characters have neutral directionality.
+ * @private
+ */
+soyshim.$$bidiIsNeutralText_ = function(str) {
+ return soyshim.$$bidiNeutralDirCheckRe_.test(str);
+};
+
+
+/**
+ * This constant controls threshold of rtl directionality.
+ * @type {number}
+ * @private
+ */
+soyshim.$$bidiRtlDetectionThreshold_ = 0.40;
+
+
+/**
+ * Returns the RTL ratio based on word count.
+ * @param {string} str the string that need to be checked.
+ * @return {number} the ratio of RTL words among all words with directionality.
+ * @private
+ */
+soyshim.$$bidiRtlWordRatio_ = function(str) {
+ var rtlCount = 0;
+ var totalCount = 0;
+ var tokens = str.split(' ');
+ for (var i = 0; i < tokens.length; i++) {
+ if (soyshim.$$bidiIsRtlText_(tokens[i])) {
+ rtlCount++;
+ totalCount++;
+ } else if (!soyshim.$$bidiIsNeutralText_(tokens[i])) {
+ totalCount++;
+ }
+ }
+
+ return totalCount == 0 ? 0 : rtlCount / totalCount;
+};
+
+
+/**
+ * Regular expressions to check if the last strongly-directional character in a
+ * piece of text is LTR.
+ * @type {RegExp}
+ * @private
+ */
+soyshim.$$bidiLtrExitDirCheckRe_ = new RegExp(
+ '[' + soyshim.$$bidiLtrChars_ + '][^' + soyshim.$$bidiRtlChars_ + ']*$');
+
+
+/**
+ * Regular expressions to check if the last strongly-directional character in a
+ * piece of text is RTL.
+ * @type {RegExp}
+ * @private
+ */
+soyshim.$$bidiRtlExitDirCheckRe_ = new RegExp(
+ '[' + soyshim.$$bidiRtlChars_ + '][^' + soyshim.$$bidiLtrChars_ + ']*$');
+
+
+/**
+ * Check if the exit directionality a piece of text is LTR, i.e. if the last
+ * strongly-directional character in the string is LTR.
+ * @param {string} str string being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether LTR exit directionality was detected.
+ * @private
+ */
+soyshim.$$bidiIsLtrExitText_ = function(str, opt_isHtml) {
+ str = soyshim.$$bidiStripHtmlIfNecessary_(str, opt_isHtml);
+ return soyshim.$$bidiLtrExitDirCheckRe_.test(str);
+};
+
+
+/**
+ * Check if the exit directionality a piece of text is RTL, i.e. if the last
+ * strongly-directional character in the string is RTL.
+ * @param {string} str string being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether RTL exit directionality was detected.
+ * @private
+ */
+soyshim.$$bidiIsRtlExitText_ = function(str, opt_isHtml) {
+ str = soyshim.$$bidiStripHtmlIfNecessary_(str, opt_isHtml);
+ return soyshim.$$bidiRtlExitDirCheckRe_.test(str);
+};
+
+
+// =============================================================================
+// COPIED FROM soyutils_usegoog.js
+
+
+// -----------------------------------------------------------------------------
+// StringBuilder (compatible with the 'stringbuilder' code style).
+
+
+/**
+ * Utility class to facilitate much faster string concatenation in IE,
+ * using Array.join() rather than the '+' operator. For other browsers
+ * we simply use the '+' operator.
+ *
+ * @param {Object} var_args Initial items to append,
+ * e.g., new soy.StringBuilder('foo', 'bar').
+ * @constructor
+ */
+soy.StringBuilder = goog.string.StringBuffer;
+
+
+// -----------------------------------------------------------------------------
+// soydata: Defines typed strings, e.g. an HTML string {@code "ac"} is
+// semantically distinct from the plain text string {@code "ac"} and smart
+// templates can take that distinction into account.
+
+/**
+ * A type of textual content.
+ * @enum {number}
+ */
+soydata.SanitizedContentKind = {
+
+ /**
+ * A snippet of HTML that does not start or end inside a tag, comment, entity,
+ * or DOCTYPE; and that does not contain any executable code
+ * (JS, {@code