diff options
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client')
5 files changed, 1725 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Builder.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Builder.js new file mode 100644 index 0000000000..03156282f5 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Builder.js @@ -0,0 +1,478 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + + +************************************************************************ */ + +/*! + A class to generate a widget hierarchy from XML + + qx.client.Builder is not thread safe by design + - state information is stored at the instance level + - only use it from a single thread +*/ +qx.OO.defineClass("qx.client.Builder", qx.core.Target, +function(flags) +{ + qx.core.Target.call(this); + + // map<className, map<propertyName, function>> + this._propertyEditors = {}; + + this._registerDefaultPropertyEditors(); + + this._flags = flags || {}; + + // ensure the default flags are setup + if (this._flags.strict == null) { + // strick mode throws exceptions when + // * widget setters don't exist + this._flags.strict = true; + } + +}); + +/* +------------------------------------------------------------------------------------ + BUILD +------------------------------------------------------------------------------------ +*/ + +/*! + Asynchronous method - fetches XML data from the URL then delegates to build to process the xml + Dispatches a qx.event.type.Event("done") after the hierarchy is built +*/ +qx.Proto.buildFromUrl = function(parent, url) { + var req = new qx.io.remote.Request(url, "GET", "application/xml"); + var self = this; + req.addEventListener("completed", function(e) { + self.build(parent, e.getData().getContent()); + qx.ui.core.Widget.flushGlobalQueues(); + }); + req.send(); +} + +/*! + parse the children of the xml and appending all widgets to the parent widget + @param parent can either be the application instance, or a widget to append the xml toplevel widgets to + @param node can be either a xml string, or a xml dom document or fragment +*/ +qx.Proto.build = function(parent, node) { + // support embedding of an XML string within a textarea + if (typeof node == "object" && node.nodeName == 'TEXTAREA') { + node = node.value; + } + + // parse strings in to XML DOM + if (typeof node == "string") { + var parser = new DOMParser(); + node = parser.parseFromString(node, "text/xml"); + // TODO handle parse errors + } + this._buildNodes(parent, node.childNodes); +} + +qx.Proto._buildNodes = function(parent, nodes) { + var x = 0; + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + // 1 = ELEMENT_NODE + if (n.nodeType == 1) { + this._buildWidgetFromNode(parent, n); + } + } +} + +qx.Proto._buildEventListener = function(widget, args, text) { + if (qx.util.Validation.isInvalidString(args.type)) { + throw this._newError('eventListener requires a string type attribute'); + } + + var self = this; + + // are we delegating ? + if (qx.util.Validation.isValidString(args.delegate)) { + + if (args.delegate.indexOf('.') > -1) { + // delegation to a global method + var p = args.delegate.split('.'); + var o = p[0]; + var m = p[1]; + widget.addEventListener(args.type, function(e) { + + if (!window[o]) { + throw self._newError('delegate not found', {delegate:args.delegate}); + } + + if (!window[o][m]) { + throw self._newError('delegate not found', {delegate:args.delegate}); + } + + window[o][m].apply(window[o], [e]); + }); + } + else { + + // delegation to a global method + widget.addEventListener(args.type, function(e) { + + if (!window[args.delegate]) { + throw self._newError('delegate not found', {delegate:args.delegate}); + } + + window[args.delegate].apply(null, [e]); + }); + } + } + else { + + // build a function object using text as the function body + // + // the args attribute indicates the name of the event argument + // if not provided - use 'event' as the name + if (!args.args) { + args.args = "event"; + } + + var f = new Function(args.args, text); + widget.addEventListener(args.type, f); + } +} + + +/* + a node builder that will be used if no node builder is declared for a nodeName +*/ +qx.Proto._buildWidgetFromNode = function(parent, node) { + + var className = this._extractClassName(node); + + if (!className) { + throw this._newError("unrecognised node", {nodeName:node.nodeName}); + } + + if (className == "qx.client.builder.Container") { + // generic container node to allow xml to contain multiple toplevel nodes + this._buildNodes(parent, node.childNodes); + return; + } + + if (className == "qx.client.builder.Script") { + var e = document.createElement("script"); + var attribs = this._mapXmlAttribToObject(node); + if (attribs.type) { + e.type = attribs.type; + } + else { + e.type='text/javascript'; + } + + // e.innerHTML = node.firstChild.nodeValue; + + // fix for Internet Explorer by Cristian Bica + if (qx.sys.Client.getInstance().isMshtml()) + { + e.innerHTML = eval(node.firstChild.nodeValue); + } + else + { + e.innerHTML = node.firstChild.nodeValue; + } + + document.body.appendChild(e); + return; + } + + if (className == "qx.client.builder.EventListener") { + var attribs = this._mapXmlAttribToObject(node); + var text; + if (node.firstChild) { + text = node.firstChild.nodeValue; + } + this._buildEventListener(parent, attribs, text); + return; + } + + + var classConstructor = qx.OO.classes[className]; + if (!classConstructor) { + throw this._newError("constructor not found", {className:className}); + } + + // construct the widget instance - using the default constructor + var widget = new classConstructor(); + var attribs = this._mapXmlAttribToObject(node, widget); + delete attribs['qxtype']; + + var dummyWidget = attribs.id && attribs.id.indexOf("_") == 0; + + if (attribs.id) { + // register a global refrence for this widget + window[attribs.id] = widget; + delete attribs.id; + } + + // convert any on?? attribs into event listeners + for (var a in attribs) { + + if (a.toLowerCase().indexOf('on') == 0 && a.length > 2) { + + // there may be issues here for XHTML based attributes - due to their case + var type = a.substring(2); + type = type.charAt(0) + type.substring(1); + + this._buildEventListener(widget, {type:type,args:'event'}, attribs[a]); + + delete attribs[a]; + } + } + + for (var n in attribs) { + this._setWidgetProperty(widget, n, attribs[n]); + } + + if(!dummyWidget) { + parent.add(widget); + } + + // recurse to all of the nodes children, using the newly created widget as the parent + this._buildNodes(widget, node.childNodes); +} + +/* +------------------------------------------------------------------------------------ + WIDGET PROPERTIES +------------------------------------------------------------------------------------ +*/ + + +/*! + Set a widget's property using a propertyEditor +*/ +qx.Proto._setWidgetProperty = function(widget, name, value) { + var editor = this._findPropertyEditor(widget.classname, name); + if (!editor) { + editor = this._coercePropertyEditor; + } + editor.set(widget, name, value); +} + +qx.Proto._findPropertyEditor = function(className, propertyName) { + // get all defined propertyEditors for this widget's prototype + var m = this._propertyEditors[className]; + // lookup the converter for this property name + if (m && m[propertyName]) { + return m[propertyName]; + } + + // try the widget's superclass + var w = qx.OO.classes[className]; + if (w && w.superclass && w.superclass.prototype.classname) { + return this._findPropertyEditor(w.superclass.prototype.classname, propertyName); + } + + return null; +} + +qx.Proto.registerPropertyEditor = function(className, propertyName, editor) { + if (!this._propertyEditors[className]) this._propertyEditors[className] = {}; + this._propertyEditors[className][propertyName] = editor; +} + +qx.Proto._registerDefaultPropertyEditors = function() { + var self = this; + + // a property editor that splits the values on a comma and coerces each one into a suitable type + var commaDelimitedPropertyEditor = {}; + commaDelimitedPropertyEditor.set = function(widget, name, value) { + if (value == null || value == "") { + self._setProperty(widget, name, null); + return; + } + + var s = value.split(","); + var v = []; + for (var i = 0; i < s.length; i++) { + v[i] = self._coerce(s[i]); + } + + self._setProperties(widget, name, v); + } + + var evalPropertyEditor = {}; + evalPropertyEditor.set = function(widget, name, value) { + if (value == null || value == "") { + self._setProperty(widget, name, null); + return; + } + + self._setProperty(widget, name, eval(value)); + } + + var referencePropertyEditor = {}; + referencePropertyEditor.set = function(widget, name, value) { + self._setProperty(widget, name, window[value]); + } + + this.registerPropertyEditor('qx.ui.core.Widget', 'location', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'dimension', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'space', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'edge', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'padding', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'margin', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'heights', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'widths', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'align', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'stretch', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'clipLocation', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'clipDimension', commaDelimitedPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'clip', commaDelimitedPropertyEditor); + + this.registerPropertyEditor('qx.ui.core.Widget', 'backgroundColor', evalPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'color', evalPropertyEditor); + this.registerPropertyEditor('qx.ui.core.Widget', 'border', evalPropertyEditor); + + + this.registerPropertyEditor('qx.ui.menu.Button', 'menu', referencePropertyEditor); + this.registerPropertyEditor('qx.ui.form.RadioButton', 'manager', referencePropertyEditor); + this.registerPropertyEditor('qx.ui.menu.RadioButton', 'group', referencePropertyEditor); + + + // a property editor that just tries to coerce the string value into a suitable type + this._coercePropertyEditor = {}; + this._coercePropertyEditor.set = function(widget, name, value) { + self._setProperty(widget, name, self._coerce(value)); + } + +} + + +qx.Proto._coerce = function(value) { + + // don't really care if its null + if (value == null) return value; + + // is it alreay a javascript type + if (typeof value == 'object') return value; + if (typeof value == 'function') return value; + if (typeof value == 'number') return value; + if (typeof value == 'boolean') return value; + if (typeof value == 'date') return value; + if (typeof value == 'array') return value; + + // is it a number ? + var n = new Number(value); + if (!isNaN(n)) return n.valueOf(); + + // is it a boolean ? + if (value == "true") return true; + if (value == "false") return false; + + // is it a date ? + var d = Date.parse(value); + if (d != null && !isNaN(d)) return d; + + // leave it as a string + if (typeof value == 'string') { + // convert empty string into null + if (value == "") return null; + } + + return value; +} + +qx.Proto._setProperty = function(widget, name, value) { + this._setProperties(widget, name, [value]); +} + +qx.Proto._setProperties = function(widget, name, value) { + + // TODO : find a cheaper way to find the setter + // NOTE : the name is LOWERCASE - hence we iterate all properties of the widget + // to try and find a matching one + var n = "set" + name; + for (var a in widget) { + if (n == a.toLowerCase()) { + var setter = widget[a]; + break; + } + } + if (!setter && this._flags.strict) throw this._newError('no setter defined on widget instance', {widget:widget, property:name}); + setter.apply(widget, value); +} + + +/* +------------------------------------------------------------------------------------ + UTILS +------------------------------------------------------------------------------------ +*/ + +/* +2 format +1. <qx.ui.basic.Atom/> +3. <div qxtype="qx.ui.basic.Atom"/> +*/ +qx.Proto._extractClassName = function(node) { + if (node.nodeName.toLowerCase() == "div") { + if (!node.attributes['qxtype']) + return null; + return node.attributes['qxtype'].value; + } else { + return node.nodeName; + } +} + +qx.Proto._mapXmlAttribToObject = function(node) { + var r = {}; + var c = node.attributes; + for (var i=0; i<c.length; i++) { + r[c[i].name.toLowerCase()] = c[i].value; + } + return r; +} + +/* +------------------------------------------------------------------------------------ + EXCEPTION HANDLING / DEBUGGING +------------------------------------------------------------------------------------ +*/ + +qx.Proto._newError = function(message, data, exception) { + var m = message; + var joiner = ""; + var d = ""; + if (data) { + for (var p in data) { + d += joiner + p + "=" + data[p] + ''; + joiner = " "; + } + m += " " + d + " "; + } + if (exception) { + m+= " error: " + exception + " "; + } + return new Error(m); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Command.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Command.js new file mode 100644 index 0000000000..6ea2fd0d14 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Command.js @@ -0,0 +1,288 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + * Fabian Jakobs (fjakobs) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) + +************************************************************************ */ + +/** + * This contains a command with shortcut. + * + * Each command could be assigned to multiple widgets. + * + * @event execute {qx.event.type.DataEvent} when the command is executed. + * + * @param vShortcut (string) shortcuts can be composed of optional modifier + * keys Control, Alt, Shift, Meta and a non modifier key. + * If no non modifier key is specified, the second paramater is evaluated. + * The key must be seperated by a ''+'' or ''-'' character. + * Examples: Alt+F1, Control+C, Control+Alt+Enf + * + * @param vKeyCodeOrIdentifier (int) Additional key of the command. It is interpreted as a + * keyIdentifier if it is given as integer. Otherwhise it is interpreted as keyCode. + */ +qx.OO.defineClass("qx.client.Command", qx.core.Target, +function(vShortcut, vKeyCodeOrIdentifier) +{ + qx.core.Target.call(this); + + this._modifier = {}; + this._key = null; + + if (qx.util.Validation.isValid(vShortcut)) { + this.setShortcut(vShortcut); + } + + if (qx.util.Validation.isValid(vKeyCodeOrIdentifier)) + { + if (qx.util.Validation.isValidString(vKeyCodeOrIdentifier)) + { + this.setKeyIdentifier(vKeyCodeOrIdentifier); + } + else if (qx.util.Validation.isValidNumber(vKeyCodeOrIdentifier)) + { + this.warn("The use of keyCode in command is deprecated. Use keyIdentifier instead."); + this.setKeyCode(vKeyCodeOrIdentifier); + } + else + { + var msg = "vKeyCodeOrIdentifier must be of type string or number: " + vKeyCodeOrIdentifier; + this.error(msg); + throw msg; + } + } + + // OSX warning for Alt key combinations + if (this._modifier.Alt && this._key && this._key.length == 1) { + if ( + (this._key >= "A" && this._key <= "Z") || + (this._key >= "0" && this._key <= "9") + ) { + this.warn("A shortcut containing Alt and a letter or number will not work under OS X!"); + } + } + qx.event.handler.EventHandler.getInstance().addCommand(this); +}); + + +/** the command shortcut */ +qx.OO.addProperty({ name : "shortcut", type : "string" }); + +/** + * keyCode (Deprecated) + * Still there for compatibility with the old key handler/commands + */ +qx.OO.addProperty({ name : "keyCode", type : "number" }); + +/** KeyIdentifier */ +qx.OO.addProperty({ name : "keyIdentifier", type : "string" }); + + + +/* +--------------------------------------------------------------------------- + USER METHODS +--------------------------------------------------------------------------- +*/ + +/** + * Fire the "execute" event on this command. + * + * @param vTarget (Object) + */ +qx.Proto.execute = function(vTarget) +{ + if (this.hasEventListeners("execute")) { + this.dispatchEvent(new qx.event.type.DataEvent("execute", vTarget), true); + } + + return false; +}; + + + +/* +--------------------------------------------------------------------------- + MODIFIER +--------------------------------------------------------------------------- +*/ + +qx.Proto._modifyShortcut = function(propValue, propOldValue, propData) +{ + if (propValue) + { + this._modifier = {}; + this._key = null; + + // split string to get each key which must be pressed + // build a hash with active keys + var a = propValue.split(/[-+\s]+/); + var al = a.length; + + for (var i=0; i<al; i++) + { + var identifier = qx.event.handler.KeyEventHandler.getInstance().oldKeyNameToKeyIdentifier(a[i]); + + switch (identifier) + { + case "Control": + case "Shift": + case "Meta": + case "Alt": + this._modifier[identifier] = true; + break; + + case "Unidentified": + var msg = "Not a valid key name for a command: " + a[i]; + this.error(msg); + throw msg; + + default: + if (this._key) { + var msg = "You can only specify one non modifier key!"; + this.error(msg); + throw msg; + } + this._key = identifier; + } + } + } + return true; +}; + + + +/* +--------------------------------------------------------------------------- + INTERNAL MATCHING LOGIC +--------------------------------------------------------------------------- +*/ + +/** + * Checks wether the given key event matches the command's shortcut + * + * @param e (qx.event.type.KeyEvent) the key event object + * @return (boolean) wether the commands shortcut matches the key event + */ +qx.Proto._matchesKeyEvent = function(e) +{ + var key = this._key || this.getKeyIdentifier(); + if (!key && !this.getKeyCode()) { + // no shortcut defined. + return; + } + + // pre-check for check special keys + // we handle this here to omit to check this later again. + if ( + (this._modifier.Shift && !e.getShiftKey()) || + (this._modifier.Control && !e.getCtrlKey()) || +// (this._modifier.Meta && !e.getCtrlKey()) || + (this._modifier.Alt && !e.getAltKey()) + ) { + return false; + } + + if (key) + { + if (key == e.getKeyIdentifier()) { + return true; + } + } + else + { + if (this.getKeyCode() == e.getKeyCode()) { + return true; + } + } + + return false; +}; + + + +/* +--------------------------------------------------------------------------- + STRING CONVERTION +--------------------------------------------------------------------------- +*/ + +/** + * Returns the shortcut as string + * + * @return (string) shortcut + */ +qx.Proto.toString = function() +{ + var vShortcut = this.getShortcut(); + var vKeyCode = this.getKeyCode(); + var vString = ""; + var vKeyIdentifier = this._key || this.getKeyIdentifier(); + + var vKeyString = ""; + if (qx.util.Validation.isValidString(vKeyIdentifier)) + { + vKeyString = vKeyIdentifier; + } + else if (qx.util.Validation.isValidNumber(vKeyCode)) + { + var vTemp = qx.event.type.KeyEvent.codes[vKeyCode]; + vKeyString = vTemp ? qx.lang.String.toFirstUp(vTemp) : String(vKeyCode); + } + + if (qx.util.Validation.isValidString(vShortcut)) + { + vString = vShortcut + "+" + vKeyString; + } + else if (qx.util.Validation.isValidNumber(vKeyCode)) + { + vString = vKeyString; + } + + return vString; +}; + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +/** + * Destructor + */ +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + this._shortcutParts = null; + + var vMgr = qx.event.handler.EventHandler.getInstance(); + if (vMgr) { + vMgr.removeCommand(this); + } + + return qx.core.Target.prototype.dispose.call(this); +}; diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/History.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/History.js new file mode 100644 index 0000000000..e242d7c85a --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/History.js @@ -0,0 +1,137 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#resource(html:static/history) +#require(qx.manager.object.AliasManager) + +************************************************************************ */ + +/** + * A helper for using the browser history in JavaScript Applications without + * reloading the main page. + * <p> + * Adds entries to the browser history and fires a "request" event when one of + * the entries was requested by the user (e.g. by clicking on the back button). + * </p> + * + * @event request {qx.event.type.DataEvent} Fired when the user moved in the + * history. The data property of the event holds the command, which was + * passed to {@link #addToHistory}. + */ +qx.OO.defineClass("qx.client.History", qx.core.Target, +function() { + qx.core.Target.call(this); + + this._pageFlag = true; +}); + + +/** + * Initializes the History. This method has to called by applications using this + * class once during initialization. Subsequent calls have no (negative) effect. + */ +qx.Proto.init = function() { + if (this._iframe == null) { + this._iframe = document.createElement("iframe"); + this._iframe.style.visibility = "hidden"; + document.body.appendChild(this._iframe); + } +} + + +/** + * Adds an entry to the browser history. + * + * @param command {string} a string representing the old state of the + * application. This command will be delivered in the data property of + * the "request" event. + * @param newTitle {string ? null} the page title to set after the history entry + * is done. This title should represent the new state of the application. + */ +qx.Proto.addToHistory = function(command, newTitle) { + if (command == this._currentCommand) { + document.title = newTitle; + } else { + if (this._iframe == null) { + throw new Error("You have to call init first!"); + } + + this._pageFlag = !this._pageFlag; + this._currentCommand = command; + this._newTitle = newTitle; + + // NOTE: We need the command attribute to enforce a loading of the page + // (Otherwise we don't get an onload event). + // The browser will still cache commands loaded once. + // Without the onload-problem anchors would work, too. + // (Anchors would have the advantage that the helper is only loaded once) + this._iframe.src = this.getSetting("helperFile") + "?c=" + command; + } +} + + +/** + * Event handler. Called when the history helper page was loaded. + * + * @param location {Map} the location property of the window object of the + * helper page. + */ +qx.Proto._onHistoryLoad = function(location) +{ + try { + var equalsPos = location.search.indexOf("="); + var command = location.search.substring(equalsPos + 1); + + if (this._newTitle) { + document.title = this._newTitle; + this._newTitle = null; + } + + if (command != this._currentCommand) { + this._currentCommand = command; + + this.createDispatchDataEvent("request", command); + } + } catch (exc) { + this.error("Handling history load failed", exc); + } + + qx.ui.core.Widget.flushGlobalQueues(); +} + + +/** The URL to the helper page. */ +qx.Settings.setDefault("helperFile", qx.Settings.getValueOfClass("qx.manager.object.AliasManager", "staticUri") + "/history/historyHelper.html"); + + + + + + +/* +--------------------------------------------------------------------------- + DEFER SINGLETON INSTANCE +--------------------------------------------------------------------------- +*/ + +/** + * Singleton Instance Getter + */ +qx.Class.getInstance = qx.util.Return.returnInstance; diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/NativeWindow.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/NativeWindow.js new file mode 100644 index 0000000000..69e9c2a87c --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/NativeWindow.js @@ -0,0 +1,639 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#require(qx.dom.Window) + +************************************************************************ */ + +qx.OO.defineClass("qx.client.NativeWindow", qx.core.Target, +function(vUrl, vName) +{ + qx.core.Target.call(this); + + + // ************************************************************************ + // TIMER + // ************************************************************************ + + this._timer = new qx.client.Timer(100); + this._timer.addEventListener("interval", this._oninterval, this); + + + // ************************************************************************ + // INITIAL PROPERTIES + // ************************************************************************ + + if (qx.util.Validation.isValidString(vUrl)) { + this.setUrl(vUrl); + } + + if (qx.util.Validation.isValidString(vName)) { + this.setName(vName); + } +}); + + + + + +/* +--------------------------------------------------------------------------- + PROPERTIES +--------------------------------------------------------------------------- +*/ + +/*! + If the window is open or closed +*/ +qx.OO.addProperty({ name : "open", type : "boolean", defaultValue : false }); + +/*! + The outer width of the window. +*/ +qx.OO.addProperty({ name : "width", type : "number", defaultValue : 400, impl : "dimension" }); + +/*! + The outer height of the window. +*/ +qx.OO.addProperty({ name : "height", type : "number", defaultValue : 250, impl : "dimension" }); + +/*! + The left screen coordinate of the window. +*/ +qx.OO.addProperty({ name : "left", type : "number", defaultValue : 100, impl : "position" }); + +/*! + The top screen coordinate of the window. +*/ +qx.OO.addProperty({ name : "top", type : "number", defaultValue : 200, impl : "position" }); + +/*! + Should be window be modal +*/ +qx.OO.addProperty({ name : "modal", type : "boolean", defaultValue : false }); + +/*! + Should be window be dependent on this application window +*/ +qx.OO.addProperty({ name : "dependent", type : "boolean", defaultValue : true }); + +/*! + The url +*/ +qx.OO.addProperty({ name : "url", type : "string" }); + +/*! + The window name +*/ +qx.OO.addProperty({ name : "name", type : "string" }); + +/*! + The text of the statusbar +*/ +qx.OO.addProperty({ name : "status", type : "string", defaultValue : "Ready" }); + +/*! + Should the statusbar be shown +*/ +qx.OO.addProperty({ name : "showStatusbar", type : "boolean", defaultValue : false }); + +/*! + Should the menubar be shown +*/ +qx.OO.addProperty({ name : "showMenubar", type : "boolean", defaultValue : false }); + +/*! + Should the location(bar) be shown +*/ +qx.OO.addProperty({ name : "showLocation", type : "boolean", defaultValue : false }); + +/*! + Should the toolbar be shown +*/ +qx.OO.addProperty({ name : "showToolbar", type : "boolean", defaultValue : false }); + +/*! + If the window is resizeable +*/ +qx.OO.addProperty({ name : "resizeable", type : "boolean", defaultValue : true }); + +/*! + If the window is able to scroll and has visible scrollbars if needed +*/ +qx.OO.addProperty({ name : "allowScrollbars", type : "boolean", defaultValue : true }); + + + +/* +--------------------------------------------------------------------------- + STATE +--------------------------------------------------------------------------- +*/ + +qx.Proto._loaded = false; + + + + +/* +--------------------------------------------------------------------------- + PROPERTY GROUPS +--------------------------------------------------------------------------- +*/ + +qx.OO.addPropertyGroup({ name : "location", members : [ "left", "top" ]}); +qx.OO.addPropertyGroup({ name : "dimension", members : [ "width", "height" ]}); + + + + +/* +--------------------------------------------------------------------------- + MODIFIERS +--------------------------------------------------------------------------- +*/ + +qx.Proto._modifyPosition = function(propValue, propOldValue, propName) +{ + /* + http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx + Changes to Functionality in Microsoft Windows XP Service Pack 2 + Part 5: Enhanced Browsing Security + URLACTION_FEATURE_WINDOW_RESTRICTIONS + Allow script-initiated windows without size or position constraints + Code: 2102 + */ + + if (!this.isClosed()) + { + try + { + this._window.moveTo(this.getLeft(), this.getTop()); + } + catch(ex) + { + this.error("Cross-Domain Scripting problem: Could not move window!", ex); + } + } + + return true; +} + +qx.Proto._modifyDimension = function(propValue, propOldValue, propName) +{ + /* + http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx + Changes to Functionality in Microsoft Windows XP Service Pack 2 + Part 5: Enhanced Browsing Security + URLACTION_FEATURE_WINDOW_RESTRICTIONS + Allow script-initiated windows without size or position constraints + Code: 2102 + */ + + if (!this.isClosed()) + { + try + { + this._window.resizeTo(this.getWidth(), this.getHeight()); + } + catch(ex) + { + this.error("Cross-Domain Scripting problem: Could not resize window!", ex); + } + } + + return true; +} + +qx.Proto._modifyName = function(propValue, propOldValue, propName) +{ + if (!this.isClosed()) { + this._window.name = propValue; + } + + return true; +} + +qx.Proto._modifyUrl = function(propValue, propOldValue, propName) +{ + // String hack needed for old compressor (compile.py) + if(!this.isClosed()) { + this._window.location.replace(qx.util.Validation.isValidString(propValue) ? propValue : ("javascript:/" + "/")); + } + + return true; +} + +qx.Proto._modifyOpen = function(propValue, propOldValue, propData) +{ + propValue ? this._open() : this._close(); + return true; +} + + + + + + +/* +--------------------------------------------------------------------------- + NAME +--------------------------------------------------------------------------- +*/ + +qx.Proto.getName = function() +{ + if (!this.isClosed()) + { + try + { + var vName = this._window.name; + } + catch(ex) + { + return this._valueName; + } + + if (vName == this._valueName) + { + return vName; + } + else + { + throw new Error("window name and name property are not identical"); + } + } + else + { + return this._valueName; + } +} + + + + + + +/* +--------------------------------------------------------------------------- + UTILITY +--------------------------------------------------------------------------- +*/ + +qx.Proto.isClosed = function() +{ + var vClosed = true; + + if (this._window) + { + try { + vClosed = this._window.closed; + } catch(ex) {} + } + + return vClosed; +} + +qx.Proto.open = function() { + this.setOpen(true); +} + +qx.Proto.close = function() { + this.setOpen(false); +} + +qx.Proto.isLoaded = function() { + return this._loaded; +} + + + + + + + +/* +--------------------------------------------------------------------------- + OPEN METHOD +--------------------------------------------------------------------------- +*/ + +qx.Proto._open = function() +{ + var vConf = []; + + + /* + ------------------------------------------------------------------------------ + PRE CONFIGURE WINDOW + ------------------------------------------------------------------------------ + */ + + if (qx.util.Validation.isValidNumber(this.getWidth())) + { + vConf.push("width"); + vConf.push("="); + vConf.push(this.getWidth()); + vConf.push(","); + } + + if (qx.util.Validation.isValidNumber(this.getHeight())) + { + vConf.push("height"); + vConf.push("="); + vConf.push(this.getHeight()); + vConf.push(","); + } + + if (qx.util.Validation.isValidNumber(this.getLeft())) + { + vConf.push("left"); + vConf.push("="); + vConf.push(this.getLeft()); + vConf.push(","); + } + + if (qx.util.Validation.isValidNumber(this.getTop())) + { + vConf.push("top"); + vConf.push("="); + vConf.push(this.getTop()); + vConf.push(","); + } + + + + vConf.push("dependent"); + vConf.push("="); + vConf.push(this.getDependent() ? "yes" : "no"); + vConf.push(","); + + vConf.push("resizable"); + vConf.push("="); + vConf.push(this.getResizeable() ? "yes" : "no"); + vConf.push(","); + + vConf.push("status"); + vConf.push("="); + vConf.push(this.getShowStatusbar() ? "yes" : "no"); + vConf.push(","); + + vConf.push("location"); + vConf.push("="); + vConf.push(this.getShowLocation() ? "yes" : "no"); + vConf.push(","); + + vConf.push("menubar"); + vConf.push("="); + vConf.push(this.getShowMenubar() ? "yes" : "no"); + vConf.push(","); + + vConf.push("toolbar"); + vConf.push("="); + vConf.push(this.getShowToolbar() ? "yes" : "no"); + vConf.push(","); + + vConf.push("scrollbars"); + vConf.push("="); + vConf.push(this.getAllowScrollbars() ? "yes" : "no"); + vConf.push(","); + + vConf.push("modal"); + vConf.push("="); + vConf.push(this.getModal() ? "yes" : "no"); + vConf.push(","); + + + + + + + /* + ------------------------------------------------------------------------------ + OPEN WINDOW + ------------------------------------------------------------------------------ + */ + + if (qx.util.Validation.isInvalidString(this.getName())) { + this.setName("qx_NativeWindow" + this.toHashCode()); + } + + this._window = window.open(this.getUrl(), this.getName(), vConf.join("")); + + if (this.isClosed()) + { + this.error("Window could not be opened. It seems, there is a popup blocker active!"); + } + else + { + // This try-catch is needed because of cross domain issues (access rights) + try + { + this._window._native = this; + this._window.onload = this._onload; + } + catch(ex) {} + + // start timer for close detection + this._timer.start(); + + // block original document + if (this.getModal()) { + qx.ui.core.ClientDocument.getInstance().block(this); + } + } +} + +qx.Proto._close = function() +{ + if (!this._window) { + return; + } + + // stop timer for close detection + this._timer.stop(); + + // release window again + if (this.getModal()){ + qx.ui.core.ClientDocument.getInstance().release(this); + } + + // finally close window + if (!this.isClosed()) { + this._window.close(); + } + + try + { + this._window._native = null; + this._window.onload = null; + } + catch(ex) {}; + + this._window = null; + this._loaded = false; + + this.createDispatchEvent("close"); +} + + + + + + +/* +--------------------------------------------------------------------------- + CENTER SUPPORT +--------------------------------------------------------------------------- +*/ + +qx.Proto.centerToScreen = function() { + return this._centerHelper((screen.width - this.getWidth()) / 2, (screen.height - this.getHeight()) / 2); +} + +qx.Proto.centerToScreenArea = function() { + return this._centerHelper((screen.availWidth - this.getWidth()) / 2, (screen.availHeight - this.getHeight()) / 2); +} + +qx.Proto.centerToOpener = function() { + return this._centerHelper(((qx.dom.Window.getInnerWidth(window) - this.getWidth()) / 2) + qx.dom.Location.getScreenBoxLeft(window.document.body), ((qx.dom.Window.getInnerHeight(window) - this.getHeight()) / 2) + qx.dom.Location.getScreenBoxTop(window.document.body)); +} + +qx.Proto._centerHelper = function(l, t) +{ + // set new values + this.setLeft(l); + this.setTop(t); + + // focus window if opened + if (!this.isClosed()) { + this.focus(); + } +} + + + + + + +/* +--------------------------------------------------------------------------- + FOCUS HANDLING +--------------------------------------------------------------------------- +*/ + +qx.Proto.focus = function() +{ + if (!this.isClosed()) { + this._window.focus(); + } +} + +qx.Proto.blur = function() +{ + if (!this.isClosed()) { + this._window.blur(); + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + EVENT HANDLING +--------------------------------------------------------------------------- +*/ + +qx.Proto._oninterval = function(e) +{ + if (this.isClosed()) { + this.setOpen(false); + } + else if (!this._loaded) + { + // This try-catch is needed because of cross domain issues (access rights) + try + { + if (this._window.document && this._window.document.readyState == "complete") + { + this._loaded = true; + this.createDispatchEvent("load"); + } + } + catch(ex) {}; + } +} + +qx.Proto._onload = function(e) +{ + var obj = this._native; + + if (!obj._loaded) + { + obj._loaded = true; + obj.createDispatchEvent("load"); + } +} + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + if (this.getDependent()) { + this.close(); + } + + if (this._timer) + { + this._timer.stop(); + this._timer = null; + } + + if (this._window) + { + try + { + this._window._native = null; + this._window.onload = null; + } + catch(ex) {}; + + this._window = null; + } + + return qx.core.Target.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Timer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Timer.js new file mode 100644 index 0000000000..674bbdb154 --- /dev/null +++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/client/Timer.js @@ -0,0 +1,183 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL 2.1: http://www.gnu.org/licenses/lgpl.html + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) + +************************************************************************ */ + +/** + * Global timer support. Simplifies javascript intervals for objects. + * + * @event interval {qx.event.type.Event} + */ +qx.OO.defineClass("qx.client.Timer", qx.core.Target, +function(vInterval) +{ + qx.core.Target.call(this); + + this.setEnabled(false); + + if (qx.util.Validation.isValidNumber(vInterval)) { + this.setInterval(vInterval); + } + + // Object wrapper to timer event + var o = this; + this.__oninterval = function() { o._oninterval(); } +}); + +qx.OO.addProperty({ name : "interval", type : "number", defaultValue : 1000 }); + +qx.Proto._intervalHandle = null; + + + +/* +--------------------------------------------------------------------------- + MODIFIER +--------------------------------------------------------------------------- +*/ + +qx.Proto._modifyEnabled = function(propValue, propOldValue, propData) +{ + if (propOldValue) + { + window.clearInterval(this._intervalHandle); + this._intervalHandle = null; + } + else if (propValue) + { + this._intervalHandle = window.setInterval(this.__oninterval, this.getInterval()); + } + + return true; +} + + + + +/* +--------------------------------------------------------------------------- + USER-ACCESS +--------------------------------------------------------------------------- +*/ + +qx.Proto.start = function() { + this.setEnabled(true); +} + +qx.Proto.startWith = function(vInterval) +{ + this.setInterval(vInterval); + this.start(); +} + +qx.Proto.stop = function() { + this.setEnabled(false); +} + +qx.Proto.restart = function() +{ + this.stop(); + this.start(); +} + +qx.Proto.restartWith = function(vInterval) +{ + this.stop(); + this.startWith(vInterval); +} + + + + +/* +--------------------------------------------------------------------------- + EVENT-MAPPER +--------------------------------------------------------------------------- +*/ + +qx.Proto._oninterval = function() +{ + if (this.getEnabled()) { + this.createDispatchEvent("interval"); + } +} + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if(this.getDisposed()) { + return; + } + + // Stop interval + this.stop(); + + // Clear handle + if (this._intervalHandler) + { + window.clearInterval(this._intervalHandle); + this._intervalHandler = null; + } + + // Clear object wrapper function + this.__oninterval = null; + + // Call qx.core.Target to do the other dispose work + return qx.core.Target.prototype.dispose.call(this); +} + + + + + +/* +--------------------------------------------------------------------------- + HELPER +--------------------------------------------------------------------------- +*/ + +qx.client.Timer.once = function(vFunction, vObject, vTimeout) +{ + // Create time instance + var vTimer = new qx.client.Timer(vTimeout); + + // Add event listener to interval + vTimer.addEventListener("interval", function(e) + { + vFunction.call(vObject, e); + vTimer.dispose(); + + vObject = null; + }, vObject); + + // Directly start timer + vTimer.start(); +} |