diff --git a/ajax/libs/qooxdoo/3.0.1/q.js b/ajax/libs/qooxdoo/3.0.1/q.js
new file mode 100644
index 000000000..a53877501
--- /dev/null
+++ b/ajax/libs/qooxdoo/3.0.1/q.js
@@ -0,0 +1,47292 @@
+/** qooxdoo v3.0.1 | (c) 2013 1&1 Internet AG, http://1und1.de | http://qooxdoo.org/license */
+(function(){
+if (!window.qx) window.qx = {};
+var qx = window.qx;
+
+if (!qx.$$environment) qx.$$environment = {};
+var envinfo = {"json":true,"qx.application":"library.Application","qx.debug":false,"qx.debug.databinding":false,"qx.debug.dispose":false,"qx.debug.io":false,"qx.debug.ui.queue":false,"qx.globalErrorHandling":false,"qx.optimization.variants":true,"qx.revision":"","qx.theme":"qx.theme.Modern","qx.version":"3.0.1"};
+for (var k in envinfo) qx.$$environment[k] = envinfo[k];
+
+qx.$$packageData = {};
+
+/** qooxdoo v3.0.1 | (c) 2013 1&1 Internet AG, http://1und1.de | http://qooxdoo.org/license */
+qx.$$packageData['0']={"locales":{},"resources":{},"translations":{"C":{},"en":{}}};
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Martin Wittemann (martinwittemann)
+
+************************************************************************ */
+/**
+ * Create namespace
+ *
+ * @ignore(qx.data)
+ * @ignore(qx.data.IListData)
+ * @ignore(qx.util.OOUtil)
+ */
+if(!window.qx){
+
+ window.qx = {
+ };
+};
+/**
+ * Bootstrap qx.Bootstrap to create myself later
+ * This is needed for the API browser etc. to let them detect me
+ */
+qx.Bootstrap = {
+ genericToString : function(){
+
+ return "[Class " + this.classname + "]";
+ },
+ createNamespace : function(name, object){
+
+ var splits = name.split(".");
+ var part = splits[0];
+ var parent = this.__root && this.__root[part] ? this.__root : window;
+ for(var i = 0,len = splits.length - 1;i < len;i++,part = splits[i]){
+
+ if(!parent[part]){
+
+ parent = parent[part] = {
+ };
+ } else {
+
+ parent = parent[part];
+ };
+ };
+ // store object
+ parent[part] = object;
+ // return last part name (e.g. classname)
+ return part;
+ },
+ setDisplayName : function(fcn, classname, name){
+
+ fcn.displayName = classname + "." + name + "()";
+ },
+ setDisplayNames : function(functionMap, classname){
+
+ for(var name in functionMap){
+
+ var value = functionMap[name];
+ if(value instanceof Function){
+
+ value.displayName = classname + "." + name + "()";
+ };
+ };
+ },
+ base : function(args, varargs){
+
+ {
+ };
+ if(arguments.length === 1){
+
+ return args.callee.base.call(this);
+ } else {
+
+ return args.callee.base.apply(this, Array.prototype.slice.call(arguments, 1));
+ };
+ },
+ define : function(name, config){
+
+ if(!config){
+
+ var config = {
+ statics : {
+ }
+ };
+ };
+ var clazz;
+ var proto = null;
+ qx.Bootstrap.setDisplayNames(config.statics, name);
+ if(config.members || config.extend){
+
+ qx.Bootstrap.setDisplayNames(config.members, name + ".prototype");
+ clazz = config.construct || new Function;
+ if(config.extend){
+
+ this.extendClass(clazz, clazz, config.extend, name, basename);
+ };
+ var statics = config.statics || {
+ };
+ // use keys to include the shadowed in IE
+ for(var i = 0,keys = qx.Bootstrap.keys(statics),l = keys.length;i < l;i++){
+
+ var key = keys[i];
+ clazz[key] = statics[key];
+ };
+ proto = clazz.prototype;
+ // Enable basecalls within constructor
+ proto.base = qx.Bootstrap.base;
+ var members = config.members || {
+ };
+ var key,member;
+ // use keys to include the shadowed in IE
+ for(var i = 0,keys = qx.Bootstrap.keys(members),l = keys.length;i < l;i++){
+
+ key = keys[i];
+ member = members[key];
+ // Enable basecalls for methods
+ // Hint: proto[key] is not yet overwritten here
+ if(member instanceof Function && proto[key]){
+
+ member.base = proto[key];
+ };
+ proto[key] = member;
+ };
+ } else {
+
+ clazz = config.statics || {
+ };
+ // Merge class into former class (nedded for 'optimize: ["statics"]')
+ if(qx.Bootstrap.$$registry && qx.Bootstrap.$$registry[name]){
+
+ var formerClass = qx.Bootstrap.$$registry[name];
+ // Add/overwrite properties and return early if necessary
+ if(this.keys(clazz).length !== 0){
+
+ // Execute defer to prevent too early overrides
+ if(config.defer){
+
+ config.defer(clazz, proto);
+ };
+ for(var curProp in clazz){
+
+ formerClass[curProp] = clazz[curProp];
+ };
+ return;
+ };
+ };
+ };
+ // Store type info
+ clazz.$$type = "Class";
+ // Attach toString
+ if(!clazz.hasOwnProperty("toString")){
+
+ clazz.toString = this.genericToString;
+ };
+ // Create namespace
+ var basename = name ? this.createNamespace(name, clazz) : "";
+ // Store names in constructor/object
+ clazz.name = clazz.classname = name;
+ clazz.basename = basename;
+ // Execute defer section
+ if(config.defer){
+
+ config.defer(clazz, proto);
+ };
+ // Store class reference in global class registry
+ qx.Bootstrap.$$registry[name] = clazz;
+ return clazz;
+ }
+};
+/**
+ * Internal class that is responsible for bootstrapping the qooxdoo
+ * framework at load time.
+ */
+qx.Bootstrap.define("qx.Bootstrap", {
+ statics : {
+ /** Root for create namespace. **/
+ __root : null,
+ /** Timestamp of qooxdoo based application startup */
+ LOADSTART : qx.$$start || new Date(),
+ /**
+ * Mapping for early use of the qx.debug environment setting.
+ */
+ DEBUG : (function(){
+
+ // make sure to reflect all changes here to the environment class!
+ var debug = true;
+ if(qx.$$environment && qx.$$environment["qx.debug"] === false){
+
+ debug = false;
+ };
+ return debug;
+ })(),
+ /**
+ * Minimal accessor API for the environment settings given from the
+ * generator.
+ *
+ * WARNING: This method only should be used if the
+ * {@link qx.core.Environment} class is not loaded!
+ *
+ * @param key {String} The key to get the value from.
+ * @return {var} The value of the setting or undefined.
+ */
+ getEnvironmentSetting : function(key){
+
+ if(qx.$$environment){
+
+ return qx.$$environment[key];
+ };
+ },
+ /**
+ * Minimal mutator for the environment settings given from the generator.
+ * It checks for the existance of the environment settings and sets the
+ * key if its not given from the generator. If a setting is available from
+ * the generator, the setting will be ignored.
+ *
+ * WARNING: This method only should be used if the
+ * {@link qx.core.Environment} class is not loaded!
+ *
+ * @param key {String} The key of the setting.
+ * @param value {var} The value for the setting.
+ */
+ setEnvironmentSetting : function(key, value){
+
+ if(!qx.$$environment){
+
+ qx.$$environment = {
+ };
+ };
+ if(qx.$$environment[key] === undefined){
+
+ qx.$$environment[key] = value;
+ };
+ },
+ /**
+ * Creates a namespace and assigns the given object to it.
+ *
+ * @internal
+ * @param name {String} The complete namespace to create. Typically, the last part is the class name itself
+ * @param object {Object} The object to attach to the namespace
+ * @return {Object} last part of the namespace (typically the class name)
+ * @throws {Error} when the given object already exists.
+ */
+ createNamespace : qx.Bootstrap.createNamespace,
+ /**
+ * Offers the ability to change the root for creating namespaces from window to
+ * whatever object is given.
+ *
+ * @param root {Object} The root to use.
+ * @internal
+ */
+ setRoot : function(root){
+
+ this.__root = root;
+ },
+ /**
+ * Call the same method of the super class.
+ *
+ * @param args {arguments} the arguments variable of the calling method
+ * @param varargs {var} variable number of arguments passed to the overwritten function
+ * @return {var} the return value of the method of the base class.
+ */
+ base : qx.Bootstrap.base,
+ /**
+ * Define a new class using the qooxdoo class system.
+ * Lightweight version of {@link qx.Class#define} with less features.
+ *
+ * @signature function(name, config)
+ * @param name {String?} Name of the class. If null, the class will not be
+ * attached to a namespace.
+ * @param config {Map ? null} Class definition structure. The configuration map has the following keys:
+ *
| Name | Type | Description |
|---|---|---|
| extend | Class | The super class the current class inherits from. |
| construct | Function | The constructor of the class. |
| statics | Map | Map of static values / functions of the class. |
| members | Map | Map of instance members of the class. |
| defer | Function | Function that is called at the end of + * processing the class declaration. |
base
+ * property has to be attached to the constructor, while the superclass
+ * property has to be attached to the wrapped constructor.
+ *
+ * @param clazz {Function} The class's wrapped constructor
+ * @param construct {Function} The unwrapped constructor
+ * @param superClass {Function} The super class
+ * @param name {Function} fully qualified class name
+ * @param basename {Function} the base name
+ */
+ extendClass : function(clazz, construct, superClass, name, basename){
+
+ var superproto = superClass.prototype;
+ // Use helper function/class to save the unnecessary constructor call while
+ // setting up inheritance.
+ var helper = new Function();
+ helper.prototype = superproto;
+ var proto = new helper();
+ // Apply prototype to new helper instance
+ clazz.prototype = proto;
+ // Store names in prototype
+ proto.name = proto.classname = name;
+ proto.basename = basename;
+ /*
+ - Store base constructor to constructor-
+ - Store reference to extend class
+ */
+ construct.base = superClass;
+ clazz.superclass = superClass;
+ /*
+ - Store statics/constructor onto constructor/prototype
+ - Store correct constructor
+ - Store statics onto prototype
+ */
+ construct.self = clazz.constructor = proto.constructor = clazz;
+ },
+ /**
+ * Find a class by its name
+ *
+ * @param name {String} class name to resolve
+ * @return {Class} the class
+ */
+ getByName : function(name){
+
+ return qx.Bootstrap.$$registry[name];
+ },
+ /** @type {Map} Stores all defined classes */
+ $$registry : {
+ },
+ /*
+ ---------------------------------------------------------------------------
+ OBJECT UTILITY FUNCTIONS
+ ---------------------------------------------------------------------------
+ */
+ /**
+ * Get the number of own properties in the object.
+ *
+ * @param map {Object} the map
+ * @return {Integer} number of objects in the map
+ * @lint ignoreUnused(key)
+ */
+ objectGetLength : function(map){
+
+ return qx.Bootstrap.keys(map).length;
+ },
+ /**
+ * Inserts all keys of the source object into the
+ * target objects. Attention: The target map gets modified.
+ *
+ * @param target {Object} target object
+ * @param source {Object} object to be merged
+ * @param overwrite {Boolean ? true} If enabled existing keys will be overwritten
+ * @return {Object} Target with merged values from the source object
+ */
+ objectMergeWith : function(target, source, overwrite){
+
+ if(overwrite === undefined){
+
+ overwrite = true;
+ };
+ for(var key in source){
+
+ if(overwrite || target[key] === undefined){
+
+ target[key] = source[key];
+ };
+ };
+ return target;
+ },
+ /**
+ * IE does not return "shadowed" keys even if they are defined directly
+ * in the object.
+ *
+ * @internal
+ */
+ __shadowedKeys : ["isPrototypeOf", "hasOwnProperty", "toLocaleString", "toString", "valueOf", "propertyIsEnumerable", "constructor"],
+ /**
+ * Get the keys of a map as array as returned by a "for ... in" statement.
+ *
+ * @signature function(map)
+ * @internal
+ * @param map {Object} the map
+ * @return {Array} array of the keys of the map
+ */
+ keys : ({
+ "ES5" : Object.keys,
+ "BROKEN_IE" : function(map){
+
+ if(map === null || (typeof map != "object" && typeof map != "function")){
+
+ throw new TypeError("Object.keys requires an object as argument.");
+ };
+ var arr = [];
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ for(var key in map){
+
+ if(hasOwnProperty.call(map, key)){
+
+ arr.push(key);
+ };
+ };
+ // IE does not return "shadowed" keys even if they are defined directly
+ // in the object. This is incompatible with the ECMA standard!!
+ // This is why this checks are needed.
+ var shadowedKeys = qx.Bootstrap.__shadowedKeys;
+ for(var i = 0,a = shadowedKeys,l = a.length;i < l;i++){
+
+ if(hasOwnProperty.call(map, a[i])){
+
+ arr.push(a[i]);
+ };
+ };
+ return arr;
+ },
+ "default" : function(map){
+
+ if(map === null || (typeof map != "object" && typeof map != "function")){
+
+ throw new TypeError("Object.keys requires an object as argument.");
+ };
+ var arr = [];
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ for(var key in map){
+
+ if(hasOwnProperty.call(map, key)){
+
+ arr.push(key);
+ };
+ };
+ return arr;
+ }
+ })[typeof (Object.keys) == "function" ? "ES5" : (function(){
+
+ for(var key in {
+ toString : 1
+ }){
+
+ return key;
+ };
+ })() !== "toString" ? "BROKEN_IE" : "default"],
+ /**
+ * Mapping from JavaScript string representation of objects to names
+ * @internal
+ */
+ __classToTypeMap : {
+ "[object String]" : "String",
+ "[object Array]" : "Array",
+ "[object Object]" : "Object",
+ "[object RegExp]" : "RegExp",
+ "[object Number]" : "Number",
+ "[object Boolean]" : "Boolean",
+ "[object Date]" : "Date",
+ "[object Function]" : "Function",
+ "[object Error]" : "Error"
+ },
+ /*
+ ---------------------------------------------------------------------------
+ FUNCTION UTILITY FUNCTIONS
+ ---------------------------------------------------------------------------
+ */
+ /**
+ * Returns a function whose "this" is altered.
+ *
+ * *Syntax*
+ *
+ * qx.Bootstrap.bind(myFunction, [self, [varargs...]]);+ * + * *Example* + * + *
+ * function myFunction()
+ * {
+ * this.setStyle('color', 'red');
+ * // note that 'this' here refers to myFunction, not an element
+ * // we'll need to bind this function to the element we want to alter
+ * };
+ *
+ * var myBoundFunction = qx.Bootstrap.bind(myFunction, myElement);
+ * myBoundFunction(); // this will make the element myElement red.
+ *
+ *
+ * @param func {Function} Original function to wrap
+ * @param self {Object ? null} The object that the "this" of the function will refer to.
+ * @param varargs {arguments ? null} The arguments to pass to the function.
+ * @return {Function} The bound function.
+ */
+ bind : function(func, self, varargs){
+
+ var fixedArgs = Array.prototype.slice.call(arguments, 2, arguments.length);
+ return function(){
+
+ var args = Array.prototype.slice.call(arguments, 0, arguments.length);
+ return func.apply(self, fixedArgs.concat(args));
+ };
+ },
+ /*
+ ---------------------------------------------------------------------------
+ STRING UTILITY FUNCTIONS
+ ---------------------------------------------------------------------------
+ */
+ /**
+ * Convert the first character of the string to upper case.
+ *
+ * @param str {String} the string
+ * @return {String} the string with an upper case first character
+ */
+ firstUp : function(str){
+
+ return str.charAt(0).toUpperCase() + str.substr(1);
+ },
+ /**
+ * Convert the first character of the string to lower case.
+ *
+ * @param str {String} the string
+ * @return {String} the string with a lower case first character
+ */
+ firstLow : function(str){
+
+ return str.charAt(0).toLowerCase() + str.substr(1);
+ },
+ /*
+ ---------------------------------------------------------------------------
+ TYPE UTILITY FUNCTIONS
+ ---------------------------------------------------------------------------
+ */
+ /**
+ * Get the internal class of the value. See
+ * http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
+ * for details.
+ *
+ * @param value {var} value to get the class for
+ * @return {String} the internal class of the value
+ */
+ getClass : function(value){
+
+ var classString = Object.prototype.toString.call(value);
+ return (qx.Bootstrap.__classToTypeMap[classString] || classString.slice(8, -1));
+ },
+ /**
+ * Whether the value is a string.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a string.
+ */
+ isString : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof String" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal difference between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (typeof value === "string" || qx.Bootstrap.getClass(value) == "String" || value instanceof String || (!!value && !!value.$$isString)));
+ },
+ /**
+ * Whether the value is an array.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is an array.
+ */
+ isArray : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof Array" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal difference between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (value instanceof Array || (value && qx.data && qx.data.IListData && qx.util.OOUtil.hasInterface(value.constructor, qx.data.IListData)) || qx.Bootstrap.getClass(value) == "Array" || (!!value && !!value.$$isArray)));
+ },
+ /**
+ * Whether the value is an object. Note that built-in types like Window are
+ * not reported to be objects.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is an object.
+ */
+ isObject : function(value){
+
+ return (value !== undefined && value !== null && qx.Bootstrap.getClass(value) == "Object");
+ },
+ /**
+ * Whether the value is a function.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a function.
+ */
+ isFunction : function(value){
+
+ return qx.Bootstrap.getClass(value) == "Function";
+ },
+ /*
+ ---------------------------------------------------------------------------
+ LOGGING UTILITY FUNCTIONS
+ ---------------------------------------------------------------------------
+ */
+ $$logs : [],
+ /**
+ * Sending a message at level "debug" to the logger.
+ *
+ * @param object {Object} Contextual object (either instance or static class)
+ * @param message {var} Any number of arguments supported. An argument may
+ * have any JavaScript data type. All data is serialized immediately and
+ * does not keep references to other objects.
+ */
+ debug : function(object, message){
+
+ qx.Bootstrap.$$logs.push(["debug", arguments]);
+ },
+ /**
+ * Sending a message at level "info" to the logger.
+ *
+ * @param object {Object} Contextual object (either instance or static class)
+ * @param message {var} Any number of arguments supported. An argument may
+ * have any JavaScript data type. All data is serialized immediately and
+ * does not keep references to other objects.
+ */
+ info : function(object, message){
+
+ qx.Bootstrap.$$logs.push(["info", arguments]);
+ },
+ /**
+ * Sending a message at level "warn" to the logger.
+ *
+ * @param object {Object} Contextual object (either instance or static class)
+ * @param message {var} Any number of arguments supported. An argument may
+ * have any JavaScript data type. All data is serialized immediately and
+ * does not keep references to other objects.
+ */
+ warn : function(object, message){
+
+ qx.Bootstrap.$$logs.push(["warn", arguments]);
+ },
+ /**
+ * Sending a message at level "error" to the logger.
+ *
+ * @param object {Object} Contextual object (either instance or static class)
+ * @param message {var} Any number of arguments supported. An argument may
+ * have any JavaScript data type. All data is serialized immediately and
+ * does not keep references to other objects.
+ */
+ error : function(object, message){
+
+ qx.Bootstrap.$$logs.push(["error", arguments]);
+ },
+ /**
+ * Prints the current stack trace at level "info"
+ *
+ * @param object {Object} Contextual object (either instance or static class)
+ */
+ trace : function(object){
+ }
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2011 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (wittemann)
+
+************************************************************************ */
+/**
+ * This class is a base class for the OO system defined by Class, Mixin
+ * and Interface. It contains helper which are basically needed to create the
+ * Classes which define the OO system.
+ */
+qx.Bootstrap.define("qx.util.OOUtil", {
+ statics : {
+ /**
+ * Whether the given class exists
+ *
+ * @param name {String} class name to check
+ * @return {Boolean} true if class exists
+ */
+ classIsDefined : function(name){
+
+ return qx.Bootstrap.getByName(name) !== undefined;
+ },
+ /**
+ * Returns the definition of the given property, if not redefined.
+ * Returns null if the property does not exist.
+ *
+ * @param clazz {Class} class to check
+ * @param name {String} name of the class to check for
+ * @return {Map|null} whether the object support the given event.
+ */
+ getPropertyDefinition : function(clazz, name){
+
+ while(clazz){
+
+ if(clazz.$$properties && clazz.$$properties[name]){
+
+ return clazz.$$properties[name];
+ };
+ clazz = clazz.superclass;
+ };
+ return null;
+ },
+ /**
+ * Whether a class has the given property
+ *
+ * @param clazz {Class} class to check
+ * @param name {String} name of the property to check for
+ * @return {Boolean} whether the class includes the given property.
+ */
+ hasProperty : function(clazz, name){
+
+ return !!qx.util.OOUtil.getPropertyDefinition(clazz, name);
+ },
+ /**
+ * Returns the event type of the given event. Returns null if
+ * the event does not exist.
+ *
+ * @param clazz {Class} class to check
+ * @param name {String} name of the event
+ * @return {Map|null} Event type of the given event.
+ */
+ getEventType : function(clazz, name){
+
+ var clazz = clazz.constructor;
+ while(clazz.superclass){
+
+ if(clazz.$$events && clazz.$$events[name] !== undefined){
+
+ return clazz.$$events[name];
+ };
+ clazz = clazz.superclass;
+ };
+ return null;
+ },
+ /**
+ * Whether a class supports the given event type
+ *
+ * @param clazz {Class} class to check
+ * @param name {String} name of the event to check for
+ * @return {Boolean} whether the class supports the given event.
+ */
+ supportsEvent : function(clazz, name){
+
+ return !!qx.util.OOUtil.getEventType(clazz, name);
+ },
+ /**
+ * Returns the class or one of its super classes which contains the
+ * declaration of the given interface. Returns null if the interface is not
+ * specified anywhere.
+ *
+ * @param clazz {Class} class to look for the interface
+ * @param iface {Interface} interface to look for
+ * @return {Class | null} the class which directly implements the given interface
+ */
+ getByInterface : function(clazz, iface){
+
+ var list,i,l;
+ while(clazz){
+
+ if(clazz.$$implements){
+
+ list = clazz.$$flatImplements;
+ for(i = 0,l = list.length;i < l;i++){
+
+ if(list[i] === iface){
+
+ return clazz;
+ };
+ };
+ };
+ clazz = clazz.superclass;
+ };
+ return null;
+ },
+ /**
+ * Whether a given class or any of its super classes includes a given interface.
+ *
+ * This function will return "true" if the interface was defined
+ * in the class declaration ({@link qx.Class#define}) of the class
+ * or any of its super classes using the "implement"
+ * key.
+ *
+ * @param clazz {Class} class to check
+ * @param iface {Interface} the interface to check for
+ * @return {Boolean} whether the class includes the interface.
+ */
+ hasInterface : function(clazz, iface){
+
+ return !!qx.util.OOUtil.getByInterface(clazz, iface);
+ },
+ /**
+ * Returns a list of all mixins available in a given class.
+ *
+ * @param clazz {Class} class which should be inspected
+ * @return {Mixin[]} array of mixins this class uses
+ */
+ getMixins : function(clazz){
+
+ var list = [];
+ while(clazz){
+
+ if(clazz.$$includes){
+
+ list.push.apply(list, clazz.$$flatIncludes);
+ };
+ clazz = clazz.superclass;
+ };
+ return list;
+ }
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2005-2011 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (martinwittemann)
+
+************************************************************************ */
+/**
+ * This class is the single point to access all settings that may be different
+ * in different environments. This contains e.g. the browser name, engine
+ * version but also qooxdoo or application specific settings.
+ *
+ * Its public API can be found in its four main methods. One pair of methods
+ * is used to check the synchronous values of the environment. The other pair
+ * of methods is used for asynchronous checks.
+ *
+ * The most often used method should be {@link #get}, which returns the
+ * current value for a given environment check.
+ *
+ * All qooxdoo settings can be changed via the generator's config. See the manual
+ * for more details about the environment key in the config. As you can see
+ * from the methods API, there is no way to override an existing key. So if you
+ * need to change a qooxdoo setting, you have to use the generator to do so.
+ *
+ * The following table shows the available checks. If you are
+ * interested in more details, check the reference to the implementation of
+ * each check. Please do not use those check implementations directly, as the
+ * Environment class comes with a smart caching feature.
+ *
+ * Synchronous checks+ * |
+ * |||
Key |
+ * Type |
+ * Example |
+ * Details |
+ *
|---|---|---|---|
| browser | + *|||
| browser.documentmode | Integer | 0 |
+ * {@link qx.bom.client.Browser#getDocumentMode} | + *
| browser.name | String | chrome |
+ * {@link qx.bom.client.Browser#getName} | + *
| browser.quirksmode | Boolean | false |
+ * {@link qx.bom.client.Browser#getQuirksMode} | + *
| browser.version | String | 11.0 |
+ * {@link qx.bom.client.Browser#getVersion} | + *
| runtime | + *|||
| runtime.name | String | node.js |
+ * {@link qx.bom.client.Runtime#getName} | + *
| css | + *|||
| css.borderradius | String or null | borderRadius |
+ * {@link qx.bom.client.Css#getBorderRadius} | + *
| css.borderimage | String or null | WebkitBorderImage |
+ * {@link qx.bom.client.Css#getBorderImage} | + *
| css.borderimage.standardsyntax | Boolean or null | true |
+ * {@link qx.bom.client.Css#getBorderImageSyntax} | + *
| css.boxmodel | String | content |
+ * {@link qx.bom.client.Css#getBoxModel} | + *
| css.boxshadow | String or null | boxShadow |
+ * {@link qx.bom.client.Css#getBoxShadow} | + *
| css.gradient.linear | String or null | -moz-linear-gradient |
+ * {@link qx.bom.client.Css#getLinearGradient} | + *
| css.gradient.filter | Boolean | true |
+ * {@link qx.bom.client.Css#getFilterGradient} | + *
| css.gradient.radial | String or null | -moz-radial-gradient |
+ * {@link qx.bom.client.Css#getRadialGradient} | + *
| css.gradient.legacywebkit | Boolean | false |
+ * {@link qx.bom.client.Css#getLegacyWebkitGradient} | + *
| css.placeholder | Boolean | true |
+ * {@link qx.bom.client.Css#getPlaceholder} | + *
| css.textoverflow | String or null | textOverflow |
+ * {@link qx.bom.client.Css#getTextOverflow} | + *
| css.rgba | Boolean | true |
+ * {@link qx.bom.client.Css#getRgba} | + *
| css.usermodify | String or null | WebkitUserModify |
+ * {@link qx.bom.client.Css#getUserModify} | + *
| css.appearance | String or null | WebkitAppearance |
+ * {@link qx.bom.client.Css#getAppearance} | + *
| css.float | String or null | cssFloat |
+ * {@link qx.bom.client.Css#getFloat} | + *
| css.userselect | String or null | WebkitUserSelect |
+ * {@link qx.bom.client.Css#getUserSelect} | + *
| css.userselect.none | String or null | -moz-none |
+ * {@link qx.bom.client.Css#getUserSelectNone} | + *
| css.boxsizing | String or null | boxSizing |
+ * {@link qx.bom.client.Css#getBoxSizing} | + *
| css.animation | Object or null | {end-event: "webkitAnimationEnd", keyframes: "@-webkit-keyframes", play-state: null, name: "WebkitAnimation"} |
+ * {@link qx.bom.client.CssAnimation#getSupport} | + *
| css.animation.requestframe | String or null | mozRequestAnimationFrame |
+ * {@link qx.bom.client.CssAnimation#getRequestAnimationFrame} | + *
| css.transform | Object or null | {3d: true, origin: "WebkitTransformOrigin", name: "WebkitTransform", style: "WebkitTransformStyle", perspective: "WebkitPerspective", perspective-origin: "WebkitPerspectiveOrigin", backface-visibility: "WebkitBackfaceVisibility"} |
+ * {@link qx.bom.client.CssTransform#getSupport} | + *
| css.transform.3d | Boolean | false |
+ * {@link qx.bom.client.CssTransform#get3D} | + *
| css.transition | Object or null | {end-event: "webkitTransitionEnd", name: "WebkitTransition"} |
+ * {@link qx.bom.client.CssTransition#getSupport} | + *
| css.inlineblock | String or null | inline-block |
+ * {@link qx.bom.client.Css#getInlineBlock} | + *
| css.opacity | Boolean | true |
+ * {@link qx.bom.client.Css#getOpacity} | + *
| css.textShadow | Boolean | true |
+ * {@link qx.bom.client.Css#getTextShadow} | + *
| css.textShadow.filter | Boolean | true |
+ * {@link qx.bom.client.Css#getFilterTextShadow} | + *
| css.alphaimageloaderneeded | Boolean | false |
+ * {@link qx.bom.client.Css#getAlphaImageLoaderNeeded} | + *
| css.pointerevents | Boolean | true |
+ * {@link qx.bom.client.Css#getPointerEvents} | + *
| device | + *|||
| device.name | String | pc |
+ * {@link qx.bom.client.Device#getName} | + *
| device.type | String | mobile |
+ * {@link qx.bom.client.Device#getType} | + *
| device.pixelRatio | Number | 2 |
+ * {@link qx.bom.client.Device#getDevicePixelRatio} | + *
| device.touch | String | true |
+ * {@link qx.bom.client.Device#getTouch} | + *
| ecmascript | + *|||
| ecmascript.error.stacktrace | String or null | stack |
+ * {@link qx.bom.client.EcmaScript#getStackTrace} | + *
| ecmascript.array.indexof | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayIndexOf} | + *
| ecmascript.array.lastindexof | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayLastIndexOf} | + *
| ecmascript.array.foreach | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayForEach} | + *
| ecmascript.array.filter | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayFilter} | + *
| ecmascript.array.map | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayMap} | + *
| ecmascript.array.some | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArraySome} | + *
| ecmascript.array.every | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayEvery} | + *
| ecmascript.array.reduce | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayReduce} | + *
| ecmascript.array.reduceright | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getArrayReduceRight} | + *
| ecmascript.function.bind | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getFunctionBind} | + *
| ecmascript.object.keys | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getObjectKeys} | + *
| ecmascript.date.now | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getDateNow} | + *
| ecmascript.error.toString | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getErrorToString} | + *
| ecmascript.string.trim | Boolean | true |
+ * {@link qx.bom.client.EcmaScript#getStringTrim} | + *
| engine | + *|||
| engine.name | String | webkit |
+ * {@link qx.bom.client.Engine#getName} | + *
| engine.version | String | 534.24 |
+ * {@link qx.bom.client.Engine#getVersion} | + *
| event | + *|||
| event.mspointer | Boolean | true |
+ * {@link qx.bom.client.Event#getMsPointer} | + *
| event.touch | Boolean | false |
+ * {@link qx.bom.client.Event#getTouch} | + *
| event.help | Boolean | false |
+ * {@link qx.bom.client.Event#getHelp} | + *
| event.hashchange | Boolean | true |
+ * {@link qx.bom.client.Event#getHashChange} | + *
| html | + *|||
| html.audio | Boolean | true |
+ * {@link qx.bom.client.Html#getAudio} | + *
| html.audio.mp3 | String | "" |
+ * {@link qx.bom.client.Html#getAudioMp3} | + *
| html.audio.ogg | String | "maybe" |
+ * {@link qx.bom.client.Html#getAudioOgg} | + *
| html.audio.wav | String | "probably" |
+ * {@link qx.bom.client.Html#getAudioWav} | + *
| html.audio.au | String | "maybe" |
+ * {@link qx.bom.client.Html#getAudioAu} | + *
| html.audio.aif | String | "probably" |
+ * {@link qx.bom.client.Html#getAudioAif} | + *
| html.canvas | Boolean | true |
+ * {@link qx.bom.client.Html#getCanvas} | + *
| html.classlist | Boolean | true |
+ * {@link qx.bom.client.Html#getClassList} | + *
| html.geolocation | Boolean | true |
+ * {@link qx.bom.client.Html#getGeoLocation} | + *
| html.storage.local | Boolean | true |
+ * {@link qx.bom.client.Html#getLocalStorage} | + *
| html.storage.session | Boolean | true |
+ * {@link qx.bom.client.Html#getSessionStorage} | + *
| html.storage.userdata | Boolean | true |
+ * {@link qx.bom.client.Html#getUserDataStorage} | + *
| html.svg | Boolean | true |
+ * {@link qx.bom.client.Html#getSvg} | + *
| html.video | Boolean | true |
+ * {@link qx.bom.client.Html#getVideo} | + *
| html.video.h264 | String | "probably" |
+ * {@link qx.bom.client.Html#getVideoH264} | + *
| html.video.ogg | String | "" |
+ * {@link qx.bom.client.Html#getVideoOgg} | + *
| html.video.webm | String | "maybe" |
+ * {@link qx.bom.client.Html#getVideoWebm} | + *
| html.vml | Boolean | false |
+ * {@link qx.bom.client.Html#getVml} | + *
| html.webworker | Boolean | true |
+ * {@link qx.bom.client.Html#getWebWorker} | + *
| html.filereader | Boolean | true |
+ * {@link qx.bom.client.Html#getFileReader} | + *
| html.xpath | Boolean | true |
+ * {@link qx.bom.client.Html#getXPath} | + *
| html.xul | Boolean | true |
+ * {@link qx.bom.client.Html#getXul} | + *
| html.console | Boolean | true |
+ * {@link qx.bom.client.Html#getConsole} | + *
| html.element.contains | Boolean | true |
+ * {@link qx.bom.client.Html#getContains} | + *
| html.element.compareDocumentPosition | Boolean | true |
+ * {@link qx.bom.client.Html#getCompareDocumentPosition} | + *
| html.element.textContent | Boolean | true |
+ * {@link qx.bom.client.Html#getTextContent} | + *
| html.image.naturaldimensions | Boolean | true |
+ * {@link qx.bom.client.Html#getNaturalDimensions} | + *
| html.history.state | Boolean | true |
+ * {@link qx.bom.client.Html#getHistoryState} | + *
| html.selection | String | getSelection |
+ * {@link qx.bom.client.Html#getSelection} | + *
| XML | + *|||
| xml.implementation | Boolean | true |
+ * {@link qx.bom.client.Xml#getImplementation} | + *
| xml.domparser | Boolean | true |
+ * {@link qx.bom.client.Xml#getDomParser} | + *
| xml.selectsinglenode | Boolean | false |
+ * {@link qx.bom.client.Xml#getSelectSingleNode} | + *
| xml.selectnodes | Boolean | false |
+ * {@link qx.bom.client.Xml#getSelectNodes} | + *
| xml.getelementsbytagnamens | Boolean | true |
+ * {@link qx.bom.client.Xml#getElementsByTagNameNS} | + *
| xml.domproperties | Boolean | false |
+ * {@link qx.bom.client.Xml#getDomProperties} | + *
| xml.attributens | Boolean | true |
+ * {@link qx.bom.client.Xml#getAttributeNS} | + *
| xml.createelementns | Boolean | true |
+ * {@link qx.bom.client.Xml#getCreateElementNS} | + *
| xml.createnode | Boolean | false |
+ * {@link qx.bom.client.Xml#getCreateNode} | + *
| xml.getqualifieditem | Boolean | false |
+ * {@link qx.bom.client.Xml#getQualifiedItem} | + *
| Stylesheets | + *|||
| html.stylesheet.createstylesheet | Boolean | false |
+ * {@link qx.bom.client.Stylesheet#getCreateStyleSheet} | + *
| html.stylesheet.insertrule | Boolean | true |
+ * {@link qx.bom.client.Stylesheet#getInsertRule} | + *
| html.stylesheet.deleterule | Boolean | true |
+ * {@link qx.bom.client.Stylesheet#getDeleteRule} | + *
| html.stylesheet.addimport | Boolean | false |
+ * {@link qx.bom.client.Stylesheet#getAddImport} | + *
| html.stylesheet.removeimport | Boolean | false |
+ * {@link qx.bom.client.Stylesheet#getRemoveImport} | + *
| io | + *|||
| io.maxrequests | Integer | 4 |
+ * {@link qx.bom.client.Transport#getMaxConcurrentRequestCount} | + *
| io.ssl | Boolean | false |
+ * {@link qx.bom.client.Transport#getSsl} | + *
| io.xhr | String | xhr |
+ * {@link qx.bom.client.Transport#getXmlHttpRequest} | + *
| locale | + *|||
| locale | String | de |
+ * {@link qx.bom.client.Locale#getLocale} | + *
| locale.variant | String | de |
+ * {@link qx.bom.client.Locale#getVariant} | + *
| os | + *|||
| os.name | String | osx |
+ * {@link qx.bom.client.OperatingSystem#getName} | + *
| os.version | String | 10.6 |
+ * {@link qx.bom.client.OperatingSystem#getVersion} | + *
| os.scrollBarOverlayed | Boolean | false |
+ * {@link qx.bom.client.Scroll#scrollBarOverlayed} | + *
| phonegap | + *|||
| phonegap | Boolean | false |
+ * {@link qx.bom.client.PhoneGap#getPhoneGap} | + *
| phonegap.notification | Boolean | false |
+ * {@link qx.bom.client.PhoneGap#getNotification} | + *
| plugin | + *|||
| plugin.divx | Boolean | false |
+ * {@link qx.bom.client.Plugin#getDivX} | + *
| plugin.divx.version | String | + * | {@link qx.bom.client.Plugin#getDivXVersion} | + *
| plugin.flash | Boolean | true |
+ * {@link qx.bom.client.Flash#isAvailable} | + *
| plugin.flash.express | Boolean | true |
+ * {@link qx.bom.client.Flash#getExpressInstall} | + *
| plugin.flash.strictsecurity | Boolean | true |
+ * {@link qx.bom.client.Flash#getStrictSecurityModel} | + *
| plugin.flash.version | String | 10.2.154 |
+ * {@link qx.bom.client.Flash#getVersion} | + *
| plugin.gears | Boolean | false |
+ * {@link qx.bom.client.Plugin#getGears} | + *
| plugin.activex | Boolean | false |
+ * {@link qx.bom.client.Plugin#getActiveX} | + *
| plugin.skype | Boolean | false |
+ * {@link qx.bom.client.Plugin#getSkype} | + *
| plugin.pdf | Boolean | false |
+ * {@link qx.bom.client.Plugin#getPdf} | + *
| plugin.pdf.version | String | + * | {@link qx.bom.client.Plugin#getPdfVersion} | + *
| plugin.quicktime | Boolean | true |
+ * {@link qx.bom.client.Plugin#getQuicktime} | + *
| plugin.quicktime.version | String | 7.6 |
+ * {@link qx.bom.client.Plugin#getQuicktimeVersion} | + *
| plugin.silverlight | Boolean | false |
+ * {@link qx.bom.client.Plugin#getSilverlight} | + *
| plugin.silverlight.version | String | + * | {@link qx.bom.client.Plugin#getSilverlightVersion} | + *
| plugin.windowsmedia | Boolean | false |
+ * {@link qx.bom.client.Plugin#getWindowsMedia} | + *
| plugin.windowsmedia.version | String | + * | {@link qx.bom.client.Plugin#getWindowsMediaVersion} | + *
| qx | + *|||
| qx.allowUrlSettings | Boolean | true |
+ * default: false |
+ *
| qx.allowUrlVariants | Boolean | true |
+ * default: false |
+ *
| qx.application | String | name.space |
+ * default: <<application name>> |
+ *
| qx.aspects | Boolean | false |
+ * default: false |
+ *
| qx.debug | Boolean | true |
+ * default: true |
+ *
| qx.debug.databinding | Boolean | false |
+ * default: false |
+ *
| qx.debug.dispose | Boolean | false |
+ * default: false |
+ *
| qx.debug.dispose.level | Integer | 0 |
+ * default: 0 |
+ *
| qx.debug.io | Boolean | true |
+ * default: false |
+ *
| qx.debug.io.remote | Boolean | true |
+ * default: false |
+ *
| qx.debug.io.remote.data | Boolean | true |
+ * default: false |
+ *
| qx.debug.property.level | Integer | 0 |
+ * default: 0 |
+ *
| qx.debug.ui.queue | Boolean | true |
+ * default: true |
+ *
| qx.dynamicmousewheel | Boolean | true |
+ * default: true |
+ *
| qx.dynlocale | Boolean | true |
+ * default: true |
+ *
| qx.dyntheme | Boolean | true |
+ * default: true |
+ *
| qx.globalErrorHandling | Boolean | true |
+ * default: true |
+ *
| qx.emulatemouse | Boolean | false |
+ * default: false |
+ *
| qx.mobile.emulatetouch | Boolean | false |
+ * default: false |
+ *
| qx.mobile.nativescroll | Boolean | false |
+ * {@link qx.bom.client.Scroll#getNativeScroll} | + *
| qx.optimization.basecalls | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.optimization.comments | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.optimization.privates | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.optimization.strings | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.optimization.variables | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.optimization.variants | Boolean | true |
+ * true if the corresp. optimize key is set in the config | + *
| qx.revision | String | 27348 |
+ * |
| qx.theme | String | qx.theme.Modern |
+ * default: <<initial theme name>> |
+ *
| qx.version | String | ${qxversion} |
+ * |
| qx.blankpage | String | URI to blank.html page |
+ * |
| module | + *|||
| module.databinding | Boolean | true |
+ * default: true |
+ *
| module.logger | Boolean | true |
+ * default: true |
+ *
| module.property | Boolean | true |
+ * default: true |
+ *
| module.events | Boolean | true |
+ * default: true |
+ *
Asynchronous checks+ * |
+ * |||
| html.dataurl | Boolean | true |
+ * {@link qx.bom.client.Html#getDataUrl} | + *
true. This is especially handy for conditional
+ * includes of mixins.
+ * @param map {Map} A map containing check names as keys and values.
+ * @return {Array} An array containing the values.
+ */
+ filter : function(map){
+
+ var returnArray = [];
+ for(var check in map){
+
+ if(this.get(check)){
+
+ returnArray.push(map[check]);
+ };
+ };
+ return returnArray;
+ },
+ /**
+ * Invalidates the cache for the given key.
+ *
+ * @param key {String} The key of the check.
+ */
+ invalidateCacheKey : function(key){
+
+ delete this.__cache[key];
+ },
+ /**
+ * Add a check to the environment class. If there is already a check
+ * added for the given key, the add will be ignored.
+ *
+ * @param key {String} The key for the check e.g. html.featurexyz.
+ * @param check {var} It could be either a function or a simple value.
+ * The function should be responsible for the check and should return the
+ * result of the check.
+ */
+ add : function(key, check){
+
+ // ignore already added checks.
+ if(this._checks[key] == undefined){
+
+ // add functions directly
+ if(check instanceof Function){
+
+ this._checks[key] = check;
+ } else {
+
+ this._checks[key] = this.__createCheck(check);
+ };
+ };
+ },
+ /**
+ * Adds an asynchronous check to the environment. If there is already a check
+ * added for the given key, the add will be ignored.
+ *
+ * @param key {String} The key of the check e.g. html.featureabc
+ * @param check {Function} A function which should check for a specific
+ * environment setting in an asynchronous way. The method should take two
+ * arguments. First one is the callback and the second one is the context.
+ */
+ addAsync : function(key, check){
+
+ if(this._checks[key] == undefined){
+
+ this._asyncChecks[key] = check;
+ };
+ },
+ /**
+ * Returns all currently defined synchronous checks.
+ *
+ * @internal
+ * @return {Map} The map of synchronous checks
+ */
+ getChecks : function(){
+
+ return this._checks;
+ },
+ /**
+ * Returns all currently defined asynchronous checks.
+ *
+ * @internal
+ * @return {Map} The map of asynchronous checks
+ */
+ getAsyncChecks : function(){
+
+ return this._asyncChecks;
+ },
+ /**
+ * Initializer for the default values of the framework settings.
+ */
+ _initDefaultQxValues : function(){
+
+ // an always-true key (e.g. for use in qx.core.Environment.filter() calls)
+ this.add("true", function(){
+
+ return true;
+ });
+ // old settings
+ this.add("qx.allowUrlSettings", function(){
+
+ return false;
+ });
+ this.add("qx.allowUrlVariants", function(){
+
+ return false;
+ });
+ this.add("qx.debug.property.level", function(){
+
+ return 0;
+ });
+ // old variants
+ // make sure to reflect all changes to qx.debug here in the bootstrap class!
+ this.add("qx.debug", function(){
+
+ return true;
+ });
+ this.add("qx.debug.ui.queue", function(){
+
+ return true;
+ });
+ this.add("qx.aspects", function(){
+
+ return false;
+ });
+ this.add("qx.dynlocale", function(){
+
+ return true;
+ });
+ this.add("qx.dyntheme", function(){
+
+ return true;
+ });
+ this.add("qx.mobile.emulatetouch", function(){
+
+ return false;
+ });
+ this.add("qx.emulatemouse", function(){
+
+ return false;
+ });
+ this.add("qx.blankpage", function(){
+
+ return "qx/static/blank.html";
+ });
+ this.add("qx.dynamicmousewheel", function(){
+
+ return true;
+ });
+ this.add("qx.debug.databinding", function(){
+
+ return false;
+ });
+ this.add("qx.debug.dispose", function(){
+
+ return false;
+ });
+ // generator optimization vectors
+ this.add("qx.optimization.basecalls", function(){
+
+ return false;
+ });
+ this.add("qx.optimization.comments", function(){
+
+ return false;
+ });
+ this.add("qx.optimization.privates", function(){
+
+ return false;
+ });
+ this.add("qx.optimization.strings", function(){
+
+ return false;
+ });
+ this.add("qx.optimization.variables", function(){
+
+ return false;
+ });
+ this.add("qx.optimization.variants", function(){
+
+ return false;
+ });
+ // qooxdoo modules
+ this.add("module.databinding", function(){
+
+ return true;
+ });
+ this.add("module.logger", function(){
+
+ return true;
+ });
+ this.add("module.property", function(){
+
+ return true;
+ });
+ this.add("module.events", function(){
+
+ return true;
+ });
+ this.add("qx.nativeScrollBars", function(){
+
+ return false;
+ });
+ },
+ /**
+ * Import checks from global qx.$$environment into the Environment class.
+ */
+ __importFromGenerator : function(){
+
+ // import the environment map
+ if(qx && qx.$$environment){
+
+ for(var key in qx.$$environment){
+
+ var value = qx.$$environment[key];
+ this._checks[key] = this.__createCheck(value);
+ };
+ };
+ },
+ /**
+ * Checks the URL for environment settings and imports these into the
+ * Environment class.
+ */
+ __importFromUrl : function(){
+
+ if(window.document && window.document.location){
+
+ var urlChecks = window.document.location.search.slice(1).split("&");
+ for(var i = 0;i < urlChecks.length;i++){
+
+ var check = urlChecks[i].split(":");
+ if(check.length != 3 || check[0] != "qxenv"){
+
+ continue;
+ };
+ var key = check[1];
+ var value = decodeURIComponent(check[2]);
+ // implicit type conversion
+ if(value == "true"){
+
+ value = true;
+ } else if(value == "false"){
+
+ value = false;
+ } else if(/^(\d|\.)+$/.test(value)){
+
+ value = parseFloat(value);
+ };;
+ this._checks[key] = this.__createCheck(value);
+ };
+ };
+ },
+ /**
+ * Internal helper which creates a function returning the given value.
+ *
+ * @param value {var} The value which should be returned.
+ * @return {Function} A function which could be used by a test.
+ */
+ __createCheck : function(value){
+
+ return qx.Bootstrap.bind(function(value){
+
+ return value;
+ }, null, value);
+ }
+ },
+ defer : function(statics){
+
+ // create default values for the environment class
+ statics._initDefaultQxValues();
+ // load the checks from the generator
+ statics.__importFromGenerator();
+ // load the checks from the url
+ if(statics.get("qx.allowUrlSettings") === true){
+
+ statics.__importFromUrl();
+ };
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Martin Wittemann (martinwittemann)
+
+ ======================================================================
+
+ This class contains code from:
+
+ Copyright:
+ 2011 Pocket Widget S.L., Spain, http://www.pocketwidget.com
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+
+ Authors:
+ * Javier Martinez Villacampa
+
+************************************************************************ */
+/**
+ * This class comes with all relevant information regarding
+ * the client's engine.
+ *
+ * This class is used by {@link qx.core.Environment} and should not be used
+ * directly. Please check its class comment for details how to use it.
+ *
+ * @internal
+ */
+qx.Bootstrap.define("qx.bom.client.Engine", {
+ // General: http://en.wikipedia.org/wiki/Browser_timeline
+ // Webkit: https://developer.apple.com/internet/safari/uamatrix.html
+ // Firefox: http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox
+ // Maple: http://www.scribd.com/doc/46675822/2011-SDK2-0-Maple-Browser-Specification-V1-00
+ statics : {
+ /**
+ * Returns the version of the engine.
+ *
+ * @return {String} The version number of the current engine.
+ * @internal
+ */
+ getVersion : function(){
+
+ var agent = window.navigator.userAgent;
+ var version = "";
+ if(qx.bom.client.Engine.__isOpera()){
+
+ // Opera has a special versioning scheme, where the second part is combined
+ // e.g. 8.54 which should be handled like 8.5.4 to be compatible to the
+ // common versioning system used by other browsers
+ if(/Opera[\s\/]([0-9]+)\.([0-9])([0-9]*)/.test(agent)){
+
+ // opera >= 10 has as a first verison 9.80 and adds the proper version
+ // in a separate "Version/" postfix
+ // http://my.opera.com/chooseopera/blog/2009/05/29/changes-in-operas-user-agent-string-format
+ if(agent.indexOf("Version/") != -1){
+
+ var match = agent.match(/Version\/(\d+)\.(\d+)/);
+ // ignore the first match, its the whole version string
+ version = match[1] + "." + match[2].charAt(0) + "." + match[2].substring(1, match[2].length);
+ } else {
+
+ version = RegExp.$1 + "." + RegExp.$2;
+ if(RegExp.$3 != ""){
+
+ version += "." + RegExp.$3;
+ };
+ };
+ };
+ } else if(qx.bom.client.Engine.__isWebkit()){
+
+ if(/AppleWebKit\/([^ ]+)/.test(agent)){
+
+ version = RegExp.$1;
+ // We need to filter these invalid characters
+ var invalidCharacter = RegExp("[^\\.0-9]").exec(version);
+ if(invalidCharacter){
+
+ version = version.slice(0, invalidCharacter.index);
+ };
+ };
+ } else if(qx.bom.client.Engine.__isGecko() || qx.bom.client.Engine.__isMaple()){
+
+ // Parse "rv" section in user agent string
+ if(/rv\:([^\);]+)(\)|;)/.test(agent)){
+
+ version = RegExp.$1;
+ };
+ } else if(qx.bom.client.Engine.__isMshtml()){
+
+ var isTrident = /Trident\/([^\);]+)(\)|;)/.test(agent);
+ if(/MSIE\s+([^\);]+)(\)|;)/.test(agent)){
+
+ version = RegExp.$1;
+ // If the IE8 or IE9 is running in the compatibility mode, the MSIE value
+ // is set to an older version, but we need the correct version. The only
+ // way is to compare the trident version.
+ if(version < 8 && isTrident){
+
+ if(RegExp.$1 == "4.0"){
+
+ version = "8.0";
+ } else if(RegExp.$1 == "5.0"){
+
+ version = "9.0";
+ };
+ };
+ } else if(isTrident){
+
+ // IE 11 dropped the "MSIE" string
+ var match = /\brv\:(\d+?\.\d+?)\b/.exec(agent);
+ if(match){
+
+ version = match[1];
+ };
+ };
+ } else {
+
+ var failFunction = window.qxFail;
+ if(failFunction && typeof failFunction === "function"){
+
+ version = failFunction().FULLVERSION;
+ } else {
+
+ version = "1.9.0.0";
+ qx.Bootstrap.warn("Unsupported client: " + agent + "! Assumed gecko version 1.9.0.0 (Firefox 3.0).");
+ };
+ };;;
+ return version;
+ },
+ /**
+ * Returns the name of the engine.
+ *
+ * @return {String} The name of the current engine.
+ * @internal
+ */
+ getName : function(){
+
+ var name;
+ if(qx.bom.client.Engine.__isOpera()){
+
+ name = "opera";
+ } else if(qx.bom.client.Engine.__isWebkit()){
+
+ name = "webkit";
+ } else if(qx.bom.client.Engine.__isGecko() || qx.bom.client.Engine.__isMaple()){
+
+ name = "gecko";
+ } else if(qx.bom.client.Engine.__isMshtml()){
+
+ name = "mshtml";
+ } else {
+
+ // check for the fallback
+ var failFunction = window.qxFail;
+ if(failFunction && typeof failFunction === "function"){
+
+ name = failFunction().NAME;
+ } else {
+
+ name = "gecko";
+ qx.Bootstrap.warn("Unsupported client: " + window.navigator.userAgent + "! Assumed gecko version 1.9.0.0 (Firefox 3.0).");
+ };
+ };;;
+ return name;
+ },
+ /**
+ * Internal helper for checking for opera (presto powered).
+ *
+ * Note that with opera >= 15 their engine switched to blink, so
+ * things like "window.opera" don't work anymore or changed (e.g. user agent).
+ *
+ * @return {Boolean} true, if its opera (presto powered).
+ */
+ __isOpera : function(){
+
+ return window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";
+ },
+ /**
+ * Internal helper for checking for webkit.
+ * @return {Boolean} true, if its webkit.
+ */
+ __isWebkit : function(){
+
+ return window.navigator.userAgent.indexOf("AppleWebKit/") != -1;
+ },
+ /**
+ * Internal helper for checking for Maple .
+ * Maple is used in Samsung SMART TV 2010-2011 models. It's based on Gecko
+ * engine 1.8.1.11.
+ * @return {Boolean} true, if its maple.
+ */
+ __isMaple : function(){
+
+ return window.navigator.userAgent.indexOf("Maple") != -1;
+ },
+ /**
+ * Internal helper for checking for gecko.
+ * @return {Boolean} true, if its gecko.
+ */
+ __isGecko : function(){
+
+ return window.controllers && window.navigator.product === "Gecko" && window.navigator.userAgent.indexOf("Maple") == -1 && window.navigator.userAgent.indexOf("Trident") == -1;
+ },
+ /**
+ * Internal helper to check for MSHTML.
+ * @return {Boolean} true, if its MSHTML.
+ */
+ __isMshtml : function(){
+
+ return window.navigator.cpuClass && (/MSIE\s+([^\);]+)(\)|;)/.test(window.navigator.userAgent) || /Trident\/\d+?\.\d+?/.test(window.navigator.userAgent));
+ }
+ },
+ defer : function(statics){
+
+ qx.core.Environment.add("engine.version", statics.getVersion);
+ qx.core.Environment.add("engine.name", statics.getName);
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2011 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (martinwittemann)
+
+************************************************************************ */
+/**
+ * The main purpose of this class to hold all checks about ECMAScript.
+ *
+ * This class is used by {@link qx.core.Environment} and should not be used
+ * directly. Please check its class comment for details how to use it.
+ *
+ * @internal
+ */
+qx.Bootstrap.define("qx.bom.client.EcmaScript", {
+ statics : {
+ /**
+ * Returns the name of the Error object property that holds stack trace
+ * information or null if the client does not provide any.
+ *
+ * @internal
+ * @return {String|null} stack, stacktrace or
+ * null
+ */
+ getStackTrace : function(){
+
+ var propName;
+ var e = new Error("e");
+ propName = e.stack ? "stack" : e.stacktrace ? "stacktrace" : null;
+ // only thrown errors have the stack property in IE10 and PhantomJS
+ if(!propName){
+
+ try{
+
+ throw e;
+ } catch(ex) {
+
+ e = ex;
+ };
+ };
+ return e.stacktrace ? "stacktrace" : e.stack ? "stack" : null;
+ },
+ /**
+ * Checks if 'indexOf' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayIndexOf : function(){
+
+ return !!Array.prototype.indexOf;
+ },
+ /**
+ * Checks if 'lastIndexOf' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayLastIndexOf : function(){
+
+ return !!Array.prototype.lastIndexOf;
+ },
+ /**
+ * Checks if 'forEach' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayForEach : function(){
+
+ return !!Array.prototype.forEach;
+ },
+ /**
+ * Checks if 'filter' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayFilter : function(){
+
+ return !!Array.prototype.filter;
+ },
+ /**
+ * Checks if 'map' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayMap : function(){
+
+ return !!Array.prototype.map;
+ },
+ /**
+ * Checks if 'some' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArraySome : function(){
+
+ return !!Array.prototype.some;
+ },
+ /**
+ * Checks if 'every' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayEvery : function(){
+
+ return !!Array.prototype.every;
+ },
+ /**
+ * Checks if 'reduce' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayReduce : function(){
+
+ return !!Array.prototype.reduce;
+ },
+ /**
+ * Checks if 'reduceRight' is supported on the Array object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getArrayReduceRight : function(){
+
+ return !!Array.prototype.reduceRight;
+ },
+ /**
+ * Checks if 'toString' is supported on the Error object and
+ * its working as expected.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getErrorToString : function(){
+
+ return typeof Error.prototype.toString == "function" && Error.prototype.toString() !== "[object Error]";
+ },
+ /**
+ * Checks if 'bind' is supported on the Function object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getFunctionBind : function(){
+
+ return typeof Function.prototype.bind === "function";
+ },
+ /**
+ * Checks if 'keys' is supported on the Object object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getObjectKeys : function(){
+
+ return !!Object.keys;
+ },
+ /**
+ * Checks if 'now' is supported on the Date object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getDateNow : function(){
+
+ return !!Date.now;
+ },
+ /**
+ * Checks if 'trim' is supported on the String object.
+ * @internal
+ * @return {Boolean} true, if the method is available.
+ */
+ getStringTrim : function(){
+
+ return typeof String.prototype.trim === "function";
+ }
+ },
+ defer : function(statics){
+
+ // array polyfill
+ qx.core.Environment.add("ecmascript.array.indexof", statics.getArrayIndexOf);
+ qx.core.Environment.add("ecmascript.array.lastindexof", statics.getArrayLastIndexOf);
+ qx.core.Environment.add("ecmascript.array.foreach", statics.getArrayForEach);
+ qx.core.Environment.add("ecmascript.array.filter", statics.getArrayFilter);
+ qx.core.Environment.add("ecmascript.array.map", statics.getArrayMap);
+ qx.core.Environment.add("ecmascript.array.some", statics.getArraySome);
+ qx.core.Environment.add("ecmascript.array.every", statics.getArrayEvery);
+ qx.core.Environment.add("ecmascript.array.reduce", statics.getArrayReduce);
+ qx.core.Environment.add("ecmascript.array.reduceright", statics.getArrayReduceRight);
+ // date polyfill
+ qx.core.Environment.add("ecmascript.date.now", statics.getDateNow);
+ // error bugfix
+ qx.core.Environment.add("ecmascript.error.toString", statics.getErrorToString);
+ qx.core.Environment.add("ecmascript.error.stacktrace", statics.getStackTrace);
+ // function polyfill
+ qx.core.Environment.add("ecmascript.function.bind", statics.getFunctionBind);
+ // object polyfill
+ qx.core.Environment.add("ecmascript.object.keys", statics.getObjectKeys);
+ // string polyfill
+ qx.core.Environment.add("ecmascript.string.trim", statics.getStringTrim);
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2011 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (wittemann)
+
+************************************************************************ */
+/**
+ * This class takes care of the normalization of the native 'Array' object.
+ * Therefore it checks the availability of the following methods and appends
+ * it, if not available. This means you can use the methods during
+ * development in every browser. For usage samples, check out the attached links.
+ *
+ * *indexOf*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *lastIndexOf*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *forEach*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *filter*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *map*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *some*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *every*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *reduce*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * *reduceRight*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ *
+ * Here is a little sample of how to use indexOf e.g.
+ * var a = ["a", "b", "c"];
+ * a.indexOf("b"); // returns 1
+ */
+qx.Bootstrap.define("qx.lang.normalize.Array", {
+ defer : function(){
+
+ // fix indexOf
+ if(!qx.core.Environment.get("ecmascript.array.indexof")){
+
+ Array.prototype.indexOf = function(searchElement, fromIndex){
+
+ if(fromIndex == null){
+
+ fromIndex = 0;
+ } else if(fromIndex < 0){
+
+ fromIndex = Math.max(0, this.length + fromIndex);
+ };
+ for(var i = fromIndex;i < this.length;i++){
+
+ if(this[i] === searchElement){
+
+ return i;
+ };
+ };
+ return -1;
+ };
+ };
+ // lastIndexOf
+ if(!qx.core.Environment.get("ecmascript.array.lastindexof")){
+
+ Array.prototype.lastIndexOf = function(searchElement, fromIndex){
+
+ if(fromIndex == null){
+
+ fromIndex = this.length - 1;
+ } else if(fromIndex < 0){
+
+ fromIndex = Math.max(0, this.length + fromIndex);
+ };
+ for(var i = fromIndex;i >= 0;i--){
+
+ if(this[i] === searchElement){
+
+ return i;
+ };
+ };
+ return -1;
+ };
+ };
+ // forEach
+ if(!qx.core.Environment.get("ecmascript.array.foreach")){
+
+ Array.prototype.forEach = function(callback, obj){
+
+ var l = this.length;
+ for(var i = 0;i < l;i++){
+
+ var value = this[i];
+ if(value !== undefined){
+
+ callback.call(obj || window, value, i, this);
+ };
+ };
+ };
+ };
+ // filter
+ if(!qx.core.Environment.get("ecmascript.array.filter")){
+
+ Array.prototype.filter = function(callback, obj){
+
+ var res = [];
+ var l = this.length;
+ for(var i = 0;i < l;i++){
+
+ var value = this[i];
+ if(value !== undefined){
+
+ if(callback.call(obj || window, value, i, this)){
+
+ res.push(this[i]);
+ };
+ };
+ };
+ return res;
+ };
+ };
+ // map
+ if(!qx.core.Environment.get("ecmascript.array.map")){
+
+ Array.prototype.map = function(callback, obj){
+
+ var res = [];
+ var l = this.length;
+ for(var i = 0;i < l;i++){
+
+ var value = this[i];
+ if(value !== undefined){
+
+ res[i] = callback.call(obj || window, value, i, this);
+ };
+ };
+ return res;
+ };
+ };
+ // some
+ if(!qx.core.Environment.get("ecmascript.array.some")){
+
+ Array.prototype.some = function(callback, obj){
+
+ var l = this.length;
+ for(var i = 0;i < l;i++){
+
+ var value = this[i];
+ if(value !== undefined){
+
+ if(callback.call(obj || window, value, i, this)){
+
+ return true;
+ };
+ };
+ };
+ return false;
+ };
+ };
+ // every
+ if(!qx.core.Environment.get("ecmascript.array.every")){
+
+ Array.prototype.every = function(callback, obj){
+
+ var l = this.length;
+ for(var i = 0;i < l;i++){
+
+ var value = this[i];
+ if(value !== undefined){
+
+ if(!callback.call(obj || window, value, i, this)){
+
+ return false;
+ };
+ };
+ };
+ return true;
+ };
+ };
+ // reduce
+ if(!qx.core.Environment.get("ecmascript.array.reduce")){
+
+ Array.prototype.reduce = function(callback, init){
+
+ if(typeof callback !== "function"){
+
+ throw new TypeError("First argument is not callable");
+ };
+ if(init === undefined && this.length === 0){
+
+ throw new TypeError("Length is 0 and no second argument given");
+ };
+ var ret = init === undefined ? this[0] : init;
+ for(var i = init === undefined ? 1 : 0;i < this.length;i++){
+
+ if(i in this){
+
+ ret = callback.call(undefined, ret, this[i], i, this);
+ };
+ };
+ return ret;
+ };
+ };
+ // reduceRight
+ if(!qx.core.Environment.get("ecmascript.array.reduceright")){
+
+ Array.prototype.reduceRight = function(callback, init){
+
+ if(typeof callback !== "function"){
+
+ throw new TypeError("First argument is not callable");
+ };
+ if(init === undefined && this.length === 0){
+
+ throw new TypeError("Length is 0 and no second argument given");
+ };
+ var ret = init === undefined ? this[this.length - 1] : init;
+ for(var i = init === undefined ? this.length - 2 : this.length - 1;i >= 0;i--){
+
+ if(i in this){
+
+ ret = callback.call(undefined, ret, this[i], i, this);
+ };
+ };
+ return ret;
+ };
+ };
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2007-2009 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Fabian Jakobs (fjakobs)
+
+ ======================================================================
+
+ This class uses ideas and code snipplets presented at
+ http://webreflection.blogspot.com/2008/05/habemus-array-unlocked-length-in-ie8.html
+ http://webreflection.blogspot.com/2008/05/stack-and-arrayobject-how-to-create.html
+
+ Author:
+ Andrea Giammarchi
+
+ License:
+ MIT: http://www.opensource.org/licenses/mit-license.php
+
+ ======================================================================
+
+ This class uses documentation of the native Array methods from the MDC
+ documentation of Mozilla.
+
+ License:
+ CC Attribution-Sharealike License:
+ http://creativecommons.org/licenses/by-sa/2.5/
+
+************************************************************************ */
+/**
+ * This class is the common superclass for most array classes in
+ * qooxdoo. It supports all of the shiny 1.6 JavaScript array features
+ * like forEach and map.
+ *
+ * This class may be instantiated instead of the native Array if
+ * one wants to work with a feature-unified Array instead of the native
+ * one. This class uses native features whereever possible but fills
+ * all missing implementations with custom ones.
+ *
+ * Through the ability to extend from this class one could add even
+ * more utility features on top of it.
+ *
+ * @require(qx.bom.client.Engine)
+ * @require(qx.lang.normalize.Array)
+ */
+qx.Bootstrap.define("qx.type.BaseArray", {
+ extend : Array,
+ /*
+ *****************************************************************************
+ CONSTRUCTOR
+ *****************************************************************************
+ */
+ /**
+ * Creates a new Array with the given length or the listed elements.
+ *
+ * + * var arr1 = new qx.type.BaseArray(arrayLength); + * var arr2 = new qx.type.BaseArray(item0, item1, ..., itemN); + *+ * + * *
arrayLength: The initial length of the array. You can access
+ * this value using the length property. If the value specified is not a
+ * number, an array of length 1 is created, with the first element having
+ * the specified value. The maximum length allowed for an
+ * array is 2^32-1, i.e. 4,294,967,295.
+ * * itemN: A value for the element in that position in the
+ * array. When this form is used, the array is initialized with the specified
+ * values as its elements, and the array's length property is set to the
+ * number of arguments.
+ *
+ * @param length_or_items {Integer|var?null} The initial length of the array
+ * OR an argument list of values.
+ */
+ construct : function(length_or_items){
+ },
+ /*
+ *****************************************************************************
+ MEMBERS
+ *****************************************************************************
+ */
+ members : {
+ /**
+ * Converts a base array to a native Array
+ *
+ * @signature function()
+ * @return {Array} The native array
+ */
+ toArray : null,
+ /**
+ * Returns the current number of items stored in the Array
+ *
+ * @signature function()
+ * @return {Integer} number of items
+ */
+ valueOf : null,
+ /**
+ * Removes the last element from an array and returns that element.
+ *
+ * This method modifies the array.
+ *
+ * @signature function()
+ * @return {var} The last element of the array.
+ */
+ pop : null,
+ /**
+ * Adds one or more elements to the end of an array and returns the new length of the array.
+ *
+ * This method modifies the array.
+ *
+ * @signature function(varargs)
+ * @param varargs {var} The elements to add to the end of the array.
+ * @return {Integer} The new array's length
+ */
+ push : null,
+ /**
+ * Reverses the order of the elements of an array -- the first becomes the last, and the last becomes the first.
+ *
+ * This method modifies the array.
+ *
+ * @signature function()
+ * @return {Array} Returns the modified array (works in place)
+ */
+ reverse : null,
+ /**
+ * Removes the first element from an array and returns that element.
+ *
+ * This method modifies the array.
+ *
+ * @signature function()
+ * @return {var} The first element of the array.
+ */
+ shift : null,
+ /**
+ * Sorts the elements of an array.
+ *
+ * This method modifies the array.
+ *
+ * @signature function(compareFunction)
+ * @param compareFunction {Function?null} Specifies a function that defines the sort order. If omitted,
+ * the array is sorted lexicographically (in dictionary order) according to the string conversion of each element.
+ * @return {Array} Returns the modified array (works in place)
+ */
+ sort : null,
+ /**
+ * Adds and/or removes elements from an array.
+ *
+ * @signature function(index, howMany, varargs)
+ * @param index {Integer} Index at which to start changing the array. If negative, will begin
+ * that many elements from the end.
+ * @param howMany {Integer} An integer indicating the number of old array elements to remove.
+ * If howMany is 0, no elements are removed. In this case, you should specify
+ * at least one new element.
+ * @param varargs {var?null} The elements to add to the array. If you don't specify any elements,
+ * splice simply removes elements from the array.
+ * @return {BaseArray} New array with the removed elements.
+ */
+ splice : null,
+ /**
+ * Adds one or more elements to the front of an array and returns the new length of the array.
+ *
+ * This method modifies the array.
+ *
+ * @signature function(varargs)
+ * @param varargs {var} The elements to add to the front of the array.
+ * @return {Integer} The new array's length
+ */
+ unshift : null,
+ /**
+ * Returns a new array comprised of this array joined with other array(s) and/or value(s).
+ *
+ * This method does not modify the array and returns a modified copy of the original.
+ *
+ * @signature function(varargs)
+ * @param varargs {Array|var} Arrays and/or values to concatenate to the resulting array.
+ * @return {qx.type.BaseArray} New array built of the given arrays or values.
+ */
+ concat : null,
+ /**
+ * Joins all elements of an array into a string.
+ *
+ * @signature function(separator)
+ * @param separator {String} Specifies a string to separate each element of the array. The separator is
+ * converted to a string if necessary. If omitted, the array elements are separated with a comma.
+ * @return {String} The stringified values of all elements divided by the given separator.
+ */
+ join : null,
+ /**
+ * Extracts a section of an array and returns a new array.
+ *
+ * @signature function(begin, end)
+ * @param begin {Integer} Zero-based index at which to begin extraction. As a negative index, start indicates
+ * an offset from the end of the sequence. slice(-2) extracts the second-to-last element and the last element
+ * in the sequence.
+ * @param end {Integer?length} Zero-based index at which to end extraction. slice extracts up to but not including end.
+ * slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
+ * As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence.
+ * If end is omitted, slice extracts to the end of the sequence.
+ * @return {BaseArray} An new array which contains a copy of the given region.
+ */
+ slice : null,
+ /**
+ * Returns a string representing the array and its elements. Overrides the Object.prototype.toString method.
+ *
+ * @signature function()
+ * @return {String} The string representation of the array.
+ */
+ toString : null,
+ /**
+ * Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found.
+ *
+ * @signature function(searchElement, fromIndex)
+ * @param searchElement {var} Element to locate in the array.
+ * @param fromIndex {Integer?0} The index at which to begin the search. Defaults to 0, i.e. the
+ * whole array will be searched. If the index is greater than or equal to the length of the
+ * array, -1 is returned, i.e. the array will not be searched. If negative, it is taken as
+ * the offset from the end of the array. Note that even when the index is negative, the array
+ * is still searched from front to back. If the calculated index is less than 0, the whole
+ * array will be searched.
+ * @return {Integer} The index of the given element
+ */
+ indexOf : null,
+ /**
+ * Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found.
+ *
+ * @signature function(searchElement, fromIndex)
+ * @param searchElement {var} Element to locate in the array.
+ * @param fromIndex {Integer?length} The index at which to start searching backwards. Defaults to
+ * the array's length, i.e. the whole array will be searched. If the index is greater than
+ * or equal to the length of the array, the whole array will be searched. If negative, it
+ * is taken as the offset from the end of the array. Note that even when the index is
+ * negative, the array is still searched from back to front. If the calculated index is
+ * less than 0, -1 is returned, i.e. the array will not be searched.
+ * @return {Integer} The index of the given element
+ */
+ lastIndexOf : null,
+ /**
+ * Executes a provided function once per array element.
+ *
+ * forEach executes the provided function (callback) once for each
+ * element present in the array. callback is invoked only for indexes of the array
+ * which have assigned values; it is not invoked for indexes which have been deleted or which
+ * have never been assigned values.
+ *
+ * callback is invoked with three arguments: the value of the element, the index
+ * of the element, and the Array object being traversed.
+ *
+ * If a obj parameter is provided to forEach, it will be used
+ * as the this for each invocation of the callback. If it is not
+ * provided, or is null, the global object associated with callback
+ * is used instead.
+ *
+ * forEach does not mutate the array on which it is called.
+ *
+ * The range of elements processed by forEach is set before the first invocation of
+ * callback. Elements which are appended to the array after the call to
+ * forEach begins will not be visited by callback. If existing elements
+ * of the array are changed, or deleted, their value as passed to callback will be
+ * the value at the time forEach visits them; elements that are deleted are not visited.
+ *
+ * @signature function(callback, obj)
+ * @param callback {Function} Function to execute for each element.
+ * @param obj {Object} Object to use as this when executing callback.
+ */
+ forEach : null,
+ /**
+ * Creates a new array with all elements that pass the test implemented by the provided
+ * function.
+ *
+ * filter calls a provided callback function once for each
+ * element in an array, and constructs a new array of all the values for which
+ * callback returns a true value. callback is invoked only
+ * for indexes of the array which have assigned values; it is not invoked for indexes
+ * which have been deleted or which have never been assigned values. Array elements which
+ * do not pass the callback test are simply skipped, and are not included
+ * in the new array.
+ *
+ * callback is invoked with three arguments: the value of the element, the
+ * index of the element, and the Array object being traversed.
+ *
+ * If a obj parameter is provided to filter, it will
+ * be used as the this for each invocation of the callback.
+ * If it is not provided, or is null, the global object associated with
+ * callback is used instead.
+ *
+ * filter does not mutate the array on which it is called. The range of
+ * elements processed by filter is set before the first invocation of
+ * callback. Elements which are appended to the array after the call to
+ * filter begins will not be visited by callback. If existing
+ * elements of the array are changed, or deleted, their value as passed to callback
+ * will be the value at the time filter visits them; elements that are deleted
+ * are not visited.
+ *
+ * @signature function(callback, obj)
+ * @param callback {Function} Function to test each element of the array.
+ * @param obj {Object} Object to use as this when executing callback.
+ * @return {BaseArray} The newly created array with all matching elements
+ */
+ filter : null,
+ /**
+ * Creates a new array with the results of calling a provided function on every element in this array.
+ *
+ * map calls a provided callback function once for each element in an array,
+ * in order, and constructs a new array from the results. callback is invoked only for
+ * indexes of the array which have assigned values; it is not invoked for indexes which have been
+ * deleted or which have never been assigned values.
+ *
+ * callback is invoked with three arguments: the value of the element, the index of the
+ * element, and the Array object being traversed.
+ *
+ * If a obj parameter is provided to map, it will be used as the
+ * this for each invocation of the callback. If it is not provided, or is
+ * null, the global object associated with callback is used instead.
+ *
+ * map does not mutate the array on which it is called.
+ *
+ * The range of elements processed by map is set before the first invocation of
+ * callback. Elements which are appended to the array after the call to map
+ * begins will not be visited by callback. If existing elements of the array are changed,
+ * or deleted, their value as passed to callback will be the value at the time
+ * map visits them; elements that are deleted are not visited.
+ *
+ * @signature function(callback, obj)
+ * @param callback {Function} Function produce an element of the new Array from an element of the current one.
+ * @param obj {Object} Object to use as this when executing callback.
+ * @return {BaseArray} A new array which contains the return values of every item executed through the given function
+ */
+ map : null,
+ /**
+ * Tests whether some element in the array passes the test implemented by the provided function.
+ *
+ * some executes the callback function once for each element present in
+ * the array until it finds one where callback returns a true value. If such an element
+ * is found, some immediately returns true. Otherwise, some
+ * returns false. callback is invoked only for indexes of the array which
+ * have assigned values; it is not invoked for indexes which have been deleted or which have never
+ * been assigned values.
+ *
+ * callback is invoked with three arguments: the value of the element, the index of the
+ * element, and the Array object being traversed.
+ *
+ * If a obj parameter is provided to some, it will be used as the
+ * this for each invocation of the callback. If it is not provided, or is
+ * null, the global object associated with callback is used instead.
+ *
+ * some does not mutate the array on which it is called.
+ *
+ * The range of elements processed by some is set before the first invocation of
+ * callback. Elements that are appended to the array after the call to some
+ * begins will not be visited by callback. If an existing, unvisited element of the array
+ * is changed by callback, its value passed to the visiting callback will
+ * be the value at the time that some visits that element's index; elements that are
+ * deleted are not visited.
+ *
+ * @signature function(callback, obj)
+ * @param callback {Function} Function to test for each element.
+ * @param obj {Object} Object to use as this when executing callback.
+ * @return {Boolean} Whether at least one elements passed the test
+ */
+ some : null,
+ /**
+ * Tests whether all elements in the array pass the test implemented by the provided function.
+ *
+ * every executes the provided callback function once for each element
+ * present in the array until it finds one where callback returns a false value. If
+ * such an element is found, the every method immediately returns false.
+ * Otherwise, if callback returned a true value for all elements, every
+ * will return true. callback is invoked only for indexes of the array
+ * which have assigned values; it is not invoked for indexes which have been deleted or which have
+ * never been assigned values.
+ *
+ * callback is invoked with three arguments: the value of the element, the index of
+ * the element, and the Array object being traversed.
+ *
+ * If a obj parameter is provided to every, it will be used as
+ * the this for each invocation of the callback. If it is not provided,
+ * or is null, the global object associated with callback is used instead.
+ *
+ * every does not mutate the array on which it is called. The range of elements processed
+ * by every is set before the first invocation of callback. Elements which
+ * are appended to the array after the call to every begins will not be visited by
+ * callback. If existing elements of the array are changed, their value as passed
+ * to callback will be the value at the time every visits them; elements
+ * that are deleted are not visited.
+ *
+ * @signature function(callback, obj)
+ * @param callback {Function} Function to test for each element.
+ * @param obj {Object} Object to use as this when executing callback.
+ * @return {Boolean} Whether all elements passed the test
+ */
+ every : null
+ }
+});
+(function(){
+
+ function createStackConstructor(stack){
+
+ // In IE don't inherit from Array but use an empty object as prototype
+ // and copy the methods from Array
+ if((qx.core.Environment.get("engine.name") == "mshtml")){
+
+ Stack.prototype = {
+ length : 0,
+ $$isArray : true
+ };
+ var args = "pop.push.reverse.shift.sort.splice.unshift.join.slice".split(".");
+ for(var length = args.length;length;){
+
+ Stack.prototype[args[--length]] = Array.prototype[args[length]];
+ };
+ };
+ // Remember Array's slice method
+ var slice = Array.prototype.slice;
+ // Fix "concat" method
+ Stack.prototype.concat = function(){
+
+ var constructor = this.slice(0);
+ for(var i = 0,length = arguments.length;i < length;i++){
+
+ var copy;
+ if(arguments[i] instanceof Stack){
+
+ copy = slice.call(arguments[i], 0);
+ } else if(arguments[i] instanceof Array){
+
+ copy = arguments[i];
+ } else {
+
+ copy = [arguments[i]];
+ };
+ constructor.push.apply(constructor, copy);
+ };
+ return constructor;
+ };
+ // Fix "toString" method
+ Stack.prototype.toString = function(){
+
+ return slice.call(this, 0).toString();
+ };
+ // Fix "toLocaleString"
+ Stack.prototype.toLocaleString = function(){
+
+ return slice.call(this, 0).toLocaleString();
+ };
+ // Fix constructor
+ Stack.prototype.constructor = Stack;
+ // Add JS 1.6 Array features
+ Stack.prototype.indexOf = Array.prototype.indexOf;
+ Stack.prototype.lastIndexOf = Array.prototype.lastIndexOf;
+ Stack.prototype.forEach = Array.prototype.forEach;
+ Stack.prototype.some = Array.prototype.some;
+ Stack.prototype.every = Array.prototype.every;
+ var filter = Array.prototype.filter;
+ var map = Array.prototype.map;
+ // Fix methods which generates a new instance
+ // to return an instance of the same class
+ Stack.prototype.filter = function(){
+
+ var ret = new this.constructor;
+ ret.push.apply(ret, filter.apply(this, arguments));
+ return ret;
+ };
+ Stack.prototype.map = function(){
+
+ var ret = new this.constructor;
+ ret.push.apply(ret, map.apply(this, arguments));
+ return ret;
+ };
+ Stack.prototype.slice = function(){
+
+ var ret = new this.constructor;
+ ret.push.apply(ret, Array.prototype.slice.apply(this, arguments));
+ return ret;
+ };
+ Stack.prototype.splice = function(){
+
+ var ret = new this.constructor;
+ ret.push.apply(ret, Array.prototype.splice.apply(this, arguments));
+ return ret;
+ };
+ // Add new "toArray" method for convert a base array to a native Array
+ Stack.prototype.toArray = function(){
+
+ return Array.prototype.slice.call(this, 0);
+ };
+ // Add valueOf() to return the length
+ Stack.prototype.valueOf = function(){
+
+ return this.length;
+ };
+ // Return final class
+ return Stack;
+ };
+ function Stack(length){
+
+ if(arguments.length === 1 && typeof length === "number"){
+
+ this.length = -1 < length && length === length >> .5 ? length : this.push(length);
+ } else if(arguments.length){
+
+ this.push.apply(this, arguments);
+ };
+ };
+ function PseudoArray(){
+ };
+ PseudoArray.prototype = [];
+ Stack.prototype = new PseudoArray;
+ Stack.prototype.length = 0;
+ qx.type.BaseArray = createStackConstructor(Stack);
+})();
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2012 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (wittemann)
+
+************************************************************************ */
+/**
+ * The Core module's responsibility is to query the DOM for elements and offer
+ * these elements as a collection. The Core module itself does not offer any methods to
+ * work with the collection. These methods are added by the other included modules,
+ * such as Manipulating or Attributes.
+ *
+ * Core also provides the plugin API which allows modules to attach either
+ * static functions to the global q object or define methods on the
+ * collection it returns.
+ *
+ * By default, the core module is assigned to a global module named q.
+ * In case q is already defined, the name qxWeb
+ * is used instead.
+ *
+ * For further details, take a look at the documentation in the
+ * user manual.
+ *
+ * @ignore(q)
+ */
+qx.Bootstrap.define("qxWeb", {
+ extend : qx.type.BaseArray,
+ statics : {
+ // internal storage for all initializers
+ __init : [],
+ // internal reference to the used qx namespace
+ $$qx : qx,
+ /**
+ * Internal helper to initialize collections.
+ *
+ * @param arg {var} An array of Elements which will
+ * be initialized as {@link q}. All items in the array which are not
+ * either a window object, a DOM element node or a DOM document node will
+ * be ignored.
+ * @return {q} A new initialized collection.
+ */
+ $init : function(arg){
+
+ var clean = [];
+ for(var i = 0;i < arg.length;i++){
+
+ // check for node or window object
+ var isNode = !!(arg[i] && (arg[i].nodeType === 1 || arg[i].nodeType === 9));
+ if(isNode){
+
+ clean.push(arg[i]);
+ continue;
+ };
+ var isWindow = !!(arg[i] && arg[i].history && arg[i].location && arg[i].document);
+ if(isWindow){
+
+ clean.push(arg[i]);
+ };
+ };
+ var col = qx.lang.Array.cast(clean, qxWeb);
+ for(var i = 0;i < qxWeb.__init.length;i++){
+
+ qxWeb.__init[i].call(col);
+ };
+ return col;
+ },
+ /**
+ * This is an API for module development and can be used to attach new methods
+ * to {@link q}.
+ *
+ * @param module {Map} A map containing the methods to attach.
+ */
+ $attach : function(module){
+
+ for(var name in module){
+
+ {
+ };
+ qxWeb.prototype[name] = module[name];
+ };
+ },
+ /**
+ * This is an API for module development and can be used to attach new methods
+ * to {@link q}.
+ *
+ * @param module {Map} A map containing the methods to attach.
+ */
+ $attachStatic : function(module){
+
+ for(var name in module){
+
+ {
+ };
+ qxWeb[name] = module[name];
+ };
+ },
+ /**
+ * This is an API for module development and can be used to attach new initialization
+ * methods to {@link q} which will be called when a new collection is
+ * created.
+ *
+ * @param init {Function} The initialization method for a module.
+ */
+ $attachInit : function(init){
+
+ this.__init.push(init);
+ },
+ /**
+ * Define a new class using the qooxdoo class system.
+ *
+ * @param name {String?} Name of the class. If null, the class will not be
+ * attached to a namespace.
+ * @param config {Map ? null} Class definition structure. The configuration map has the following keys:
+ * | Name | Type | Description |
|---|---|---|
| extend | Class | The super class the current class inherits from. |
| construct | Function | The constructor of the class. |
| statics | Map | Map of static values / functions of the class. |
| members | Map | Map of instance members of the class. |
| defer | Function | Function that is called at the end of + * processing the class declaration. |
remove or contains.
+ *
+ * The native JavaScript Array is not modified by this class. However,
+ * there are modifications to the native Array in {@link qx.lang.normalize.Array} for
+ * browsers that do not support certain JavaScript features natively .
+ *
+ * @ignore(qx.data)
+ * @ignore(qx.data.IListData)
+ * @ignore(qx.Class.*)
+ * @require(qx.lang.normalize.Date)
+ */
+qx.Bootstrap.define("qx.lang.Array", {
+ statics : {
+ /**
+ * Converts an array like object to any other array like
+ * object.
+ *
+ * Attention: The returned array may be same
+ * instance as the incoming one if the constructor is identical!
+ *
+ * @param object {var} any array-like object
+ * @param constructor {Function} constructor of the new instance
+ * @param offset {Integer?0} position to start from
+ * @return {Array} the converted array
+ */
+ cast : function(object, constructor, offset){
+
+ if(object.constructor === constructor){
+
+ return object;
+ };
+ if(qx.data && qx.data.IListData){
+
+ if(qx.Class && qx.Class.hasInterface(object, qx.data.IListData)){
+
+ var object = object.toArray();
+ };
+ };
+ // Create from given constructor
+ var ret = new constructor;
+ // Some collections in mshtml are not able to be sliced.
+ // These lines are a special workaround for this client.
+ if((qx.core.Environment.get("engine.name") == "mshtml")){
+
+ if(object.item){
+
+ for(var i = offset || 0,l = object.length;i < l;i++){
+
+ ret.push(object[i]);
+ };
+ return ret;
+ };
+ };
+ // Copy over items
+ if(Object.prototype.toString.call(object) === "[object Array]" && offset == null){
+
+ ret.push.apply(ret, object);
+ } else {
+
+ ret.push.apply(ret, Array.prototype.slice.call(object, offset || 0));
+ };
+ return ret;
+ },
+ /**
+ * Convert an arguments object into an array.
+ *
+ * @param args {arguments} arguments object
+ * @param offset {Integer?0} position to start from
+ * @return {Array} a newly created array (copy) with the content of the arguments object.
+ */
+ fromArguments : function(args, offset){
+
+ return Array.prototype.slice.call(args, offset || 0);
+ },
+ /**
+ * Convert a (node) collection into an array
+ *
+ * @param coll {var} node collection
+ * @return {Array} a newly created array (copy) with the content of the node collection.
+ */
+ fromCollection : function(coll){
+
+ // The native Array.slice cannot be used with some Array-like objects
+ // including NodeLists in older IEs
+ if((qx.core.Environment.get("engine.name") == "mshtml")){
+
+ if(coll.item){
+
+ var arr = [];
+ for(var i = 0,l = coll.length;i < l;i++){
+
+ arr[i] = coll[i];
+ };
+ return arr;
+ };
+ };
+ return Array.prototype.slice.call(coll, 0);
+ },
+ /**
+ * Expand shorthand definition to a four element list.
+ * This is an utility function for padding/margin and all other shorthand handling.
+ *
+ * @param input {Array} arr with one to four elements
+ * @return {Array} an arr with four elements
+ */
+ fromShortHand : function(input){
+
+ var len = input.length;
+ var result = qx.lang.Array.clone(input);
+ // Copy Values (according to the length)
+ switch(len){case 1:
+ result[1] = result[2] = result[3] = result[0];
+ break;case 2:
+ result[2] = result[0];// no break here
+ case 3:
+ result[3] = result[1];};
+ // Return list with 4 items
+ return result;
+ },
+ /**
+ * Return a copy of the given array
+ *
+ * @param arr {Array} the array to copy
+ * @return {Array} copy of the array
+ */
+ clone : function(arr){
+
+ return arr.concat();
+ },
+ /**
+ * Insert an element at a given position into the array
+ *
+ * @param arr {Array} the array
+ * @param obj {var} the element to insert
+ * @param i {Integer} position where to insert the element into the array
+ * @return {Array} the array
+ */
+ insertAt : function(arr, obj, i){
+
+ arr.splice(i, 0, obj);
+ return arr;
+ },
+ /**
+ * Insert an element into the array before a given second element.
+ *
+ * @param arr {Array} the array
+ * @param obj {var} object to be inserted
+ * @param obj2 {var} insert obj1 before this object
+ * @return {Array} the array
+ */
+ insertBefore : function(arr, obj, obj2){
+
+ var i = arr.indexOf(obj2);
+ if(i == -1){
+
+ arr.push(obj);
+ } else {
+
+ arr.splice(i, 0, obj);
+ };
+ return arr;
+ },
+ /**
+ * Insert an element into the array after a given second element.
+ *
+ * @param arr {Array} the array
+ * @param obj {var} object to be inserted
+ * @param obj2 {var} insert obj1 after this object
+ * @return {Array} the array
+ */
+ insertAfter : function(arr, obj, obj2){
+
+ var i = arr.indexOf(obj2);
+ if(i == -1 || i == (arr.length - 1)){
+
+ arr.push(obj);
+ } else {
+
+ arr.splice(i + 1, 0, obj);
+ };
+ return arr;
+ },
+ /**
+ * Remove an element from the array at the given index
+ *
+ * @param arr {Array} the array
+ * @param i {Integer} index of the element to be removed
+ * @return {var} The removed element.
+ */
+ removeAt : function(arr, i){
+
+ return arr.splice(i, 1)[0];
+ },
+ /**
+ * Remove all elements from the array
+ *
+ * @param arr {Array} the array
+ * @return {Array} empty array
+ */
+ removeAll : function(arr){
+
+ arr.length = 0;
+ return this;
+ },
+ /**
+ * Append the elements of an array to the array
+ *
+ * @param arr1 {Array} the array
+ * @param arr2 {Array} the elements of this array will be appended to other one
+ * @return {Array} The modified array.
+ * @throws {Error} if one of the arguments is not an array
+ */
+ append : function(arr1, arr2){
+
+ {
+ };
+ Array.prototype.push.apply(arr1, arr2);
+ return arr1;
+ },
+ /**
+ * Modifies the first array as it removes all elements
+ * which are listed in the second array as well.
+ *
+ * @param arr1 {Array} the array
+ * @param arr2 {Array} the elements of this array will be excluded from the other one
+ * @return {Array} The modified array.
+ * @throws {Error} if one of the arguments is not an array
+ */
+ exclude : function(arr1, arr2){
+
+ {
+ };
+ for(var i = 0,il = arr2.length,index;i < il;i++){
+
+ index = arr1.indexOf(arr2[i]);
+ if(index != -1){
+
+ arr1.splice(index, 1);
+ };
+ };
+ return arr1;
+ },
+ /**
+ * Remove an element from the array.
+ *
+ * @param arr {Array} the array
+ * @param obj {var} element to be removed from the array
+ * @return {var} the removed element
+ */
+ remove : function(arr, obj){
+
+ var i = arr.indexOf(obj);
+ if(i != -1){
+
+ arr.splice(i, 1);
+ return obj;
+ };
+ },
+ /**
+ * Whether the array contains the given element
+ *
+ * @param arr {Array} the array
+ * @param obj {var} object to look for
+ * @return {Boolean} whether the arr contains the element
+ */
+ contains : function(arr, obj){
+
+ return arr.indexOf(obj) !== -1;
+ },
+ /**
+ * Check whether the two arrays have the same content. Checks only the
+ * equality of the arrays' content.
+ *
+ * @param arr1 {Array} first array
+ * @param arr2 {Array} second array
+ * @return {Boolean} Whether the two arrays are equal
+ */
+ equals : function(arr1, arr2){
+
+ var length = arr1.length;
+ if(length !== arr2.length){
+
+ return false;
+ };
+ for(var i = 0;i < length;i++){
+
+ if(arr1[i] !== arr2[i]){
+
+ return false;
+ };
+ };
+ return true;
+ },
+ /**
+ * Returns the sum of all values in the given array. Supports
+ * numeric values only.
+ *
+ * @param arr {Number[]} Array to process
+ * @return {Number} The sum of all values.
+ */
+ sum : function(arr){
+
+ var result = 0;
+ for(var i = 0,l = arr.length;i < l;i++){
+
+ result += arr[i];
+ };
+ return result;
+ },
+ /**
+ * Returns the highest value in the given array. Supports
+ * numeric values only.
+ *
+ * @param arr {Number[]} Array to process
+ * @return {Number | null} The highest of all values or undefined if array is empty.
+ */
+ max : function(arr){
+
+ {
+ };
+ var i,len = arr.length,result = arr[0];
+ for(i = 1;i < len;i++){
+
+ if(arr[i] > result){
+
+ result = arr[i];
+ };
+ };
+ return result === undefined ? null : result;
+ },
+ /**
+ * Returns the lowest value in the given array. Supports
+ * numeric values only.
+ *
+ * @param arr {Number[]} Array to process
+ * @return {Number | null} The lowest of all values or undefined if array is empty.
+ */
+ min : function(arr){
+
+ {
+ };
+ var i,len = arr.length,result = arr[0];
+ for(i = 1;i < len;i++){
+
+ if(arr[i] < result){
+
+ result = arr[i];
+ };
+ };
+ return result === undefined ? null : result;
+ },
+ /**
+ * Recreates an array which is free of all duplicate elements from the original.
+ *
+ * This method do not modifies the original array!
+ *
+ * Keep in mind that this methods deletes undefined indexes.
+ *
+ * @param arr {Array} Incoming array
+ * @return {Array} Returns a copy with no duplicates or the original array if no duplicates were found
+ */
+ unique : function(arr){
+
+ var ret = [],doneStrings = {
+ },doneNumbers = {
+ },doneObjects = {
+ };
+ var value,count = 0;
+ var key = "qx" + Date.now();
+ var hasNull = false,hasFalse = false,hasTrue = false;
+ // Rebuild array and omit duplicates
+ for(var i = 0,len = arr.length;i < len;i++){
+
+ value = arr[i];
+ // Differ between null, primitives and reference types
+ if(value === null){
+
+ if(!hasNull){
+
+ hasNull = true;
+ ret.push(value);
+ };
+ } else if(value === undefined){
+ } else if(value === false){
+
+ if(!hasFalse){
+
+ hasFalse = true;
+ ret.push(value);
+ };
+ } else if(value === true){
+
+ if(!hasTrue){
+
+ hasTrue = true;
+ ret.push(value);
+ };
+ } else if(typeof value === "string"){
+
+ if(!doneStrings[value]){
+
+ doneStrings[value] = 1;
+ ret.push(value);
+ };
+ } else if(typeof value === "number"){
+
+ if(!doneNumbers[value]){
+
+ doneNumbers[value] = 1;
+ ret.push(value);
+ };
+ } else {
+
+ var hash = value[key];
+ if(hash == null){
+
+ hash = value[key] = count++;
+ };
+ if(!doneObjects[hash]){
+
+ doneObjects[hash] = value;
+ ret.push(value);
+ };
+ };;;;;
+ };
+ // Clear object hashs
+ for(var hash in doneObjects){
+
+ try{
+
+ delete doneObjects[hash][key];
+ } catch(ex) {
+
+ try{
+
+ doneObjects[hash][key] = null;
+ } catch(ex1) {
+
+ throw new Error("Cannot clean-up map entry doneObjects[" + hash + "][" + key + "]");
+ };
+ };
+ };
+ return ret;
+ }
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2008-2010 Sebastian Werner, http://sebastian-werner.net
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Fabian Jakobs (fjakobs)
+ * Andreas Ecker (ecker)
+
+ ======================================================================
+
+ This class contains code based on the following work:
+
+ * Sizzle CSS Selector Engine - v1.8.2
+
+ Homepage:
+ http://sizzlejs.com/
+
+ Documentation:
+ http://wiki.github.com/jeresig/sizzle
+
+ Discussion:
+ http://groups.google.com/group/sizzlejs
+
+ Code:
+ http://github.com/jeresig/sizzle/tree
+
+ Copyright:
+ (c) 2009, The Dojo Foundation
+
+ License:
+ MIT: http://www.opensource.org/licenses/mit-license.php
+
+ ----------------------------------------------------------------------
+
+ Copyright (c) 2009 John Resig
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ ----------------------------------------------------------------------
+
+ Version:
+ Snapshot taken on 2012-10-02, latest Sizzle commit on 2012-09-20:
+ commit 41a7c2ce9be6c66e0c9b8b15e0a29c8e3ca6fb31
+
+************************************************************************ */
+/**
+ * The selector engine supports virtually all CSS 3 Selectors – this even
+ * includes some parts that are infrequently implemented such as escaped
+ * selectors (.foo\\+bar), Unicode selectors, and results returned
+ * in document order. There are a few notable exceptions to the CSS 3 selector
+ * support:
+ *
+ * * :root
+ * * :target
+ * * :nth-last-child
+ * * :nth-of-type
+ * * :nth-last-of-type
+ * * :first-of-type
+ * * :last-of-type
+ * * :only-of-type
+ * * :lang()
+ *
+ * In addition to the CSS 3 Selectors the engine supports the following
+ * additional selectors or conventions.
+ *
+ * *Changes*
+ *
+ * * :not(a.b): Supports non-simple selectors in :not() (most browsers only support :not(a), for example).
+ * * :not(div > p): Supports full selectors in :not().
+ * * :not(div, p): Supports multiple selectors in :not().
+ * * [NAME=VALUE]: Doesn't require quotes around the specified value in an attribute selector.
+ *
+ * *Additions*
+ *
+ * * [NAME!=VALUE]: Finds all elements whose NAME attribute doesn't match the specified value. Is equivalent to doing :not([NAME=VALUE]).
+ * * :contains(TEXT): Finds all elements whose textual context contains the word TEXT (case sensitive).
+ * * :header: Finds all elements that are a header element (h1, h2, h3, h4, h5, h6).
+ * * :parent: Finds all elements that contains another element.
+ *
+ * *Positional Selector Additions*
+ *
+ * * :first/:last: Finds the first or last matching element on the page. (e.g. div:first would find the first div on the page, in document order)
+ * * :even/:odd: Finds every other element on the page (counting begins at 0, so :even would match the first element).
+ * * :eq/:nth: Finds the Nth element on the page (e.g. :eq(5) finds the 6th element on the page).
+ * * :lt/:gt: Finds all elements at positions less than or greater than the specified positions.
+ *
+ * *Form Selector Additions*
+ *
+ * * :input: Finds all input elements (includes textareas, selects, and buttons).
+ * * :text, :checkbox, :file, :password, :submit, :image, :reset, :button: Finds the input element with the specified input type (:button also finds button elements).
+ *
+ * Based on Sizzle by John Resig, see:
+ *
+ * * http://sizzlejs.com/
+ *
+ * For further usage details also have a look at the wiki page at:
+ *
+ * * https://github.com/jquery/sizzle/wiki/Sizzle-Home
+ */
+qx.Bootstrap.define("qx.bom.Selector", {
+ statics : {
+ /**
+ * Queries the document for the given selector. Supports all CSS3 selectors
+ * plus some extensions as mentioned in the class description.
+ *
+ * @signature function(selector, context)
+ * @param selector {String} Valid selector (CSS3 + extensions)
+ * @param context {Element} Context element (result elements must be children of this element)
+ * @return {Array} Matching elements
+ */
+ query : null,
+ /**
+ * Returns an reduced array which only contains the elements from the given
+ * array which matches the given selector
+ *
+ * @signature function(selector, set)
+ * @param selector {String} Selector to filter given set
+ * @param set {Array} List to filter according to given selector
+ * @return {Array} New array containing matching elements
+ */
+ matches : null
+ }
+});
+/**
+ * Below is the original Sizzle code. Snapshot date is mentioned in the head of
+ * this file.
+ * @lint ignoreUnused(j, rnot, rendsWithNot)
+ */
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function(window, undefined){
+
+ var cachedruns,assertGetIdNotName,Expr,getText,isXML,contains,compile,sortOrder,hasDuplicate,outermostContext,baseHasDuplicate = true,strundefined = "undefined",expando = ("sizcache" + Math.random()).replace(".", ""),Token = String,document = window.document,docElem = document.documentElement,dirruns = 0,done = 0,pop = [].pop,push = [].push,slice = [].slice,// Use a stripped-down indexOf if a native one is unavailable
+ indexOf = [].indexOf || function(elem){
+
+ var i = 0,len = this.length;
+ for(;i < len;i++){
+
+ if(this[i] === elem){
+
+ return i;
+ };
+ };
+ return -1;
+ },// Augment a function for special use by Sizzle
+ markFunction = function(fn, value){
+
+ fn[expando] = value == null || value;
+ return fn;
+ },createCache = function(){
+
+ var cache = {
+ },keys = [];
+ return markFunction(function(key, value){
+
+ // Only keep the most recent entries
+ if(keys.push(key) > Expr.cacheLength){
+
+ delete cache[keys.shift()];
+ };
+ return (cache[key] = value);
+ }, cache);
+ },classCache = createCache(),tokenCache = createCache(),compilerCache = createCache(),// Regex
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",// http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",// Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace("w", "w#"),// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",// Prefer arguments not in parens/brackets,
+ // then attribute selectors and non-pseudos (denoted by :),
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",// For matchExpr.POS and matchExpr.needsContext
+ pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),rcombinators = new RegExp("^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*"),rpseudo = new RegExp(pseudos),// Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,rnot = /^:not/,rsibling = /[\x20\t\r\n\f]*[+~]/,rendsWithNot = /:not\($/,rheader = /h\d/i,rinputs = /input|select|textarea|button/i,rbackslash = /\\(?!\\)/g,matchExpr = {
+ "ID" : new RegExp("^#(" + characterEncoding + ")"),
+ "CLASS" : new RegExp("^\\.(" + characterEncoding + ")"),
+ "NAME" : new RegExp("^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]"),
+ "TAG" : new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
+ "ATTR" : new RegExp("^" + attributes),
+ "PSEUDO" : new RegExp("^" + pseudos),
+ "POS" : new RegExp(pos, "i"),
+ "CHILD" : new RegExp("^:(only|nth|first|last)-child(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
+ // For use in libraries implementing .is()
+ "needsContext" : new RegExp("^" + whitespace + "*[>+~]|" + pos, "i")
+ },// Support
+ // Used for testing something on an element
+ assert = function(fn){
+
+ var div = document.createElement("div");
+ try{
+
+ return fn(div);
+ } catch(e) {
+
+ return false;
+ }finally{
+
+ // release memory in IE
+ div = null;
+ };
+ },// Check if getElementsByTagName("*") returns only elements
+ assertTagNameNoComments = assert(function(div){
+
+ div.appendChild(document.createComment(""));
+ return !div.getElementsByTagName("*").length;
+ }),// Check if getAttribute returns normalized href attributes
+ assertHrefNotNormalized = assert(function(div){
+
+ div.innerHTML = "";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && div.firstChild.getAttribute("href") === "#";
+ }),// Check if attributes should be retrieved by attribute nodes
+ assertAttributes = assert(function(div){
+
+ div.innerHTML = "";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ }),// Check if getElementsByClassName can be trusted
+ assertUsableClassName = assert(function(div){
+
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "";
+ if(!div.getElementsByClassName || !div.getElementsByClassName("e").length){
+
+ return false;
+ };
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ }),// Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ assertUsableName = assert(function(div){
+
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "";
+ docElem.insertBefore(div, docElem.firstChild);
+ // Test
+ var pass = document.getElementsByName && // buggy browsers will return fewer than the correct 2
+ document.getElementsByName(expando).length === 2 + // buggy browsers will return more than the correct 0
+ document.getElementsByName(expando + 0).length;
+ assertGetIdNotName = !document.getElementById(expando);
+ // Cleanup
+ docElem.removeChild(div);
+ return pass;
+ });
+ // If slice is not available, provide a backup
+ try{
+
+ slice.call(docElem.childNodes, 0)[0].nodeType;
+ } catch(e) {
+
+ slice = function(i){
+
+ var elem,results = [];
+ for(;(elem = this[i]);i++){
+
+ results.push(elem);
+ };
+ return results;
+ };
+ };
+ function Sizzle(selector, context, results, seed){
+
+ results = results || [];
+ context = context || document;
+ var match,elem,xml,m,nodeType = context.nodeType;
+ if(!selector || typeof selector !== "string"){
+
+ return results;
+ };
+ if(nodeType !== 1 && nodeType !== 9){
+
+ return [];
+ };
+ xml = isXML(context);
+ if(!xml && !seed){
+
+ if((match = rquickExpr.exec(selector))){
+
+ // Speed-up: Sizzle("#ID")
+ if((m = match[1])){
+
+ if(nodeType === 9){
+
+ elem = context.getElementById(m);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if(elem && elem.parentNode){
+
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if(elem.id === m){
+
+ results.push(elem);
+ return results;
+ };
+ } else {
+
+ return results;
+ };
+ } else {
+
+ // Context is not a document
+ if(context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && contains(context, elem) && elem.id === m){
+
+ results.push(elem);
+ return results;
+ };
+ };
+ } else if(match[2]){
+
+ push.apply(results, slice.call(context.getElementsByTagName(selector), 0));
+ return results;
+ } else if((m = match[3]) && assertUsableClassName && context.getElementsByClassName){
+
+ push.apply(results, slice.call(context.getElementsByClassName(m), 0));
+ return results;
+ };;
+ };
+ };
+ // All others
+ return select(selector.replace(rtrim, "$1"), context, results, seed, xml);
+ };
+ Sizzle.matches = function(expr, elements){
+
+ return Sizzle(expr, null, null, elements);
+ };
+ Sizzle.matchesSelector = function(elem, expr){
+
+ return Sizzle(expr, null, null, [elem]).length > 0;
+ };
+ // Returns a function to use in pseudos for input types
+ function createInputPseudo(type){
+
+ return function(elem){
+
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+ };
+ // Returns a function to use in pseudos for buttons
+ function createButtonPseudo(type){
+
+ return function(elem){
+
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+ };
+ // Returns a function to use in pseudos for positionals
+ function createPositionalPseudo(fn){
+
+ return markFunction(function(argument){
+
+ argument = +argument;
+ return markFunction(function(seed, matches){
+
+ var j,matchIndexes = fn([], seed.length, argument),i = matchIndexes.length;
+ // Match elements found at the specified indexes
+ while(i--){
+
+ if(seed[(j = matchIndexes[i])]){
+
+ seed[j] = !(matches[j] = seed[j]);
+ };
+ };
+ });
+ });
+ };
+ /**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param elem {Array|Element}
+ */
+ getText = Sizzle.getText = function(elem){
+
+ var node,ret = "",i = 0,nodeType = elem.nodeType;
+ if(nodeType){
+
+ if(nodeType === 1 || nodeType === 9 || nodeType === 11){
+
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if(typeof elem.textContent === "string"){
+
+ return elem.textContent;
+ } else {
+
+ // Traverse its children
+ for(elem = elem.firstChild;elem;elem = elem.nextSibling){
+
+ ret += getText(elem);
+ };
+ };
+ } else if(nodeType === 3 || nodeType === 4){
+
+ return elem.nodeValue;
+ };
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for(;(node = elem[i]);i++){
+
+ // Do not traverse comment nodes
+ ret += getText(node);
+ };
+ };
+ return ret;
+ };
+ isXML = Sizzle.isXML = function(elem){
+
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ };
+ // Element contains another
+ contains = Sizzle.contains = docElem.contains ? function(a, b){
+
+ var adown = a.nodeType === 9 ? a.documentElement : a,bup = b && b.parentNode;
+ return a === bup || !!(bup && bup.nodeType === 1 && adown.contains && adown.contains(bup));
+ } : docElem.compareDocumentPosition ? function(a, b){
+
+ return b && !!(a.compareDocumentPosition(b) & 16);
+ } : function(a, b){
+
+ while((b = b.parentNode)){
+
+ if(b === a){
+
+ return true;
+ };
+ };
+ return false;
+ };
+ Sizzle.attr = function(elem, name){
+
+ var val,xml = isXML(elem);
+ if(!xml){
+
+ name = name.toLowerCase();
+ };
+ if((val = Expr.attrHandle[name])){
+
+ return val(elem);
+ };
+ if(xml || assertAttributes){
+
+ return elem.getAttribute(name);
+ };
+ val = elem.getAttributeNode(name);
+ return val ? typeof elem[name] === "boolean" ? elem[name] ? name : null : val.specified ? val.value : null : null;
+ };
+ Expr = Sizzle.selectors = {
+ // Can be adjusted by the user
+ cacheLength : 50,
+ createPseudo : markFunction,
+ match : matchExpr,
+ // IE6/7 return a modified href
+ attrHandle : assertHrefNotNormalized ? {
+ } : {
+ "href" : function(elem){
+
+ return elem.getAttribute("href", 2);
+ },
+ "type" : function(elem){
+
+ return elem.getAttribute("type");
+ }
+ },
+ find : {
+ "ID" : assertGetIdNotName ? function(id, context, xml){
+
+ if(typeof context.getElementById !== strundefined && !xml){
+
+ var m = context.getElementById(id);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ };
+ } : function(id, context, xml){
+
+ if(typeof context.getElementById !== strundefined && !xml){
+
+ var m = context.getElementById(id);
+ return m ? m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? [m] : undefined : [];
+ };
+ },
+ "TAG" : assertTagNameNoComments ? function(tag, context){
+
+ if(typeof context.getElementsByTagName !== strundefined){
+
+ return context.getElementsByTagName(tag);
+ };
+ } : function(tag, context){
+
+ var results = context.getElementsByTagName(tag);
+ // Filter out possible comments
+ if(tag === "*"){
+
+ var elem,tmp = [],i = 0;
+ for(;(elem = results[i]);i++){
+
+ if(elem.nodeType === 1){
+
+ tmp.push(elem);
+ };
+ };
+ return tmp;
+ };
+ return results;
+ },
+ "NAME" : assertUsableName && function(tag, context){
+
+ if(typeof context.getElementsByName !== strundefined){
+
+ return context.getElementsByName(name);
+ };
+ },
+ "CLASS" : assertUsableClassName && function(className, context, xml){
+
+ if(typeof context.getElementsByClassName !== strundefined && !xml){
+
+ return context.getElementsByClassName(className);
+ };
+ }
+ },
+ relative : {
+ ">" : {
+ dir : "parentNode",
+ first : true
+ },
+ " " : {
+ dir : "parentNode"
+ },
+ "+" : {
+ dir : "previousSibling",
+ first : true
+ },
+ "~" : {
+ dir : "previousSibling"
+ }
+ },
+ preFilter : {
+ "ATTR" : function(match){
+
+ match[1] = match[1].replace(rbackslash, "");
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = (match[4] || match[5] || "").replace(rbackslash, "");
+ if(match[2] === "~="){
+
+ match[3] = " " + match[3] + " ";
+ };
+ return match.slice(0, 4);
+ },
+ "CHILD" : function(match){
+
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 3 xn-component of xn+y argument ([+-]?\d*n|)
+ 4 sign of xn-component
+ 5 x of xn-component
+ 6 sign of y-component
+ 7 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+ if(match[1] === "nth"){
+
+ // nth-child requires argument
+ if(!match[2]){
+
+ Sizzle.error(match[0]);
+ };
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[3] = +(match[3] ? match[4] + (match[5] || 1) : 2 * (match[2] === "even" || match[2] === "odd"));
+ match[4] = +((match[6] + match[7]) || match[2] === "odd");
+ } else if(match[2]){
+
+ Sizzle.error(match[0]);
+ };
+ return match;
+ },
+ "PSEUDO" : function(match){
+
+ var unquoted,excess;
+ if(matchExpr["CHILD"].test(match[0])){
+
+ return null;
+ };
+ if(match[3]){
+
+ match[2] = match[3];
+ } else if((unquoted = match[4])){
+
+ // Only check arguments that contain a pseudo
+ if(rpseudo.test(unquoted) && // Get excess from tokenize (recursively)
+ (excess = tokenize(unquoted, true)) && // advance to the next closing parenthesis
+ (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)){
+
+ // excess is a negative index
+ unquoted = unquoted.slice(0, excess);
+ match[0] = match[0].slice(0, excess);
+ };
+ match[2] = unquoted;
+ };
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice(0, 3);
+ }
+ },
+ filter : {
+ "ID" : assertGetIdNotName ? function(id){
+
+ id = id.replace(rbackslash, "");
+ return function(elem){
+
+ return elem.getAttribute("id") === id;
+ };
+ } : function(id){
+
+ id = id.replace(rbackslash, "");
+ return function(elem){
+
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === id;
+ };
+ },
+ "TAG" : function(nodeName){
+
+ if(nodeName === "*"){
+
+ return function(){
+
+ return true;
+ };
+ };
+ nodeName = nodeName.replace(rbackslash, "").toLowerCase();
+ return function(elem){
+
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+ "CLASS" : function(className){
+
+ var pattern = classCache[expando][className];
+ if(!pattern){
+
+ pattern = classCache(className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)"));
+ };
+ return function(elem){
+
+ return pattern.test(elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "");
+ };
+ },
+ "ATTR" : function(name, operator, check){
+
+ return function(elem, context){
+
+ var result = Sizzle.attr(elem, name);
+ if(result == null){
+
+ return operator === "!=";
+ };
+ if(!operator){
+
+ return true;
+ };
+ result += "";
+ return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.substr(result.length - check.length) === check : operator === "~=" ? (" " + result + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.substr(0, check.length + 1) === check + "-" : false;
+ };
+ },
+ "CHILD" : function(type, argument, first, last){
+
+ if(type === "nth"){
+
+ return function(elem){
+
+ var node,diff,parent = elem.parentNode;
+ if(first === 1 && last === 0){
+
+ return true;
+ };
+ if(parent){
+
+ diff = 0;
+ for(node = parent.firstChild;node;node = node.nextSibling){
+
+ if(node.nodeType === 1){
+
+ diff++;
+ if(elem === node){
+
+ break;
+ };
+ };
+ };
+ };
+ // Incorporate the offset (or cast to NaN), then check against cycle size
+ diff -= last;
+ return diff === first || (diff % first === 0 && diff / first >= 0);
+ };
+ };
+ return function(elem){
+
+ var node = elem;
+ switch(type){case "only":case "first":
+ while((node = node.previousSibling)){
+
+ if(node.nodeType === 1){
+
+ return false;
+ };
+ };
+ if(type === "first"){
+
+ return true;
+ };
+ node = elem;/* falls through */
+ case "last":
+ while((node = node.nextSibling)){
+
+ if(node.nodeType === 1){
+
+ return false;
+ };
+ };
+ return true;};
+ };
+ },
+ "PSEUDO" : function(pseudo, argument){
+
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error("unsupported pseudo: " + pseudo);
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if(fn[expando]){
+
+ return fn(argument);
+ };
+ // But maintain support for old signatures
+ if(fn.length > 1){
+
+ args = [pseudo, pseudo, "", argument];
+ return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function(seed, matches){
+
+ var idx,matched = fn(seed, argument),i = matched.length;
+ while(i--){
+
+ idx = indexOf.call(seed, matched[i]);
+ seed[idx] = !(matches[idx] = matched[i]);
+ };
+ }) : function(elem){
+
+ return fn(elem, 0, args);
+ };
+ };
+ return fn;
+ }
+ },
+ pseudos : {
+ "not" : markFunction(function(selector){
+
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],results = [],matcher = compile(selector.replace(rtrim, "$1"));
+ return matcher[expando] ? markFunction(function(seed, matches, context, xml){
+
+ var elem,unmatched = matcher(seed, null, xml, []),i = seed.length;
+ // Match elements unmatched by `matcher`
+ while(i--){
+
+ if((elem = unmatched[i])){
+
+ seed[i] = !(matches[i] = elem);
+ };
+ };
+ }) : function(elem, context, xml){
+
+ input[0] = elem;
+ matcher(input, null, xml, results);
+ return !results.pop();
+ };
+ }),
+ "has" : markFunction(function(selector){
+
+ return function(elem){
+
+ return Sizzle(selector, elem).length > 0;
+ };
+ }),
+ "contains" : markFunction(function(text){
+
+ return function(elem){
+
+ return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
+ };
+ }),
+ "enabled" : function(elem){
+
+ return elem.disabled === false;
+ },
+ "disabled" : function(elem){
+
+ return elem.disabled === true;
+ },
+ "checked" : function(elem){
+
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+ "selected" : function(elem){
+
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if(elem.parentNode){
+
+ elem.parentNode.selectedIndex;
+ };
+ return elem.selected === true;
+ },
+ "parent" : function(elem){
+
+ return !Expr.pseudos["empty"](elem);
+ },
+ "empty" : function(elem){
+
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ var nodeType;
+ elem = elem.firstChild;
+ while(elem){
+
+ if(elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4){
+
+ return false;
+ };
+ elem = elem.nextSibling;
+ };
+ return true;
+ },
+ "header" : function(elem){
+
+ return rheader.test(elem.nodeName);
+ },
+ "text" : function(elem){
+
+ var type,attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && (type = elem.type) === "text" && ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type);
+ },
+ // Input types
+ "radio" : createInputPseudo("radio"),
+ "checkbox" : createInputPseudo("checkbox"),
+ "file" : createInputPseudo("file"),
+ "password" : createInputPseudo("password"),
+ "image" : createInputPseudo("image"),
+ "submit" : createButtonPseudo("submit"),
+ "reset" : createButtonPseudo("reset"),
+ "button" : function(elem){
+
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+ "input" : function(elem){
+
+ return rinputs.test(elem.nodeName);
+ },
+ "focus" : function(elem){
+
+ var doc = elem.ownerDocument;
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
+ },
+ "active" : function(elem){
+
+ return elem === elem.ownerDocument.activeElement;
+ },
+ // Positional types
+ "first" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ return [0];
+ }),
+ "last" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ return [length - 1];
+ }),
+ "eq" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ return [argument < 0 ? argument + length : argument];
+ }),
+ "even" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ for(var i = 0;i < length;i += 2){
+
+ matchIndexes.push(i);
+ };
+ return matchIndexes;
+ }),
+ "odd" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ for(var i = 1;i < length;i += 2){
+
+ matchIndexes.push(i);
+ };
+ return matchIndexes;
+ }),
+ "lt" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ for(var i = argument < 0 ? argument + length : argument;--i >= 0;){
+
+ matchIndexes.push(i);
+ };
+ return matchIndexes;
+ }),
+ "gt" : createPositionalPseudo(function(matchIndexes, length, argument){
+
+ for(var i = argument < 0 ? argument + length : argument;++i < length;){
+
+ matchIndexes.push(i);
+ };
+ return matchIndexes;
+ })
+ }
+ };
+ function siblingCheck(a, b, ret){
+
+ if(a === b){
+
+ return ret;
+ };
+ var cur = a.nextSibling;
+ while(cur){
+
+ if(cur === b){
+
+ return -1;
+ };
+ cur = cur.nextSibling;
+ };
+ return 1;
+ };
+ sortOrder = docElem.compareDocumentPosition ? function(a, b){
+
+ if(a === b){
+
+ hasDuplicate = true;
+ return 0;
+ };
+ return (!a.compareDocumentPosition || !b.compareDocumentPosition ? a.compareDocumentPosition : a.compareDocumentPosition(b) & 4) ? -1 : 1;
+ } : function(a, b){
+
+ // The nodes are identical, we can exit early
+ if(a === b){
+
+ hasDuplicate = true;
+ return 0;
+ } else if(a.sourceIndex && b.sourceIndex){
+
+ return a.sourceIndex - b.sourceIndex;
+ };
+ var al,bl,ap = [],bp = [],aup = a.parentNode,bup = b.parentNode,cur = aup;
+ // If the nodes are siblings (or identical) we can do a quick check
+ if(aup === bup){
+
+ return siblingCheck(a, b);
+ } else if(!aup){
+
+ return -1;
+ } else if(!bup){
+
+ return 1;
+ };;
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while(cur){
+
+ ap.unshift(cur);
+ cur = cur.parentNode;
+ };
+ cur = bup;
+ while(cur){
+
+ bp.unshift(cur);
+ cur = cur.parentNode;
+ };
+ al = ap.length;
+ bl = bp.length;
+ // Start walking down the tree looking for a discrepancy
+ for(var i = 0;i < al && i < bl;i++){
+
+ if(ap[i] !== bp[i]){
+
+ return siblingCheck(ap[i], bp[i]);
+ };
+ };
+ // We ended someplace up the tree so do a sibling check
+ return i === al ? siblingCheck(a, bp[i], -1) : siblingCheck(ap[i], b, 1);
+ };
+ // Always assume the presence of duplicates if sort doesn't
+ // pass them to our comparison function (as in Google Chrome).
+ [0, 0].sort(sortOrder);
+ baseHasDuplicate = !hasDuplicate;
+ // Document sorting and removing duplicates
+ Sizzle.uniqueSort = function(results){
+
+ var elem,i = 1;
+ hasDuplicate = baseHasDuplicate;
+ results.sort(sortOrder);
+ if(hasDuplicate){
+
+ for(;(elem = results[i]);i++){
+
+ if(elem === results[i - 1]){
+
+ results.splice(i--, 1);
+ };
+ };
+ };
+ return results;
+ };
+ Sizzle.error = function(msg){
+
+ throw new Error("Syntax error, unrecognized expression: " + msg);
+ };
+ function tokenize(selector, parseOnly){
+
+ var matched,match,tokens,type,soFar,groups,preFilters,cached = tokenCache[expando][selector];
+ if(cached){
+
+ return parseOnly ? 0 : cached.slice(0);
+ };
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+ while(soFar){
+
+ // Comma and first run
+ if(!matched || (match = rcomma.exec(soFar))){
+
+ if(match){
+
+ soFar = soFar.slice(match[0].length);
+ };
+ groups.push(tokens = []);
+ };
+ matched = false;
+ // Combinators
+ if((match = rcombinators.exec(soFar))){
+
+ tokens.push(matched = new Token(match.shift()));
+ soFar = soFar.slice(matched.length);
+ // Cast descendant combinators to space
+ matched.type = match[0].replace(rtrim, " ");
+ };
+ // Filters
+ for(type in Expr.filter){
+
+ if((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || // The last two arguments here are (context, xml) for backCompat
+ (match = preFilters[type](match, document, true)))){
+
+ tokens.push(matched = new Token(match.shift()));
+ soFar = soFar.slice(matched.length);
+ matched.type = type;
+ matched.matches = match;
+ };
+ };
+ if(!matched){
+
+ break;
+ };
+ };
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : // Cache the tokens
+ tokenCache(selector, groups).slice(0);
+ };
+ function addCombinator(matcher, combinator, base){
+
+ var dir = combinator.dir,checkNonElements = base && combinator.dir === "parentNode",doneName = done++;
+ return combinator.first ? // Check against closest ancestor/preceding element
+ function(elem, context, xml){
+
+ while((elem = elem[dir])){
+
+ if(checkNonElements || elem.nodeType === 1){
+
+ return matcher(elem, context, xml);
+ };
+ };
+ } : // Check against all ancestor/preceding elements
+ function(elem, context, xml){
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if(!xml){
+
+ var cache,dirkey = dirruns + " " + doneName + " ",cachedkey = dirkey + cachedruns;
+ while((elem = elem[dir])){
+
+ if(checkNonElements || elem.nodeType === 1){
+
+ if((cache = elem[expando]) === cachedkey){
+
+ return elem.sizset;
+ } else if(typeof cache === "string" && cache.indexOf(dirkey) === 0){
+
+ if(elem.sizset){
+
+ return elem;
+ };
+ } else {
+
+ elem[expando] = cachedkey;
+ if(matcher(elem, context, xml)){
+
+ elem.sizset = true;
+ return elem;
+ };
+ elem.sizset = false;
+ };
+ };
+ };
+ } else {
+
+ while((elem = elem[dir])){
+
+ if(checkNonElements || elem.nodeType === 1){
+
+ if(matcher(elem, context, xml)){
+
+ return elem;
+ };
+ };
+ };
+ };
+ };
+ };
+ function elementMatcher(matchers){
+
+ return matchers.length > 1 ? function(elem, context, xml){
+
+ var i = matchers.length;
+ while(i--){
+
+ if(!matchers[i](elem, context, xml)){
+
+ return false;
+ };
+ };
+ return true;
+ } : matchers[0];
+ };
+ function condense(unmatched, map, filter, context, xml){
+
+ var elem,newUnmatched = [],i = 0,len = unmatched.length,mapped = map != null;
+ for(;i < len;i++){
+
+ if((elem = unmatched[i])){
+
+ if(!filter || filter(elem, context, xml)){
+
+ newUnmatched.push(elem);
+ if(mapped){
+
+ map.push(i);
+ };
+ };
+ };
+ };
+ return newUnmatched;
+ };
+ function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector){
+
+ if(postFilter && !postFilter[expando]){
+
+ postFilter = setMatcher(postFilter);
+ };
+ if(postFinder && !postFinder[expando]){
+
+ postFinder = setMatcher(postFinder, postSelector);
+ };
+ return markFunction(function(seed, results, context, xml){
+
+ // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
+ if(seed && postFinder){
+
+ return;
+ };
+ var i,elem,postFilterIn,preMap = [],postMap = [],preexisting = results.length,// Get initial elements from seed or context
+ elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, [], seed),// Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems,matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || (seed ? preFilter : preexisting || postFilter) ? // ...intermediate processing is necessary
+ [] : // ...otherwise use results directly
+ results : matcherIn;
+ // Find primary matches
+ if(matcher){
+
+ matcher(matcherIn, matcherOut, context, xml);
+ };
+ // Apply postFilter
+ if(postFilter){
+
+ postFilterIn = condense(matcherOut, postMap);
+ postFilter(postFilterIn, [], context, xml);
+ // Un-match failing elements by moving them back to matcherIn
+ i = postFilterIn.length;
+ while(i--){
+
+ if((elem = postFilterIn[i])){
+
+ matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
+ };
+ };
+ };
+ // Keep seed and results synchronized
+ if(seed){
+
+ // Ignore postFinder because it can't coexist with seed
+ i = preFilter && matcherOut.length;
+ while(i--){
+
+ if((elem = matcherOut[i])){
+
+ seed[preMap[i]] = !(results[preMap[i]] = elem);
+ };
+ };
+ } else {
+
+ matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);
+ if(postFinder){
+
+ postFinder(null, results, matcherOut, xml);
+ } else {
+
+ push.apply(results, matcherOut);
+ };
+ };
+ });
+ };
+ function matcherFromTokens(tokens){
+
+ var checkContext,matcher,j,len = tokens.length,leadingRelative = Expr.relative[tokens[0].type],implicitRelative = leadingRelative || Expr.relative[" "],i = leadingRelative ? 1 : 0,// The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator(function(elem){
+
+ return elem === checkContext;
+ }, implicitRelative, true),matchAnyContext = addCombinator(function(elem){
+
+ return indexOf.call(checkContext, elem) > -1;
+ }, implicitRelative, true),matchers = [function(elem, context, xml){
+
+ return (!leadingRelative && (xml || context !== outermostContext)) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml));
+ }];
+ for(;i < len;i++){
+
+ if((matcher = Expr.relative[tokens[i].type])){
+
+ matchers = [addCombinator(elementMatcher(matchers), matcher)];
+ } else {
+
+ // The concatenated values are (context, xml) for backCompat
+ matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
+ // Return special upon seeing a positional matcher
+ if(matcher[expando]){
+
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for(;j < len;j++){
+
+ if(Expr.relative[tokens[j].type]){
+
+ break;
+ };
+ };
+ return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && tokens.slice(0, i - 1).join("").replace(rtrim, "$1"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens((tokens = tokens.slice(j))), j < len && tokens.join(""));
+ };
+ matchers.push(matcher);
+ };
+ };
+ return elementMatcher(matchers);
+ };
+ function matcherFromGroupMatchers(elementMatchers, setMatchers){
+
+ var bySet = setMatchers.length > 0,byElement = elementMatchers.length > 0,superMatcher = function(seed, context, xml, results, expandContext){
+
+ var elem,j,matcher,setMatched = [],matchedCount = 0,i = "0",unmatched = seed && [],outermost = expandContext != null,contextBackup = outermostContext,// We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]("*", expandContext && context.parentNode || context),// Nested matchers should use non-integer dirruns
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
+ if(outermost){
+
+ outermostContext = context !== document && context;
+ cachedruns = superMatcher.el;
+ };
+ // Add elements passing elementMatchers directly to results
+ for(;(elem = elems[i]) != null;i++){
+
+ if(byElement && elem){
+
+ for(j = 0;(matcher = elementMatchers[j]);j++){
+
+ if(matcher(elem, context, xml)){
+
+ results.push(elem);
+ break;
+ };
+ };
+ if(outermost){
+
+ dirruns = dirrunsUnique;
+ cachedruns = ++superMatcher.el;
+ };
+ };
+ // Track unmatched elements for set filters
+ if(bySet){
+
+ // They will have gone through all possible matchers
+ if((elem = !matcher && elem)){
+
+ matchedCount--;
+ };
+ // Lengthen the array for every element, matched or not
+ if(seed){
+
+ unmatched.push(elem);
+ };
+ };
+ };
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if(bySet && i !== matchedCount){
+
+ for(j = 0;(matcher = setMatchers[j]);j++){
+
+ matcher(unmatched, setMatched, context, xml);
+ };
+ if(seed){
+
+ // Reintegrate element matches to eliminate the need for sorting
+ if(matchedCount > 0){
+
+ while(i--){
+
+ if(!(unmatched[i] || setMatched[i])){
+
+ setMatched[i] = pop.call(results);
+ };
+ };
+ };
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense(setMatched);
+ };
+ // Add matches to results
+ push.apply(results, setMatched);
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if(outermost && !seed && setMatched.length > 0 && (matchedCount + setMatchers.length) > 1){
+
+ Sizzle.uniqueSort(results);
+ };
+ };
+ // Override manipulation of globals by nested matchers
+ if(outermost){
+
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ };
+ return unmatched;
+ };
+ superMatcher.el = 0;
+ return bySet ? markFunction(superMatcher) : superMatcher;
+ };
+ compile = Sizzle.compile = function(selector, group){
+
+ var i,setMatchers = [],elementMatchers = [],cached = compilerCache[expando][selector];
+ if(!cached){
+
+ // Generate a function of recursive functions that can be used to check each element
+ if(!group){
+
+ group = tokenize(selector);
+ };
+ i = group.length;
+ while(i--){
+
+ cached = matcherFromTokens(group[i]);
+ if(cached[expando]){
+
+ setMatchers.push(cached);
+ } else {
+
+ elementMatchers.push(cached);
+ };
+ };
+ // Cache the compiled function
+ cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
+ };
+ return cached;
+ };
+ function multipleContexts(selector, contexts, results, seed){
+
+ var i = 0,len = contexts.length;
+ for(;i < len;i++){
+
+ Sizzle(selector, contexts[i], results, seed);
+ };
+ return results;
+ };
+ function select(selector, context, results, seed, xml){
+
+ var i,tokens,token,type,find,match = tokenize(selector),j = match.length;
+ if(!seed){
+
+ // Try to minimize operations if there is only one group
+ if(match.length === 1){
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice(0);
+ if(tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && !xml && Expr.relative[tokens[1].type]){
+
+ context = Expr.find["ID"](token.matches[0].replace(rbackslash, ""), context, xml)[0];
+ if(!context){
+
+ return results;
+ };
+ selector = selector.slice(tokens.shift().length);
+ };
+ // Fetch a seed set for right-to-left matching
+ for(i = matchExpr["POS"].test(selector) ? -1 : tokens.length - 1;i >= 0;i--){
+
+ token = tokens[i];
+ // Abort if we hit a combinator
+ if(Expr.relative[(type = token.type)]){
+
+ break;
+ };
+ if((find = Expr.find[type])){
+
+ // Search, expanding context for leading sibling combinators
+ if((seed = find(token.matches[0].replace(rbackslash, ""), rsibling.test(tokens[0].type) && context.parentNode || context, xml))){
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice(i, 1);
+ selector = seed.length && tokens.join("");
+ if(!selector){
+
+ push.apply(results, slice.call(seed, 0));
+ return results;
+ };
+ break;
+ };
+ };
+ };
+ };
+ };
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile(selector, match)(seed, context, xml, results, rsibling.test(selector));
+ return results;
+ };
+ if(document.querySelectorAll){
+
+ (function(){
+
+ var disconnectedMatch,oldSelect = select,rescape = /'|\\/g,rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,// qSa(:focus) reports false when true (Chrome 21),
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [":focus"],// matchesSelector(:focus) reports false when true (Chrome 21),
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ // A support test would require too much code (would include document ready)
+ // just skip matchesSelector for :active
+ rbuggyMatches = [":active", ":focus"],matches = docElem.matchesSelector || docElem.mozMatchesSelector || docElem.webkitMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector;
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function(div){
+
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "";
+ // IE8 - Some boolean attributes are not treated correctly
+ if(!div.querySelectorAll("[selected]").length){
+
+ rbuggyQSA.push("\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)");
+ };
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here (do not put tests after this one)
+ if(!div.querySelectorAll(":checked").length){
+
+ rbuggyQSA.push(":checked");
+ };
+ });
+ assert(function(div){
+
+ // Opera 10-12/IE9 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = "";
+ if(div.querySelectorAll("[test^='']").length){
+
+ rbuggyQSA.push("[*^$]=" + whitespace + "*(?:\"\"|'')");
+ };
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here (do not put tests after this one)
+ div.innerHTML = "";
+ if(!div.querySelectorAll(":enabled").length){
+
+ rbuggyQSA.push(":enabled", ":disabled");
+ };
+ });
+ // rbuggyQSA always contains :focus, so no need for a length check
+ rbuggyQSA = /* rbuggyQSA.length && */ new RegExp(rbuggyQSA.join("|"));
+ select = function(selector, context, results, seed, xml){
+
+ // Only use querySelectorAll when not filtering,
+ // when this is not xml,
+ // and when no QSA bugs apply
+ if(!seed && !xml && (!rbuggyQSA || !rbuggyQSA.test(selector))){
+
+ var groups,i,old = true,nid = expando,newContext = context,newSelector = context.nodeType === 9 && selector;
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if(context.nodeType === 1 && context.nodeName.toLowerCase() !== "object"){
+
+ groups = tokenize(selector);
+ if((old = context.getAttribute("id"))){
+
+ nid = old.replace(rescape, "\\$&");
+ } else {
+
+ context.setAttribute("id", nid);
+ };
+ nid = "[id='" + nid + "'] ";
+ i = groups.length;
+ while(i--){
+
+ groups[i] = nid + groups[i].join("");
+ };
+ newContext = rsibling.test(selector) && context.parentNode || context;
+ newSelector = groups.join(",");
+ };
+ if(newSelector){
+
+ try{
+
+ push.apply(results, slice.call(newContext.querySelectorAll(newSelector), 0));
+ return results;
+ } catch(qsaError) {
+ }finally{
+
+ if(!old){
+
+ context.removeAttribute("id");
+ };
+ };
+ };
+ };
+ return oldSelect(selector, context, results, seed, xml);
+ };
+ if(matches){
+
+ assert(function(div){
+
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ disconnectedMatch = matches.call(div, "div");
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ try{
+
+ matches.call(div, "[test!='']:sizzle");
+ rbuggyMatches.push("!=", pseudos);
+ } catch(e) {
+ };
+ });
+ // rbuggyMatches always contains :active and :focus, so no need for a length check
+ rbuggyMatches = /* rbuggyMatches.length && */ new RegExp(rbuggyMatches.join("|"));
+ Sizzle.matchesSelector = function(elem, expr){
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(rattributeQuotes, "='$1']");
+ // rbuggyMatches always contains :active, so no need for an existence check
+ if(!isXML(elem) && !rbuggyMatches.test(expr) && (!rbuggyQSA || !rbuggyQSA.test(expr))){
+
+ try{
+
+ var ret = matches.call(elem, expr);
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if(ret || disconnectedMatch || // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11){
+
+ return ret;
+ };
+ } catch(e) {
+ };
+ };
+ return Sizzle(expr, null, null, [elem]).length > 0;
+ };
+ };
+ })();
+ };
+ // Deprecated
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
+ // Back-compat
+ function setFilters(){
+ };
+ Expr.filters = setFilters.prototype = Expr.pseudos;
+ Expr.setFilters = new setFilters();
+ // EXPOSE qooxdoo variant
+ qx.bom.Selector.query = function(selector, context){
+
+ return Sizzle(selector, context);
+ };
+ qx.bom.Selector.matches = function(selector, set){
+
+ return Sizzle(selector, null, null, set);
+ };
+})(window);
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2007-2008 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Fabian Jakobs (fjakobs)
+
+************************************************************************ */
+/**
+ * Utility class with type check for all native JavaScript data types.
+ */
+qx.Bootstrap.define("qx.lang.Type", {
+ statics : {
+ /**
+ * Get the internal class of the value. See
+ * http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
+ * for details.
+ *
+ * @signature function(value)
+ * @param value {var} value to get the class for
+ * @return {String} the internal class of the value
+ */
+ getClass : qx.Bootstrap.getClass,
+ /**
+ * Whether the value is a string.
+ *
+ * @signature function(value)
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a string.
+ */
+ isString : qx.Bootstrap.isString,
+ /**
+ * Whether the value is an array.
+ *
+ * @signature function(value)
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is an array.
+ */
+ isArray : qx.Bootstrap.isArray,
+ /**
+ * Whether the value is an object. Note that built-in types like Window are
+ * not reported to be objects.
+ *
+ * @signature function(value)
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is an object.
+ */
+ isObject : qx.Bootstrap.isObject,
+ /**
+ * Whether the value is a function.
+ *
+ * @signature function(value)
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a function.
+ */
+ isFunction : qx.Bootstrap.isFunction,
+ /**
+ * Whether the value is a regular expression.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a regular expression.
+ */
+ isRegExp : function(value){
+
+ return this.getClass(value) == "RegExp";
+ },
+ /**
+ * Whether the value is a number.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a number.
+ */
+ isNumber : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof Number" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal different between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (this.getClass(value) == "Number" || value instanceof Number));
+ },
+ /**
+ * Whether the value is a boolean.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a boolean.
+ */
+ isBoolean : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof Boolean" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal different between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (this.getClass(value) == "Boolean" || value instanceof Boolean));
+ },
+ /**
+ * Whether the value is a date.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a date.
+ */
+ isDate : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof Date" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal different between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (this.getClass(value) == "Date" || value instanceof Date));
+ },
+ /**
+ * Whether the value is a Error.
+ *
+ * @param value {var} Value to check.
+ * @return {Boolean} Whether the value is a Error.
+ */
+ isError : function(value){
+
+ // Added "value !== null" because IE throws an exception "Object expected"
+ // by executing "value instanceof Error" if value is a DOM element that
+ // doesn't exist. It seems that there is an internal different between a
+ // JavaScript null and a null returned from calling DOM.
+ // e.q. by document.getElementById("ReturnedNull").
+ return (value !== null && (this.getClass(value) == "Error" || value instanceof Error));
+ }
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2007-2013 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Romeo Kenfack (rkenfack)
+
+************************************************************************ */
+/**
+ * Module for handling of HTML5 data-* attributes
+ */
+qx.Bootstrap.define("qx.module.Dataset", {
+ statics : {
+ /**
+ * Sets an HTML "data-*" attribute on each item in the collection
+ *
+ * @attach {qxWeb}
+ * @param name {String} Name of the attribute [CamelCase variant]
+ * @param value {var} New value of the attribute
+ * @return {qxWeb} The collection for chaining
+ */
+ setData : function(name, value){
+
+ this._forEachElement(function(item){
+
+ qx.bom.element.Dataset.set(item, name, value);
+ });
+ return this;
+ },
+ /**
+ *
+ * Returns the value of the given HTML "data-*" attribute for the first item in the collection
+ *
+ * @attach {qxWeb}
+ * @param name {String} Name of the attribute [CamelCase variant]
+ * @return {var} The value of the attribute
+ *
+ */
+ getData : function(name){
+
+ if(this[0] && this[0].nodeType === 1){
+
+ return qx.bom.element.Dataset.get(this[0], name);
+ };
+ return null;
+ },
+ /**
+ * Returns a map containing all the HTML "data-*" attributes of the specified element
+ *
+ * @attach {qxWeb}
+ * @return {Map} The map containing the "data-*" attributes
+ *
+ */
+ getAllData : function(){
+
+ if(this[0] && this[0].nodeType === 1){
+
+ return qx.bom.element.Dataset.getAll(this[0]);
+ };
+ return null;
+ },
+ /**
+ * Remove an HTML "data-*" attribute from the given DOM element
+ *
+ * @attach {qxWeb}
+ * @param name {String} Name of the attribute
+ * @return {qxWeb} The collection for chaining
+ */
+ removeData : function(name){
+
+ if(this[0] && this[0].nodeType === 1){
+
+ qx.bom.element.Dataset.remove(this[0], name);
+ };
+ return this;
+ }
+ },
+ defer : function(statics){
+
+ qxWeb.$attach({
+ "getData" : statics.getData,
+ "setData" : statics.setData,
+ "removeData" : statics.removeData,
+ "getAllData" : statics.getAllData
+ });
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2011 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Author:
+ * Gabriel Munteanu (gabios)
+
+************************************************************************ */
+/**
+ * Data-* attribute handling for DOM HTML elements.
+ *
+ * This feature set is supported cross-browser
+ * through one common interface and is independent of the differences between
+ * the multiple implementations.
+ *
+ */
+qx.Bootstrap.define("qx.bom.element.Dataset", {
+ /*
+ *****************************************************************************
+ STATICS
+ *****************************************************************************
+ */
+ statics : {
+ /**
+ * Sets an HTML attribute on the given DOM element
+ *
+ * @param element {Element} The DOM element to modify
+ * @param name {String} Name of the attribute [CamelCase variant]
+ * @param value {var} New value of the attribute
+ *
+ */
+ set : function(element, name, value){
+
+ if(element.dataset){
+
+ name = qx.lang.String.camelCase(name);
+ if(value != null){
+
+ element.dataset[name] = value;
+ } else {
+
+ delete element.dataset[name];
+ };
+ } else {
+
+ qx.bom.element.Attribute.set(element, "data-" + qx.lang.String.hyphenate(name), value);
+ };
+ },
+ /**
+ *
+ * Returns the value of the given HTML "data-*" attribute
+ *
+ * @param element {Element} The DOM element to query
+ * @param name {String} Name of the attribute [CamelCase variant]
+ * @return {var} The value of the attribute
+ *
+ */
+ get : function(element, name){
+
+ if(element.dataset){
+
+ name = qx.lang.String.camelCase(name);
+ return (name in element.dataset) ? element.dataset[name] : null;
+ } else {
+
+ return qx.bom.element.Attribute.get(element, "data-" + qx.lang.String.hyphenate(name));
+ };
+ },
+ /**
+ *
+ * Returns a map containing all the HTML "data-*" attributes of the specified element
+ *
+ * @param element {Element} The DOM element to query
+ * @return {Map} The map containing all the "data-*" attributes
+ *
+ */
+ getAll : function(element){
+
+ if(element.dataset){
+
+ return element.dataset;
+ } else {
+
+ var res = {
+ },attr = element.attributes;
+ for(var i = 0;i < attr.length;i++){
+
+ if(attr[i].name.match(RegExp("^data-(.*)"))){
+
+ var key = RegExp.$1;
+ res[qx.lang.String.camelCase(key)] = element.getAttribute(attr[i].name);
+ };
+ };
+ return res;
+ };
+ },
+ /**
+ * Remove an HTML "data-*" attribute from the given DOM element
+ *
+ * @param element {Element} The DOM element to modify
+ * @param name {String} Name of the attribute
+ *
+ */
+ remove : function(element, name){
+
+ this.set(element, name, null);
+ }
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2012 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Martin Wittemann (wittemann)
+
+************************************************************************ */
+/**
+ * This class takes care of the normalization of the native 'String' object.
+ * Therefore it checks the availability of the following methods and appends
+ * it, if not available. This means you can use the methods during
+ * development in every browser. For usage samples, check out the attached links.
+ *
+ * *trim*:
+ * MDN documentation |
+ * Annotated ES5 Spec
+ */
+qx.Bootstrap.define("qx.lang.normalize.String", {
+ defer : function(){
+
+ // trim
+ if(!qx.core.Environment.get("ecmascript.string.trim")){
+
+ String.prototype.trim = function(context){
+
+ return this.replace(/^\s+|\s+$/g, '');
+ };
+ };
+ }
+});
+
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
+
+ License:
+ LGPL: http://www.gnu.org/licenses/lgpl.html
+ EPL: http://www.eclipse.org/org/documents/epl-v10.php
+ See the LICENSE file in the project's top-level directory for details.
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+ ======================================================================
+
+ This class contains code based on the following work:
+
+ * Mootools
+ http://mootools.net/
+ Version 1.1.1
+
+ Copyright:
+ (c) 2007 Valerio Proietti
+
+ License:
+ MIT: http://www.opensource.org/licenses/mit-license.php
+
+ and
+
+ * XRegExp
+ http://xregexp.com/
+ Version 1.5
+
+ Copyright:
+ (c) 2006-2007, Steven Levithan qx.lang.String.camelCase("I-like-cookies"); //returns "ILikeCookies"
+ *
+ * @param str {String} hyphenated string
+ * @return {String} camelcase string
+ */
+ camelCase : function(str){
+
+ var result = this.__stringsMap[str];
+ if(!result){
+
+ result = str.replace(/\-([a-z])/g, function(match, chr){
+
+ return chr.toUpperCase();
+ });
+ if(str.indexOf("-") >= 0){
+
+ this.__stringsMap[str] = result;
+ };
+ };
+ return result;
+ },
+ /**
+ * Converts a camelcased string to a hyphenated (separated by '-') string.
+ *
+ * Example:
+ * qx.lang.String.hyphenate("weLikeCookies"); //returns "we-like-cookies"
+ *
+ * @param str {String} camelcased string
+ * @return {String} hyphenated string
+ */
+ hyphenate : function(str){
+
+ var result = this.__stringsMap[str];
+ if(!result){
+
+ result = str.replace(/[A-Z]/g, function(match){
+
+ return ('-' + match.charAt(0).toLowerCase());
+ });
+ if(str.indexOf("-") == -1){
+
+ this.__stringsMap[str] = result;
+ };
+ };
+ return result;
+ },
+ /**
+ * Converts a string to camel case.
+ *
+ * Example:
+ * qx.lang.String.camelCase("i like cookies"); //returns "I Like Cookies"
+ *
+ * @param str {String} any string
+ * @return {String} capitalized string
+ */
+ capitalize : function(str){
+
+ if(this.__unicodeFirstLetterInWordRegexp === null){
+
+ var unicodeEscapePrefix = '\\u';
+ this.__unicodeFirstLetterInWordRegexp = new RegExp("(^|[^" + this.__unicodeLetters.replace(/[0-9A-F]{4}/g, function(match){
+
+ return unicodeEscapePrefix + match;
+ }) + "])[" + this.__unicodeLetters.replace(/[0-9A-F]{4}/g, function(match){
+
+ return unicodeEscapePrefix + match;
+ }) + "]", "g");
+ };
+ return str.replace(this.__unicodeFirstLetterInWordRegexp, function(match){
+
+ return match.toUpperCase();
+ });
+ },
+ /**
+ * Removes all extraneous whitespace from a string and trims it
+ *
+ * Example:
+ *
+ *
+ * qx.lang.String.clean(" i like cookies \n\n");
+ *
+ *
+ * Returns "i like cookies"
+ *
+ * @param str {String} the string to clean up
+ * @return {String} Cleaned up string
+ */
+ clean : function(str){
+
+ return str.replace(/\s+/g, ' ').trim();
+ },
+ /**
+ * removes white space from the left side of a string
+ *
+ * @param str {String} the string to trim
+ * @return {String} the trimmed string
+ */
+ trimLeft : function(str){
+
+ return str.replace(/^\s+/, "");
+ },
+ /**
+ * removes white space from the right side of a string
+ *
+ * @param str {String} the string to trim
+ * @return {String} the trimmed string
+ */
+ trimRight : function(str){
+
+ return str.replace(/\s+$/, "");
+ },
+ /**
+ * Check whether the string starts with the given substring
+ *
+ * @param fullstr {String} the string to search in
+ * @param substr {String} the substring to look for
+ * @return {Boolean} whether the string starts with the given substring
+ */
+ startsWith : function(fullstr, substr){
+
+ return fullstr.indexOf(substr) === 0;
+ },
+ /**
+ * Check whether the string ends with the given substring
+ *
+ * @param fullstr {String} the string to search in
+ * @param substr {String} the substring to look for
+ * @return {Boolean} whether the string ends with the given substring
+ */
+ endsWith : function(fullstr, substr){
+
+ return fullstr.substring(fullstr.length - substr.length, fullstr.length) === substr;
+ },
+ /**
+ * Returns a string, which repeats a string 'length' times
+ *
+ * @param str {String} string used to repeat
+ * @param times {Integer} the number of repetitions
+ * @return {String} repeated string
+ */
+ repeat : function(str, times){
+
+ return str.length > 0 ? new Array(times + 1).join(str) : "";
+ },
+ /**
+ * Pad a string up to a given length. Padding characters are added to the left of the string.
+ *
+ * @param str {String} the string to pad
+ * @param length {Integer} the final length of the string
+ * @param ch {String} character used to fill up the string
+ * @return {String} padded string
+ */
+ pad : function(str, length, ch){
+
+ var padLength = length - str.length;
+ if(padLength > 0){
+
+ if(typeof ch === "undefined"){
+
+ ch = "0";
+ };
+ return this.repeat(ch, padLength) + str;
+ } else {
+
+ return str;
+ };
+ },
+ /**
+ * Convert the first character of the string to upper case.
+ *
+ * @signature function(str)
+ * @param str {String} the string
+ * @return {String} the string with an upper case first character
+ */
+ firstUp : qx.Bootstrap.firstUp,
+ /**
+ * Convert the first character of the string to lower case.
+ *
+ * @signature function(str)
+ * @param str {String} the string
+ * @return {String} the string with a lower case first character
+ */
+ firstLow : qx.Bootstrap.firstLow,
+ /**
+ * Check whether the string contains a given substring
+ *
+ * @param str {String} the string
+ * @param substring {String} substring to search for
+ * @return {Boolean} whether the string contains the substring
+ */
+ contains : function(str, substring){
+
+ return str.indexOf(substring) != -1;
+ },
+ /**
+ * Print a list of arguments using a format string
+ * In the format string occurrences of %n are replaced by the n'th element of the args list.
+ * Example:
+ * qx.lang.String.format("Hello %1, my name is %2", ["Egon", "Franz"]) == "Hello Egon, my name is Franz"
+ *
+ * @param pattern {String} format string
+ * @param args {Array} array of arguments to insert into the format string
+ * @return {String} the formatted string
+ */
+ format : function(pattern, args){
+
+ var str = pattern;
+ var i = args.length;
+ while(i--){
+
+ // be sure to always use a string for replacement.
+ str = str.replace(new RegExp("%" + (i + 1), "g"), args[i] + "");
+ };
+ return str;
+ },
+ /**
+ * Escapes all chars that have a special meaning in regular expressions
+ *
+ * @param str {String} the string where to escape the chars.
+ * @return {String} the string with the escaped chars.
+ */
+ escapeRegexpChars : function(str){
+
+ return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
+ },
+ /**
+ * Converts a string to an array of characters.
+ * "hello" => [ "h", "e", "l", "l", "o" ];+ * + * @param str {String} the string which should be split + * @return {Array} the result array of characters + */ + toArray : function(str){ + + return str.split(/\B|\b/g); + }, + /** + * Remove HTML/XML tags from a string + * Example: + *
qx.lang.String.stripTags("<h1>Hello</h1>") == "Hello"
+ *
+ * @param str {String} string containing tags
+ * @return {String} the string with stripped tags
+ */
+ stripTags : function(str){
+
+ return str.replace(/<\/?[^>]+>/gi, "");
+ },
+ /**
+ * Strips