diff options
author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
---|---|---|
committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dojox/wire | |
parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
download | semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2 |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dojox/wire')
55 files changed, 5592 insertions, 0 deletions
diff --git a/includes/js/dojox/wire/CompositeWire.js b/includes/js/dojox/wire/CompositeWire.js new file mode 100644 index 0000000..7d1015d --- /dev/null +++ b/includes/js/dojox/wire/CompositeWire.js @@ -0,0 +1,103 @@ +if(!dojo._hasResource["dojox.wire.CompositeWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.CompositeWire"] = true; +dojo.provide("dojox.wire.CompositeWire"); + +dojo.require("dojox.wire._base"); +dojo.require("dojox.wire.Wire"); + +dojo.declare("dojox.wire.CompositeWire", dojox.wire.Wire, { + // summary: + // A Wire for composite values in object or array + // description: + // This class has multiple child Wires for object properties or array + // elements. + // When an object with Wires is specified to 'children' property, they + // are used to get or set an object with property values. + // When an array of Wiares is specified to 'children' property, they + // are used to get or set an array with element values. + + _wireClass: "dojox.wire.CompositeWire", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If object properties or array elements specified in 'children' + // property are not Wires, Wires are created from them as + // arguments, with 'parent' property set to this Wire instance. + // args: + // Arguments to initialize properties + // children: + // An object or array containing child Wires + this._initializeChildren(this.children); + }, + _getValue: function(/*Object||Array*/object){ + // summary: + // Return an object with property values or an array with element + // values + // description: + // This method calls getValue() method of the child Wires with + // 'object' argument and returns an object with the values as + // properties or an arary of the values as elements. + // object: + // A root object + // returns: + // An object or array with values + if(!object || !this.children){ + return object; //Object||Array + } + + var value = (dojo.isArray(this.children) ? [] : {}); // array or object + for(var c in this.children){ + value[c] = this.children[c].getValue(object); + } + return value;//Object||Array + }, + + _setValue: function(/*Object||Array*/object, /*Object||Array*/value){ + // summary: + // Set an object properties or an array elements to an object + // desription: + // This method calls setValues() method of the child Wires with + // a corresponding property or element in 'value' argument and + // 'object' argument. + // object: + // A root object + // value: + // An object or array with values to set + // returns: + // 'object' + if(!object || !this.children){ + return object; //Object||Array + } + + for(var c in this.children){ + this.children[c].setValue(value[c], object); + } + return object; //Object||Array + }, + + _initializeChildren: function(/*Object||Array*/children){ + // summary: + // Initialize child Wires + // description: + // If object properties or array elements specified in 'children' + // argument are not Wires, Wires are created from them as + // arguments, with 'parent' property set to this Wire instance. + // children: + // An object or array containing child Wires + if(!children){ + return; //undefined + } + + for(var c in children){ + var child = children[c]; + child.parent = this; + if(!dojox.wire.isWire(child)){ + children[c] = dojox.wire.create(child); + } + } + } +}); + +} diff --git a/includes/js/dojox/wire/DataWire.js b/includes/js/dojox/wire/DataWire.js new file mode 100644 index 0000000..ecb6223 --- /dev/null +++ b/includes/js/dojox/wire/DataWire.js @@ -0,0 +1,179 @@ +if(!dojo._hasResource["dojox.wire.DataWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.DataWire"] = true; +dojo.provide("dojox.wire.DataWire"); + +dojo.require("dojox.wire.Wire"); + +dojo.declare("dojox.wire.DataWire", dojox.wire.Wire, { + // summary: + // A Wire for item attributes of data stores + // description: + // This class accesses item attributes of data stores with a dotted + // notation of attribute names specified to 'attribute' property, + // using data APIs of a data store specified to 'dataStore' property. + // The root object for this class must be an item of the data store. + // Intermediate attribute names in the dotted notation specify + // attributes for child items, which are used for repeated calls to + // data APIs until reached to a descendant attribute. + // Attribute names may have an array index, such as "a[0]", to + // identify an array element of the attribute value. + + _wireClass: "dojox.wire.DataWire", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If 'dataStore' property is not specified, but 'parent' property + // is specified, 'dataStore' property is copied from the parent. + // args: + // Arguments to initialize properties + // dataStore: + // A data store + // attribute: + // A dotted notation to a descendant attribute + if(!this.dataStore && this.parent){ + this.dataStore = this.parent.dataStore; + } + }, + _getValue: function(/*Object*/object){ + // summary: + // Return an attribute value of an item + // description: + // This method uses a root item passed in 'object' argument and + // 'attribute' property to call getValue() method of + // 'dataStore'. + // If an attribute name have an array suffix ("[]"), getValues() + // method is called, instead. + // If an index is specified in the array suffix, an array element + // for the index is returned, instead of the array itself. + // object: + // A root item + // returns: + // A value found, otherwise 'undefined' + if(!object || !this.attribute || !this.dataStore){ + return object; //Object + } + + var value = object; + var list = this.attribute.split('.'); + for(var i in list){ + value = this._getAttributeValue(value, list[i]); + if(!value){ + return undefined; //undefined + } + } + return value; //anything + }, + + _setValue: function(/*Object*/object, /*anything*/value){ + // summary: + // Set an attribute value to an item + // description: + // This method uses a root item passed in 'object' argument and + // 'attribute' property to identify an item. + // Then, setValue() method of 'dataStore' is called with a leaf + // attribute name and 'value' argument. + // If an attribute name have an array suffix ("[]"), setValues() + // method is called, instead. + // If an index is specified in the array suffix, an array element + // for the index is set to 'value', instead of the array itself. + // object: + // A root item + // value: + // A value to set + // returns: + // 'object', or 'undefined' for invalid attribute + if(!object || !this.attribute || !this.dataStore){ + return object; //Object + } + + var item = object; + var list = this.attribute.split('.'); + var last = list.length - 1; + for(var i = 0; i < last; i++){ + item = this._getAttributeValue(item, list[i]); + if(!item){ + return undefined; //undefined + } + } + this._setAttributeValue(item, list[last], value); + return object; //Object + }, + + _getAttributeValue: function(/*Object*/item, /*String*/attribute){ + // summary: + // Return an attribute value of an item + // description: + // This method uses an item passed in 'item' argument and + // 'attribute' argument to call getValue() method of 'dataStore'. + // If an attribute name have an array suffix ("[]"), getValues() + // method is called, instead. + // If an index is specified in the array suffix, an array element + // for the index is returned, instead of the array itself. + // item: + // An item + // attribute + // An attribute name + // returns: + // A value found, otherwise 'undefined' + var value = undefined; + var i1 = attribute.indexOf('['); + if(i1 >= 0){ + var i2 = attribute.indexOf(']'); + var index = attribute.substring(i1 + 1, i2); + attribute = attribute.substring(0, i1); + var array = this.dataStore.getValues(item, attribute); + if(array){ + if(!index){ // return array for "attribute[]" + value = array; + }else{ + value = array[index]; + } + } + }else{ + value = this.dataStore.getValue(item, attribute); + } + return value; //anything + }, + + _setAttributeValue: function(/*Object*/item, /*String*/attribute, /*anything*/value){ + // summary: + // Set an attribute value to an item + // description: + // This method uses an item passed in 'item' argument and + // 'attribute' argument to call setValue() method of 'dataStore' + // with 'value' argument. + // If an attribute name have an array suffix ("[]"), setValues() + // method is called, instead. + // If an index is specified in the array suffix, an array element + // for the index is set to 'value', instead of the array itself. + // item: + // An item + // attribute: + // An attribute name + // value: + // A value to set + var i1 = attribute.indexOf('['); + if(i1 >= 0){ + var i2 = attribute.indexOf(']'); + var index = attribute.substring(i1 + 1, i2); + attribute = attribute.substring(0, i1); + var array = null; + if(!index){ // replace whole array for "attribute[]" + array = value; + }else{ + array = this.dataStore.getValues(item, attribute); + if(!array){ + array = []; + } + array[index] = value; + } + this.dataStore.setValues(item, attribute, array); + }else{ + this.dataStore.setValue(item, attribute, value); + } + } +}); + +} diff --git a/includes/js/dojox/wire/README b/includes/js/dojox/wire/README new file mode 100644 index 0000000..8f3f831 --- /dev/null +++ b/includes/js/dojox/wire/README @@ -0,0 +1,53 @@ +------------------------------------------------------------------------------- +DojoX Wire +------------------------------------------------------------------------------- +Version 1.0 +Release date: 05/29/2007 +------------------------------------------------------------------------------- +Project state: stable +------------------------------------------------------------------------------- +Project authors + Jared Jurkiewicz (jared.jurkiewicz@gmail.com) +------------------------------------------------------------------------------- +Project description + +The DojoX Wire project is a set of functions that build a generic data binding +and service invocation library to simplify how data values across a wide +variety of widget and non-widget JavaScript constructs are accessed, updated, +and passed to and from services. It also provides a set of widgets +within the dojox.wire.ml package to allow for declarative data binding +definitions in addition to the programmatic APIs. + +In essense, this project is an API to provide a simplified way of doing MVC +patterns in the client. + +------------------------------------------------------------------------------- +Dependencies: + +DojoX Wire has dependencies on core dojo, the dijit widget system (for classes +in the dojox.wire.ml package), dojox.data, and the D.O.H. unit test framework. +------------------------------------------------------------------------------- +Documentation: + +See the Dojo API tool (http://dojotoolkit.org/api) +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/wire.js +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/wire/* + +Install into the following directory structure: +/dojox/wire/ + +...which should be at the same level as your Dojo checkout. + +It should look like: +/dojox/wire.js +/dojox/wire/* + +Require in dojox.wire for all baseline functions (dojox.wire.connect, +dojox.wire.register, etc). For specific Wire classes, +require in the appropriate dojox.wire.<Class>. +------------------------------------------------------------------------------- + diff --git a/includes/js/dojox/wire/TableAdapter.js b/includes/js/dojox/wire/TableAdapter.js new file mode 100644 index 0000000..16a5280 --- /dev/null +++ b/includes/js/dojox/wire/TableAdapter.js @@ -0,0 +1,88 @@ +if(!dojo._hasResource["dojox.wire.TableAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.TableAdapter"] = true; +dojo.provide("dojox.wire.TableAdapter"); + +dojo.require("dojox.wire.CompositeWire"); + +dojo.declare("dojox.wire.TableAdapter", dojox.wire.CompositeWire, { + // summary: + // A composite Wire for table rows + // description: + // This class has multiple child Wires for object properties or array + // elements of a table row. + // The root object for this class must be an array. + // When an object with Wires is specified to 'columns' property, they + // are used to get a row object with property values. + // When an array of Wires is specified to 'columns' property, they + // are used to get a row array with element values. + // The row values are returned in an array. + // This class only supports getValue(), but not setValue(). + + _wireClass: "dojox.wire.TableAdapter", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If object properties or array elements specified in 'columns' + // property are not Wires, Wires are created from them as + // arguments, with 'parent' property set to this Wire instance. + // args: + // Arguments to initialize properties + // columns: + // An object or array containing child Wires for column values + this._initializeChildren(this.columns); + }, + + _getValue: function(/*Array*/object){ + // summary: + // Return an array of table row value (object or array) + // description: + // This method iterates over an array specified to 'object' + // argument and calls getValue() method of the child Wires with + // each element of the array to get a row object or array. + // Finally, an array with the row objects or arrays are retuned. + // object: + // A root array + // returns: + // An array of table row value + if(!object || !this.columns){ + return object; //Array + } + + var array = object; + if(!dojo.isArray(array)){ + array = [array]; + } + + var rows = []; + for(var i in array){ + var row = this._getRow(array[i]); + rows.push(row); + } + return rows; //Array + }, + + _setValue: function(/*Array*/object, /*Array*/value){ + // summary: + // Not supported + throw new Error("Unsupported API: " + this._wireClass + "._setValue"); + }, + + _getRow: function(/*Object||Array*/object){ + // summary: + // Return an array or object for a table row + // description: + // This method calls getValue() method of the child Wires to + // create a row object or array. + // returns: + // An array or object for a table row + var row = (dojo.isArray(this.columns) ? [] : {}); // array or object + for(var c in this.columns){ + row[c] = this.columns[c].getValue(object); + } + return row; //Array||Object + } +}); + +} diff --git a/includes/js/dojox/wire/TextAdapter.js b/includes/js/dojox/wire/TextAdapter.js new file mode 100644 index 0000000..36e7f1d --- /dev/null +++ b/includes/js/dojox/wire/TextAdapter.js @@ -0,0 +1,88 @@ +if(!dojo._hasResource["dojox.wire.TextAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.TextAdapter"] = true; +dojo.provide("dojox.wire.TextAdapter"); + +dojo.require("dojox.wire.CompositeWire"); + +dojo.declare("dojox.wire.TextAdapter", dojox.wire.CompositeWire, { + // summary: + // A composite Wire for a concatenated text + // description: + // This class has multiple child Wires for text segment values. + // Wires in 'segments' property are used to get text segments and + // values are concatenated with an optional delimiter string specified + // to 'delimiter' property. + + _wireClass: "dojox.wire.TextAdapter", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If array elements specified in 'segments' are not Wires, Wires + // are created from them as arguments, with 'parent' property set + // to this Wire instance. + // args: + // Arguments to initialize properties + // segments: + // An array containing child Wires for text segment values + // delimiter: + // A delimiter string + this._initializeChildren(this.segments); + if(!this.delimiter){ + this.delimiter = ""; + } + }, + + _getValue: function(/*Object||Array*/object){ + // summary: + // Return a concatenated text + // description: + // This method calls getValue() method of the child Wires wuth + // 'object' argument and concatenate the values with 'delimiter' + // property to return. + // arg: + // A root object + // returns: + // A concatinated text + if(!object || !this.segments){ + return object; //Object||Array + } + + var text = ""; + for(var i in this.segments){ + var segment = this.segments[i].getValue(object); + text = this._addSegment(text, segment); + } + return text; //String + }, + + _setValue: function(/*Object||Array*/object, /*String*/value){ + // summary: + // Not supported + throw new Error("Unsupported API: " + this._wireClass + "._setValue"); + }, + + _addSegment: function(/*String*/text, /*String*/segment){ + // summary: + // Return a concatenated text + // description: + // This method add a text segment specified to 'segment' argument + // to a base text specified to 'text', with 'delimiter' property. + // text: + // A base text + // segment: + // A text segment to add + // returns: + // A concatinated text + if(!segment){ + return text; //String + }else if(!text){ + return segment; //String + }else{ + return text + this.delimiter + segment; //String + } + } +}); + +} diff --git a/includes/js/dojox/wire/TreeAdapter.js b/includes/js/dojox/wire/TreeAdapter.js new file mode 100644 index 0000000..b9b16bf --- /dev/null +++ b/includes/js/dojox/wire/TreeAdapter.js @@ -0,0 +1,188 @@ +if(!dojo._hasResource["dojox.wire.TreeAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.TreeAdapter"] = true; +dojo.provide("dojox.wire.TreeAdapter"); + +dojo.require("dojox.wire.CompositeWire"); + +dojo.declare("dojox.wire.TreeAdapter", dojox.wire.CompositeWire, { + // summary: + // A composite Wire for tree nodes + // description: + // This class has multiple child Wires for tree nodes, their title and + // child nodes. + // The root object for this class must be an array. + // 'node' Wires in 'nodes' property is used to identify an object + // representing a node. + // 'title' Wires in 'nodes' property is used to get the title string + // of a node. + // 'children' Wires in 'nodes' property is used to iterate over child + // node objects. + // The node values are returned in an array as follows: + // [ + // {title: title1, + // children: [ + // {title: title2, + // child: ...}, + // {title: title3, + // child: ...}, + // ... + // ]}, + // ... + // ] + // This class only supports getValue(), but not setValue(). + + _wireClass: "dojox.wire.TreeAdapter", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If object properties ('node', 'title' and 'children') of array + // elements specified in 'nodes' property are not Wires, Wires are + // created from them as arguments, with 'parent' property set to + // this Wire instance. + // args: + // Arguments to initialize properties + // nodes: + // An array containing objects for child Wires for node values + this._initializeChildren(this.nodes); + }, + _getValue: function(/*Array*/object){ + // summary: + // Return an array of tree node values + // description: + // This method iterates over an array specified to 'object' + // argument and calls getValue() method of 'node' Wires with each + // element of the array to get object(s) that represetns nodes. + // (If 'node' Wires are omitted, the array element is used for + // further processing.) + // Then, getValue() method of 'title' Wires are called to get + // title strings for nodes. + // (If 'title' Wires are omitted, the objects representing nodes + // are used as title strings.) + // And if an array of objects with 'node' and 'title' Wires is + // specified to 'children', it is used to gather child nodes and + // their title strings in the same way recursively. + // Finally, an array of the top-level node objects are retuned. + // object: + // A root array + // returns: + // An array of tree node values + if(!object || !this.nodes){ + return object; //Array + } + + var array = object; + if(!dojo.isArray(array)){ + array = [array]; + } + + var nodes = []; + for(var i in array){ + for(var i2 in this.nodes){ + nodes = nodes.concat(this._getNodes(array[i], this.nodes[i2])); + } + } + return nodes; //Array + }, + + _setValue: function(/*Array*/object, /*Array*/value){ + // summary: + // Not supported + throw new Error("Unsupported API: " + this._wireClass + "._setValue"); + }, + + _initializeChildren: function(/*Array*/children){ + // summary: + // Initialize child Wires + // description: + // If 'node' or 'title' properties of array elements specified in + // 'children' argument are not Wires, Wires are created from them + // as arguments, with 'parent' property set to this Wire instance. + // If an array element has 'children' property, this method is + // called recursively with it. + // children: + // An array of objects containing child Wires + if(!children){ + return; //undefined + } + + for(var i in children){ + var child = children[i]; + if(child.node){ + child.node.parent = this; + if(!dojox.wire.isWire(child.node)){ + child.node = dojox.wire.create(child.node); + } + } + if(child.title){ + child.title.parent = this; + if(!dojox.wire.isWire(child.title)){ + child.title = dojox.wire.create(child.title); + } + } + if(child.children){ + this._initializeChildren(child.children); + } + } + }, + + _getNodes: function(/*Object*/object, /*Object*/child){ + // summary: + // Return an array of tree node values + // description: + // This method calls getValue() method of 'node' Wires with + // 'object' argument to get object(s) that represents nodes. + // (If 'node' Wires are omitted, 'object' is used for further + // processing.) + // Then, getValue() method of 'title' Wires are called to get + // title strings for nodes. + // (If 'title' Wires are omitted, the objects representing nodes + // are used as title strings.) + // And if an array of objects with 'node' and 'title' Wires is + // specified to 'children', it is used to gather child nodes and + // their title strings in the same way recursively. + // Finally, an array of node objects are returned. + // object: + // An object + // child: + // An object with child Wires + // returns: + var array = null; + if(child.node){ + array = child.node.getValue(object); + if(!array){ + return []; + } + if(!dojo.isArray(array)){ + array = [array]; + } + }else{ + array = [object]; + } + + var nodes = []; + for(var i in array){ + object = array[i]; + var node = {}; + if(child.title){ + node.title = child.title.getValue(object); + }else{ + node.title = object; + } + if(child.children){ + var children = []; + for(var i2 in child.children){ + children = children.concat(this._getNodes(object, child.children[i2])); + } + if(children.length > 0){ + node.children = children; + } + } + nodes.push(node); + } + return nodes; //Array + } +}); + +} diff --git a/includes/js/dojox/wire/Wire.js b/includes/js/dojox/wire/Wire.js new file mode 100644 index 0000000..f9dde1d --- /dev/null +++ b/includes/js/dojox/wire/Wire.js @@ -0,0 +1,336 @@ +if(!dojo._hasResource["dojox.wire.Wire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.Wire"] = true; +dojo.provide("dojox.wire.Wire"); + +dojo.require("dojox.wire._base"); + +dojo.declare("dojox.wire.Wire", null, { + // summary: + // A default and base Wire to access an object property + // description: + // This class accesses a property of an object with a dotted notation + // specified to 'property' property, such as "a.b.c", which identifies + // a descendant property, "object.a.b.c". + // Property names in the dotted notation may have an array index, such + // as "a[0]", to identify an array element, literally, "object.a[0]". + // When a notation start with an array index, such as "[0].a", it + // specifies an array element of the root object (array), + // "object[0].a". + // This class also serves as a base class for other Wire classes, + // preparing a root object and converting a return value, so that + // sub-classes just can implement _getValue() and _setValue() called + // from getValue() and setValue() implemented by this calss. + + _wireClass: "dojox.wire.Wire", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // If 'converter' property is specified and is a string for + // a converter class, an instanceof the converter class is + // created. + // args: + // Arguments to initialize properties + // object: + // A root object (or another Wire to access a root object) + // property: + // A dotted notation to a descendant property + // type: + // A type of the return value (for the source Wire) + // converter: + // A converter object (or class name) to convert the return + // value (for the source Wire) + dojo.mixin(this, args); + + if(this.converter){ + if(dojo.isString(this.converter)){ + //First check the object tree for it. Might be defined variable + //name/global function (like a jsId, or just a function name). + var convertObject = dojo.getObject(this.converter); + if (dojo.isFunction(convertObject)){ + //We need to see if this is a pure function or an object constructor... + try{ + var testObj = new convertObject(); + if(testObj && !dojo.isFunction(testObj["convert"])){ + //Looks like a 'pure' function... + this.converter = {convert: convertObject}; + }else{ + this.converter = testObj; + } + }catch(e){ + //Do if this fails. + } + }else if(dojo.isObject(convertObject)){ + //It's an object, like a jsId ... see if it has a convert function + if(dojo.isFunction(convertObject["convert"])){ + this.converter = convertObject; + } + } + + //No object with that name (Converter is still a string), + //then look for a class that needs to be dynamically loaded... + if (dojo.isString(this.converter)) { + var converterClass = dojox.wire._getClass(this.converter); + if(converterClass){ + this.converter = new converterClass(); + }else{ + this.converter = undefined; + } + } + }else if(dojo.isFunction(this.converter)){ + this.converter = {convert: this.converter}; + } + } + }, + + getValue: function(/*Object||Array*/defaultObject){ + // summary: + // Return a value of an object + // description: + // This method first determins a root object as follows: + // 1. If 'object' property specified, + // 1.1 If 'object' is a Wire, its getValue() method is called to + // obtain a root object. + // 1.2 Otherwise, use 'object' as a root object. + // 2. Otherwise, use 'defaultObject' argument. + // 3. If 'property' is specified, it is used to get a property + // value. + // Then, if a sub-class implements _getValue() method, it is + // called with the root object to get the return value. + // Otherwise, the root object (typically, a property valye) is + // used for the return value. + // Finally, if 'type' property is specified, the return value is + // converted to the specified primitive type ("string", "number", + // "boolean" and "array"). + // If 'converter' property is specified, its convert() method is + // called to convert the value. + // defaultObject: + // A default root object + // returns: + // A value found + var object = undefined; + if(dojox.wire.isWire(this.object)){ + object = this.object.getValue(defaultObject); + }else{ + object = (this.object || defaultObject); + } + + if(this.property){ + var list = this.property.split('.'); + for(var i in list){ + if(!object){ + return object; //anything (null, undefined, etc) + } + object = this._getPropertyValue(object, list[i]); + } + } + + var value = undefined; + if(this._getValue){ + value = this._getValue(object); + }else{ + value = object; + } + + if(value){ + if(this.type){ + if(this.type == "string"){ + value = value.toString(); + }else if(this.type == "number"){ + value = parseInt(value); + }else if(this.type == "boolean"){ + value = (value != "false"); + }else if(this.type == "array"){ + if(!dojo.isArray(value)){ + value = [value]; + } + } + } + if(this.converter && this.converter.convert){ + value = this.converter.convert(value, this); // optional "this" context + } + } + return value; //anything + }, + + setValue: function(/*anything*/value, /*Object||Array*/defaultObject){ + // summary: + // Set a value to an object + // description: + // This method first determins a root object as follows: + // 1. If 'object' property specified, + // 1.1 If 'object' is a Wire, its getValue() method is called to + // obtain a root object. + // 1.2 Otherwise, use 'object' as a root object. + // 2. Otherwise, use 'defaultObject' argument. + // 3. If 'property' is specified, it is used to get a property + // value. + // Then, if a sub-class implements _setValue() method, it is + // called with the root object and 'value' argument to set + // the value. + // Otherwise, 'value' is set to a property specified with + // 'property' property. + // If the root object is undefined and 'object' property is a Wire + // and a new object is created and returned by _setValue() it is + // set through 'object' (setValue() method). + // value: + // A value to set + // defaultObject: + // A default root object + var object = undefined; + if(dojox.wire.isWire(this.object)){ + object = this.object.getValue(defaultObject); + }else{ + object = (this.object || defaultObject); + } + + var property = undefined; + if(this.property){ + if(!object){ + if(dojox.wire.isWire(this.object)){ + object = {}; + this.object.setValue(object, defaultObject); + }else{ + throw new Error(this._wireClass + ".setValue(): invalid object"); + } + } + var list = this.property.split('.'); + var last = list.length - 1; + for(var i = 0; i < last; i++){ + var p = list[i]; + var o = this._getPropertyValue(object, p); + if(!o){ + o = {}; + this._setPropertyValue(object, p, o); + } + object = o; + } + property = list[last]; + } + + if(this._setValue){ + if(property){ + var o = this._getPropertyValue(object, property); + if(!o){ + o = {}; + this._setPropertyValue(object, property, o); + } + object = o; + } + var newObject = this._setValue(object, value); + if(!object && newObject){ + if(dojox.wire.isWire(this.object)){ + this.object.setValue(newObject, defaultObject); + }else{ + throw new Error(this._wireClass + ".setValue(): invalid object"); + } + } + }else{ + if(property){ + this._setPropertyValue(object, property, value); + }else{ + if(dojox.wire.isWire(this.object)){ + this.object.setValue(value, defaultObject); + }else{ + throw new Error(this._wireClass + ".setValue(): invalid property"); + } + } + } + }, + + _getPropertyValue: function(/*Object||Array*/object, /*String*/property){ + // summary: + // Return a property value of an object + // description: + // A value for 'property' of 'object' is returned. + // If 'property' ends with an array index, it is used to indentify + // an element of an array property. + // If 'object' implements getPropertyValue(), it is called with + // 'property' to obtain the property value. + // If 'object' implements a getter for the property, it is called + // to obtain the property value. + // object: + // A default root object + // property: + // A property name + // returns: + // A value found, otherwise 'undefined' + var value = undefined; + var i1 = property.indexOf('['); + if(i1 >= 0){ + var i2 = property.indexOf(']'); + var index = property.substring(i1 + 1, i2); + var array = null; + if(i1 === 0){ // object is array + array = object; + }else{ + property = property.substring(0, i1); + array = this._getPropertyValue(object, property); + if(array && !dojo.isArray(array)){ + array = [array]; + } + } + if(array){ + value = array[index]; + } + }else if(object.getPropertyValue){ + value = object.getPropertyValue(property); + }else{ + var getter = "get" + property.charAt(0).toUpperCase() + property.substring(1); + if(object[getter]){ + value = object[getter](); + }else{ + value = object[property]; + } + } + return value; //anything + }, + + _setPropertyValue: function(/*Object||Array*/object, /*String*/property, /*anything*/value){ + // summary: + // Set a property value to an object + // description: + // 'value' is set to 'property' of 'object'. + // If 'property' ends with an array index, it is used to indentify + // an element of an array property to set the value. + // If 'object' implements setPropertyValue(), it is called with + // 'property' and 'value' to set the property value. + // If 'object' implements a setter for the property, it is called + // with 'value' to set the property value. + // object: + // An object + // property: + // A property name + // value: + // A value to set + var i1 = property.indexOf('['); + if(i1 >= 0){ + var i2 = property.indexOf(']'); + var index = property.substring(i1 + 1, i2); + var array = null; + if(i1 === 0){ // object is array + array = object; + }else{ + property = property.substring(0, i1); + array = this._getPropertyValue(object, property); + if(!array){ + array = []; + this._setPropertyValue(object, property, array); + } + } + array[index] = value; + }else if(object.setPropertyValue){ + object.setPropertyValue(property, value); + }else{ + var setter = "set" + property.charAt(0).toUpperCase() + property.substring(1); + if(object[setter]){ + object[setter](value); + }else{ + object[property] = value; + } + } + } +}); + +} diff --git a/includes/js/dojox/wire/XmlWire.js b/includes/js/dojox/wire/XmlWire.js new file mode 100644 index 0000000..dc5666f --- /dev/null +++ b/includes/js/dojox/wire/XmlWire.js @@ -0,0 +1,244 @@ +if(!dojo._hasResource["dojox.wire.XmlWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.XmlWire"] = true; +dojo.provide("dojox.wire.XmlWire"); + +dojo.require("dojox.data.dom"); +dojo.require("dojox.wire.Wire"); + +dojo.declare("dojox.wire.XmlWire", dojox.wire.Wire, { + // summary: + // A Wire for XML nodes or values (element, attribute and text) + // description: + // This class accesses XML nodes or value with a simplified XPath + // specified to 'path' property. + // The root object for this class must be an DOM document or element + // node. + // "@name" accesses to an attribute value of an element and "text()" + // accesses to a text value of an element. + // The hierarchy of the elements from the root node can be specified + // with slash-separated list, such as "a/b/@c", which specifies + // the value of an attribute named "c" of an element named "b" as + // a child of another element named "a" of a child of the root node. + + _wireClass: "dojox.wire.XmlWire", + + constructor: function(/*Object*/args){ + // summary: + // Initialize properties + // description: + // 'args' is just mixed in with no further processing. + // args: + // Arguments to initialize properties + // path: + // A simplified XPath to an attribute, a text or elements + }, + _getValue: function(/*Node*/object){ + // summary: + // Return an attribute value, a text value or an array of elements + // description: + // This method first uses a root node passed in 'object' argument + // and 'path' property to identify an attribute, a text or + // elements. + // If 'path' starts with a slash (absolute), the first path + // segment is ignored assuming it point to the root node. + // (That is, "/a/b/@c" and "b/@c" against a root node access + // the same attribute value, assuming the root node is an element + // with a tag name, "a".) + // object: + // A root node + // returns: + // A value found, otherwise 'undefined' + if(!object || !this.path){ + return object; //Node + } + + var node = object; + var path = this.path; + if(path.charAt(0) == '/'){ // absolute + // skip the first expression (supposed to select the top node) + var i = path.indexOf('/', 1); + path = path.substring(i + 1); + } + var list = path.split('/'); + var last = list.length - 1; + for(var i = 0; i < last; i++){ + node = this._getChildNode(node, list[i]); + if(!node){ + return undefined; //undefined + } + } + var value = this._getNodeValue(node, list[last]); + return value; //String||Array + }, + + _setValue: function(/*Node*/object, /*String*/value){ + // summary: + // Set an attribute value or a child text value to an element + // description: + // This method first uses a root node passed in 'object' argument + // and 'path' property to identify an attribute, a text or + // elements. + // If an intermediate element does not exist, it creates + // an element of the tag name in the 'path' segment as a child + // node of the current node. + // Finally, 'value' argument is set to an attribute or a text + // (a child node) of the leaf element. + // object: + // A root node + // value: + // A value to set + if(!this.path){ + return object; //Node + } + + var node = object; + var doc = this._getDocument(node); + var path = this.path; + if(path.charAt(0) == '/'){ // absolute + var i = path.indexOf('/', 1); + if(!node){ + var name = path.substring(1, i); + node = doc.createElement(name); + object = node; // to be returned as a new object + } + // skip the first expression (supposed to select the top node) + path = path.substring(i + 1); + }else{ + if(!node){ + return undefined; //undefined + } + } + + var list = path.split('/'); + var last = list.length - 1; + for(var i = 0; i < last; i++){ + var child = this._getChildNode(node, list[i]); + if(!child){ + child = doc.createElement(list[i]); + node.appendChild(child); + } + node = child; + } + this._setNodeValue(node, list[last], value); + return object; //Node + }, + + _getNodeValue: function(/*Node*/node, /*String*/exp){ + // summary: + // Return an attribute value, a text value or an array of elements + // description: + // If 'exp' starts with '@', an attribute value of the specified + // attribute is returned. + // If 'exp' is "text()", a child text value is returned. + // Otherwise, an array of child elements, the tag name of which + // match 'exp', is returned. + // node: + // A node + // exp: + // An expression for attribute, text or elements + // returns: + // A value found, otherwise 'undefined' + var value = undefined; + if(exp.charAt(0) == '@'){ + var attribute = exp.substring(1); + value = node.getAttribute(attribute); + }else if(exp == "text()"){ + var text = node.firstChild; + if(text){ + value = text.nodeValue; + } + }else{ // assume elements + value = []; + for(var i = 0; i < node.childNodes.length; i++){ + var child = node.childNodes[i]; + if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == exp){ + value.push(child); + } + } + } + return value; //String||Array + }, + + _setNodeValue: function(/*Node*/node, /*String*/exp, /*String*/value){ + // summary: + // Set an attribute value or a child text value to an element + // description: + // If 'exp' starts with '@', 'value' is set to the specified + // attribute. + // If 'exp' is "text()", 'value' is set to a child text. + // node: + // A node + // exp: + // An expression for attribute or text + // value: + // A value to set + if(exp.charAt(0) == '@'){ + var attribute = exp.substring(1); + if(value){ + node.setAttribute(attribute, value); + }else{ + node.removeAttribute(attribute); + } + }else if(exp == "text()"){ + while(node.firstChild){ + node.removeChild(node.firstChild); + } + if(value){ + var text = this._getDocument(node).createTextNode(value); + node.appendChild(text); + } + } + // else not supported + }, + + _getChildNode: function(/*Node*/node, /*String*/name){ + // summary: + // Return a child node + // description: + // A child element of the tag name specified with 'name' is + // returned. + // If 'name' ends with an array index, it is used to pick up + // the corresponding element from multiple child elements. + // node: + // A parent node + // name: + // A tag name + // returns: + // A child node + var index = 1; + var i1 = name.indexOf('['); + if(i1 >= 0){ + var i2 = name.indexOf(']'); + index = name.substring(i1 + 1, i2); + name = name.substring(0, i1); + } + var count = 1; + for(var i = 0; i < node.childNodes.length; i++){ + var child = node.childNodes[i]; + if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == name){ + if(count == index){ + return child; //Node + } + count++; + } + } + return null; //null + }, + + _getDocument: function(/*Node*/node){ + // summary: + // Return a DOM document + // description: + // If 'node' is specified, a DOM document of the node is returned. + // Otherwise, a DOM document is created. + // returns: + // A DOM document + if(node){ + return (node.nodeType == 9 /* DOCUMENT_NODE */ ? node : node.ownerDocument); //Document + }else{ + return dojox.data.dom.createDocument(); //Document + } + } +}); + +} diff --git a/includes/js/dojox/wire/_base.js b/includes/js/dojox/wire/_base.js new file mode 100644 index 0000000..cc632c1 --- /dev/null +++ b/includes/js/dojox/wire/_base.js @@ -0,0 +1,195 @@ +if(!dojo._hasResource["dojox.wire._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire._base"] = true; +dojo.provide("dojox.wire._base"); + +dojox.wire._defaultWireClass = "dojox.wire.Wire"; + +dojox.wire._wireClasses = { + "attribute": "dojox.wire.DataWire", + "path": "dojox.wire.XmlWire", + "children": "dojox.wire.CompositeWire", + "columns": "dojox.wire.TableAdapter", + "nodes": "dojox.wire.TreeAdapter", + "segments": "dojox.wire.TextAdapter" +}; + +dojox.wire.register = function(/*Function||String*/wireClass, /*String*/key){ + // summary: + // Register a Wire class + // desription: + // The specified Wire class or a class name is registered with + // a key property of arguments to create a Wire + // wireClass: + // A class or full qualified class name + // key: + // A key property of arguments to create a Wire + if(!wireClass || !key){ + return; //undefined + } + if(dojox.wire._wireClasses[key]){ // key already in use + return; //undefined + } + dojox.wire._wireClasses[key] = wireClass; +}; + +dojox.wire._getClass = function(/*String*/name){ + // summary: + // Returns a class + // description: + // The class is loaded by dojo.require() and returned + // by dojo.getObject(). + // name: + // A class name + // returns: + // A class + dojo["require"](name); // use dojo["require"] instead of dojo.require to avoid a build problem + return dojo.getObject(name); //Function +}; + +dojox.wire.create = function(/*Object*/args){ + // summary: + // Create a Wire from arguments + // description: + // If 'args' specifies 'wireClass', it is used as a class or full + // qualified class name to create a Wire with 'args' as arguments. + // Otherwise, a Wire class is determined by other proeprties of 'args' + // checking if 'args' specifies a key property for a Wire class. + // If no key property found, the default Wire class is used. + // args: + // Arguments to create a Wire + // returns: + // A Wire + if(!args){ + args = {}; + } + var wireClass = args.wireClass; + if(wireClass){ + if(dojo.isString(wireClass)){ + wireClass = dojox.wire._getClass(wireClass); + } + }else{ + for(var key in args){ + if(!args[key]){ + continue; + } + wireClass = dojox.wire._wireClasses[key]; + if(wireClass){ + if(dojo.isString(wireClass)){ + wireClass = dojox.wire._getClass(wireClass); + dojox.wire._wireClasses[key] = wireClass; + } + break; + } + } + } + if(!wireClass){ + if(dojo.isString(dojox.wire._defaultWireClass)){ + dojox.wire._defaultWireClass = dojox.wire._getClass(dojox.wire._defaultWireClass); + } + wireClass = dojox.wire._defaultWireClass; + } + return new wireClass(args); //Object +}; + +dojox.wire.isWire = function(/*Object*/wire){ + // summary: + // Check if an object is a Wire + // description: + // If the specified object is a Wire, true is returned. + // Otherwise, false is returned. + // wire: + // An object to check + // returns: + // True if the object is a Wire, otherwise false + return (wire && wire._wireClass); //Boolean +}; + +dojox.wire.transfer = function(/*Wire||Object*/source, /*Wire||Object*/target, /*Object?*/defaultObject, /*Object?*/defaultTargetObject){ + // summary: + // Transfer a source value to a target value + // description: + // If 'source' and/or 'target' are not Wires, Wires are created with + // them as arguments. + // A value is got through the source Wire and set through the target + // Wire. + // 'defaultObject' is passed to Wires as a default root object. + // If 'defaultTargetObject' is specified, it is passed to the target + // Wire as a default root object, instead of 'defaultObject'. + // source: + // A Wire or arguments to create a Wire for a source value + // target: + // A Wire or arguments to create a Wire for a target value + // defaultObject: + // defaultTargetObject; + // Optional default root objects passed to Wires + if(!source || !target){ + return; //undefined + } + if(!dojox.wire.isWire(source)){ + source = dojox.wire.create(source); + } + if(!dojox.wire.isWire(target)){ + target = dojox.wire.create(target); + } + + var value = source.getValue(defaultObject); + target.setValue(value, (defaultTargetObject || defaultObject)); +}; + +dojox.wire.connect = function(/*Object*/trigger, /*Wire||Object*/source, /*Wire||Object*/target){ + // summary: + // Transfer a source value to a target value on a trigger event or + // topic + // description: + // If 'trigger' specifies 'topic', the topic is subscribed to transer + // a value on the topic. + // Otherwise, the event specified to 'event' of 'trigger' is listened + // to transfer a value. + // On the specified event or topic, transfer() is called with + // 'source', 'target' and the arguments of the event or topic (as + // default root objects). + // trigger: + // An event or topic to trigger a transfer + // source: + // A Wire or arguments to create a Wire for a source value + // target: + // A Wire or arguments to create a Wire for a target value + // returns: + // A connection handle for disconnect() + if(!trigger || !source || !target){ + return; //undefined + } + + var connection = {topic: trigger.topic}; + if(trigger.topic){ + connection.handle = dojo.subscribe(trigger.topic, function(){ + dojox.wire.transfer(source, target, arguments); + }); + }else if(trigger.event){ + connection.handle = dojo.connect(trigger.scope, trigger.event, function(){ + dojox.wire.transfer(source, target, arguments); + }); + } + return connection; //Object +}; + +dojox.wire.disconnect = function(/*Object*/connection){ + // summary: + // Remove a connection or subscription for transfer + // description: + // If 'handle' has 'topic', the topic is unsubscribed. + // Otherwise, the listener to an event is removed. + // connection: + // A connection handle returned by connect() + if(!connection || !connection.handle){ + return; //undefined + } + + if(connection.topic){ + dojo.unsubscribe(connection.handle); + }else{ + dojo.disconnect(connection.handle); + } +}; + +} diff --git a/includes/js/dojox/wire/demos/TableContainer.css b/includes/js/dojox/wire/demos/TableContainer.css new file mode 100644 index 0000000..fded51f --- /dev/null +++ b/includes/js/dojox/wire/demos/TableContainer.css @@ -0,0 +1,25 @@ +.tablecontainer { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; + border-collapse: separate; +} +.tablecontainer th { + text-align: left; +} +.tablecontainer tr { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} +.tablecontainer tr td { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} +.alternate { + background-color: #EEEEEE; +} diff --git a/includes/js/dojox/wire/demos/TableContainer.css.commented.css b/includes/js/dojox/wire/demos/TableContainer.css.commented.css new file mode 100644 index 0000000..4ee2706 --- /dev/null +++ b/includes/js/dojox/wire/demos/TableContainer.css.commented.css @@ -0,0 +1,30 @@ +.tablecontainer { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; + border-collapse: separate; +} + +.tablecontainer th { + text-align: left; +} + +.tablecontainer tr { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} + +.tablecontainer tr td { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} + +.alternate { + background-color: #EEEEEE; +} + diff --git a/includes/js/dojox/wire/demos/TableContainer.js b/includes/js/dojox/wire/demos/TableContainer.js new file mode 100644 index 0000000..fd4ad73 --- /dev/null +++ b/includes/js/dojox/wire/demos/TableContainer.js @@ -0,0 +1,68 @@ +if(!dojo._hasResource["dojox.wire.demos.TableContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.demos.TableContainer"] = true; +dojo.provide("dojox.wire.demos.TableContainer"); + +dojo.require("dojo.parser"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); + +dojo.declare("dojox.wire.demos.TableContainer", [ dijit._Widget, dijit._Templated, dijit._Container ], { + // summary: + // Extremely simple 'widget' that is a table generator with an addRow function that takes an array + // as the row to add, where each entry is a cell in the row. This demo widget is for use with the + // wire demos. + + templateString: "<table class='tablecontainer'><tbody dojoAttachPoint='tableContainer'></tbody></table>", + rowCount: 0, + headers: "", + addRow: function(array){ + // summary: + // Function to add in a new row from the elements in the array map to cells in the row. + // array: + // Array of row values to add. + try{ + var row = document.createElement("tr"); + if((this.rowCount%2) === 0){ + dojo.addClass(row, "alternate"); + } + this.rowCount++; + for(var i in array){ + var cell = document.createElement("td"); + var text = document.createTextNode(array[i]); + cell.appendChild(text); + row.appendChild(cell); + + } + this.tableContainer.appendChild(row); + }catch(e){ console.debug(e); } + }, + + clearTable: function(){ + // summary: + // Function to clear all the current rows in the table, except for the header. + + //Always leave the first row, which is the table header. + while(this.tableContainer.firstChild.nextSibling){ + this.tableContainer.removeChild(this.tableContainer.firstChild.nextSibling); + } + this.rowCount = 0; + }, + + postCreate: function(){ + // summary: + // Widget lifecycle function to handle generation of the header elements in the table. + var headers = this.headers.split(","); + var tr = document.createElement("tr"); + for(i in headers){ + + var header = headers[i]; + var th = document.createElement("th"); + var text = document.createTextNode(header); + th.appendChild(text); + tr.appendChild(th); + } + this.tableContainer.appendChild(tr); + } +}); + +} diff --git a/includes/js/dojox/wire/demos/WidgetRepeater.js b/includes/js/dojox/wire/demos/WidgetRepeater.js new file mode 100644 index 0000000..ad1b8b0 --- /dev/null +++ b/includes/js/dojox/wire/demos/WidgetRepeater.js @@ -0,0 +1,33 @@ +if(!dojo._hasResource["dojox.wire.demos.WidgetRepeater"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.demos.WidgetRepeater"] = true; +dojo.provide("dojox.wire.demos.WidgetRepeater") + +dojo.require("dojo.parser"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.require("dijit._Container"); + +dojo.declare("dojox.wire.demos.WidgetRepeater", [ dijit._Widget, dijit._Templated, dijit._Container ], { + // summary: + // Simple widget that does generation of widgets repetatively, based on calls to + // the createNew function and contains them as child widgets. + templateString: "<div class='WidgetRepeater' dojoAttachPoint='repeaterNode'></div>", + widget: null, + repeater: null, + createNew: function(obj){ + // summary: + // Function to handle the creation of a new widget and appending it into the widget tree. + // obj: + // The parameters to pass to the widget. + try{ + if(dojo.isString(this.widget)){ + dojo.require(this.widget); + this.widget = dojo.getObject(this.widget); + } + this.addChild(new this.widget(obj)); + this.repeaterNode.appendChild(document.createElement("br")); + }catch(e){ console.debug(e); } + } +}); + +} diff --git a/includes/js/dojox/wire/demos/markup/countries.json b/includes/js/dojox/wire/demos/markup/countries.json new file mode 100644 index 0000000..ad3a07a --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/countries.json @@ -0,0 +1,43 @@ +{ identifier: 'name', + items: [ + { name:'Africa', type:'continent', + children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] }, + { name:'Egypt', type:'country' }, + { name:'Kenya', type:'country', + children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] }, + { name:'Nairobi', type:'city' }, + { name:'Mombasa', type:'city' }, + { name:'Sudan', type:'country', + children:{_reference:'Khartoum'} }, + { name:'Khartoum', type:'city' }, + { name:'Asia', type:'continent', + children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] }, + { name:'China', type:'country' }, + { name:'India', type:'country' }, + { name:'Russia', type:'country' }, + { name:'Mongolia', type:'country' }, + { name:'Australia', type:'continent', population:'21 million', + children:{_reference:'Commonwealth of Australia'}}, + { name:'Commonwealth of Australia', type:'country', population:'21 million'}, + { name:'Europe', type:'continent', + children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] }, + { name:'Germany', type:'country' }, + { name:'France', type:'country' }, + { name:'Spain', type:'country' }, + { name:'Italy', type:'country' }, + { name:'North America', type:'continent', + children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] }, + { name:'Mexico', type:'country', population:'108 million', area:'1,972,550 sq km', + children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] }, + { name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'}, + { name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' }, + { name:'Canada', type:'country', population:'33 million', area:'9,984,670 sq km', + children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] }, + { name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'}, + { name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' }, + { name:'United States of America', type:'country' }, + { name:'South America', type:'continent', + children:[{_reference:'Brazil'}, {_reference:'Argentina'}] }, + { name:'Brazil', type:'country', population:'186 million' }, + { name:'Argentina', type:'country', population:'40 million' } +]} diff --git a/includes/js/dojox/wire/demos/markup/demo_ActionChaining.html b/includes/js/dojox/wire/demos/markup/demo_ActionChaining.html new file mode 100644 index 0000000..596d6ec --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_ActionChaining.html @@ -0,0 +1,108 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of events. Specifically, it shows how you can chain actions together + in a sequence. In this case the setting of a value on one textbox triggers a + copy over to another textbox. That in turn triggers yet another copy to another + text box. +--> +<html> +<head> + <title>Sample Action Chaining</title> + <style type="text/css"> + + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "../TableContainer.css"; + + .splitView { + width: 90%; + height: 90%; + border: 1px solid #bfbfbf; + border-collapse: separate; + } + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + dojo.require("dojox.wire.ml.Data"); + dojo.require("dijit.form.TextBox"); + </script> +</head> + +<body class="tundra"> + + <!-- Layout --> + <font size="3"><b>Demo of Chaining Actions:</b></font><br/><br/> + This demo shows how you can chain actions together to fire in a sequence. + Such as the completion of setting one value on a widget triggers the setting of another value on the widget + <br/> + <br/> + <table> + <tr> + <td> + <div dojoType="dijit.form.TextBox" id="inputField" value="" size="50"></div> + </td> + </tr> + <tr> + <td> + <div dojoType="dijit.form.TextBox" id="targetField1" value="" disabled="true" size="50"></div> + </td> + </tr> + <tr> + <td> + <div dojoType="dijit.form.TextBox" id="targetField2" value="" disabled="true" size="50"></div> + </td> + </tr> + </table> + + + <!-------------------------------- Using dojox.wire, declaratively wire up the widgets. ---------------------------> + + <!-- + This is an example of using the declarative data value definition. + These are effectively declarative variables to act as placeholders + for data values. + --> + <div dojoType="dojox.wire.ml.Data" + id="data"> + <div dojoType="dojox.wire.ml.DataProperty" + name="tempData" + value=""> + </div> + </div> + + <!-- + Whenever a key is entered into the textbox, copy the value somewhere, then invoke a method on another widget, in this case + on just another text box. + --> + <div dojoType="dojox.wire.ml.Action" + id="action1" + trigger="inputField" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.Invocation" object="inputField" method="getValue" result="data.tempData"></div> + <div dojoType="dojox.wire.ml.Invocation" id="targetCopy" object="targetField1" method="setValue" parameters="data.tempData"></div> + </div> + + <!-- + Whenever the primary cloning invocation completes, invoke a secondary cloning action. + --> + <div dojoType="dojox.wire.ml.Action" + id="action2" + trigger="targetCopy" + triggerEvent="onComplete"> + <!-- + Note that this uses the basic 'property' form of copying the property over and setting it. The Wire + code supports both getX and setX functions of setting a property as well as direct access. It first looks + for the getX/setX functions and if present, uses them. If missing, it will just do direct access. Because + of the standard getValue/setValue API of dijit form widgets, these transfers work really well and are very compact. + --> + <div dojoType="dojox.wire.ml.Transfer" source="targetField1.value" target="targetField2.value"></div> + </div> +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_ActionWiring.html b/includes/js/dojox/wire/demos/markup/demo_ActionWiring.html new file mode 100644 index 0000000..995b67f --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_ActionWiring.html @@ -0,0 +1,142 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of events on one item to trigger event on other widgets. It also shows + how you can use the Transfer object to morph data values from one format to + another. In this specific case, it maps the values from a dojo.data Datastore + item into values stored in a JavaScript Array, which is the format required for + the addRow method of the demonstration TableContainer. + + Note that this demo expects dojo, digit, and dojox to all be peers in the same directory + in order for it to execute. +--> +<html> +<head> + <title>Sample declarative data binding</title> + <style type="text/css"> + + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "../TableContainer.css"; + + .splitView { + width: 90%; + height: 90%; + border: 1px solid #bfbfbf; + border-collapse: separate; + } + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + + dojo.require("dijit.layout.SplitContainer"); + dojo.require("dijit.layout.LayoutContainer"); + dojo.require("dijit.layout.ContentPane"); + dojo.require("dijit.form.Button"); + dojo.require("dijit.form.TextBox"); + + dojo.require("dojo.data.ItemFileReadStore"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.demos.TableContainer"); + + //Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem function + // to trap on for triggering other events. + dataHolder = { + //Simple object definition to get all items and sort it by the attribute 'type'. + request: {query: {name: "*"}, onItem: function(item, req){}, sort: [{attribute: "type"}]}, + //Spot to store off data values as they're generated by the declarative binding. + result: null + }; + + </script> +</head> + +<body class="tundra"> + + <!-- The following is the basic layout. A split container with a button and a text field. Data will be displayed on the right. --> + <div dojoType="dijit.layout.SplitContainer" + orientation="horizontal" + sizerWidth="7" + activeSizing="true" + class="splitView"> + <div dojoType="dijit.layout.ContentPane" sizeMin="50" sizeShare="50"> + <font size="3"><b>Demo Searcher (Searches on Attribute 'name'):</b></font><br/><br/> + <b>Usage:</b><br/> + Enter the name you want to search the store for. Wildcards * (multiple character), and ? (single character), are allowed. + <br/> + <br/> + <table style="width: 90%;"> + <tr> + <td align="left"> + <div dojoType="dijit.form.Button" jsId="searchButton">Search Datastore</div> + </td> + <td align="right"> + <div dojoType="dijit.form.TextBox" jsId="inputField" value="*"></div> + </td> + </tr> + </table> + </div> + <div dojoType="dijit.layout.ContentPane" sizeMin="50" sizeShare="50"> + <div class="dataTable" dojoType="dojox.wire.demos.TableContainer" jsId="dataTable" headers="Name,Location Type"></div> + </div> + </div> + + + <!-------------------------------- Using dojox.wire, declaratively wire up the widgets. ---------------------------> + + <!-- The store that is queried in this demo --> + <div dojoType="dojo.data.ItemFileReadStore" + jsId="DataStore1" + url="countries.json"> + </div> + + <!-- + When the search button is clicked, clear existing rows from table, + Then invoke the fetch to repopulate the table. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="searchButton" + triggerEvent="onClick"> + <div dojoType="dojox.wire.ml.Invocation" object="dataTable" method="clearTable"></div> + <div dojoType="dojox.wire.ml.Invocation" object="DataStore1" method="fetch" parameters="dataHolder.request"></div> + </div> + + <!-- + Link existing of the text box to transfering the search string to the query param. + We are wiring the value of TextBox value of the widget to the name property of our request + object. The copy of values to the search should occur on each keyup event (each keypress) + --> + <div dojoType="dojox.wire.ml.Transfer" + trigger="inputField" triggerEvent="onkeyup" + source="inputField.textbox.value" + target="dataHolder.request.query.name"> + </div> + + <!-- + On the call of the onItem function of 'dataHolder', trigger a binding/mapping of the + item's attribute 'name' and 'type' attributes to specific columns in an array. Note here that since + sourceStore is set, it treats the arguments as items from that store and accesses the attributes + appropriately. In this case 'name' becomes array entry 0, type, array entry 1, and so on. + + Then take the result of the data mapping and pass it into the invoke of the addRow function on the + TableContainer widget. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="dataHolder.request" triggerEvent="onItem"> + <div dojoType="dojox.wire.ml.Transfer" + source="arguments[0]" sourceStore="DataStore1" + target="dataHolder.result"> + <div dojoType="dojox.wire.ml.ColumnWire" attribute="name"></div> + <div dojoType="dojox.wire.ml.ColumnWire" attribute="type"></div> + </div> + <div dojoType="dojox.wire.ml.Invocation" + object="dataTable" method="addRow" parameters='dataHolder.result'> + </div> + </div> +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_BasicChildWire.html b/includes/js/dojox/wire/demos/markup/demo_BasicChildWire.html new file mode 100644 index 0000000..f5973e7 --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_BasicChildWire.html @@ -0,0 +1,78 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of properties/attributes of some object to the properties/attributes of + another object. It specifically uses the Child (Composite) wire type to perform + the mapping. + + Note that this demo expects dojo, digit, and dojox to all be peers in the same directory + in order for it to execute. +--> +<html> + <head> + <title>Sample Composite (Child) Wire usage.</title> + <style type="text/css"> + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dijit.form.Button"); + dojo.require("dojo.data.ItemFileReadStore"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.demos.WidgetRepeater"); + + dataHolder = { + request: {onItem: function(item){}}, + result: null + }; + </script> + </head> + <body class="tundra"> + <!-- + On load of the page, invoke the fetch method of the object 'DataStore1', + get its parameters from the JS object 'sample.request + --> + <div dojoType="dojox.wire.ml.Invocation" + triggerEvent="onLoad" + object="DataStore1" method="fetch" parameters="dataHolder.request"> + </div> + + <!-- + The store that is queried in this demo + --> + <div dojoType="dojo.data.ItemFileReadStore" + jsId="DataStore1" + url="countries.json"> + </div> + + <!-- + Simple container widget for creating a 'list' of some set of widgets + As defined by the widget type it contains. + --> + <div dojoType="dojox.wire.demos.WidgetRepeater" + widget="dijit.form.Button" jsId="r1"> + </div> + + <!-- + On the call of the onItem function of 'sample', trigger a binding/mapping of the + item's attribute 'name' to the target object property: dataHolder.result.caption + Then invoke the WidgetRepeater (r1)'s createNew method, using the parameters from + dataHolder.result. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="dataHolder.request" triggerEvent="onItem"> + <div dojoType="dojox.wire.ml.Transfer" + source="arguments[0]" sourceStore="DataStore1" + target="dataHolder.result"> + <div dojoType="dojox.wire.ml.ChildWire" name="label" attribute="name"></div> + </div> + <div dojoType="dojox.wire.ml.Invocation" object="r1" method="createNew" parameters='dataHolder.result'></div> + </div> + </body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_BasicColumnWiring.html b/includes/js/dojox/wire/demos/markup/demo_BasicColumnWiring.html new file mode 100644 index 0000000..48c327e --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_BasicColumnWiring.html @@ -0,0 +1,90 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of events on one item to trigger event on other items. It also shows + how you can use the Transfer object to morph data values from one format to + another. In this specific case, it maps the values from a dojo.data Datastore + item into values stored in a JavaScript Array, which is the format required for + the addRow method of the demonstration TableContainer. + + Note that this demo expects dojo, digit, and dojox to all be peers in the same directory + in order for it to execute. +--> +<html> +<head> + <title>Sample Declarative Data Binding using ColumnWire</title> + <style type="text/css"> + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "../TableContainer.css"; + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + + dojo.require("dijit._Widget"); + dojo.require("dijit._Templated"); + dojo.require("dojo.data.ItemFileReadStore"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.demos.TableContainer"); + + //Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem function + // to trap on for triggering other events. + dataHolder = { + //Simple object definition to get all items and sort it by the attribute 'type'. + request: {onItem: function(item){}, sort: [{attribute: "type"}]}, + //Spot to store off data values as they're generated by the declarative binding. + result: null + }; + </script> +</head> + +<body class="tundra"> + <!-- + The store that is queried in this demo + --> + <div dojoType="dojo.data.ItemFileReadStore" + jsId="DataStore1" + url="countries.json"> + </div> + + <!-- + On load of the page, invoke the fetch method of the object 'DataStore1', + get its parameters from the JS object 'sample.request + --> + <div dojoType="dojox.wire.ml.Invocation" + triggerEvent="onLoad" + object="DataStore1" method="fetch" parameters="dataHolder.request"></div> + + <!-- + Simple container widget for creating a 'table from rows defined by an array + --> + <div dojoType="dojox.wire.demos.TableContainer" jsId="r1" headers="Name,Location Type"></div> + + <!-- + On the call of the onItem function of 'dataHolder', trigger a binding/mapping of the + item's attribute 'name' and 'type' attributes to specific columns in an array. Note here that since + sourceStore is set, it treats the arguments as items from that store and accesses the attributes + appropriately. In this case 'name' becomes array entry 0, type, array entry 1, and so on. + + Then take the result of the data mapping and pass it into the invoke of the addRow function on the + TableContainer widget. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="dataHolder.request" triggerEvent="onItem"> + <div dojoType="dojox.wire.ml.Transfer" + source="arguments[0]" sourceStore="DataStore1" + target="dataHolder.result"> + <div dojoType="dojox.wire.ml.ColumnWire" attribute="name"></div> + <div dojoType="dojox.wire.ml.ColumnWire" attribute="type"></div> + </div> + <div dojoType="dojox.wire.ml.Invocation" + object="r1" method="addRow" parameters='dataHolder.result'> + </div> + </div> +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_ConditionalActions.html b/includes/js/dojox/wire/demos/markup/demo_ConditionalActions.html new file mode 100644 index 0000000..ea0ca64 --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_ConditionalActions.html @@ -0,0 +1,221 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of events. Specifically, it shows how you can wire actions to set values + across to other widgets, but only if certain conditions are met. +--> +<html> +<head> + <title>Conditional Actions Demo</title> + <style type="text/css"> + + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "../TableContainer.css"; + + .splitView { + width: 90%; + height: 90%; + border: 1px solid #bfbfbf; + border-collapse: separate; + } + + b { + float: left; + } + + .rJustified { + float: right; + } + + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dojo.data.ItemFileReadStore"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + dojo.require("dojox.wire.ml.Data"); + dojo.require("dijit.form.TextBox"); + dojo.require("dijit.form.CheckBox"); + dojo.require("dijit.form.ComboBox"); + </script> +</head> + +<body class="tundra"> + + <!-- Layout --> + <font size="3"><b>Demo of Conditional Actions:</b></font><br/><br/> + This demo shows how you can use actions to read and set widget values, as well as have actions only occur if + if certain conditions are met, such as cloning values as they are typed from the billing address over to the + shipping address if the 'Use Same Address' checkbox is checked true. + <br/> + <br/> + <div dojoType="dojo.data.ItemFileReadStore" url="states.json" jsId="statesStore"></div> + <table width="100%"> + <tr> + <td colspan="2" align="center"> + Use Same Address: <div dojoType="dijit.form.CheckBox" id="useSameAddress" checked="true"></div> + </td> + </tr> + <tr> + <td> + <b>Billing Address</b> + </td> + <td> + <b>Shipping Address</b> + </td> + </tr> + + <tr> + <td> + <b>Name:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingName" name="billingname" value="" size="50"></div> + </td> + <td> + <b>Name:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingName" name="shippingname" value="" disabled="true" size="50"></div> + </td> + </tr> + <tr> + <td> + <b>Address 1:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingAddress1" name="billingaddress1" value="" size="50"></div> + </td> + <td> + <b>Address 1:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingAddress1" name="shippingaddress1" value="" disabled="true" size="50"></div> + </td> + </tr> + <tr> + <td> + <b>Address 2:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingAddress2" name="billingaddress2" value="" size="50"></div> + </td> + <td> + <b>Address 2:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingAddress2" name="shippingaddress2" value="" disabled="true" size="50"></div> + </td> + </tr> + <tr> + <td> + <b>City:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingCity" name="billingcity" value="" size="50"></div> + </td> + <td> + <b>City:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingCity" name="shippingcity" value="" disabled="true" size="50"></div> + </td> + </tr> + <tr> + <td> + <b>State:</b> <div class="rJustified" dojoType="dijit.form.ComboBox" searchAttr="name" id="BillingState" name="billingstate" value="" store="statesStore" size="46"></div> + </td> + <td> + <b>State:</b> <div class="rJustified" dojoType="dijit.form.ComboBox" searchAttr="name" id="ShippingState" name="shippingstate" value="" store="statesStore" disabled="true" size="46"></div> + </td> + </tr> + <tr> + <td> + <b>Zip code:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingZip" name="billingzip" value="" size="50"></div> + </td> + <td> + <b>Zip code:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingZip" name="shippingzip" value="" disabled="true" size="50"></div> + </td> + </tr> + </table> + + + <!-------------------------------- Using dojox.wire, declaratively wire up the widgets. ---------------------------> + + <!-- + This is a simple data map so that the attributes we support modifying on ComboBox, TextField, etc, are lookupable. + since steAttribute(attr, value), replaced the single attribute setDisabled + --> + <div dojoType="dojox.wire.ml.Data" + id="attributesMap"> + <div dojoType="dojox.wire.ml.DataProperty" + name="disabled" + value="disabled"></div> + </div> + + + <!-- + Enable/disable the Right hand side of the shipping address view based on the checkbox events. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="useSameAddress" + triggerEvent="setChecked"> + <!-- + Trigger a setting of the Shipping fields' input state based on the state of the checkbox. + --> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingName" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingAddress1" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingAddress2" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingCity" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingState" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + <div dojoType="dojox.wire.ml.Invocation" object="ShippingZip" method="setAttribute" parameters="attributesMap.disabled, arguments[0]"></div> + </div> + + <!-- + Clone the values of form fields while typing based on the setting of the checkbox. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="BillingName" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingName.value" target="ShippingName.value"></div> + </div> + <div dojoType="dojox.wire.ml.Action" + trigger="BillingAddress1" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingAddress1.value" target="ShippingAddress1.value"></div> + </div> + <div dojoType="dojox.wire.ml.Action" + trigger="BillingAddress2" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingAddress2.value" target="ShippingAddress2.value"></div> + </div> + <div dojoType="dojox.wire.ml.Action" + trigger="BillingCity" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingCity.value" target="ShippingCity.value"></div> + </div> + <div dojoType="dojox.wire.ml.Action" + trigger="BillingState" + triggerEvent="onChange"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingState.value" target="ShippingState.value"></div> + </div> + + <div dojoType="dojox.wire.ml.Action" + trigger="BillingZip" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingZip.value" target="ShippingZip.value"></div> + </div> + + + <!-- + Clone the values of form fields from billing over to shipping over if the + useSameAddress checkbox is set back to true. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="useSameAddress" + triggerEvent="setChecked"> + <div dojoType="dojox.wire.ml.ActionFilter" required="arguments[0]" requiredValue="true" type="boolean"></div> + + <!-- + Note that this uses the basic 'property' form of copying the property over and setting it. The Wire + code supports both getX and setX functions of setting a property as well as direct access. It first looks + for the getX/setX functions and if present, uses them. If missing, it will just do direct access. Because + of the standard getValue/setValue API of dijit form widgets, transfers work well and are compact. + --> + <div dojoType="dojox.wire.ml.Transfer" source="BillingName.value" target="ShippingName.value"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingAddress1.value" target="ShippingAddress1.value"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingAddress2.value" target="ShippingAddress2.value"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingCity.value" target="ShippingCity.value"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingState.value" target="ShippingState.value"></div> + <div dojoType="dojox.wire.ml.Transfer" source="BillingZip.value" target="ShippingZip.value"></div> + </div> + +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_FlickrStoreWire.html b/includes/js/dojox/wire/demos/markup/demo_FlickrStoreWire.html new file mode 100644 index 0000000..54068a9 --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_FlickrStoreWire.html @@ -0,0 +1,281 @@ +<!-- + This file is a demo of the FlickrStore, a simple wrapper to the public feed service + of Flickr. This just does very basic queries against Flickr and loads the results + into a list viewing widget. +--> +<html> +<head> + <title>Demo of FlickrStore</title> + <style type="text/css"> + + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "./flickrDemo.css"; + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dijit.form.TextBox"); + dojo.require("dijit.form.Button"); + dojo.require("dijit.form.ComboBox"); + dojo.require("dijit.form.NumberSpinner"); + dojo.require("dojox.data.FlickrStore"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.Transfer"); + dojo.require("dojox.wire.ml.Data"); + dojo.require("dojox.wire"); + dojo.require("dojox.data.demos.widgets.FlickrViewList"); + dojo.require("dojox.data.demos.widgets.FlickrView"); + + //Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem and onComplete function + // to trap on for triggering other events. + var dataHolder = { + //Simple stub datastore request + request: {query: {}, onItem: function(item, req){}, onComplete: function(items, req){}}, + + //Spot to store off data values as they're generated by the declarative binding. + result: null + }; + + //Function to convert the input from a widget into a comma separated list. + //that is the format of the store parameter. + var tagsInputConverter = function(tags){ + if(tags && tags !== ""){ + var tagsArray = tags.split(" "); + tags = ""; + for(var i = 0; i < tagsArray.length; i++){ + tags = tags + tagsArray[i]; + if(i < (tagsArray.length - 1)){ + tags += "," + } + } + } + return tags + } + + </script> +</head> + +<body class="tundra"> + <h1> + DEMO: FlickrStore Search + </h1> + <hr> + <h3> + Description: + </h3> + <p> + This simple demo shows how services, such as Flickr, can be wrapped by the datastore API. In this demo, you can search public + Flickr images through a simple FlickrStore by specifying a series of tags (separated by spaces) to search on. The results + will be displayed below the search box. This demo is the same as the example demo provided in dojox/data/demos/demo_FlickrStore.html, + except that all the interactions are implemented via Wire instead of a script that runs at dojo.addOnLoad(). + </p> + <p> + For fun, search on the 3dny tag! + </p> + + <blockquote> + + <!-- + Layout. + --> + <table> + <tbody> + <tr> + <td> + <b>Status:</b> + </td> + <td> + <div dojoType="dijit.form.TextBox" size="50" id="status" jsId="statusWidget" disabled="true"></div> + </td> + </tr> + <tr> + <td> + <b>ID:</b> + </td> + <td> + <div dojoType="dijit.form.TextBox" size="50" id="userid" jsId="idWidget"></div> + </td> + </tr> + <tr> + <td> + <b>Tags:</b> + </td> + <td> + <div dojoType="dijit.form.TextBox" size="50" id="tags" jsId="tagsWidget" value="3dny"></div> + </td> + </tr> + <tr> + <td> + <b>Tagmode:</b> + </td> + <td> + <select id="tagmode" + jsId="tagmodeWidget" + dojoType="dijit.form.ComboBox" + autocomplete="false" + value="any" + > + <option>any</option> + <option>all</option> + </select> + </td> + </tr> + <tr> + <td> + <b>Number of Pictures:</b> + </td> + <td> + <div + id="count" + jsId="countWidget" + dojoType="dijit.form.NumberSpinner" + value="20" + constraints="{min:1,max:20,places:0}" + ></div> + </td> + </tr> + <tr> + <td> + </td> + <td> + <div dojoType="dijit.form.Button" label="Search" id="searchButton" jsId="searchButtonWidget"></div> + </td> + </tr> + </tbody> + </table> + </blockquote> + <!-- + The store instance used by this demo. + --> + <div dojoType="dojox.data.FlickrStore" jsId="flickrStore" label="title"></div> + <div dojoType="dojox.data.demos.widgets.FlickrViewList" id="flickrViews" jsId="flickrViewsWidget"></div> + + <!-------------------------------- Using dojox.wire, declaratively wire up the widgets. ---------------------------> + + + <!-- + This is an example of using the declarative data value definition. + These are effectively declarative variables to act as placeholders + for data values. + --> + <div dojoType="dojox.wire.ml.Data" + id="messageData" + jsId="messageData"> + <div dojoType="dojox.wire.ml.DataProperty" + name="processingStart" + value="PROCESSING REQUEST"> + </div> + <div dojoType="dojox.wire.ml.DataProperty" + name="processingDone" + value="PROCESSING COMPLETE"> + </div> + </div> + + + <!-- + When the search button is clicked, do the following in order: + 1.) Map the widget values over to the request properties. + 2.) Clear existing rows from table, + 3.) Set the status to processing + 4.) Invoke the fetch to repopulate the table. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="searchButtonWidget" + triggerEvent="onClick"> + + <!-- + Read in the values from the widgets and bind them to the appropriate data locations + For basic properties, you could use transfer directly, but since the text boxes are + designed to be accessed through getValue/setValue, it's better to do these as + Invocations on widget methods. + --> + <div dojoType="dojox.wire.ml.Invocation" + object="idWidget" + method="getValue" + result="dataHolder.request.query.id"> + </div> + + + <!-- + For the tags, we need to get the value and then perform a conversion on the result + This is done by doing an invoke, then a transfer through a converter. + --> + <div dojoType="dojox.wire.ml.Invocation" + object="tagsWidget" + method="getValue" + result="dataHolder.request.query.tags"> + </div> + <div dojoType="dojox.wire.ml.Transfer" + source="dataHolder.request.query.tags" + target="dataHolder.request.query.tags" + converter="tagsInputConverter"> + </div> + + <div dojoType="dojox.wire.ml.Invocation" + object="tagmodeWidget" + method="getValue" + result="dataHolder.request.query.tagmode"> + </div> + + <div dojoType="dojox.wire.ml.Invocation" + object="countWidget" + method="getValue" + result="dataHolder.request.count"> + </div> + + + <!-- Now invoke the actions in order. --> + <div dojoType="dojox.wire.ml.Invocation" object="flickrViewsWidget" method="clearList"></div> + <div dojoType="dojox.wire.ml.Invocation" object="statusWidget" method="setValue" parameters="messageData.processingStart"></div> + <div dojoType="dojox.wire.ml.Invocation" object="flickrStore" method="fetch" parameters="dataHolder.request"></div> + </div> + + <!-- + When the fetch processing finishes (onComplete is called), then set status to complete. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="dataHolder.request" + triggerEvent="onComplete"> + <div dojoType="dojox.wire.ml.Invocation" object="statusWidget" method="setValue" parameters="messageData.processingDone"></div> + </div> + + + <!-- + On the call of the onItem function of 'dataHolder', trigger a binding/mapping of the + item's attributes to the requires parameters that are passed into addView. In this case + FlikrItemAttribute -> viewItemParam + title title + imageUrlSmall iconUrl + imageUrl imageUrl + author author + + Then take the result of the data mapping and pass it into the invoke of the addView function on the + FlickerViews widget. + --> + <div dojoType="dojox.wire.ml.Action" + trigger="dataHolder.request" triggerEvent="onItem"> + <div dojoType="dojox.wire.ml.Transfer" + source="arguments[0]" sourceStore="flickrStore" + target="dataHolder.result"> + <!-- + Map the attributes of the items to the property name defined + in the wire on the object in the target + --> + <div dojoType="dojox.wire.ml.ChildWire" + name="title" attribute="title"></div> + <div dojoType="dojox.wire.ml.ChildWire" + name="imageUrl" attribute="imageUrl"></div> + <div dojoType="dojox.wire.ml.ChildWire" + name="iconUrl" attribute="imageUrlSmall"></div> + <div dojoType="dojox.wire.ml.ChildWire" + name="author" attribute="author"></div> + </div> + <div dojoType="dojox.wire.ml.Invocation" + object="flickrViewsWidget" method="addView" parameters='dataHolder.result'> + </div> + </div> +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/demo_TopicWiring.html b/includes/js/dojox/wire/demos/markup/demo_TopicWiring.html new file mode 100644 index 0000000..e091e8b --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/demo_TopicWiring.html @@ -0,0 +1,78 @@ +<!-- + This file demonstrates how the dojox.wire code can be used to do declarative + wiring of events. Specifically, it shows how you can publish and subscribe + to topics. In this case the setting of a value on one textbox triggers a + publish of that value to a topic. Another invoke is wired to fire when + values are published to that topic which is then displayed in another + textbox. +--> +<html> +<head> + <title>Sample Topic Wiring</title> + <style type="text/css"> + + @import "../../../../dijit/themes/tundra/tundra.css"; + @import "../../../../dojo/resources/dojo.css"; + @import "../../../../dijit/tests/css/dijitTests.css"; + @import "../TableContainer.css"; + + .splitView { + width: 90%; + height: 90%; + border: 1px solid #bfbfbf; + border-collapse: separate; + } + </style> + + <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> + <script type="text/javascript"> + dojo.require("dojo.parser"); + dojo.require("dojox.wire"); + dojo.require("dojox.wire.ml.Invocation"); + dojo.require("dojox.wire.ml.DataStore"); + dojo.require("dojox.wire.ml.Transfer"); + dojo.require("dojox.wire.ml.Data"); + + dojo.require("dijit.form.TextBox"); + </script> +</head> + +<body class="tundra"> + + <!-- Layout --> + <font size="3"><b>Demo of Topic Wiring</b></font><br/><br/> + This demo shows how you can wire events to publish to a topic as well as recieve topic events + <br/> + <br/> + <table> + <tr> + <td> + <div dojoType="dijit.form.TextBox" jsId="inputField" value="" size="50"></div> + </td> + </tr> + <tr> + <td> + <div dojoType="dijit.form.TextBox" jsId="targetField1" value="" disabled="true" size="50"></div> + </td> + </tr> + </table> + + + <!-------------------------------- Using dojox.wire, declaratively wire up the widgets. ---------------------------> + + <!-- + Whenever a key is entered into the textbox, publish the value of it to a topic. + --> + <div dojoType="dojox.wire.ml.Action" + id="action1" + trigger="inputField" + triggerEvent="onkeyup"> + <div dojoType="dojox.wire.ml.Invocation" topic="sampleTopic" parameters="inputField.value"></div> + </div> + + <!-- + Whenever a value is published to a topic, set it as the value of the textbox by calling the setValue function. + --> + <div dojoType="dojox.wire.ml.Invocation" triggerTopic="sampleTopic" object="targetField1" method="setValue" parameters="arguments[0]"></div> +</body> +</html> diff --git a/includes/js/dojox/wire/demos/markup/flickrDemo.css b/includes/js/dojox/wire/demos/markup/flickrDemo.css new file mode 100644 index 0000000..793d1c6 --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/flickrDemo.css @@ -0,0 +1,29 @@ +.flickrView { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; + border-collapse: separate; + width: 100%; +} +.flickrView th { + text-align: left; +} +.flickrView tr { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} +.flickrView tr td { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} +.flickrView { + background-color: #EFEFEF; +} +.flickrTitle { + background-color: #CCCCCC; +} diff --git a/includes/js/dojox/wire/demos/markup/flickrDemo.css.commented.css b/includes/js/dojox/wire/demos/markup/flickrDemo.css.commented.css new file mode 100644 index 0000000..7e75a5d --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/flickrDemo.css.commented.css @@ -0,0 +1,35 @@ +.flickrView { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; + border-collapse: separate; + width: 100%; +} + +.flickrView th { + text-align: left; +} + +.flickrView tr { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} + +.flickrView tr td { + padding: 3 3 3 3; + border-width: 1px; + border-style: solid; + border-color: #000000; +} + +.flickrView { + background-color: #EFEFEF; +} + +.flickrTitle { + background-color: #CCCCCC; +} + diff --git a/includes/js/dojox/wire/demos/markup/states.json b/includes/js/dojox/wire/demos/markup/states.json new file mode 100644 index 0000000..bdaa609 --- /dev/null +++ b/includes/js/dojox/wire/demos/markup/states.json @@ -0,0 +1,56 @@ +{"identifier":"abbreviation", +"label": "label", +"items": [ + {"name":"Alabama", "label":"Alabama","abbreviation":"AL"}, + {"name":"Alaska", "label":"Alaska","abbreviation":"AK"}, + {"name":"American Samoa", "label":"American Samoa","abbreviation":"AS"}, + {"name":"Arizona", "label":"Arizona","abbreviation":"AZ"}, + {"name":"Arkansas", "label":"Arkansas","abbreviation":"AR"}, + {"name":"California", "label":"California","abbreviation":"CA"}, + {"name":"Colorado", "label":"Colorado","abbreviation":"CO"}, + {"name":"Connecticut", "label":"Connecticut","abbreviation":"CT"}, + {"name":"Delaware", "label":"Delaware","abbreviation":"DE"}, + {"name":"Florida", "label":"Florida","abbreviation":"FL"}, + {"name":"Georgia", "label":"Georgia","abbreviation":"GA"}, + {"name":"Hawaii", "label":"Hawaii","abbreviation":"HI"}, + {"name":"Idaho", "label":"Idaho","abbreviation":"ID"}, + {"name":"Illinois", "label":"Illinois","abbreviation":"IL"}, + {"name":"Indiana", "label":"Indiana","abbreviation":"IN"}, + {"name":"Iowa", "label":"Iowa","abbreviation":"IA"}, + {"name":"Kansas", "label":"Kansas","abbreviation":"KS"}, + {"name":"Kentucky", "label":"Kentucky","abbreviation":"KY"}, + {"name":"Louisiana", "label":"Louisiana","abbreviation":"LA"}, + {"name":"Maine", "label":"Maine","abbreviation":"ME"}, + {"name":"Marshall Islands", "label":"Marshall Islands","abbreviation":"MH"}, + {"name":"Maryland", "label":"Maryland","abbreviation":"MD"}, + {"name":"Massachusetts", "label":"Massachusetts","abbreviation":"MA"}, + {"name":"Michigan", "label":"Michigan","abbreviation":"MI"}, + {"name":"Minnesota", "label":"Minnesota","abbreviation":"MN"}, + {"name":"Mississippi", "label":"Mississippi","abbreviation":"MS"}, + {"name":"Missouri", "label":"Missouri","abbreviation":"MO"}, + {"name":"Montana", "label":"Montana","abbreviation":"MT"}, + {"name":"Nebraska", "label":"Nebraska","abbreviation":"NE"}, + {"name":"Nevada", "label":"Nevada","abbreviation":"NV"}, + {"name":"New Hampshire", "label":"New Hampshire","abbreviation":"NH"}, + {"name":"New Jersey", "label":"New Jersey","abbreviation":"NJ"}, + {"name":"New Mexico", "label":"New Mexico","abbreviation":"NM"}, + {"name":"New York", "label":"New York","abbreviation":"NY"}, + {"name":"North Carolina", "label":"North Carolina","abbreviation":"NC"}, + {"name":"North Dakota", "label":"North Dakota","abbreviation":"ND"}, + {"name":"Ohio", "label":"Ohio","abbreviation":"OH"}, + {"name":"Oklahoma", "label":"Oklahoma","abbreviation":"OK"}, + {"name":"Oregon", "label":"Oregon","abbreviation":"OR"}, + {"name":"Pennsylvania", "label":"Pennsylvania","abbreviation":"PA"}, + {"name":"Rhode Island", "label":"Rhode Island","abbreviation":"RI"}, + {"name":"South Carolina", "label":"South Carolina","abbreviation":"SC"}, + {"name":"South Dakota", "label":"South Dakota","abbreviation":"SD"}, + {"name":"Tennessee", "label":"Tennessee","abbreviation":"TN"}, + {"name":"Texas", "label":"Texas","abbreviation":"TX"}, + {"name":"Utah", "label":"Utah","abbreviation":"UT"}, + {"name":"Vermont", "label":"Vermont","abbreviation":"VT"}, + {"name":"Virginia", "label":"Virginia","abbreviation":"VA"}, + {"name":"Washington", "label":"Washington","abbreviation":"WA"}, + {"name":"West Virginia", "label":"West Virginia","abbreviation":"WV"}, + {"name":"Wisconsin", "label":"Wisconsin","abbreviation":"WI"}, + {"name":"Wyoming", "label":"Wyoming","abbreviation":"WY"} +]}
\ No newline at end of file diff --git a/includes/js/dojox/wire/ml/Action.js b/includes/js/dojox/wire/ml/Action.js new file mode 100644 index 0000000..637de41 --- /dev/null +++ b/includes/js/dojox/wire/ml/Action.js @@ -0,0 +1,225 @@ +if(!dojo._hasResource["dojox.wire.ml.Action"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.Action"] = true; +dojo.provide("dojox.wire.ml.Action"); +dojo.provide("dojox.wire.ml.ActionFilter"); + +dojo.require("dijit._Widget"); +dojo.require("dijit._Container"); +dojo.require("dojox.wire.Wire"); +dojo.require("dojox.wire.ml.util"); + +dojo.declare("dojox.wire.ml.Action", [dijit._Widget, dijit._Container], { + // summary: + // A base widget to "run" a task on an event or a topic + // description: + // This widget represents a controller task to be run when an event + // (a function) or a topic is issued. + // Sub-classes must implement _run() method to implement their tasks. + // 'trigger' specifies an event scope, an ID of a widget or an DOM + // element, or its property with the optional dotted notation. + // If this widget has child ActionFilter widgets, their filter() + // methods are called with the arguments to the event or the topic. + // If one of filter() methods returns false, run() won't be invoked. + // This widget also can serve as a composite task to run child + // Actions on an event or a topic specified to this widget. + // trigger: + // An event scope + // triggerEvent: + // An event (function) name + // triggerTopic: + // A topic name + trigger: "", + triggerEvent: "", + triggerTopic: "", + + postCreate: function(){ + // summary: + // Call _connect() + // description: + // See _connect(). + this._connect(); + }, + + _connect: function(){ + // summary: + // Connect run() method to an event or a topic + // description: + // If 'triggerEvent' and 'trigger' are specified, connect() is + // used to set up run() to be called on the event. + // If 'triggerTopic' is specified, subscribe() is used to set up + // run() to be called on the topic. + if(this.triggerEvent){ + if(this.trigger){ + var scope = dojox.wire.ml._getValue(this.trigger); + if(scope){ + if(!scope[this.triggerEvent]){ + // set a dummy function for an anonymous object + scope[this.triggerEvent] = function(){}; + } + this._triggerHandle = dojo.connect(scope, this.triggerEvent, this, "run"); + } + }else{ + var event = this.triggerEvent.toLowerCase(); + if(event == "onload"){ + var self = this; + dojo.addOnLoad(function(){ + self._run.apply(self, arguments); + }); + } + } + }else if(this.triggerTopic){ + this._triggerHandle = dojo.subscribe(this.triggerTopic, this, "run"); + } + }, + + _disconnect: function(){ + // summary: + // Disconnect run() method from an event or a topic + // description: + // If 'triggerEvent' and 'trigger' are specified, disconnect() is + // used to set up run() not to be called on the event. + // If 'triggerTopic' is specified, unsubscribe() is used to set up + // run() not to be called on the topic. + if(this._triggerHandle){ + if(this.triggerTopic){ + dojo.unsubscribe(this.triggerTopic, this._triggerHandle); + }else{ + dojo.disconnect(this._triggerHandle); + } + } + }, + + run: function(){ + // summary: + // Run a task + // description: + // This method calls filter() method of child ActionFilter + // widgets. + // If one of them returns false, this method returns. + // Otherwise, _run() method is called. + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if(child instanceof dojox.wire.ml.ActionFilter){ + if(!child.filter.apply(child, arguments)){ + return; + } + } + } + this._run.apply(this, arguments); + }, + + _run: function(){ + // summary: + // Call run() methods of child Action widgets + // description: + // If this widget has child Action widgets, their run() methods + // are called. + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if(child instanceof dojox.wire.ml.Action){ + child.run.apply(child, arguments); + } + } + }, + + uninitialize: function(){ + // summary: + // Over-ride of base widget unitialize function to do some connection cleanup. + this._disconnect(); + return true; + } +}); + +dojo.declare("dojox.wire.ml.ActionFilter", dijit._Widget, { + // summary: + // A widget to define a filter for the parent Action to run + // description: + // This base class checks a required property specified with + // 'required' attribute. + // If 'message' is specified, the message is set to a property + // specified with 'error'. + // Subclasses may implement their own filter() method. + // required: + // A property required + // requiredValue: + // Optional. A specific value the property is required to have. If this isn't provided + // than any non-false/non-null value of the required propery will cause this filter + // to pass. + // type: + // Optional. A specific type to compare the values as (if requiredValue is set) + // Valid values for type are boolean, int, string. Default is string. + // message: + // An error message to emit if the filter doesn't execute due to property mismatch. + // error: + // A property to store an error due to property mismatch. + required: "", + requiredValue: "", + type: "", + message: "", + error: "", + + + filter: function(){ + // summary: + // Check if a required property is specified. Also, if provided, check to see + // if the required property contains a specific value. + // description: + // If a value is undefined for a property, specified with + // 'required', this method returns false. + // If the value for a property is defined, but there isn't a requiredValue for it + // then any non-false value will cause the method to return true. + // if requiredValue is set, then filter compares that value with the value from + // the required property and returns true if and only if they match. + // The type option just allows for a way to convert the required property values + // into a proper form for comparison (boolean, number, etc). + // If 'message' is specified, it is set to a proeprty specified + // with 'error' or shown with alert(). + // If 'required' starts with "arguments", a property of + // the method arguments are checked. + // returns: + // True if a required property is specified (and if requiredValue is specified, + // that they match), otherwise false + if(this.required === ""){ + return true; //Boolean + }else{ + var value = dojox.wire.ml._getValue(this.required, arguments); + if(this.requiredValue === ""){ + //Just see if there's a value, nothing to compare it to. + if(value){ + return true; //Boolean + } + }else{ + //See if we need to type convert. + var reqValue = this.requiredValue; + if(this.type !== ""){ + var lType = this.type.toLowerCase(); + if(lType === "boolean"){ + if(reqValue.toLowerCase() === "false"){ + reqValue = false; + }else{ + reqValue = true; + } + }else if(lType === "number"){ + reqValue = parseInt(reqValue, 10); + } + } + if(value === reqValue){ + return true; //boolean + } + } + } + + if(this.message){ + if(this.error){ + dojox.wire.ml._setValue(this.error, this.message); + }else{ + alert(this.message); + } + } + return false; //Boolean + } +}); + +} diff --git a/includes/js/dojox/wire/ml/Data.js b/includes/js/dojox/wire/ml/Data.js new file mode 100644 index 0000000..71ab0ad --- /dev/null +++ b/includes/js/dojox/wire/ml/Data.js @@ -0,0 +1,143 @@ +if(!dojo._hasResource["dojox.wire.ml.Data"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.Data"] = true; +dojo.provide("dojox.wire.ml.Data"); +dojo.provide("dojox.wire.ml.DataProperty"); + +dojo.require("dijit._Widget"); +dojo.require("dijit._Container"); +dojo.require("dojox.wire.ml.util"); + +dojo.declare("dojox.wire.ml.Data", [dijit._Widget, dijit._Container], { + // summary: + // A widget for a data object + // description: + // This widget represents an object with '_properties' property. + // If child 'DataProperty' widgets exist, they are used to initialize + // propertiy values of '_properties' object. + + startup: function(){ + // summary: + // Call _initializeProperties() + // description: + // See _initializeProperties(). + this._initializeProperties(); + }, + + _initializeProperties: function(/*Boolean*/reset){ + // summary: + // Initialize a data object + // description: + // If this widget has child DataProperty widgets, their getValue() + // methods are called and set the return value to a property + // specified by 'name' attribute of the child widgets. + // reset: + // A boolean to reset current properties + if(!this._properties || reset){ + this._properties = {}; + } + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if((child instanceof dojox.wire.ml.DataProperty) && child.name){ + this.setPropertyValue(child.name, child.getValue()); + } + } + }, + + getPropertyValue: function(/*String*/property){ + // summary: + // Return a property value + // description: + // This method returns the value of a property, specified with + // 'property' argument, in '_properties' object. + // property: + // A property name + // returns: + // A property value + return this._properties[property]; //anything + }, + + setPropertyValue: function(/*String*/property, /*anything*/value){ + // summary: + // Store a property value + // description: + // This method stores 'value' as a property, specified with + // 'property' argument, in '_properties' object. + // property: + // A property name + // value: + // A property value + this._properties[property] = value; + } +}); + +dojo.declare("dojox.wire.ml.DataProperty", [dijit._Widget, dijit._Container], { + // summary: + // A widget to define a data property + // description: + // Attributes of this widget are used to add a property to the parent + // Data widget. + // 'type' attribute specifies one of "string", "number", "boolean", + // "array", "object" and "element" (DOM Element) + // (default to "string"). + // If 'type' is "array" or "object", child DataProperty widgets are + // used to initialize the array elements or the object properties. + // name: + // A property name + // type: + // A property type name + // value: + // A property value + name: "", + type: "", + value: "", + + getValue: function(){ + // summary: + // Returns a property value + // description: + // If 'type' is specified, 'value' attribute is converted to + // the specified type and returned. + // Otherwise, 'value' attribute is returned as is. + // returns: + // A property value + var value = this.value; + if(this.type){ + if(this.type == "number"){ + value = parseInt(value); + }else if(this.type == "boolean"){ + value = (value == "true"); + }else if(this.type == "array"){ + value = []; + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if(child instanceof dojox.wire.ml.DataProperty){ + value.push(child.getValue()); + } + } + }else if(this.type == "object"){ + value = {}; + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if((child instanceof dojox.wire.ml.DataProperty) && child.name){ + value[child.name] = child.getValue(); + } + } + }else if(this.type == "element"){ + value = new dojox.wire.ml.XmlElement(value); + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if((child instanceof dojox.wire.ml.DataProperty) && child.name){ + value.setPropertyValue(child.name, child.getValue()); + } + } + } + } + return value; //anything + } +}); + +} diff --git a/includes/js/dojox/wire/ml/DataStore.js b/includes/js/dojox/wire/ml/DataStore.js new file mode 100644 index 0000000..e366d05 --- /dev/null +++ b/includes/js/dojox/wire/ml/DataStore.js @@ -0,0 +1,116 @@ +if(!dojo._hasResource["dojox.wire.ml.DataStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.DataStore"] = true; +dojo.provide("dojox.wire.ml.DataStore"); + +dojo.require("dijit._Widget"); +dojo.require("dojox.wire._base"); + +dojo.declare("dojox.wire.ml.DataStore", dijit._Widget, { + // summary: + // A widget for a data store + // description: + // This widget represents a data store of 'storeClass' attribute. + // storeClass: + // A class name of a data store + storeClass: "", + + postCreate: function(){ + // summary: + // Call _createStore() + // description: + // See _createStore(). + this.store = this._createStore(); + }, + + _createStore: function(){ + // summary: + // Create a data store + // desription: + // A data store of 'storeClass' is created with arguments + // specified with attributes. + // returns: + // A data store + if(!this.storeClass){ + return null; //null + } + var storeClass = dojox.wire._getClass(this.storeClass); + if(!storeClass){ + return null; //null + } + var args = {}; + var attributes = this.domNode.attributes; + for(var i = 0; i < attributes.length; i++){ + var a = attributes.item(i); + if(a.specified && !this[a.nodeName]){ + args[a.nodeName] = a.nodeValue; + } + } + return new storeClass(args); //Object + }, + + getFeatures: function(){ + // summary: + // Call getFeatures() method of a data store + // description: + // See dojo.data.api.Read.getFeatures(). + // returns: + // A features object + return this.store.getFeatures(); //Object + }, + + fetch: function(/*Object*/request){ + // summary: + // Call fetch() method of a data store + // description: + // See dojo.data.api.Read.fetch(). + // request: + // A request object + // returns: + // A request object + return this.store.fetch(request); //Object + }, + + save: function(/*Object*/args){ + // summary: + // Call save() method of a data store + // description: + // See dojo.data.api.Write.save(). + // args: + // A save arguments object + this.store.save(args); + }, + + newItem: function(/*Object*/args){ + // summary: + // Call newItem() method of a data store + // description: + // See dojo.data.api.Write.newItem(). + // args: + // A new item arguments object + // returns: + // A new item + return this.store.newItem(args); //Object + }, + + deleteItem: function(/*Object*/item){ + // summary: + // Call deleteItem() method of a data store + // description: + // See dojo.data.api.Write.deleteItem(). + // returns: + // A boolean + return this.store.deleteItem(item); //Boolean + }, + + revert: function(){ + // summary: + // Call revert() method of a data store + // description: + // See dojo.data.api.Write.revert(). + // returns: + // A boolean + return this.store.revert(); //Boolean + } +}); + +} diff --git a/includes/js/dojox/wire/ml/Invocation.js b/includes/js/dojox/wire/ml/Invocation.js new file mode 100644 index 0000000..3d36623 --- /dev/null +++ b/includes/js/dojox/wire/ml/Invocation.js @@ -0,0 +1,171 @@ +if(!dojo._hasResource["dojox.wire.ml.Invocation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.Invocation"] = true; +dojo.provide("dojox.wire.ml.Invocation"); + +dojo.require("dojox.wire.ml.Action"); + +dojo.declare("dojox.wire.ml.Invocation", dojox.wire.ml.Action, { + // summary: + // A widget to invoke a method or publish a topic + // description: + // This widget represents a controller task to invoke a method or + // publish a topic when an event (a function) or a topic is issued. + // object: + // A scope of a method to invoke + // method: + // A name of a method to invoke + // topic: + // A name of a topic to publish + // parameters: + // Arguments for the method or the topic + // result: + // A property to store a return value of the method call + // error: + // A property to store an error on the method call + object: "", + method: "", + topic: "", + parameters: "", + result: "", + error: "", + + _run: function(){ + // summary: + // Invoke a method or publish a topic + // description: + // If 'topic' is specified, the topic is published with arguments + // specified to 'parameters'. + // If 'method' and 'object' are specified, the method is invoked + // with arguments specified to 'parameters' and set the return + // value to a property specified to 'result'. + // 'object', 'parameters' and 'result' can specify properties of + // a widget or an DOM element with the dotted notation. + // If 'parameters' are omitted, the arguments to this method are + // passed as is. + if(this.topic){ + var args = this._getParameters(arguments); + try{ + dojo.publish(this.topic, args); + this.onComplete(); + }catch(e){ + this.onError(e); + } + }else if(this.method){ + var scope = (this.object ? dojox.wire.ml._getValue(this.object) : dojo.global); + if(!scope){ + return; //undefined + } + var args = this._getParameters(arguments); + var func = scope[this.method]; + if(!func){ + func = scope.callMethod; + if(!func){ + return; //undefined + } + args = [this.method, args]; + } + try{ + var connected = false; + if(scope.getFeatures){ + var features = scope.getFeatures(); + if((this.method == "fetch" && features["dojo.data.api.Read"]) || + (this.method == "save" && features["dojo.data.api.Write"])){ + var arg = args[0]; + if(!arg.onComplete){ + arg.onComplete = function(){}; + } + //dojo.connect(arg, "onComplete", this, "onComplete"); + this.connect(arg, "onComplete", "onComplete"); + if(!arg.onError){ + arg.onError = function(){}; + } + //dojo.connect(arg, "onError", this, "onError"); + this.connect(arg, "onError", "onError"); + connected = true; + } + } + var r = func.apply(scope, args); + if(!connected){ + if(r && (r instanceof dojo.Deferred)){ + var self = this; + r.addCallbacks( + function(result){self.onComplete(result);}, + function(error){self.onError(error);} + ); + }else{ + this.onComplete(r); + } + } + }catch(e){ + this.onError(e); + } + } + }, + + onComplete: function(/*anything*/result){ + // summary: + // A function called when the method or the topic publish + // completed + // description: + // If 'result' attribute is specified, the result object also set + // to the specified property. + // result: + // The return value of a method or undefined for a topic + if(this.result){ + dojox.wire.ml._setValue(this.result, result); + } + if(this.error){ // clear error + dojox.wire.ml._setValue(this.error, ""); + } + }, + + onError: function(/*anything*/error){ + // summary: + // A function called on an error occurs + // description: + // If 'error' attribute is specified, the error object also set to + // the specified property. + // error: + // The exception or error occurred + if(this.error){ + if(error && error.message){ + error = error.message; + } + dojox.wire.ml._setValue(this.error, error); + } + }, + + _getParameters: function(/*Array*/args){ + // summary: + // Returns arguments to a method or topic to invoke + // description: + // This method retunrs an array of arguments specified by + // 'parameters' attribute, a comma-separated list of IDs and + // their properties in a dotted notation. + // If 'parameters' are omitted, the original arguments are + // used. + // args: + // Arguments to a trigger event or topic + if(!this.parameters){ + // use arguments as is + return args; //Array + } + var parameters = []; + var list = this.parameters.split(","); + if(list.length == 1){ + var parameter = dojox.wire.ml._getValue(dojo.trim(list[0]), args); + if(dojo.isArray(parameter)){ + parameters = parameter; + }else{ + parameters.push(parameter); + } + }else{ + for(var i in list){ + parameters.push(dojox.wire.ml._getValue(dojo.trim(list[i]), args)); + } + } + return parameters; //Array + } +}); + +} diff --git a/includes/js/dojox/wire/ml/Service.js b/includes/js/dojox/wire/ml/Service.js new file mode 100644 index 0000000..15f074b --- /dev/null +++ b/includes/js/dojox/wire/ml/Service.js @@ -0,0 +1,340 @@ +if(!dojo._hasResource["dojox.wire.ml.Service"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.Service"] = true; +dojo.provide("dojox.wire.ml.Service"); +dojo.provide("dojox.wire.ml.RestHandler"); +dojo.provide("dojox.wire.ml.XmlHandler"); +dojo.provide("dojox.wire.ml.JsonHandler"); + +dojo.require("dijit._Widget"); +dojo.require("dojox.data.dom"); +dojo.require("dojox.wire._base"); +dojo.require("dojox.wire.ml.util"); + +dojo.declare("dojox.wire.ml.Service", dijit._Widget, { + // summary: + // A widget for a service + // description: + // This widget represents a service defined by a service description + // specified with 'url' attribute. + // If 'serviceType' and 'serviceUrl' attributes are specified, 'url' + // attribute can be omitted. + // url: + // A URL to a service description + // serviceUrl: + // A URL to a service + // serviceType: + // A service type + // handlerClass: + // A service handler class name + url: "", + serviceUrl: "", + serviceType: "", + handlerClass: "", + preventCache: true, + + postCreate: function(){ + // summary: + // Call _createHandler() + // description: + // See _createHandler(). + this.handler = this._createHandler(); + }, + + _handlerClasses: { + "TEXT": "dojox.wire.ml.RestHandler", + "XML": "dojox.wire.ml.XmlHandler", + "JSON": "dojox.wire.ml.JsonHandler", + "JSON-RPC": "dojo.rpc.JsonService" + }, + + _createHandler: function(){ + // summary: + // Create a service handler + // desription: + // A service handler class is determined by: + // 1. 'handlerClass' attribute + // 2. 'serviceType' attribute + // 3. 'serviceType' property in a service description + // returns: + // A service handler + if(this.url){ + var self = this; + var d = dojo.xhrGet({ + url: this.url, + handleAs: "json", + sync: true + }); + d.addCallback(function(result){ + self.smd = result; + }); + if(this.smd && !this.serviceUrl){ + this.serviceUrl = (this.smd.serviceUrl || this.smd.serviceURL); + } + } + var handlerClass = undefined; + if(this.handlerClass){ + handlerClass = dojox.wire._getClass(this.handlerClass); + }else if(this.serviceType){ + handlerClass = this._handlerClasses[this.serviceType]; + if(handlerClass && dojo.isString(handlerClass)){ + handlerClass = dojox.wire._getClass(handlerClass); + this._handlerClasses[this.serviceType] = handlerClass; + } + }else if(this.smd && this.smd.serviceType){ + handlerClass = this._handlerClasses[this.smd.serviceType]; + if(handlerClass && dojo.isString(handlerClass)){ + handlerClass = dojox.wire._getClass(handlerClass); + this._handlerClasses[this.smd.serviceType] = handlerClass; + } + } + if(!handlerClass){ + return null; //null + } + return new handlerClass(); //Object + }, + + callMethod: function(method, parameters){ + // summary: + // Call a service method with parameters + // method: + // A method name + // parameters: + // An array parameters + var deferred = new dojo.Deferred(); + this.handler.bind(method, parameters, deferred, this.serviceUrl); + return deferred; + } +}); + +dojo.declare("dojox.wire.ml.RestHandler", null, { + // summary: + // A REST service handler + // description: + // This class serves as a base REST service. + // Sub-classes may override _getContent() and _getResult() to handle + // specific content types. + contentType: "text/plain", + handleAs: "text", + + bind: function(method, parameters, deferred, url){ + // summary: + // Call a service method with parameters. + // description: + // A service is called with a URL generated by _getUrl() and + // an HTTP method specified with 'method'. + // For "POST" and "PUT", a content is generated by _getContent(). + // When data is loaded, _getResult() is used to pass the result to + // Deferred.callback(). + // method: + // A method name + // parameters: + // An array of parameters + // deferred: + // 'Deferred' + // url: + // A URL for the method + method = method.toUpperCase(); + var self = this; + var args = { + url: this._getUrl(method, parameters, url), + contentType: this.contentType, + handleAs: this.handleAs, + headers: this.headers, + preventCache: this.preventCache + }; + var d = null; + if(method == "POST"){ + args.postData = this._getContent(method, parameters); + d = dojo.rawXhrPost(args); + }else if(method == "PUT"){ + args.putData = this._getContent(method, parameters); + d = dojo.rawXhrPut(args); + }else if(method == "DELETE"){ + d = dojo.xhrDelete(args); + }else{ // "GET" + d = dojo.xhrGet(args); + } + d.addCallbacks(function(result){ + deferred.callback(self._getResult(result)); + }, function(error){ + deferred.errback(error); + }); + }, + + _getUrl: function(/*String*/method, /*Array*/parameters, /*String*/url){ + // summary: + // Generate a URL + // description: + // If 'method' is "GET" or "DELETE", a query string is generated + // from a query object specified to the first parameter in + // 'parameters' and appended to 'url'. + // If 'url' contains variable seguments ("{parameter_name}"), + // they are replaced with corresponding parameter values, instead. + // method: + // A method name + // parameters: + // An array of parameters + // url: + // A base URL + // returns: + // A URL + var query; + if(method == "GET" || method == "DELETE"){ + if(parameters.length > 0){ + query = parameters[0]; + } + }else{ // "POST" || "PUT" + if(parameters.length > 1){ + query = parameters[1]; + } + } + if(query){ + var queryString = ""; + for(var name in query){ + var value = query[name]; + if(value){ + value = encodeURIComponent(value); + var variable = "{" + name + "}"; + var index = url.indexOf(variable); + if(index >= 0){ // encode in path + url = url.substring(0, index) + value + url.substring(index + variable.length); + }else{ // encode as query string + if(queryString){ + queryString += "&"; + } + queryString += (name + "=" + value); + } + } + } + if(queryString){ + url += "?" + queryString; + } + } + return url; //String + }, + + _getContent: function(/*String*/method, /*Array*/parameters){ + // summary: + // Generate a request content + // description: + // If 'method' is "POST" or "PUT", the first parameter in + // 'parameters' is returned. + // method: + // A method name + // parameters: + // An array of parameters + // returns: + // A request content + if(method == "POST" || method == "PUT"){ + return (parameters ? parameters[0] : null); //anything + }else{ + return null; //null + } + }, + + _getResult: function(/*anything*/data){ + // summary: + // Extract a result + // description: + // A response data is returned as is. + // data: + // A response data returned by a service + // returns: + // A result object + return data; //anything + } +}); + +dojo.declare("dojox.wire.ml.XmlHandler", dojox.wire.ml.RestHandler, { + // summary: + // A REST service handler for XML + // description: + // This class provides XML handling for a REST service. + contentType: "text/xml", + handleAs: "xml", + + _getContent: function(/*String*/method, /*Array*/parameters){ + // description: + // If 'method' is "POST" or "PUT", the first parameter in + // 'parameters' is used to generate an XML content. + // method: + // A method name + // parameters: + // An array of parameters + // returns: + // A request content + var content = null; + if(method == "POST" || method == "PUT"){ + var p = parameters[0]; + if(p){ + if(dojo.isString(p)){ + content = p; + }else{ + var element = p; + if(element instanceof dojox.wire.ml.XmlElement){ + element = element.element; + }else if(element.nodeType === 9 /* DOCUMENT_NODE */){ + element = element.documentElement; + } + var declaration = "<?xml version=\"1.0\"?>"; // TODO: encoding? + content = declaration + dojox.data.dom.innerXML(element); + } + } + } + return content; + }, + + _getResult: function(/*Document*/data){ + // summary: + // Extract a result + // description: + // A response data (XML Document) is returned wrapped with + // XmlElement. + // data: + // A response data returned by a service + // returns: + // A result object + if(data){ + data = new dojox.wire.ml.XmlElement(data); + } + return data; + } +}); + +dojo.declare("dojox.wire.ml.JsonHandler", dojox.wire.ml.RestHandler, { + // summary: + // A REST service handler for JSON + // description: + // This class provides JSON handling for a REST service. + contentType: "text/json", + handleAs: "json", + headers: {"Accept": "*/json"}, + + _getContent: function(/*String*/method, /*Array*/parameters){ + // summary: + // Generate a request content + // description: + // If 'method' is "POST" or "PUT", the first parameter in + // 'parameter' is used to generate a JSON content. + // method: + // A method name + // parameters: + // An array of parameters + // returns: + // A request content + var content = null; + if(method == "POST" || method == "PUT"){ + var p = (parameters ? parameters[0] : undefined); + if(p){ + if(dojo.isString(p)){ + content = p; + }else{ + content = dojo.toJson(p); + } + } + } + return content; //String + } +}); + +} diff --git a/includes/js/dojox/wire/ml/Transfer.js b/includes/js/dojox/wire/ml/Transfer.js new file mode 100644 index 0000000..c7780ca --- /dev/null +++ b/includes/js/dojox/wire/ml/Transfer.js @@ -0,0 +1,359 @@ +if(!dojo._hasResource["dojox.wire.ml.Transfer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.Transfer"] = true; +dojo.provide("dojox.wire.ml.Transfer"); +dojo.provide("dojox.wire.ml.ChildWire"); +dojo.provide("dojox.wire.ml.ColumnWire"); +dojo.provide("dojox.wire.ml.NodeWire"); +dojo.provide("dojox.wire.ml.SegmentWire"); + +dojo.require("dijit._Widget"); +dojo.require("dijit._Container"); +dojo.require("dojox.wire._base"); +dojo.require("dojox.wire.ml.Action"); + +dojo.declare("dojox.wire.ml.Transfer", dojox.wire.ml.Action, { + // summary: + // A widget to transfer values through source and target Wires + // description: + // This widget represents a controller task to transfer a value from + // a source to a target, through a source and a target Wires, when + // an event (a function) or a topic is issued. + // If this widget has child ChildWire widgets, their _addWire() + // methods are called to add Wire arguments to a source or a target + // Wire. + // source: + // A source object and/or property + // sourceStore: + // A data store for a source data item + // sourceAttribute: + // An attribute of a source data item + // sourcePath: + // A simplified XPath to a source property of an XML element + // type: + // A type of the value to be transferred + // converter: + // A class name of a converter for the value to be transferred + // target: + // A target object and/or property + // targetStore: + // A data store for a target data item + // targetAttribute: + // An attribute of a target data item + // targetPath: + // A simplified XPath to a target property of an XML element + source: "", + sourceStore: "", + sourceAttribute: "", + sourcePath: "", + type: "", + converter: "", + delimiter: "", + target: "", + targetStore: "", + targetAttribute: "", + targetPath: "", + + _run: function(){ + // summary: + // Transfer a value from a source to a target + // description: + // First, Wires for a source and a target are created from attributes. + // Then, a value is obtained by getValue() of the source Wire is set + // by setValue() of the target Wire. + // The arguments to this method is passed to getValue() and setValue() + // of Wires, so that they can be used to identify the root objects off + // the arguments. + var sourceWire = this._getWire("source"); + var targetWire = this._getWire("target"); + dojox.wire.transfer(sourceWire, targetWire, arguments); + }, + + _getWire: function(/*String*/which){ + // summary: + // Build Wire arguments from attributes + // description: + // Arguments object for a source or a target Wire, specified by + // 'which' argument, are build from corresponding attributes, + // including '*Store' (for 'dataStore'), '*Attribute' + // (for 'attribute), '*Path' (for 'path'), 'type' and 'converter'. + // 'source' or 'target' attribute is parsed as: + // "object_id.property_name[.sub_property_name...]" + // If 'source' or 'target' starts with "arguments", 'object' + // argument for a Wire is set to null, so that the root object is + // given as an event or topic arguments. + // If this widget has child ChildWire widgets with a corresponding + // 'which' attribute, their _addWire() methods are called to add + // additional Wire arguments and nested Wire is created, + // specifying the Wire defined by this widget to 'object' argument. + // which: + // Which Wire arguments to build, "source" or "target" + // returns: + // Wire arguments object + var args = undefined; + if(which == "source"){ + args = { + object: this.source, + dataStore: this.sourceStore, + attribute: this.sourceAttribute, + path: this.sourcePath, + type: this.type, + converter: this.converter + }; + }else{ // "target" + args = { + object: this.target, + dataStore: this.targetStore, + attribute: this.targetAttribute, + path: this.targetPath + }; + } + if(args.object){ + if(args.object.length >= 9 && args.object.substring(0, 9) == "arguments"){ + args.property = args.object.substring(9); + args.object = null; + }else{ + var i = args.object.indexOf('.'); + if(i < 0){ + args.object = dojox.wire.ml._getValue(args.object); + }else{ + args.property = args.object.substring(i + 1); + args.object = dojox.wire.ml._getValue(args.object.substring(0, i)); + } + } + } + if(args.dataStore){ + args.dataStore = dojox.wire.ml._getValue(args.dataStore); + } + var childArgs = undefined; + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if(child instanceof dojox.wire.ml.ChildWire && child.which == which){ + if(!childArgs){ + childArgs = {}; + } + child._addWire(this, childArgs); + } + } + if(childArgs){ // make nested Wires + childArgs.object = dojox.wire.create(args); + childArgs.dataStore = args.dataStore; + args = childArgs; + } + return args; //Object + } +}); + +dojo.declare("dojox.wire.ml.ChildWire", dijit._Widget, { + // summary: + // A widget to add a child wire + // description: + // Attributes of this widget are used to add a child Wire to + // a composite Wire of the parent Transfer widget. + // which: + // Which Wire to add a child Wire, "source" or "target", default to + // "source" + // object: + // A root object for the value + // property: + // A property for the value + // type: + // A type of the value + // converter: + // A class name of a converter for the value + // attribute: + // A data item attribute for the value + // path: + // A simplified XPath for the value + // name: + // A composite property name + which: "source", + object: "", + property: "", + type: "", + converter: "", + attribute: "", + path: "", + name: "", + + _addWire: function(/*Transfer*/parent, /*Object*/args){ + // summary: + // Add a child Wire to Wire arguments + // description: + // If 'name' attribute is specified, a child Wire is added as + // the named property of 'children' object of 'args'. + // Otherwise, a child Wire is added to 'children' array of 'args'. + // parent: + // A parent Transfer widget + // args: + // Wire arguments + if(this.name){ // object + if(!args.children){ + args.children = {}; + } + args.children[this.name] = this._getWire(parent); + }else{ // array + if(!args.children){ + args.children = []; + } + args.children.push(this._getWire(parent)); + } + }, + + _getWire: function(/*Transfer*/parent){ + // summary: + // Build child Wire arguments from attributes + // description: + // Arguments object for a child Wire are build from attributes, + // including 'object', 'property', 'type', 'converter', + // 'attribute' and 'path'. + // parent: + // A parent Transfer widget + // returns: + // Wire arguments object + return { + object: (this.object ? dojox.wire.ml._getValue(this.object) : undefined), + property: this.property, + type: this.type, + converter: this.converter, + attribute: this.attribute, + path: this.path + }; //Object + } +}); + +dojo.declare("dojox.wire.ml.ColumnWire", dojox.wire.ml.ChildWire, { + // summary: + // A widget to add a column wire + // description: + // Attributes of this widget are used to add a column Wire to + // a TableAdapter of the parent Transfer widget. + // column: + // A column name + column: "", + + _addWire: function(/*Transfer*/parent, /*Object*/args){ + // summary: + // Add a column Wire to Wire arguments + // description: + // If 'column' attribute is specified, a column Wire is added as + // the named property of 'columns' object of 'args'. + // Otherwise, a column Wire is added to 'columns' array of 'args'. + // parent: + // A parent Transfer widget + // args: + // Wire arguments + if(this.column){ // object + if(!args.columns){ + args.columns = {}; + } + args.columns[this.column] = this._getWire(parent); + }else{ // array + if(!args.columns){ + args.columns = []; + } + args.columns.push(this._getWire(parent)); + } + } +}); + +dojo.declare("dojox.wire.ml.NodeWire", [dojox.wire.ml.ChildWire, dijit._Container], { + // summary: + // A widget to add node wires + // description: + // Attributes of this widget are used to add node Wires to + // a TreeAdapter of the parent Transfer widget. + // titleProperty: + // A property for the node title + // titleAttribute: + // A data item attribute for the node title + // titlePath: + // A simplified XPath for the node title + titleProperty: "", + titleAttribute: "", + titlePath: "", + + _addWire: function(/*Transfer*/parent, /*Object*/args){ + // summary: + // Add node Wires to Wire arguments + // description: + // Node Wires are added to 'nodes' array of 'args'. + // parent: + // A parent Transfer widget + // args: + // Wire arguments + if(!args.nodes){ + args.nodes = []; + } + args.nodes.push(this._getWires(parent)); + }, + + _getWires: function(/*Transfer*/parent){ + // summary: + // Build node Wires arguments from attributes + // description: + // Arguments object for 'node' Wire are build from attributes, + // including 'object', 'property', 'type', 'converter', + // 'attribute' and 'path'. + // Arguments object for 'title' Wire are build from another set of + // attributes, 'titleProperty', 'titleAttribute' and 'titlePath'. + // If this widget has child NodeWire widgets, their _getWires() + // methods are called recursively to build 'children' array of + // 'args'. + // parent: + // A parent Transfer widget + // returns: + // Wire arguments object + var args = { + node: this._getWire(parent), + title: { + type: "string", + property: this.titleProperty, + attribute: this.titleAttribute, + path: this.titlePath + } + }; + var childArgs = []; + var children = this.getChildren(); + for(var i in children){ + var child = children[i]; + if(child instanceof dojox.wire.ml.NodeWire){ + childArgs.push(child._getWires(parent)); + } + } + if(childArgs.length > 0){ + args.children = childArgs; + } + return args; //Object + } +}); + +dojo.declare("dojox.wire.ml.SegmentWire", dojox.wire.ml.ChildWire, { + // summary: + // A widget to add a segment wire + // description: + // Attributes of this widget are used to add a segment Wire to + // a TextAdapter of the parent Transfer widget. + + _addWire: function(/*Transfer*/parent, /*Object*/args){ + // summary: + // Add a segument Wire to Wire arguments + // description: + // A segment Wire is added to 'segments' array of 'args'. + // If 'parent' has 'delimiter' attribute, it is used for + // 'delimiter' property of 'args'. + // parent: + // A parent Transfer widget + // args: + // Wire arguments + if(!args.segments){ + args.segments = []; + } + args.segments.push(this._getWire(parent)); + if(parent.delimiter && !args.delimiter){ + args.delimiter = parent.delimiter; + } + } +}); + +} diff --git a/includes/js/dojox/wire/ml/util.js b/includes/js/dojox/wire/ml/util.js new file mode 100644 index 0000000..a336b28 --- /dev/null +++ b/includes/js/dojox/wire/ml/util.js @@ -0,0 +1,295 @@ +if(!dojo._hasResource["dojox.wire.ml.util"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.ml.util"] = true; +dojo.provide("dojox.wire.ml.util"); + +dojo.require("dojox.data.dom"); +dojo.require("dojox.wire.Wire"); + +dojox.wire.ml._getValue = function(/*String*/source, /*Array*/args){ + // summary: + // Return a value + // description: + // This method obtains an object by an ID of a widget or an DOM + // element. + // If 'source' specifies a dotted notation to its property, a Wire is + // used to get the object property. + // If 'source' starts with "arguments", 'args' is used as a root + // object for the Wire. + // source: + // A string to specify an object and its property + // args: + // An optional arguments array + // returns: + // A value + if(!source){ + return undefined; //undefined + } + var property = undefined; + if(args && source.length >= 9 && source.substring(0, 9) == "arguments"){ + property = source.substring(9); + return new dojox.wire.Wire({property: property}).getValue(args); + } + var i = source.indexOf('.'); + if(i >= 0){ + property = source.substring(i + 1); + source = source.substring(0, i); + } + var object = (dijit.byId(source) || dojo.byId(source) || dojo.getObject(source)); + if(!object){ + return undefined; //undefined + } + if(!property){ + return object; //Object + }else{ + return new dojox.wire.Wire({object: object, property: property}).getValue(); //anything + } +}; + +dojox.wire.ml._setValue = function(/*String*/target, /*anything*/value){ + // summary: + // Store a value + // description: + // This method stores a value by an ID of a widget or an DOM + // element with a dotted notation to its property, using a Wire. + // target: + // A string to specify an object and its property + // value: + // A value + if(!target){ + return; //undefined + } + var i = target.indexOf('.'); + if(i < 0){ + return; //undefined + } + var object = this._getValue(target.substring(0, i)); + if(!object){ + return; //undefined + } + var property = target.substring(i + 1); + new dojox.wire.Wire({object: object, property: property}).setValue(value); +}; + +dojo.declare("dojox.wire.ml.XmlElement", null, { + // summary: + // An object wrapping an XML element + // description: + // This class represents an XML element. + + constructor: function(/*Element||String*/element){ + // summary: + // Initialize with an XML element or a tag name + // element: + // An XML element or a tag name + if(dojo.isString(element)){ + element = this._getDocument().createElement(element); + } + this.element = element; + }, + getPropertyValue: function(/*String*/property){ + // summary: + // Return a property value + // description: + // If 'property' starts with '@', the attribute value is returned. + // If 'property' specifies "text()", the value of the first child + // text is returned. + // Otherwise, child elements of the tag name specified with + // 'property' are returned. + // property: + // A property name + // returns: + // A property value + var value = undefined; + if(!this.element){ + return value; //undefined + } + if(!property){ + return value; //undefined + } + + if(property.charAt(0) == '@'){ + var attribute = property.substring(1); + value = this.element.getAttribute(attribute); + }else if(property == "text()"){ + var text = this.element.firstChild; + if(text){ + value = text.nodeValue; + } + }else{ // child elements + var elements = []; + for(var i = 0; i < this.element.childNodes.length; i++){ + var child = this.element.childNodes[i]; + if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == property){ + elements.push(new dojox.wire.ml.XmlElement(child)); + } + } + if(elements.length > 0){ + if(elements.length === 1){ + value = elements[0]; + }else{ + value = elements; + } + } + } + return value; //String||Array||XmlElement + }, + + setPropertyValue: function(/*String*/property, /*String||Array||XmlElement*/value){ + // summary: + // Store a property value + // description: + // If 'property' starts with '@', 'value' is set to the attribute. + // If 'property' specifies "text()", 'value' is set as the first + // child text. + // If 'value' is a string, a child element of the tag name + // specified with 'property' is created and 'value' is set as + // the first child text of the child element. + // Otherwise, 'value' is set to as child elements. + // property: + // A property name + // value: + // A property value + if(!this.element){ + return; //undefined + } + if(!property){ + return; //undefined + } + + if(property.charAt(0) == '@'){ + var attribute = property.substring(1); + if(value){ + this.element.setAttribute(attribute, value); + }else{ + this.element.removeAttribute(attribute); + } + }else if(property == "text()"){ + while(this.element.firstChild){ + this.element.removeChild(this.element.firstChild); + } + if(value){ + var text = this._getDocument().createTextNode(value); + this.element.appendChild(text); + } + }else{ // child elements + var nextChild = null; + for(var i = this.element.childNodes.length - 1; i >= 0; i--){ + var child = this.element.childNodes[i]; + if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == property){ + if(!nextChild){ + nextChild = child.nextSibling; + } + this.element.removeChild(child); + } + } + if(value){ + if(dojo.isArray(value)){ + for(var i in value){ + var e = value[i]; + if(e.element){ + this.element.insertBefore(e.element, nextChild); + } + } + }else if(value instanceof dojox.wire.ml.XmlElement){ + if(value.element){ + this.element.insertBefore(value.element, nextChild); + } + }else{ // assume string + var child = this._getDocument().createElement(property); + var text = this._getDocument().createTextNode(value); + child.appendChild(text); + this.element.insertBefore(child, nextChild); + } + } + } + }, + + toString: function(){ + // summary: + // Return a value of the first text child of the element + // description: + // A value of the first text child of the element is returned. + // returns: + // A value of the first text child of the element + var s = ""; + if(this.element){ + var text = this.element.firstChild; + if(text){ + s = text.nodeValue; + } + } + return s; //String + }, + + toObject: function(){ + // summary: + // Return an object representation of the element + // description: + // An object with properties for child elements, attributes and + // text is returned. + // returns: + // An object representation of the element + if(!this.element){ + return null; //null + } + var text = ""; + var obj = {}; + var elements = 0; + for(var i = 0; i < this.element.childNodes.length; i++){ + var child = this.element.childNodes[i]; + if(child.nodeType === 1 /* ELEMENT_NODE */){ + elements++; + var o = new dojox.wire.ml.XmlElement(child).toObject(); + var name = child.nodeName; + var p = obj[name]; + if(!p){ + obj[name] = o; + }else if(dojo.isArray(p)){ + p.push(o); + }else{ + obj[name] = [p, o]; // make them array + } + }else if(child.nodeType === 3 /* TEXT_NODE */ || + child.nodeType === 4 /* CDATA_SECTION_NODE */){ + text += child.nodeValue; + } + } + var attributes = 0; + if(this.element.nodeType === 1 /* ELEMENT_NODE */){ + attributes = this.element.attributes.length; + for(var i = 0; i < attributes; i++){ + var attr = this.element.attributes[i]; + obj["@" + attr.nodeName] = attr.nodeValue; + } + } + if(elements === 0){ + if(attributes === 0){ + // text only + return text; //String + } + // text with attributes + obj["text()"] = text; + } + // else ignore text + return obj; //Object + }, + + _getDocument: function(){ + // summary: + // Return a DOM document + // description: + // If 'element' is specified, a DOM document of the element is + // returned. + // Otherwise, a DOM document is created. + // returns: + // A DOM document + if(this.element){ + return (this.element.nodeType == 9 /* DOCUMENT_NODE */ ? + this.element : this.element.ownerDocument); //Document + }else{ + return dojox.data.dom.createDocument(); //Document + } + } +}); + +} diff --git a/includes/js/dojox/wire/tests/markup/Action.html b/includes/js/dojox/wire/tests/markup/Action.html new file mode 100644 index 0000000..75cbd49 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Action.html @@ -0,0 +1,147 @@ +<html> +<head> +<title>Test Action</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.Action"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.wire.ml.Action"); +dojo.require("dojox.wire.ml.Transfer"); + +dojox.wire.ml.tests.markup.Action = { + transfer: function(){}, + source: {a: "A", b: "B"} +}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.Action", [ + function test_Action_triggerEvent(t){ + dojox.wire.ml.tests.markup.Action.target = {}; + dojox.wire.ml.tests.markup.Action.transfer(); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.b, dojox.wire.ml.tests.markup.Action.target.b); + }, + + function test_Action_triggerTopic(t){ + dojox.wire.ml.tests.markup.Action.target = {}; + dojo.publish("transfer"); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + }, + + function test_ActionFilter_required(t){ + dojox.wire.ml.tests.markup.Action.target = {}; + dojo.publish("transferFilter"); + t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a); + t.assertEqual("no required", dojox.wire.ml.tests.markup.Action.error); + dojox.wire.ml.tests.markup.Action.required = true; + dojo.publish("transferFilter"); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + }, + + function test_ActionFilter_requiredSpecificNumber(t){ + dojox.wire.ml.tests.markup.Action.value = null + dojox.wire.ml.tests.markup.Action.target = {}; + dojo.publish("transferFilterNumber"); + + t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a); + + dojox.wire.ml.tests.markup.Action.value = 20; + dojo.publish("transferFilterNumber"); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + }, + + function test_ActionFilter_requiredSpecificBoolean(t){ + dojox.wire.ml.tests.markup.Action.value = null; + dojox.wire.ml.tests.markup.Action.target = {}; + dojo.publish("transferFilterBoolean"); + + t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a); + + dojox.wire.ml.tests.markup.Action.value = true; + dojo.publish("transferFilterBoolean"); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + }, + + function test_ActionFilter_requiredSpecificString(t){ + dojox.wire.ml.tests.markup.Action.target = {}; + dojox.wire.ml.tests.markup.Action.value = null; + dojo.publish("transferFilterString"); + + t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a); + + dojox.wire.ml.tests.markup.Action.value = "executeThis"; + dojo.publish("transferFilterString"); + t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a); + } + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.Action" + trigger="dojox.wire.ml.tests.markup.Action" + triggerEvent="transfer"> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.b" + target="dojox.wire.ml.tests.markup.Action.target.b"></div> +</div> +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transfer"> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> +</div> +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferFilter"> + <div dojoType="dojox.wire.ml.ActionFilter" + required="dojox.wire.ml.tests.markup.Action.required" + message="no required" + error="dojox.wire.ml.tests.markup.Action.error"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> +</div> + +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferFilterNumber"> + <div dojoType="dojox.wire.ml.ActionFilter" + required="dojox.wire.ml.tests.markup.Action.value" + requiredValue="20" + type="number"> + </div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> +</div> + +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferFilterBoolean"> + <div dojoType="dojox.wire.ml.ActionFilter" + required="dojox.wire.ml.tests.markup.Action.value" + requiredValue="true" + type="boolean"> + </div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> +</div> + +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferFilterString"> + <div dojoType="dojox.wire.ml.ActionFilter" + required="dojox.wire.ml.tests.markup.Action.value" + requiredValue="executeThis"> + </div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Action.source.a" + target="dojox.wire.ml.tests.markup.Action.target.a"></div> +</div> + +</body> +</html> diff --git a/includes/js/dojox/wire/tests/markup/Data.html b/includes/js/dojox/wire/tests/markup/Data.html new file mode 100644 index 0000000..b1107c0 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Data.html @@ -0,0 +1,105 @@ +<html> +<head> +<title>Test Data</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.Data"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.wire.ml.Action"); +dojo.require("dojox.wire.ml.Data"); +dojo.require("dojox.wire.ml.Transfer"); + +dojox.wire.ml.tests.markup.Data = {}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.Data", [ + + function test_DataProperty(t){ + dojox.wire.ml.tests.markup.Data.target = {}; + dojo.publish("transfer"); + t.assertEqual("A", dojox.wire.ml.tests.markup.Data.target.a); + t.assertEqual(1, dojox.wire.ml.tests.markup.Data.target.b); + t.assertEqual(true, dojox.wire.ml.tests.markup.Data.target.c); + t.assertEqual("DA", dojox.wire.ml.tests.markup.Data.target.d.a); + t.assertEqual("DB", dojox.wire.ml.tests.markup.Data.target.d.b); + t.assertEqual("E1", dojox.wire.ml.tests.markup.Data.target.e[0]); + t.assertEqual("E2", dojox.wire.ml.tests.markup.Data.target.e[1]); + t.assertEqual("F", dojox.wire.ml.tests.markup.Data.target.f); + t.assertEqual("G", dojox.wire.ml.tests.markup.Data.target.g); + } + + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.Data" + id="Data1"> + <div dojoType="dojox.wire.ml.DataProperty" + name="a" + value="A"></div> + <div dojoType="dojox.wire.ml.DataProperty" + name="b" + type="number" value="1"></div> + <div dojoType="dojox.wire.ml.DataProperty" + name="c" + type="boolean" value="true"></div> + <div dojoType="dojox.wire.ml.DataProperty" + name="d" + type="object"> + <div dojoType="dojox.wire.ml.DataProperty" + name="a" + value="DA"></div> + <div dojoType="dojox.wire.ml.DataProperty" + name="b" + value="DB"></div> + </div> + <div dojoType="dojox.wire.ml.DataProperty" + name="e" + type="array"> + <div dojoType="dojox.wire.ml.DataProperty" + value="E1"></div> + <div dojoType="dojox.wire.ml.DataProperty" + value="E2"></div> + </div> + <div dojoType="dojox.wire.ml.DataProperty" + name="f" + type="element" + value="x"> + <div dojoType="dojox.wire.ml.DataProperty" + name="text()" + value="F"></div> + <div dojoType="dojox.wire.ml.DataProperty" + name="@y" + value="G"></div> + </div> +</div> +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transfer"> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.a" + target="dojox.wire.ml.tests.markup.Data.target.a"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.b" + target="dojox.wire.ml.tests.markup.Data.target.b"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.c" + target="dojox.wire.ml.tests.markup.Data.target.c"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.d" + target="dojox.wire.ml.tests.markup.Data.target.d"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.e" + target="dojox.wire.ml.tests.markup.Data.target.e"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.f" + target="dojox.wire.ml.tests.markup.Data.target.f"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="Data1.f.@y" + target="dojox.wire.ml.tests.markup.Data.target.g"></div> +</div> +</body> +</html> diff --git a/includes/js/dojox/wire/tests/markup/DataStore.html b/includes/js/dojox/wire/tests/markup/DataStore.html new file mode 100644 index 0000000..3c55f7e --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/DataStore.html @@ -0,0 +1,66 @@ +<html> +<head> +<title>Test DataStore</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.DataStore"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.wire.ml.DataStore"); +dojo.require("dojox.wire.ml.Invocation"); +dojo.require("dojox.wire.ml.Transfer"); + +dojox.wire.ml.tests.markup.DataStore = { + request: {onComplete: function(){}, onError: function(){}} +}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.DataStore", [ + + function test_DataStore_url(t){ + var d = new doh.Deferred(); + dojo.connect(dojox.wire.ml.tests.markup.DataStore.request, "onComplete", function(){ + t.assertEqual("X1", dojox.wire.ml.tests.markup.DataStore.target[0].a); + t.assertEqual("Y2", dojox.wire.ml.tests.markup.DataStore.target[1].b); + t.assertEqual("Z3", dojox.wire.ml.tests.markup.DataStore.target[2].c); + d.callback(true); + }); + dojo.connect(dojox.wire.ml.tests.markup.DataStore.request, "onError", function(error){ + d.errback(error); + }); + dojo.publish("invokeFetch"); + return d; + } + + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.DataStore" + id="DataStore1" + storeClass="dojox.data.XmlStore" + url="DataStore.xml"></div> +<div dojoType="dojox.wire.ml.Invocation" + triggerTopic="invokeFetch" + object="DataStore1" + method="fetch" + parameters="dojox.wire.ml.tests.markup.DataStore.request"> +</div> +<div dojoType="dojox.wire.ml.Transfer" + trigger="dojox.wire.ml.tests.markup.DataStore.request" + triggerEvent="onComplete" + source="arguments[0]" + sourceStore="DataStore1.store" + target="dojox.wire.ml.tests.markup.DataStore.target"> + <div dojoType="dojox.wire.ml.ColumnWire" + column="a" attribute="x"></div> + <div dojoType="dojox.wire.ml.ColumnWire" + column="b" attribute="y"></div> + <div dojoType="dojox.wire.ml.ColumnWire" + column="c" attribute="z"></div> +</div> +</body> +</html> diff --git a/includes/js/dojox/wire/tests/markup/DataStore.xml b/includes/js/dojox/wire/tests/markup/DataStore.xml new file mode 100644 index 0000000..eeff4c2 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/DataStore.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<dataStore> + <item> + <x>X1</x> + <y>Y1</y> + <z>Z1</z> + </item> + <item> + <x>X2</x> + <y>Y2</y> + <z>Z2</z> + </item> + <item> + <x>X3</x> + <y>Y3</y> + <z>Z3</z> + </item> +</dataStore> diff --git a/includes/js/dojox/wire/tests/markup/Invocation.html b/includes/js/dojox/wire/tests/markup/Invocation.html new file mode 100644 index 0000000..dd6f6e4 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Invocation.html @@ -0,0 +1,53 @@ +<html> +<head> +<title>Test Invocation</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad:true "></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.Invocation"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.wire.ml.Invocation"); + +dojox.wire.ml.tests.markup.Invocation = { + invoke: function(p1, p2){return p1 + p2;}, + invokeError: function(p){throw new Error(p);}, + parameters: {a: "A", b: "B", c: "C"} +}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.Invocation", [ + + function test_Invocation_method(t){ + dojo.publish("invokeMethod"); + t.assertEqual("AB", dojox.wire.ml.tests.markup.Invocation.result); + }, + + function test_Invocation_topic(t){ + dojo.publish("invokeTopic"); + t.assertEqual("C", dojox.wire.ml.tests.markup.Invocation.error); + } + + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.Invocation" + triggerTopic="invokeMethod" + object="dojox.wire.ml.tests.markup.Invocation" + method="invoke" + parameters="dojox.wire.ml.tests.markup.Invocation.parameters.a,dojox.wire.ml.tests.markup.Invocation.parameters.b" + result="dojox.wire.ml.tests.markup.Invocation.result"></div> +<div dojoType="dojox.wire.ml.Invocation" + triggerTopic="invokeTopic" + topic="invokeError" + parameters="dojox.wire.ml.tests.markup.Invocation.parameters.c"></div> +<div dojoType="dojox.wire.ml.Invocation" + triggerTopic="invokeError" + object="dojox.wire.ml.tests.markup.Invocation" + method="invokeError" + error="dojox.wire.ml.tests.markup.Invocation.error"></div> +</body> +</html> diff --git a/includes/js/dojox/wire/tests/markup/Service.html b/includes/js/dojox/wire/tests/markup/Service.html new file mode 100644 index 0000000..0448c61 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Service.html @@ -0,0 +1,84 @@ +<html> +<head> +<title>Test Service</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.Service"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.wire.ml.Service"); +dojo.require("dojox.wire.ml.Invocation"); +dojo.require("dojox.wire.ml.Transfer"); + +dojox.wire.ml.tests.markup.Service = { + query: {name: "a"} +}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.Service", [ + + function test_Service_url(t){ + var d = new doh.Deferred(); + dojo.connect(dijit.byId("Invocation1"), "onComplete", function(result){ + t.assertEqual("a", dojox.wire.ml.tests.markup.Service.target.a); + var o = result.toObject(); + t.assertEqual("a", o.item.name); // test XmlElement.toObject() + t.assertEqual("b", o.item.data); // test XmlElement.toObject() + + d.callback(true); + }); + dojo.connect(dijit.byId("Invocation1"), "onError", function(error){ + d.errback(error); + }); + dojo.publish("invokeGetXml"); + return d; + }, + + function test_Service_serviceUrl(t){ + var d = new doh.Deferred(); + dojo.connect(dijit.byId("Invocation2"), "onComplete", function(){ + t.assertEqual("a", dojox.wire.ml.tests.markup.Service.result.item.name); + d.callback(true); + }); + dojo.connect(dijit.byId("Invocation2"), "onError", function(error){ + d.errback(error); + }); + dojo.publish("invokeGetJson"); + return d; + } + + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.Service" + id="Service1" + url="Service/XML.smd"></div> +<div dojoType="dojox.wire.ml.Invocation" + id="Invocation1" + triggerTopic="invokeGetXml" + object="Service1" + method="get" + parameters="dojox.wire.ml.tests.markup.Service.query"> +</div> +<div dojoType="dojox.wire.ml.Transfer" + trigger="Invocation1" + triggerEvent="onComplete" + source="arguments[0].item.name" + target="dojox.wire.ml.tests.markup.Service.target.a"></div> +<div dojoType="dojox.wire.ml.Service" + id="Service2" + serviceType="JSON" + serviceUrl="Service/{name}.json"></div> +<div dojoType="dojox.wire.ml.Invocation" + id="Invocation2" + triggerTopic="invokeGetJson" + object="Service2" + method="get" + parameters="dojox.wire.ml.tests.markup.Service.query" + result="dojox.wire.ml.tests.markup.Service.result"></div> +</body> +</html> diff --git a/includes/js/dojox/wire/tests/markup/Service/JSON.smd b/includes/js/dojox/wire/tests/markup/Service/JSON.smd new file mode 100644 index 0000000..2ac9682 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Service/JSON.smd @@ -0,0 +1,11 @@ +{ + "serviceType": "JSON", + "serviceURL": "Service/{name}.json", + "methods": [{ + "name": "get", + "parameters": [{ + "name": "name", + "type": "str" + }] + }] +} diff --git a/includes/js/dojox/wire/tests/markup/Service/XML.smd b/includes/js/dojox/wire/tests/markup/Service/XML.smd new file mode 100644 index 0000000..d833f88 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Service/XML.smd @@ -0,0 +1,11 @@ +{ + "serviceType": "XML", + "serviceURL": "Service/{name}.xml", + "methods": [{ + "name": "get", + "parameters": [{ + "name": "name", + "type": "str" + }] + }] +} diff --git a/includes/js/dojox/wire/tests/markup/Service/a.json b/includes/js/dojox/wire/tests/markup/Service/a.json new file mode 100644 index 0000000..93fc00b --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Service/a.json @@ -0,0 +1,5 @@ +{ + "item": { + "name": "a" + } +} diff --git a/includes/js/dojox/wire/tests/markup/Service/a.xml b/includes/js/dojox/wire/tests/markup/Service/a.xml new file mode 100644 index 0000000..21e4367 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Service/a.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<item> + <name>a</name> + <data><![CDATA[b]]></data> +</item> diff --git a/includes/js/dojox/wire/tests/markup/Transfer.html b/includes/js/dojox/wire/tests/markup/Transfer.html new file mode 100644 index 0000000..3ec11a4 --- /dev/null +++ b/includes/js/dojox/wire/tests/markup/Transfer.html @@ -0,0 +1,157 @@ +<html> +<head> +<title>Test Transfer</title> +<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script> +<script type="text/javascript"> +dojo.provide("dojox.wire.ml.tests.markup.Transfer"); + +dojo.require("dojo.parser"); +dojo.require("doh.runner"); +dojo.require("dojox.data.dom"); +dojo.require("dojox.data.XmlStore"); +dojo.require("dojox.wire.ml.Action"); +dojo.require("dojox.wire.ml.Transfer"); + +dojox.wire.ml.tests.markup.Transfer = { + source: {a: "A", b: "B", c: [ + {d: "D1", e: "E1"}, + {d: "D2", e: "E2"} + ]} +}; + +dojo.addOnLoad(function(){ + doh.register("dojox.wire.ml.tests.markup.Transfer", [ + + function test_Transfer_attribute(t){ + dojox.wire.ml.tests.markup.Transfer.store = new dojox.data.XmlStore(); + dojox.wire.ml.tests.markup.Transfer.item = dojox.wire.ml.tests.markup.Transfer.store.newItem({tagName: "x"}); + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferData"); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.a); + }, + + function test_Transfer_path(t){ + dojox.wire.ml.tests.markup.Transfer.element = dojox.data.dom.createDocument().createElement("x"); + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferXml"); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.a); + }, + + function test_ChildWire(t){ + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferComposite"); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.c); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.b, dojox.wire.ml.tests.markup.Transfer.target.d); + }, + + function test_ColumnWire(t){ + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferTable"); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[0].d, dojox.wire.ml.tests.markup.Transfer.target.a[0].b); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[1].e, dojox.wire.ml.tests.markup.Transfer.target.a[1].c); + }, + + function test_NodeWire(t){ + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferTree"); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[0].d, dojox.wire.ml.tests.markup.Transfer.target.a[0].title); + t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[1].e, dojox.wire.ml.tests.markup.Transfer.target.a[1].children[0].title); + }, + + function test_SegimentWire(t){ + dojox.wire.ml.tests.markup.Transfer.target = {}; + dojo.publish("transferText"); + t.assertEqual("A/B", dojox.wire.ml.tests.markup.Transfer.target.c); + } + + ]); + doh.run(); +}); +</script> +</head> +<body> +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferData"> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.source.a" + target="dojox.wire.ml.tests.markup.Transfer.item" + targetStore="dojox.wire.ml.tests.markup.Transfer.store" + targetAttribute="y"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.item" + sourceStore="dojox.wire.ml.tests.markup.Transfer.store" + sourceAttribute="y" + target="dojox.wire.ml.tests.markup.Transfer.target.a"></div> +</div> +<div dojoType="dojox.wire.ml.Action" + triggerTopic="transferXml"> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.source.a" + target="dojox.wire.ml.tests.markup.Transfer.element" + targetPath="y/text()"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.element" + sourcePath="y/text()" + target="dojox.wire.ml.tests.markup.Transfer.target.a"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.source.b" + target="dojox.wire.ml.tests.markup.Transfer.element" + targetPath="y/@z"></div> + <div dojoType="dojox.wire.ml.Transfer" + source="dojox.wire.ml.tests.markup.Transfer.element" + sourcePath="y/@z" + target="dojox.wire.ml.tests.markup.Transfer.target.b"></div> +</div> +<div dojoType="dojox.wire.ml.Transfer" + triggerTopic="transferComposite" + source="dojox.wire.ml.tests.markup.Transfer.source" + target="dojox.wire.ml.tests.markup.Transfer.target"> + <div dojoType="dojox.wire.ml.ChildWire" + name="x" + property="a"></div> + <div dojoType="dojox.wire.ml.ChildWire" + which="source" + name="y" + property="b"></div> + <div dojoType="dojox.wire.ml.ChildWire" + which="target" + name="x" + property="c"></div> + <div dojoType="dojox.wire.ml.ChildWire" + which="target" + name="y" + property="d"></div> +</div> +<div dojoType="dojox.wire.ml.Transfer" + triggerTopic="transferTable" + source="dojox.wire.ml.tests.markup.Transfer.source.c" + target="dojox.wire.ml.tests.markup.Transfer.target.a"> + <div dojoType="dojox.wire.ml.ColumnWire" + column="b" + property="d"></div> + <div dojoType="dojox.wire.ml.ColumnWire" + column="c" + property="e"></div> +</div> +<div dojoType="dojox.wire.ml.Transfer" + triggerTopic="transferTree" + source="dojox.wire.ml.tests.markup.Transfer.source.c" + target="dojox.wire.ml.tests.markup.Transfer.target.a"> + <div dojoType="dojox.wire.ml.NodeWire" + titleProperty="d"> + <div dojoType="dojox.wire.ml.NodeWire" + titleProperty="e"></div> + </div> +</div> +<div dojoType="dojox.wire.ml.Transfer" + triggerTopic="transferText" + source="dojox.wire.ml.tests.markup.Transfer.source" + delimiter="/" + target="dojox.wire.ml.tests.markup.Transfer.target.c"> + <div dojoType="dojox.wire.ml.SegmentWire" + property="a"></div> + <div dojoType="dojox.wire.ml.SegmentWire" + property="b"></div> +</div> +</body> +</html> diff --git a/includes/js/dojox/wire/tests/module.js b/includes/js/dojox/wire/tests/module.js new file mode 100644 index 0000000..17f10c3 --- /dev/null +++ b/includes/js/dojox/wire/tests/module.js @@ -0,0 +1,13 @@ +if(!dojo._hasResource["dojox.wire.tests.module"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.module"] = true; +dojo.provide("dojox.wire.tests.module"); + +try{ + dojo.require("dojox.wire.tests.wire"); + dojo.require("dojox.wire.tests.wireml"); +}catch(e){ + doh.debug(e); +} + + +} diff --git a/includes/js/dojox/wire/tests/programmatic/CompositeWire.js b/includes/js/dojox/wire/tests/programmatic/CompositeWire.js new file mode 100644 index 0000000..ae9866a --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/CompositeWire.js @@ -0,0 +1,51 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.CompositeWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.CompositeWire"] = true; +dojo.provide("dojox.wire.tests.programmatic.CompositeWire"); + +dojo.require("dojox.wire.CompositeWire"); + +tests.register("dojox.wire.tests.programmatic.CompositeWire", [ + + function test_CompositeWire_children(t){ + var source = {a: "A", b: "B"}; + var target = {}; + var children = {x: {property: "a"}, y: {property: "b"}}; + var value = new dojox.wire.CompositeWire({object: source, children: children}).getValue(); + t.assertEqual(source.a, value.x); + t.assertEqual(source.b, value.y); + new dojox.wire.CompositeWire({object: target, children: children}).setValue(value); + t.assertEqual(source.a, target.a); + t.assertEqual(source.b, target.b); + + // with argument + target = {}; + value = new dojox.wire.CompositeWire({children: children}).getValue(source); + t.assertEqual(source.a, value.x); + t.assertEqual(source.b, value.y); + new dojox.wire.CompositeWire({children: children}).setValue(value, target); + t.assertEqual(source.a, target.a); + t.assertEqual(source.b, target.b); + + // by array + target = {}; + children = [{property: "a"}, {property: "b"}]; + value = new dojox.wire.CompositeWire({object: source, children: children}).getValue(); + t.assertEqual(source.a, value[0]); + t.assertEqual(source.b, value[1]); + new dojox.wire.CompositeWire({object: target, children: children}).setValue(value); + t.assertEqual(source.a, target.a); + t.assertEqual(source.b, target.b); + + // by array with argument + target = {}; + value = new dojox.wire.CompositeWire({children: children}).getValue(source); + t.assertEqual(source.a, value[0]); + t.assertEqual(source.b, value[1]); + new dojox.wire.CompositeWire({children: children}).setValue(value, target); + t.assertEqual(source.a, target.a); + t.assertEqual(source.b, target.b); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/ConverterDynamic.js b/includes/js/dojox/wire/tests/programmatic/ConverterDynamic.js new file mode 100644 index 0000000..2665148 --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/ConverterDynamic.js @@ -0,0 +1,12 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.ConverterDynamic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.ConverterDynamic"] = true; +dojo.provide("dojox.wire.tests.programmatic.ConverterDynamic"); + +dojo.declare("dojox.wire.tests.programmatic.ConverterDynamic", null, { + convert: function(v){ + return v + 1; + } +}); + + +} diff --git a/includes/js/dojox/wire/tests/programmatic/DataWire.js b/includes/js/dojox/wire/tests/programmatic/DataWire.js new file mode 100644 index 0000000..b146901 --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/DataWire.js @@ -0,0 +1,25 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.DataWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.DataWire"] = true; +dojo.provide("dojox.wire.tests.programmatic.DataWire"); + +dojo.require("dojox.wire.DataWire"); +dojo.require("dojox.data.XmlStore"); + +tests.register("dojox.wire.tests.programmatic.DataWire", [ + + function test_DataWire_attribute(t){ + var store = new dojox.data.XmlStore(); + var item = store.newItem({tagName: "x"}); + new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y"}).setValue("Y"); + var value = new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y"}).getValue(); + t.assertEqual("Y", value); + + // nested attribute + new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y.z"}).setValue("Z"); + value = new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y.z"}).getValue(); + t.assertEqual("Z", value); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/TableAdapter.js b/includes/js/dojox/wire/tests/programmatic/TableAdapter.js new file mode 100644 index 0000000..9e6adc1 --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/TableAdapter.js @@ -0,0 +1,24 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.TableAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.TableAdapter"] = true; +dojo.provide("dojox.wire.tests.programmatic.TableAdapter"); + +dojo.require("dojox.wire.TableAdapter"); + +tests.register("dojox.wire.tests.programmatic.TableAdapter", [ + + function test_TableAdapter_columns(t){ + var source = [ + {a: "A1", b: "B1", c: "C1"}, + {a: "A2", b: "B2", c: "C2"}, + {a: "A3", b: "B3", c: "C3"} + ]; + var columns = {x: {property: "a"}, y: {property: "b"}, z: {property: "c"}}; + var value = new dojox.wire.TableAdapter({object: source, columns: columns}).getValue(); + t.assertEqual(source[0].a, value[0].x); + t.assertEqual(source[1].b, value[1].y); + t.assertEqual(source[2].c, value[2].z); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/TextAdapter.js b/includes/js/dojox/wire/tests/programmatic/TextAdapter.js new file mode 100644 index 0000000..1014b5c --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/TextAdapter.js @@ -0,0 +1,25 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.TextAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.TextAdapter"] = true; +dojo.provide("dojox.wire.tests.programmatic.TextAdapter"); + +dojo.require("dojox.wire.TextAdapter"); + +tests.register("dojox.wire.tests.programmatic.TextAdapter", [ + + function test_TextAdapter_segments(t){ + var source = {a: "a", b: "b", c: "c"}; + var segments = [{property: "a"}, {property: "b"}, {property: "c"}]; + var value = new dojox.wire.TextAdapter({object: source, segments: segments}).getValue(); + t.assertEqual("abc", value); + }, + + function test_TextAdapter_delimiter(t){ + var source = {a: "a", b: "b", c: "c"}; + var segments = [{property: "a"}, {property: "b"}, {property: "c"}]; + var value = new dojox.wire.TextAdapter({object: source, segments: segments, delimiter: "/"}).getValue(); + t.assertEqual("a/b/c", value); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/TreeAdapter.js b/includes/js/dojox/wire/tests/programmatic/TreeAdapter.js new file mode 100644 index 0000000..e1671ed --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/TreeAdapter.js @@ -0,0 +1,29 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.TreeAdapter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.TreeAdapter"] = true; +dojo.provide("dojox.wire.tests.programmatic.TreeAdapter"); + +dojo.require("dojox.wire.TreeAdapter"); + +tests.register("dojox.wire.tests.programmatic.TreeAdapter", [ + + function test_TreeAdapter_nodes(t){ + var source = [ + {a: "A1", b: "B1", c: "C1"}, + {a: "A2", b: "B2", c: "C2"}, + {a: "A3", b: "B3", c: "C3"} + ]; + var nodes = [ + {title: {property: "a"}, children: [ + {node: {property: "b"}}, + {title: {property: "c"}} + ]} + ]; + var value = new dojox.wire.TreeAdapter({object: source, nodes: nodes}).getValue(); + t.assertEqual(source[0].a, value[0].title); + t.assertEqual(source[1].b, value[1].children[0].title); + t.assertEqual(source[2].c, value[2].children[1].title); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/Wire.js b/includes/js/dojox/wire/tests/programmatic/Wire.js new file mode 100644 index 0000000..25a82ec --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/Wire.js @@ -0,0 +1,123 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.Wire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.Wire"] = true; +dojo.provide("dojox.wire.tests.programmatic.Wire"); +dojo.require("dojox.wire.Wire"); + +//Simple connverter class to try to use. +dojo.declare("dojox.wire.tests.programmatic.Wire.Converter", null, { + convert: function(v){ + return v + 1; + } +}); + +//Simple converter function to try to use. +//To get it in the global namespace, gotta assign it to the +//'window' toplevel object. Otherwise it ends up in the +//dojo NS and can't be found. +if (dojo.isBrowser) { + window["__wireTestConverterFunction"] = function(v){ + return v + 1; + }; +}else{ + var __wireTestConverterFunction = function(v){ + return v + 1; + }; +} + +tests.register("dojox.wire.tests.programmatic.Wire", [ + + function test_Wire_property(t){ + var source = {a: "A", b: {c: "B.C"}}; + var target = {a: "a", b: {c: "b.c"}}; + var value = new dojox.wire.Wire({object: source, property: "a"}).getValue(); + new dojox.wire.Wire({object: target, property: "a"}).setValue(value); + t.assertEqual(source.a, target.a); + + // child property + value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue(); + new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value); + t.assertEqual(source.b.c, target.b.c); + + // new property + target = {}; + value = new dojox.wire.Wire({object: source, property: "a"}).getValue(); + new dojox.wire.Wire({object: target, property: "a"}).setValue(value); + t.assertEqual(source.a, target.a); + + // new parent and child property + target.b = {}; + value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue(); + new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value); + t.assertEqual(source.b.c, target.b.c); + + // new parent and child property + target = {}; + value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue(); + new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value); + t.assertEqual(source.b.c, target.b.c); + + // new array property + source = {a: ["A"]}; + target = {}; + value = new dojox.wire.Wire({object: source, property: "a[0]"}).getValue(); + new dojox.wire.Wire({object: target, property: "a[0]"}).setValue(value); + t.assertEqual(source.a[0], target.a[0]); + + // by getter/setter + source = {getA: function() { return this._a; }, _a: "A"}; + target = {setA: function(a) { this._a = a; }}; + value = new dojox.wire.Wire({object: source, property: "a"}).getValue(); + new dojox.wire.Wire({object: target, property: "a"}).setValue(value); + t.assertEqual(source._a, target._a); + + // by get/setPropertyValue + source = {getPropertyValue: function(p) { return this["_" + p]; }, _a: "A"}; + target = {setPropertyValue: function(p, v) { this["_" + p] = v; }}; + value = new dojox.wire.Wire({object: source, property: "a"}).getValue(); + new dojox.wire.Wire({object: target, property: "a"}).setValue(value); + t.assertEqual(source._a, target._a); + }, + + function test_Wire_type(t){ + var source = {a: "1"}; + var string = new dojox.wire.Wire({object: source, property: "a"}).getValue(); + t.assertEqual("11", string + 1); + var number = new dojox.wire.Wire({object: source, property: "a", type: "number"}).getValue(); + t.assertEqual(2, number + 1); + }, + + function test_Wire_converterObject(t){ + var source = {a: "1"}; + var converter = {convert: function(v) { return v + 1; }}; + var string = new dojox.wire.Wire({object: source, property: "a", converter: converter}).getValue(); + t.assertEqual("11", string); + }, + + function test_Wire_converterFunction(t){ + var source = {a: "1"}; + var converter = {convert: function(v) { return v + 1; }}; + var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: converter.convert}).getValue(); + t.assertEqual(2, number); + }, + + function test_Wire_converterObjectByString(t){ + var source = {a: "1"}; + var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "dojox.wire.tests.programmatic.Wire.Converter"}).getValue(); + t.assertEqual(2, number); + }, + + function test_Wire_converterFunctionByString(t){ + var source = {a: "1"}; + var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "__wireTestConverterFunction"}).getValue(); + t.assertEqual(2, number); + }, + + function test_Wire_converterObjectByStringDynamic(t){ + var source = {a: "1"}; + var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "dojox.wire.tests.programmatic.ConverterDynamic"}).getValue(); + t.assertEqual(2, number); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/XmlWire.js b/includes/js/dojox/wire/tests/programmatic/XmlWire.js new file mode 100644 index 0000000..b0772d7 --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/XmlWire.js @@ -0,0 +1,32 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic.XmlWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic.XmlWire"] = true; +dojo.provide("dojox.wire.tests.programmatic.XmlWire"); + +dojo.require("dojox.wire.XmlWire"); + +tests.register("dojox.wire.tests.programmatic.XmlWire", [ + + function test_XmlWire_path(t){ + var object = {}; + var wire = dojox.wire.create({object: object, property: "element"}); + new dojox.wire.XmlWire({object: wire, path: "/x/y/text()"}).setValue("Y"); + var value = new dojox.wire.XmlWire({object: object, property: "element", path: "y/text()"}).getValue(); + t.assertEqual("Y", value); + + // attribute + new dojox.wire.XmlWire({object: object, property: "element", path: "y/@z"}).setValue("Z"); + value = new dojox.wire.XmlWire({object: wire, path: "/x/y/@z"}).getValue(); + t.assertEqual("Z", value); + + // with index + var document = object.element.ownerDocument; + var element = document.createElement("y"); + element.appendChild(document.createTextNode("Y2")); + object.element.appendChild(element); + value = new dojox.wire.XmlWire({object: object.element, path: "y[2]/text()"}).getValue(); + t.assertEqual("Y2", value); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/programmatic/_base.js b/includes/js/dojox/wire/tests/programmatic/_base.js new file mode 100644 index 0000000..00f9abe --- /dev/null +++ b/includes/js/dojox/wire/tests/programmatic/_base.js @@ -0,0 +1,111 @@ +if(!dojo._hasResource["dojox.wire.tests.programmatic._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.programmatic._base"] = true; +dojo.provide("dojox.wire.tests.programmatic._base"); + +dojo.require("dojox.wire._base"); + +tests.register("dojox.wire.tests.programmatic._base", [ + + function test_create(t){ + var wire = dojox.wire.create({}); + t.assertTrue(wire instanceof dojox.wire.Wire); + + wire = dojox.wire.create({property: "a"}); + t.assertTrue(wire instanceof dojox.wire.Wire); + + wire = dojox.wire.create({attribute: "a"}); + t.assertTrue(wire instanceof dojox.wire.DataWire); + + wire = dojox.wire.create({path: "a"}); + t.assertTrue(wire instanceof dojox.wire.XmlWire); + + wire = dojox.wire.create({children: "a"}); + t.assertTrue(wire instanceof dojox.wire.CompositeWire); + + wire = dojox.wire.create({columns: "a"}); + t.assertTrue(wire instanceof dojox.wire.TableAdapter); + + wire = dojox.wire.create({nodes: "a"}); + t.assertTrue(wire instanceof dojox.wire.TreeAdapter); + + wire = dojox.wire.create({segments: "a"}); + t.assertTrue(wire instanceof dojox.wire.TextAdapter); + + wire = dojox.wire.create({wireClass: "dojox.wire.DataWire"}); + t.assertTrue(wire instanceof dojox.wire.DataWire); + }, + + function test_transfer(t){ + var source = {a: "A"}; + var target = {}; + dojox.wire.transfer( + {object: source, property: "a"}, + {object: target, property: "a"}); + t.assertEqual(source.a, target.a); + }, + + function test_connect(t){ + var trigger = {transfer: function() {}, transferArgument: function() {}}; + var source = {a: "A"}; + var target = {}; + dojox.wire.connect({scope: trigger, event: "transfer"}, + {object: source, property: "a"}, + {object: target, property: "a"}); + trigger.transfer(); + t.assertEqual(source.a, target.a); + + // with argument + target = {}; + dojox.wire.connect({scope: trigger, event: "transferArgument"}, + {property: "[0].a"}, + {object: target, property: "a"}); + trigger.transferArgument(source); + t.assertEqual(source.a, target.a); + + // by topic + target = {}; + dojox.wire.connect({topic: "transfer"}, + {object: source, property: "a"}, + {object: target, property: "a"}); + dojo.publish("transfer"); + t.assertEqual(source.a, target.a); + + // by topic with argument + target = {}; + dojox.wire.connect({topic: "transferArgument"}, + {property: "[0].a"}, + {object: target, property: "a"}); + dojo.publish("transferArgument", [source]); + t.assertEqual(source.a, target.a); + }, + + function test_disconnect(t){ + var trigger = {transferDisconnect: function() {}}; + var source = {a: "A"}; + var target = {}; + var connection = dojox.wire.connect({scope: trigger, event: "transferDisconnect"}, + {object: source, property: "a"}, + {object: target, property: "a"}); + trigger.transferDisconnect(); + t.assertEqual(source.a, target.a); + delete target.a; + dojox.wire.disconnect(connection); + trigger.transferDisconnect(); + t.assertEqual(undefined, target.a); + + // by topic + target = {}; + connection = dojox.wire.connect({topic: "transferDisconnect"}, + {object: source, property: "a"}, + {object: target, property: "a"}); + dojo.publish("transferDisconnect"); + t.assertEqual(source.a, target.a); + delete target.a; + dojox.wire.disconnect(connection); + dojo.publish("transferDisconnect"); + t.assertEqual(undefined, target.a); + } + +]); + +} diff --git a/includes/js/dojox/wire/tests/runTests.html b/includes/js/dojox/wire/tests/runTests.html new file mode 100644 index 0000000..f4a51de --- /dev/null +++ b/includes/js/dojox/wire/tests/runTests.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Dojox.wire Unit Test Runner</title> + <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.wire.tests.module"></HEAD> + <BODY> + Redirecting to D.O.H runner. + </BODY> +</HTML> diff --git a/includes/js/dojox/wire/tests/wire.js b/includes/js/dojox/wire/tests/wire.js new file mode 100644 index 0000000..e4e2a21 --- /dev/null +++ b/includes/js/dojox/wire/tests/wire.js @@ -0,0 +1,18 @@ +if(!dojo._hasResource["dojox.wire.tests.wire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.wire"] = true; +dojo.provide("dojox.wire.tests.wire"); + +try{ + dojo.require("dojox.wire.tests.programmatic._base"); + dojo.require("dojox.wire.tests.programmatic.Wire"); + dojo.requireIf(dojo.isBrowser, "dojox.wire.tests.programmatic.DataWire"); + dojo.requireIf(dojo.isBrowser, "dojox.wire.tests.programmatic.XmlWire"); + dojo.require("dojox.wire.tests.programmatic.CompositeWire"); + dojo.require("dojox.wire.tests.programmatic.TableAdapter"); + dojo.require("dojox.wire.tests.programmatic.TreeAdapter"); + dojo.require("dojox.wire.tests.programmatic.TextAdapter"); +}catch(e){ + doh.debug(e); +} + +} diff --git a/includes/js/dojox/wire/tests/wireml.js b/includes/js/dojox/wire/tests/wireml.js new file mode 100644 index 0000000..db47056 --- /dev/null +++ b/includes/js/dojox/wire/tests/wireml.js @@ -0,0 +1,18 @@ +if(!dojo._hasResource["dojox.wire.tests.wireml"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.wire.tests.wireml"] = true; +dojo.provide("dojox.wire.tests.wireml"); + +try{ + if(dojo.isBrowser){ + doh.registerUrl("dojox.wire.tests.ml.Action", dojo.moduleUrl("dojox", "wire/tests/markup/Action.html")); + doh.registerUrl("dojox.wire.tests.ml.Transfer", dojo.moduleUrl("dojox", "wire/tests/markup/Transfer.html")); + doh.registerUrl("dojox.wire.tests.ml.Invocation", dojo.moduleUrl("dojox", "wire/tests/markup/Invocation.html")); + doh.registerUrl("dojox.wire.tests.ml.Data", dojo.moduleUrl("dojox", "wire/tests/markup/Data.html")); + doh.registerUrl("dojox.wire.tests.ml.DataStore", dojo.moduleUrl("dojox", "wire/tests/markup/DataStore.html")); + doh.registerUrl("dojox.wire.tests.ml.Service", dojo.moduleUrl("dojox", "wire/tests/markup/Service.html")); + } +}catch(e){ + doh.debug(e); +} + +} |