diff --git a/ajax/libs/qooxdoo/2.0.3/q.js b/ajax/libs/qooxdoo/2.0.3/q.js new file mode 100644 index 000000000..a027e8d6e --- /dev/null +++ b/ajax/libs/qooxdoo/2.0.3/q.js @@ -0,0 +1,25235 @@ +/** qooxdoo v.2.0.3 | (c) 2012 1&1 Internet AG 1und1.de | qooxdoo.org/license */ +(function(){ +if (!window.qx) window.qx = {}; +var qx = window.qx; + +if (!qx.$$environment) qx.$$environment = {}; +var envinfo = {"qx.application":"library.Application","qx.debug":false,"qx.debug.databinding":false,"qx.debug.dispose":false,"qx.optimization.variants":true,"qx.revision":"","qx.theme":"qx.theme.Modern","qx.version":"2.0.3"}; +for (var k in envinfo) qx.$$environment[k] = envinfo[k]; + +qx.$$packageData = {}; + +/** qooxdoo v.2.0.3 | (c) 2012 1&1 Internet AG 1und1.de | 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) + +************************************************************************ */ +/* ************************************************************************ + +#ignore(qx.data) +#ignore(qx.data.IListData) +#ignore(qx.util.OOUtil) + +************************************************************************ */ +/** + * Create namespace + */ +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 parent = window; + var part = splits[0]; + 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 + "()"; + }; + }; + }, + 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 getKeys to include the shadowed in IE + for(var i = 0,keys = qx.Bootstrap.getKeys(statics),l = keys.length;i < l;i++){ + + var key = keys[i]; + clazz[key] = statics[key]; + }; + proto = clazz.prototype; + var members = config.members || { + }; + // use getKeys to include the shadowed in IE + for(var i = 0,keys = qx.Bootstrap.getKeys(members),l = keys.length;i < l;i++){ + + var key = keys[i]; + proto[key] = members[key]; + }; + } else { + + clazz = config.statics || { + }; + }; + // Create namespace + var basename = name ? this.createNamespace(name, clazz) : ""; + // Store names in constructor/object + clazz.name = clazz.classname = name; + clazz.basename = basename; + // Store type info + clazz.$$type = "Class"; + // Attach toString + if(!clazz.hasOwnProperty("toString")){ + + clazz.toString = this.genericToString; + }; + // 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. + * + * Automatically loads JavaScript language fixes and enhancements to + * bring all engines to at least JavaScript 1.6. + * + * Does support: + * + * * Construct + * * Statics + * * Members + * * Extend + * * Defer + * + * Does not support: + * + * * Super class calls + * * Mixins, Interfaces, Properties, ... + */ +qx.Bootstrap.define("qx.Bootstrap", { + statics : { + /** 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 an exception when the given object already exists. + */ + createNamespace : qx.Bootstrap.createNamespace, + /** + * Define a new class using the qooxdoo class system. + * Lightweight version of {@link qx.Class#define} only used during bootstrap phase. + * + * @internal + * @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. + * @return {Class} The defined class + */ + define : qx.Bootstrap.define, + /** + * Sets the display name of the given function + * + * @signature function(fcn, classname, name) + * @param fcn {Function} the function to set the display name for + * @param classname {String} the name of the class the function is defined in + * @param name {String} the function name + */ + setDisplayName : qx.Bootstrap.setDisplayName, + /** + * Set the names of all functions defined in the given map + * + * @signature function(functionMap, classname) + * @param functionMap {Object} a map with functions as values + * @param classname {String} the name of the class, the functions are + * defined in + */ + setDisplayNames : qx.Bootstrap.setDisplayNames, + /** + * This method will be attached to all classes to return + * a nice identifier for them. + * + * @internal + * @signature function() + * @return {String} The class identifier + */ + genericToString : qx.Bootstrap.genericToString, + /** + * Inherit a clazz from a super class. + * + * This function differentiates between class and constructor because the + * constructor written by the user might be wrapped and the 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 = 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]; + }, + /** {Map} Stores all defined classes */ + $$registry : { + }, + /* + --------------------------------------------------------------------------- + OBJECT UTILITY FUNCTIONS + --------------------------------------------------------------------------- + */ + /** + * Get the number of objects in the map + * + * @signature function(map) + * @param map {Object} the map + * @return {Integer} number of objects in the map + */ + objectGetLength : function(map){ + + var length = 0; + for(var key in map){ + + length++; + }; + return 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", "constructor"], + /** + * Get the keys of a map as array as returned by a "for ... in" statement. + * + * @signature function(map) + * @param map {Object} the map + * @return {Array} array of the keys of the map + */ + getKeys : ({ + "ES5" : Object.keys, + "BROKEN_IE" : function(map){ + + 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){ + + 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"], + /** + * Get the keys of a map as string + * + * @param map {Object} the map + * @return {String} String of the keys of the map + * The keys are separated by ", " + */ + getKeysAsString : function(map){ + + var keys = qx.Bootstrap.getKeys(map); + if(keys.length == 0){ + + return ""; + }; + return '"' + keys.join('\", "') + '"'; + }, + /** + * 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 different 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 different 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. + * @return {void} + */ + 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. + * @return {void} + */ + 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. + * @return {void} + */ + 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. + * @return {void} + */ + 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-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) + * Fabian Jakobs (fjakobs) + +************************************************************************ */ +/** + * The intention of this class is to add features to native JavaScript + * objects so that all browsers operate on a common JavaScript language level + * (particularly JavaScript 1.6). + * + * The methods defined in this class contain implementations of methods, which + * are not supported by all browsers. If a method is supported it points to + * the native implementation, otherwise it contains an emulation function. + * + * For reference: + * + * * http://www.ecma-international.org/publications/standards/Ecma-262.htm + * * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference + * * http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6 + * + * The following methods are added if they are not supported natively: + * + * * Error.toString() + * * Array.indexOf() + * * Array.lastIndexOf() + * * Array.forEach() + * * Array.filter() + * * Array.map() + * * Array.some() + * * Array.every() + * * String.quote() + */ +qx.Bootstrap.define("qx.lang.Core", { + statics : { + /** + * Some browsers (e.g. Internet Explorer) do not support to stringify + * error objects like other browsers usually do. This feature is added to + * those browsers. + * + * @signature function() + * @return {String} Error message + */ + errorToString : { + "native" : Error.prototype.toString, + "emulated" : function(){ + + return this.message; + } + }[(!Error.prototype.toString || Error.prototype.toString() == "[object Error]") ? "emulated" : "native"], + /** + * Returns the first index at which a given element can be found in the array, + * or -1 if it is not present. It compares searchElement to elements of the Array + * using strict equality (the same method used by the ===, or + * triple-equals, operator). + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf + * + * @signature function(searchElement, fromIndex) + * @param searchElement {var} Element to locate in the array. + * @param fromIndex {Integer} 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} Returns the first index at which a given element can + * be found in the array, or -1 if it is not present. + */ + arrayIndexOf : { + "native" : Array.prototype.indexOf, + "emulated" : 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; + } + }[Array.prototype.indexOf ? "native" : "emulated"], + /** + * Returns the last index at which a given element can be found in the array, or -1 + * if it is not present. The array is searched backwards, starting at fromIndex. + * It compares searchElement to elements of the Array using strict equality + * (the same method used by the ===, or triple-equals, operator). + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf + * + * @signature function(searchElement, fromIndex) + * @param searchElement {var} Element to locate in the array. + * @param fromIndex {Integer} 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} Returns the last index at which a given element can be + * found in the array, or -1 if it is not present. + */ + arrayLastIndexOf : { + "native" : Array.prototype.lastIndexOf, + "emulated" : 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; + } + }[Array.prototype.lastIndexOf ? "native" : "emulated"], + /** + * 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. + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach + * + * @signature function(callback, obj) + * @param callback {Function} Function to execute for each element. + * @param obj {Object} Object to use as this when executing callback. + * @return {void} + */ + arrayForEach : { + "native" : Array.prototype.forEach, + "emulated" : 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); + }; + }; + } + }[Array.prototype.forEach ? "native" : "emulated"], + /** + * 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. + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter + * + * @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 {Array} Returns a new array with all elements that pass the test + * implemented by the provided function. + */ + arrayFilter : { + "native" : Array.prototype.filter, + "emulated" : 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; + } + }[Array.prototype.filter ? "native" : "emulated"], + /** + * 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. + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:map + * + * @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 {Array} Returns a new array with the results of calling a provided + * function on every element in this array. + */ + arrayMap : { + "native" : Array.prototype.map, + "emulated" : 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; + } + }[Array.prototype.map ? "native" : "emulated"], + /** + * 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. + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some + * + * @param callback {Function} Function to test for each element. + * @param obj {Object} Object to use as this when executing callback. + * @return {Boolean} Returns true whether some element in the + * array passes the test implemented by the provided function, + * false otherwise. + */ + arraySome : { + "native" : Array.prototype.some, + "emulated" : 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; + } + }[Array.prototype.some ? "native" : "emulated"], + /** + * 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. + * + * Natively supported in Gecko since version 1.8. + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every + * + * @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} Returns false whether all elements in the + * array pass the test implemented by the provided function, + * false otherwise. + */ + arrayEvery : { + "native" : Array.prototype.every, + "emulated" : 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; + } + }[Array.prototype.every ? "native" : "emulated"], + /** + * Surrounds the string with double quotes and escapes all double quotes + * and backslashes within the string. + * + * Note: Not part of ECMAScript Language Specification ECMA-262 + * 3rd edition (December 1999), but implemented by Gecko: + * http://lxr.mozilla.org/seamonkey/source/js/src/jsstr.c + * + * @signature function() + * @return {String} Returns a string with double quotes and escapes all + * double quotes and backslashes within the string. + */ + stringQuote : { + "native" : String.prototype.quote, + "emulated" : function(){ + + return '"' + this.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"") + '"'; + } + }[String.prototype.quote ? "native" : "emulated"] + } +}); +/* +--------------------------------------------------------------------------- + FEATURE EXTENSION OF NATIVE ERROR OBJECT +--------------------------------------------------------------------------- +*/ +if(!Error.prototype.toString || Error.prototype.toString() == "[object Error]"){ + + Error.prototype.toString = qx.lang.Core.errorToString; +}; +/* +--------------------------------------------------------------------------- + FEATURE EXTENSION OF NATIVE ARRAY OBJECT +--------------------------------------------------------------------------- +*/ +if(!Array.prototype.indexOf){ + + Array.prototype.indexOf = qx.lang.Core.arrayIndexOf; +}; +if(!Array.prototype.lastIndexOf){ + + Array.prototype.lastIndexOf = qx.lang.Core.arrayLastIndexOf; +}; +if(!Array.prototype.forEach){ + + Array.prototype.forEach = qx.lang.Core.arrayForEach; +}; +if(!Array.prototype.filter){ + + Array.prototype.filter = qx.lang.Core.arrayFilter; +}; +if(!Array.prototype.map){ + + Array.prototype.map = qx.lang.Core.arrayMap; +}; +if(!Array.prototype.some){ + + Array.prototype.some = qx.lang.Core.arraySome; +}; +if(!Array.prototype.every){ + + Array.prototype.every = qx.lang.Core.arrayEvery; +}; +/* +--------------------------------------------------------------------------- + FEATURE EXTENSION OF NATIVE STRING OBJECT +--------------------------------------------------------------------------- +*/ +if(!String.prototype.quote){ + + String.prototype.quote = qx.lang.Core.stringQuote; +}; + +/* ************************************************************************ + + 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.documentmodeInteger0{@link qx.bom.client.Browser#getDocumentMode}
browser.nameString chrome {@link qx.bom.client.Browser#getName}
browser.quirksmodeBooleanfalse{@link qx.bom.client.Browser#getQuirksMode}
browser.versionString11.0{@link qx.bom.client.Browser#getVersion}
runtime
runtime.name String node.js {@link qx.bom.client.Runtime#getName}
css
css.borderradiusString or nullborderRadius{@link qx.bom.client.Css#getBorderRadius}
css.borderimageString or nullWebkitBorderImage{@link qx.bom.client.Css#getBorderImage}
css.borderimage.standardsyntaxBoolean or nulltrue{@link qx.bom.client.Css#getBorderImageSyntax}
css.boxmodelStringcontent{@link qx.bom.client.Css#getBoxModel}
css.boxshadowString or nullboxShadow{@link qx.bom.client.Css#getBoxShadow}
css.gradient.linearString or null-moz-linear-gradient{@link qx.bom.client.Css#getLinearGradient}
css.gradient.filterBooleantrue{@link qx.bom.client.Css#getFilterGradient}
css.gradient.radialString or null-moz-radial-gradient{@link qx.bom.client.Css#getRadialGradient}
css.gradient.legacywebkitBooleanfalse{@link qx.bom.client.Css#getLegacyWebkitGradient}
css.placeholderBooleantrue{@link qx.bom.client.Css#getPlaceholder}
css.textoverflowString or nulltextOverflow{@link qx.bom.client.Css#getTextOverflow}
css.rgbaBooleantrue{@link qx.bom.client.Css#getRgba}
css.usermodifyString or nullWebkitUserModify{@link qx.bom.client.Css#getUserModify}
css.appearanceString or nullWebkitAppearance{@link qx.bom.client.Css#getAppearance}
css.floatString or nullcssFloat{@link qx.bom.client.Css#getFloat}
css.userselectString or nullWebkitUserSelect{@link qx.bom.client.Css#getUserSelect}
css.userselect.noneString or null-moz-none{@link qx.bom.client.Css#getUserSelectNone}
css.boxsizingString or nullboxSizing{@link qx.bom.client.Css#getBoxSizing}
css.animationObject or null{end-event: "webkitAnimationEnd", keyframes: "@-webkit-keyframes", play-state: null, name: "WebkitAnimation"}{@link qx.bom.client.CssAnimation#getSupport}
css.transformObject 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.3dBooleanfalse{@link qx.bom.client.CssTransform#get3D}
css.inlineblockString or nullinline-block{@link qx.bom.client.Css#getInlineBlock}
css.opacityBooleantrue{@link qx.bom.client.Css#getOpacity}
css.overflowxyBooleantrue{@link qx.bom.client.Css#getOverflowXY}
css.textShadowBooleantrue{@link qx.bom.client.Css#getTextShadow}
css.textShadow.filterBooleantrue{@link qx.bom.client.Css#getFilterTextShadow}
device
device.nameStringpc{@link qx.bom.client.Device#getName}
device.typeStringmobile{@link qx.bom.client.Device#getType}
ecmascript
ecmascript.stacktraceString or nullstack{@link qx.bom.client.EcmaScript#getStackTrace}
engine
engine.nameStringwebkit{@link qx.bom.client.Engine#getName}
engine.versionString534.24{@link qx.bom.client.Engine#getVersion}
event
event.pointerBooleantrue{@link qx.bom.client.Event#getPointer}
event.touchBooleanfalse{@link qx.bom.client.Event#getTouch}
event.helpBooleanfalse{@link qx.bom.client.Event#getHelp}
event.hashchangeBooleantrue{@link qx.bom.client.Event#getHashChange}
html
html.audioBooleantrue{@link qx.bom.client.Html#getAudio}
html.audio.mp3String""{@link qx.bom.client.Html#getAudioMp3}
html.audio.oggString"maybe"{@link qx.bom.client.Html#getAudioOgg}
html.audio.wavString"probably"{@link qx.bom.client.Html#getAudioWav}
html.audio.auString"maybe"{@link qx.bom.client.Html#getAudioAu}
html.audio.aifString"probably"{@link qx.bom.client.Html#getAudioAif}
html.canvasBooleantrue{@link qx.bom.client.Html#getCanvas}
html.classlistBooleantrue{@link qx.bom.client.Html#getClassList}
html.geolocationBooleantrue{@link qx.bom.client.Html#getGeoLocation}
html.storage.localBooleantrue{@link qx.bom.client.Html#getLocalStorage}
html.storage.sessionBooleantrue{@link qx.bom.client.Html#getSessionStorage}
html.storage.userdataBooleantrue{@link qx.bom.client.Html#getUserDataStorage}
html.svgBooleantrue{@link qx.bom.client.Html#getSvg}
html.videoBooleantrue{@link qx.bom.client.Html#getVideo}
html.video.h264String"probably"{@link qx.bom.client.Html#getVideoH264}
html.video.oggString""{@link qx.bom.client.Html#getVideoOgg}
html.video.webmString"maybe"{@link qx.bom.client.Html#getVideoWebm}
html.vmlBooleanfalse{@link qx.bom.client.Html#getVml}
html.webworkerBooleantrue{@link qx.bom.client.Html#getWebWorker}
html.filereaderBooleantrue{@link qx.bom.client.Html#getFileReader}
html.xpathBooleantrue{@link qx.bom.client.Html#getXPath}
html.xulBooleantrue{@link qx.bom.client.Html#getXul}
html.consoleBooleantrue{@link qx.bom.client.Html#getConsole}
html.element.containsBooleantrue{@link qx.bom.client.Html#getContains}
html.element.compareDocumentPositionBooleantrue{@link qx.bom.client.Html#getCompareDocumentPosition}
html.element.textContentBooleantrue{@link qx.bom.client.Html#getTextContent}
html.image.naturaldimensionsBooleantrue{@link qx.bom.client.Html#getNaturalDimensions}
XML
xml.implementationBooleantrue{@link qx.bom.client.Xml#getImplementation}
xml.domparserBooleantrue{@link qx.bom.client.Xml#getDomParser}
xml.selectsinglenodeBooleanfalse{@link qx.bom.client.Xml#getSelectSingleNode}
xml.selectnodesBooleanfalse{@link qx.bom.client.Xml#getSelectNodes}
xml.getelementsbytagnamensBooleantrue{@link qx.bom.client.Xml#getElementsByTagNameNS}
xml.dompropertiesBooleanfalse{@link qx.bom.client.Xml#getDomProperties}
xml.attributensBooleantrue{@link qx.bom.client.Xml#getAttributeNS}
xml.createelementnsBooleantrue{@link qx.bom.client.Xml#getCreateElementNS}
xml.createnodeBooleanfalse{@link qx.bom.client.Xml#getCreateNode}
xml.getqualifieditemBooleanfalse{@link qx.bom.client.Xml#getQualifiedItem}
Stylesheets
html.stylesheet.createstylesheetBooleanfalse{@link qx.bom.client.Stylesheet#getCreateStyleSheet}
html.stylesheet.insertruleBooleantrue{@link qx.bom.client.Stylesheet#getInsertRule}
html.stylesheet.deleteruleBooleantrue{@link qx.bom.client.Stylesheet#getDeleteRule}
html.stylesheet.addimportBooleanfalse{@link qx.bom.client.Stylesheet#getAddImport}
html.stylesheet.removeimportBooleanfalse{@link qx.bom.client.Stylesheet#getRemoveImport}
io
io.maxrequestsInteger4{@link qx.bom.client.Transport#getMaxConcurrentRequestCount}
io.sslBooleanfalse{@link qx.bom.client.Transport#getSsl}
io.xhrStringxhr{@link qx.bom.client.Transport#getXmlHttpRequest}
locale
localeStringde{@link qx.bom.client.Locale#getLocale}
locale.variantStringde{@link qx.bom.client.Locale#getVariant}
os
os.nameStringosx{@link qx.bom.client.OperatingSystem#getName}
os.versionString10.6{@link qx.bom.client.OperatingSystem#getVersion}
os.scrollBarOverlayedBooleanfalse{@link qx.bom.client.Scroll#scrollBarOverlayed}
phonegap
phonegapBooleanfalse{@link qx.bom.client.PhoneGap#getPhoneGap}
phonegap.notificationBooleanfalse{@link qx.bom.client.PhoneGap#getNotification}
plugin
plugin.divxBooleanfalse{@link qx.bom.client.Plugin#getDivX}
plugin.divx.versionString{@link qx.bom.client.Plugin#getDivXVersion}
plugin.flashBooleantrue{@link qx.bom.client.Flash#isAvailable}
plugin.flash.expressBooleantrue{@link qx.bom.client.Flash#getExpressInstall}
plugin.flash.strictsecurityBooleantrue{@link qx.bom.client.Flash#getStrictSecurityModel}
plugin.flash.versionString10.2.154{@link qx.bom.client.Flash#getVersion}
plugin.gearsBooleanfalse{@link qx.bom.client.Plugin#getGears}
plugin.activexBooleanfalse{@link qx.bom.client.Plugin#getActiveX}
plugin.pdfBooleanfalse{@link qx.bom.client.Plugin#getPdf}
plugin.pdf.versionString{@link qx.bom.client.Plugin#getPdfVersion}
plugin.quicktimeBooleantrue{@link qx.bom.client.Plugin#getQuicktime}
plugin.quicktime.versionString7.6{@link qx.bom.client.Plugin#getQuicktimeVersion}
plugin.silverlightBooleanfalse{@link qx.bom.client.Plugin#getSilverlight}
plugin.silverlight.versionString{@link qx.bom.client.Plugin#getSilverlightVersion}
plugin.windowsmediaBooleanfalse{@link qx.bom.client.Plugin#getWindowsMedia}
plugin.windowsmedia.versionString{@link qx.bom.client.Plugin#getWindowsMediaVersion}
qx
qx.allowUrlSettingsBooleantruedefault: false
qx.allowUrlVariantsBooleantruedefault: false
qx.applicationStringname.spacedefault: <<application name>>
qx.aspectsBooleanfalsedefault: false
qx.debugBooleantruedefault: true
qx.debug.databindingBooleanfalsedefault: false
qx.debug.disposeBooleanfalsedefault: false
qx.debug.dispose.levelInteger0default: 0
qx.debug.ioBooleantruedefault: false
qx.debug.io.remoteBooleantruedefault: false
qx.debug.io.remote.dataBooleantruedefault: false
qx.debug.property.levelInteger0default: 0
qx.dynamicmousewheelBooleantruedefault: true
qx.dynlocaleBooleantruedefault: true
qx.globalErrorHandlingBooleantruedefault: true
qx.mobile.emulatetouchBooleanfalsedefault: false
qx.mobile.nativescrollBooleanfalsedefault: false
qx.optimization.basecallsBooleantruetrue if the corresp. optimize key is set in the config
qx.optimization.commentsBooleantruetrue if the corresp. optimize key is set in the config
qx.optimization.privatesBooleantruetrue if the corresp. optimize key is set in the config
qx.optimization.stringsBooleantruetrue if the corresp. optimize key is set in the config
qx.optimization.variablesBooleantruetrue if the corresp. optimize key is set in the config
qx.optimization.variantsBooleantruetrue if the corresp. optimize key is set in the config
qx.revisionString27348
qx.themeStringqx.theme.Moderndefault: <<theme name>>
qx.versionString${qxversion}
qx.blankpageStringURI to blank.html page
module
module.databindingBooleantruedefault: true
module.loggerBooleantruedefault: true
module.propertyBooleantruedefault: true
module.eventsBooleantruedefault: true

Asynchronous checks

+ *
html.dataurlBooleantrue{@link qx.bom.client.Html#getDataUrl}
+ * + */ +qx.Bootstrap.define("qx.core.Environment", { + statics : { + /** Map containing the synchronous check functions. */ + _checks : { + }, + /** Map containing the asynchronous check functions. */ + _asyncChecks : { + }, + /** Internal cache for all checks. */ + __cache : { + }, + /** Internal map for environment keys to check methods. */ + _checksMap : { + "engine.version" : "qx.bom.client.Engine.getVersion", + "engine.name" : "qx.bom.client.Engine.getName", + "browser.name" : "qx.bom.client.Browser.getName", + "browser.version" : "qx.bom.client.Browser.getVersion", + "browser.documentmode" : "qx.bom.client.Browser.getDocumentMode", + "browser.quirksmode" : "qx.bom.client.Browser.getQuirksMode", + "runtime.name" : "qx.bom.client.Runtime.getName", + "device.name" : "qx.bom.client.Device.getName", + "device.type" : "qx.bom.client.Device.getType", + "locale" : "qx.bom.client.Locale.getLocale", + "locale.variant" : "qx.bom.client.Locale.getVariant", + "os.name" : "qx.bom.client.OperatingSystem.getName", + "os.version" : "qx.bom.client.OperatingSystem.getVersion", + "os.scrollBarOverlayed" : "qx.bom.client.Scroll.scrollBarOverlayed", + "plugin.gears" : "qx.bom.client.Plugin.getGears", + "plugin.activex" : "qx.bom.client.Plugin.getActiveX", + "plugin.quicktime" : "qx.bom.client.Plugin.getQuicktime", + "plugin.quicktime.version" : "qx.bom.client.Plugin.getQuicktimeVersion", + "plugin.windowsmedia" : "qx.bom.client.Plugin.getWindowsMedia", + "plugin.windowsmedia.version" : "qx.bom.client.Plugin.getWindowsMediaVersion", + "plugin.divx" : "qx.bom.client.Plugin.getDivX", + "plugin.divx.version" : "qx.bom.client.Plugin.getDivXVersion", + "plugin.silverlight" : "qx.bom.client.Plugin.getSilverlight", + "plugin.silverlight.version" : "qx.bom.client.Plugin.getSilverlightVersion", + "plugin.flash" : "qx.bom.client.Flash.isAvailable", + "plugin.flash.version" : "qx.bom.client.Flash.getVersion", + "plugin.flash.express" : "qx.bom.client.Flash.getExpressInstall", + "plugin.flash.strictsecurity" : "qx.bom.client.Flash.getStrictSecurityModel", + "plugin.pdf" : "qx.bom.client.Plugin.getPdf", + "plugin.pdf.version" : "qx.bom.client.Plugin.getPdfVersion", + "io.maxrequests" : "qx.bom.client.Transport.getMaxConcurrentRequestCount", + "io.ssl" : "qx.bom.client.Transport.getSsl", + "io.xhr" : "qx.bom.client.Transport.getXmlHttpRequest", + "event.touch" : "qx.bom.client.Event.getTouch", + "event.pointer" : "qx.bom.client.Event.getPointer", + "event.help" : "qx.bom.client.Event.getHelp", + "event.hashchange" : "qx.bom.client.Event.getHashChange", + "ecmascript.stacktrace" : "qx.bom.client.EcmaScript.getStackTrace", + "html.webworker" : "qx.bom.client.Html.getWebWorker", + "html.filereader" : "qx.bom.client.Html.getFileReader", + "html.geolocation" : "qx.bom.client.Html.getGeoLocation", + "html.audio" : "qx.bom.client.Html.getAudio", + "html.audio.ogg" : "qx.bom.client.Html.getAudioOgg", + "html.audio.mp3" : "qx.bom.client.Html.getAudioMp3", + "html.audio.wav" : "qx.bom.client.Html.getAudioWav", + "html.audio.au" : "qx.bom.client.Html.getAudioAu", + "html.audio.aif" : "qx.bom.client.Html.getAudioAif", + "html.video" : "qx.bom.client.Html.getVideo", + "html.video.ogg" : "qx.bom.client.Html.getVideoOgg", + "html.video.h264" : "qx.bom.client.Html.getVideoH264", + "html.video.webm" : "qx.bom.client.Html.getVideoWebm", + "html.storage.local" : "qx.bom.client.Html.getLocalStorage", + "html.storage.session" : "qx.bom.client.Html.getSessionStorage", + "html.storage.userdata" : "qx.bom.client.Html.getUserDataStorage", + "html.classlist" : "qx.bom.client.Html.getClassList", + "html.xpath" : "qx.bom.client.Html.getXPath", + "html.xul" : "qx.bom.client.Html.getXul", + "html.canvas" : "qx.bom.client.Html.getCanvas", + "html.svg" : "qx.bom.client.Html.getSvg", + "html.vml" : "qx.bom.client.Html.getVml", + "html.dataset" : "qx.bom.client.Html.getDataset", + "html.dataurl" : "qx.bom.client.Html.getDataUrl", + "html.console" : "qx.bom.client.Html.getConsole", + "html.stylesheet.createstylesheet" : "qx.bom.client.Stylesheet.getCreateStyleSheet", + "html.stylesheet.insertrule" : "qx.bom.client.Stylesheet.getInsertRule", + "html.stylesheet.deleterule" : "qx.bom.client.Stylesheet.getDeleteRule", + "html.stylesheet.addimport" : "qx.bom.client.Stylesheet.getAddImport", + "html.stylesheet.removeimport" : "qx.bom.client.Stylesheet.getRemoveImport", + "html.element.contains" : "qx.bom.client.Html.getContains", + "html.element.compareDocumentPosition" : "qx.bom.client.Html.getCompareDocumentPosition", + "html.element.textcontent" : "qx.bom.client.Html.getTextContent", + "html.image.naturaldimensions" : "qx.bom.client.Html.getNaturalDimensions", + "json" : "qx.bom.client.Json.getJson", + "css.textoverflow" : "qx.bom.client.Css.getTextOverflow", + "css.placeholder" : "qx.bom.client.Css.getPlaceholder", + "css.borderradius" : "qx.bom.client.Css.getBorderRadius", + "css.borderimage" : "qx.bom.client.Css.getBorderImage", + "css.borderimage.standardsyntax" : "qx.bom.client.Css.getBorderImageSyntax", + "css.boxshadow" : "qx.bom.client.Css.getBoxShadow", + "css.gradient.linear" : "qx.bom.client.Css.getLinearGradient", + "css.gradient.filter" : "qx.bom.client.Css.getFilterGradient", + "css.gradient.radial" : "qx.bom.client.Css.getRadialGradient", + "css.gradient.legacywebkit" : "qx.bom.client.Css.getLegacyWebkitGradient", + "css.boxmodel" : "qx.bom.client.Css.getBoxModel", + "css.rgba" : "qx.bom.client.Css.getRgba", + "css.userselect" : "qx.bom.client.Css.getUserSelect", + "css.userselect.none" : "qx.bom.client.Css.getUserSelectNone", + "css.usermodify" : "qx.bom.client.Css.getUserModify", + "css.appearance" : "qx.bom.client.Css.getAppearance", + "css.float" : "qx.bom.client.Css.getFloat", + "css.boxsizing" : "qx.bom.client.Css.getBoxSizing", + "css.animation" : "qx.bom.client.CssAnimation.getSupport", + "css.transform" : "qx.bom.client.CssTransform.getSupport", + "css.transform.3d" : "qx.bom.client.CssTransform.get3D", + "css.inlineblock" : "qx.bom.client.Css.getInlineBlock", + "css.opacity" : "qx.bom.client.Css.getOpacity", + "css.overflowxy" : "qx.bom.client.Css.getOverflowXY", + "css.textShadow" : "qx.bom.client.Css.getTextShadow", + "css.textShadow.filter" : "qx.bom.client.Css.getFilterTextShadow", + "phonegap" : "qx.bom.client.PhoneGap.getPhoneGap", + "phonegap.notification" : "qx.bom.client.PhoneGap.getNotification", + "xml.implementation" : "qx.bom.client.Xml.getImplementation", + "xml.domparser" : "qx.bom.client.Xml.getDomParser", + "xml.selectsinglenode" : "qx.bom.client.Xml.getSelectSingleNode", + "xml.selectnodes" : "qx.bom.client.Xml.getSelectNodes", + "xml.getelementsbytagnamens" : "qx.bom.client.Xml.getElementsByTagNameNS", + "xml.domproperties" : "qx.bom.client.Xml.getDomProperties", + "xml.attributens" : "qx.bom.client.Xml.getAttributeNS", + "xml.createnode" : "qx.bom.client.Xml.getCreateNode", + "xml.getqualifieditem" : "qx.bom.client.Xml.getQualifiedItem", + "xml.createelementns" : "qx.bom.client.Xml.getCreateElementNS" + }, + /** + * The default accessor for the checks. It returns the value the current + * environment has for the given key. The key could be something like + * "qx.debug", "css.textoverflow" or "io.ssl". A complete list of + * checks can be found in the class comment of this class. + * + * Please keep in mind that the result is cached. If you want to run the + * check function again in case something could have been changed, take a + * look at the {@link #invalidateCacheKey} function. + * + * @param key {String} The name of the check you want to query. + * @return {var} The stored value depending on the given key. + * (Details in the class doc) + */ + get : function(key){ + + // check the cache + if(this.__cache[key] != undefined){ + + return this.__cache[key]; + }; + // search for a matching check + var check = this._checks[key]; + if(check){ + + // execute the check and write the result in the cache + var value = check(); + this.__cache[key] = value; + return value; + }; + // try class lookup + var classAndMethod = this._getClassNameFromEnvKey(key); + if(classAndMethod[0] != undefined){ + + var clazz = classAndMethod[0]; + var method = classAndMethod[1]; + var value = clazz[method](); + // call the check method + this.__cache[key] = value; + return value; + }; + // debug flag + if(qx.Bootstrap.DEBUG){ + + qx.Bootstrap.warn(key + " is not a valid key. Please see the API-doc of " + "qx.core.Environment for a list of predefined keys."); + qx.Bootstrap.trace(this); + }; + }, + /** + * Maps an environment key to a check class and method name. + * + * @param key {String} The name of the check you want to query. + * @return {Array} [className, methodName] of + * the corresponding implementation. + */ + _getClassNameFromEnvKey : function(key){ + + var envmappings = this._checksMap; + if(envmappings[key] != undefined){ + + var implementation = envmappings[key]; + // separate class from method + var lastdot = implementation.lastIndexOf("."); + if(lastdot > -1){ + + var classname = implementation.slice(0, lastdot); + var methodname = implementation.slice(lastdot + 1); + var clazz = qx.Bootstrap.getByName(classname); + if(clazz != undefined){ + + return [clazz, methodname]; + }; + }; + }; + return [undefined, undefined]; + }, + /** + * Invokes the callback as soon as the check has been done. If no check + * could be found, a warning will be printed. + * + * @param key {String} The key of the asynchronous check. + * @param callback {Function} The function to call as soon as the check is + * done. The function should have one argument which is the result of the + * check. + * @param self {var} The context to use when invoking the callback. + */ + getAsync : function(key, callback, self){ + + // check the cache + var env = this; + if(this.__cache[key] != undefined){ + + // force async behavior + window.setTimeout(function(){ + + callback.call(self, env.__cache[key]); + }, 0); + return; + }; + var check = this._asyncChecks[key]; + if(check){ + + check(function(result){ + + env.__cache[key] = result; + callback.call(self, result); + }); + return; + }; + // try class lookup + var classAndMethod = this._getClassNameFromEnvKey(key); + if(classAndMethod[0] != undefined){ + + var clazz = classAndMethod[0]; + var method = classAndMethod[1]; + clazz[method](function(result){ + + // call the check method + env.__cache[key] = result; + callback.call(self, result); + }); + return; + }; + // debug flag + if(qx.Bootstrap.DEBUG){ + + qx.Bootstrap.warn(key + " is not a valid key. Please see the API-doc of " + "qx.core.Environment for a list of predefined keys."); + qx.Bootstrap.trace(this); + }; + }, + /** + * Returns the proper value dependent on the check for the given key. + * + * @param key {String} The name of the check the select depends on. + * @param values {Map} A map containing the values which should be returned + * in any case. The "default" key could be used as a catch all statement. + * @return {var} The value which is stored in the map for the given + * check of the key. + */ + select : function(key, values){ + + return this.__pickFromValues(this.get(key), values); + }, + /** + * Selects the proper function dependent on the asynchronous check. + * + * @param key {String} The key for the async check. + * @param values {Map} A map containing functions. The map keys should + * contain all possibilities which could be returned by the given check + * key. The "default" key could be used as a catch all statement. + * The called function will get one parameter, the result of the query. + * @param self {var} The context which should be used when calling the + * method in the values map. + */ + selectAsync : function(key, values, self){ + + this.getAsync(key, function(result){ + + var value = this.__pickFromValues(key, values); + value.call(self, result); + }, this); + }, + /** + * Internal helper which tries to pick the given key from the given values + * map. If that key is not found, it tries to use a key named "default". + * If there is also no default key, it prints out a warning and returns + * undefined. + * + * @param key {String} The key to search for in the values. + * @param values {Map} A map containing some keys. + * @return {var} The value stored as values[key] usually. + */ + __pickFromValues : function(key, values){ + + var value = values[key]; + if(values.hasOwnProperty(key)){ + + return value; + }; + // check for piped values + for(var id in values){ + + if(id.indexOf("|") != -1){ + + var ids = id.split("|"); + for(var i = 0;i < ids.length;i++){ + + if(ids[i] == key){ + + return values[id]; + }; + }; + }; + }; + if(values["default"] !== undefined){ + + return values["default"]; + }; + if(qx.Bootstrap.DEBUG){ + + throw new Error('No match for variant "' + key + '" (' + (typeof key) + ' type)' + ' in variants [' + qx.Bootstrap.getKeysAsString(values) + '] found, and no default ("default") given'); + }; + }, + /** + * Takes a given map containing the check names as keys and converts + * the map to an array only containing the values for check evaluating + * to 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.aspects", function(){ + + return false; + }); + this.add("qx.dynlocale", function(){ + + return true; + }); + this.add("qx.mobile.emulatetouch", function(){ + + return false; + }); + this.add("qx.mobile.nativescroll", 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; + }); + }, + /** + * 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: http://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()){ + + 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 && /Trident\/([^\);]+)(\)|;)/.test(agent)){ + + if(RegExp.$1 == "4.0"){ + + version = "8.0"; + } else if(RegExp.$1 == "5.0"){ + + version = "9.0"; + }; + }; + }; + } 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. + * @return {boolean} true, if its opera. + */ + __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; + }, + /** + * Internal helper to check for MSHTML. + * @return {boolean} true, if its MSHTML. + */ + __isMshtml : function(){ + + return window.navigator.cpuClass && /MSIE\s+([^\);]+)(\)|;)/.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: + 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/ + +************************************************************************ */ +/* ************************************************************************ + +#require(qx.lang.Core) +#require(qx.bom.client.Engine) + +************************************************************************ */ +/** + * 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. + */ +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|varargs?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 = qx.lang.Core.arrayIndexOf; + Stack.prototype.lastIndexOf = qx.lang.Core.arrayLastIndexOf; + Stack.prototype.forEach = qx.lang.Core.arrayForEach; + Stack.prototype.some = qx.lang.Core.arraySome; + Stack.prototype.every = qx.lang.Core.arrayEvery; + var filter = qx.lang.Core.arrayFilter; + var map = qx.lang.Core.arrayMap; + // 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. + * + * For further details, take a look at the documentation in the + * user manual. + */ +qx.Bootstrap.define("q", { + 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 or a node object will be ignored. + * @return {q} A new initialized collection. + */ + $init : function(arg){ + + var clean = []; + for(var i = 0;i < arg.length;i++){ + + var isNode = !!(arg[i] && arg[i].nodeType != null); + 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]); + }; + }; + // check for node or window object + var col = qx.lang.Array.cast(clean, q); + for(var i = 0;i < q.__init.length;i++){ + + q.__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){ + + { + }; + q.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){ + + { + }; + q[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. + * + * @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} Class definition structure. + * @return {Function} The defined class. + */ + define : function(name, config){ + + if(config == undefined){ + + config = name; + name = null; + }; + return qx.Bootstrap.define.call(qx.Bootstrap, name, config); + } + }, + /** + * Accepts a selector string and returns a set of found items. The optional context + * element can be used to reduce the amount of found elements to children of the + * context element. + * + * Sizzle is used as selector engine. + * Check out the documentation + * for more details. + * + * @param selector {String|Element|Array} Valid selector (CSS3 + extensions) + * or DOM element or Array of DOM Elements. + * @param context {Element} Only the children of this element are considered. + * @return {q} A collection of DOM elements. + */ + construct : function(selector, context){ + + if(!selector && this instanceof q){ + + return this; + }; + if(qx.Bootstrap.isString(selector)){ + + selector = qx.bom.Selector.query(selector, context); + } else if(!(qx.Bootstrap.isArray(selector))){ + + selector = [selector]; + }; + return q.$init(selector); + } +}); + +/* ************************************************************************ + + 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: + + * jQuery + http://jquery.com + Version 1.3.1 + + Copyright: + 2009 John Resig + + License: + MIT: http://www.opensource.org/licenses/mit-license.php + +************************************************************************ */ +/* ************************************************************************ + +#ignore(qx.data.IListData) +#ignore(qx.Class) + +************************************************************************ */ +/** + * Static helper functions for arrays with a lot of often used convenience + * methods like 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.Core} for + * browsers that do not support certain JavaScript 1.6 features natively . + * + * The string/array generics introduced in JavaScript 1.6 are supported by + * {@link qx.lang.Generics}. + */ +qx.Bootstrap.define("qx.lang.Array", { + statics : { + /** + * Converts array like constructions like the argument object, + * node collections like the ones returned by getElementsByTagName + * or extended array objects like qx.type.BaseArray to an + * native Array instance. + * + * @param object {var} any array like object + * @param offset {Integer?0} position to start from + * @return {Array} New array with the content of the incoming object + */ + toArray : function(object, offset){ + + return this.cast(object, Array, offset); + }, + /** + * 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){ + + // Some collection is mshtml are not able to be sliced. + // This lines are a special workaround for this client. + 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 an exception 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 an exception 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" + qx.lang.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{ + + // TODO: The following delete seems to fail in IE7 + delete doneObjects[hash][key]; + } catch(ex) { + + try{ + + doneObjects[hash][key] = null; + } catch(ex) { + + throw new Error("Cannot clean-up map entry doneObjects[" + hash + "][" + key + "]"); + }; + }; + }; + return ret; + } + } +}); + +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2009 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) + + ====================================================================== + + This class contains code based on the following work: + + * jQuery + http://jquery.com + Version 1.3.1 + + Copyright: + 2009 John Resig + + License: + MIT: http://www.opensource.org/licenses/mit-license.php + +************************************************************************ */ +/** + * Helper functions for dates. + * + * The native JavaScript Date is not modified by this class. + */ +qx.Bootstrap.define("qx.lang.Date", { + statics : { + /** + * Returns the current time + * + * @return {Integer} Time in ms from 1970. + */ + now : function(){ + + return +new Date; + } + } +}); + +/* ************************************************************************ + + 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.5.1 + + 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 2011-03-15, latest Sizzle commit on 2011-02-18: + commit ef19279f54ba49242c6461d47577c703f4f4e80e + +************************************************************************ */ +/** + * 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 + } +}); +(function(){ + + var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,done = 0,toString = Object.prototype.toString,hasDuplicate = false,baseHasDuplicate = true,rBackslash = /\\/g,rNonWord = /\W/; + [0, 0].sort(function(){ + + baseHasDuplicate = false; + return 0; + }); + var Sizzle = function(selector, context, results, seed){ + + results = results || []; + context = context || document; + var origContext = context; + if(context.nodeType !== 1 && context.nodeType !== 9){ + + return []; + }; + if(!selector || typeof selector !== "string"){ + + return results; + }; + var m,set,checkSet,extra,ret,cur,pop,i,prune = true,contextXML = Sizzle.isXML(context),parts = [],soFar = selector; + // Reset the position of the chunker regexp (start from head) + do { + + chunker.exec(""); + m = chunker.exec(soFar); + if(m){ + + soFar = m[3]; + parts.push(m[1]); + if(m[2]){ + + extra = m[3]; + break; + }; + }; + }while(m); + if(parts.length > 1 && origPOS.exec(selector)){ + + if(parts.length === 2 && Expr.relative[parts[0]]){ + + set = posProcess(parts[0] + parts[1], context); + } else { + + set = Expr.relative[parts[0]] ? [context] : Sizzle(parts.shift(), context); + while(parts.length){ + + selector = parts.shift(); + if(Expr.relative[selector]){ + + selector += parts.shift(); + }; + set = posProcess(selector, set); + }; + }; + } else { + + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if(!seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])){ + + ret = Sizzle.find(parts.shift(), context, contextXML); + context = ret.expr ? Sizzle.filter(ret.expr, ret.set)[0] : ret.set[0]; + }; + if(context){ + + ret = seed ? { + expr : parts.pop(), + set : makeArray(seed) + } : Sizzle.find(parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML); + set = ret.expr ? Sizzle.filter(ret.expr, ret.set) : ret.set; + if(parts.length > 0){ + + checkSet = makeArray(set); + } else { + + prune = false; + }; + while(parts.length){ + + cur = parts.pop(); + pop = cur; + if(!Expr.relative[cur]){ + + cur = ""; + } else { + + pop = parts.pop(); + }; + if(pop == null){ + + pop = context; + }; + Expr.relative[cur](checkSet, pop, contextXML); + }; + } else { + + checkSet = parts = []; + }; + }; + if(!checkSet){ + + checkSet = set; + }; + if(!checkSet){ + + Sizzle.error(cur || selector); + }; + if(toString.call(checkSet) === "[object Array]"){ + + if(!prune){ + + results.push.apply(results, checkSet); + } else if(context && context.nodeType === 1){ + + for(i = 0;checkSet[i] != null;i++){ + + if(checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i]))){ + + results.push(set[i]); + }; + }; + } else { + + for(i = 0;checkSet[i] != null;i++){ + + if(checkSet[i] && checkSet[i].nodeType === 1){ + + results.push(set[i]); + }; + }; + }; + } else { + + makeArray(checkSet, results); + }; + if(extra){ + + Sizzle(extra, origContext, results, seed); + Sizzle.uniqueSort(results); + }; + return results; + }; + Sizzle.uniqueSort = function(results){ + + if(sortOrder){ + + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + if(hasDuplicate){ + + for(var i = 1;i < results.length;i++){ + + if(results[i] === results[i - 1]){ + + results.splice(i--, 1); + }; + }; + }; + }; + return results; + }; + Sizzle.matches = function(expr, set){ + + return Sizzle(expr, null, null, set); + }; + Sizzle.matchesSelector = function(node, expr){ + + return Sizzle(expr, null, null, [node]).length > 0; + }; + Sizzle.find = function(expr, context, isXML){ + + var set; + if(!expr){ + + return []; + }; + for(var i = 0,l = Expr.order.length;i < l;i++){ + + var match,type = Expr.order[i]; + if((match = Expr.leftMatch[type].exec(expr))){ + + var left = match[1]; + match.splice(1, 1); + if(left.substr(left.length - 1) !== "\\"){ + + match[1] = (match[1] || "").replace(rBackslash, ""); + set = Expr.find[type](match, context, isXML); + if(set != null){ + + expr = expr.replace(Expr.match[type], ""); + break; + }; + }; + }; + }; + if(!set){ + + set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName("*") : []; + }; + return { + set : set, + expr : expr + }; + }; + Sizzle.filter = function(expr, set, inplace, not){ + + var match,anyFound,old = expr,result = [],curLoop = set,isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); + while(expr && set.length){ + + for(var type in Expr.filter){ + + if((match = Expr.leftMatch[type].exec(expr)) != null && match[2]){ + + var found,item,filter = Expr.filter[type],left = match[1]; + anyFound = false; + match.splice(1, 1); + if(left.substr(left.length - 1) === "\\"){ + + continue; + }; + if(curLoop === result){ + + result = []; + }; + if(Expr.preFilter[type]){ + + match = Expr.preFilter[type](match, curLoop, inplace, result, not, isXMLFilter); + if(!match){ + + anyFound = found = true; + } else if(match === true){ + + continue; + }; + }; + if(match){ + + for(var i = 0;(item = curLoop[i]) != null;i++){ + + if(item){ + + found = filter(item, match, i, curLoop); + var pass = not ^ !!found; + if(inplace && found != null){ + + if(pass){ + + anyFound = true; + } else { + + curLoop[i] = false; + }; + } else if(pass){ + + result.push(item); + anyFound = true; + }; + }; + }; + }; + if(found !== undefined){ + + if(!inplace){ + + curLoop = result; + }; + expr = expr.replace(Expr.match[type], ""); + if(!anyFound){ + + return []; + }; + break; + }; + }; + }; + // Improper expression + if(expr === old){ + + if(anyFound == null){ + + Sizzle.error(expr); + } else { + + break; + }; + }; + old = expr; + }; + return curLoop; + }; + Sizzle.error = function(msg){ + + throw "Syntax error, unrecognized expression: " + msg; + }; + var Expr = Sizzle.selectors = { + order : ["ID", "NAME", "TAG"], + match : { + ID : /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS : /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME : /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR : /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG : /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD : /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS : /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO : /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch : { + }, + attrMap : { + "class" : "className", + "for" : "htmlFor" + }, + attrHandle : { + href : function(elem){ + + return elem.getAttribute("href"); + }, + type : function(elem){ + + return elem.getAttribute("type"); + } + }, + relative : { + "+" : function(checkSet, part){ + + var isPartStr = typeof part === "string",isTag = isPartStr && !rNonWord.test(part),isPartStrNotTag = isPartStr && !isTag; + if(isTag){ + + part = part.toLowerCase(); + }; + for(var i = 0,l = checkSet.length,elem;i < l;i++){ + + if((elem = checkSet[i])){ + + while((elem = elem.previousSibling) && elem.nodeType !== 1){ + }; + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; + }; + }; + if(isPartStrNotTag){ + + Sizzle.filter(part, checkSet, true); + }; + }, + ">" : function(checkSet, part){ + + var elem,isPartStr = typeof part === "string",i = 0,l = checkSet.length; + if(isPartStr && !rNonWord.test(part)){ + + part = part.toLowerCase(); + for(;i < l;i++){ + + elem = checkSet[i]; + if(elem){ + + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + }; + }; + } else { + + for(;i < l;i++){ + + elem = checkSet[i]; + if(elem){ + + checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; + }; + }; + if(isPartStr){ + + Sizzle.filter(part, checkSet, true); + }; + }; + }, + "" : function(checkSet, part, isXML){ + + var nodeCheck,doneName = done++,checkFn = dirCheck; + if(typeof part === "string" && !rNonWord.test(part)){ + + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + }; + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~" : function(checkSet, part, isXML){ + + var nodeCheck,doneName = done++,checkFn = dirCheck; + if(typeof part === "string" && !rNonWord.test(part)){ + + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + }; + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find : { + ID : function(match, context, isXML){ + + if(typeof context.getElementById !== "undefined" && !isXML){ + + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + }; + }, + NAME : function(match, context){ + + if(typeof context.getElementsByName !== "undefined"){ + + var ret = [],results = context.getElementsByName(match[1]); + for(var i = 0,l = results.length;i < l;i++){ + + if(results[i].getAttribute("name") === match[1]){ + + ret.push(results[i]); + }; + }; + return ret.length === 0 ? null : ret; + }; + }, + TAG : function(match, context){ + + if(typeof context.getElementsByTagName !== "undefined"){ + + return context.getElementsByTagName(match[1]); + }; + } + }, + preFilter : { + CLASS : function(match, curLoop, inplace, result, not, isXML){ + + match = " " + match[1].replace(rBackslash, "") + " "; + if(isXML){ + + return match; + }; + for(var i = 0,elem;(elem = curLoop[i]) != null;i++){ + + if(elem){ + + if(not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0)){ + + if(!inplace){ + + result.push(elem); + }; + } else if(inplace){ + + curLoop[i] = false; + }; + }; + }; + return false; + }, + ID : function(match){ + + return match[1].replace(rBackslash, ""); + }, + TAG : function(match, curLoop){ + + return match[1].replace(rBackslash, "").toLowerCase(); + }, + CHILD : function(match){ + + if(match[1] === "nth"){ + + if(!match[2]){ + + Sizzle.error(match[0]); + }; + match[2] = match[2].replace(/^\+|\s*/g, ''); + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test(match[2]) && "0n+" + match[2] || match[2]); + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } else if(match[2]){ + + Sizzle.error(match[0]); + }; + // TODO: Move to normal caching system + match[0] = done++; + return match; + }, + ATTR : function(match, curLoop, inplace, result, not, isXML){ + + var name = match[1] = match[1].replace(rBackslash, ""); + if(!isXML && Expr.attrMap[name]){ + + match[1] = Expr.attrMap[name]; + }; + // Handle if an un-quoted value was used + match[4] = (match[4] || match[5] || "").replace(rBackslash, ""); + if(match[2] === "~="){ + + match[4] = " " + match[4] + " "; + }; + return match; + }, + PSEUDO : function(match, curLoop, inplace, result, not){ + + if(match[1] === "not"){ + + // If we're dealing with a complex expression, or a simple one + if((chunker.exec(match[3]) || "").length > 1 || /^\w/.test(match[3])){ + + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if(!inplace){ + + result.push.apply(result, ret); + }; + return false; + }; + } else if(Expr.match.POS.test(match[0]) || Expr.match.CHILD.test(match[0])){ + + return true; + }; + return match; + }, + POS : function(match){ + + match.unshift(true); + return match; + } + }, + filters : { + enabled : function(elem){ + + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled : function(elem){ + + return elem.disabled === true; + }, + checked : function(elem){ + + return elem.checked === true; + }, + 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 !!elem.firstChild; + }, + empty : function(elem){ + + return !elem.firstChild; + }, + has : function(elem, i, match){ + + return !!Sizzle(match[3], elem).length; + }, + header : function(elem){ + + return (/h\d/i).test(elem.nodeName); + }, + text : function(elem){ + + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return "text" === elem.getAttribute('type'); + }, + radio : function(elem){ + + return "radio" === elem.type; + }, + checkbox : function(elem){ + + return "checkbox" === elem.type; + }, + file : function(elem){ + + return "file" === elem.type; + }, + password : function(elem){ + + return "password" === elem.type; + }, + submit : function(elem){ + + return "submit" === elem.type; + }, + image : function(elem){ + + return "image" === elem.type; + }, + reset : function(elem){ + + return "reset" === elem.type; + }, + button : function(elem){ + + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input : function(elem){ + + return (/input|select|textarea|button/i).test(elem.nodeName); + } + }, + setFilters : { + first : function(elem, i){ + + return i === 0; + }, + last : function(elem, i, match, array){ + + return i === array.length - 1; + }, + even : function(elem, i){ + + return i % 2 === 0; + }, + odd : function(elem, i){ + + return i % 2 === 1; + }, + lt : function(elem, i, match){ + + return i < match[3] - 0; + }, + gt : function(elem, i, match){ + + return i > match[3] - 0; + }, + nth : function(elem, i, match){ + + return match[3] - 0 === i; + }, + eq : function(elem, i, match){ + + return match[3] - 0 === i; + } + }, + filter : { + PSEUDO : function(elem, match, i, array){ + + var name = match[1],filter = Expr.filters[name]; + if(filter){ + + return filter(elem, i, match, array); + } else if(name === "contains"){ + + return (elem.textContent || elem.innerText || Sizzle.getText([elem]) || "").indexOf(match[3]) >= 0; + } else if(name === "not"){ + + var not = match[3]; + for(var j = 0,l = not.length;j < l;j++){ + + if(not[j] === elem){ + + return false; + }; + }; + return true; + } else { + + Sizzle.error(name); + };; + }, + CHILD : function(elem, match){ + + var type = match[1],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;case "last": + while((node = node.nextSibling)){ + + if(node.nodeType === 1){ + + return false; + }; + }; + return true;case "nth": + var first = match[2],last = match[3]; + if(first === 1 && last === 0){ + + return true; + }; + var doneName = match[0],parent = elem.parentNode; + if(parent && (parent.sizcache !== doneName || !elem.nodeIndex)){ + + var count = 0; + for(node = parent.firstChild;node;node = node.nextSibling){ + + if(node.nodeType === 1){ + + node.nodeIndex = ++count; + }; + }; + parent.sizcache = doneName; + }; + var diff = elem.nodeIndex - last; + if(first === 0){ + + return diff === 0; + } else { + + return (diff % first === 0 && diff / first >= 0); + };}; + }, + ID : function(elem, match){ + + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG : function(elem, match){ + + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS : function(elem, match){ + + return (" " + (elem.className || elem.getAttribute("class")) + " ").indexOf(match) > -1; + }, + ATTR : function(elem, match){ + + var name = match[1],result = Expr.attrHandle[name] ? Expr.attrHandle[name](elem) : elem[name] != null ? elem[name] : elem.getAttribute(name),value = result + "",type = match[2],check = match[4]; + return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; + }, + POS : function(elem, match, i, array){ + + var name = match[2],filter = Expr.setFilters[name]; + if(filter){ + + return filter(elem, i, match, array); + }; + } + } + }; + var origPOS = Expr.match.POS,fescape = function(all, num){ + + return "\\" + (num - 0 + 1); + }; + for(var type in Expr.match){ + + Expr.match[type] = new RegExp(Expr.match[type].source + (/(?![^\[]*\])(?![^\(]*\))/.source)); + Expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + Expr.match[type].source.replace(/\\(\d+)/g, fescape)); + }; + var makeArray = function(array, results){ + + array = Array.prototype.slice.call(array, 0); + if(results){ + + results.push.apply(results, array); + return results; + }; + return array; + }; + // Perform a simple check to determine if the browser is capable of + // converting a NodeList to an array using builtin methods. + // Also verifies that the returned array holds DOM nodes + // (which is not the case in the Blackberry browser) + try{ + + Array.prototype.slice.call(document.documentElement.childNodes, 0)[0].nodeType; + } catch(e) { + + makeArray = function(array, results){ + + var i = 0,ret = results || []; + if(toString.call(array) === "[object Array]"){ + + Array.prototype.push.apply(ret, array); + } else { + + if(typeof array.length === "number"){ + + for(var l = array.length;i < l;i++){ + + ret.push(array[i]); + }; + } else { + + for(;array[i];i++){ + + ret.push(array[i]); + }; + }; + }; + return ret; + }; + }; + var sortOrder,siblingCheck; + if(document.documentElement.compareDocumentPosition){ + + sortOrder = function(a, b){ + + if(a === b){ + + hasDuplicate = true; + return 0; + }; + if(!a.compareDocumentPosition || !b.compareDocumentPosition){ + + return a.compareDocumentPosition ? -1 : 1; + }; + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + } else { + + sortOrder = function(a, b){ + + var al,bl,ap = [],bp = [],aup = a.parentNode,bup = b.parentNode,cur = aup; + // The nodes are identical, we can exit early + if(a === b){ + + hasDuplicate = true; + return 0; + } else 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); + }; + siblingCheck = function(a, b, ret){ + + if(a === b){ + + return ret; + }; + var cur = a.nextSibling; + while(cur){ + + if(cur === b){ + + return -1; + }; + cur = cur.nextSibling; + }; + return 1; + }; + }; + // Utility function for retreiving the text value of an array of DOM nodes + Sizzle.getText = function(elems){ + + var ret = "",elem; + for(var i = 0;elems[i];i++){ + + elem = elems[i]; + // Get the text from text nodes and CDATA nodes + if(elem.nodeType === 3 || elem.nodeType === 4){ + + ret += elem.nodeValue; + } else if(elem.nodeType !== 8){ + + ret += Sizzle.getText(elem.childNodes); + }; + }; + return ret; + }; + (function(){ + + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"),id = "script" + (new Date()).getTime(),root = document.documentElement; + form.innerHTML = ""; + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore(form, root.firstChild); + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if(document.getElementById(id)){ + + Expr.find.ID = function(match, context, isXML){ + + if(typeof context.getElementById !== "undefined" && !isXML){ + + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + }; + }; + Expr.filter.ID = function(elem, match){ + + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + }; + root.removeChild(form); + // release memory in IE + root = form = null; + })(); + (function(){ + + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + // Create a fake element + var div = document.createElement("div"); + div.appendChild(document.createComment("")); + // Make sure no comments are found + if(div.getElementsByTagName("*").length > 0){ + + Expr.find.TAG = function(match, context){ + + var results = context.getElementsByTagName(match[1]); + // Filter out possible comments + if(match[1] === "*"){ + + var tmp = []; + for(var i = 0;results[i];i++){ + + if(results[i].nodeType === 1){ + + tmp.push(results[i]); + }; + }; + results = tmp; + }; + return results; + }; + }; + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if(div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#"){ + + Expr.attrHandle.href = function(elem){ + + return elem.getAttribute("href", 2); + }; + }; + // release memory in IE + div = null; + })(); + if(document.querySelectorAll){ + + (function(){ + + var oldSizzle = Sizzle,div = document.createElement("div"),id = "__sizzle__"; + div.innerHTML = "

"; + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if(div.querySelectorAll && div.querySelectorAll(".TEST").length === 0){ + + return; + }; + Sizzle = function(query, context, extra, seed){ + + context = context || document; + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if(!seed && !Sizzle.isXML(context)){ + + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(query); + if(match && (context.nodeType === 1 || context.nodeType === 9)){ + + // Speed-up: Sizzle("TAG") + if(match[1]){ + + return makeArray(context.getElementsByTagName(query), extra); + } else if(match[2] && Expr.find.CLASS && context.getElementsByClassName){ + + return makeArray(context.getElementsByClassName(match[2]), extra); + }; + }; + if(context.nodeType === 9){ + + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if(query === "body" && context.body){ + + return makeArray([context.body], extra); + } else if(match && match[3]){ + + var elem = context.getElementById(match[3]); + // 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 and Opera return items + // by name instead of ID + if(elem.id === match[3]){ + + return makeArray([elem], extra); + }; + } else { + + return makeArray([], extra); + }; + }; + try{ + + return makeArray(context.querySelectorAll(query), extra); + } catch(qsaError) { + }; + } else if(context.nodeType === 1 && context.nodeName.toLowerCase() !== "object"){ + + var oldContext = context,old = context.getAttribute("id"),nid = old || id,hasParent = context.parentNode,relativeHierarchySelector = /^\s*[+~]/.test(query); + if(!old){ + + context.setAttribute("id", nid); + } else { + + nid = nid.replace(/'/g, "\\$&"); + }; + if(relativeHierarchySelector && hasParent){ + + context = context.parentNode; + }; + try{ + + if(!relativeHierarchySelector || hasParent){ + + return makeArray(context.querySelectorAll("[id='" + nid + "'] " + query), extra); + }; + } catch(pseudoError) { + }finally{ + + if(!old){ + + oldContext.removeAttribute("id"); + }; + }; + }; + }; + return oldSizzle(query, context, extra, seed); + }; + for(var prop in oldSizzle){ + + Sizzle[prop] = oldSizzle[prop]; + }; + // release memory in IE + div = null; + })(); + }; + (function(){ + + var html = document.documentElement,matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,pseudoWorks = false; + try{ + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call(document.documentElement, "[test!='']:sizzle"); + } catch(pseudoError) { + + pseudoWorks = true; + }; + if(matches){ + + Sizzle.matchesSelector = function(node, expr){ + + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + if(!Sizzle.isXML(node)){ + + try{ + + if(pseudoWorks || !Expr.match.PSEUDO.test(expr) && !/!=/.test(expr)){ + + return matches.call(node, expr); + }; + } catch(e) { + }; + }; + return Sizzle(expr, null, null, [node]).length > 0; + }; + }; + })(); + (function(){ + + var div = document.createElement("div"); + div.innerHTML = "
"; + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if(!div.getElementsByClassName || div.getElementsByClassName("e").length === 0){ + + return; + }; + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + if(div.getElementsByClassName("e").length === 1){ + + return; + }; + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML){ + + if(typeof context.getElementsByClassName !== "undefined" && !isXML){ + + return context.getElementsByClassName(match[1]); + }; + }; + // release memory in IE + div = null; + })(); + function dirNodeCheck(dir, cur, doneName, checkSet, nodeCheck, isXML){ + + for(var i = 0,l = checkSet.length;i < l;i++){ + + var elem = checkSet[i]; + if(elem){ + + var match = false; + elem = elem[dir]; + while(elem){ + + if(elem.sizcache === doneName){ + + match = checkSet[elem.sizset]; + break; + }; + if(elem.nodeType === 1 && !isXML){ + + elem.sizcache = doneName; + elem.sizset = i; + }; + if(elem.nodeName.toLowerCase() === cur){ + + match = elem; + break; + }; + elem = elem[dir]; + }; + checkSet[i] = match; + }; + }; + }; + function dirCheck(dir, cur, doneName, checkSet, nodeCheck, isXML){ + + for(var i = 0,l = checkSet.length;i < l;i++){ + + var elem = checkSet[i]; + if(elem){ + + var match = false; + elem = elem[dir]; + while(elem){ + + if(elem.sizcache === doneName){ + + match = checkSet[elem.sizset]; + break; + }; + if(elem.nodeType === 1){ + + if(!isXML){ + + elem.sizcache = doneName; + elem.sizset = i; + }; + if(typeof cur !== "string"){ + + if(elem === cur){ + + match = true; + break; + }; + } else if(Sizzle.filter(cur, [elem]).length > 0){ + + match = elem; + break; + }; + }; + elem = elem[dir]; + }; + checkSet[i] = match; + }; + }; + }; + if(document.documentElement.contains){ + + Sizzle.contains = function(a, b){ + + return a !== b && (a.contains ? a.contains(b) : true); + }; + } else if(document.documentElement.compareDocumentPosition){ + + Sizzle.contains = function(a, b){ + + return !!(a.compareDocumentPosition(b) & 16); + }; + } else { + + Sizzle.contains = function(){ + + return false; + }; + }; + 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 : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; + }; + var posProcess = function(selector, context){ + + var match,tmpSet = [],later = "",root = context.nodeType ? [context] : context; + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while((match = Expr.match.PSEUDO.exec(selector))){ + + later += match[0]; + selector = selector.replace(Expr.match.PSEUDO, ""); + }; + selector = Expr.relative[selector] ? selector + "*" : selector; + for(var i = 0,l = root.length;i < l;i++){ + + Sizzle(selector, root[i], tmpSet); + }; + return Sizzle.filter(later, tmpSet); + }; + /** + * Above is the original Sizzle code. + */ + // EXPOSE qooxdoo variant + var Selector = qx.bom.Selector; + Selector.query = function(selector, context){ + + return Sizzle(selector, context); + }; + Selector.matches = function(selector, set){ + + return Sizzle(selector, null, null, set); + }; +})(); + +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2011-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) + * Daniel Wagner (danielwagner) + +************************************************************************ */ +/** + * CSS/Style property manipulation module + */ +qx.Bootstrap.define("qx.module.Css", { + statics : { + /** + * Modifies the given style property on all elements in the collection. + * + * @attach {q} + * @param name {String} Name of the style property to modify + * @param value {var} The value to apply + * @return {q} The collection for chaining + */ + setStyle : function(name, value){ + + if(/\w-\w/.test(name)){ + + name = qx.lang.String.camelCase(name); + }; + for(var i = 0;i < this.length;i++){ + + qx.bom.element.Style.set(this[i], name, value); + }; + return this; + }, + /** + * Returns the value of the given style property for the first item in the + * collection. + * + * @attach {q} + * @param name {String} Style property name + * @return {var} Style property value + */ + getStyle : function(name){ + + if(this[0]){ + + if(/\w-\w/.test(name)){ + + name = qx.lang.String.camelCase(name); + }; + return qx.bom.element.Style.get(this[0], name); + }; + return null; + }, + /** + * Sets multiple style properties for each item in the collection. + * + * @attach {q} + * @param styles {Map} A map of style property name/value pairs + * @return {q} The collection for chaining + */ + setStyles : function(styles){ + + for(var name in styles){ + + this.setStyle(name, styles[name]); + }; + return this; + }, + /** + * Returns the values of multiple style properties for each item in the + * collection + * + * @attach {q} + * @param names {String[]} List of style property names + * @return {Map} Map of style property name/value pairs + */ + getStyles : function(names){ + + var styles = { + }; + for(var i = 0;i < names.length;i++){ + + styles[names[i]] = this.getStyle(names[i]); + }; + return styles; + }, + /** + * Adds a class name to each element in the collection + * + * @attach {q} + * @param name {String} Class name + * @return {q} The collection for chaining + */ + addClass : function(name){ + + for(var i = 0;i < this.length;i++){ + + qx.bom.element.Class.add(this[i], name); + }; + return this; + }, + /** + * Adds multiple class names to each element in the collection + * + * @attach {q} + * @param names {String[]} List of class names to add + * @return {q} The collection for chaining + */ + addClasses : function(names){ + + for(var i = 0;i < this.length;i++){ + + qx.bom.element.Class.addClasses(this[i], names); + }; + return this; + }, + /** + * Removes a class name from each element in the collection + * + * @attach {q} + * @param name {String} The class name to remove + * @return {q} The collection for chaining + */ + removeClass : function(name){ + + for(var i = 0;i < this.length;i++){ + + qx.bom.element.Class.remove(this[i], name); + }; + return this; + }, + /** + * Removes multiple class names from each element in the collection + * + * @attach {q} + * @param names {String[]} List of class names to remove + * @return {q} The collection for chaining + */ + removeClasses : function(names){ + + for(var i = 0;i < this.length;i++){ + + qx.bom.element.Class.removeClasses(this[i], names); + }; + return this; + }, + /** + * Checks if the first element in the collection has the given class name + * + * @attach {q} + * @param name {String} Class name to check for + * @return {Boolean} true if the first item has the given class name + */ + hasClass : function(name){ + + if(!this[0]){ + + return false; + }; + return qx.bom.element.Class.has(this[0], name); + }, + /** + * Returns the class name of the first element in the collection + * + * @attach {q} + * @return {String} Class name + */ + getClass : function(){ + + if(!this[0]){ + + return ""; + }; + return qx.bom.element.Class.get(this[0]); + }, + /** + * Toggles the given class name on each item in the collection + * + * @attach {q} + * @param name {String} Class name + * @return {q} The collection for chaining + */ + toggleClass : function(name){ + + var bCls = qx.bom.element.Class; + for(var i = 0,l = this.length;i < l;i++){ + + bCls.has(this[i], name) ? bCls.remove(this[i], name) : bCls.add(this[i], name); + }; + return this; + }, + /** + * Toggles the given list of class names on each item in the collection + * + * @attach {q} + * @param names {String[]} Class names + * @return {q} The collection for chaining + */ + toggleClasses : function(names){ + + for(var i = 0,l = names.length;i < l;i++){ + + this.toggleClass(names[i]); + }; + return this; + }, + /** + * Replaces a class name on each element in the collection + * + * @attach {q} + * @param oldName {String} Class name to remove + * @param newName {String} Class name to add + * @return {q} The collection for chaining + */ + replaceClass : function(oldName, newName){ + + for(var i = 0,l = this.length;i < l;i++){ + + qx.bom.element.Class.replace(this[i], oldName, newName); + }; + return this; + }, + /** + * Returns the rendered height of the first element in the collection. + * @attach {q} + * @return {Number} The first item's rendered height + */ + getHeight : function(){ + + var elem = this[0]; + if(elem){ + + if(qx.dom.Node.isElement(elem)){ + + return qx.bom.element.Dimension.getHeight(elem); + } else if(qx.dom.Node.isDocument(elem)){ + + return qx.bom.Document.getHeight(qx.dom.Node.getWindow(elem)); + } else if(qx.dom.Node.isWindow(elem)){ + + return qx.bom.Viewport.getHeight(elem); + };; + }; + return null; + }, + /** + * Returns the rendered width of the first element in the collection + * @attach {q} + * @return {Number} The first item's rendered width + */ + getWidth : function(){ + + var elem = this[0]; + if(elem){ + + if(qx.dom.Node.isElement(elem)){ + + return qx.bom.element.Dimension.getWidth(elem); + } else if(qx.dom.Node.isDocument(elem)){ + + return qx.bom.Document.getWidth(qx.dom.Node.getWindow(elem)); + } else if(qx.dom.Node.isWindow(elem)){ + + return qx.bom.Viewport.getWidth(elem); + };; + }; + return null; + }, + /** + * Returns the computed location of the given element in the context of the + * document dimensions. + * + * @attach {q} + * @return {Map} A map with the keys left, top, + * right and bottom which contains the distance + * of the element relative to the document. + */ + getOffset : function(){ + + var elem = this[0]; + if(elem){ + + return qx.bom.element.Location.get(elem); + }; + return null; + }, + /** + * Returns the content height of the first element in the collection. + * This is the maximum height the element can use, excluding borders, + * margins, padding or scroll bars. + * @attach {q} + * @return {Number} Computed content height + */ + getContentHeight : function(){ + + var obj = this[0]; + if(qx.dom.Node.isElement(obj)){ + + return qx.bom.element.Dimension.getContentHeight(obj); + }; + return null; + }, + /** + * Returns the content width of the first element in the collection. + * This is the maximum width the element can use, excluding borders, + * margins, padding or scroll bars. + * @attach {q} + * @return {Number} Computed content width + */ + getContentWidth : function(){ + + var obj = this[0]; + if(qx.dom.Node.isElement(obj)){ + + return qx.bom.element.Dimension.getContentWidth(obj); + }; + return null; + }, + /** + * Returns the distance between the first element in the collection and its + * offset parent + * + * @attach {q} + * @return {Map} a map with the keys left and top + * containing the distance between the elements + */ + getPosition : function(){ + + var obj = this[0]; + if(qx.dom.Node.isElement(obj)){ + + return qx.bom.element.Location.getPosition(obj); + }; + return null; + }, + /** + * Includes a Stylesheet file + * + * @attachStatic {q} + * @param uri {String} The stylesheet's URI + * @param doc {Document?} Document to modify + */ + includeStylesheet : function(uri, doc){ + + qx.bom.Stylesheet.includeFile(uri, doc); + } + }, + defer : function(statics){ + + q.$attach({ + "setStyle" : statics.setStyle, + "getStyle" : statics.getStyle, + "setStyles" : statics.setStyles, + "getStyles" : statics.getStyles, + "addClass" : statics.addClass, + "addClasses" : statics.addClasses, + "removeClass" : statics.removeClass, + "removeClasses" : statics.removeClasses, + "hasClass" : statics.hasClass, + "getClass" : statics.getClass, + "toggleClass" : statics.toggleClass, + "toggleClasses" : statics.toggleClasses, + "replaceClass" : statics.replaceClass, + "getHeight" : statics.getHeight, + "getWidth" : statics.getWidth, + "getOffset" : statics.getOffset, + "getContentHeight" : statics.getContentHeight, + "getContentWidth" : statics.getContentWidth, + "getPosition" : statics.getPosition + }); + q.$attachStatic({ + "includeStylesheet" : statics.includeStylesheet + }); + } +}); + +/* ************************************************************************ + + 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 + + License: + MIT: http://www.opensource.org/licenses/mit-license.php + + Authors: + * Steven Levithan + +************************************************************************ */ +/** + * String helper functions + * + * The native JavaScript String is not modified by this class. However, + * there are modifications to the native String in {@link qx.lang.Core} for + * browsers that do not support certain features. + * + * The string/array generics introduced in JavaScript 1.6 are supported by + * {@link qx.lang.Generics}. + */ +qx.Bootstrap.define("qx.lang.String", { + statics : { + /** + * Unicode letters. they are taken from Steve Levithan's excellent XRegExp library [http://xregexp.com/plugins/xregexp-unicode-base.js] + */ + __unicodeLetters : "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + /** + * A RegExp that matches the first letter in a word - unicode aware + */ + __unicodeFirstLetterInWordRegexp : null, + /** + * {Map} Cache for often used string operations [camelCasing and hyphenation] + * e.g. marginTop => margin-top + */ + __stringsMap : { + }, + /** + * Converts a hyphenated string (separated by '-') to camel case. + * + * Example: + *
qx.lang.String.camelCase("I-like-cookies"); //returns "ILikeCookies"
+ * The implementation does not force a lowerCamelCase or upperCamelCase version. + * (think java variables that start with lower case versus classnames that start with capital letter) + * The first letter of the parameter keeps its case. + * + * @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(); + }); + this.__stringsMap[str] = result; + }; + return result; + }, + /** + * Converts a camelcased string to a hyphenated (separated by '-') string. + * + * Example: + *
qx.lang.String.hyphenate("ILikeCookies"); //returns "I-like-cookies"
+ * The implementation does not force a lowerCamelCase or upperCamelCase version. + * (think java variables that start with lower case versus classnames that start with capital letter) + * The first letter of the parameter keeps its case. + * + * @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()); + }); + 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 this.trim(str.replace(/\s+/g, ' ')); + }, + /** + * 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+$/, ""); + }, + /** + * removes white space from the left and the right side of a string + * + * @param str {String} the string to trim + * @return {String} the trimmed string + */ + trim : function(str){ + + return str.replace(/^\s+|\s+$/g, ""); + }, + /** + * 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