From 541bb378ddece2eab135a8066a16994e94436dea Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Mon, 03 Oct 2011 16:04:12 +0000 Subject: Merge pull request #1 from gcsolaroli/master First version of the restructured repository --- (limited to 'frontend/beta/js/YUI-extensions/data/XMLDataModel.js') diff --git a/frontend/beta/js/YUI-extensions/data/XMLDataModel.js b/frontend/beta/js/YUI-extensions/data/XMLDataModel.js new file mode 100644 index 0000000..e312a9e --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/data/XMLDataModel.js @@ -0,0 +1,274 @@ +/** + * @class YAHOO.ext.grid.XMLDataModel + * This is an implementation of a DataModel used by the Grid. It works + * with XML data. + *
Example schema from Amazon search: + *

+ * var schema = {
+ *     tagName: 'Item',
+ *     id: 'ASIN',
+ *     fields: ['Author', 'Title', 'Manufacturer', 'ProductGroup']
+ * };
+ * 
+ * @extends YAHOO.ext.grid.LoadableDataModel + * @constructor + * @param {Object} schema The schema to use + * @param {XMLDocument} xml An XML document to load immediately +*/ +YAHOO.ext.grid.XMLDataModel = function(schema, xml){ + YAHOO.ext.grid.XMLDataModel.superclass.constructor.call(this, YAHOO.ext.grid.LoadableDataModel.XML); + /**@private*/ + this.schema = schema; + this.xml = xml; + if(xml){ + this.loadData(xml); + } + this.idSeed = 0; +}; +YAHOO.extendX(YAHOO.ext.grid.XMLDataModel, YAHOO.ext.grid.LoadableDataModel, { + + getDocument: function(){ + return this.xml; + }, + + /** + * Overrides loadData in LoadableDataModel to process XML + * @param {XMLDocument} doc The document to load + * @param {Function} callback (optional) callback to call when loading is complete + * @param {Boolean} keepExisting (optional) true to keep existing data + * @param {Number} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data + */ + loadData: function(doc, callback, keepExisting, insertIndex){ + this.xml = doc; + var idField = this.schema.id; + var fields = this.schema.fields; + if(this.schema.totalTag){ + this.totalCount = null; + var totalNode = doc.getElementsByTagName(this.schema.totalTag); + if(totalNode && totalNode.item(0) && totalNode.item(0).firstChild) { + var v = parseInt(totalNode.item(0).firstChild.nodeValue, 10); + if(!isNaN(v)){ + this.totalCount = v; + } + } + } + var rowData = []; + var nodes = doc.getElementsByTagName(this.schema.tagName); + if(nodes && nodes.length > 0) { + for(var i = 0; i < nodes.length; i++) { + var node = nodes.item(i); + var colData = []; + colData.node = node; + colData.id = this.getNamedValue(node, idField, String(++this.idSeed)); + for(var j = 0; j < fields.length; j++) { + var val = this.getNamedValue(node, fields[j], ""); + if(this.preprocessors[j]){ + val = this.preprocessors[j](val); + } + colData.push(val); + } + rowData.push(colData); + } + } + if(keepExisting !== true){ + YAHOO.ext.grid.XMLDataModel.superclass.removeAll.call(this); + } + if(typeof insertIndex != 'number'){ + insertIndex = this.getRowCount(); + } + YAHOO.ext.grid.XMLDataModel.superclass.insertRows.call(this, insertIndex, rowData); + if(typeof callback == 'function'){ + callback(this, true); + } + this.fireLoadEvent(); + }, + + /** + * Adds a row to this DataModel and syncs the XML document + * @param {String} id The id of the row, if null the next row index is used + * @param {Array} cellValues The cell values for this row + * @return {Number} The index of the new row (if the model is sorted this index may not be accurate) + */ + addRow: function(id, cellValues){ + var node = this.createNode(this.xml, id, cellValues); + cellValues.id = id || ++this.idSeed; + cellValues.node = node; + return YAHOO.ext.grid.XMLDataModel.superclass.addRow.call(this, cellValues); + }, + + /** + * Inserts a row into this DataModel and syncs the XML document + * @param {Number} index The index to insert the row + * @param {String} id The id of the row, if null the next row index is used + * @param {Array} cellValues The cell values for this row + * @return {Number} The index of the new row (if the model is sorted this index may not be accurate) + */ + insertRow: function(index, id, cellValues){ + var node = this.createNode(this.xml, id, cellValues); + cellValues.id = id || ++this.idSeed; + cellValues.node = node; + return YAHOO.ext.grid.XMLDataModel.superclass.insertRow.call(this, index, cellValues); + }, + + /** + * Removes the row from DataModel and syncs the XML document + * @param {Number} index The index of the row to remove + */ + removeRow: function(index){ + var node = this.data[index].node; + node.parentNode.removeChild(node); + YAHOO.ext.grid.XMLDataModel.superclass.removeRow.call(this, index, index); + }, + + getNode: function(rowIndex){ + return this.data[rowIndex].node; + }, + + /** + * Override this method to define your own node creation routine for when new rows are added. + * By default this method clones the first node and sets the column values in the newly cloned node. + * In many instances this will not work and you will have to create the node manually. + * @param {XMLDocument} xmlDoc The xml document being used by this model + * @param {String/Number} id The row id + * @param {Array} colData The column data for the new node + * @return {XMLNode} The created node + */ + createNode: function(xmlDoc, id, colData){ + var template = this.data[0].node; + var newNode = template.cloneNode(true); + var fields = this.schema.fields; + for(var i = 0, len = fields.length; i < len; i++){ + var nodeValue = colData[i]; + if(this.postprocessors[i]){ + nodeValue = this.postprocessors[i](nodeValue); + } + this.setNamedValue(newNode, fields[i], nodeValue); + } + if(id){ + this.setNamedValue(newNode, this.schema.idField, id); + } + template.parentNode.appendChild(newNode); + return newNode; + }, + + /** + * @private + * Convenience function looks for value in attributes, then in children tags - also + * normalizes namespace matches (ie matches ns:tag, FireFox matches tag and not ns:tag). + */ + getNamedValue: function(node, name, defaultValue){ + if(!node || !name){ + return defaultValue; + } + var nodeValue = defaultValue; + var attrNode = node.attributes.getNamedItem(name); + if(attrNode) { + nodeValue = attrNode.value; + } else { + var childNode = node.getElementsByTagName(name); + if(childNode && childNode.item(0) && childNode.item(0).firstChild) { + nodeValue = childNode.item(0).firstChild.nodeValue; + }else{ + // try to strip namespace for FireFox + var index = name.indexOf(':'); + if(index > 0){ + return this.getNamedValue(node, name.substr(index+1), defaultValue); + } + } + } + return nodeValue; + }, + + /** + * @private + * Convenience function set a value in the underlying xml node. + */ + setNamedValue: function(node, name, value){ + if(!node || !name){ + return; + } + var attrNode = node.attributes.getNamedItem(name); + if(attrNode) { + attrNode.value = value; + return; + } + var childNode = node.getElementsByTagName(name); + if(childNode && childNode.item(0) && childNode.item(0).firstChild) { + childNode.item(0).firstChild.nodeValue = value; + }else{ + // try to strip namespace for FireFox + var index = name.indexOf(':'); + if(index > 0){ + this.setNamedValue(node, name.substr(index+1), value); + } + } + }, + + /** + * Overrides DefaultDataModel.setValueAt to update the underlying XML Document + * @param {Object} value The new value + * @param {Number} rowIndex + * @param {Number} colIndex + */ + setValueAt: function(value, rowIndex, colIndex){ + var node = this.data[rowIndex].node; + if(node){ + var nodeValue = value; + if(this.postprocessors[colIndex]){ + nodeValue = this.postprocessors[colIndex](value); + } + this.setNamedValue(node, this.schema.fields[colIndex], nodeValue); + } + YAHOO.ext.grid.XMLDataModel.superclass.setValueAt.call(this, value, rowIndex, colIndex); + }, + + /** + * Overrides getRowId in DefaultDataModel to return the ID value of the specified node. + * @param {Number} rowIndex + * @return {Number} + */ + getRowId: function(rowIndex){ + return this.data[rowIndex].id; + }, + + addRows : function(rowData){ + for(var j = 0, len = rowData.length; j < len; j++){ + var cellValues = rowData[j]; + var id = ++this.idSeed; + var node = this.createNode(this.xml, id, cellValues); + cellValues.node=node; + cellValues.id = cellValues.id || id; + YAHOO.ext.grid.XMLDataModel.superclass.addRow.call(this,cellValues); + } + }, + + insertRows : function(index, rowData){ + // copy original array so it is not reversed + rowData = rowData.slice(0).reverse(); + for(var j = 0, len = rowData.length; j < len; j++){ + var cellValues = rowData[j]; + var id = ++this.idSeed; + var node = this.createNode(this.xml, id, cellValues); + cellValues.id = cellValues.id || id; + cellValues.node = node; + YAHOO.ext.grid.XMLDataModel.superclass.insertRow.call(this, index, cellValues); + } + } +}); + +YAHOO.ext.grid.XMLQueryDataModel = function(){ + YAHOO.ext.grid.XMLQueryDataModel.superclass.constructor.apply(this, arguments); +}; +YAHOO.extendX(YAHOO.ext.grid.XMLQueryDataModel, YAHOO.ext.grid.XMLDataModel, { + getNamedValue: function(node, name, defaultValue){ + if(!node || !name){ + return defaultValue; + } + var nodeValue = defaultValue; + var childNode = cssQuery(name, node); + if(childNode && childNode[0]) { + nodeValue = childNode[0].firstChild.nodeValue; + } + return nodeValue; + } +}); -- cgit v0.9.0.2