Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Axis.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/Axis.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Axis.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,146 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.Axis"); +dojo.require("dojo.lang.common"); + +dojo.charting.Axis = function(/* string? */label, /* string? */scale, /* array? */labels){ + var id = "dojo-charting-axis-"+dojo.charting.Axis.count++; + this.getId=function(){ return id; }; + this.setId=function(key){ id = key; }; + this.scale = scale || "linear"; // linear || log + this.label = label || ""; + this.showLabel = true; // show axis label. + this.showLabels = true; // show interval ticks. + this.showLines = false; // if you want lines over the range of the plot area + this.showTicks = false; // if you want tick marks on the axis. + this.range = { upper : 0, lower : 0 }; // range of individual axis. + this.origin = "min"; // this can be any number, "min" or "max". min/max is translated on init. + + this.labels = labels || []; + this._labels = []; // what we really use to draw things. + this.nodes={ main: null, axis: null, label: null, labels: null, lines: null, ticks: null }; +}; +dojo.charting.Axis.count = 0; + +dojo.extend(dojo.charting.Axis, { + // TODO: implement log scaling. + getCoord: function( + /* float */val, + /* dojo.charting.PlotArea */plotArea, + /* dojo.charting.Plot */plot + ){ + // summary + // returns the coordinate of val based on this axis range, plot area and plot. + val = parseFloat(val, 10); + var area = plotArea.getArea(); + if(plot.axisX == this){ + var offset = 0 - this.range.lower; + var min = this.range.lower + offset; // FIXME: check this. + var max = this.range.upper + offset; + val += offset; + return (val*((area.right-area.left)/max))+area.left; // float + } else { + var max = this.range.upper; + var min = this.range.lower; + var offset = 0; + if(min<0){ + offset += Math.abs(min); + } + max += offset; min += offset; val += offset; + var pmin = area.bottom; + var pmax = area.top; + return (((pmin-pmax)/(max-min))*(max-val))+pmax; + } + }, + initializeOrigin: function(drawAgainst, plane){ + // figure out the origin value. + if(isNaN(this.origin)){ + if(this.origin.toLowerCase() == "max"){ + this.origin = drawAgainst.range[(plane=="y")?"upper":"lower"]; + } + else if (this.origin.toLowerCase() == "min"){ + this.origin = drawAgainst.range[(plane=="y")?"lower":"upper"]; + } + else { this.origin=0; } + } + }, + initializeLabels: function(){ + // Translate the labels if needed. + if(this.labels.length == 0){ + this.showLabels = false; + this.showLines = false; + this.showTicks = false; + } else { + if(this.labels[0].label && this.labels[0].value != null){ + for(var i=0; i0){ + var s=a.pop(); + this._labels.push({ label: s, value: this.range.upper }); + } + // do the rest. + if(a.length>0){ + var range = this.range.upper - this.range.lower; + var step = range / (this.labels.length-1); + for(var i=1; i<=a.length; i++){ + this._labels.push({ + label: a[i-1], + value: this.range.lower+(step*i) + }); + } + } + } + } + }, + initialize: function(plotArea, plot, drawAgainst, plane){ + // summary + // Initialize the passed axis descriptor. Note that this should always + // be the result of plotArea.getAxes, and not the axis directly! + this.destroy(); + this.initializeOrigin(drawAgainst, plane); + this.initializeLabels(); + var node = this.render(plotArea, plot, drawAgainst, plane); + return node; + }, + destroy: function(){ + for(var p in this.nodes){ + while(this.nodes[p] && this.nodes[p].childNodes.length > 0){ + this.nodes[p].removeChild(this.nodes[p].childNodes[0]); + } + if(this.nodes[p] && this.nodes[p].parentNode){ + this.nodes[p].parentNode.removeChild(this.nodes[p]); + } + this.nodes[p] = null; + } + } +}); + +dojo["requireIf"](dojo.render.svg.capable, "dojo.charting.svg.Axis"); +dojo["requireIf"](!dojo.render.svg.capable && dojo.render.vml.capable, "dojo.charting.vml.Axis"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Chart.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/Chart.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Chart.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,85 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.Chart"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.charting.PlotArea"); + +dojo.charting.Chart = function( + /* HTMLElement? */node, + /* string? */title, + /* string? */description +){ + // summary + // Create the basic Chart object. + this.node = node || null; + this.title = title || "Chart"; // pure string. + this.description = description || ""; // HTML is allowed. + this.plotAreas = []; +}; + +dojo.extend(dojo.charting.Chart, { + // methods + addPlotArea: function(/* object */obj, /* bool? */doRender){ + // summary + // Add a PlotArea to this chart; object should be in the + // form of: { plotArea, (x, y) or (top, left) } + if(obj.x && !obj.left){ obj.left = obj.x; } + if(obj.y && !obj.top){ obj.top = obj.y; } + this.plotAreas.push(obj); + if(doRender){ this.render(); } + }, + + // events + onInitialize:function(chart){ }, + onRender:function(chart){ }, + onDestroy:function(chart){ }, + + // standard build methods + initialize: function(){ + // summary + // Initialize the Chart by rendering it. + if(!this.node){ + dojo.raise("dojo.charting.Chart.initialize: there must be a root node defined for the Chart."); + } + this.destroy(); + this.render(); + this.onInitialize(this); + }, + render:function(){ + // summary + // Render the chart in its entirety. + if(this.node.style.position != "absolute"){ + this.node.style.position = "relative"; + } + for(var i=0; i 0){ + this.node.removeChild(this.node.childNodes[0]); + } + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Plot.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/Plot.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Plot.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,103 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.Plot"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.charting.Axis"); +dojo.require("dojo.charting.Series"); + +dojo.charting.RenderPlotSeries = { Singly:"single", Grouped:"grouped" }; + +dojo.charting.Plot = function( + /* dojo.charting.Axis? */xaxis, + /* dojo.charting.Axis? */yaxis, + /* dojo.charting.Series[]? */series +){ + // summary + // Creates a new instance of a Plot (X/Y Axis + n Series). + var id = "dojo-charting-plot-"+dojo.charting.Plot.count++; + this.getId=function(){ return id; }; + this.setId=function(key){ id = key; }; + this.axisX = null; + this.axisY = null; + this.series = []; + this.dataNode = null; + + // for bar charts, pie charts and stacked charts, change to Grouped. + this.renderType = dojo.charting.RenderPlotSeries.Singly; + if(xaxis){ + this.setAxis(xaxis,"x"); + } + if(yaxis){ + this.setAxis(yaxis,"y"); + } + if(series){ + for(var i=0; i 0){ + node.removeChild(node.childNodes[0]); + } + this.dataNode=null; + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/PlotArea.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/PlotArea.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/PlotArea.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,193 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.PlotArea"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.gfx.color"); +dojo.require("dojo.gfx.color.hsl"); +dojo.require("dojo.charting.Plot"); + +dojo.charting.PlotArea = function(){ + // summary + // Creates a new PlotArea for drawing onto a Chart. + var id="dojo-charting-plotarea-"+dojo.charting.PlotArea.count++; + this.getId=function(){ return id; }; + this.setId=function(key){ id = key; }; + this.areaType = "standard"; // standard || radar + this.plots = []; // plots that will be drawn on this area + + this.size={ width:600, height:400 }; + this.padding={ top:10, right:10, bottom:20, left:20 }; + + // drawing node references. + this.nodes = { + main:null, + area:null, + background: null, + axes: null, + plots: null + }; + + // this is preset for a limited color range (green to purple), + // anticipating a max of 32 series on this plot area. + // if you need more flexibility, override these numbers. + this._color = { h: 140, s: 120, l: 120, step: 27 }; +}; +dojo.charting.PlotArea.count = 0; + +dojo.extend(dojo.charting.PlotArea, { + nextColor: function(){ + // summary + // Advances the internal HSV cursor and returns the next generated color. + var rgb=dojo.gfx.color.hsl2rgb(this._color.h, this._color.s, this._color.l); + this._color.h = (this._color.h + this._color.step)%360; + while(this._color.h < 140){ + this._color.h += this._color.step; + } + return dojo.gfx.color.rgb2hex(rgb[0], rgb[1], rgb[2]); // string + }, + getArea:function(){ + // summary + // Return an object describing the coordinates of the available area to plot on. + return { + left: this.padding.left, + right: this.size.width - this.padding.right, + top: this.padding.top, + bottom: this.size.height - this.padding.bottom, + toString:function(){ + var a=[ this.top, this.right, this.bottom, this.left ]; + return "["+a.join()+"]"; + } + }; // object + }, + getAxes: function(){ + // summary + // get the unique axes for this plot area. + var axes={}; + for(var i=0; i 0){ + node.removeChild(node.childNodes[0]); + } + this.nodes[p]=null; + } + } +}); + +dojo["requireIf"](dojo.render.svg.capable, "dojo.charting.svg.PlotArea"); +dojo["requireIf"](!dojo.render.svg.capable && dojo.render.vml.capable, "dojo.charting.vml.PlotArea"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Plotters.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/Plotters.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Plotters.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,19 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.Plotters"); + +/* + * Plotters is the placeholder; what will happen is that the proper renderer types + * will be mixed into this object (as opposed to creating a new one). + */ + +dojo["requireIf"](dojo.render.svg.capable, "dojo.charting.svg.Plotters"); +dojo["requireIf"](!dojo.render.svg.capable && dojo.render.vml.capable, "dojo.charting.vml.Plotters"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/README.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/README.txt,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/README.txt 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,46 @@ +Dojo Charting Engine +========================================================================= +The Dojo Charting Engine is a (fairly) complex object structure, designed +to provide as much flexibility as possible in terms of chart construction. +To this end, the engine details the following structure: + +Chart +---PlotArea[] +------Plot[] +---------Axis (axisX) +---------Axis (axisY) +---------Series[] + + +A Chart object is the main entity; it is the entire graphic. A Chart may +have any number of PlotArea objects, which are the basic canvas against +which data is plotted. A PlotArea may have any number of Plot objects, +which is a container representing up to 2 axes and any number of series +to be plotted against those axes; a Series represents a binding against +two fields from a data source (initial rev, this data source is always of +type dojo.collections.Store but this will probably change once dojo.data +is in production). + +The point of this structure is to allow for as much flexibility as possible +in terms of what kinds of charts can be represented by the engine. The +current plan is to accomodate up to analytical financial charts, which tend +to have 3 plot areas and any number of different types of axes on each one. + +The main exception to this is the pie chart, which will have it's own +custom codebase. Also, 3D charts are not accounted for at this time, +although the only thing that will probably need to be altered to make +that work would be Plot and Series (to accomodate the additional Z axis). + +Finally, a Plot will render its series[] through the use of Plotters, which +are custom methods to render specific types of charts. +------------------------------------------------------------------------- +In terms of widgets, the basic concept is that there is a central, super- +flexible Chart widget (Chart, oddly enough), and then any number of preset +chart type widgets, that are basically built to serve a simple, easy +purpose. For instance, if someone just needs to plot a series of lines, +they would be better off using the LineChart widget; but if someone needed +to plot a combo chart, that has 2 Y Axes (one linear, one log) against the +same X Axis, using lines and areas, then they will want to use a Chart widget. +Note also that unlike other widgets, the Charting engine *can* be called +directly from script *without* the need for the actual widget engine to be +loaded; the Chart widgets are thin wrappers around the charting engine. \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Series.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/Series.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Series.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,215 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.Series"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.charting.Plotters"); + +dojo.charting.Series = function(/* object? */kwArgs){ + // summary + // Create an instance of data series for plotting. + var args = kwArgs || { length:1 }; + this.dataSource = args.dataSource || null; + this.bindings = { }; + this.color = args.color; + this.label = args.label; + + if(args.bindings){ + for(var p in args.bindings){ + this.addBinding(p, args.bindings[p]); + } + } +}; + +dojo.extend(dojo.charting.Series, { + bind:function(/* dojo.collections.Store */src, /* object */bindings){ + // summary + // Bind this series to src, with bindings. + this.dataSource = src; + this.bindings = bindings; + }, + addBinding:function(/* string */name, /* string */binding){ + // summary + // Bind to field "binding" using "name". + this.bindings[name] = binding; + }, + evaluate:function(/* object? */kwArgs){ + // summary + // Evaluate all bindings and return an array of objects describing the bind. + var ret = []; + var a = this.dataSource.getData(); + var l = a.length; + var start = 0; + var end = l; + + /* Allow for ranges. Can be done in one of two ways: + * 1. { from, to } as 0-based indices + * 2. { length } as num of data points to get; a negative + * value will start from the end of the data set. + * No kwArg object means the full data set will be evaluated + * and returned. + */ + if(kwArgs){ + if(kwArgs.from){ + start = Math.max(kwArgs.from,0); + if(kwArgs.to){ + end = Math.min(kwArgs.to, end); + } + } + else if(kwArgs.length){ + if(kwArgs.length < 0){ + // length points from end + start = Math.max((end + length),0); + } else { + end = Math.min((start + length), end); + } + } + } + + for(var i=start; i b.x) return 1; + if(a.x < b.x) return -1; + return 0; + }); + } + return ret; // array + }, + + // trends + trends:{ + createRange: function(/* array */values, /* int */len){ + // summary + // Creates the data range used for all trends. + var idx = values.length-1; + var length = (len||values.length); + return { "index": idx, "length": length, "start":Math.max(idx-length,0) }; // object + }, + + mean: function(/* array */values, /* int */len){ + // summary + // Returns the mean or average over the set of values. + var range = this.createRange(values, len); + if(range.index<0){ return 0; } + var total = 0; + var count = 0; + for(var i=range.index; i>=range.start; i--){ + total += values[i].y; + count++; + } + total /= Math.max(count,1); + return total; // float + }, + + variance: function(/* array */values,/* int */len){ + // summary + // Returns the variance of the set of values. + var range = this.createRange(values,len); + if(range.index < 0){ return 0; } + var total = 0; + var square = 0; + var count = 0; + for(var i=range.index; i>=range.start; i--){ + total += values[i].y; + square += Math.pow(values[i].y, 2); + count++; + } + return (square/count)-Math.pow(total/count,2); // float + }, + + standardDeviation: function(/* array */values, /* int */len){ + // summary + // Returns the standard deviation of the set of values. + return Math.sqrt(this.getVariance(values, len)); // float + }, + + max: function(/* array */values, /* int */len){ + // summary + // Returns the max number in the set of values. + var range = this.createRange(values, len); + if(range.index < 0){ return 0; } + var max = Number.MIN_VALUE; + for (var i=range.index; i>=range.start; i--){ + max = Math.max(values[i].y,max); + } + return max; // float + }, + + min: function(/* array */values, /* int */len){ + // summary + // Returns the lowest number in the set of values. + var range=this.createRange(values, len); + if(range.index < 0){ return 0; } + var min = Number.MAX_VALUE; + for(var i=range.index; i>=range.start; i--){ + min = Math.min(values[i].y, min); + } + return min; // float + }, + + median: function(/* array */values, /* int */len){ + // summary + // Returns the median in the set of values (number closest to the middle of a sorted set). + var range = this.createRange(values, len); + if(range.index<0){ return 0; } + var a = []; + for (var i=range.index; i>=range.start; i--){ + var b=false; + for(var j=0; j 0){ + return a[Math.ceil(a.length / 2)]; // float + } + return 0; // float + }, + + mode: function(/* array */values, /* int */len){ + // summary + // Returns the mode in the set of values + var range=this.createRange(values, len); + if(range.index<0){ return 0; } + var o = {}; + var ret = 0 + var median = Number.MIN_VALUE; + for(var i=range.index; i>=range.start; i--){ + if (!o[values[i].y]){ + o[values[i].y] = 1; + } else { + o[values[i].y]++; + } + } + for(var p in o){ + if(median < o[p]){ + median = o[p]; + ret=p; + } + } + return ret; + } + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/charting/__package__.js 6 Nov 2006 14:50:05 -0000 1.1 @@ -0,0 +1,11 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.charting.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/ArrayList.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Attic/ArrayList.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/ArrayList.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,146 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.collections.ArrayList"); +dojo.require("dojo.collections.Collections"); + +dojo.collections.ArrayList=function(/* array? */arr){ + // summary + // Returns a new object of type dojo.collections.ArrayList + var items=[]; + if(arr) items=items.concat(arr); + this.count=items.length; + this.add=function(/* object */obj){ + // summary + // Add an element to the collection. + items.push(obj); + this.count=items.length; + }; + this.addRange=function(/* array */a){ + // summary + // Add a range of objects to the ArrayList + if(a.getIterator){ + var e=a.getIterator(); + while(!e.atEnd()){ + this.add(e.get()); + } + this.count=items.length; + }else{ + for(var i=0; i=0) { + items.splice(i,1); + } + this.count=items.length; + }; + this.removeAt=function(/* int */ i){ + // summary + // return an array with function applied to all elements + items.splice(i,1); + this.count=items.length; + }; + this.reverse=function(){ + // summary + // Reverse the internal array + items.reverse(); + }; + this.sort=function(/* function? */ fn){ + // summary + // sort the internal array + if(fn){ + items.sort(fn); + }else{ + items.sort(); + } + }; + this.setByIndex=function(/* int */ i, /* object */ obj){ + // summary + // Set an element in the array by the passed index. + items[i]=obj; + this.count=items.length; + }; + this.toArray=function(){ + // summary + // Return a new array with all of the items of the internal array concatenated. + return [].concat(items); + } + this.toString=function(/* string */ delim){ + // summary + // implementation of toString, follows [].toString(); + return items.join((delim||",")); + }; +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/BinaryTree.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Attic/BinaryTree.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/BinaryTree.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,203 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.collections.BinaryTree"); +dojo.require("dojo.collections.Collections"); +dojo.require("dojo.experimental"); + +dojo.experimental("dojo.collections.BinaryTree"); + +dojo.collections.BinaryTree=function(data){ + function node(data, rnode, lnode){ + this.value=data||null; + this.right=rnode||null; + this.left=lnode||null; + this.clone=function(){ + var c=new node(); + if (this.value.value) c.value=this.value.clone(); + else c.value=this.value; + if (this.left) c.left=this.left.clone(); + if (this.right) c.right=this.right.clone(); + } + this.compare=function(n){ + if (this.value > n.value) return 1; + if (this.value < n.value) return -1; + return 0; + } + this.compareData=function(d){ + if (this.value > d) return 1; + if (this.value < d) return -1; + return 0; + } + } + + function inorderTraversalBuildup(current, a){ + if (current){ + inorderTraversalBuildup(current.left, a); + a.add(current); + inorderTraversalBuildup(current.right, a); + } + } + + function preorderTraversal(current, sep){ + var s=""; + if (current){ + s=current.value.toString() + sep; + s += preorderTraversal(current.left, sep); + s += preorderTraversal(current.right, sep); + } + return s; + } + function inorderTraversal(current, sep){ + var s=""; + if (current){ + s=inorderTraversal(current.left, sep); + s += current.value.toString() + sep; + s += inorderTraversal(current.right, sep); + } + return s; + } + function postorderTraversal(current, sep){ + var s=""; + if (current){ + s=postorderTraversal(current.left, sep); + s += postorderTraversal(current.right, sep); + s += current.value.toString() + sep; + } + return s; + } + + function searchHelper(current, data){ + if (!current) return null; + var i=current.compareData(data); + if (i==0) return current; + if (i>0) return searchHelper(current.left, data); + else return searchHelper(current.right, data); + } + + this.add=function(data){ + var n=new node(data); + var i; + var current=root; + var parent=null; + while (current){ + i=current.compare(n); + if (i == 0) return; + parent=current; + if (i > 0) current=current.left; + else current=current.right; + } + this.count++; + if (!parent) root=n; + else { + i=parent.compare(n); + if (i > 0) parent.left=n; + else parent.right=n; + } + }; + this.clear=function(){ + root=null; + this.count=0; + }; + this.clone=function(){ + var c=new dojo.collections.BinaryTree(); + c.root=root.clone(); + c.count=this.count; + return c; + }; + this.contains=function(data){ + return this.search(data) != null; + }; + this.deleteData=function(data){ + var current=root; + var parent=null; + var i=current.compareData(data); + while (i != 0 && current != null){ + if (i > 0){ + parent=current; + current=current.left; + } else if (i < 0) { + parent=current; + current=current.right; + } + i=current.compareData(data); + } + if (!current) return; + this.count--; + if (!current.right) { + if (!parent) root=current.left; + else { + i=parent.compare(current); + if (i > 0) parent.left=current.left; + else if (i < 0) parent.right=current.left; + } + } else if (!current.right.left){ + if (!parent) root=current.right; + else { + i=parent.compare(current); + if (i > 0) parent.left=current.right; + else if (i < 0) parent.right=current.right; + } + } else { + var leftmost=current.right.left; + var lmParent=current.right; + while (leftmost.left != null){ + lmParent=leftmost; + leftmost=leftmost.left; + } + lmParent.left=leftmost.right; + leftmost.left=current.left; + leftmost.right=current.right; + if (!parent) root=leftmost; + else { + i=parent.compare(current); + if (i > 0) parent.left=leftmost; + else if (i < 0) parent.right=leftmost; + } + } + }; + this.getIterator=function(){ + var a=[]; + inorderTraversalBuildup(root, a); + return new dojo.collections.Iterator(a); + }; + this.search=function(data){ + return searchHelper(root, data); + }; + this.toString=function(order, sep){ + if (!order) var order=dojo.collections.BinaryTree.TraversalMethods.Inorder; + if (!sep) var sep=" "; + var s=""; + switch (order){ + case dojo.collections.BinaryTree.TraversalMethods.Preorder: + s=preorderTraversal(root, sep); + break; + case dojo.collections.BinaryTree.TraversalMethods.Inorder: + s=inorderTraversal(root, sep); + break; + case dojo.collections.BinaryTree.TraversalMethods.Postorder: + s=postorderTraversal(root, sep); + break; + }; + if (s.length == 0) return ""; + else return s.substring(0, s.length - sep.length); + }; + + this.count=0; + var root=this.root=null; + if (data) { + this.add(data); + } +} +dojo.collections.BinaryTree.TraversalMethods={ + Preorder : 1, + Inorder : 2, + Postorder : 3 +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Collections.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Attic/Collections.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Collections.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,124 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.collections.Collections"); + +dojo.collections.DictionaryEntry=function(/* string */k, /* object */v){ + // summary + // return an object of type dojo.collections.DictionaryEntry + this.key=k; + this.value=v; + this.valueOf=function(){ + return this.value; // object + }; + this.toString=function(){ + return String(this.value); // string + }; +} + +/* Iterators + * The collections.Iterators (Iterator and DictionaryIterator) are built to + * work with the Collections included in this module. However, they *can* + * be used with arrays and objects, respectively, should one choose to do so. + */ +dojo.collections.Iterator=function(/* array */arr){ + // summary + // return an object of type dojo.collections.Iterator + var a=arr; + var position=0; + this.element=a[position]||null; + this.atEnd=function(){ + // summary + // Test to see if the internal cursor has reached the end of the internal collection. + return (position>=a.length); // bool + }; + this.get=function(){ + // summary + // Test to see if the internal cursor has reached the end of the internal collection. + if(this.atEnd()){ + return null; // object + } + this.element=a[position++]; + return this.element; // object + }; + this.map=function(/* function */fn, /* object? */scope){ + // summary + // Functional iteration with optional scope. + var s=scope||dj_global; + if(Array.map){ + return Array.map(a,fn,s); // array + }else{ + var arr=[]; + for(var i=0; i=a.length); // bool + }; + this.get=function(){ + // summary + // Test to see if the internal cursor has reached the end of the internal collection. + if(this.atEnd()){ + return null; // object + } + this.element=a[position++]; + return this.element; // object + }; + this.map=function(/* function */fn, /* object? */scope){ + // summary + // Functional iteration with optional scope. + var s=scope||dj_global; + if(Array.map){ + return Array.map(a,fn,s); // array + }else{ + var arr=[]; + for(var i=0; i=o.length); + } + this.get=function(){ + if(this.atEnd()){ + return null; // object + } + this.element=o[position++]; + return this.element; // object + }; + this.map=function(/* function */fn, /* object? */scope){ + var s=scope||dj_global; + if(Array.map){ + return Array.map(o,fn,s); // array + }else{ + var arr=[]; + for(var i=0; i 1){ + n=new node(arguments[0],arguments[1]); + } + if(!this.nodes.containsKey(n.key)){ + this.nodes.add(n); + this.count++; + } + }; + this.addDirectedEdge=function(uKey, vKey, cost){ + var uNode,vNode; + if(uKey.constructor!= node){ + uNode=this.nodes.item(uKey); + vNode=this.nodes.item(vKey); + }else{ + uNode=uKey; + vNode=vKey; + } + var c=cost||0; + uNode.addDirected(vNode,c); + }; + this.addUndirectedEdge=function(uKey, vKey, cost){ + var uNode, vNode; + if(uKey.constructor!=node){ + uNode=this.nodes.item(uKey); + vNode=this.nodes.item(vKey); + }else{ + uNode=uKey; + vNode=vKey; + } + var c=cost||0; + uNode.addDirected(vNode,c); + vNode.addDirected(uNode,c); + }; + this.contains=function(n){ + return this.nodes.containsKey(n.key); + }; + this.containsKey=function(k){ + return this.nodes.containsKey(k); + }; +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Queue.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Attic/Queue.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Queue.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,87 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.collections.Queue"); +dojo.require("dojo.collections.Collections"); + +dojo.collections.Queue=function(/* array? */arr){ + // summary + // return an object of type dojo.collections.Queue + var q=[]; + if (arr){ + q=q.concat(arr); + } + this.count=q.length; + this.clear=function(){ + // summary + // clears the internal collection + q=[]; + this.count=q.length; + }; + this.clone=function(){ + // summary + // creates a new Queue based on this one + return new dojo.collections.Queue(q); // dojo.collections.Queue + }; + this.contains=function(/* object */ o){ + // summary + // Check to see if the passed object is an element in this queue + for(var i=0; i val) return 1; + if (this.value < val) return -1; + return 0; + } + this.incrementHeight = function(){ + this.nodes.incrementHeight(); + this.height++; + }; + this.decrementHeight = function(){ + this.nodes.decrementHeight(); + this.height--; + }; + } + function nodeList(height){ + var arr = []; + this.height = height; + for (var i = 0; i < height; i++) arr[i] = null; + this.item = function(i){ + return arr[i]; + }; + this.incrementHeight = function(){ + this.height++; + arr[this.height] = null; + }; + this.decrementHeight = function(){ + arr.splice(arr.length - 1, 1); + this.height--; + }; + } + function iterator(list){ + this.element = list.head; + this.atEnd = function(){ + return (this.element==null); + } + this.get = function(){ + if(this.atEnd()){ + return null; + } + this.element=this.element.nodes[0]; + return this.element; + } + this.reset = function(){ + this.element = list.head; + } + } + + function chooseRandomHeight(max){ + var level = 1; + while (Math.random() < PROB && level < max) level++; + return level; + } + + var PROB = 0.5; + var comparisons = 0; + + this.head = new node(1); + this.count = 0; + this.add = function(val){ + var updates = []; + var current = this.head; + for (var i = this.head.height; i >= 0; i--){ + if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++; + while (current.nodes[i] != null && current.nodes[i].compare(val) < 0){ + current = current.nodes[i]; + comparisons++; + } + updates[i] = current; + } + if (current.nodes[0] != null && current.nodes[0].compare(val) == 0) return; + var n = new node(val, chooseRandomHeight(this.head.height + 1)); + this.count++; + if (n.height > this.head.height){ + this.head.incrementHeight(); + this.head.nodes[this.head.height - 1] = n; + } + for (i = 0; i < n.height; i++){ + if (i < updates.length) { + n.nodes[i] = updates[i].nodes[i]; + updates[i].nodes[i] = n; + } + } + }; + + this.contains = function(val){ + var current = this.head; + var i; + for (i = this.head.height - 1; i >= 0; i--) { + while (current.item(i) != null) { + comparisons++; + var result = current.nodes[i].compare(val); + if (result == 0) return true; + else if (result < 0) current = current.nodes[i]; + else break; + } + } + return false; + }; + this.getIterator = function(){ + return new iterator(this); + }; + + this.remove = function(val){ + var updates = []; + var current = this.head; + for (var i = this.head.height - 1; i >= 0; i--){ + if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++; + while (current.nodes[i] != null && current.nodes[i].compare(val) < 0) { + current = current.nodes[i]; + comparisons++; + } + updates[i] = current; + } + + current = current.nodes[0]; + if (current != null && current.compare(val) == 0){ + this.count--; + for (var i = 0; i < this.head.height; i++){ + if (updates[i].nodes[i] != current) break; + else updates[i].nodes[i] = current.nodes[i]; + } + if (this.head.nodes[this.head.height - 1] == null) this.head.decrementHeight(); + } + }; + this.resetComparisons = function(){ + comparisons = 0; + }; +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/SortedList.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/Attic/SortedList.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/collections/SortedList.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,211 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.collections.SortedList"); +dojo.require("dojo.collections.Collections"); + +dojo.collections.SortedList=function(/* object? */ dictionary){ + // summary + // creates a collection that acts like a dictionary but is also internally sorted. + // Note that the act of adding any elements forces an internal resort, making this object potentially slow. + var _this=this; + var items={}; + var q=[]; + var sorter=function(a,b){ + if (a.key > b.key) return 1; + if (a.key < b.key) return -1; + return 0; + }; + var build=function(){ + q=[]; + var e=_this.getIterator(); + while (!e.atEnd()){ + q.push(e.get()); + } + q.sort(sorter); + }; + var testObject={}; + + this.count=q.length; + this.add=function(/* string */ k,/* object */v){ + // summary + // add the passed value to the dictionary at location k + if (!items[k]) { + items[k]=new dojo.collections.DictionaryEntry(k,v); + this.count=q.push(items[k]); + q.sort(sorter); + } + }; + this.clear=function(){ + // summary + // clear the internal collections + items={}; + q=[]; + this.count=q.length; + }; + this.clone=function(){ + // summary + // create a clone of this sorted list + return new dojo.collections.SortedList(this); // dojo.collections.SortedList + }; + this.contains=this.containsKey=function(/* string */ k){ + // summary + // Check to see if the list has a location k + if(testObject[k]){ + return false; // bool + } + return (items[k]!=null); // bool + }; + this.containsValue=function(/* object */ o){ + // summary + // Check to see if this list contains the passed object + var e=this.getIterator(); + while (!e.atEnd()){ + var item=e.get(); + if(item.value==o){ + return true; // bool + } + } + return false; // bool + }; + this.copyTo=function(/* array */ arr, /* int */ i){ + // summary + // copy the contents of the list into array arr at index i + var e=this.getIterator(); + var idx=i; + while(!e.atEnd()){ + arr.splice(idx,0,e.get()); + idx++; + } + }; + this.entry=function(/* string */ k){ + // summary + // return the object at location k + return items[k]; // dojo.collections.DictionaryEntry + }; + this.forEach=function(/* function */ fn, /* object? */ scope){ + // summary + // functional iterator, following the mozilla spec. + var s=scope||dj_global; + if(Array.forEach){ + Array.forEach(q, fn, s); + }else{ + for(var i=0; i1) { + field = parts.pop(); + do{ + if(parts[i].indexOf("()")>-1){ + var temp=parts[i++].split("()")[0]; + if(!o[temp]){ + dojo.raise("dojo.collections.Store.getField(obj, '" + field + "'): '" + temp + "' is not a property of the passed object."); + } else { + // this *will* throw an error if the method in question can't be invoked without arguments. + o = o[temp](); + } + } else { + o = o[parts[i++]]; + } + } while (i-1){ + data.splice(idx,1); + } + }; + this.removeDataByKey = function(/*string*/key){ + // summary + // remove the object at key from the internal data array. + this.removeData(this.getDataByKey(key)); + }; + this.removeDataByIndex = function(/*number*/idx){ + // summary + // remove the object at idx from the internal data array. + this.removeData(this.getDataByIndex(idx)); + }; + + if(jsonArray && jsonArray.length && jsonArray[0]){ + this.setData(jsonArray); + } +}; + +dojo.extend(dojo.collections.Store, { + getField:function(/*object*/obj, /*string*/field){ + // helper to get the nested value if needed. + var parts=field.split("."), i=0, o=obj; + do{ + if(parts[i].indexOf("()")>-1){ + var temp=parts[i++].split("()")[0]; + if(!o[temp]){ + dojo.raise("dojo.collections.Store.getField(obj, '" + field + "'): '" + temp + "' is not a property of the passed object."); + } else { + // this *will* throw an error if the method in question can't be invoked without arguments. + o = o[temp](); + } + } else { + o = o[parts[i++]]; + } + } while (i -1){ + p = p.split("."); + while(p.length>1){ + var pr = p.shift(); + o[pr] = {}; + o = o[pr]; + } + p = p[0]; + } + + var type = meta[i].getType(); + if(type == String){ + o[p] = data; + } else { + if(data){ + o[p] = new type(data); + } else { + o[p] = new type(); + } + } + } + return obj; + }; + + // we have initialization data, let's parse it. + var arr=[]; + for(var i=0; i>16)^0xffff))+(((sum&0xffff)^0xffff)+1); + } + return sum; + } + function split(x){ + var r=x&0xffffffff; + if(r<0) { + r=-r; + return [((r&0xffff)^0xffff)+1,(r>>16)^0xffff]; + } + return [r&0xffff,(r>>16)]; + } + function xor(x,y){ + var xs=split(x); + var ys=split(y); + return (0x10000*(xs[1]^ys[1]))+(xs[0]^ys[0]); + } + function $(v, box){ + var d=v&0xff; v>>=8; + var c=v&0xff; v>>=8; + var b=v&0xff; v>>=8; + var a=v&0xff; + var r=add(box.s0[a],box.s1[b]); + r=xor(r,box.s2[c]); + return add(r,box.s3[d]); + } +//////////////////////////////////////////////////////////////////////////// + function eb(o, box){ + var l=o.left; + var r=o.right; + l=xor(l,box.p[0]); + r=xor(r,xor($(l,box),box.p[1])); + l=xor(l,xor($(r,box),box.p[2])); + r=xor(r,xor($(l,box),box.p[3])); + l=xor(l,xor($(r,box),box.p[4])); + r=xor(r,xor($(l,box),box.p[5])); + l=xor(l,xor($(r,box),box.p[6])); + r=xor(r,xor($(l,box),box.p[7])); + l=xor(l,xor($(r,box),box.p[8])); + r=xor(r,xor($(l,box),box.p[9])); + l=xor(l,xor($(r,box),box.p[10])); + r=xor(r,xor($(l,box),box.p[11])); + l=xor(l,xor($(r,box),box.p[12])); + r=xor(r,xor($(l,box),box.p[13])); + l=xor(l,xor($(r,box),box.p[14])); + r=xor(r,xor($(l,box),box.p[15])); + l=xor(l,xor($(r,box),box.p[16])); + o.right=l; + o.left=xor(r,box.p[17]); + } + + function db(o, box){ + var l=o.left; + var r=o.right; + l=xor(l,box.p[17]); + r=xor(r,xor($(l,box),box.p[16])); + l=xor(l,xor($(r,box),box.p[15])); + r=xor(r,xor($(l,box),box.p[14])); + l=xor(l,xor($(r,box),box.p[13])); + r=xor(r,xor($(l,box),box.p[12])); + l=xor(l,xor($(r,box),box.p[11])); + r=xor(r,xor($(l,box),box.p[10])); + l=xor(l,xor($(r,box),box.p[9])); + r=xor(r,xor($(l,box),box.p[8])); + l=xor(l,xor($(r,box),box.p[7])); + r=xor(r,xor($(l,box),box.p[6])); + l=xor(l,xor($(r,box),box.p[5])); + r=xor(r,xor($(l,box),box.p[4])); + l=xor(l,xor($(r,box),box.p[3])); + r=xor(r,xor($(l,box),box.p[2])); + l=xor(l,xor($(r,box),box.p[1])); + o.right=l; + o.left=xor(r,box.p[0]); + } + + // Note that we aren't caching contexts here; it might take a little longer + // but we should be more secure this way. + function init(key){ + var k=key; + if (typeof(k)=="string"){ + var a=[]; + for(var i=0; i>>18)&0x3f)); + s.push(tab.charAt((t>>>12)&0x3f)); + s.push(tab.charAt((t>>>6)&0x3f)); + s.push(tab.charAt(t&0x3f)); + } + // deal with trailers, based on patch from Peter Wood. + switch(rm){ + case 2:{ + var t=ba[i++]<<16|ba[i++]<<8; + s.push(tab.charAt((t>>>18)&0x3f)); + s.push(tab.charAt((t>>>12)&0x3f)); + s.push(tab.charAt((t>>>6)&0x3f)); + s.push(p); + break; + } + case 1:{ + var t=ba[i++]<<16; + s.push(tab.charAt((t>>>18)&0x3f)); + s.push(tab.charAt((t>>>12)&0x3f)); + s.push(p); + s.push(p); + break; + } + } + return s.join(""); + } + function fromBase64(str){ + var s=str.split(""); + var p="="; + var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var out=[]; + var l=s.length; + while(s[--l]==p){ } + for (var i=0; i>>16)&0xff); + out.push((t>>>8)&0xff); + out.push(t&0xff); + } + return out; + } +//////////////////////////////////////////////////////////////////////////// +// PUBLIC FUNCTIONS +// 0.2: Only supporting ECB mode for now. +//////////////////////////////////////////////////////////////////////////// + this.getIV=function(/* dojo.crypto.outputTypes? */ outputType){ + // summary + // returns the initialization vector in the output format specified by outputType + var out=outputType||dojo.crypto.outputTypes.Base64; + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + var s=[]; + for(var i=0; i> 3; + var pos=0; + var o={}; + var isCBC=(mode==dojo.crypto.cipherModes.CBC); + var vector={left:iv.left||null, right:iv.right||null}; + for(var i=0; i>24)&0xff); + cipher.push((o.left>>16)&0xff); + cipher.push((o.left>>8)&0xff); + cipher.push(o.left&0xff); + cipher.push((o.right>>24)&0xff); + cipher.push((o.right>>16)&0xff); + cipher.push((o.right>>8)&0xff); + cipher.push(o.right&0xff); + pos+=8; + } + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + var s=[]; + for(var i=0; i> 3; + var pos=0; + var o={}; + var isCBC=(mode==dojo.crypto.cipherModes.CBC); + var vector={left:iv.left||null, right:iv.right||null}; + for(var i=0; i>24)&0xff); + pt.push((o.left>>16)&0xff); + pt.push((o.left>>8)&0xff); + pt.push(o.left&0xff); + pt.push((o.right>>24)&0xff); + pt.push((o.right>>16)&0xff); + pt.push((o.right>>8)&0xff); + pt.push(o.right&0xff); + pos+=8; + } + + // check for padding, and remove. + if(pt[pt.length-1]==pt[pt.length-2]||pt[pt.length-1]==0x01){ + var n=pt[pt.length-1]; + pt.splice(pt.length-n, n); + } + + // convert to string + for(var i=0; i>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32); + return wa; + } + function toString(wa){ + var s=[]; + for(var i=0; i>5]>>>(i%32))&mask)); + return s.join(""); + } + function toHex(wa) { + var h="0123456789abcdef"; + var s=[]; + for(var i=0; i>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF)); + } + return s.join(""); + } + function toBase64(wa){ + var p="="; + var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var s=[]; + for(var i=0; i>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF); + for(var j=0; j<4; j++){ + if(i*8+j*6>wa.length*32) s.push(p); + else s.push(tab.charAt((t>>6*(3-j))&0x3F)); + } + } + return s.join(""); + } + function add(x,y) { + var l=(x&0xFFFF)+(y&0xFFFF); + var m=(x>>16)+(y>>16)+(l>>16); + return (m<<16)|(l&0xFFFF); + } + function R(n,c){ return (n<>>(32-c)); } + function C(q,a,b,x,s,t){ return add(R(add(add(a,q),add(x,t)),s),b); } + function FF(a,b,c,d,x,s,t){ return C((b&c)|((~b)&d),a,b,x,s,t); } + function GG(a,b,c,d,x,s,t){ return C((b&d)|(c&(~d)),a,b,x,s,t); } + function HH(a,b,c,d,x,s,t){ return C(b^c^d,a,b,x,s,t); } + function II(a,b,c,d,x,s,t){ return C(c^(b|(~d)),a,b,x,s,t); } + function core(x,len){ + x[len>>5]|=0x80<<((len)%32); + x[(((len+64)>>>9)<<4)+14]=len; + var a= 1732584193; + var b=-271733879; + var c=-1732584194; + var d= 271733878; + for(var i=0; i16) wa=core(wa,key.length*chrsz); + var l=[], r=[]; + for(var i=0; i<16; i++){ + l[i]=wa[i]^0x36363636; + r[i]=wa[i]^0x5c5c5c5c; + } + var h=core(l.concat(toWord(data)),512+data.length*chrsz); + return core(r.concat(h),640); + } + + // Public functions + this.compute=function(/* string */data, /* dojo.crypto.outputTypes */outputType){ + // summary + // computes the digest of data, and returns the result as a string of type outputType + var out=outputType||dojo.crypto.outputTypes.Base64; + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + return toHex(core(toWord(data),data.length*chrsz)); // string + } + case dojo.crypto.outputTypes.String:{ + return toString(core(toWord(data),data.length*chrsz)); // string + } + default:{ + return toBase64(core(toWord(data),data.length*chrsz)); // string + } + } + }; + this.getHMAC=function(/* string */data, /* string */key, /* dojo.crypto.outputTypes */outputType){ + // summary + // computes a digest of data using key, and returns the result as a string of outputType + var out=outputType||dojo.crypto.outputTypes.Base64; + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + return toHex(hmac(data,key)); // string + } + case dojo.crypto.outputTypes.String:{ + return toString(hmac(data,key)); // string + } + default:{ + return toBase64(hmac(data,key)); // string + } + } + }; +}(); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Rijndael.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Attic/Rijndael.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Rijndael.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,22 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.crypto.Rijndael"); +dojo.require("dojo.crypto"); +dojo.require("dojo.experimental"); + +dojo.experimental("dojo.crypto.Rijndael"); + +dojo.crypto.Rijndael = new function(){ + this.encrypt=function(plaintext, key){ + }; + this.decrypt=function(ciphertext, key){ + }; +}(); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/SHA1.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Attic/SHA1.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/SHA1.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,154 @@ +dojo.require("dojo.crypto"); +dojo.provide("dojo.crypto.SHA1"); +dojo.require("dojo.experimental"); + +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + * + * Dojo port by Tom Trenka + */ +dojo.experimental("dojo.crypto.SHA1"); + +dojo.crypto.SHA1 = new function(){ + var chrsz=8; + var mask=(1<>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32); + return wa; + } + function toString(wa){ + var s=[]; + for(var i=0; i>5]>>>(i%32))&mask)); + return s.join(""); + } + function toHex(wa) { + var h="0123456789abcdef"; + var s=[]; + for(var i=0; i>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF)); + } + return s.join(""); + } + function toBase64(wa){ + var p="="; + var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var s=[]; + for(var i=0; i>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF); + for(var j=0; j<4; j++){ + if(i*8+j*6>wa.length*32) s.push(p); + else s.push(tab.charAt((t>>6*(3-j))&0x3F)); + } + } + return s.join(""); + } + + // math + function add(x,y){ + var l=(x&0xffff)+(y&0xffff); + var m=(x>>16)+(y>>16)+(l>>16); + return (m<<16)|(l&0xffff); + } + function r(x,n){ return (x<>>(32-n)); } + + // SHA rounds + function f(u,v,w){ return ((u&v)|(~u&w)); } + function g(u,v,w){ return ((u&v)|(u&w)|(v&w)); } + function h(u,v,w){ return (u^v^w); } + + function fn(i,u,v,w){ + if(i<20) return f(u,v,w); + if(i<40) return h(u,v,w); + if(i<60) return g(u,v,w); + return h(u,v,w); + } + function cnst(i){ + if(i<20) return 1518500249; + if(i<40) return 1859775393; + if(i<60) return -1894007588; + return -899497514; + } + + function core(x,len){ + x[len>>5]|=0x80<<(24-len%32); + x[((len+64>>9)<<4)+15]=len; + + var w=[]; + var a= 1732584193; // 0x67452301 + var b=-271733879; // 0xefcdab89 + var c=-1732584194; // 0x98badcfe + var d= 271733878; // 0x10325476 + var e=-1009589776; // 0xc3d2e1f0 + + for(var i=0; i16) wa=core(wa,key.length*chrsz); + var l=[], r=[]; + for(var i=0; i<16; i++){ + l[i]=wa[i]^0x36363636; + r[i]=wa[i]^0x5c5c5c5c; + } + var h=core(l.concat(toWord(data)),512+data.length*chrsz); + return core(r.concat(h),640); + } + + this.compute=function(data,outputType){ + var out=outputType||dojo.crypto.outputTypes.Base64; + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + return toHex(core(toWord(data),data.length*chrsz)); + } + case dojo.crypto.outputTypes.String:{ + return toString(core(toWord(data),data.length*chrsz)); + } + default:{ + return toBase64(core(toWord(data),data.length*chrsz)); + } + } + }; + this.getHMAC=function(data,key,outputType){ + var out=outputType||dojo.crypto.outputTypes.Base64; + switch(out){ + case dojo.crypto.outputTypes.Hex:{ + return toHex(hmac(data,key)); + } + case dojo.crypto.outputTypes.String:{ + return toString(hmac(data,key)); + } + default:{ + return toBase64(hmac(data,key)); + } + } + }; +}(); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/SHA256.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Attic/SHA256.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/SHA256.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,20 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.crypto.SHA256"); +dojo.require("dojo.crypto"); +dojo.require("dojo.experimental"); + +dojo.experimental("dojo.crypto.SHA256"); + +dojo.crypto.SHA256 = new function(){ + this.compute=function(s){ + }; +}(); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/crypto/__package__.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,17 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [ + "dojo.crypto", + "dojo.crypto.MD5" + ] +}); +dojo.provide("dojo.crypto.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Read.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Attic/Read.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Read.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,224 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.data.Read"); +dojo.require("dojo.lang.declare"); +dojo.require("dojo.data.Result"); +dojo.require("dojo.experimental"); + +/* summary: + * This is an abstract API that data provider implementations conform to. + * This file defines methods signatures and intentionally leaves all the + * methods unimplemented. + */ +dojo.experimental("dojo.data.Read"); + +dojo.declare("dojo.data.Read", null, { + get: + function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* value? */ defaultValue) { + /* summary: + * Returns a single attribute value. + * Returns defaultValue if item does not have a value for attribute. + * Returns null if null was explicitly set as the attribute value. + * Returns undefined if the item does not have a value for the given attribute. + * (So, if store.hasAttribute(item, attribute) returns false, then + * store.get(item, attribute) will return undefined.) + */ + + /* exceptions: + * Conforming implementations should throw an exception if *item* is not + * an item, or *attribute* is neither an attribute object or a string. + * examples: + * var darthVader = store.get(lukeSkywalker, "father"); + */ + dojo.unimplemented('dojo.data.Read.get'); + var attributeValue = null; + return attributeValue; // a literal, an item, null, or undefined (never an array) + }, + getValues: + function(/* item */ item, /* attribute || attribute-name-string */ attribute) { + /* summary: + * This getValues() method works just like the get() method, but getValues() + * always returns an array rather than a single attribute value. The array + * may be empty, may contain a single attribute value, or may contain many + * attribute values. + * If the item does not have a value for the given attribute, then getValues() + * will return an empty array: []. (So, if store.hasAttribute(item, attribute) + * returns false, then store.getValues(item, attribute) will return [].) + */ + + /* exceptions: + * Throws an exception if item is not an item, or attribute is neither an + * attribute object or a string. + * examples: + * var friendsOfLuke = store.get(lukeSkywalker, "friends"); + */ + dojo.unimplemented('dojo.data.Read.getValues'); + var array = null; + return array; // an array that may contain literals and items + }, + getAttributes: + function(/* item */ item) { + /* summary: + * Returns an array with all the attributes that this item has. + */ + + /* exceptions: + * Throws an exception if item is not an item. + * examples: + * var array = store.getAttributes(kermit); + */ + dojo.unimplemented('dojo.data.Read.getAttributes'); + var array = null; + return array; // array + }, + hasAttribute: + function(/* item */ item, /* attribute || attribute-name-string */ attribute) { + /* summary: + * Returns true if the given *item* has a value or the given *attribute*. + */ + + /* exceptions: + * Throws an exception if item is not an item, or attribute is neither an + * attribute object or a string. + * examples: + * var yes = store.hasAttribute(kermit, "color"); + */ + dojo.unimplemented('dojo.data.Read.hasAttribute'); + return false; // boolean + }, + hasAttributeValue: + function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* anything */ value) { + /* summary: + * Returns true if the given *value* is one of the values that getValue() + * would return. + */ + + /* exceptions: + * Throws an exception if item is not an item, or attribute is neither an + * attribute object or a string. + * examples: + * var yes = store.hasAttributeValue(kermit, "color", "green"); + */ + dojo.unimplemented('dojo.data.Read.hasAttributeValue'); + return false; // boolean + }, + isItem: + function(/* anything */ something) { + /* summary: + * Returns true if *something* is an item. Returns false if *something* + * is a literal or is any object other than an item. + */ + + /* examples: + * var yes = store.isItem(store.newItem()); + * var no = store.isItem("green"); + */ + dojo.unimplemented('dojo.data.Read.isItem'); + return false; // boolean + }, + find: + function(/* implementation-dependent */ query, /* object */ optionalKeywordArgs ) { + /* summary: + * Given a query, this method returns a Result object containing + * all the items in the query result set. + * description: + * A Result object will always be returned, even if the result set + * is empty. A Result object will always be returned immediately. + * By default the Result object will be fully populated with result + * items as soon as it is created (synchronously). The caller may request + * an asynchronous Result, meaning a Result that will be populated + * with result items at some point in the future. If the caller requests + * an asynchronous Result, the data store may return either a synchronous + * or asynchronous Result, whichever it prefers. Simple data store + * implementations may always return synchronous Results. + * For more info about the Result API, see dojo.data.Result + * query: + * The query may be optional in some data store implementations. + * The dojo.data.Read API does not specify the syntax or semantics + * of the query itself -- each different data store implementation + * may have its own notion of what a query should look like. + * In most implementations the query will probably be a string, but + * in some implementations the query might be a Date, or a number, + * or some complex keyword parameter object. The dojo.data.Read + * API is completely agnostic about what the query actually is. + * optionalKeywordArgs: + * The optionalKeywordArgs argument is a object like {async: true}. + * All implementations should accept {async: true} and {async: false} + * as valid parameters, although the API does not require that the + * the implementation actually perform asynchronously when + * {async: true} is set. Some implementations may take additional + * keyword options, such as {async: true, maxResults:100}. + */ + + /* exceptions: + * Throws an exception if the query is not valid, or if the query + * is required but was not supplied. + * examples: + * var results = store.find("all books"); + * var results = store.find(); + * var results = store.find("foo/bar", {async: true}); + * var results = store.find("foo/bar", {async: false}); + * var results = store.find({author:"King", {async: true, maxResults:100}); + */ + dojo.unimplemented('dojo.data.Read.find'); + var result = null; // new dojo.data.Result(). + return result; // an object that implements dojo.data.Result + }, + getIdentity: + function(/* item */ item) { + /* summary: + * Returns a unique identifer for an item. The return value will be + * either a string or something that has a toString() method (such as, + * for example, a dojo.uuid.Uuid object). + * description: + * ISSUE - + * Should we move this method out of dojo.data.Read, and put it somewhere + * else, like maybe dojo.data.Identity? + */ + + /* exceptions: + * Conforming implementations may throw an exception or return null if + * item is not an item. + * examples: + * var itemId = store.getIdentity(kermit); + * assert(kermit === store.getByIdentity(store.getIdentity(kermit))); + */ + dojo.unimplemented('dojo.data.Read.getIdentity'); + var itemIdentifyString = null; + return itemIdentifyString; // string + }, + getByIdentity: + function(/* string */ id) { + /* summary: + * Given the id of an item, this method returns the item that has that id. + * Conforming implementations should return null if there is no item with + * the given id. + * description: + * ISSUE - + * We may want to change the name from getByIdentity() to findByIdentity(), + * to reflect the fact that an implementation may not be able to get the + * item from a local cache, and may need to send a request to the server. + * ISSUE - + * Can this method run asynchronously? Should the return value be a Deferred? + * ISSUE - + * Should we move this method out of dojo.data.Read, and put it somewhere + * else, like maybe dojo.data.Identity? + */ + + /* examples: + * var alaska = store.getByIdentity("AK"); + * assert("AK" == store.getIdentity(store.getByIdentity("AK"))); + */ + dojo.unimplemented('dojo.data.Read.getByIdentity'); + var item = null; + return item; // item + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Result.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Attic/Result.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Result.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,158 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.data.Result"); +dojo.require("dojo.lang.declare"); +dojo.require("dojo.experimental"); + +/* summary: + * This is an abstract API used by data provider implementations. + * This file defines methods signatures and intentionally leaves all the + * methods unimplemented. + */ +dojo.experimental("dojo.data.Result"); + +dojo.declare("dojo.data.Result", null, { + forEach: + function(/* function */ callbackFunction, /* object? */ callbackObject, /* object? */ optionalKeywordArgs) { + /* summary: + * Loops through the result list, calling a callback function + * for each item in the result list. + * description: + * The forEach() method will call the callback function once for + * each item in the result list. The forEach() method will pass + * 3 arguments to the callbackFunction: an item, the index of + * item in the context of this forEach() loop, and the result object + * itself. The signature of this forEach() method was modeled on + * the forEach() method of Mozilla's Array object in JavaScript 1.6: + * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach + * The forEach() method will returns true if the entire result list + * has been looped through, or false if the result list has not yet + * been looped through. + * The forEach() method will ignore any return value returned by + * the callbackFunction. + * After the forEach() operation has finished (or been cancelled) + * result.forEach() can be called again on the same result object. + * ISSUES - + * We haven't yet decided what other parameters we might allow to + * support fancy features. Here are some ideas: + * results.forEach({callback:callbackFunction, onCompletion: finishedFunction}); + * results.forEach({callback:callbackFunction, first: 201, last: 300}); // partial loop + * results.forEach({callback:callbackFunction, first: 200, numItems: 50}); // partial loop from 200 to 250 + * CCM - How to specify datastore-specific options to allow caching n + * items before/after current window of items being viewed? + * callbackObject: + * If a callbackObject is provided the callbackFunction will be called + * in the context of the callbackObject (the callbackObject will be + * used as the 'this' for each invocation of the callbackFunction). + * If callbackObject is not provided, or is null, the global object + * associated with callback is used instead. + * optionalKeywordArgs: + * The forEach() method may accept a third parameter, which should be + * an object with keyword parameters. Different implementations may + * make use of different keyword paramters. Conforming + * implementations ignore keyword parameters that they don't + * recognize. + */ + + /* examples: + * var results = store.find("recent books"); // synchronous + * var results = store.find("all books", {sync: false}); // asynchronous + * someCallbackFunction = function(item, resultObject) {}; + * results.forEach(someCallbackFunction); + * results.forEach({object:someHandlerObject, callback:"someCallbackMethod"}); + */ + dojo.unimplemented('dojo.data.Result.forEach'); + return false; // boolean + }, + getLength: + function() { + /* summary: + * Returns an integer -- the number of items in the result list. + * Returns -1 if the length is not known when the method is called. + */ + dojo.unimplemented('dojo.data.Result.getLength'); + return -1; // integer + }, + inProgress: + function() { + /* summary: + * Returns true if a forEach() loop is in progress. + */ + dojo.unimplemented('dojo.data.Result.inProgress'); + return false; // boolean + }, + cancel: + function() { + /* summary: + * Calling cancel() stops any and all processing associated with this + * result object. + * description: + * If a forEach() loop is in progress, calling cancel() will stop + * the loop. If a store.find() is in progress, and that find() + * involves an XMLHttpRequest, calling cancel() will abort the + * XMLHttpRequest. If callbacks have been set using setOnFindCompleted() + * or setOnError(), calling cancel() will cause those callbacks to + * not be called under any circumstances. + */ + dojo.unimplemented('dojo.data.Result.cancel'); + }, + setOnFindCompleted: + function(/* function */ callbackFunction, /* object? */ callbackObject) { + /* summary: + * Allows you to register a callbackFunction that will + * be called when all the results are available. + * description: + * If a callbackObject is provided the callbackFunction will be + * called in the context of the callbackObject (the callbackObject + * will be used as the 'this' for each invocation of the + * callbackFunction). If callbackObject is not provided, or is + * null, the global object associated with callback is used instead. + * The setOnFindCompleted() method will ignore any return value + * returned by the callbackFunction. + * ISSUES - + * We have not yet decided what parameters the setOnFindCompleted() + * will pass to the callbackFunction... + * (A) The setOnFindCompleted() method will pass one parameter to the + * callbackFunction: the result object itself. + * (B) The setOnFindCompleted() method will pass two parameters to the + * callbackFunction: an iterator object, and the result object itself. + */ + dojo.unimplemented('dojo.data.Result.setOnFindCompleted'); + }, + setOnError: + function(/* function */ errorCallbackFunction, /* object? */ callbackObject) { + /* summary: + * Allows you to register a errorCallbackFunction that + * will be called if there is any sort of error. + * description: + * If a callbackObject is provided the errorCallbackFunction will + * be called in the context of the callbackObject (the callbackObject + * will be used as the 'this' for each invocation of the + * errorCallbackFunction). If callbackObject is not provided, or is + * null, the global object associated with callback is used instead. + * The setOnError() method will pass two parameters to the + * errorCallbackFunction: an Error object, and the result object + * itself: + * errorCallbackFunction(errorObject, resultObject); + * The setOnError() method will ignore any return value returned + * by the errorCallbackFunction. + */ + dojo.unimplemented('dojo.data.Result.setOnError'); + }, + getStore: + function() { + /* summary: + * Returns the datastore object that created this result list + */ + dojo.unimplemented('dojo.data.Result.getStore'); + return null; // an object that implements dojo.data.Read + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Write.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Attic/Write.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/data/Write.js 6 Nov 2006 14:50:06 -0000 1.1 @@ -0,0 +1,169 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.data.Write"); +dojo.require("dojo.lang.declare"); +dojo.require("dojo.data.Read"); +dojo.require("dojo.experimental"); + +/* summary: + * This is an abstract API that data provider implementations conform to. + * This file defines methods signatures and intentionally leaves all the + * methods unimplemented. + */ +dojo.experimental("dojo.data.Write"); + +dojo.declare("dojo.data.Write", dojo.data.Read, { + newItem: + function(/* object? */ keywordArgs) { + /* summary: + * Returns a newly created item. Sets the attributes of the new + * item based on the keywordArgs provided. + */ + + /* exceptions: + * Throws an exception if *keywordArgs* is a string or a number or + * anything other than a simple anonymous object. + * examples: + * var kermit = store.newItem({name: "Kermit"}); + */ + var newItem; + dojo.unimplemented('dojo.data.Write.newItem'); + return newItem; // item + }, + deleteItem: + function(/* item */ item) { + /* summary: + * Deletes an item from the store. + */ + + /* exceptions: + * Throws an exception if *item* is not an item (if store.isItem(item) + * returns false). + * examples: + * var success = store.deleteItem(kermit); + */ + dojo.unimplemented('dojo.data.Write.deleteItem'); + return false; // boolean + }, + set: + function(/* item */ item, /* attribute || string */ attribute, /* almost anything */ value) { + /* summary: + * Sets the value of an attribute on an item. + * Replaces any previous value or values. + */ + + /* exceptions: + * Throws an exception if *item* is not an item, or if *attribute* + * is neither an attribute object or a string. + * Throws an exception if *value* is undefined. + * examples: + * var success = store.set(kermit, "color", "green"); + */ + dojo.unimplemented('dojo.data.Write.set'); + return false; // boolean + }, + setValues: + function(/* item */ item, /* attribute || string */ attribute, /* array */ values) { + /* summary: + * Adds each value in the *values* array as a value of the given + * attribute on the given item. + * Replaces any previous value or values. + * Calling store.setValues(x, y, []) (with *values* as an empty array) has + * the same effect as calling store.clear(x, y). + */ + + /* exceptions: + * Throws an exception if *values* is not an array, if *item* is not an + * item, or if *attribute* is neither an attribute object or a string. + * examples: + * var success = store.setValues(kermit, "color", ["green", "aqua"]); + * success = store.setValues(kermit, "color", []); + * if (success) {assert(!store.hasAttribute(kermit, "color"));} + */ + dojo.unimplemented('dojo.data.Write.setValues'); + return false; // boolean + }, + clear: + function(/* item */ item, /* attribute || string */ attribute) { + /* summary: + * Deletes all the values of an attribute on an item. + */ + + /* exceptions: + * Throws an exception if *item* is not an item, or if *attribute* + * is neither an attribute object or a string. + * examples: + * var success = store.clear(kermit, "color"); + * if (success) {assert(!store.hasAttribute(kermit, "color"));} + */ + dojo.unimplemented('dojo.data.Write.clear'); + return false; // boolean + }, + save: + function() { + /* summary: + * Saves to the server all the changes that have been made locally. + * The save operation may take some time. By default the save will + * be done synchronously, before the call returns. The caller may + * be request an asynchronous save by passing {async: true}. + * If the caller requests an asynchronous save, the data store may do + * either a synchronous or asynchronous save, whichever it prefers. + * Different data store implementations may take additional optional + * parameters. + * description: + * ISSUE - + * Should the async save take a callback, like this: + * store.save({async: true, onComplete: callback}); + * Or should the async save return a Deferred, like this: + * var deferred = store.save({async: true}); + * deferred.addCallbacks(successCallback, errorCallback); + * Or should save() return boolean, like this: + * var success = store.save(); + */ + + /* examples: + * var success = store.save(); + * var success = store.save({async: true}); + */ + dojo.unimplemented('dojo.data.Write.save'); + return false; // boolean + }, + revert: + function() { + /* summary: + * Discards any unsaved changes. + */ + + /* examples: + * var success = store.revert(); + */ + dojo.unimplemented('dojo.data.Write.revert'); + return false; // boolean + }, + isDirty: + function(/* item (or store) */ item) { + /* summary: + * Returns true if the given item has been modified since the last save(). + * If the datastore object itself is given as a parameter instead of an + * item, then this method returns true if any item has been modified since + * the last save(). + */ + + /* exceptions: + * Throws an exception if *item* is neither an item nor the datastore itself. + * examples: + * var trueOrFalse = store.isDirty(kermit); // true if kermit is dirty + * var trueOrFalse = store.isDirty(store); // true if any item is dirty + */ + dojo.unimplemented('dojo.data.Write.isDirty'); + return false; // boolean + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/Attic/common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/common.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,496 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.date.common"); + + +/* Supplementary Date Functions + *******************************/ + +dojo.date.setDayOfYear = function(/*Date*/dateObject, /*Number*/dayOfYear){ + // summary: sets dateObject according to day of the year (1..366) + dateObject.setMonth(0); + dateObject.setDate(dayOfYear); + return dateObject; // Date +} + +dojo.date.getDayOfYear = function(/*Date*/dateObject){ + // summary: gets the day of the year as represented by dateObject + var fullYear = dateObject.getFullYear(); + var lastDayOfPrevYear = new Date(fullYear-1, 11, 31); + return Math.floor((dateObject.getTime() - + lastDayOfPrevYear.getTime()) / 86400000); // Number +} + + +dojo.date.setWeekOfYear = function(/*Date*/dateObject, /*Number*/week, /*Number*/firstDay){ + if(arguments.length == 1){ firstDay = 0; } // Sunday + dojo.unimplemented("dojo.date.setWeekOfYear"); +} + +dojo.date.getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDay){ + if(arguments.length == 1){ firstDay = 0; } // Sunday + + // work out the first day of the year corresponding to the week + var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1); + var day = firstDayOfYear.getDay(); + firstDayOfYear.setDate(firstDayOfYear.getDate() - + day + firstDay - (day > firstDay ? 7 : 0)); + + return Math.floor((dateObject.getTime() - + firstDayOfYear.getTime()) / 604800000); +} + +dojo.date.setIsoWeekOfYear = function(/*Date*/dateObject, /*Number*/week, /*Number*/firstDay){ + // summary: unimplemented + if (arguments.length == 1) { firstDay = 1; } // Monday + dojo.unimplemented("dojo.date.setIsoWeekOfYear"); +} + +dojo.date.getIsoWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDay) { + // summary: unimplemented + if (arguments.length == 1) { firstDay = 1; } // Monday + dojo.unimplemented("dojo.date.getIsoWeekOfYear"); +} + + +/* Informational Functions + **************************/ + +//DEPRECATED: These timezone arrays will be deprecated in 0.5 +dojo.date.shortTimezones = ["IDLW", "BET", "HST", "MART", "AKST", "PST", "MST", + "CST", "EST", "AST", "NFT", "BST", "FST", "AT", "GMT", "CET", "EET", "MSK", + "IRT", "GST", "AFT", "AGTT", "IST", "NPT", "ALMT", "MMT", "JT", "AWST", + "JST", "ACST", "AEST", "LHST", "VUT", "NFT", "NZT", "CHAST", "PHOT", + "LINT"]; +dojo.date.timezoneOffsets = [-720, -660, -600, -570, -540, -480, -420, -360, + -300, -240, -210, -180, -120, -60, 0, 60, 120, 180, 210, 240, 270, 300, + 330, 345, 360, 390, 420, 480, 540, 570, 600, 630, 660, 690, 720, 765, 780, + 840]; +/* +dojo.date.timezones = ["International Date Line West", "Bering Standard Time", + "Hawaiian Standard Time", "Marquesas Time", "Alaska Standard Time", + "Pacific Standard Time (USA)", "Mountain Standard Time", + "Central Standard Time (USA)", "Eastern Standard Time (USA)", + "Atlantic Standard Time", "Newfoundland Time", "Brazil Standard Time", + "Fernando de Noronha Standard Time (Brazil)", "Azores Time", + "Greenwich Mean Time", "Central Europe Time", "Eastern Europe Time", + "Moscow Time", "Iran Standard Time", "Gulf Standard Time", + "Afghanistan Time", "Aqtobe Time", "Indian Standard Time", "Nepal Time", + "Almaty Time", "Myanmar Time", "Java Time", + "Australian Western Standard Time", "Japan Standard Time", + "Australian Central Standard Time", "Lord Hove Standard Time (Australia)", + "Vanuata Time", "Norfolk Time (Australia)", "New Zealand Standard Time", + "Chatham Standard Time (New Zealand)", "Phoenix Islands Time (Kribati)", + "Line Islands Time (Kribati)"]; +*/ + +dojo.date.getDaysInMonth = function(/*Date*/dateObject){ + // summary: returns the number of days in the month used by dateObject + var month = dateObject.getMonth(); + var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + if (month == 1 && dojo.date.isLeapYear(dateObject)) { return 29; } // Number + else { return days[month]; } // Number +} + +dojo.date.isLeapYear = function(/*Date*/dateObject){ +// summary: +// Determines if the year of the dateObject is a leap year +// +// description: +// Leap years are years with an additional day YYYY-02-29, where the year +// number is a multiple of four with the following exception: If a year +// is a multiple of 100, then it is only a leap year if it is also a +// multiple of 400. For example, 1900 was not a leap year, but 2000 is one. + + var year = dateObject.getFullYear(); + return (year%400 == 0) ? true : (year%100 == 0) ? false : (year%4 == 0) ? true : false; // Boolean +} + +// FIXME: This is not localized +dojo.date.getTimezoneName = function(/*Date*/dateObject){ +// summary: +// Get the user's time zone as provided by the browser +// +// dateObject: needed because the timezone may vary with time (daylight savings) +// +// description: +// Try to get time zone info from toString or toLocaleString +// method of the Date object -- UTC offset is not a time zone. +// See http://www.twinsun.com/tz/tz-link.htm +// Note: results may be inconsistent across browsers. + + var str = dateObject.toString(); // Start looking in toString + var tz = ''; // The result -- return empty string if nothing found + var match; + + // First look for something in parentheses -- fast lookup, no regex + var pos = str.indexOf('('); + if (pos > -1) { + pos++; + tz = str.substring(pos, str.indexOf(')')); + } + // If at first you don't succeed ... + else{ + // If IE knows about the TZ, it appears before the year + // Capital letters or slash before a 4-digit year + // at the end of string + var pat = /([A-Z\/]+) \d{4}$/; + if((match = str.match(pat))) { + tz = match[1]; + } + // Some browsers (e.g. Safari) glue the TZ on the end + // of toLocaleString instead of putting it in toString + else{ + str = dateObject.toLocaleString(); + // Capital letters or slash -- end of string, + // after space + pat = / ([A-Z\/]+)$/; + if((match = str.match(pat))) { + tz = match[1]; + } + } + } + + // Make sure it doesn't somehow end up return AM or PM + return tz == 'AM' || tz == 'PM' ? '' : tz; //String +} + + +//FIXME: not localized +dojo.date.getOrdinal = function(dateObject){ + // summary: returns the appropriate suffix (English only) for the day of the month, e.g. 'st' for 1, 'nd' for 2, etc.) + var date = dateObject.getDate(); + + if(date%100 != 11 && date%10 == 1){ return "st"; } // String + else if(date%100 != 12 && date%10 == 2){ return "nd"; } // String + else if(date%100 != 13 && date%10 == 3){ return "rd"; } // String + else{ return "th"; } // String +} + + +/* compare and add + ******************/ +dojo.date.compareTypes={ + // summary + // bitmask for comparison operations. + DATE:1, TIME:2 +}; +dojo.date.compare=function(/* Date */ dateA, /* Date */ dateB, /* dojo.date.compareTypes */ options){ + // summary + // Compare two date objects by date, time, or both. Returns 0 if equal, positive if a > b, else negative. + var dA=dateA; + var dB=dateB||new Date(); + var now=new Date(); + //FIXME: shorten this code + with(dojo.date.compareTypes){ + var opt=options||(DATE|TIME); + var d1=new Date( + (opt&DATE)?dA.getFullYear():now.getFullYear(), + (opt&DATE)?dA.getMonth():now.getMonth(), + (opt&DATE)?dA.getDate():now.getDate(), + (opt&TIME)?dA.getHours():0, + (opt&TIME)?dA.getMinutes():0, + (opt&TIME)?dA.getSeconds():0 + ); + var d2=new Date( + (opt&DATE)?dB.getFullYear():now.getFullYear(), + (opt&DATE)?dB.getMonth():now.getMonth(), + (opt&DATE)?dB.getDate():now.getDate(), + (opt&TIME)?dB.getHours():0, + (opt&TIME)?dB.getMinutes():0, + (opt&TIME)?dB.getSeconds():0 + ); + } + if(d1.valueOf()>d2.valueOf()){ + return 1; // int + } + if(d1.valueOf() 0) ? 5 : -5; + weeks = (incr > 0) ? ((incr-5)/5) : ((incr+5)/5); + } + else { + days = mod; + weeks = parseInt(incr/5); + } + // Get weekday value for orig date param + strt = dt.getDay(); + // Orig date is Sat / positive incrementer + // Jump over Sun + if (strt == 6 && incr > 0) { + adj = 1; + } + // Orig date is Sun / negative incrementer + // Jump back over Sat + else if (strt == 0 && incr < 0) { + adj = -1; + } + // Get weekday val for the new date + trgt = (strt + days); + // New date is on Sat or Sun + if (trgt == 0 || trgt == 6) { + adj = (incr > 0) ? 2 : -2; + } + // Increment by number of weeks plus leftover days plus + // weekend adjustments + sum.setDate(dat + (7*weeks) + days + adj); + break; + case HOUR: + sum.setHours(sum.getHours()+incr); + break; + case MINUTE: + sum.setMinutes(sum.getMinutes()+incr); + break; + case SECOND: + sum.setSeconds(sum.getSeconds()+incr); + break; + case MILLISECOND: + sum.setMilliseconds(sum.getMilliseconds()+incr); + break; + default: + // Do nothing + break; + } + } + + return sum; // Date +}; + +dojo.date.diff = function(/* Date */ dtA, /* Date */ dtB, /* dojo.date.dateParts */ interv){ +// summary: +// Get the difference in a specific unit of time (e.g., number of months, weeks, +// days, etc.) between two dates. +// +// dtA: +// A Javascript Date object +// +// dtB: +// A Javascript Date object +// +// interv: +// A constant representing the interval, e.g. YEAR, MONTH, DAY. See dojo.date.dateParts. + + // Accept timestamp input + if(typeof dtA == 'number'){dtA = new Date(dtA);} + if(typeof dtB == 'number'){dtB = new Date(dtB);} + var yeaDiff = dtB.getFullYear() - dtA.getFullYear(); + var monDiff = (dtB.getMonth() - dtA.getMonth()) + (yeaDiff * 12); + var msDiff = dtB.getTime() - dtA.getTime(); // Millisecs + var secDiff = msDiff/1000; + var minDiff = secDiff/60; + var houDiff = minDiff/60; + var dayDiff = houDiff/24; + var weeDiff = dayDiff/7; + var delta = 0; // Integer return value + + with(dojo.date.dateParts){ + switch(interv){ + case YEAR: + delta = yeaDiff; + break; + case QUARTER: + var mA = dtA.getMonth(); + var mB = dtB.getMonth(); + // Figure out which quarter the months are in + var qA = Math.floor(mA/3) + 1; + var qB = Math.floor(mB/3) + 1; + // Add quarters for any year difference between the dates + qB += (yeaDiff * 4); + delta = qB - qA; + break; + case MONTH: + delta = monDiff; + break; + case WEEK: + // Truncate instead of rounding + // Don't use Math.floor -- value may be negative + delta = parseInt(weeDiff); + break; + case DAY: + delta = dayDiff; + break; + case WEEKDAY: + var days = Math.round(dayDiff); + var weeks = parseInt(days/7); + var mod = days % 7; + + // Even number of weeks + if (mod == 0) { + days = weeks*5; + } + // Weeks plus spare change (< 7 days) + else { + var adj = 0; + var aDay = dtA.getDay(); + var bDay = dtB.getDay(); + + weeks = parseInt(days/7); + mod = days % 7; + // Mark the date advanced by the number of + // round weeks (may be zero) + var dtMark = new Date(dtA); + dtMark.setDate(dtMark.getDate()+(weeks*7)); + var dayMark = dtMark.getDay(); + // Spare change days -- 6 or less + // ---------- + // Positive diff + if (dayDiff > 0) { + switch (true) { + // Range starts on Sat + case aDay == 6: + adj = -1; + break; + // Range starts on Sun + case aDay == 0: + adj = 0; + break; + // Range ends on Sat + case bDay == 6: + adj = -1; + break; + // Range ends on Sun + case bDay == 0: + adj = -2; + break; + // Range contains weekend + case (dayMark + mod) > 5: + adj = -2; + break; + default: + // Do nothing + break; + } + } + // Negative diff + else if (dayDiff < 0) { + switch (true) { + // Range starts on Sat + case aDay == 6: + adj = 0; + break; + // Range starts on Sun + case aDay == 0: + adj = 1; + break; + // Range ends on Sat + case bDay == 6: + adj = 2; + break; + // Range ends on Sun + case bDay == 0: + adj = 1; + break; + // Range contains weekend + case (dayMark + mod) < 0: + adj = 2; + break; + default: + // Do nothing + break; + } + } + days += adj; + days -= (weeks*2); + } + delta = days; + + break; + case HOUR: + delta = houDiff; + break; + case MINUTE: + delta = minDiff; + break; + case SECOND: + delta = secDiff; + break; + case MILLISECOND: + delta = msDiff; + break; + default: + // Do nothing + break; + } + } + + // Round for fractional values and DST leaps + return Math.round(delta); // Number (integer) +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/format.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/Attic/format.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/format.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,922 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.date.format"); + +dojo.require("dojo.date.common"); +dojo.require("dojo.date.supplemental"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.func"); +dojo.require("dojo.string.common"); +dojo.require("dojo.i18n.common"); + +// Load the bundles containing localization information for +// names and formats +dojo.requireLocalization("dojo.i18n.calendar", "gregorian"); +dojo.requireLocalization("dojo.i18n.calendar", "gregorianExtras"); + +//NOTE: Everything in this module assumes Gregorian calendars. +// Other calendars will be implemented in separate modules. + +(function(){ +dojo.date.format = function(/*Date*/dateObject, /*Object?*/options){ +// +// summary: +// Format a Date object as a String, using locale-specific settings. +// +// description: +// Create a string from a Date object using a known localized pattern. +// By default, this method formats both date and time from dateObject. +// Formatting patterns are chosen appropriate to the locale. Different +// formatting lengths may be chosen, with "full" used by default. +// Custom patterns may be used or registered with translations using +// the addCustomBundle method. +// Formatting patterns are implemented using the syntax described at +// http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns +// +// dateObject: +// the date and/or time to be formatted. If a time only is formatted, +// the values in the year, month, and day fields are irrelevant. The +// opposite is true when formatting only dates. +// +// options: object {selector: string, formatLength: string, datePattern: string, timePattern: string, locale: string} +// selector- choice of timeOnly,dateOnly (default: date and time) +// formatLength- choice of long, short, medium or full (plus any custom additions). Defaults to 'full' +// datePattern,timePattern- override pattern with this string +// am,pm- override strings for am/pm in times +// locale- override the locale used to determine formatting rules +// + + if(typeof options == "string"){ + dojo.deprecated("dojo.date.format", "To format dates with POSIX-style strings, please use dojo.date.strftime instead", "0.5"); + return dojo.date.strftime(dateObject, options); + } + + // Format a pattern without literals + function formatPattern(dateObject, pattern){ + return pattern.replace(/[a-zA-Z]+/g, function(match){ + var s; + var c = match.charAt(0); + var l = match.length; + var pad; + var widthList = ["abbr", "wide", "narrow"]; + switch(c){ + case 'G': + if(l>3){dojo.unimplemented("Era format not implemented");} + s = info.eras[dateObject.getFullYear() < 0 ? 1 : 0]; + break; + case 'y': + s = dateObject.getFullYear(); + switch(l){ + case 1: + break; + case 2: + s = String(s).substr(-2); + break; + default: + pad = true; + } + break; + case 'Q': + case 'q': + s = Math.ceil((dateObject.getMonth()+1)/3); + switch(l){ + case 1: case 2: + pad = true; + break; + case 3: + case 4: + dojo.unimplemented("Quarter format not implemented"); + } + break; + case 'M': + case 'L': + var m = dateObject.getMonth(); + var width; + switch(l){ + case 1: case 2: + s = m+1; pad = true; + break; + case 3: case 4: case 5: + width = widthList[l-3]; + break; + } + if(width){ + var type = (c == "L") ? "standalone" : "format"; + var prop = ["months",type,width].join("-"); + s = info[prop][m]; + } + break; + case 'w': + var firstDay = 0; + s = dojo.date.getWeekOfYear(dateObject, firstDay); pad = true; + break; + case 'd': + s = dateObject.getDate(); pad = true; + break; + case 'D': + s = dojo.date.getDayOfYear(dateObject); pad = true; + break; + case 'E': + case 'e': + case 'c': // REVIEW: don't see this in the spec? + var d = dateObject.getDay(); + var width; + switch(l){ + case 1: case 2: + if(c == 'e'){ + var first = dojo.date.getFirstDayOfWeek(options.locale); + d = (d-first+7)%7; + } + if(c != 'c'){ + s = d+1; pad = true; + break; + } + // else fallthrough... + case 3: case 4: case 5: + width = widthList[l-3]; + break; + } + if(width){ + var type = (c == "c") ? "standalone" : "format"; + var prop = ["days",type,width].join("-"); + s = info[prop][d]; + } + break; + case 'a': + var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm'; + s = info[timePeriod]; + break; + case 'h': + case 'H': + case 'K': + case 'k': + var h = dateObject.getHours(); + // strange choices in the date format make it impossible to write this succinctly + switch (c) { + case 'h': // 1-12 + s = (h % 12) || 12; + break; + case 'H': // 0-23 + s = h; + break; + case 'K': // 0-11 + s = (h % 12); + break; + case 'k': // 1-24 + s = h || 24; + break; + } + pad = true; + break; + case 'm': + s = dateObject.getMinutes(); pad = true; + break; + case 's': + s = dateObject.getSeconds(); pad = true; + break; + case 'S': + s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); + break; + case 'v': // FIXME: don't know what this is. seems to be same as z? + case 'z': + // We only have one timezone to offer; the one from the browser + s = dojo.date.getTimezoneName(dateObject); + if(s){break;} + l=4; + // fallthrough... use GMT if tz not available + case 'Z': + var offset = dateObject.getTimezoneOffset(); + var tz = [ + (offset<=0 ? "+" : "-"), + dojo.string.pad(Math.floor(Math.abs(offset)/60), 2), + dojo.string.pad(Math.abs(offset)% 60, 2) + ]; + if(l==4){ + tz.splice(0, 0, "GMT"); + tz.splice(3, 0, ":"); + } + s = tz.join(""); + break; + case 'Y': + case 'u': + case 'W': + case 'F': + case 'g': + case 'A': + dojo.debug(match+" modifier not yet implemented"); + s = "?"; + break; + default: + dojo.raise("dojo.date.format: invalid pattern char: "+pattern); + } + if(pad){ s = dojo.string.pad(s, l); } + return s; + }); + } + + options = options || {}; + + var locale = dojo.hostenv.normalizeLocale(options.locale); + var formatLength = options.formatLength || 'full'; + var info = dojo.date._getGregorianBundle(locale); + var str = []; + var sauce = dojo.lang.curry(this, formatPattern, dateObject); + if(options.selector != "timeOnly"){ + var datePattern = options.datePattern || info["dateFormat-"+formatLength]; + if(datePattern){str.push(_processPattern(datePattern, sauce));} + } + if(options.selector != "dateOnly"){ + var timePattern = options.timePattern || info["timeFormat-"+formatLength]; + if(timePattern){str.push(_processPattern(timePattern, sauce));} + } + var result = str.join(" "); //TODO: use locale-specific pattern to assemble date + time + return result; /*String*/ +}; + +dojo.date.parse = function(/*String*/value, /*Object?*/options){ +// +// summary: +// Convert a properly formatted string to a primitive Date object, +// using locale-specific settings. +// +// description: +// Create a Date object from a string using a known localized pattern. +// By default, this method parses looking for both date and time in the string. +// Formatting patterns are chosen appropriate to the locale. Different +// formatting lengths may be chosen, with "full" used by default. +// Custom patterns may be used or registered with translations using +// the addCustomBundle method. +// Formatting patterns are implemented using the syntax described at +// http://www.unicode.org/reports/tr35/#Date_Format_Patterns +// +// value: +// A string representation of a date +// +// options: object {selector: string, formatLength: string, datePattern: string, timePattern: string, locale: string, strict: boolean} +// selector- choice of timeOnly, dateOnly, dateTime (default: dateOnly) +// formatLength- choice of long, short, medium or full (plus any custom additions). Defaults to 'full' +// datePattern,timePattern- override pattern with this string +// am,pm- override strings for am/pm in times +// locale- override the locale used to determine formatting rules +// strict- strict parsing, off by default +// + + options = options || {}; + var locale = dojo.hostenv.normalizeLocale(options.locale); + var info = dojo.date._getGregorianBundle(locale); + var formatLength = options.formatLength || 'full'; + if(!options.selector){ options.selector = 'dateOnly'; } + var datePattern = options.datePattern || info["dateFormat-" + formatLength]; + var timePattern = options.timePattern || info["timeFormat-" + formatLength]; + + var pattern; + if(options.selector == 'dateOnly'){ + pattern = datePattern; + } + else if(options.selector == 'timeOnly'){ + pattern = timePattern; + }else if(options.selector == 'dateTime'){ + pattern = datePattern + ' ' + timePattern; //TODO: use locale-specific pattern to assemble date + time + }else{ + var msg = "dojo.date.parse: Unknown selector param passed: '" + options.selector + "'."; + msg += " Defaulting to date pattern."; + dojo.debug(msg); + pattern = datePattern; + } + + var groups = []; + var dateREString = _processPattern(pattern, dojo.lang.curry(this, _buildDateTimeRE, groups, info, options)); + var dateRE = new RegExp("^" + dateREString + "$"); + + var match = dateRE.exec(value); + if(!match){ + return null; + } + + var widthList = ['abbr', 'wide', 'narrow']; + //1972 is a leap year. We want to avoid Feb 29 rolling over into Mar 1, + //in the cases where the year is parsed after the month and day. + var result = new Date(1972, 0); + var expected = {}; + for(var i=1; i2) { + if(!options.strict){ + //Tolerate abbreviating period in month part + v = v.replace(/\./g,''); + //Case-insensitive + v = v.toLowerCase(); + } + var months = info['months-format-' + widthList[l-3]].concat(); + for (var j=0; j 15 + } else if(v == am && hours == 12){ + result.setHours(0); //12am -> 0 + } + break; + case 'K': //hour (1-24) + if(v==24){v=0;} + // fallthrough... + case 'h': //hour (1-12) + case 'H': //hour (0-23) + case 'k': //hour (0-11) + //TODO: strict bounds checking, padding + if(v>23){ + dojo.debug("dojo.date.parse: Illegal hours value"); + return null; + } + + //in the 12-hour case, adjusting for am/pm requires the 'a' part + //which for now we will assume always comes after the 'h' part + result.setHours(v); + break; + case 'm': //minutes + result.setMinutes(v); + break; + case 's': //seconds + result.setSeconds(v); + break; + case 'S': //milliseconds + result.setMilliseconds(v); + break; + default: + dojo.unimplemented("dojo.date.parse: unsupported pattern char=" + grp.charAt(0)); + } + } + + //validate parse date fields versus input date fields + if(expected.year && result.getFullYear() != expected.year){ + dojo.debug("Parsed year: '" + result.getFullYear() + "' did not match input year: '" + expected.year + "'."); + return null; + } + if(expected.month && result.getMonth() != expected.month){ + dojo.debug("Parsed month: '" + result.getMonth() + "' did not match input month: '" + expected.month + "'."); + return null; + } + if(expected.date && result.getDate() != expected.date){ + dojo.debug("Parsed day of month: '" + result.getDate() + "' did not match input day of month: '" + expected.date + "'."); + return null; + } + + //TODO: implement a getWeekday() method in order to test + //validity of input strings containing 'EEE' or 'EEEE'... + + return result; /*Date*/ +}; + +function _processPattern(pattern, applyPattern, applyLiteral, applyAll){ + // Process a pattern with literals in it + // Break up on single quotes, treat every other one as a literal, except '' which becomes ' + var identity = function(x){return x;}; + applyPattern = applyPattern || identity; + applyLiteral = applyLiteral || identity; + applyAll = applyAll || identity; + + //split on single quotes (which escape literals in date format strings) + //but preserve escaped single quotes (e.g., o''clock) + var chunks = pattern.match(/(''|[^'])+/g); + var literal = false; + + for(var i=0; i2) ? '\\S+' : '\\d{1,2}'; + break; + case 'd': + s = '\\d{1,2}'; + break; + case 'E': + s = '\\S+'; + break; + case 'h': + case 'H': + case 'K': + case 'k': + s = '\\d{1,2}'; + break; + case 'm': + case 's': + s = '[0-5]\\d'; + break; + case 'S': + s = '\\d{1,3}'; + break; + case 'a': + var am = options.am || info.am || 'AM'; + var pm = options.pm || info.pm || 'PM'; + if(options.strict){ + s = am + '|' + pm; + }else{ + s = am; + s += (am != am.toLowerCase()) ? '|' + am.toLowerCase() : ''; + s += '|'; + s += (pm != pm.toLowerCase()) ? pm + '|' + pm.toLowerCase() : pm; + } + break; + default: + dojo.unimplemented("parse of date format, pattern=" + pattern); + } + + if(groups){ groups.push(match); } + +//FIXME: replace whitespace within final regexp with more flexible whitespace match instead? + //tolerate whitespace + return '\\s*(' + s + ')\\s*'; + }); +} +})(); + +//TODO: try to common strftime and format code somehow? + +dojo.date.strftime = function(/*Date*/dateObject, /*String*/format, /*String?*/locale){ +// +// summary: +// Formats the date object using the specifications of the POSIX strftime function +// +// description: +// see + + // zero pad + var padChar = null; + function _(s, n){ + return dojo.string.pad(s, n || 2, padChar || "0"); + } + + var info = dojo.date._getGregorianBundle(locale); + + function $(property){ + switch (property){ + case "a": // abbreviated weekday name according to the current locale + return dojo.date.getDayShortName(dateObject, locale); + + case "A": // full weekday name according to the current locale + return dojo.date.getDayName(dateObject, locale); + + case "b": + case "h": // abbreviated month name according to the current locale + return dojo.date.getMonthShortName(dateObject, locale); + + case "B": // full month name according to the current locale + return dojo.date.getMonthName(dateObject, locale); + + case "c": // preferred date and time representation for the current + // locale + return dojo.date.format(dateObject, {locale: locale}); + + case "C": // century number (the year divided by 100 and truncated + // to an integer, range 00 to 99) + return _(Math.floor(dateObject.getFullYear()/100)); + + case "d": // day of the month as a decimal number (range 01 to 31) + return _(dateObject.getDate()); + + case "D": // same as %m/%d/%y + return $("m") + "/" + $("d") + "/" + $("y"); + + case "e": // day of the month as a decimal number, a single digit is + // preceded by a space (range ' 1' to '31') + if(padChar == null){ padChar = " "; } + return _(dateObject.getDate()); + + case "f": // month as a decimal number, a single digit is + // preceded by a space (range ' 1' to '12') + if(padChar == null){ padChar = " "; } + return _(dateObject.getMonth()+1); + + case "g": // like %G, but without the century. + break; + + case "G": // The 4-digit year corresponding to the ISO week number + // (see %V). This has the same format and value as %Y, + // except that if the ISO week number belongs to the + // previous or next year, that year is used instead. + dojo.unimplemented("unimplemented modifier 'G'"); + break; + + case "F": // same as %Y-%m-%d + return $("Y") + "-" + $("m") + "-" + $("d"); + + case "H": // hour as a decimal number using a 24-hour clock (range + // 00 to 23) + return _(dateObject.getHours()); + + case "I": // hour as a decimal number using a 12-hour clock (range + // 01 to 12) + return _(dateObject.getHours() % 12 || 12); + + case "j": // day of the year as a decimal number (range 001 to 366) + return _(dojo.date.getDayOfYear(dateObject), 3); + + case "k": // Hour as a decimal number using a 24-hour clock (range + // 0 to 23 (space-padded)) + if (padChar == null) { padChar = " "; } + return _(dateObject.getHours()); + + case "l": // Hour as a decimal number using a 12-hour clock (range + // 1 to 12 (space-padded)) + if (padChar == null) { padChar = " "; } + return _(dateObject.getHours() % 12 || 12); + + case "m": // month as a decimal number (range 01 to 12) + return _(dateObject.getMonth() + 1); + + case "M": // minute as a decimal number + return _(dateObject.getMinutes()); + + case "n": + return "\n"; + + case "p": // either `am' or `pm' according to the given time value, + // or the corresponding strings for the current locale + return info[dateObject.getHours() < 12 ? "am" : "pm"]; + + case "r": // time in a.m. and p.m. notation + return $("I") + ":" + $("M") + ":" + $("S") + " " + $("p"); + + case "R": // time in 24 hour notation + return $("H") + ":" + $("M"); + + case "S": // second as a decimal number + return _(dateObject.getSeconds()); + + case "t": + return "\t"; + + case "T": // current time, equal to %H:%M:%S + return $("H") + ":" + $("M") + ":" + $("S"); + + case "u": // weekday as a decimal number [1,7], with 1 representing + // Monday + return String(dateObject.getDay() || 7); + + case "U": // week number of the current year as a decimal number, + // starting with the first Sunday as the first day of the + // first week + return _(dojo.date.getWeekOfYear(dateObject)); + + case "V": // week number of the year (Monday as the first day of the + // week) as a decimal number [01,53]. If the week containing + // 1 January has four or more days in the new year, then it + // is considered week 1. Otherwise, it is the last week of + // the previous year, and the next week is week 1. + return _(dojo.date.getIsoWeekOfYear(dateObject)); + + case "W": // week number of the current year as a decimal number, + // starting with the first Monday as the first day of the + // first week + return _(dojo.date.getWeekOfYear(dateObject, 1)); + + case "w": // day of the week as a decimal, Sunday being 0 + return String(dateObject.getDay()); + + case "x": // preferred date representation for the current locale + // without the time + return dojo.date.format(dateObject, {selector:'dateOnly', locale:locale}); + + case "X": // preferred time representation for the current locale + // without the date + return dojo.date.format(dateObject, {selector:'timeOnly', locale:locale}); + + case "y": // year as a decimal number without a century (range 00 to + // 99) + return _(dateObject.getFullYear()%100); + + case "Y": // year as a decimal number including the century + return String(dateObject.getFullYear()); + + case "z": // time zone or name or abbreviation + var timezoneOffset = dateObject.getTimezoneOffset(); + return (timezoneOffset > 0 ? "-" : "+") + + _(Math.floor(Math.abs(timezoneOffset)/60)) + ":" + + _(Math.abs(timezoneOffset)%60); + + case "Z": // time zone or name or abbreviation + return dojo.date.getTimezoneName(dateObject); + + case "%": + return "%"; + } + } + + // parse the formatting string and construct the resulting string + var string = ""; + var i = 0; + var index = 0; + var switchCase = null; + while ((index = format.indexOf("%", i)) != -1){ + string += format.substring(i, index++); + + // inspect modifier flag + switch (format.charAt(index++)) { + case "_": // Pad a numeric result string with spaces. + padChar = " "; break; + case "-": // Do not pad a numeric result string. + padChar = ""; break; + case "0": // Pad a numeric result string with zeros. + padChar = "0"; break; + case "^": // Convert characters in result string to uppercase. + switchCase = "upper"; break; + case "*": // Convert characters in result string to lowercase + switchCase = "lower"; break; + case "#": // Swap the case of the result string. + switchCase = "swap"; break; + default: // no modifier flag so decrement the index + padChar = null; index--; break; + } + + // toggle case if a flag is set + var property = $(format.charAt(index++)); + switch (switchCase){ + case "upper": + property = property.toUpperCase(); + break; + case "lower": + property = property.toLowerCase(); + break; + case "swap": // Upper to lower, and versey-vicea + var compareString = property.toLowerCase(); + var swapString = ''; + var j = 0; + var ch = ''; + while (j < property.length){ + ch = property.charAt(j); + swapString += (ch == compareString.charAt(j)) ? + ch.toUpperCase() : ch.toLowerCase(); + j++; + } + property = swapString; + break; + default: + break; + } + switchCase = null; + + string += property; + i = index; + } + string += format.substring(i); + + return string; // String +}; + +(function(){ +var _customFormats = []; +dojo.date.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){ +// +// summary: +// Add a reference to a bundle containing localized custom formats to be +// used by date/time formatting and parsing routines. +// +// description: +// The user may add custom localized formats where the bundle has properties following the +// same naming convention used by dojo for the CLDR data: dateFormat-xxxx / timeFormat-xxxx +// The pattern string should match the format used by the CLDR. +// See dojo.date.format for details. +// The resources must be loaded by dojo.requireLocalization() prior to use + + _customFormats.push({pkg:packageName,name:bundleName}); +}; + +dojo.date._getGregorianBundle = function(/*String*/locale){ + var gregorian = {}; + dojo.lang.forEach(_customFormats, function(desc){ + var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale); + gregorian = dojo.lang.mixin(gregorian, bundle); + }, this); + return gregorian; /*Object*/ +}; +})(); + +dojo.date.addCustomFormats("dojo.i18n.calendar","gregorian"); +dojo.date.addCustomFormats("dojo.i18n.calendar","gregorianExtras"); + +dojo.date.getNames = function(/*String*/item, /*String*/type, /*String?*/use, /*String?*/locale){ +// +// summary: +// Used to get localized strings for day or month names. +// +// item: 'months' || 'days' +// type: 'wide' || 'narrow' || 'abbr' (e.g. "Monday", "Mon", or "M" respectively, in English) +// use: 'standAlone' || 'format' (default) +// locale: override locale used to find the names + + var label; + var lookup = dojo.date._getGregorianBundle(locale); + var props = [item, use, type]; + if(use == 'standAlone'){ + label = lookup[props.join('-')]; + } + props[1] = 'format'; + + // return by copy so changes won't be made accidentally to the in-memory model + return (label || lookup[props.join('-')]).concat(); /*Array*/ +}; + +// Convenience methods + +dojo.date.getDayName = function(/*Date*/dateObject, /*String?*/locale){ +// summary: gets the full localized day of the week corresponding to the date object + return dojo.date.getNames('days', 'wide', 'format', locale)[dateObject.getDay()]; /*String*/ +}; + +dojo.date.getDayShortName = function(/*Date*/dateObject, /*String?*/locale){ +// summary: gets the abbreviated localized day of the week corresponding to the date object + return dojo.date.getNames('days', 'abbr', 'format', locale)[dateObject.getDay()]; /*String*/ +}; + +dojo.date.getMonthName = function(/*Date*/dateObject, /*String?*/locale){ +// summary: gets the full localized month name corresponding to the date object + return dojo.date.getNames('months', 'wide', 'format', locale)[dateObject.getMonth()]; /*String*/ +}; + +dojo.date.getMonthShortName = function(/*Date*/dateObject, /*String?*/locale){ +// summary: gets the abbreviated localized month name corresponding to the date object + return dojo.date.getNames('months', 'abbr', 'format', locale)[dateObject.getMonth()]; /*String*/ +}; + +//FIXME: not localized +dojo.date.toRelativeString = function(/*Date*/dateObject){ +// summary: +// Returns an description in English of the date relative to the current date. Note: this is not localized yet. English only. +// +// description: Example returns: +// - "1 minute ago" +// - "4 minutes ago" +// - "Yesterday" +// - "2 days ago" + + var now = new Date(); + var diff = (now - dateObject) / 1000; + var end = " ago"; + var future = false; + if(diff < 0){ + future = true; + end = " from now"; + diff = -diff; + } + + if(diff < 60){ + diff = Math.round(diff); + return diff + " second" + (diff == 1 ? "" : "s") + end; + } + if(diff < 60*60){ + diff = Math.round(diff/60); + return diff + " minute" + (diff == 1 ? "" : "s") + end; + } + if(diff < 60*60*24){ + diff = Math.round(diff/3600); + return diff + " hour" + (diff == 1 ? "" : "s") + end; + } + if(diff < 60*60*24*7){ + diff = Math.round(diff/(3600*24)); + if(diff == 1){ + return future ? "Tomorrow" : "Yesterday"; + }else{ + return diff + " days" + end; + } + } + return dojo.date.format(dateObject); // String +}; + +//FIXME: SQL methods can probably be moved to a different module without i18n deps + +dojo.date.toSql = function(/*Date*/dateObject, /*Boolean?*/noTime){ +// summary: +// Convert a Date to a SQL string +// noTime: whether to ignore the time portion of the Date. Defaults to false. + + return dojo.date.strftime(dateObject, "%F" + !noTime ? " %T" : ""); // String +}; + +dojo.date.fromSql = function(/*String*/sqlDate){ +// summary: +// Convert a SQL date string to a JavaScript Date object + + var parts = sqlDate.split(/[\- :]/g); + while(parts.length < 6){ + parts.push(0); + } + return new Date(parts[0], (parseInt(parts[1],10)-1), parts[2], parts[3], parts[4], parts[5]); // Date +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/serialize.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/Attic/serialize.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/serialize.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,175 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.date.serialize"); + +dojo.require("dojo.string.common"); + +/* ISO 8601 Functions + *********************/ + +dojo.date.setIso8601 = function(/*Date*/dateObject, /*String*/formattedString){ + // summary: sets a Date object based on an ISO 8601 formatted string (uses date and time) + var comps = (formattedString.indexOf("T") == -1) ? formattedString.split(" ") : formattedString.split("T"); + dateObject = dojo.date.setIso8601Date(dateObject, comps[0]); + if(comps.length == 2){ dateObject = dojo.date.setIso8601Time(dateObject, comps[1]); } + return dateObject; /* Date or null */ +}; + +dojo.date.fromIso8601 = function(/*String*/formattedString){ + // summary: returns a Date object based on an ISO 8601 formatted string (uses date and time) + return dojo.date.setIso8601(new Date(0, 0), formattedString); +}; + +dojo.date.setIso8601Date = function(/*String*/dateObject, /*String*/formattedString){ + // summary: sets a Date object based on an ISO 8601 formatted string (date only) + var regexp = "^([0-9]{4})((-?([0-9]{2})(-?([0-9]{2}))?)|" + + "(-?([0-9]{3}))|(-?W([0-9]{2})(-?([1-7]))?))?$"; + var d = formattedString.match(new RegExp(regexp)); + if(!d){ + dojo.debug("invalid date string: " + formattedString); + return null; // null + } + var year = d[1]; + var month = d[4]; + var date = d[6]; + var dayofyear = d[8]; + var week = d[10]; + var dayofweek = d[12] ? d[12] : 1; + + dateObject.setFullYear(year); + + if(dayofyear){ + dateObject.setMonth(0); + dateObject.setDate(Number(dayofyear)); + } + else if(week){ + dateObject.setMonth(0); + dateObject.setDate(1); + var gd = dateObject.getDay(); + var day = gd ? gd : 7; + var offset = Number(dayofweek) + (7 * Number(week)); + + if(day <= 4){ dateObject.setDate(offset + 1 - day); } + else{ dateObject.setDate(offset + 8 - day); } + } else{ + if(month){ + dateObject.setDate(1); + dateObject.setMonth(month - 1); + } + if(date){ dateObject.setDate(date); } + } + + return dateObject; // Date +}; + +dojo.date.fromIso8601Date = function(/*String*/formattedString){ + // summary: returns a Date object based on an ISO 8601 formatted string (date only) + return dojo.date.setIso8601Date(new Date(0, 0), formattedString); +}; + +dojo.date.setIso8601Time = function(/*Date*/dateObject, /*String*/formattedString){ + // summary: sets a Date object based on an ISO 8601 formatted string (time only) + + // first strip timezone info from the end + var timezone = "Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$"; + var d = formattedString.match(new RegExp(timezone)); + + var offset = 0; // local time if no tz info + if(d){ + if(d[0] != 'Z'){ + offset = (Number(d[3]) * 60) + Number(d[5]); + offset *= ((d[2] == '-') ? 1 : -1); + } + offset -= dateObject.getTimezoneOffset(); + formattedString = formattedString.substr(0, formattedString.length - d[0].length); + } + + // then work out the time + var regexp = "^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(\.([0-9]+))?)?)?$"; + d = formattedString.match(new RegExp(regexp)); + if(!d){ + dojo.debug("invalid time string: " + formattedString); + return null; // null + } + var hours = d[1]; + var mins = Number((d[3]) ? d[3] : 0); + var secs = (d[5]) ? d[5] : 0; + var ms = d[7] ? (Number("0." + d[7]) * 1000) : 0; + + dateObject.setHours(hours); + dateObject.setMinutes(mins); + dateObject.setSeconds(secs); + dateObject.setMilliseconds(ms); + + if(offset !== 0){ + dateObject.setTime(dateObject.getTime() + offset * 60000); + } + return dateObject; // Date +}; + +dojo.date.fromIso8601Time = function(/*String*/formattedString){ + // summary: returns a Date object based on an ISO 8601 formatted string (date only) + return dojo.date.setIso8601Time(new Date(0, 0), formattedString); +}; + + +/* RFC-3339 Date Functions + *************************/ + +dojo.date.toRfc3339 = function(/*Date?*/dateObject, /*String?*/selector){ +// summary: +// Format a JavaScript Date object as a string according to RFC 3339 +// +// dateObject: +// A JavaScript date, or the current date and time, by default +// +// selector: +// "dateOnly" or "timeOnly" to format selected portions of the Date object. +// Date and time will be formatted by default. + +//FIXME: tolerate Number, string input? + if(!dateObject){ + dateObject = new Date(); + } + + var _ = dojo.string.pad; + var formattedDate = []; + if(selector != "timeOnly"){ + var date = [_(dateObject.getFullYear(),4), _(dateObject.getMonth()+1,2), _(dateObject.getDate(),2)].join('-'); + formattedDate.push(date); + } + if(selector != "dateOnly"){ + var time = [_(dateObject.getHours(),2), _(dateObject.getMinutes(),2), _(dateObject.getSeconds(),2)].join(':'); + var timezoneOffset = dateObject.getTimezoneOffset(); + time += (timezoneOffset > 0 ? "-" : "+") + + _(Math.floor(Math.abs(timezoneOffset)/60),2) + ":" + + _(Math.abs(timezoneOffset)%60,2); + formattedDate.push(time); + } + return formattedDate.join('T'); // String +}; + +dojo.date.fromRfc3339 = function(/*String*/rfcDate){ +// summary: +// Create a JavaScript Date object from a string formatted according to RFC 3339 +// +// rfcDate: +// A string such as 2005-06-30T08:05:00-07:00 +// "any" is also supported in place of a time. + + // backwards compatible support for use of "any" instead of just not + // including the time + if(rfcDate.indexOf("Tany")!=-1){ + rfcDate = rfcDate.replace("Tany",""); + } + var dateObject = new Date(); + return dojo.date.setIso8601(dateObject, rfcDate); // Date or null +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/supplemental.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/Attic/supplemental.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/date/supplemental.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,76 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.date.supplemental"); + +dojo.date.getFirstDayOfWeek = function(/*String?*/locale){ +// summary: Returns a zero-based index for first day of the week +// description: +// Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar. +// e.g. Sunday (returns 0), or Monday (returns 1) + + // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay + var firstDay = {/*default is 1=Monday*/ + mv:5, + ae:6,af:6,bh:6,dj:6,dz:6,eg:6,er:6,et:6,iq:6,ir:6,jo:6,ke:6,kw:6,lb:6,ly:6,ma:6,om:6,qa:6,sa:6, + sd:6,so:6,tn:6,ye:6, + as:0,au:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,ie:0,il:0,is:0,jm:0,jp:0,kg:0,kr:0,la:0, + mh:0,mo:0,mp:0,mt:0,nz:0,ph:0,pk:0,sg:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,vi:0,za:0,zw:0, + et:0,mw:0,ng:0,tj:0, + gb:0, + sy:4 + }; + + locale = dojo.hostenv.normalizeLocale(locale); + var country = locale.split("-")[1]; + var dow = firstDay[country]; + return (typeof dow == 'undefined') ? 1 : dow; /*Number*/ +}; + +dojo.date.getWeekend = function(/*String?*/locale){ +// summary: Returns a hash containing the start and end days of the weekend +// description: +// Returns a hash containing the start and end days of the weekend according to local custom using locale, +// or by default in the user's locale. +// e.g. {start:6, end:0} + + // from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End} + var weekendStart = {/*default is 6=Saturday*/ + eg:5,il:5,sy:5, + 'in':0, + ae:4,bh:4,dz:4,iq:4,jo:4,kw:4,lb:4,ly:4,ma:4,om:4,qa:4,sa:4,sd:4,tn:4,ye:4 + }; + + var weekendEnd = {/*default is 0=Sunday*/ + ae:5,bh:5,dz:5,iq:5,jo:5,kw:5,lb:5,ly:5,ma:5,om:5,qa:5,sa:5,sd:5,tn:5,ye:5,af:5,ir:5, + eg:6,il:6,sy:6 + }; + + locale = dojo.hostenv.normalizeLocale(locale); + var country = locale.split("-")[1]; + var start = weekendStart[country]; + var end = weekendEnd[country]; + if(typeof start == 'undefined'){start=6;} + if(typeof end == 'undefined'){end=0;} + return {start:start, end:end}; /*Object {start,end}*/ +}; + +dojo.date.isWeekend = function(/*Date?*/dateObj, /*String?*/locale){ +// summary: +// Determines if the date falls on a weekend, according to local custom. + + var weekend = dojo.date.getWeekend(locale); + var day = (dateObj || new Date()).getDay(); + if(weekend.end= weekend.start && day <= weekend.end; // Boolean +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Firebug.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/Firebug.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Firebug.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,62 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.debug.Firebug"); +dojo.deprecated("dojo.debug.Firebug is slated for removal in 0.5; use dojo.debug.console instead.", "0.5"); + +// summary +// Firebug Console logger. +// This package redirects the normal dojo debugging output to the firebug console. It does +// so by sending the entire object to the console, rather than just overriding dojo.hostenv.println +// so that firebugs object inspector can be taken advantage of. + +if (dojo.render.html.moz) { + if (console && console.log) { + var consoleLog = function() { + if (!djConfig.isDebug) { return ; } + + var args = dojo.lang.toArray(arguments); + args.splice(0,0, "DEBUG: "); + console.log.apply(console, args); + } + + dojo.debug = consoleLog; + + dojo.debugDeep=consoleLog; + + dojo.debugShallow=function(obj) { + if (!djConfig.isDebug) { return; } + + if (dojo.lang.isArray(obj)) { + console.log('Array: ', obj); + for (var i=0; x 0.4"); + } +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/arrow_hide.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/arrow_hide.gif,v diff -u -N Binary files differ Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/arrow_show.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/arrow_show.gif,v diff -u -N Binary files differ Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/console.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/console.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/console.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,115 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.debug.console"); +dojo.require("dojo.logging.ConsoleLogger"); + +// summary: +// Console logger, for use with FireFox Firebug, Safari and Opera's consoles. +// description: +// This package redirects the normal dojo debugging output to the console log in modern browsers. +// When using Firebug, it does this by sending the entire object to the console, +// rather than just overriding dojo.hostenv.println, so that Firebug's interactive +// object inspector is available. +// see: http://www.joehewitt.com/software/firebug/docs.php + +if (window.console) { + if (console.info != null) { + // using a later version of Firebug -- lots of fun stuff! + + dojo.hostenv.println = function() { + // summary: Write all of the arguments to the Firebug console + // description: Uses console.info() so that the (i) icon prints next to the debug line + // rather than munging the arguments by adding "DEBUG:" in front of them. + // This allows us to use Firebug's string handling to do interesting things + if (!djConfig.isDebug) { return; } + console.info.apply(console, arguments); + } + dojo.debug=dojo.hostenv.println; + dojo.debugDeep = dojo.debug; + + dojo.debugShallow = function(/*Object*/ obj, /*Boolean?*/showMethods, /*Boolean?*/sort) { + // summary: Write first-level properties of obj to the console. + // obj: Object or Array to debug + // showMethods: Pass false to skip outputing methods of object, any other value will output them. + // sort: Pass false to skip sorting properties, any other value will sort. + if (!djConfig.isDebug) { return; } + + showMethods = (showMethods != false); + sort = (sort != false); + + // handle null or something without a constructor (in which case we don't know the type) + if (obj == null || obj.constructor == null) { + return dojo.debug(obj); + } + + // figure out type via a standard constructor (Object, String, Date, etc) + var type = obj.declaredClass; + if (type == null) { + type = obj.constructor.toString().match(/function\s*(.*)\(/); + if (type) { type = type[1] }; + } + // if we got a viable type, use Firebug's interactive property dump feature + if (type) { + if (type == "String" || type == "Number") { + return dojo.debug(type+": ", obj); + } + if (showMethods && !sort) { + var sortedObj = obj; + } else { + var propNames = []; + if (showMethods) { + for (var prop in obj) { + propNames.push(prop); + } + } else { + for (var prop in obj) { + if (typeof obj[prop] != "function") { propNames.push(prop); } + else dojo.debug(prop); + } + } + if (sort) propNames.sort(); + var sortedObj = {}; + dojo.lang.forEach(propNames, function(prop) { + sortedObj[prop] = obj[prop]; + }); + } + + return dojo.debug(type+": %o\n%2.o",obj,sortedObj); + } + + // otherwise just output the constructor + object, + // which is nice for a DOM element, etc + return dojo.debug(obj.constructor + ": ", obj); + } + + } else if (console.log != null) { + // using Safari or an old version of Firebug + dojo.hostenv.println=function() { + if (!djConfig.isDebug) { return ; } + // make sure we're only writing a single string to Safari's console + var args = dojo.lang.toArray(arguments); + console.log("DEBUG: " + args.join(" ")); + } + dojo.debug=dojo.hostenv.println; + } else { + // not supported + dojo.debug("dojo.debug.console requires Firebug > 0.4"); + } +} else if (dojo.render.html.opera) { + // using Opera 8.0 or later + if (opera && opera.postError) { + dojo.hostenv.println=opera.postError; + // summary: hook debugging up to Opera's postError routine + } else { + dojo.debug("dojo.debug.Opera requires Opera > 8.0"); + } +} + Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/deep.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/deep.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/deep.html 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,362 @@ + + +Deep Debugger + + + + + +

Javascript Object Browser

+ +
+ + + \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/spacer.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/debug/Attic/spacer.gif,v diff -u -N Binary files differ Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/DragAndDrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/DragAndDrop.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/DragAndDrop.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,173 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.declare"); +dojo.provide("dojo.dnd.DragAndDrop"); + +dojo.declare("dojo.dnd.DragSource", null, { + type: "", + + onDragEnd: function(){ + }, + + onDragStart: function(){ + }, + + /* + * This function gets called when the DOM element was + * selected for dragging by the HtmlDragAndDropManager. + */ + onSelected: function(){ + }, + + unregister: function(){ + dojo.dnd.dragManager.unregisterDragSource(this); + }, + + reregister: function(){ + dojo.dnd.dragManager.registerDragSource(this); + } +}, function(){ + + //dojo.profile.start("DragSource"); + + var dm = dojo.dnd.dragManager; + if(dm["registerDragSource"]){ // side-effect prevention + dm.registerDragSource(this); + } + + //dojo.profile.end("DragSource"); + +}); + +dojo.declare("dojo.dnd.DragObject", null, { + type: "", + + onDragStart: function(){ + // gets called directly after being created by the DragSource + // default action is to clone self as icon + }, + + onDragMove: function(){ + // this changes the UI for the drag icon + // "it moves itself" + }, + + onDragOver: function(){ + }, + + onDragOut: function(){ + }, + + onDragEnd: function(){ + }, + + // normal aliases + onDragLeave: this.onDragOut, + onDragEnter: this.onDragOver, + + // non-camel aliases + ondragout: this.onDragOut, + ondragover: this.onDragOver +}, function(){ + var dm = dojo.dnd.dragManager; + if(dm["registerDragObject"]){ // side-effect prevention + dm.registerDragObject(this); + } +}); + +dojo.declare("dojo.dnd.DropTarget", null, { + + acceptsType: function(type){ + if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard + if(!dojo.lang.inArray(this.acceptedTypes, type)) { return false; } + } + return true; + }, + + accepts: function(dragObjects){ + if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard + for (var i = 0; i < dragObjects.length; i++) { + if (!dojo.lang.inArray(this.acceptedTypes, + dragObjects[i].type)) { return false; } + } + } + return true; + }, + + unregister: function(){ + dojo.dnd.dragManager.unregisterDropTarget(this); + }, + + onDragOver: function(){ + }, + + onDragOut: function(){ + }, + + onDragMove: function(){ + }, + + onDropStart: function(){ + }, + + onDrop: function(){ + }, + + onDropEnd: function(){ + } +}, function(){ + if (this.constructor == dojo.dnd.DropTarget) { return; } // need to be subclassed + this.acceptedTypes = []; + dojo.dnd.dragManager.registerDropTarget(this); +}); + +// NOTE: this interface is defined here for the convenience of the DragManager +// implementor. It is expected that in most cases it will be satisfied by +// extending a native event (DOM event in HTML and SVG). +dojo.dnd.DragEvent = function(){ + this.dragSource = null; + this.dragObject = null; + this.target = null; + this.eventStatus = "success"; + // + // can be one of: + // [ "dropSuccess", "dropFailure", "dragMove", + // "dragStart", "dragEnter", "dragLeave"] + // +} +/* + * The DragManager handles listening for low-level events and dispatching + * them to higher-level primitives like drag sources and drop targets. In + * order to do this, it must keep a list of the items. + */ +dojo.declare("dojo.dnd.DragManager", null, { + selectedSources: [], + dragObjects: [], + dragSources: [], + registerDragSource: function(){}, + dropTargets: [], + registerDropTarget: function(){}, + lastDragTarget: null, + currentDragTarget: null, + onKeyDown: function(){}, + onMouseOut: function(){}, + onMouseMove: function(){}, + onMouseUp: function(){} +}); + +// NOTE: despite the existance of the DragManager class, there will be a +// singleton drag manager provided by the renderer-specific D&D support code. +// It is therefore sane for us to assign instance variables to the DragManager +// prototype + +// The renderer-specific file will define the following object: +// dojo.dnd.dragManager = null; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/HtmlDragAndDrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/HtmlDragAndDrop.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/HtmlDragAndDrop.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,508 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.dnd.HtmlDragAndDrop"); + +dojo.require("dojo.dnd.HtmlDragManager"); +dojo.require("dojo.dnd.DragAndDrop"); + +dojo.require("dojo.html.*"); +dojo.require("dojo.html.display"); +dojo.require("dojo.html.util"); +dojo.require("dojo.html.selection"); +dojo.require("dojo.html.iframe"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.lfx.*"); +dojo.require("dojo.event.*"); + +dojo.declare("dojo.dnd.HtmlDragSource", dojo.dnd.DragSource, { + dragClass: "", // CSS classname(s) applied to node when it is being dragged + + onDragStart: function(){ + var dragObj = new dojo.dnd.HtmlDragObject(this.dragObject, this.type); + if(this.dragClass) { dragObj.dragClass = this.dragClass; } + + if (this.constrainToContainer) { + dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode); + } + + return dragObj; + }, + + setDragHandle: function(node){ + node = dojo.byId(node); + dojo.dnd.dragManager.unregisterDragSource(this); + this.domNode = node; + dojo.dnd.dragManager.registerDragSource(this); + }, + + setDragTarget: function(node){ + this.dragObject = node; + }, + + constrainTo: function(container) { + this.constrainToContainer = true; + if (container) { + this.constrainingContainer = container; + } + }, + + /* + * + * see dojo.dnd.DragSource.onSelected + */ + onSelected: function() { + for (var i=0; i this.constraints.maxX) { x = this.constraints.maxX; } + if (y > this.constraints.maxY) { y = this.constraints.maxY; } + } + + this.setAbsolutePosition(x, y); + + dojo.event.topic.publish('dragMove', { source: this } ); + }, + + /** + * Set the position of the drag clone. (x,y) is relative to . + */ + setAbsolutePosition: function(x, y){ + // The drag clone is attached to document.body so this is trivial + if(!this.disableY) { this.dragClone.style.top = y + "px"; } + if(!this.disableX) { this.dragClone.style.left = x + "px"; } + }, + + + /** + * If the drag operation returned a success we reomve the clone of + * ourself from the original position. If the drag operation returned + * failure we slide back over to where we came from and end the operation + * with a little grace. + */ + onDragEnd: function(e){ + switch(e.dragStatus){ + + case "dropSuccess": + dojo.html.removeNode(this.dragClone); + this.dragClone = null; + break; + + case "dropFailure": // slide back to the start + var startCoords = dojo.html.getAbsolutePosition(this.dragClone, true); + // offset the end so the effect can be seen + var endCoords = { left: this.dragStartPosition.x + 1, + top: this.dragStartPosition.y + 1}; + + // animate + var anim = dojo.lfx.slideTo(this.dragClone, endCoords, 500, dojo.lfx.easeOut); + var dragObject = this; + dojo.event.connect(anim, "onEnd", function (e) { + // pause for a second (not literally) and disappear + dojo.lang.setTimeout(function() { + dojo.html.removeNode(dragObject.dragClone); + // Allow drag clone to be gc'ed + dragObject.dragClone = null; + }, + 200); + }); + anim.play(); + break; + } + + dojo.event.topic.publish('dragEnd', { source: this } ); + }, + + squelchOnClick: function(e){ + // squelch this onClick() event because it's the result of a drag (it's not a real click) + dojo.event.browser.stopEvent(e); + + // disconnect after a short delay to prevent "Null argument to unrollAdvice()" warning + dojo.lang.setTimeout(function() { + dojo.event.disconnect(this.domNode, "onclick", this, "squelchOnClick"); + },50); + }, + + constrainTo: function(container) { + this.constrainToContainer=true; + if (container) { + this.constrainingContainer = container; + } else { + this.constrainingContainer = this.domNode.parentNode; + } + } +}, function(node, type){ + this.domNode = dojo.byId(node); + this.type = type; + this.constrainToContainer = false; + this.dragSource = null; +}); + +dojo.declare("dojo.dnd.HtmlDropTarget", dojo.dnd.DropTarget, { + vertical: false, + onDragOver: function(e){ + if(!this.accepts(e.dragObjects)){ return false; } + + // cache the positions of the child nodes + this.childBoxes = []; + for (var i = 0, child; i < this.domNode.childNodes.length; i++) { + child = this.domNode.childNodes[i]; + if (child.nodeType != dojo.html.ELEMENT_NODE) { continue; } + var pos = dojo.html.getAbsolutePosition(child, true); + var inner = dojo.html.getBorderBox(child); + this.childBoxes.push({top: pos.y, bottom: pos.y+inner.height, + left: pos.x, right: pos.x+inner.width, height: inner.height, + width: inner.width, node: child}); + } + + // TODO: use dummy node + + return true; + }, + + _getNodeUnderMouse: function(e){ + // find the child + for (var i = 0, child; i < this.childBoxes.length; i++) { + with (this.childBoxes[i]) { + if (e.pageX >= left && e.pageX <= right && + e.pageY >= top && e.pageY <= bottom) { return i; } + } + } + + return -1; + }, + + createDropIndicator: function() { + this.dropIndicator = document.createElement("div"); + with (this.dropIndicator.style) { + position = "absolute"; + zIndex = 999; + if(this.vertical){ + borderLeftWidth = "1px"; + borderLeftColor = "black"; + borderLeftStyle = "solid"; + height = dojo.html.getBorderBox(this.domNode).height + "px"; + top = dojo.html.getAbsolutePosition(this.domNode, true).y + "px"; + }else{ + borderTopWidth = "1px"; + borderTopColor = "black"; + borderTopStyle = "solid"; + width = dojo.html.getBorderBox(this.domNode).width + "px"; + left = dojo.html.getAbsolutePosition(this.domNode, true).x + "px"; + } + } + }, + + onDragMove: function(e, dragObjects){ + var i = this._getNodeUnderMouse(e); + + if(!this.dropIndicator){ + this.createDropIndicator(); + } + + var gravity = this.vertical ? dojo.html.gravity.WEST : dojo.html.gravity.NORTH; + var hide = false; + if(i < 0) { + if(this.childBoxes.length) { + var before = (dojo.html.gravity(this.childBoxes[0].node, e) & gravity); + if(before){ hide = true; } + } else { + var before = true; + } + } else { + var child = this.childBoxes[i]; + var before = (dojo.html.gravity(child.node, e) & gravity); + if(child.node === dragObjects[0].dragSource.domNode){ + hide = true; + }else{ + var currentPosChild = before ? + (i>0?this.childBoxes[i-1]:child) : + (i + * (draggable selection) + * (dragObject generation) + * mouse-move -> + * (draggable movement) + * (droppable detection) + * (inform droppable) + * (inform dragObject) + * mouse-up + * (inform/destroy dragObject) + * (inform draggable) + * (inform droppable) + * 2.) mouse-down -> mouse-down + * (click-hold context menu) + * 3.) mouse-click -> + * (draggable selection) + * shift-mouse-click -> + * (augment draggable selection) + * mouse-down -> + * (dragObject generation) + * mouse-move -> + * (draggable movement) + * (droppable detection) + * (inform droppable) + * (inform dragObject) + * mouse-up + * (inform draggable) + * (inform droppable) + * 4.) mouse-up + * (clobber draggable selection) + */ + disabled: false, // to kill all dragging! + nestedTargets: false, + mouseDownTimer: null, // used for click-hold operations + dsCounter: 0, + dsPrefix: "dojoDragSource", + + // dimension calculation cache for use durring drag + dropTargetDimensions: [], + + currentDropTarget: null, + // currentDropTargetPoints: null, + previousDropTarget: null, + _dragTriggered: false, + + selectedSources: [], + dragObjects: [], + + // mouse position properties + currentX: null, + currentY: null, + lastX: null, + lastY: null, + mouseDownX: null, + mouseDownY: null, + threshold: 7, + + dropAcceptable: false, + + cancelEvent: function(e){ e.stopPropagation(); e.preventDefault();}, + + // method over-rides + registerDragSource: function(ds){ + //dojo.profile.start("register DragSource"); + + if(ds["domNode"]){ + // FIXME: dragSource objects SHOULD have some sort of property that + // references their DOM node, we shouldn't just be passing nodes and + // expecting it to work. + //dojo.profile.start("register DragSource 1"); + var dp = this.dsPrefix; + var dpIdx = dp+"Idx_"+(this.dsCounter++); + ds.dragSourceId = dpIdx; + this.dragSources[dpIdx] = ds; + ds.domNode.setAttribute(dp, dpIdx); + //dojo.profile.end("register DragSource 1"); + + //dojo.profile.start("register DragSource 2"); + + // so we can drag links + if(dojo.render.html.ie){ + //dojo.profile.start("register DragSource IE"); + + dojo.event.browser.addListener(ds.domNode, "ondragstart", this.cancelEvent); + // terribly slow + //dojo.event.connect(ds.domNode, "ondragstart", this.cancelEvent); + //dojo.profile.end("register DragSource IE"); + + } + //dojo.profile.end("register DragSource 2"); + + } + //dojo.profile.end("register DragSource"); + }, + + unregisterDragSource: function(ds){ + if (ds["domNode"]){ + var dp = this.dsPrefix; + var dpIdx = ds.dragSourceId; + delete ds.dragSourceId; + delete this.dragSources[dpIdx]; + ds.domNode.setAttribute(dp, null); + if(dojo.render.html.ie){ + dojo.event.browser.removeListener(ds.domNode, "ondragstart", this.cancelEvent); + } + } + }, + + registerDropTarget: function(dt){ + this.dropTargets.push(dt); + }, + + unregisterDropTarget: function(dt){ + var index = dojo.lang.find(this.dropTargets, dt, true); + if (index>=0) { + this.dropTargets.splice(index, 1); + } + }, + + /** + * Get the DOM element that is meant to drag. + * Loop through the parent nodes of the event target until + * the element is found that was created as a DragSource and + * return it. + * + * @param event object The event for which to get the drag source. + */ + getDragSource: function(e){ + var tn = e.target; + if(tn === dojo.body()){ return; } + var ta = dojo.html.getAttribute(tn, this.dsPrefix); + while((!ta)&&(tn)){ + tn = tn.parentNode; + if((!tn)||(tn === dojo.body())){ return; } + ta = dojo.html.getAttribute(tn, this.dsPrefix); + } + return this.dragSources[ta]; + }, + + onKeyDown: function(e){ + }, + + onMouseDown: function(e){ + if(this.disabled) { return; } + + // only begin on left click + if(dojo.render.html.ie) { + if(e.button != 1) { return; } + } else if(e.which != 1) { + return; + } + + var target = e.target.nodeType == dojo.html.TEXT_NODE ? + e.target.parentNode : e.target; + + // do not start drag involvement if the user is interacting with + // a form element. + if(dojo.html.isTag(target, "button", "textarea", "input", "select", "option")) { + return; + } + + // find a selection object, if one is a parent of the source node + var ds = this.getDragSource(e); + + // this line is important. if we aren't selecting anything then + // we need to return now, so preventDefault() isn't called, and thus + // the event is propogated to other handling code + if(!ds){ return; } + + if(!dojo.lang.inArray(this.selectedSources, ds)){ + this.selectedSources.push(ds); + ds.onSelected(); + } + + this.mouseDownX = e.pageX; + this.mouseDownY = e.pageY; + + // Must stop the mouse down from being propogated, or otherwise can't + // drag links in firefox. + // WARNING: preventing the default action on all mousedown events + // prevents user interaction with the contents. + e.preventDefault(); + + dojo.event.connect(document, "onmousemove", this, "onMouseMove"); + }, + + onMouseUp: function(e, cancel){ + // if we aren't dragging then ignore the mouse-up + // (in particular, don't call preventDefault(), because other + // code may need to process this event) + if(this.selectedSources.length==0){ + return; + } + + this.mouseDownX = null; + this.mouseDownY = null; + this._dragTriggered = false; + // e.preventDefault(); + e.dragSource = this.dragSource; + // let ctrl be used for multiselect or another action + // if I use same key to trigger treeV3 node selection and here, + // I have bugs with drag'n'drop. why ?? no idea.. + if((!e.shiftKey)&&(!e.ctrlKey)){ + //if(!e.shiftKey){ + if(this.currentDropTarget) { + this.currentDropTarget.onDropStart(); + } + dojo.lang.forEach(this.dragObjects, function(tempDragObj){ + var ret = null; + if(!tempDragObj){ return; } + if(this.currentDropTarget) { + e.dragObject = tempDragObj; + + // NOTE: we can't get anything but the current drop target + // here since the drag shadow blocks mouse-over events. + // This is probelematic for dropping "in" something + var ce = this.currentDropTarget.domNode.childNodes; + if(ce.length > 0){ + e.dropTarget = ce[0]; + while(e.dropTarget == tempDragObj.domNode){ + e.dropTarget = e.dropTarget.nextSibling; + } + }else{ + e.dropTarget = this.currentDropTarget.domNode; + } + if(this.dropAcceptable){ + ret = this.currentDropTarget.onDrop(e); + }else{ + this.currentDropTarget.onDragOut(e); + } + } + + e.dragStatus = this.dropAcceptable && ret ? "dropSuccess" : "dropFailure"; + // decouple the calls for onDragEnd, so they don't block the execution here + // ie. if the onDragEnd would call an alert, the execution here is blocked until the + // user has confirmed the alert box and then the rest of the dnd code is executed + // while the mouse doesnt "hold" the dragged object anymore ... and so on + dojo.lang.delayThese([ + function() { + // in FF1.5 this throws an exception, see + // http://dojotoolkit.org/pipermail/dojo-interest/2006-April/006751.html + try{ + tempDragObj.dragSource.onDragEnd(e) + } catch(err) { + // since the problem seems passing e, we just copy all + // properties and try the copy ... + var ecopy = {}; + for (var i in e) { + if (i=="type") { // the type property contains the exception, no idea why... + ecopy.type = "mouseup"; + continue; + } + ecopy[i] = e[i]; + } + tempDragObj.dragSource.onDragEnd(ecopy); + } + } + , function() {tempDragObj.onDragEnd(e)}]); + }, this); + + this.selectedSources = []; + this.dragObjects = []; + this.dragSource = null; + if(this.currentDropTarget) { + this.currentDropTarget.onDropEnd(); + } + } else { + //dojo.debug("special click"); + } + + dojo.event.disconnect(document, "onmousemove", this, "onMouseMove"); + this.currentDropTarget = null; + }, + + onScroll: function(){ + //dojo.profile.start("DNDManager updateoffset"); + for(var i = 0; i < this.dragObjects.length; i++) { + if(this.dragObjects[i].updateDragOffset) { + this.dragObjects[i].updateDragOffset(); + } + } + //dojo.profile.end("DNDManager updateoffset"); + + // TODO: do not recalculate, only adjust coordinates + if (this.dragObjects.length) { + this.cacheTargetLocations(); + } + }, + + _dragStartDistance: function(x, y){ + if((!this.mouseDownX)||(!this.mouseDownX)){ + return; + } + var dx = Math.abs(x-this.mouseDownX); + var dx2 = dx*dx; + var dy = Math.abs(y-this.mouseDownY); + var dy2 = dy*dy; + return parseInt(Math.sqrt(dx2+dy2), 10); + }, + + cacheTargetLocations: function(){ + dojo.profile.start("cacheTargetLocations"); + + this.dropTargetDimensions = []; + dojo.lang.forEach(this.dropTargets, function(tempTarget){ + var tn = tempTarget.domNode; + //only cache dropTarget which can accept current dragSource + if(!tn || dojo.lang.find(tempTarget.acceptedTypes, this.dragSource.type) < 0){ return; } + var abs = dojo.html.getAbsolutePosition(tn, true); + var bb = dojo.html.getBorderBox(tn); + this.dropTargetDimensions.push([ + [abs.x, abs.y], // upper-left + // lower-right + [ abs.x+bb.width, abs.y+bb.height ], + tempTarget + ]); + //dojo.debug("Cached for "+tempTarget) + }, this); + + dojo.profile.end("cacheTargetLocations"); + + //dojo.debug("Cache locations") + }, + + onMouseMove: function(e){ + if((dojo.render.html.ie)&&(e.button != 1)){ + // Oooops - mouse up occurred - e.g. when mouse was not over the + // window. I don't think we can detect this for FF - but at least + // we can be nice in IE. + this.currentDropTarget = null; + this.onMouseUp(e, true); + return; + } + + // if we've got some sources, but no drag objects, we need to send + // onDragStart to all the right parties and get things lined up for + // drop target detection + + if( (this.selectedSources.length)&& + (!this.dragObjects.length) ){ + var dx; + var dy; + if(!this._dragTriggered){ + this._dragTriggered = (this._dragStartDistance(e.pageX, e.pageY) > this.threshold); + if(!this._dragTriggered){ return; } + dx = e.pageX - this.mouseDownX; + dy = e.pageY - this.mouseDownY; + } + + // the first element is always our dragSource, if there are multiple + // selectedSources (elements that move along) then the first one is the master + // and for it the events will be fired etc. + this.dragSource = this.selectedSources[0]; + + dojo.lang.forEach(this.selectedSources, function(tempSource){ + if(!tempSource){ return; } + var tdo = tempSource.onDragStart(e); + if(tdo){ + tdo.onDragStart(e); + + // "bump" the drag object to account for the drag threshold + tdo.dragOffset.y += dy; + tdo.dragOffset.x += dx; + tdo.dragSource = tempSource; + + this.dragObjects.push(tdo); + } + }, this); + + /* clean previous drop target in dragStart */ + this.previousDropTarget = null; + + this.cacheTargetLocations(); + } + + // FIXME: we need to add dragSources and dragObjects to e + dojo.lang.forEach(this.dragObjects, function(dragObj){ + if(dragObj){ dragObj.onDragMove(e); } + }); + + // if we have a current drop target, check to see if we're outside of + // it. If so, do all the actions that need doing. + if(this.currentDropTarget){ + //dojo.debug(dojo.html.hasParent(this.currentDropTarget.domNode)) + var c = dojo.html.toCoordinateObject(this.currentDropTarget.domNode, true); + // var dtp = this.currentDropTargetPoints; + var dtp = [ + [c.x,c.y], [c.x+c.width, c.y+c.height] + ]; + } + + if((!this.nestedTargets)&&(dtp)&&(this.isInsideBox(e, dtp))){ + if(this.dropAcceptable){ + this.currentDropTarget.onDragMove(e, this.dragObjects); + } + }else{ + // FIXME: need to fix the event object! + // see if we can find a better drop target + var bestBox = this.findBestTarget(e); + + if(bestBox.target === null){ + if(this.currentDropTarget){ + this.currentDropTarget.onDragOut(e); + this.previousDropTarget = this.currentDropTarget; + this.currentDropTarget = null; + // this.currentDropTargetPoints = null; + } + this.dropAcceptable = false; + return; + } + + if(this.currentDropTarget !== bestBox.target){ + if(this.currentDropTarget){ + this.previousDropTarget = this.currentDropTarget; + this.currentDropTarget.onDragOut(e); + } + this.currentDropTarget = bestBox.target; + // this.currentDropTargetPoints = bestBox.points; + e.dragObjects = this.dragObjects; + this.dropAcceptable = this.currentDropTarget.onDragOver(e); + + }else{ + if(this.dropAcceptable){ + this.currentDropTarget.onDragMove(e, this.dragObjects); + } + } + } + }, + + findBestTarget: function(e) { + var _this = this; + var bestBox = new Object(); + bestBox.target = null; + bestBox.points = null; + dojo.lang.every(this.dropTargetDimensions, function(tmpDA) { + if(!_this.isInsideBox(e, tmpDA)){ + return true; + } + + bestBox.target = tmpDA[2]; + bestBox.points = tmpDA; + // continue iterating only if _this.nestedTargets == true + return Boolean(_this.nestedTargets); + }); + + return bestBox; + }, + + isInsideBox: function(e, coords){ + if( (e.pageX > coords[0][0])&& + (e.pageX < coords[1][0])&& + (e.pageY > coords[0][1])&& + (e.pageY < coords[1][1]) ){ + return true; + } + return false; + }, + + onMouseOver: function(e){ + }, + + onMouseOut: function(e){ + } +}); + +dojo.dnd.dragManager = new dojo.dnd.HtmlDragManager(); + +// global namespace protection closure +(function(){ + var d = document; + var dm = dojo.dnd.dragManager; + //TODO: when focus manager is ready, dragManager should be rewritten to use it + // set up event handlers on the document (or no?) + dojo.event.connect(d, "onkeydown", dm, "onKeyDown"); + dojo.event.connect(d, "onmouseover", dm, "onMouseOver"); + dojo.event.connect(d, "onmouseout", dm, "onMouseOut"); + dojo.event.connect(d, "onmousedown", dm, "onMouseDown"); + dojo.event.connect(d, "onmouseup", dm, "onMouseUp"); + // TODO: process scrolling of elements, not only window (focus manager would + // probably come to rescue here as well) + dojo.event.connect(window, "onscroll", dm, "onScroll"); +})(); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/HtmlDragMove.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/HtmlDragMove.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/HtmlDragMove.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,66 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.dnd.HtmlDragMove"); +dojo.require("dojo.dnd.*"); + +dojo.declare("dojo.dnd.HtmlDragMoveSource", dojo.dnd.HtmlDragSource, { + onDragStart: function(){ + var dragObj = new dojo.dnd.HtmlDragMoveObject(this.dragObject, this.type); + if (this.constrainToContainer) { + dragObj.constrainTo(this.constrainingContainer); + } + return dragObj; + }, + /* + * see dojo.dnd.HtmlDragSource.onSelected + */ + onSelected: function() { + for (var i=0; i. + */ + setAbsolutePosition: function(x, y){ + // The drag clone is attached to it's constraining container so offset for that + if(!this.disableY) { this.domNode.style.top = (y-this.containingBlockPosition.y) + "px"; } + if(!this.disableX) { this.domNode.style.left = (x-this.containingBlockPosition.x) + "px"; } + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Sortable.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/Sortable.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Sortable.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,28 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.dnd.Sortable"); +dojo.require("dojo.dnd.*"); + +dojo.dnd.Sortable = function () {} + +dojo.lang.extend(dojo.dnd.Sortable, { + + ondragstart: function (e) { + var dragObject = e.target; + while (dragObject.parentNode && dragObject.parentNode != this) { + dragObject = dragObject.parentNode; + } + // TODO: should apply HtmlDropTarget interface to self + // TODO: should apply HtmlDragObject interface? + return dragObject; + } + +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/TreeDragAndDrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/TreeDragAndDrop.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/TreeDragAndDrop.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,475 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +/** + * TreeDrag* specialized on managing subtree drags + * It selects nodes and visualises what's going on, + * but delegates real actions upon tree to the controller + * + * This code is considered a part of controller +*/ + +dojo.provide("dojo.dnd.TreeDragAndDrop"); + +dojo.require("dojo.dnd.HtmlDragAndDrop"); +dojo.require("dojo.lang.func"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.html.layout"); + +dojo.dnd.TreeDragSource = function(node, syncController, type, treeNode){ + this.controller = syncController; + this.treeNode = treeNode; + + dojo.dnd.HtmlDragSource.call(this, node, type); +} + +dojo.inherits(dojo.dnd.TreeDragSource, dojo.dnd.HtmlDragSource); + +dojo.lang.extend(dojo.dnd.TreeDragSource, { + onDragStart: function(){ + /* extend adds functions to prototype */ + var dragObject = dojo.dnd.HtmlDragSource.prototype.onDragStart.call(this); + //dojo.debugShallow(dragObject) + + dragObject.treeNode = this.treeNode; + + dragObject.onDragStart = dojo.lang.hitch(dragObject, function(e) { + + /* save selection */ + this.savedSelectedNode = this.treeNode.tree.selector.selectedNode; + if (this.savedSelectedNode) { + this.savedSelectedNode.unMarkSelected(); + } + + var result = dojo.dnd.HtmlDragObject.prototype.onDragStart.apply(this, arguments); + + + /* remove background grid from cloned object */ + var cloneGrid = this.dragClone.getElementsByTagName('img'); + for(var i=0; i it was allowed before, no accept check is needed + if (position=="onto" || + (!this.isAdjacentNode(sourceTreeNode, position) + && this.controller.canMove(sourceTreeNode, this.treeNode.parent) + ) + ) { + return position; + } else { + return false; + } + + }, + + onDragOut: function(e) { + this.clearAutoExpandTimer(); + + this.hideIndicator(); + }, + + + clearAutoExpandTimer: function() { + if (this.autoExpandTimer) { + clearTimeout(this.autoExpandTimer); + this.autoExpandTimer = null; + } + }, + + + + onDragMove: function(e, dragObjects){ + + var sourceTreeNode = dragObjects[0].treeNode; + + var position = this.getAcceptPosition(e, sourceTreeNode); + + if (position) { + this.showIndicator(position); + } + + }, + + isAdjacentNode: function(sourceNode, position) { + + if (sourceNode === this.treeNode) return true; + if (sourceNode.getNextSibling() === this.treeNode && position=="before") return true; + if (sourceNode.getPreviousSibling() === this.treeNode && position=="after") return true; + + return false; + }, + + + /* get DNDMode and see which position e fits */ + getPosition: function(e, DNDMode) { + var node = dojo.byId(this.treeNode.labelNode); + var mousey = e.pageY || e.clientY + dojo.body().scrollTop; + var nodey = dojo.html.getAbsolutePosition(node).y; + var height = dojo.html.getBorderBox(node).height; + + var relY = mousey - nodey; + var p = relY / height; + + var position = ""; // "" <=> forbidden + if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO + && DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) { + if (p<=0.3) { + position = "before"; + } else if (p<=0.7) { + position = "onto"; + } else { + position = "after"; + } + } else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) { + if (p<=0.5) { + position = "before"; + } else { + position = "after"; + } + } + else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO) { + position = "onto"; + } + + + return position; + }, + + + + getTargetParentIndex: function(sourceTreeNode, position) { + + var index = position == "before" ? this.treeNode.getParentIndex() : this.treeNode.getParentIndex()+1; + if (this.treeNode.parent === sourceTreeNode.parent + && this.treeNode.getParentIndex() > sourceTreeNode.getParentIndex()) { + index--; // dragging a node is different for simple move bacause of before-after issues + } + + return index; + }, + + + onDrop: function(e){ + // onDragOut will clean position + + + var position = this.position; + +//dojo.debug(position); + + this.onDragOut(e); + + var sourceTreeNode = e.dragObject.treeNode; + + if (!dojo.lang.isObject(sourceTreeNode)) { + dojo.raise("TreeNode not found in dragObject") + } + + if (position == "onto") { + return this.controller.move(sourceTreeNode, this.treeNode, 0); + } else { + var index = this.getTargetParentIndex(sourceTreeNode, position); + return this.controller.move(sourceTreeNode, this.treeNode.parent, index); + } + + //dojo.debug('drop2'); + + + + } + + +}); + + + +dojo.dnd.TreeDNDController = function(treeController) { + + // I use this controller to perform actions + this.treeController = treeController; + + this.dragSources = {}; + + this.dropTargets = {}; + +} + +dojo.lang.extend(dojo.dnd.TreeDNDController, { + + + listenTree: function(tree) { + //dojo.debug("Listen tree "+tree); + dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode"); + dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom"); + dojo.event.topic.subscribe(tree.eventNames.moveTo, this, "onMoveTo"); + dojo.event.topic.subscribe(tree.eventNames.addChild, this, "onAddChild"); + dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode"); + dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy"); + }, + + + unlistenTree: function(tree) { + //dojo.debug("Listen tree "+tree); + dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode"); + dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom"); + dojo.event.topic.unsubscribe(tree.eventNames.moveTo, this, "onMoveTo"); + dojo.event.topic.unsubscribe(tree.eventNames.addChild, this, "onAddChild"); + dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode"); + dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy"); + }, + + onTreeDestroy: function(message) { + this.unlistenTree(message.source); + // I'm not widget so don't use destroy() call and dieWithTree + }, + + onCreateDOMNode: function(message) { + this.registerDNDNode(message.source); + }, + + onAddChild: function(message) { + this.registerDNDNode(message.child); + }, + + onMoveFrom: function(message) { + var _this = this; + dojo.lang.forEach( + message.child.getDescendants(), + function(node) { _this.unregisterDNDNode(node); } + ); + }, + + onMoveTo: function(message) { + var _this = this; + dojo.lang.forEach( + message.child.getDescendants(), + function(node) { _this.registerDNDNode(node); } + ); + }, + + /** + * Controller(node model) creates DNDNodes because it passes itself to node for synchroneous drops processing + * I can't process DnD with events cause an event can't return result success/false + */ + registerDNDNode: function(node) { + if (!node.tree.DNDMode) return; + +//dojo.debug("registerDNDNode "+node); + + /* I drag label, not domNode, because large domNodes are very slow to copy and large to drag */ + + var source = null; + var target = null; + + if (!node.actionIsDisabled(node.actions.MOVE)) { + //dojo.debug("reg source") + var source = new dojo.dnd.TreeDragSource(node.labelNode, this, node.tree.widgetId, node); + this.dragSources[node.widgetId] = source; + } + + var target = new dojo.dnd.TreeDropTarget(node.labelNode, this.treeController, node.tree.DNDAcceptTypes, node); + + this.dropTargets[node.widgetId] = target; + + }, + + + unregisterDNDNode: function(node) { + + if (this.dragSources[node.widgetId]) { + dojo.dnd.dragManager.unregisterDragSource(this.dragSources[node.widgetId]); + delete this.dragSources[node.widgetId]; + } + + if (this.dropTargets[node.widgetId]) { + dojo.dnd.dragManager.unregisterDropTarget(this.dropTargets[node.widgetId]); + delete this.dropTargets[node.widgetId]; + } + } + + + + + +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/TreeDragAndDropV3.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/TreeDragAndDropV3.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/TreeDragAndDropV3.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,404 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +/** + * TreeDrag* specialized on managing subtree drags + * It selects nodes and visualises what's going on, + * but delegates real actions upon tree to the controller + * + * This code is considered a part of controller +*/ + +dojo.provide("dojo.dnd.TreeDragAndDropV3"); + +dojo.require("dojo.dnd.HtmlDragAndDrop"); +dojo.require("dojo.lang.func"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.Deferred"); +dojo.require("dojo.html.layout"); + +// FIXME: if controller can't move then skip node on move start +dojo.dnd.TreeDragSourceV3 = function(node, syncController, type, treeNode){ + //dojo.profile.start("TreeDragSourceV3 "+treeNode); + this.controller = syncController; + this.treeNode = treeNode; + + dojo.dnd.HtmlDragSource.call(this, node, type); + //dojo.profile.end("TreeDragSourceV3 "+treeNode); + +} + +dojo.inherits(dojo.dnd.TreeDragSourceV3, dojo.dnd.HtmlDragSource); + + +// ....................................... + +dojo.dnd.TreeDropTargetV3 = function(domNode, controller, type, treeNode){ + + this.treeNode = treeNode; + this.controller = controller; // I will sync-ly process drops + + dojo.dnd.HtmlDropTarget.call(this, domNode, type); +} + +dojo.inherits(dojo.dnd.TreeDropTargetV3, dojo.dnd.HtmlDropTarget); + +dojo.lang.extend(dojo.dnd.TreeDropTargetV3, { + + autoExpandDelay: 1500, + autoExpandTimer: null, + + + position: null, + + indicatorStyle: "2px black groove", + + showIndicator: function(position) { + + // do not change style too often, cause of blinking possible + if (this.position == position) { + return; + } + + //dojo.debug("set position for "+this.treeNode) + + this.hideIndicator(); + + this.position = position; + + var node = this.treeNode; + + + node.contentNode.style.width = dojo.html.getBorderBox(node.labelNode).width + "px"; + + if (position == "onto") { + node.contentNode.style.border = this.indicatorStyle; + } else { + // FIXME: bottom-top or highlight should cover ONLY top/bottom or div itself, + // not span whole line (try Dnd) + // FAILURE: Can't put span inside div: multiline bottom-top will span multiple lines + if (position == "before") { + node.contentNode.style.borderTop = this.indicatorStyle; + } else if (position == "after") { + node.contentNode.style.borderBottom = this.indicatorStyle; + } + } + }, + + hideIndicator: function() { + this.treeNode.contentNode.style.borderBottom = ""; + this.treeNode.contentNode.style.borderTop = ""; + this.treeNode.contentNode.style.border = ""; + this.treeNode.contentNode.style.width="" + this.position = null; + }, + + + + // is the target possibly ok ? + // This function is run on dragOver, but drop possibility is also determined by position over node + // that's why acceptsWithPosition is called + // doesnt take index into account ( can change while moving mouse w/o changing target ) + /** + * Coarse (tree-level) access check. + * We can't determine real accepts status w/o position + */ + onDragOver: function(e){ + //dojo.debug("onDragOver for "+e); + + var accepts = dojo.dnd.HtmlDropTarget.prototype.onDragOver.apply(this, arguments); + + //dojo.debug("TreeDropTarget.onDragOver accepts:"+accepts) + + if (accepts && this.treeNode.isFolder && !this.treeNode.isExpanded) { + this.setAutoExpandTimer(); + } + + if (accepts) { + this.cacheNodeCoords(); + } + + + return accepts; + }, + + /* Parent.onDragOver calls this function to get accepts status */ + accepts: function(dragObjects) { + + var accepts = dojo.dnd.HtmlDropTarget.prototype.accepts.apply(this, arguments); + + //dojo.debug("accepts "+accepts); + + if (!accepts) return false; + + for(var i=0; i it was allowed before, no accept check is needed + if (position=="onto") { + return position; + } + + for(var i=0; i forbidden + if (DndMode & dojo.widget.TreeV3.prototype.DndModes.ONTO + && DndMode & dojo.widget.TreeV3.prototype.DndModes.BETWEEN) { + //dojo.debug("BOTH"); + if (p<=0.33) { + position = "before"; + // if children are expanded then I ignore understrike, cause it is confusing with firstChild + // but for last nodes I put understrike there + } else if (p<=0.66 || this.treeNode.isExpanded && this.treeNode.children.length && !this.treeNode.isLastChild()) { + position = "onto"; + } else { + position = "after"; + } + } else if (DndMode & dojo.widget.TreeV3.prototype.DndModes.BETWEEN) { + //dojo.debug("BETWEEN"); + if (p<=0.5 || this.treeNode.isExpanded && this.treeNode.children.length && !this.treeNode.isLastChild()) { + position = "before"; + } else { + position = "after"; + } + } + else if (DndMode & dojo.widget.TreeV3.prototype.DndModes.ONTO) { + //dojo.debug("ONTO"); + position = "onto"; + } + + //dojo.debug(position); + + return position; + }, + + + + getTargetParentIndex: function(source, position) { + + var index = position == "before" ? this.treeNode.getParentIndex() : this.treeNode.getParentIndex()+1; + if (source.treeNode + && this.treeNode.parent === source.treeNode.parent + && this.treeNode.getParentIndex() > source.treeNode.getParentIndex()) { + index--; // dragging a node is different for simple move bacause of before-after issues + } + + return index; + }, + + + onDrop: function(e) { + // onDropEnd will clean position + + + var position = this.position; + +//dojo.debug(position); + var source = e.dragObject.dragSource; + + //dojo.debug("onDrop "+source.treeNode+" " + position + " "+this.treeNode); + + + var targetParent, targetIndex; + if (position == "onto") { + targetParent = this.treeNode; + targetIndex = 0; + } else { + targetIndex = this.getTargetParentIndex(source, position); + targetParent = this.treeNode.parent; + } + + //dojo.profile.start("onDrop "+sourceTreeNode); + var r = this.getDropHandler(e, source, targetParent, targetIndex)(); + + //dojo.profile.end("onDrop "+sourceTreeNode); + + return r; + + }, + + /** + * determine, which action I should perform with nodes + * e.g move, clone.. + */ + getDropHandler: function(e, source, targetParent, targetIndex) { + var handler; + var _this = this; + handler = function () { + var result; + + //dojo.debug("Move "+source.treeNode+" to parent "+targetParent+":"+targetIndex); + if (source.treeNode) { + result = _this.controller.move(source.treeNode, targetParent, targetIndex, true); + //dojo.debug("moved "+result); + } else { + if (dojo.lang.isFunction(source.onDrop)) { + source.onDrop(targetParent, targetIndex); + } + + var treeNode = source.getTreeNode(); + if (treeNode) { + result = _this.controller.createChild(targetParent, targetIndex, treeNode, true); + } else { + result = true; + } + } + + if (result instanceof dojo.Deferred) { + // this Deferred is always sync + var isSuccess = result.fired == 0; + if (!isSuccess) { + _this.handleDropError(source, targetParent, targetIndex, result); + } + + return isSuccess; + + } else { + return result; + } + } + + return handler; + }, + + + handleDropError: function(source, parent, index, result) { + dojo.debug("TreeDropTargetV3.handleDropError: DND error occured"); + dojo.debugShallow(result); + } + + +}); + Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/dnd/__package__.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,16 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: ["dojo.dnd.DragAndDrop"], + browser: ["dojo.dnd.HtmlDragAndDrop"], + dashboard: ["dojo.dnd.HtmlDragAndDrop"] +}); +dojo.provide("dojo.dnd.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/__package__.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,16 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: ["dojo.event.common", "dojo.event.topic"], + browser: ["dojo.event.browser"], + dashboard: ["dojo.event.browser"] +}); +dojo.provide("dojo.event.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/browser.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/Attic/browser.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/browser.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,514 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.event.browser"); +dojo.require("dojo.event.common"); + +// FIXME: any particular reason this is in the global scope? +dojo._ie_clobber = new function(){ + this.clobberNodes = []; + + function nukeProp(node, prop){ + // try{ node.removeAttribute(prop); }catch(e){ /* squelch */ } + try{ node[prop] = null; }catch(e){ /* squelch */ } + try{ delete node[prop]; }catch(e){ /* squelch */ } + // FIXME: JotLive needs this, but I'm not sure if it's too slow or not + try{ node.removeAttribute(prop); }catch(e){ /* squelch */ } + } + + this.clobber = function(nodeRef){ + var na; + var tna; + if(nodeRef){ + tna = nodeRef.all || nodeRef.getElementsByTagName("*"); + na = [nodeRef]; + for(var x=0; x=0; i=i-1){ + var el = na[i]; + try{ + if(el && el["__clobberAttrs__"]){ + for(var j=0; j= 65 && unifiedCharCode <= 90 && evt.shiftKey == false){ + unifiedCharCode += 32; + } + if(unifiedCharCode >= 1 && unifiedCharCode <= 26 && evt.ctrlKey){ + unifiedCharCode += 96; // 001-032 = ctrl+[a-z] + } + evt.key = String.fromCharCode(unifiedCharCode); + } + } + } else if(evt["type"] == "keypress"){ + if(dojo.render.html.opera){ + if(evt.which == 0){ + evt.key = evt.keyCode; + }else if(evt.which > 0){ + switch(evt.which){ + case evt.KEY_SHIFT: + case evt.KEY_CTRL: + case evt.KEY_ALT: + case evt.KEY_CAPS_LOCK: + case evt.KEY_NUM_LOCK: + case evt.KEY_SCROLL_LOCK: + break; + case evt.KEY_PAUSE: + case evt.KEY_TAB: + case evt.KEY_BACKSPACE: + case evt.KEY_ENTER: + case evt.KEY_ESCAPE: + evt.key = evt.which; + break; + default: + var unifiedCharCode = evt.which; + if((evt.ctrlKey || evt.altKey || evt.metaKey) && (evt.which >= 65 && evt.which <= 90 && evt.shiftKey == false)){ + unifiedCharCode += 32; + } + evt.key = String.fromCharCode(unifiedCharCode); + } + } + }else if(dojo.render.html.ie){ // catch some IE keys that are hard to get in keyDown + // key combinations were handled in onKeyDown + if(!evt.ctrlKey && !evt.altKey && evt.keyCode >= evt.KEY_SPACE){ + evt.key = String.fromCharCode(evt.keyCode); + } + }else if(dojo.render.html.safari){ + switch(evt.keyCode){ + case 63232: evt.key = evt.KEY_UP_ARROW; break; + case 63233: evt.key = evt.KEY_DOWN_ARROW; break; + case 63234: evt.key = evt.KEY_LEFT_ARROW; break; + case 63235: evt.key = evt.KEY_RIGHT_ARROW; break; + default: + evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode; + } + }else{ + evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode; + } + } + } + if(dojo.render.html.ie){ + if(!evt.target){ evt.target = evt.srcElement; } + if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); } + if(!evt.layerX){ evt.layerX = evt.offsetX; } + if(!evt.layerY){ evt.layerY = evt.offsetY; } + // FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module + // DONOT replace the following to use dojo.body(), in IE, document.documentElement should be used + // here rather than document.body + var doc = (evt.srcElement && evt.srcElement.ownerDocument) ? evt.srcElement.ownerDocument : document; + var docBody = ((dojo.render.html.ie55)||(doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement; + if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) } + if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) } + // mouseover + if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; } + // mouseout + if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; } + this.currentEvent = evt; + evt.callListener = this.callListener; + evt.stopPropagation = this._stopPropagation; + evt.preventDefault = this._preventDefault; + } + return evt; // Event + } + + this.stopEvent = function(/*Event*/evt){ + // summary: + // prevents propigation and clobbers the default action of the + // passed event + // evt: Optional for IE. The native event object. + if(window.event){ + evt.returnValue = false; + evt.cancelBubble = true; + }else{ + evt.preventDefault(); + evt.stopPropagation(); + } + } +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/Attic/common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/event/common.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,878 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.event.common"); + +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.lang.func"); + +// TODO: connection filter functions +// these are functions that accept a method invocation (like around +// advice) and return a boolean based on it. That value determines +// whether or not the connection proceeds. It could "feel" like around +// advice for those who know what it is (calling proceed() or not), +// but I think presenting it as a "filter" and/or calling it with the +// function args and not the MethodInvocation might make it more +// palletable to "normal" users than around-advice currently is +// TODO: execution scope mangling +// YUI's event facility by default executes listeners in the context +// of the source object. This is very odd, but should probably be +// supported as an option (both for the source and for the dest). It +// can be thought of as a connection-specific hitch(). +// TODO: more resiliency for 4+ arguments to connect() + +dojo.event = new function(){ + this._canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]); + + // FIXME: where should we put this method (not here!)? + function interpolateArgs(args, searchForNames){ + var dl = dojo.lang; + var ao = { + srcObj: dj_global, + srcFunc: null, + adviceObj: dj_global, + adviceFunc: null, + aroundObj: null, + aroundFunc: null, + adviceType: (args.length>2) ? args[0] : "after", + precedence: "last", + once: false, + delay: null, + rate: 0, + adviceMsg: false + }; + + switch(args.length){ + case 0: return; + case 1: return; + case 2: + ao.srcFunc = args[0]; + ao.adviceFunc = args[1]; + break; + case 3: + if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){ + ao.adviceType = "after"; + ao.srcObj = args[0]; + ao.srcFunc = args[1]; + ao.adviceFunc = args[2]; + }else if((dl.isString(args[1]))&&(dl.isString(args[2]))){ + ao.srcFunc = args[1]; + ao.adviceFunc = args[2]; + }else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){ + ao.adviceType = "after"; + ao.srcObj = args[0]; + ao.srcFunc = args[1]; + var tmpName = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames); + ao.adviceFunc = tmpName; + }else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){ + ao.adviceType = "after"; + ao.srcObj = dj_global; + var tmpName = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames); + ao.srcFunc = tmpName; + ao.adviceObj = args[1]; + ao.adviceFunc = args[2]; + } + break; + case 4: + if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){ + // we can assume that we've got an old-style "connect" from + // the sigslot school of event attachment. We therefore + // assume after-advice. + ao.adviceType = "after"; + ao.srcObj = args[0]; + ao.srcFunc = args[1]; + ao.adviceObj = args[2]; + ao.adviceFunc = args[3]; + }else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){ + ao.adviceType = args[0]; + ao.srcObj = dj_global; + ao.srcFunc = args[1]; + ao.adviceObj = args[2]; + ao.adviceFunc = args[3]; + }else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){ + ao.adviceType = args[0]; + ao.srcObj = dj_global; + var tmpName = dl.nameAnonFunc(args[1], dj_global, searchForNames); + ao.srcFunc = tmpName; + ao.adviceObj = args[2]; + ao.adviceFunc = args[3]; + }else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){ + ao.srcObj = args[1]; + ao.srcFunc = args[2]; + var tmpName = dl.nameAnonFunc(args[3], dj_global, searchForNames); + ao.adviceObj = dj_global; + ao.adviceFunc = tmpName; + }else if(dl.isObject(args[1])){ + ao.srcObj = args[1]; + ao.srcFunc = args[2]; + ao.adviceObj = dj_global; + ao.adviceFunc = args[3]; + }else if(dl.isObject(args[2])){ + ao.srcObj = dj_global; + ao.srcFunc = args[1]; + ao.adviceObj = args[2]; + ao.adviceFunc = args[3]; + }else{ + ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global; + ao.srcFunc = args[1]; + ao.adviceFunc = args[2]; + ao.aroundFunc = args[3]; + } + break; + case 6: + ao.srcObj = args[1]; + ao.srcFunc = args[2]; + ao.adviceObj = args[3] + ao.adviceFunc = args[4]; + ao.aroundFunc = args[5]; + ao.aroundObj = dj_global; + break; + default: + ao.srcObj = args[1]; + ao.srcFunc = args[2]; + ao.adviceObj = args[3] + ao.adviceFunc = args[4]; + ao.aroundObj = args[5]; + ao.aroundFunc = args[6]; + ao.once = args[7]; + ao.delay = args[8]; + ao.rate = args[9]; + ao.adviceMsg = args[10]; + break; + } + + if(dl.isFunction(ao.aroundFunc)){ + var tmpName = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames); + ao.aroundFunc = tmpName; + } + + if(dl.isFunction(ao.srcFunc)){ + ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc); + } + + if(dl.isFunction(ao.adviceFunc)){ + ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc); + } + + if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){ + ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc); + } + + if(!ao.srcObj){ + dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc); + } + if(!ao.adviceObj){ + dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc); + } + + if(!ao.adviceFunc){ + dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc); + dojo.debugShallow(ao); + } + + return ao; + } + + this.connect = function(/*...*/){ + // summary: + // dojo.event.connect is the glue that holds most Dojo-based + // applications together. Most combinations of arguments are + // supported, with the connect() method attempting to disambiguate + // the implied types of positional parameters. The following will + // all work: + // dojo.event.connect("globalFunctionName1", "globalFunctionName2"); + // dojo.event.connect(functionReference1, functionReference2); + // dojo.event.connect("globalFunctionName1", functionReference2); + // dojo.event.connect(functionReference1, "globalFunctionName2"); + // dojo.event.connect(scope1, "functionName1", "globalFunctionName2"); + // dojo.event.connect("globalFunctionName1", scope2, "functionName2"); + // dojo.event.connect(scope1, "functionName1", scope2, "functionName2"); + // dojo.event.connect("after", scope1, "functionName1", scope2, "functionName2"); + // dojo.event.connect("before", scope1, "functionName1", scope2, "functionName2"); + // dojo.event.connect("around", scope1, "functionName1", + // scope2, "functionName2", + // aroundFunctionReference); + // dojo.event.connect("around", scope1, "functionName1", + // scope2, "functionName2", + // scope3, "aroundFunctionName"); + // dojo.event.connect("before-around", scope1, "functionName1", + // scope2, "functionName2", + // aroundFunctionReference); + // dojo.event.connect("after-around", scope1, "functionName1", + // scope2, "functionName2", + // aroundFunctionReference); + // dojo.event.connect("after-around", scope1, "functionName1", + // scope2, "functionName2", + // scope3, "aroundFunctionName"); + // dojo.event.connect("around", scope1, "functionName1", + // scope2, "functionName2", + // scope3, "aroundFunctionName", true, 30); + // dojo.event.connect("around", scope1, "functionName1", + // scope2, "functionName2", + // scope3, "aroundFunctionName", null, null, 10); + // adviceType: + // Optional. String. One of "before", "after", "around", + // "before-around", or "after-around". FIXME + // srcObj: + // the scope in which to locate/execute the named srcFunc. Along + // with srcFunc, this creates a way to dereference the function to + // call. So if the function in question is "foo.bar", the + // srcObj/srcFunc pair would be foo and "bar", where "bar" is a + // string and foo is an object reference. + // srcFunc: + // the name of the function to connect to. When it is executed, + // the listener being registered with this call will be called. + // The adviceType defines the call order between the source and + // the target functions. + // adviceObj: + // the scope in which to locate/execute the named adviceFunc. + // adviceFunc: + // the name of the function being conected to srcObj.srcFunc + // aroundObj: + // the scope in which to locate/execute the named aroundFunc. + // aroundFunc: + // the name of, or a reference to, the function that will be used + // to mediate the advice call. Around advice requires a special + // unary function that will be passed a "MethodInvocation" object. + // These objects have several important properties, namely: + // - args + // a mutable array of arguments to be passed into the + // wrapped function + // - proceed + // a function that "continues" the invocation. The result + // of this function is the return of the wrapped function. + // You can then manipulate this return before passing it + // back out (or take further action based on it). + // once: + // boolean that determines whether or not this connect() will + // create a new connection if an identical connect() has already + // been made. Defaults to "false". + // delay: + // an optional delay (in ms), as an integer, for dispatch of a + // listener after the source has been fired. + // rate: + // an optional rate throttling parameter (integer, in ms). When + // specified, this particular connection will not fire more than + // once in the interval specified by the rate + // adviceMsg: + // boolean. Should the listener have all the parameters passed in + // as a single argument? + + /* + ao.adviceType = args[0]; + ao.srcObj = args[1]; + ao.srcFunc = args[2]; + ao.adviceObj = args[3] + ao.adviceFunc = args[4]; + ao.aroundObj = args[5]; + ao.aroundFunc = args[6]; + ao.once = args[7]; + ao.delay = args[8]; + ao.rate = args[9]; + ao.adviceMsg = args[10]; + */ + if(arguments.length == 1){ + var ao = arguments[0]; + }else{ + var ao = interpolateArgs(arguments, true); + } + if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){ + if(dojo.render.html.ie){ + ao.srcFunc = "onkeydown"; + this.connect(ao); + } + ao.srcFunc = "onkeypress"; + } + + + if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){ + var tmpAO = {}; + for(var x in ao){ + tmpAO[x] = ao[x]; + } + var mjps = []; + dojo.lang.forEach(ao.srcObj, function(src){ + if((dojo.render.html.capable)&&(dojo.lang.isString(src))){ + src = dojo.byId(src); + // dojo.debug(src); + } + tmpAO.srcObj = src; + // dojo.debug(tmpAO.srcObj, tmpAO.srcFunc); + // dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc); + mjps.push(dojo.event.connect.call(dojo.event, tmpAO)); + }); + return mjps; + } + + // FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!! + var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc); + if(ao.adviceFunc){ + var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc); + } + + mjp.kwAddAdvice(ao); + + // advanced users might want to fsck w/ the join point manually + return mjp; // a MethodJoinPoint object + } + + this.log = function(/*object or funcName*/ a1, /*funcName*/ a2){ + // summary: + // a function that will wrap and log all calls to the specified + // a1.a2() function. If only a1 is passed, it'll be used as a + // function or function name on the global context. Logging will + // be sent to dojo.debug + // a1: + // if a2 is passed, this should be an object. If not, it can be a + // function or function name. + // a2: + // a function name + var kwArgs; + if((arguments.length == 1)&&(typeof a1 == "object")){ + kwArgs = a1; + }else{ + kwArgs = { + srcObj: a1, + srcFunc: a2 + }; + } + kwArgs.adviceFunc = function(){ + var argsStr = []; + for(var x=0; x= this.jp_.around.length){ + return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args); + // return this.jp_.run_before_after(this.object, this.args); + }else{ + var ti = this.jp_.around[this.around_index]; + var mobj = ti[0]||dj_global; + var meth = ti[1]; + return mobj[meth].call(mobj, this); + } +} + + +dojo.event.MethodJoinPoint = function(/*Object*/obj, /*String*/funcName){ + this.object = obj||dj_global; + this.methodname = funcName; + this.methodfunc = this.object[funcName]; + this.squelch = false; + // this.before = []; + // this.after = []; + // this.around = []; +} + +dojo.event.MethodJoinPoint.getForMethod = function(/*Object*/obj, /*String*/funcName){ + // summary: + // "static" class function for returning a MethodJoinPoint from a + // scoped function. If one doesn't exist, one is created. + // obj: + // the scope to search for the function in + // funcName: + // the name of the function to return a MethodJoinPoint for + if(!obj){ obj = dj_global; } + if(!obj[funcName]){ + // supply a do-nothing method implementation + obj[funcName] = function(){}; + if(!obj[funcName]){ + // e.g. cannot add to inbuilt objects in IE6 + dojo.raise("Cannot set do-nothing method on that object "+funcName); + } + }else if((!dojo.lang.isFunction(obj[funcName]))&&(!dojo.lang.isAlien(obj[funcName]))){ + // FIXME: should we throw an exception here instead? + return null; + } + // we hide our joinpoint instance in obj[funcName + '$joinpoint'] + var jpname = funcName + "$joinpoint"; + var jpfuncname = funcName + "$joinpoint$method"; + var joinpoint = obj[jpname]; + if(!joinpoint){ + var isNode = false; + if(dojo.event["browser"]){ + if( (obj["attachEvent"])|| + (obj["nodeType"])|| + (obj["addEventListener"]) ){ + isNode = true; + dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, funcName]); + } + } + var origArity = obj[funcName].length; + obj[jpfuncname] = obj[funcName]; + // joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, funcName); + joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname); + obj[funcName] = function(){ + var args = []; + + if((isNode)&&(!arguments.length)){ + var evt = null; + try{ + if(obj.ownerDocument){ + evt = obj.ownerDocument.parentWindow.event; + }else if(obj.documentElement){ + evt = obj.documentElement.ownerDocument.parentWindow.event; + }else if(obj.event){ //obj is a window + evt = obj.event; + }else{ + evt = window.event; + } + }catch(e){ + evt = window.event; + } + + if(evt){ + args.push(dojo.event.browser.fixEvent(evt, this)); + } + }else{ + for(var x=0; x0)){ + // pass a cloned array, if this event disconnects this event forEach on this.before wont work + dojo.lang.forEach(this.before.concat(new Array()), unRollSquelch); + } + + var result; + try{ + if((this["around"])&&(this.around.length>0)){ + var mi = new dojo.event.MethodInvocation(this, obj, args); + result = mi.proceed(); + }else if(this.methodfunc){ + result = this.object[this.methodname].apply(this.object, args); + } + }catch(e){ if(!this.squelch){ dojo.raise(e); } } + + if((this["after"])&&(this.after.length>0)){ + // see comment on this.before above + dojo.lang.forEach(this.after.concat(new Array()), unRollSquelch); + } + + return (this.methodfunc) ? result : null; + }, + + getArr: function(/*String*/kind){ + // summary: return a list of listeners of the past "kind" + // kind: + // can be one of: "before", "after", "around", "before-around", or + // "after-around" + var type = "after"; + // FIXME: we should be able to do this through props or Array.in() + if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){ + type = "before"; + }else if(kind=="around"){ + type = "around"; + } + if(!this[type]){ this[type] = []; } + return this[type]; // Array + }, + + kwAddAdvice: function(/*Object*/args){ + // summary: + // adds advice to the joinpoint with arguments in a map + // args: + // An object that can have the following properties: + // - adviceType + // - adviceObj + // - adviceFunc + // - aroundObj + // - aroundFunc + // - once + // - delay + // - rate + // - adviceMsg + this.addAdvice( args["adviceObj"], args["adviceFunc"], + args["aroundObj"], args["aroundFunc"], + args["adviceType"], args["precedence"], + args["once"], args["delay"], args["rate"], + args["adviceMsg"]); + }, + + addAdvice: function( thisAdviceObj, thisAdvice, + thisAroundObj, thisAround, + adviceType, precedence, + once, delay, rate, asMessage){ + // summary: + // add advice to this joinpoint using positional parameters + // thisAdviceObj: + // the scope in which to locate/execute the named adviceFunc. + // thisAdviceFunc: + // the name of the function being conected + // thisAroundObj: + // the scope in which to locate/execute the named aroundFunc. + // thisAroundFunc: + // the name of the function that will be used to mediate the + // advice call. + // adviceType: + // Optional. String. One of "before", "after", "around", + // "before-around", or "after-around". FIXME + // once: + // boolean that determines whether or not this advice will create + // a new connection if an identical advice set has already been + // provided. Defaults to "false". + // delay: + // an optional delay (in ms), as an integer, for dispatch of a + // listener after the source has been fired. + // rate: + // an optional rate throttling parameter (integer, in ms). When + // specified, this particular connection will not fire more than + // once in the interval specified by the rate + // adviceMsg: + // boolean. Should the listener have all the parameters passed in + // as a single argument? + var arr = this.getArr(adviceType); + if(!arr){ + dojo.raise("bad this: " + this); + } + + var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage]; + + if(once){ + if(this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr) >= 0){ + return; + } + } + + if(precedence == "first"){ + arr.unshift(ao); + }else{ + arr.push(ao); + } + }, + + hasAdvice: function(thisAdviceObj, thisAdvice, adviceType, arr){ + // summary: + // returns the array index of the first existing connection + // betweened the passed advice and this joinpoint. Will be -1 if + // none exists. + // thisAdviceObj: + // the scope in which to locate/execute the named adviceFunc. + // thisAdviceFunc: + // the name of the function being conected + // adviceType: + // Optional. String. One of "before", "after", "around", + // "before-around", or "after-around". FIXME + // arr: + // Optional. The list of advices to search. Will be found via + // adviceType if not passed + if(!arr){ arr = this.getArr(adviceType); } + var ind = -1; + for(var x=0; x 0.04045) ? Math.pow(((src.R + 0.055) / 1.055), 2.4) : src.R / 12.92; + var g = (src.G > 0.04045) ? Math.pow(((src.G + 0.055) / 1.055), 2.4) : src.G / 12.92; + var b = (src.B > 0.04045) ? Math.pow(((src.B + 0.055) / 1.055), 2.4) : src.B / 12.92; + }else{ + var r = Math.pow(src.R, pr.gamma); + var g = Math.pow(src.G, pr.gamma); + var b = Math.pow(src.B, pr.gamma); + } + + var XYZ = dojo.math.matrix.multiply([[r, g, b]], m); + return [XYZ[0][0], XYZ[0][1], XYZ[0][2]]; +} + +dojo.gfx.Colorspace.prototype.XYZ_to_RGB = function(){ + var src = this.munge('XYZ', arguments); + var mi = this.getXYZ_RGB_Matrix(); + var pr = this.getPrimaries(); + + var rgb = dojo.math.matrix.multiply([[src.X, src.Y, src.Z]], mi); + var r = rgb[0][0]; + var g = rgb[0][1]; + var b = rgb[0][2]; + + if (this.RGBWorkingSpace == 's_rgb'){ + var R = (r > 0.0031308) ? (1.055 * Math.pow(r, 1.0/2.4)) - 0.055 : 12.92 * r; + var G = (g > 0.0031308) ? (1.055 * Math.pow(g, 1.0/2.4)) - 0.055 : 12.92 * g; + var B = (b > 0.0031308) ? (1.055 * Math.pow(b, 1.0/2.4)) - 0.055 : 12.92 * b; + }else{ + var R = Math.pow(r, 1/pr.gamma); + var G = Math.pow(g, 1/pr.gamma); + var B = Math.pow(b, 1/pr.gamma); + } + return [R, G, B]; +} + +dojo.gfx.Colorspace.prototype.XYZ_to_Lab = function(){ + var src = this.munge('XYZ', arguments); + var wp = this.getWhitePoint(); + + var xr = src.X / wp.X; + var yr = src.Y / wp.Y; + var zr = src.Z / wp.Z; + + var fx = (xr > this.epsilon()) ? Math.pow(xr, 1/3) : (this.kappa() * xr + 16) / 116; + var fy = (yr > this.epsilon()) ? Math.pow(yr, 1/3) : (this.kappa() * yr + 16) / 116; + var fz = (zr > this.epsilon()) ? Math.pow(zr, 1/3) : (this.kappa() * zr + 16) / 116; + + var L = 116 * fy - 16; + var a = 500 * (fx - fy); + var b = 200 * (fy - fz); + + return [L, a, b]; +} + +dojo.gfx.Colorspace.prototype.Lab_to_XYZ = function(){ + var src = this.munge('Lab', arguments); + var wp = this.getWhitePoint(); + var yr = (src.L > (this.kappa() * this.epsilon())) ? Math.pow((src.L + 16) / 116, 3) : src.L / this.kappa(); + + var fy = (yr > this.epsilon()) ? (src.L + 16) / 116 : (this.kappa() * yr + 16) / 116; + var fx = (src.a / 500) + fy; + var fz = fy - (src.b / 200); + + var fxcube = Math.pow(fx, 3); + var fzcube = Math.pow(fz, 3); + + var xr = (fxcube > this.epsilon()) ? fxcube : (116 * fx - 16) / this.kappa(); + var zr = (fzcube > this.epsilon()) ? fzcube : (116 * fz - 16) / this.kappa(); + + var X = xr * wp.X; + var Y = yr * wp.Y; + var Z = zr * wp.Z; + + return [X, Y, Z]; +} + +dojo.gfx.Colorspace.prototype.Lab_to_LCHab = function(){ + var src = this.munge('Lab', arguments); + + var L = src.L; + var C = Math.pow(src.a * src.a + src.b * src.b, 0.5); + var H = Math.atan2(src.b, src.a) * (180 / Math.PI); + + if (H < 0){ H += 360; } + if (H > 360){ H -= 360; } + + return [L, C, H]; +} + +dojo.gfx.Colorspace.prototype.LCHab_to_Lab = function(){ + var src = this.munge('LCH', arguments); + + var H_rad = src.H * (Math.PI / 180); + var L = src.L; + var a = src.C / Math.pow(Math.pow(Math.tan(H_rad), 2) + 1, 0.5); + if ((90 < src.H) && (src.H < 270)){ a= -a; } + + var b = Math.pow(Math.pow(src.C, 2) - Math.pow(a, 2), 0.5); + if (src.H > 180){ b = -b; } + + return [L, a, b]; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// this function converts an XYZ color array (col) from one whitepoint (src_w) to another (dst_w) +// + +dojo.gfx.Colorspace.prototype.chromaticAdaptation = function(col, src_w, dst_w){ + col = this.munge('XYZ', [col]); + var old_wp = this.whitePoint; + + this.whitePoint = src_w; + var wp_src = this.getWhitePoint(); + + this.whitePoint = dst_w; + var wp_dst = this.getWhitePoint(); + + this.whitePoint = old_wp; + + switch(this.chromaticAdaptationAlg){ + case 'xyz_scaling': + var ma = [[1,0,0],[0,1,0],[0,0,1]]; + var mai = [[1,0,0],[0,1,0],[0,0,1]]; + break; + case 'bradford': + var ma = [[0.8951, -0.7502, 0.0389],[0.2664, 1.7135, -0.0685],[-0.1614, 0.0367, 1.0296]]; + var mai = [[0.986993, 0.432305, -0.008529],[-0.147054, 0.518360, 0.040043],[0.159963, 0.049291, 0.968487]]; + break; + case 'von_kries': + var ma = [[0.40024, -0.22630, 0.00000],[0.70760, 1.16532, 0.00000],[-0.08081, 0.04570, 0.91822]] + var mai = [[1.859936, 0.361191, 0.000000],[-1.129382, 0.638812, 0.000000],[0.219897, -0.000006, 1.089064]] + break; + default: + dojo.debug("The "+this.chromaticAdaptationAlg+" chromatic adaptation algorithm matricies are not defined"); + } + + var domain_src = dojo.math.matrix.multiply( [[wp_src.x, wp_src.y, wp_src.z]], ma); + var domain_dst = dojo.math.matrix.multiply( [[wp_dst.x, wp_dst.y, wp_dst.z]], ma); + + var centre = [ + [domain_dst[0][0]/domain_src[0][0], 0, 0], + [0, domain_dst[0][1]/domain_src[0][1], 0], + [0, 0, domain_dst[0][2]/domain_src[0][2]] + ]; + + var m = dojo.math.matrix.multiply( dojo.math.matrix.multiply( ma, centre ), mai ); + var dst = dojo.math.matrix.multiply( [[ col.X, col.Y, col.Z ]], m ); + return dst[0]; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// +dojo.gfx.Colorspace.prototype.getRGB_XYZ_Matrix = function(){ + var wp = this.getWhitePoint(); + var pr = this.getPrimaries(); + + var Xr = pr.xr / pr.yr; + var Yr = 1; + var Zr = (1 - pr.xr - pr.yr) / pr.yr; + + var Xg = pr.xg / pr.yg; + var Yg = 1; + var Zg = (1 - pr.xg - pr.yg) / pr.yg; + + var Xb = pr.xb / pr.yb; + var Yb = 1; + var Zb = (1 - pr.xb - pr.yb) / pr.yb; + + var m1 = [[Xr, Yr, Zr],[Xg, Yg, Zg],[Xb, Yb, Zb]]; + var m2 = [[wp.X, wp.Y, wp.Z]]; + var sm = dojo.math.matrix.multiply(m2, dojo.math.matrix.inverse(m1)); + + var Sr = sm[0][0]; + var Sg = sm[0][1]; + var Sb = sm[0][2]; + + var m4 = [[Sr*Xr, Sr*Yr, Sr*Zr], + [Sg*Xg, Sg*Yg, Sg*Zg], + [Sb*Xb, Sb*Yb, Sb*Zb]]; + + return m4; +} + +dojo.gfx.Colorspace.prototype.getXYZ_RGB_Matrix = function(){ + var m = this.getRGB_XYZ_Matrix(); + return dojo.math.matrix.inverse(m); +} + +dojo.gfx.Colorspace.prototype.XYZ_to_Luv = function(){ + var src = this.munge('XYZ', arguments); + + var wp = this.getWhitePoint(); + var ud = (4 * src.X) / (src.X + 15 * src.Y + 3 * src.Z); + var vd = (9 * src.Y) / (src.X + 15 * src.Y + 3 * src.Z); + + var udr = (4 * wp.X) / (wp.X + 15 * wp.Y + 3 * wp.Z); + var vdr = (9 * wp.Y) / (wp.X + 15 * wp.Y + 3 * wp.Z); + var yr = src.Y / wp.Y; + + var L = (yr > this.epsilon()) ? 116 * Math.pow(yr, 1/3) - 16 : this.kappa() * yr; + var u = 13 * L * (ud-udr); + var v = 13 * L * (vd-vdr); + + return [L, u, v]; +} + +dojo.gfx.Colorspace.prototype.Luv_to_XYZ = function(){ + var src = this.munge('Luv', arguments); + + var wp = this.getWhitePoint(); + var uz = (4 * wp.X) / (wp.X + 15 * wp.Y + 3 * wp.Z); + var vz = (9 * wp.Y) / (wp.X + 15 * wp.Y + 3 * wp.Z); + var Y = (src.L > this.kappa() * this.epsilon()) ? Math.pow((src.L + 16) / 116, 3) : src.L / this.kappa(); + + var a = (1 / 3) * (((52 * src.L) / (src.u + 13 * src.L * uz)) - 1); + var b = -5 * Y; + var c = - (1 / 3); + var d = Y * (((39 * src.L) / (src.v + 13 * src.L * vz)) - 5); + + var X = (d - b) / (a - c); + var Z = X * a + b; + + return [X, Y, Z]; +} + +dojo.gfx.Colorspace.prototype.Luv_to_LCHuv = function(){ + var src = this.munge('Luv', arguments); + + var L = src.L; + var C = Math.pow(src.u * src.u + src.v * src.v, 0.5); + var H = Math.atan2(src.v, src.u) * (180 / Math.PI); + + if (H < 0){ H += 360; } + if (H > 360){ H -= 360; } + + return [L, C, H]; +} + +dojo.gfx.Colorspace.prototype.LCHuv_to_Luv = function(){ + var src = this.munge('LCH', arguments); + + var H_rad = src.H * (Math.PI / 180); + var L = src.L; + var u = src.C / Math.pow(Math.pow(Math.tan(H_rad), 2) + 1, 0.5); + var v = Math.pow(src.C * src.C - u * u, 0.5); + + if ((90 < src.H) && (src.H < 270)){ u *= -1; } + if (src.H > 180){ v *= -1; } + + return [L, u, v]; +} + +dojo.gfx.Colorspace.colorTemp_to_whitePoint = function(T){ + if (T < 4000){ + dojo.debug("Can't find a white point for temperatures under 4000K"); + return [0,0]; + } + + if (T > 25000){ + dojo.debug("Can't find a white point for temperatures over 25000K"); + return [0,0]; + } + + var T1 = T; + var T2 = T * T; + var T3 = T2 * T; + + var ten9 = Math.pow(10, 9); + var ten6 = Math.pow(10, 6); + var ten3 = Math.pow(10, 3); + + if (T <= 7000){ + var x = (-4.6070 * ten9 / T3) + (2.9678 * ten6 / T2) + (0.09911 * ten3 / T) + 0.244063; + }else{ + var x = (-2.0064 * ten9 / T3) + (1.9018 * ten6 / T2) + (0.24748 * ten3 / T) + 0.237040; + } + var y = -3.000 * x * x + 2.870 * x - 0.275; + + return [x, y]; +} + +dojo.gfx.Colorspace.prototype.RGB_to_CMY = function(){ + var src = this.munge('RGB', arguments); + + var C = 1 - src.R; + var M = 1 - src.G; + var Y = 1 - src.B; + + return [C, M, Y]; +} + +dojo.gfx.Colorspace.prototype.CMY_to_RGB = function(){ + var src = this.munge('CMY', arguments); + + var R = 1 - src.C; + var G = 1 - src.M; + var B = 1 - src.Y; + + return [R, G, B]; +} + +dojo.gfx.Colorspace.prototype.RGB_to_CMYK = function(){ + var src = this.munge('RGB', arguments); + + var K = Math.min(1-src.R, 1-src.G, 1-src.B); + var C = (1 - src.R - K) / (1 - K); + var M = (1 - src.G - K) / (1 - K); + var Y = (1 - src.B - K) / (1 - K); + + return [C, M, Y, K]; +} + +dojo.gfx.Colorspace.prototype.CMYK_to_RGB = function(){ + var src = this.munge('CMYK', arguments); + + var R = 1 - Math.min(1, src.C * (1-src.K) + src.K); + var G = 1 - Math.min(1, src.M * (1-src.K) + src.K); + var B = 1 - Math.min(1, src.Y * (1-src.K) + src.K); + + return [R, G, B]; +} + +dojo.gfx.Colorspace.prototype.CMY_to_CMYK = function(){ + var src = this.munge('CMY', arguments); + + var K = Math.min(src.C, src.M, src.Y); + var C = (src.C - K) / (1 - K); + var M = (src.M - K) / (1 - K); + var Y = (src.Y - K) / (1 - K); + + return [C, M, Y, K]; +} + +dojo.gfx.Colorspace.prototype.CMYK_to_CMY = function(){ + var src = this.munge('CMYK', arguments); + + var C = Math.min(1, src.C * (1-src.K) + src.K); + var M = Math.min(1, src.M * (1-src.K) + src.K); + var Y = Math.min(1, src.Y * (1-src.K) + src.K); + + return [C, M, Y]; +} + +dojo.gfx.Colorspace.prototype.RGB_to_HSV = function(){ + var src = this.munge('RGB', arguments); + + // Based on C Code in "Computer Graphics -- Principles and Practice," + // Foley et al, 1996, p. 592. + + var min = Math.min(src.R, src.G, src.B); + var V = Math.max(src.R, src.G, src.B); + + var delta = V - min; + + var H = null; + var S = (V == 0) ? 0 : delta / V; + + if (S == 0){ + H = 0; + }else{ + if (src.R == V){ + H = 60 * (src.G - src.B) / delta; + }else{ + if (src.G == V){ + H = 120 + 60 * (src.B - src.R) / delta; + }else{ + if (src.B == V){ + // between magenta and cyan + H = 240 + 60 * (src.R - src.G) / delta; + } + } + } + if (H < 0){ + H += 360; + } + } + + H = (H == 0) ? 360 : H; + + return [H, S, V]; +} + +dojo.gfx.Colorspace.prototype.HSV_to_RGB = function(){ + var src = this.munge('HSV', arguments); + if (src.H == 360){ src.H = 0;} + + // Based on C Code in "Computer Graphics -- Principles and Practice," + // Foley et al, 1996, p. 593. + var r = null; + var g = null; + var b = null; + + if (src.S == 0){ + // color is on black-and-white center line + // achromatic: shades of gray + var R = src.V; + var G = src.V; + var B = src.V; + }else{ + // chromatic color + var hTemp = src.H / 60; // h is now IN [0,6] + var i = Math.floor(hTemp); // largest integer <= h + var f = hTemp - i; // fractional part of h + + var p = src.V * (1 - src.S); + var q = src.V * (1 - (src.S * f)); + var t = src.V * (1 - (src.S * (1 - f))); + + switch(i){ + case 0: R = src.V; G = t ; B = p ; break; + case 1: R = q ; G = src.V; B = p ; break; + case 2: R = p ; G = src.V; B = t ; break; + case 3: R = p ; G = q ; B = src.V; break; + case 4: R = t ; G = p ; B = src.V; break; + case 5: R = src.V; G = p ; B = q ; break; + } + } + + return [R, G, B]; +} + +dojo.gfx.Colorspace.prototype.RGB_to_HSL = function(){ + var src = this.munge('RGB', arguments); + + // based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/ + var min = Math.min(src.R, src.G, src.B); + var max = Math.max(src.R, src.G, src.B); + var delta = max - min; + + var H = 0; + var S = 0; + var L = (min + max) / 2; + + if ((L > 0) && (L < 1)){ + S = delta / ((L < 0.5) ? (2 * L) : (2 - 2 * L)); + } + + if (delta > 0) { + if ((max == src.R) && (max != src.G)){ + H += (src.G - src.B) / delta; + } + if ((max == src.G) && (max != src.B)){ + H += (2 + (src.B - src.R) / delta); + } + if ((max == src.B) && (max != src.R)){ + H += (4 + (src.R - src.G) / delta); + } + H *= 60; + } + H = (H == 0) ? 360 : H; + return [H, S, L]; +} + +dojo.gfx.Colorspace.prototype.HSL_to_RGB = function(){ + var src = this.munge('HSL', arguments); + + // based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/ + while (src.H < 0){ src.H += 360; } + while (src.H >= 360){ src.H -= 360; } + + var R = 0; + var G = 0; + var B = 0; + + if (src.H < 120){ + R = (120 - src.H) / 60; + G = src.H / 60; + B = 0; + }else if (src.H < 240){ + R = 0; + G = (240 - src.H) / 60; + B = (src.H - 120) / 60; + }else{ + R = (src.H - 240) / 60; + G = 0; + B = (360 - src.H) / 60; + } + + R = 2 * src.S * Math.min(R, 1) + (1 - src.S); + G = 2 * src.S * Math.min(G, 1) + (1 - src.S); + B = 2 * src.S * Math.min(B, 1) + (1 - src.S); + + if (src.L < 0.5){ + R = src.L * R; + G = src.L * G; + B = src.L * B; + }else{ + R = (1 - src.L) * R + 2 * src.L - 1; + G = (1 - src.L) * G + 2 * src.L - 1; + B = (1 - src.L) * B + 2 * src.L - 1; + } + return [R, G, B]; +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/__package__.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,23 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [ + "dojo.gfx.color", + "dojo.gfx.matrix", + "dojo.gfx.common" + ] +}); + +// include a renderer conditionally +dojo["requireIf"](dojo.render.svg.capable, "dojo.gfx.svg"); +dojo["requireIf"](!dojo.render.svg.capable && dojo.render.vml.capable, "dojo.gfx.vml"); + +dojo.provide("dojo.gfx.*"); \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/color.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/color.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/color.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,183 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.color"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.array"); + +// TODO: rewrite the "x2y" methods to take advantage of the parsing +// abilities of the Color object. Also, beef up the Color +// object (as possible) to parse most common formats + +// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa) +dojo.gfx.color.Color = function(r, g, b, a) { + // dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]); + if(dojo.lang.isArray(r)){ + this.r = r[0]; + this.g = r[1]; + this.b = r[2]; + this.a = r[3]||1.0; + }else if(dojo.lang.isString(r)){ + var rgb = dojo.gfx.color.extractRGB(r); + this.r = rgb[0]; + this.g = rgb[1]; + this.b = rgb[2]; + this.a = g||1.0; + }else if(r instanceof dojo.gfx.color.Color){ + // why does this create a new instance if we were passed one? + this.r = r.r; + this.b = r.b; + this.g = r.g; + this.a = r.a; + }else{ + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } +} + +dojo.gfx.color.Color.fromArray = function(arr) { + return new dojo.gfx.color.Color(arr[0], arr[1], arr[2], arr[3]); +} + +dojo.extend(dojo.gfx.color.Color, { + toRgb: function(includeAlpha) { + if(includeAlpha) { + return this.toRgba(); + } else { + return [this.r, this.g, this.b]; + } + }, + toRgba: function() { + return [this.r, this.g, this.b, this.a]; + }, + toHex: function() { + return dojo.gfx.color.rgb2hex(this.toRgb()); + }, + toCss: function() { + return "rgb(" + this.toRgb().join() + ")"; + }, + toString: function() { + return this.toHex(); // decent default? + }, + blend: function(color, weight){ + var rgb = null; + if(dojo.lang.isArray(color)){ + rgb = color; + }else if(color instanceof dojo.gfx.color.Color){ + rgb = color.toRgb(); + }else{ + rgb = new dojo.gfx.color.Color(color).toRgb(); + } + return dojo.gfx.color.blend(this.toRgb(), rgb, weight); + } +}); + +dojo.gfx.color.named = { + white: [255,255,255], + black: [0,0,0], + red: [255,0,0], + green: [0,255,0], + lime: [0,255,0], + blue: [0,0,255], + navy: [0,0,128], + gray: [128,128,128], + silver: [192,192,192] +}; + +dojo.gfx.color.blend = function(a, b, weight){ + // summary: + // blend colors a and b (both as RGB array or hex strings) with weight + // from -1 to +1, 0 being a 50/50 blend + if(typeof a == "string"){ + return dojo.gfx.color.blendHex(a, b, weight); + } + if(!weight){ + weight = 0; + } + weight = Math.min(Math.max(-1, weight), 1); + + // alex: this interface blows. + // map -1 to 1 to the range 0 to 1 + weight = ((weight + 1)/2); + + var c = []; + + // var stop = (1000*weight); + for(var x = 0; x < 3; x++){ + c[x] = parseInt( b[x] + ( (a[x] - b[x]) * weight) ); + } + return c; +} + +// very convenient blend that takes and returns hex values +// (will get called automatically by blend when blend gets strings) +dojo.gfx.color.blendHex = function(a, b, weight) { + return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a), dojo.gfx.color.hex2rgb(b), weight)); +} + +// get RGB array from css-style color declarations +dojo.gfx.color.extractRGB = function(color) { + var hex = "0123456789abcdef"; + color = color.toLowerCase(); + if( color.indexOf("rgb") == 0 ) { + var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i); + var ret = matches.splice(1, 3); + return ret; + } else { + var colors = dojo.gfx.color.hex2rgb(color); + if(colors) { + return colors; + } else { + // named color (how many do we support?) + return dojo.gfx.color.named[color] || [255, 255, 255]; + } + } +} + +dojo.gfx.color.hex2rgb = function(hex) { + var hexNum = "0123456789ABCDEF"; + var rgb = new Array(3); + if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); } + hex = hex.toUpperCase(); + if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") { + return null; + } + if( hex.length == 3 ) { + rgb[0] = hex.charAt(0) + hex.charAt(0) + rgb[1] = hex.charAt(1) + hex.charAt(1) + rgb[2] = hex.charAt(2) + hex.charAt(2); + } else { + rgb[0] = hex.substring(0, 2); + rgb[1] = hex.substring(2, 4); + rgb[2] = hex.substring(4); + } + for(var i = 0; i < rgb.length; i++) { + rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1)); + } + return rgb; +} + +dojo.gfx.color.rgb2hex = function(r, g, b) { + if(dojo.lang.isArray(r)) { + g = r[1] || 0; + b = r[2] || 0; + r = r[0] || 0; + } + var ret = dojo.lang.map([r, g, b], function(x) { + x = new Number(x); + var s = x.toString(16); + while(s.length < 2) { s = "0" + s; } + return s; + }); + ret.unshift("#"); + return ret.join(""); +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/common.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,103 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.common"); + +dojo.require("dojo.gfx.color"); +dojo.require("dojo.lang.declare"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.dom"); + +dojo.lang.mixin(dojo.gfx, { + // summary: defines constants, prototypes, and utility functions + + // default shapes, which is used to fill in missing parameters + defaultPath: {type: "path", path: ""}, + defaultPolyline: {type: "polyline", points: []}, + defaultRect: {type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0}, + defaultEllipse: {type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100}, + defaultCircle: {type: "circle", cx: 0, cy: 0, r: 100}, + defaultLine: {type: "line", x1: 0, y1: 0, x2: 100, y2: 100}, + defaultImage: {type: "image", width: 0, height: 0, src: ""}, + + // default geometric attributes (a stroke, and fills) + defaultStroke: {color: "black", width: 1, cap: "butt", join: 4}, + defaultLinearGradient: {type: "linear", x1: 0, y1: 0, x2: 100, y2: 100, + colors: [{offset: 0, color: "black"}, {offset: 1, color: "white"}]}, + defaultRadialGradient: {type: "radial", cx: 0, cy: 0, r: 100, + colors: [{offset: 0, color: "black"}, {offset: 1, color: "white"}]}, + defaultPattern: {type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""}, + + normalizeColor: function(/* Color */ color){ + // summary: converts any legal color representation to normalized Color object + return (color instanceof dojo.gfx.color.Color) ? color : new dojo.gfx.color.Color(color); // dojo.gfx.color.Color + }, + normalizeParameters: function(/* Object */ existed, /* Object */ update){ + // summary: updates an existing object with properties from the "update" object + // existed: the "target" object to be updated + // update: the "update" object, whose properties will be used to update the existed object + if(update){ + var empty = {}; + for(var x in existed){ + if(x in update && !(x in empty)){ + existed[x] = update[x]; + } + } + } + return existed; // Object + }, + makeParameters: function(/* Object */ defaults, /* Object */ update){ + // summary: copies the original object, and all copied properties from the "update" object + // defaults: the object to be cloned before updating + // update: the object, which properties are to be cloned during updating + if(!update) return dojo.lang.shallowCopy(defaults, true); + var result = {}; + for(var i in defaults){ + if(!(i in result)){ + result[i] = dojo.lang.shallowCopy((i in update) ? update[i] : defaults[i], true); + } + } + return result; // Object + }, + formatNumber: function(/* Number */ x, /* Boolean, optional */ addSpace){ + // summary: converts a number to a string using a fixed notation + // x: number to be converted + // addSpace: add a space before a positive number + var val = x.toString(); + if(val.indexOf("e") >= 0){ + val = x.toFixed(4); + }else{ + var point = val.indexOf("."); + if(point >= 0 && val.length - point > 5){ + val = x.toFixed(4); + } + } + if(x < 0){ + return val; // String + } + return addSpace ? " " + val : val; // String + }, + // a constant used to split a SVG/VML path into primitive components + pathRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g +}); + +dojo.declare("dojo.gfx.Surface", null, { + // summary: a surface object to be used for drawings + initializer: function(){ + // summary: a constructor + + // underlying node + this.rawNode = null; + }, + getEventSource: function(){ + // summary: returns a node, which can be used to attach event listeners + return this.rawNode; // Node + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/matrix.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/matrix.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/matrix.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,242 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.matrix"); + +dojo.require("dojo.lang.common"); +dojo.require("dojo.math.*"); + +dojo.gfx.matrix.Matrix2D = function(/* Matrix2D */ arg){ + // summary: a constructor for 2D matrix + // arg: a matrix-like object + if(arg){ + if(arg instanceof Array){ + if(arg.length > 0){ + var m = dojo.gfx.matrix.normalize(arg[0]); + // combine matrices + for(var i = 1; i < arg.length; ++i){ + var l = m; + var r = dojo.gfx.matrix.normalize(arg[i]); + m = new dojo.gfx.matrix.Matrix2D(); + m.xx = l.xx * r.xx + l.xy * r.yx; + m.xy = l.xx * r.xy + l.xy * r.yy; + m.yx = l.yx * r.xx + l.yy * r.yx; + m.yy = l.yx * r.xy + l.yy * r.yy; + m.dx = l.xx * r.dx + l.xy * r.dy + l.dx; + m.dy = l.yx * r.dx + l.yy * r.dy + l.dy; + } + dojo.mixin(this, m); + } + }else{ + dojo.mixin(this, arg); + } + } +}; + +// the default (identity) matrix, which is used to fill in missing values +dojo.extend(dojo.gfx.matrix.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0}); + +dojo.mixin(dojo.gfx.matrix, { + // summary: class constants, and methods of dojo.gfx.matrix.Matrix2D + + // matrix constants + identity: new dojo.gfx.matrix.Matrix2D(), + flipX: new dojo.gfx.matrix.Matrix2D({xx: -1}), + flipY: new dojo.gfx.matrix.Matrix2D({yy: -1}), + flipXY: new dojo.gfx.matrix.Matrix2D({xx: -1, yy: -1}), + + // matrix creators + translate: function(/* Number||Point */ a, /* Number, optional */ b){ + // summary: forms a translation matrix + // a: an X coordinate value (a number), or a point object + // b: an optional Y coordinate value + return arguments.length > 1 ? new dojo.gfx.matrix.Matrix2D({dx: a, dy: b}) : new dojo.gfx.matrix.Matrix2D({dx: a.x, dy: a.y}); // dojo.gfx.matrix.Matrix2D + }, + scale: function(/* Number||Point */ a, /* Number||Nothing */ b){ + // summary: forms a scaling matrix + // a: a scaling factor used for X, or a point object + // b: an optional scaling factor for Y + return arguments.length > 1 ? new dojo.gfx.matrix.Matrix2D({xx: a, yy: b}) : typeof a == "number" ? new dojo.gfx.matrix.Matrix2D({xx: a, yy: a}) : new dojo.gfx.matrix.Matrix2D({xx: a.x, yy: a.y}); // dojo.gfx.matrix.Matrix2D + }, + rotate: function(/* Number */ angle){ + // summary: forms a rotating matrix + // angle: an angle of rotation in radians (>0 for CCW) + var c = Math.cos(angle); + var s = Math.sin(angle); + return new dojo.gfx.matrix.Matrix2D({xx: c, xy: s, yx: -s, yy: c}); // dojo.gfx.matrix.Matrix2D + }, + rotateg: function(/* Number */ degree){ + // summary: forms a rotating matrix + // degree: an angle of rotation in degrees (>0 for CCW) + return dojo.gfx.matrix.rotate(dojo.math.degToRad(degree)); // dojo.gfx.matrix.Matrix2D + }, + skewX: function(/* Number */ angle) { + // summary: forms an X skewing matrix + // angle: an skewing angle in radians + return new dojo.gfx.matrix.Matrix2D({xy: Math.tan(angle)}); // dojo.gfx.matrix.Matrix2D + }, + skewXg: function(/* Number */ degree){ + // summary: forms an X skewing matrix + // degree: an skewing angle in degrees + return dojo.gfx.matrix.skewX(dojo.math.degToRad(degree)); // dojo.gfx.matrix.Matrix2D + }, + skewY: function(/* Number */ angle){ + // summary: forms a Y skewing matrix + // angle: an skewing angle in radians + return new dojo.gfx.matrix.Matrix2D({yx: -Math.tan(angle)}); // dojo.gfx.matrix.Matrix2D + }, + skewYg: function(/* Number */ degree){ + // summary: forms a Y skewing matrix + // degree: an skewing angle in degrees + return dojo.gfx.matrix.skewY(dojo.math.degToRad(degree)); // dojo.gfx.matrix.Matrix2D + }, + + // ensure matrix 2D conformance + normalize: function(/* Matrix2D */ matrix){ + // summary: converts an object to a matrix, if necessary + // matrix: an object, which is converted to a matrix, if necessary + return (matrix instanceof dojo.gfx.matrix.Matrix2D) ? matrix : new dojo.gfx.matrix.Matrix2D(matrix); // dojo.gfx.matrix.Matrix2D + }, + + // common operations + clone: function(/* Matrix2D */ matrix){ + // summary: creates a copy of a matrix + // matrix: a matrix object to be cloned + var obj = new dojo.gfx.matrix.Matrix2D(); + for(var i in matrix){ + if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i]; + } + return obj; // dojo.gfx.matrix.Matrix2D + }, + invert: function(/* Matrix2D */ matrix){ + // summary: inverts a matrix + // matrix: a matrix object to be inverted + var m = dojo.gfx.matrix.normalize(matrix); + var D = m.xx * m.yy - m.xy * m.yx; + return new dojo.gfx.matrix.Matrix2D({xx: m.yy/D, xy: -m.xy/D, yx: -m.yx/D, yy: m.xx/D, dx: (m.yx * m.dy - m.yy * m.dx) / D, dy: (m.xy * m.dx - m.xx * m.dy) / D}); // dojo.gfx.matrix.Matrix2D + }, + _multiplyPoint: function(/* Matrix2D */ m, /* Number */ x, /* Number */ y){ + // summary: applies a matrix to a point + // matrix: a matrix object to be applied + // a: an X coordinate of a point + // b: a Y coordinate of a point + return {x: m.xx * x + m.xy * y + m.dx, y: m.yx * x + m.yy * y + m.dy}; // Point + }, + multiplyPoint: function(/* Matrix */ matrix, /* Number||Point */ a, /* Number, optional */ b){ + // summary: applies a matrix to a point + // matrix: a matrix-like object to be applied + // a: an X coordinate of a point, or a point object + // b: an optional Y coordinate of a point + var m = dojo.gfx.matrix.normalize(matrix); + if(typeof a == "number" && typeof b == "number"){ + return dojo.gfx.matrix._multiplyPoint(m, a, b); + } + return dojo.gfx.matrix._multiplyPoint(m, a.x, a.y); // Point + }, + multiply: function(/* Matrix */ matrix){ + // summary: combines matrices by multiplying them + // matrix: a matrix-like object, all subsequent arguments are matrix-like objects too. + var m = dojo.gfx.matrix.normalize(matrix); + // combine matrices + for(var i = 1; i < arguments.length; ++i){ + var l = m; + var r = dojo.gfx.matrix.normalize(arguments[i]); + m = new dojo.gfx.matrix.Matrix2D(); + m.xx = l.xx * r.xx + l.xy * r.yx; + m.xy = l.xx * r.xy + l.xy * r.yy; + m.yx = l.yx * r.xx + l.yy * r.yx; + m.yy = l.yx * r.xy + l.yy * r.yy; + m.dx = l.xx * r.dx + l.xy * r.dy + l.dx; + m.dy = l.yx * r.dx + l.yy * r.dy + l.dy; + } + return m; // dojo.gfx.matrix.Matrix2D + }, + + // high level operations + _sandwich: function(/* Matrix */ m, /* Number */ x, /* Number */ y){ + // summary: applies a matrix at a centrtal point + // m: a matrix-like object, which is applied at the point + // x: an X component of the point + // y: a Y component of the point + return dojo.gfx.matrix.multiply(dojo.gfx.matrix.translate(x, y), m, dojo.gfx.matrix.translate(-x, -y)); // dojo.gfx.matrix.Matrix2D + }, + scaleAt: function(/* Number */ a, /* Number, optional */ b, /* Number||Point */ c, /* Number, optional */ d){ + // summary: scales a picture using a specified point as a center of scaling + + // accepts several signatures: + // 1) uniform scale factor, Point + // 2) uniform scale factor, x, y + // 3) x scale, y scale, Point + // 4) x scale, y scale, x, y + switch(arguments.length){ + case 2: + // a is a scale factor, b is a point + return dojo.gfx.matrix._sandwich(dojo.gfx.matrix.scale(a), b.x, b.y); // dojo.gfx.matrix.Matrix2D + case 3: + if(typeof c == "number"){ + // a is scale factor, b and c are x and y components of a point + return dojo.gfx.matrix._sandwich(dojo.gfx.matrix.scale(a), b, c); // dojo.gfx.matrix.Matrix2D + } + // a and b are scale factor components, c is a point + return dojo.gfx.matrix._sandwich(dojo.gfx.matrix.scale(a, b), c.x, c.y); // dojo.gfx.matrix.Matrix2D + } + // a and b are scale factor components, c and d are components of a point + return dojo.gfx.matrix._sandwich(dojo.gfx.matrix.scale(a, b), c, d); // dojo.gfx.matrix.Matrix2D + }, + rotateAt: function(/* Number */ angle, /* Number||Point */ a, /* Number, optional */ b){ + // summary: rotates a picture using a specified point as a center of rotation + + // accepts several signatures: + // 1) rotation angle in radians, Point + // 2) rotation angle in radians, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.rotate(angle), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.rotate(angle), a.x, a.y); // dojo.gfx.matrix.Matrix2D + }, + rotategAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){ + // summary: rotates a picture using a specified point as a center of rotation + + // accepts several signatures: + // 1) rotation angle in degrees, Point + // 2) rotation angle in degrees, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.rotateg(degree), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.rotateg(degree), a.x, a.y); // dojo.gfx.matrix.Matrix2D + }, + skewXAt: function(/* Number */ angle, /* Number||Point */ a, /* Number, optional */ b){ + // summary: skews a picture along the X axis using a specified point as a center of skewing + + // accepts several signatures: + // 1) skew angle in radians, Point + // 2) skew angle in radians, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewX(angle), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewX(angle), a.x, a.y); // dojo.gfx.matrix.Matrix2D + }, + skewXgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){ + // summary: skews a picture along the X axis using a specified point as a center of skewing + + // accepts several signatures: + // 1) skew angle in degrees, Point + // 2) skew angle in degrees, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewXg(degree), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewXg(degree), a.x, a.y); // dojo.gfx.matrix.Matrix2D + }, + skewYAt: function(/* Number */ angle, /* Number||Point */ a, /* Number, optional */ b){ + // summary: skews a picture along the Y axis using a specified point as a center of skewing + + // accepts several signatures: + // 1) skew angle in radians, Point + // 2) skew angle in radians, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewY(angle), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewY(angle), a.x, a.y); // dojo.gfx.matrix.Matrix2D + }, + skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){ + // summary: skews a picture along the Y axis using a specified point as a center of skewing + + // accepts several signatures: + // 1) skew angle in degrees, Point + // 2) skew angle in degrees, x, y + return arguments.length > 1 ? dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewYg(degree), a, b) : dojo.gfx.matrix._sandwich(dojo.gfx.matrix.skewYg(degree), a.x, a.y); // dojo.gfx.matrix.Matrix2D + } + // TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions) +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/path.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/path.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/path.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,320 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.path"); + +dojo.require("dojo.math"); + +dojo.require("dojo.gfx.shape"); + +dojo.declare("dojo.gfx.path.Path", dojo.gfx.Shape, { + // summary: + // a path shape + initializer: function(/* Node */ rawNode){ + // summary: a constructor of a path shape object + // rawNode: a DOM node to be used by this path object + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultPath, true); + this.segments = []; + this.absolute = true; + this.last = {}; + this.attach(rawNode); + }, + + // mode manipulations + setAbsoluteMode: function(/* Boolean||String */ mode){ + // summary: sets an absolute or relative mode for path points + // mode: true/false or "absolute"/"relative" to specify the mode + this.absolute = typeof(mode) == "string" ? (mode == "absolute") : mode; + return this; // self + }, + getAbsoluteMode: function(){ + // summary: returns a current value of the absolute mode + return this.absolute; // Boolean + }, + getBoundingBox: function(){ + // summary: returns a bounding box {x, y, width, height} or null + return "l" in this.bbox ? {x: this.bbox.l, y: this.bbox.t, width: this.bbox.r - this.bbox.l, height: this.bbox.b - this.bbox.t} : null; // Object + }, + getLastPosition: function(){ + // summary: returns the last point in the path, or null + return "x" in this.last ? this.last : null; // Object + }, + + // segment interpretation + _updateBBox: function(/* Number */ x, /* Number */ y){ + // summary: updates a bounding box of path with new point + + // we use {l, b, r, t} representation of a bbox + if("l" in this.bbox){ + if(this.bbox.l > x) this.bbox.l = x; + if(this.bbox.r < x) this.bbox.r = x; + if(this.bbox.t > y) this.bbox.t = y; + if(this.bbox.b < y) this.bbox.b = y; + }else{ + this.bbox = {l: x, b: y, r: x, t: y}; + } + }, + _updateWithSegment: function(/* Object */ segment){ + // summary: updates a bounding box of path with new segment + var n = segment.args; + var l = n.length; + // update internal variables: bbox, absolute, last + switch(segment.action){ + case "M": + case "L": + case "C": + case "S": + case "Q": + case "T": + for(var i = 0; i < l; i += 2){ + this._updateBBox(this.bbox, n[i], n[i + 1]); + } + this.last.x = n[l - 2]; + this.last.y = n[l - 1]; + this.absolute = true; + break; + case "H": + for(var i = 0; i < l; ++i){ + this._updateBBox(this.bbox, n[i], this.last.y); + } + this.last.x = n[l - 1]; + this.absolute = true; + break; + case "V": + for(var i = 0; i < l; ++i){ + this._updateBBox(this.bbox, this.last.x, n[i]); + } + this.last.y = n[l - 1]; + this.absolute = true; + break; + case "m": + var start = 0; + if(!("x" in this.last)){ + this._updateBBox(this.bbox, this.last.x = n[0], this.last.y = n[1]); + start = 2; + } + for(var i = start; i < l; i += 2){ + this._updateBBox(this.bbox, this.last.x += n[i], this.last.y += n[i + 1]); + } + this.absolute = false; + break; + case "l": + case "t": + for(var i = 0; i < l; i += 2){ + this._updateBBox(this.bbox, this.last.x += n[i], this.last.y += n[i + 1]); + } + this.absolute = false; + break; + case "h": + for(var i = 0; i < l; ++i){ + this._updateBBox(this.bbox, this.last.x += n[i], this.last.y); + } + this.absolute = false; + break; + case "v": + for(var i = 0; i < l; ++i){ + this._updateBBox(this.bbox, this.last.x, this.last.y += n[i]); + } + this.absolute = false; + break; + case "c": + for(var i = 0; i < l; i += 6){ + this._updateBBox(this.bbox, this.last.x + n[i], this.last.y + n[i + 1]); + this._updateBBox(this.bbox, this.last.x + n[i + 2], this.last.y + n[i + 3]); + this._updateBBox(this.bbox, this.last.x += n[i + 4], this.last.y += n[i + 5]); + } + this.absolute = false; + break; + case "s": + case "q": + for(var i = 0; i < l; i += 4){ + this._updateBBox(this.bbox, this.last.x + n[i], this.last.y + n[i + 1]); + this._updateBBox(this.bbox, this.last.x += n[i + 2], this.last.y += n[i + 3]); + } + this.absolute = false; + break; + case "A": + for(var i = 0; i < l; i += 7){ + this._updateBBox(this.bbox, n[i + 5], n[i + 6]); + } + this.last.x = n[l - 2]; + this.last.y = n[l - 1]; + this.absolute = true; + break; + case "a": + for(var i = 0; i < l; i += 7){ + this._updateBBox(this.bbox, this.last.x += n[i + 5], this.last.y += n[i + 6]); + } + this.absolute = false; + break; + } + // add an SVG path segment + var path = [segment.action]; + for(var i = 0; i < l; ++i){ + path.push(dojo.gfx.formatNumber(n[i], true)); + } + if(typeof(this.shape.path) == "string"){ + this.shape.path += path.join(""); + }else{ + this.shape.path = this.shape.path.concat(path); + } + }, + // a dictionary, which maps segment type codes to a number of their argemnts + _validSegments: {m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, z: 0}, + _pushSegment: function(/* String */ action, /* Array */ args){ + // summary: adds a segment + // action: valid SVG code for a segment's type + // args: a list of parameters for this segment + var group = this._validSegments[action.toLowerCase()]; + if(typeof(group) == "number"){ + if(group){ + if(args.length >= group){ + var segment = {action: action, args: args.slice(0, args.length - args.length % group)}; + this.segments.push(segment); + this._updateWithSegment(segment); + } + }else{ + var segment = {action: action, args: []}; + this.segments.push(segment); + this._updateWithSegment(segment); + } + } + }, + _collectArgs: function(/* Array */ array, /* Array */ args){ + // summary: converts an array of arguments to plain numeric values + for(var i = 0; i < args.length; ++i){ + var t = args[i]; + if(typeof(t) == "boolean"){ + array.push(t ? 1 : 0); + }else if(typeof(t) == "number"){ + array.push(t); + }else if(t instanceof Array){ + this._collectArgs(array, t); + }else if("x" in t && "y" in t){ + array.push(t.x); + array.push(t.y); + } + } + }, + + // segments + moveTo: function(){ + // summary: formes a move segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "M" : "m", args); + return this; // self + }, + lineTo: function(){ + // summary: formes a line segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "L" : "l", args); + return this; // self + }, + hLineTo: function(){ + // summary: formes a horizontal line segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "H" : "h", args); + return this; // self + }, + vLineTo: function(){ + // summary: formes a vertical line segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "V" : "v", args); + return this; // self + }, + curveTo: function(){ + // summary: formes a curve segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "C" : "c", args); + return this; // self + }, + smoothCurveTo: function(){ + // summary: formes a smooth curve segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "S" : "s", args); + return this; // self + }, + qCurveTo: function(){ + // summary: formes a quadratic curve segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "Q" : "q", args); + return this; // self + }, + qSmoothCurveTo: function(){ + // summary: formes a quadratic smooth curve segment + var args = []; + this._collectArgs(args, arguments); + this._pushSegment(this.absolute ? "T" : "t", args); + return this; // self + }, + arcTo: function(){ + // summary: formes an elliptic arc segment + var args = []; + this._collectArgs(args, arguments); + for(var i = 2; i < args.length; i += 7){ + args[i] = -args[i]; + } + this._pushSegment(this.absolute ? "A" : "a", args); + return this; // self + }, + closePath: function(){ + // summary: closes a path + this._pushSegment("Z", []); + return this; // self + }, + + // setShape + _setPath: function(path){ + // summary: forms a path using an SVG path string + var p = path.match(dojo.gfx.pathRegExp); + this.segments = []; + this.absolute = true; + this.bbox = {}; + this.last = {}; + if(!p) return; + // create segments + var action = ""; // current action + var args = []; // current arguments + for(var i = 0; i < p.length; ++i){ + var t = p[i]; + var x = parseFloat(t); + if(isNaN(x)){ + if(action){ + this._pushSegment(action, args); + } + args = []; + action = t; + }else{ + args.push(x); + } + } + this._pushSegment(action, args); + }, + setShape: function(newShape){ + // summary: forms a path using a shape + this.shape = dojo.gfx.makeParameters(this.shape, typeof(newShape) == "string" ? {path: newShape} : newShape); + var path = this.shape.path; + // switch to non-updating version of path building + this.shape.path = []; + this._setPath(path); + // switch back to the string path + this.shape.path = this.shape.path.join(""); + return this; // self + }, + + _2PI: Math.PI * 2 // useful constant for descendants +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/shape.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/shape.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/shape.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,238 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.shape"); + +dojo.require("dojo.lang.declare"); + +dojo.require("dojo.gfx.common"); + +// this is a Shape object, which knows how to apply graphical attributes and a transformation +dojo.declare("dojo.gfx.Shape", null, { + + initializer: function(){ + // underlying node + this.rawNode = null; + // abstract shape object + this.shape = null; + // transformation matrix + this.matrix = null; + // graphical attributes + this.fillStyle = null; + this.strokeStyle = null; + // virtual group structure + this.parent = null; + this.parentMatrix = null; + // bounding box + this.bbox = null; + }, + + // trivial getters + getNode: function(){ return this.rawNode; }, + getShape: function(){ return this.shape; }, + getTransform: function(){ return this.matrix; }, + getFill: function(){ return this.fillStyle; }, + getStroke: function(){ return this.strokeStyle; }, + getParent: function(){ return this.parent; }, + getBoundingBox: function(){ return this.bbox; }, + getEventSource: function(){ return this.rawNode; }, + + // empty settings + setShape: function(shape) { return this; }, // ignore + setStroke: function(stroke){ return this; }, // ignore + setFill: function(fill) { return this; }, // ignore + + // z-index + moveToFront: function(){ return this; }, // ignore + moveToBack: function(){ return this; }, // ignore + + // apply transformations + setTransform: function(matrix){ + this.matrix = dojo.gfx.matrix.clone(matrix ? dojo.gfx.matrix.normalize(matrix) : dojo.gfx.identity, true); + return this._applyTransform(); + }, + + // apply left & right transformation + applyRightTransform: function(matrix){ + return matrix ? this.setTransform([this.matrix, matrix]) : this; + }, + applyLeftTransform: function(matrix){ + return matrix ? this.setTransform([matrix, this.matrix]) : this; + }, + + // a shortcut for apply-right + applyTransform: function(matrix){ + return matrix ? this.setTransform([this.matrix, matrix]) : this; + }, + + // virtual group methods + remove: function(silently){ + if(this.parent){ + this.parent.remove(this, silently); + } + return this; + }, + _setParent: function(parent, matrix){ + this.parent = parent; + return this._updateParentMatrix(matrix); + }, + _updateParentMatrix: function(matrix){ + this.parentMatrix = matrix ? dojo.gfx.matrix.clone(matrix) : null; + return this._applyTransform(); + }, + _getRealMatrix: function(){ + return this.parentMatrix ? new dojo.gfx.matrix.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix; + } +}); + +dojo.declare("dojo.gfx.shape.VirtualGroup", dojo.gfx.Shape, { + initializer: function() { + this.children = []; + }, + + // group management + add: function(shape){ + var oldParent = shape.getParent(); + if(oldParent){ + oldParent.remove(shape, true); + } + this.children.push(shape); + return shape._setParent(this, this._getRealMatrix()); + }, + remove: function(shape, silently){ + var i = 0; + for(; i < this.children.length; ++i){ + if(this.children[i] == shape){ + if(silently){ + // skip for now + }else{ + shape._setParent(null, null); + } + this.children.splice(i, 1); + break; + } + } + return this; + }, + + // apply transformation + _applyTransform: function(){ + var matrix = this._getRealMatrix(); + for(var i = 0; i < this.children.length; ++i){ + this.children[i]._updateParentMatrix(matrix); + } + return this; + } +}); + +dojo.declare("dojo.gfx.shape.Rect", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultRect, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ return this.shape; } +}); + +dojo.declare("dojo.gfx.shape.Ellipse", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultEllipse, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ + if(!this.bbox){ + var shape = this.shape; + this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry, + width: 2 * shape.rx, height: 2 * shape.ry}; + } + return this.bbox; + } +}); + +dojo.declare("dojo.gfx.shape.Circle", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultCircle, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ + if(!this.bbox){ + var shape = this.shape; + this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r, + width: 2 * shape.r, height: 2 * shape.r}; + } + return this.bbox; + } +}); + +dojo.declare("dojo.gfx.shape.Line", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultLine, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ + if(!this.bbox){ + var shape = this.shape; + this.bbox = { + x: Math.min(shape.x1, shape.x2), + y: Math.min(shape.y1, shape.y2), + width: Math.abs(shape.x2 - shape.x1), + height: Math.abs(shape.y2 - shape.y1) + }; + } + return this.bbox; + } +}); + +dojo.declare("dojo.gfx.shape.Polyline", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultPolyline, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ + if(!this.bbox && this.shape.points.length){ + var p = this.shape.points; + var l = p.length; + var t = p[0]; + var bbox = {l: t.x, t: t.y, r: t.x, b: t.y}; + for(var i = 1; i < l; ++i){ + t = p[i]; + if(bbox.l > t.x) bbox.l = t.x; + if(bbox.r < t.x) bbox.r = t.x; + if(bbox.t > t.y) bbox.t = t.y; + if(bbox.b < t.y) bbox.b = t.y; + } + this.bbox = { + x: bbox.l, + y: bbox.t, + width: bbox.r - bbox.l, + height: bbox.b - bbox.t + }; + } + return this.bbox; + } +}); + +dojo.declare("dojo.gfx.shape.Image", dojo.gfx.Shape, { + initializer: function(rawNode) { + this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultImage, true); + this.attach(rawNode); + }, + getBoundingBox: function(){ + if(!this.bbox){ + var shape = this.shape; + this.bbox = { + x: 0, + y: 0, + width: shape.width, + height: shape.height + }; + } + return this.bbox; + } +}); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/svg.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/svg.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/svg.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,553 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.svg"); + +dojo.require("dojo.lang.declare"); +dojo.require("dojo.svg"); + +dojo.require("dojo.gfx.color"); +dojo.require("dojo.gfx.common"); +dojo.require("dojo.gfx.shape"); +dojo.require("dojo.gfx.path"); + +dojo.require("dojo.experimental"); +dojo.experimental("dojo.gfx.svg"); + +dojo.gfx.svg.getRef = function(fill){ + if(!fill || fill == "none") return null; + if(fill.match(/^url\(#.+\)$/)){ + return dojo.byId(fill.slice(5, -1)); + } + // Opera's bug: incorrect representation of a reference + if(dojo.render.html.opera && fill.match(/^#dj_unique_.+$/)){ + // we assume here that a reference was generated by dojo.gfx + return dojo.byId(fill.slice(1)); + } + return null; +}; + +dojo.lang.extend(dojo.gfx.Shape, { + setStroke: function(stroke){ + if(!stroke){ + // don't stroke + this.strokeStyle = null; + this.rawNode.setAttribute("stroke", "none"); + this.rawNode.setAttribute("stroke-opacity", 0); + return this; + } + // normalize the stroke + this.strokeStyle = dojo.gfx.makeParameters(dojo.gfx.defaultStroke, stroke); + this.strokeStyle.color = dojo.gfx.normalizeColor(this.strokeStyle.color); + // generate attributes + var s = this.strokeStyle; + var rn = this.rawNode; + if(s){ + rn.setAttribute("stroke", s.color.toCss()); + rn.setAttribute("stroke-opacity", s.color.a); + rn.setAttribute("stroke-width", s.width); + rn.setAttribute("stroke-linecap", s.cap); + if(typeof(s.join) == "number"){ + rn.setAttribute("stroke-linejoin", "miter"); + rn.setAttribute("stroke-miterlimit", s.join); + }else{ + rn.setAttribute("stroke-linejoin", s.join); + } + } + return this; + }, + + setFill: function(fill){ + if(!fill){ + // don't fill + this.fillStyle = null; + this.rawNode.setAttribute("fill", "none"); + this.rawNode.setAttribute("fill-opacity", 0); + return this; + } + if(typeof(fill) == "object" && "type" in fill){ + // gradient + switch(fill.type){ + case "linear": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultLinearGradient, fill); + var gradient = this._setFillObject(f, "linearGradient"); + dojo.lang.forEach(["x1", "y1", "x2", "y2"], function(x){ + gradient.setAttribute(x, f[x].toFixed(8)); + }); + break; + case "radial": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultRadialGradient, fill); + var gradient = this._setFillObject(f, "radialGradient"); + dojo.lang.forEach(["cx", "cy", "r"], function(x){ + gradient.setAttribute(x, f[x].toFixed(8)); + }); + break; + case "pattern": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultPattern, fill); + var pattern = this._setFillObject(f, "pattern"); + dojo.lang.forEach(["x", "y", "width", "height"], function(x){ + pattern.setAttribute(x, f[x].toFixed(8)); + }); + break; + } + return this; + } + // color object + var f = dojo.gfx.normalizeColor(fill); + this.fillStyle = f; + this.rawNode.setAttribute("fill", f.toCss()); + this.rawNode.setAttribute("fill-opacity", f.a); + return this; + }, + + _setFillObject: function(/*Object*/f, /*String*/nodeType){ + var def_elems = this.rawNode.parentNode.getElementsByTagName("defs"); + if(def_elems.length == 0){ return this; } + this.fillStyle = f; + var defs = def_elems[0]; + var fill = this.rawNode.getAttribute("fill"); + var ref = dojo.gfx.svg.getRef(fill); + if(ref){ + fill = ref; + if(fill.tagName.toLowerCase() != nodeType.toLowerCase()){ + var id = fill.id; + fill.parentNode.removeChild(fill); + fill = document.createElementNS(dojo.svg.xmlns.svg, nodeType); + fill.setAttribute("id", id); + defs.appendChild(fill); + }else{ + while(fill.childNodes.length){ + fill.removeChild(fill.lastChild); + } + } + }else{ + fill = document.createElementNS(dojo.svg.xmlns.svg, nodeType); + fill.setAttribute("id", dojo.dom.getUniqueId()); + defs.appendChild(fill); + } + if(nodeType == "pattern"){ + fill.setAttribute("patternUnits", "userSpaceOnUse"); + var img = document.createElementNS(dojo.svg.xmlns.svg, "image"); + img.setAttribute("x", 0); + img.setAttribute("y", 0); + img.setAttribute("width", f.width .toFixed(8)); + img.setAttribute("height", f.height.toFixed(8)); + img.setAttributeNS(dojo.svg.xmlns.xlink, "href", f.src); + fill.appendChild(img); + }else{ + fill.setAttribute("gradientUnits", "userSpaceOnUse"); + for(var i = 0; i < f.colors.length; ++i){ + f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); + var t = document.createElementNS(dojo.svg.xmlns.svg, "stop"); + t.setAttribute("offset", f.colors[i].offset.toFixed(8)); + t.setAttribute("stop-color", f.colors[i].color.toCss()); + fill.appendChild(t); + } + } + this.rawNode.setAttribute("fill", "url(#" + fill.getAttribute("id") +")"); + this.rawNode.removeAttribute("fill-opacity"); + return fill; + }, + + _applyTransform: function() { + var matrix = this._getRealMatrix(); + if(matrix){ + var tm = this.matrix; + this.rawNode.setAttribute("transform", "matrix(" + + tm.xx.toFixed(8) + "," + tm.yx.toFixed(8) + "," + + tm.xy.toFixed(8) + "," + tm.yy.toFixed(8) + "," + + tm.dx.toFixed(8) + "," + tm.dy.toFixed(8) + ")"); + }else{ + this.rawNode.removeAttribute("transform"); + } + return this; + }, + + setRawNode: function(rawNode){ + // summary: + // assigns and clears the underlying node that will represent this + // shape. Once set, transforms, gradients, etc, can be applied. + // no fill & stroke by default + with(rawNode){ + setAttribute("fill", "none"); + setAttribute("fill-opacity", 0); + setAttribute("stroke", "none"); + setAttribute("stroke-opacity", 0); + setAttribute("stroke-width", 1); + setAttribute("stroke-linecap", "butt"); + setAttribute("stroke-linejoin", "miter"); + setAttribute("stroke-miterlimit", 4); + } + this.rawNode = rawNode; + }, + + moveToFront: function(){ + this.rawNode.parentNode.appendChild(this.rawNode); + return this; + }, + moveToBack: function(){ + this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild); + return this; + }, + + setShape: function(newShape){ + this.shape = dojo.gfx.makeParameters(this.shape, newShape); + for(var i in this.shape){ + if(i != "type"){ this.rawNode.setAttribute(i, this.shape[i]); } + } + return this; + }, + + attachFill: function(rawNode){ + var fillStyle = null; + if(rawNode){ + var fill = rawNode.getAttribute("fill"); + if(fill == "none"){ return; } + var ref = dojo.gfx.svg.getRef(fill); + if(ref){ + var gradient = ref; + switch(gradient.tagName.toLowerCase()){ + case "lineargradient": + fillStyle = this._getGradient(dojo.gfx.defaultLinearGradient, gradient); + dojo.lang.forEach(["x1", "y1", "x2", "y2"], function(x){ + fillStyle[x] = gradient.getAttribute(x); + }); + break; + case "radialgradient": + fillStyle = this._getGradient(dojo.gfx.defaultRadialGradient, gradient); + dojo.lang.forEach(["cx", "cy", "r"], function(x){ + fillStyle[x] = gradient.getAttribute(x); + }); + fillStyle.cx = gradient.getAttribute("cx"); + fillStyle.cy = gradient.getAttribute("cy"); + fillStyle.r = gradient.getAttribute("r"); + break; + case "pattern": + fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultPattern, true); + dojo.lang.forEach(["x", "y", "width", "height"], function(x){ + fillStyle[x] = gradient.getAttribute(x); + }); + fillStyle.src = gradient.firstChild.getAttributeNS(dojo.svg.xmlns.xlink, "href"); + break; + } + }else{ + fillStyle = new dojo.gfx.color.Color(fill); + var opacity = rawNode.getAttribute("fill-opacity"); + if(opacity != null) fillStyle.a = opacity; + } + } + return fillStyle; + }, + + _getGradient: function(defaultGradient, gradient){ + var fillStyle = dojo.lang.shallowCopy(defaultGradient, true); + fillStyle.colors = []; + for(var i = 0; i < gradient.childNodes.length; ++i){ + fillStyle.colors.push({ + offset: gradient.childNodes[i].getAttribute("offset"), + color: new dojo.gfx.color.Color(gradient.childNodes[i].getAttribute("stop-color")) + }); + } + return fillStyle; + }, + + attachStroke: function(rawNode){ + if(!rawNode){ return; } + var stroke = rawNode.getAttribute("stroke"); + if(stroke == null || stroke == "none") return null; + var strokeStyle = dojo.lang.shallowCopy(dojo.gfx.defaultStroke, true); + var color = new dojo.gfx.color.Color(stroke); + if(color){ + strokeStyle.color = color; + strokeStyle.color.a = rawNode.getAttribute("stroke-opacity"); + strokeStyle.width = rawNode.getAttribute("stroke-width"); + strokeStyle.cap = rawNode.getAttribute("stroke-linecap"); + strokeStyle.join = rawNode.getAttribute("stroke-linejoin"); + if(strokeStyle.join == "miter"){ + strokeStyle.join = rawNode.getAttribute("stroke-miterlimit"); + } + } + return strokeStyle; + }, + + attachTransform: function(rawNode){ + var matrix = null; + if(rawNode){ + matrix = rawNode.getAttribute("transform"); + if(matrix.match(/^matrix\(.+\)$/)){ + var t = matrix.slice(7, -1).split(","); + matrix = dojo.gfx.matrix.normalize({ + xx: parseFloat(t[0]), xy: parseFloat(t[2]), + yx: parseFloat(t[1]), yy: parseFloat(t[3]), + dx: parseFloat(t[4]), dy: parseFloat(t[5]) + }); + } + } + return matrix; + }, + + attachShape: function(rawNode){ + var shape = null; + if(rawNode){ + shape = dojo.lang.shallowCopy(this.shape, true); + for(var i in shape) { + shape[i] = rawNode.getAttribute(i); + } + } + return shape; + }, + + attach: function(rawNode){ + if(rawNode) { + this.rawNode = rawNode; + this.fillStyle = this.attachFill(rawNode); + this.strokeStyle = this.attachStroke(rawNode); + this.matrix = this.attachTransform(rawNode); + this.shape = this.attachShape(rawNode); + } + } +}); + +dojo.declare("dojo.gfx.Group", dojo.gfx.Shape, { + setRawNode: function(rawNode){ + this.rawNode = rawNode; + } +}); +dojo.gfx.Group.nodeType = "g"; + +dojo.declare("dojo.gfx.Rect", dojo.gfx.shape.Rect, { + attachShape: function(rawNode){ + var shape = null; + if(rawNode){ + shape = dojo.gfx.Rect.superclass.attachShape.apply(this, arguments); + shape.r = Math.min(rawNode.getAttribute("rx"), rawNode.getAttribute("ry")); + } + return shape; + }, + setShape: function(newShape){ + this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + for(var i in this.shape){ + if(i != "type" && i != "r"){ this.rawNode.setAttribute(i, this.shape[i]); } + } + this.rawNode.setAttribute("rx", this.shape.r); + this.rawNode.setAttribute("ry", this.shape.r); + return this; + } +}); +dojo.gfx.Rect.nodeType = "rect"; + +dojo.gfx.Ellipse = dojo.gfx.shape.Ellipse; +dojo.gfx.Ellipse.nodeType = "ellipse"; + +dojo.gfx.Circle = dojo.gfx.shape.Circle; +dojo.gfx.Circle.nodeType = "circle"; + +dojo.gfx.Line = dojo.gfx.shape.Line; +dojo.gfx.Line.nodeType = "line"; + +dojo.declare("dojo.gfx.Polyline", dojo.gfx.shape.Polyline, { + setShape: function(points){ + if(points && points instanceof Array){ + this.shape = dojo.gfx.makeParameters(this.shape, { points: points }); + if(closed && this.shape.points.length){ + this.shape.points.push(this.shape.points[0]); + } + }else{ + this.shape = dojo.gfx.makeParameters(this.shape, points); + } + this.box = null; + var attr = []; + var p = this.shape.points; + for(var i = 0; i < p.length; ++i){ + attr.push(p[i].x.toFixed(8)); + attr.push(p[i].y.toFixed(8)); + } + this.rawNode.setAttribute("points", attr.join(" ")); + return this; + } +}); +dojo.gfx.Polyline.nodeType = "polyline"; + +dojo.declare("dojo.gfx.Image", dojo.gfx.shape.Image, { + setShape: function(newShape){ + this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + var rawNode = this.rawNode; + for(var i in this.shape){ + if(i != "type" && i != "src"){ rawNode.setAttribute(i, this.shape[i]); } + } + rawNode.setAttributeNS(dojo.svg.xmlns.xlink, "href", this.shape.src); + return this; + }, + setStroke: function() { return this; }, + setFill: function() { return this; }, + attachStroke: function(rawNode){ return null; }, + attachFill: function(rawNode){ return null; } +}); +dojo.gfx.Image.nodeType = "image"; + +dojo.declare("dojo.gfx.Path", dojo.gfx.path.Path, +{ + _updateWithSegment: function(segment){ + dojo.gfx.Path.superclass._updateWithSegment.apply(this, arguments); + if(typeof(this.shape.path) == "string"){ + this.rawNode.setAttribute("d", this.shape.path); + } + }, + setShape: function(newShape){ + dojo.gfx.Path.superclass.setShape.apply(this, arguments); + this.rawNode.setAttribute("d", this.shape.path); + return this; + } +}); +dojo.gfx.Path.nodeType = "path"; + +dojo.gfx._creators = { + // creators + createPath: function(path){ + return this.createObject(dojo.gfx.Path, path); + }, + createRect: function(rect){ + return this.createObject(dojo.gfx.Rect, rect); + }, + createCircle: function(circle){ + return this.createObject(dojo.gfx.Circle, circle); + }, + createEllipse: function(ellipse){ + return this.createObject(dojo.gfx.Ellipse, ellipse); + }, + createLine: function(line){ + return this.createObject(dojo.gfx.Line, line); + }, + createPolyline: function(points){ + return this.createObject(dojo.gfx.Polyline, points); + }, + createImage: function(image){ + return this.createObject(dojo.gfx.Image, image); + }, + createGroup: function(){ + return this.createObject(dojo.gfx.Group); + }, + createObject: function(/*Function*/shapeType, /*Object*/rawShape){ + // summary: creates an instance of the passed shapeType class + // shapeType: a class constructor to create an instance of + // rawShape: properties to be passed in to the classes "setShape" method + + if(!this.rawNode){ return null; } + var shape = new shapeType(); + var node = document.createElementNS(dojo.svg.xmlns.svg, shapeType.nodeType); + shape.setRawNode(node); + this.rawNode.appendChild(node); + shape.setShape(rawShape); + this.add(shape); + return shape; + }, + // group control + add: function(shape){ + var oldParent = shape.getParent(); + if(oldParent){ + oldParent.remove(shape, true); + } + shape._setParent(this, null); + this.rawNode.appendChild(shape.rawNode); + return this; + }, + remove: function(shape, silently){ + if(this.rawNode == shape.rawNode.parentNode){ + this.rawNode.removeChild(shape.rawNode); + } + shape._setParent(null, null); + return this; + } +}; + +dojo.gfx.attachNode = function(node){ + if(!node) return null; + var s = null; + switch(node.tagName.toLowerCase()){ + case dojo.gfx.Rect.nodeType: + s = new dojo.gfx.Rect(); + break; + case dojo.gfx.Ellipse.nodeType: + s = new dojo.gfx.Ellipse(); + break; + case dojo.gfx.Polyline.nodeType: + s = new dojo.gfx.Polyline(); + break; + case dojo.gfx.Path.nodeType: + s = new dojo.gfx.Path(); + break; + case dojo.gfx.Circle.nodeType: + s = new dojo.gfx.Circle(); + break; + case dojo.gfx.Line.nodeType: + s = new dojo.gfx.Line(); + break; + case dojo.gfx.Image.nodeType: + s = new dojo.gfx.Image(); + break; + default: + dojo.debug("FATAL ERROR! tagName = " + node.tagName); + } + s.attach(node); + return s; +}; + +dojo.lang.extend(dojo.gfx.Surface, { + setDimensions: function(/*String*/width, /*String*/height){ + // summary: sets the width and height of the rawNode + if(!this.rawNode){ return this; } + this.rawNode.setAttribute("width", width); + this.rawNode.setAttribute("height", height); + return this; // dojo.gfx.Surface + }, + getDimensions: function(){ + // summary: returns an object with properties "width" and "height" + return this.rawNode ? {width: this.rawNode.getAttribute("width"), height: this.rawNode.getAttribute("height")} : null; // Object + } +}); + +dojo.gfx.createSurface = function(parentNode, width, height){ + var s = new dojo.gfx.Surface(); + s.rawNode = document.createElementNS(dojo.svg.xmlns.svg, "svg"); + s.rawNode.setAttribute("width", width); + s.rawNode.setAttribute("height", height); + + var defs = new dojo.gfx.svg.Defines(); + var node = document.createElementNS(dojo.svg.xmlns.svg, dojo.gfx.svg.Defines.nodeType); + defs.setRawNode(node); + s.rawNode.appendChild(node); + + dojo.byId(parentNode).appendChild(s.rawNode); + return s; +}; + +dojo.gfx.attachSurface = function(node){ + var s = new dojo.gfx.Surface(); + s.rawNode = node; + return s; +}; + +dojo.lang.extend(dojo.gfx.Group, dojo.gfx._creators); +dojo.lang.extend(dojo.gfx.Surface, dojo.gfx._creators); + +delete dojo.gfx._creators; + +// Gradient and pattern +dojo.gfx.svg.Defines = function(){ + this.rawNode = null; +}; +dojo.lang.extend(dojo.gfx.svg.Defines, { + setRawNode: function(rawNode){ + this.rawNode = rawNode; + } +}); +dojo.gfx.svg.Defines.nodeType = "defs"; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/vml.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/Attic/vml.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/gfx/vml.js 6 Nov 2006 14:50:07 -0000 1.1 @@ -0,0 +1,1157 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.gfx.vml"); + +dojo.require("dojo.dom"); +dojo.require("dojo.math"); +dojo.require("dojo.lang.declare"); +dojo.require("dojo.lang.extras"); +dojo.require("dojo.string.*"); +dojo.require("dojo.html.metrics"); + +dojo.require("dojo.gfx.color"); +dojo.require("dojo.gfx.common"); +dojo.require("dojo.gfx.shape"); +dojo.require("dojo.gfx.path"); + +dojo.require("dojo.experimental"); +dojo.experimental("dojo.gfx.vml"); + +dojo.gfx.vml.xmlns = "urn:schemas-microsoft-com:vml"; + +dojo.gfx.vml._parseFloat = function(str) { + return str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str); +}; + +dojo.gfx.vml.cm_in_pt = 72 / 2.54; +dojo.gfx.vml.mm_in_pt = 7.2 / 2.54; + +dojo.gfx.vml.px_in_pt = function(){ return dojo.html.getCachedFontMeasurements()["12pt"] / 12; }; + +dojo.gfx.vml.pt2px = function(len){ return len * this.px_in_pt(); }; +dojo.gfx.vml.px2pt = function(len){ return len / this.px_in_pt(); }; + +dojo.gfx.vml.normalizedLength = function(len) { + if(len.length == 0) return 0; + if(len.length > 2){ + var px_in_pt = this.px_in_pt(); + var val = parseFloat(len); + switch(len.slice(-2)){ + case "px": return val; + case "pt": return val * px_in_pt; + case "in": return val * 72 * px_in_pt; + case "pc": return val * 12 * px_in_pt; + case "mm": return val / this.mm_in_pt * px_in_pt; + case "cm": return val / this.cm_in_pt * px_in_pt; + } + } + return parseFloat(len); +}; + +dojo.lang.extend(dojo.gfx.Shape, { + setStroke: function(stroke){ + if(!stroke){ + // don't stroke + this.strokeStyle = null; + this.rawNode.stroked = false; + return this; + } + // normalize the stroke + this.strokeStyle = dojo.gfx.makeParameters(dojo.gfx.defaultStroke, stroke); + this.strokeStyle.color = dojo.gfx.normalizeColor(this.strokeStyle.color); + // generate attributes + var s = this.strokeStyle; + this.rawNode.stroked = true; + this.rawNode.strokecolor = s.color.toCss(); + this.rawNode.strokeweight = s.width + "px"; // TODO: should we assume that the width is always in pixels? + if(this.rawNode.stroke) { + this.rawNode.stroke.opacity = s.color.a; + this.rawNode.stroke.endcap = this._translate(this._capMap, s.cap); + if(typeof(s.join) == "number") { + this.rawNode.stroke.joinstyle = "miter"; + this.rawNode.stroke.miterlimit = s.join; + }else{ + this.rawNode.stroke.joinstyle = s.join; + // this.rawNode.stroke.miterlimit = s.width; + } + } + return this; + }, + + _capMap: { butt: 'flat' }, + _capMapReversed: { flat: 'butt' }, + + _translate: function(dict, value) { + return (value in dict) ? dict[value] : value; + }, + + setFill: function(fill){ + if(!fill){ + // don't fill + this.fillStyle = null; + this.rawNode.filled = false; + return this; + } + if(typeof(fill) == "object" && "type" in fill){ + // gradient + switch(fill.type){ + case "linear": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultLinearGradient, fill); + this.fillStyle = f; + var s = ""; + for(var i = 0; i < f.colors.length; ++i){ + f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); + s += f.colors[i].offset.toFixed(8) + " " + f.colors[i].color.toHex() + ";"; + } + var fo = this.rawNode.fill; + fo.colors.value = s; + fo.method = "sigma"; + fo.type = "gradient"; + fo.angle = (dojo.math.radToDeg(Math.atan2(f.x2 - f.x1, f.y2 - f.y1)) + 180) % 360; + fo.on = true; + break; + case "radial": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultRadialGradient, fill); + this.fillStyle = f; + var w = parseFloat(this.rawNode.style.width); + var h = parseFloat(this.rawNode.style.height); + var c = isNaN(w) ? 1 : 2 * f.r / w; + var i = f.colors.length - 1; + f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); + var s = "0 " + f.colors[i].color.toHex(); + for(; i >= 0; --i){ + f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); + s += (1 - c * f.colors[i].offset).toFixed(8) + " " + f.colors[i].color.toHex() + ";"; + } + var fo = this.rawNode.fill; + fo.colors.value = s; + fo.method = "sigma"; + fo.type = "gradientradial"; + if(isNaN(w) || isNaN(h)){ + fo.focusposition = "0.5 0.5"; + }else{ + fo.focusposition = (f.cx / w).toFixed(8) + " " + (f.cy / h).toFixed(8); + } + fo.focussize = "0 0"; + fo.on = true; + break; + case "pattern": + var f = dojo.gfx.makeParameters(dojo.gfx.defaultPattern, fill); + this.fillStyle = f; + var fo = this.rawNode.fill; + fo.type = "tile"; + fo.src = f.src; + if(f.width && f.height){ + // in points + fo.size.x = dojo.gfx.vml.px2pt(f.width); + fo.size.y = dojo.gfx.vml.px2pt(f.height); + } + fo.alignShape = false; + fo.position.x = 0; + fo.position.y = 0; + fo.origin.x = f.width ? f.x / f.width : 0; + fo.origin.y = f.height ? f.y / f.height : 0; + fo.on = true; + break; + } + this.rawNode.fill.opacity = 1; + return this; + } + // color object + this.fillStyle = dojo.gfx.normalizeColor(fill); + this.rawNode.fillcolor = this.fillStyle.toHex(); + this.rawNode.fill.opacity = this.fillStyle.a; + this.rawNode.filled = true; + return this; + }, + + _applyTransform: function() { + var matrix = this._getRealMatrix(); + if(!matrix) return this; + var skew = this.rawNode.skew; + if(typeof(skew) == "undefined"){ + for(var i = 0; i < this.rawNode.childNodes.length; ++i){ + if(this.rawNode.childNodes[i].tagName == "skew"){ + skew = this.rawNode.childNodes[i]; + break; + } + } + } + if(skew){ + skew.on = false; + var mt = matrix.xx.toFixed(8) + " " + matrix.xy.toFixed(8) + " " + + matrix.yx.toFixed(8) + " " + matrix.yy.toFixed(8) + " 0 0"; + var offset = Math.floor(matrix.dx).toFixed() + "px " + Math.floor(matrix.dy).toFixed() + "px"; + var l = parseFloat(this.rawNode.style.left); + var t = parseFloat(this.rawNode.style.top); + var w = parseFloat(this.rawNode.style.width); + var h = parseFloat(this.rawNode.style.height); + if(isNaN(l)) l = 0; + if(isNaN(t)) t = 0; + if(isNaN(w)) w = 1; + if(isNaN(h)) h = 1; + var origin = (-l / w - 0.5).toFixed(8) + " " + (-t / h - 0.5).toFixed(8); + skew.matrix = mt; + skew.origin = origin; + skew.offset = offset; + skew.on = true; + } + return this; + }, + + setRawNode: function(rawNode){ + rawNode.stroked = false; + rawNode.filled = false; + this.rawNode = rawNode; + }, + + // Attach family + attachStroke: function(rawNode) { + var strokeStyle = dojo.lang.shallowCopy(dojo.gfx.defaultStroke, true); + if(rawNode && rawNode.stroked){ + strokeStyle.color = new dojo.gfx.color.Color(rawNode.strokecolor.value); + dojo.debug("We are expecting an .75pt here, instead of strokeweight = " + rawNode.strokeweight ); + strokeStyle.width = dojo.gfx.vml.normalizedLength(rawNode.strokeweight+""); + strokeStyle.color.a = rawNode.stroke.opacity; + strokeStyle.cap = this._translate(this._capMapReversed, rawNode.stroke.endcap); + strokeStyle.join = rawNode.stroke.joinstyle == "miter" ? rawNode.stroke.miterlimit : rawNode.stroke.joinstyle; + }else{ + return null; + } + return strokeStyle; + }, + + attachFill: function(rawNode){ + var fillStyle = null; + var fo = rawNode.fill; + if(rawNode) { + if(fo.on && fo.type == "gradient"){ + var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultLinearGradient, true); + var rad = dojo.math.degToRad(fo.angle); + fillStyle.x2 = Math.cos(rad); + fillStyle.y2 = Math.sin(rad); + fillStyle.colors = []; + var stops = fo.colors.value.split(";"); + for(var i = 0; i < stops.length; ++i){ + var t = stops[i].match(/\S+/g); + if(!t || t.length != 2) continue; + fillStyle.colors.push({offset: dojo.gfx.vml._parseFloat(t[0]), color: new dojo.gfx.color.Color(t[1])}); + } + }else if(fo.on && fo.type == "gradientradial"){ + var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultRadialGradient, true); + var w = parseFloat(rawNode.style.width); + var h = parseFloat(rawNode.style.height); + fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w; + fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h; + fillStyle.r = isNaN(w) ? 1 : w / 2; + fillStyle.colors = []; + var stops = fo.colors.value.split(";"); + for(var i = stops.length - 1; i >= 0; --i){ + var t = stops[i].match(/\S+/g); + if(!t || t.length != 2) continue; + fillStyle.colors.push({offset: dojo.gfx.vml._parseFloat(t[0]), color: new dojo.gfx.color.Color(t[1])}); + } + }else if(fo.on && fo.type == "tile"){ + var fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultPattern, true); + fillStyle.width = dojo.gfx.vml.pt2px(fo.size.x); // from pt + fillStyle.height = dojo.gfx.vml.pt2px(fo.size.y); // from pt + fillStyle.x = fo.origin.x * fillStyle.width; + fillStyle.y = fo.origin.y * fillStyle.height; + fillStyle.src = fo.src; + }else if(fo.on && rawNode.fillcolor){ + // a color object ! + fillStyle = new dojo.gfx.color.Color(rawNode.fillcolor+""); + fillStyle.a = fo.opacity; + } + } + return fillStyle; + }, + + attachTransform: function(rawNode) { + var matrix = {}; + if(rawNode){ + var s = rawNode.skew; + matrix.xx = s.matrix.xtox; + matrix.xy = s.matrix.ytox; + matrix.yx = s.matrix.xtoy; + matrix.yy = s.matrix.ytoy; + matrix.dx = dojo.gfx.vml.pt2px(s.offset.x); + matrix.dy = dojo.gfx.vml.pt2px(s.offset.y); + } + return dojo.gfx.matrix.normalize(matrix); + }, + + attach: function(rawNode){ + if(rawNode){ + this.rawNode = rawNode; + this.shape = this.attachShape(rawNode); + this.fillStyle = this.attachFill(rawNode); + this.strokeStyle = this.attachStroke(rawNode); + this.matrix = this.attachTransform(rawNode); + } + } +}); + +dojo.declare("dojo.gfx.Group", dojo.gfx.shape.VirtualGroup, { + add: function(shape){ + if(this != shape.getParent()){ + this.rawNode.appendChild(shape.rawNode); + dojo.gfx.Group.superclass.add.apply(this, arguments); + } + return this; + }, + remove: function(shape, silently){ + if(this == shape.getParent()){ + if(this.rawNode == shape.rawNode.parentNode){ + this.rawNode.removeChild(shape.rawNode); + } + dojo.gfx.Group.superclass.remove.apply(this, arguments); + } + return this; + }, + attach: function(rawNode){ + if(rawNode){ + this.rawNode = rawNode; + this.shape = null; + this.fillStyle = null; + this.strokeStyle = null; + this.matrix = null; + } + } +}); +dojo.gfx.Group.nodeType = "group"; + +var zIndex = { + moveToFront: function(){ + this.rawNode.parentNode.appendChild(this.rawNode); + return this; + }, + moveToBack: function(){ + this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild); + return this; + } +}; +dojo.lang.extend(dojo.gfx.Shape, zIndex); +dojo.lang.extend(dojo.gfx.Group, zIndex); +delete zIndex; + +dojo.declare("dojo.gfx.Rect", dojo.gfx.shape.Rect, { + setShape: function(newShape){ + var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + var style = this.rawNode.style; + style.left = shape.x.toFixed(); + style.top = shape.y.toFixed(); + style.width = (typeof(shape.width) == "string" && shape.width.indexOf("%") >= 0) ? shape.width : shape.width.toFixed(); + style.height = (typeof(shape.width) == "string" && shape.height.indexOf("%") >= 0) ? shape.height : shape.height.toFixed(); + var r = Math.min(1, (shape.r / Math.min(parseFloat(shape.width), parseFloat(shape.height)))).toFixed(8); + // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node + var parent = this.rawNode.parentNode; + var before = null; + if(parent){ + if(parent.lastChild != this.rawNode){ + for(var i = 0; i < parent.childNodes.length; ++i){ + if(parent.childNodes[i] == this.rawNode){ + before = parent.childNodes[i+1]; + break; + } + } + } + parent.removeChild(this.rawNode); + } + this.rawNode.arcsize = r; + if(parent){ + if(before){ + parent.insertBefore(this.rawNode, before); + }else{ + parent.appendChild(this.rawNode); + } + } + return this.setTransform(this.matrix); + }, + attachShape: function(rawNode){ + // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node + var arcsize = rawNode.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1]; + arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : dojo.gfx.vml._parseFloat(arcsize); + var style = rawNode.style; + var width = parseFloat(style.width); + var height = parseFloat(style.height); + // make an object + return dojo.gfx.makeParameters(dojo.gfx.defaultRect, { + x: parseInt(style.left), + y: parseInt(style.top), + width: width, + height: height, + r: Math.min(width, height) * arcsize + }); + } +}); +dojo.gfx.Rect.nodeType = "roundrect"; // use a roundrect so the stroke join type is respected + +dojo.declare("dojo.gfx.Ellipse", dojo.gfx.shape.Ellipse, { + setShape: function(newShape){ + var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + var style = this.rawNode.style; + style.left = (shape.cx - shape.rx).toFixed(); + style.top = (shape.cy - shape.ry).toFixed(); + style.width = (shape.rx * 2).toFixed(); + style.height = (shape.ry * 2).toFixed(); + return this.setTransform(this.matrix); + }, + attachShape: function(rawNode){ + var style = this.rawNode.style; + var rx = parseInt(style.width ) / 2; + var ry = parseInt(style.height) / 2; + return dojo.gfx.makeParameters(dojo.gfx.defaultEllipse, { + cx: parseInt(style.left) + rx, + cy: parseInt(style.top ) + ry, + rx: rx, + ry: ry + }); + } +}); +dojo.gfx.Ellipse.nodeType = "oval"; + +dojo.declare("dojo.gfx.Circle", dojo.gfx.shape.Circle, { + setShape: function(newShape){ + var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + var style = this.rawNode.style; + style.left = (shape.cx - shape.r).toFixed(); + style.top = (shape.cy - shape.r).toFixed(); + style.width = (shape.r * 2).toFixed(); + style.height = (shape.r * 2).toFixed(); + return this; + }, + attachShape: function(rawNode){ + var style = this.rawNode.style; + var r = parseInt(style.width) / 2; + return dojo.gfx.makeParameters(dojo.gfx.defaultCircle, { + cx: parseInt(style.left) + r, + cy: parseInt(style.top) + r, + r: r + }); + } +}); +dojo.gfx.Circle.nodeType = "oval"; + +dojo.declare("dojo.gfx.Line", dojo.gfx.shape.Line, + function(rawNode){ + if(rawNode) rawNode.setAttribute("dojoGfxType", "line"); + }, { + setShape: function(newShape){ + var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + this.rawNode.path.v = "m" + shape.x1.toFixed() + " " + shape.y1.toFixed() + + "l" + shape.x2.toFixed() + " " + shape.y2.toFixed() + "e"; + return this.setTransform(this.matrix); + }, + attachShape: function(rawNode){ + var p = rawNode.path.v.match(dojo.gfx.pathRegExp); + var shape = {}; + do{ + if(p.length < 7 || p[0] != "m" || p[3] != "l" || p[6] != "e") break; + shape.x1 = parseInt(p[1]); + shape.y1 = parseInt(p[2]); + shape.x2 = parseInt(p[4]); + shape.y2 = parseInt(p[5]); + }while(false); + return dojo.gfx.makeParameters(dojo.gfx.defaultLine, shape); + } +}); +dojo.gfx.Line.nodeType = "shape"; + +dojo.declare("dojo.gfx.Polyline", dojo.gfx.shape.Polyline, + function(rawNode){ + if(rawNode) rawNode.setAttribute("dojoGfxType", "polyline"); + }, { + setShape: function(points, closed){ + if(points && points instanceof Array){ + this.shape = dojo.gfx.makeParameters(this.shape, { points: points }); + if(closed && this.shape.points.length) this.shape.points.push(this.shape.points[0]); + }else{ + this.shape = dojo.gfx.makeParameters(this.shape, points); + } + this.bbox = null; + var attr = []; + var p = this.shape.points; + if(p.length > 0){ + attr.push("m"); + attr.push(p[0].x.toFixed()); + attr.push(p[0].y.toFixed()); + if(p.length > 1){ + attr.push("l"); + for(var i = 1; i < p.length; ++i){ + attr.push(p[i].x.toFixed()); + attr.push(p[i].y.toFixed()); + } + } + } + attr.push("e"); + this.rawNode.path.v = attr.join(" "); + return this.setTransform(this.matrix); + }, + attachShape: function(rawNode){ + var shape = dojo.lang.shallowCopy(dojo.gfx.defaultPolyline, true); + var p = rawNode.path.v.match(dojo.gfx.pathRegExp); + do{ + if(p.length < 3 || p[0] != "m") break; + var x = parseInt(p[0]); + var y = parseInt(p[1]); + if(isNaN(x) || isNaN(y)) break; + shape.points.push({x: x, y: y}); + if(p.length < 6 || p[3] != "l") break; + for(var i = 4; i < p.length; i += 2){ + x = parseInt(p[i]); + y = parseInt(p[i + 1]); + if(isNaN(x) || isNaN(y)) break; + shape.points.push({x: x, y: y}); + } + }while(false); + return shape; + } +}); +dojo.gfx.Polyline.nodeType = "shape"; + +dojo.declare("dojo.gfx.Image", dojo.gfx.shape.Image, { + getEventSource: function() { + return this.rawNode ? this.rawNode.firstChild : null; + }, + setShape: function(newShape){ + var shape = this.shape = dojo.gfx.makeParameters(this.shape, newShape); + this.bbox = null; + var firstChild = this.rawNode.firstChild; + firstChild.src = shape.src; + if(shape.width || shape.height){ + firstChild.style.width = shape.width; + firstChild.style.height = shape.height; + } + return this.setTransform(this.matrix); + }, + setStroke: function() { return this; }, + setFill: function() { return this; }, + attachShape: function(rawNode){ + var shape = dojo.lang.shallowCopy(dojo.gfx.defaultImage, true); + shape.src = rawNode.firstChild.src; + return shape; + }, + attachStroke: function(rawNode){ return null; }, + attachFill: function(rawNode){ return null; }, + attachTransform: function(rawNode) { + var matrix = {}; + if(rawNode){ + var m = rawNode.filters["DXImageTransform.Microsoft.Matrix"]; + matrix.xx = m.M11; + matrix.xy = m.M12; + matrix.yx = m.M21; + matrix.yy = m.M22; + matrix.dx = m.Dx; + matrix.dy = m.Dy; + } + return dojo.gfx.matrix.normalize(matrix); + }, + _applyTransform: function() { + var matrix = this._getRealMatrix(); + if(!matrix) return this; + with(this.rawNode.filters["DXImageTransform.Microsoft.Matrix"]){ + M11 = matrix.xx; + M12 = matrix.xy; + M21 = matrix.yx; + M22 = matrix.yy; + Dx = matrix.dx; + Dy = matrix.dy; + } + return this; + } +}); +dojo.gfx.Image.nodeType = "image"; + +dojo.gfx.path._calcArc = function(alpha){ + var cosa = Math.cos(alpha); + var sina = Math.sin(alpha); + // return a start point, 1st and 2nd control points, and an end point + var p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina}; + return { + s: {x: cosa, y: sina}, + c1: p2, + c2: {x: p2.x, y: -p2.y}, + e: {x: cosa, y: -sina} + }; +}; + +dojo.declare("dojo.gfx.Path", dojo.gfx.path.Path, + function(rawNode){ + if(rawNode) rawNode.setAttribute("dojoGfxType", "path"); + this.vmlPath = ""; + this.lastControl = {}; + }, { + _updateWithSegment: function(segment){ + var last = dojo.lang.shallowCopy(this.last); + dojo.gfx.Path.superclass._updateWithSegment.apply(this, arguments); + // add a VML path segment + var path = this[this.renderers[segment.action]](segment, last); + if(typeof(this.vmlPath) == "string"){ + this.vmlPath += path.join(""); + }else{ + this.vmlPath = this.vmlPath.concat(path); + } + if(typeof(this.vmlPath) == "string"){ + this.rawNode.path.v = this.vmlPath + " e"; + } + }, + setShape: function(newShape){ + this.vmlPath = []; + this.lastControl = {}; + dojo.gfx.Path.superclass.setShape.apply(this, arguments); + this.vmlPath = this.vmlPath.join(""); + this.rawNode.path.v = this.vmlPath + " e"; + return this; + }, + _pathVmlToSvgMap: {m: "M", l: "L", t: "m", r: "l", c: "C", v: "c", qb: "Q", x: "z", e: ""}, + attachShape: function(rawNode){ + var shape = dojo.lang.shallowCopy(dojo.gfx.defaultPath, true); + var p = rawNode.path.v.match(dojo.gfx.pathRegExp); + var t = [], skip = false; + for(var i = 0; i < p.length; ++p){ + var s = p[i]; + if(s in this._pathVmlToSvgMap) { + skip = false; + t.push(this._pathVmlToSvgMap[s]); + } else if(!skip){ + var n = parseInt(s); + if(isNaN(n)){ + skip = true; + }else{ + t.push(n); + } + } + } + if(t.length) shape.path = t.join(" "); + return shape; + }, + // VML-specific segment renderers + renderers: { + M: "_moveToA", m: "_moveToR", + L: "_lineToA", l: "_lineToR", + H: "_hLineToA", h: "_hLineToR", + V: "_vLineToA", v: "_vLineToR", + C: "_curveToA", c: "_curveToR", + S: "_smoothCurveToA", s: "_smoothCurveToR", + Q: "_qCurveToA", q: "_qCurveToR", + T: "_qSmoothCurveToA", t: "_qSmoothCurveToR", + A: "_arcTo", a: "_arcTo", + Z: "_closePath", z: "_closePath" + }, + _addArgs: function(path, args, from, upto){ + if(typeof(upto) == "undefined"){ + upto = args.length; + } + if(typeof(from) == "undefined"){ + from = 0; + } + for(var i = from; i < upto; ++i){ + path.push(" "); + path.push(args[i].toFixed()); + } + }, + _addArgsAdjusted: function(path, last, args, from, upto){ + if(typeof(upto) == "undefined"){ + upto = args.length; + } + if(typeof(from) == "undefined"){ + from = 0; + } + for(var i = from; i < upto; i += 2){ + path.push(" "); + path.push((last.x + args[i]).toFixed()); + path.push(" "); + path.push((last.y + args[i + 1]).toFixed()); + } + }, + _moveToA: function(segment){ + var p = [" m"]; + var n = segment.args; + var l = n.length; + if(l == 2){ + this._addArgs(p, n); + }else{ + this._addArgs(p, n, 0, 2); + p.push(" l"); + this._addArgs(p, n, 2); + } + this.lastControl = {}; + return p; + }, + _moveToR: function(segment, last){ + var p = ["x" in last ? " t" : " m"]; + var n = segment.args; + var l = n.length; + if(l == 2){ + this._addArgs(p, n); + }else{ + this._addArgs(p, n, 0, 2); + p.push(" r"); + this._addArgs(p, n, 2); + } + this.lastControl = {}; + return p; + }, + _lineToA: function(segment){ + var p = [" l"]; + this._addArgs(p, segment.args); + this.lastControl = {}; + return p; + }, + _lineToR: function(segment){ + var p = [" r"]; + this._addArgs(p, segment.args); + this.lastControl = {}; + return p; + }, + _hLineToA: function(segment, last){ + var p = [" l"]; + var n = segment.args; + var l = n.length; + var y = " " + last.y.toFixed(); + for(var i = 0; i < l; ++i){ + p.push(" "); + p.push(n[i].toFixed()); + p.push(y); + } + this.lastControl = {}; + return p; + }, + _hLineToR: function(segment){ + var p = [" r"]; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; ++i){ + p.push(" "); + p.push(n[i].toFixed()); + p.push(" 0"); + } + this.lastControl = {}; + return p; + }, + _vLineToA: function(segment, last){ + var p = [" l"]; + var n = segment.args; + var l = n.length; + var x = " " + last.x.toFixed(); + for(var i = 0; i < l; ++i){ + p.push(x); + p.push(" "); + p.push(n[i].toFixed()); + } + this.lastControl = {}; + return p; + }, + _vLineToR: function(segment){ + var p = [" r"]; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; ++i){ + p.push(" 0 "); + p.push(n[i].toFixed()); + } + this.lastControl = {}; + return p; + }, + _curveToA: function(segment){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 6){ + p.push(" c"); + this._addArgs(p, n, i, i + 6); + } + this.lastControl = {x: n[l - 4], y: n[l - 3], type: "C"}; + return p; + }, + _curveToR: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 6){ + p.push(" v"); + this._addArgs(p, n, i, i + 6); + this.lastControl = {x: last.x + n[i + 2], y: last.y + n[i + 3]}; + last.x += n[i + 4]; + last.y += n[i + 5]; + } + this.lastControl.type = "C"; + return p; + }, + _smoothCurveToA: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 4){ + p.push(" c"); + if(this.lastControl.type == "C"){ + this._addArgs(p, [ + 2 * last.x - this.lastControl.x, + 2 * last.y - this.lastControl.y + ]); + }else{ + this._addArgs(p, [last.x, last.y]); + } + this._addArgs(p, n, i, i + 4); + } + this.lastControl = {x: n[l - 4], y: n[l - 3], type: "C"}; + return p; + }, + _smoothCurveToR: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 4){ + p.push(" v"); + if(this.lastControl.type == "C"){ + this._addArgs(p, [ + last.x - this.lastControl.x, + last.y - this.lastControl.y + ]); + }else{ + this._addArgs(p, [0, 0]); + } + this._addArgs(p, n, i, i + 4); + this.lastControl = {x: last.x + n[i], y: last.y + n[i + 1]}; + last.x += n[i + 2]; + last.y += n[i + 3]; + } + this.lastControl.type = "C"; + return p; + }, + _qCurveToA: function(segment){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 4){ + p.push(" qb"); + this._addArgs(p, n, i, i + 4); + } + this.lastControl = {x: n[l - 4], y: n[l - 3], type: "Q"}; + return p; + }, + _qCurveToR: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 4){ + p.push(" qb"); + this._addArgsAdjusted(p, last, n, i, i + 4); + this.lastControl = {x: last.x + n[i], y: last.y + n[i + 1]}; + last.x += n[i + 2]; + last.y += n[i + 3]; + } + this.lastControl.type = "Q"; + return p; + }, + _qSmoothCurveToA: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 2){ + p.push(" qb"); + if(this.lastControl.type == "Q"){ + this._addArgs(p, [ + this.lastControl.x = 2 * last.x - this.lastControl.x, + this.lastControl.y = 2 * last.y - this.lastControl.y + ]); + }else{ + this._addArgs(p, [ + this.lastControl.x = last.x, + this.lastControl.y = last.y + ]); + } + this._addArgs(p, n, i, i + 2); + } + this.lastControl.type = "Q"; + return p; + }, + _qSmoothCurveToR: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + for(var i = 0; i < l; i += 2){ + p.push(" qb"); + if(this.lastControl.type == "Q"){ + this._addArgs(p, [ + this.lastControl.x = 2 * last.x - this.lastControl.x, + this.lastControl.y = 2 * last.y - this.lastControl.y + ]); + }else{ + this._addArgs(p, [ + this.lastControl.x = last.x, + this.lastControl.y = last.y + ]); + } + this._addArgsAdjusted(p, last, n, i, i + 2); + } + this.lastControl.type = "Q"; + return p; + }, + _PI4: Math.PI / 4, + _curvePI4: dojo.gfx.path._calcArc(Math.PI / 8), + _calcArcTo: function(path, last, rx, ry, xRotg, large, cw, x, y){ + var m = dojo.gfx.matrix; + // calculate parameters + var xRot = -dojo.math.degToRad(xRotg); + var rx2 = rx * rx; + var ry2 = ry * ry; + var pa = m.multiplyPoint( + m.rotate(-xRot), + {x: (last.x - x) / 2, y: (last.y - y) / 2} + ); + var pax2 = pa.x * pa.x; + var pay2 = pa.y * pa.y; + var c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2)); + var ca = { + x: c1 * rx * pa.y / ry, + y: -c1 * ry * pa.x / rx + }; + if(large == cw){ + ca = {x: -ca.x, y: -ca.y}; + } + // our center + var c = m.multiplyPoint( + [ + m.translate( + (last.x + x) / 2, + (last.y + y) / 2 + ), + m.rotate(xRot) + ], + ca + ); + // start of our arc + var startAngle = Math.atan2(c.y - last.y, last.x - c.x) - xRot; + var endAngle = Math.atan2(c.y - y, x - c.x) - xRot; + // size of our arc in radians + var theta = cw ? startAngle - endAngle : endAngle - startAngle; + if(theta < 0){ + theta += this._2PI; + }else if(theta > this._2PI){ + theta = this._2PI; + } + // calculate our elliptic transformation + var elliptic_transform = m.normalize([ + m.translate(c.x, c.y), + m.rotate(xRot), + m.scale(rx, ry) + ]); + // draw curve chunks + var alpha = this._PI4 / 2; + var curve = this._curvePI4; + var step = cw ? -alpha : alpha; + for(var angle = theta; angle > 0; angle -= this._PI4){ + if(angle < this._PI4){ + alpha = angle / 2; + curve = dojo.gfx.path._calcArc(alpha); + step = cw ? -alpha : alpha; + } + var c1, c2, e; + var M = m.normalize([elliptic_transform, m.rotate(startAngle + step)]); + if(cw){ + c1 = m.multiplyPoint(M, curve.c2); + c2 = m.multiplyPoint(M, curve.c1); + e = m.multiplyPoint(M, curve.s ); + }else{ + c1 = m.multiplyPoint(M, curve.c1); + c2 = m.multiplyPoint(M, curve.c2); + e = m.multiplyPoint(M, curve.e ); + } + // draw the curve + path.push(" c"); + this._addArgs(path, [c1.x, c1.y, c2.x, c2.y, e.x, e.y]); + startAngle += 2 * step; + } + }, + _arcTo: function(segment, last){ + var p = []; + var n = segment.args; + var l = n.length; + var relative = segment.action == "a"; + for(var i = 0; i < l; i += 7){ + var x1 = n[i + 5]; + var y1 = n[i + 6]; + if(relative){ + x1 += last.x; + y1 += last.y; + } + this._calcArcTo( + p, last, n[i], n[i + 1], n[i + 2], + n[i + 3] ? 1 : 0, n[i + 4] ? 1 : 0, + x1, y1 + ); + last = {x: x1, y: y1}; + } + this.lastControl = {}; + return p; + }, + _closePath: function(){ + this.lastControl = {}; + return ["x"]; + } +}); +dojo.gfx.Path.nodeType = "shape"; + + +dojo.gfx._creators = { + createRect: function(rect){ + return this.createObject(dojo.gfx.Rect, rect); + }, + createEllipse: function(ellipse){ + return this.createObject(dojo.gfx.Ellipse, ellipse); + }, + createCircle: function(circle){ + return this.createObject(dojo.gfx.Circle, circle); + }, + createLine: function(line){ + return this.createObject(dojo.gfx.Line, line, true); + }, + createPolyline: function(points){ + return this.createObject(dojo.gfx.Polyline, points, true); + }, + createPath: function(path){ + return this.createObject(dojo.gfx.Path, path, true); + }, + createGroup: function(path){ + return this.createObject(dojo.gfx.Group, null, true); + }, + createImage: function(image){ + if(!this.rawNode) return null; + var shape = new dojo.gfx.Image(); + var node = document.createElement('div'); + node.style.position = "relative"; + node.style.width = this.rawNode.style.width; + node.style.height = this.rawNode.style.height; + node.style.filter = "progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, Dx=0, Dy=0)"; + var img = document.createElement('img'); + node.appendChild(img); + shape.setRawNode(node); + this.rawNode.appendChild(node); + shape.setShape(image); + this.add(shape); + return shape; + }, + createObject: function(shapeType, rawShape, overrideSize) { + if(!this.rawNode) return null; + var shape = new shapeType(); + var node = document.createElement('v:' + shapeType.nodeType); + shape.setRawNode(node); + this.rawNode.appendChild(node); + if(overrideSize) this._overrideSize(node); + shape.setShape(rawShape); + this.add(shape); + return shape; + }, + _overrideSize: function(node){ + node.style.width = this.rawNode.style.width; + node.style.height = this.rawNode.style.height; + node.coordsize = parseFloat(node.style.width) + " " + parseFloat(node.style.height); + } +}; + +dojo.lang.extend(dojo.gfx.Group, dojo.gfx._creators); +dojo.lang.extend(dojo.gfx.Surface, dojo.gfx._creators); + +delete dojo.gfx._creators; + +dojo.gfx.attachNode = function(node){ + if(!node) return null; + var s = null; + switch(node.tagName.toLowerCase()){ + case dojo.gfx.Rect.nodeType: + s = new dojo.gfx.Rect(); + break; + case dojo.gfx.Ellipse.nodeType: + s = (node.style.width == node.style.height) + ? new dojo.gfx.Circle() + : new dojo.gfx.Ellipse(); + break; + case dojo.gfx.Path.nodeType: + switch(node.getAttribute("dojoGfxType")){ + case "line": + s = new dojo.gfx.Line(); + break; + case "polyline": + s = new dojo.gfx.Polyline(); + break; + case "path": + s = new dojo.gfx.Path(); + break; + } + break; + case dojo.gfx.Image.nodeType: + s = new dojo.gfx.Image(); + break; + default: + dojo.debug("FATAL ERROR! tagName = " + node.tagName); + } + s.attach(node); + return s; +}; + +dojo.lang.extend(dojo.gfx.Surface, { + setDimensions: function(width, height){ + if(!this.rawNode) return this; + this.rawNode.style.width = width; + this.rawNode.style.height = height; + this.rawNode.coordsize = width + " " + height; + return this; + }, + getDimensions: function(){ + return this.rawNode ? { width: this.rawNode.style.width, height: this.rawNode.style.height } : null; + }, + // group control + add: function(shape){ + var oldParent = shape.getParent(); + if(this != oldParent){ + this.rawNode.appendChild(shape.rawNode); + if(oldParent){ + oldParent.remove(shape, true); + } + shape._setParent(this, null); + } + return this; + }, + remove: function(shape, silently){ + if(this == shape.getParent()){ + if(this.rawNode == shape.rawNode.parentNode){ + this.rawNode.removeChild(shape.rawNode); + } + shape._setParent(null, null); + } + return this; + } +}); + +dojo.gfx.createSurface = function(parentNode, width, height){ + var s = new dojo.gfx.Surface(); + s.rawNode = document.createElement("v:group"); + s.rawNode.style.width = width ? width : "100%"; + s.rawNode.style.height = height ? height : "100%"; + s.rawNode.coordsize = (width && height) + ? (parseFloat(width) + " " + parseFloat(height)) + : "100% 100%"; + s.rawNode.coordorigin = "0 0"; + dojo.byId(parentNode).appendChild(s.rawNode); + return s; +}; + +dojo.gfx.attachSurface = function(node){ + var s = new dojo.gfx.Surface(); + s.rawNode = node; + return s; +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/Colorspace.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/Attic/Colorspace.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/Colorspace.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,15 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.graphics.Colorspace"); +dojo.require("dojo.gfx.Colorspace"); + +dojo.deprecated("dojo.graphics.Colorspace: use dojo.gfx.Colorspace instead.", "0.5"); +dojo.graphics.Colorspace = dojo.gfx.Colorspace; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/__package__.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,12 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +// By default... don't pull in anything? (todo: figure out what should be in list) +dojo.provide("dojo.graphics.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/color.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/Attic/color.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/graphics/color.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,37 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.graphics.color"); +dojo.require("dojo.gfx.color"); + +dojo.deprecated("dojo.graphics.color.Color is now dojo.gfx.color.Color.", "0.5"); +dojo.graphics.color.Color = dojo.gfx.color.Color; + +dojo.graphics.color.named = dojo.gfx.color.named; +dojo.graphics.color.blend = function(a, b, weight) { + dojo.deprecated("dojo.graphics.color.blend is now dojo.gfx.color.blend", "0.5"); + return dojo.gfx.color.blend(a, b, weight); +} +dojo.graphics.color.blendHex = function(a, b, weight) { + dojo.deprecated("dojo.graphics.color.blendHex is now dojo.gfx.color.blendHex", "0.5"); + return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a), dojo.gfx.color.hex2rgb(b), weight)); +} +dojo.graphics.color.extractRGB = function(color) { + dojo.deprecated("dojo.graphics.color.extractRGB is now dojo.gfx.color.extractRGB", "0.5"); + return dojo.gfx.color.extractRGB(color); +} +dojo.graphics.color.hex2rgb = function(hex) { + dojo.deprecated("dojo.graphics.color.hex2rgb is now dojo.gfx.color.hex2rgb", "0.5"); + return dojo.gfx.color.hex2rgb(hex); +} +dojo.graphics.color.rgb2hex = function(r, g, b) { + dojo.deprecated("dojo.graphics.color.rgb2hex is now dojo.gfx.color.rgb2hex", "0.5"); + return dojo.gfx.color.rgb2hex; +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/__package__.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,15 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [ "dojo.html.common", + "dojo.html.style" ] +}); +dojo.provide("dojo.html.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/color.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/Attic/color.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/color.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,35 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.require("dojo.html.style"); +dojo.provide("dojo.html.color"); + +dojo.require("dojo.gfx.color"); +dojo.require("dojo.lang.common"); + +dojo.html.getBackgroundColor = function(/* HTMLElement */node){ + // summary + // returns the background color of the passed node as a 32-bit color (RGBA) + node = dojo.byId(node); + var color; + do{ + color = dojo.html.getStyle(node, "background-color"); + // Safari doesn't say "transparent" + if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; } + if(node == document.getElementsByTagName("body")[0]) { node = null; break; } + node = node.parentNode; + }while(node && dojo.lang.inArray(["transparent", ""], color)); + if(color == "transparent"){ + color = [255, 255, 255, 0]; + }else{ + color = dojo.gfx.color.extractRGB(color); + } + return color; // array +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/Attic/common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/common.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,230 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.html.common"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.dom"); + +dojo.lang.mixin(dojo.html, dojo.dom); + +dojo.html.body = function(){ + dojo.deprecated("dojo.html.body() moved to dojo.body()", "0.5"); + return dojo.body(); +} + +// FIXME: we are going to assume that we can throw any and every rendering +// engine into the IE 5.x box model. In Mozilla, we do this w/ CSS. +// Need to investigate for KHTML and Opera + +dojo.html.getEventTarget = function(/* DOMEvent */evt){ + // summary + // Returns the target of an event + if(!evt) { evt = dojo.global().event || {} }; + var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null)); + while((t)&&(t.nodeType!=1)){ t = t.parentNode; } + return t; // HTMLElement +} + +dojo.html.getViewport = function(){ + // summary + // Returns the dimensions of the viewable area of a browser window + var _window = dojo.global(); + var _document = dojo.doc(); + var w = 0; + var h = 0; + + if(dojo.render.html.mozilla){ + // mozilla + w = _document.documentElement.clientWidth; + h = _window.innerHeight; + }else if(!dojo.render.html.opera && _window.innerWidth){ + //in opera9, dojo.body().clientWidth should be used, instead + //of window.innerWidth/document.documentElement.clientWidth + //so we have to check whether it is opera + w = _window.innerWidth; + h = _window.innerHeight; + } else if (!dojo.render.html.opera && dojo.exists(_document, "documentElement.clientWidth")){ + // IE6 Strict + var w2 = _document.documentElement.clientWidth; + // this lets us account for scrollbars + if(!w || w2 && w2 < w) { + w = w2; + } + h = _document.documentElement.clientHeight; + } else if (dojo.body().clientWidth){ + // IE, Opera + w = dojo.body().clientWidth; + h = dojo.body().clientHeight; + } + return { width: w, height: h }; // object +} + +dojo.html.getScroll = function(){ + // summary + // Returns the scroll position of the document + var _window = dojo.global(); + var _document = dojo.doc(); + var top = _window.pageYOffset || _document.documentElement.scrollTop || dojo.body().scrollTop || 0; + var left = _window.pageXOffset || _document.documentElement.scrollLeft || dojo.body().scrollLeft || 0; + return { + top: top, + left: left, + offset:{ x: left, y: top } // note the change, NOT an Array with added properties. + }; // object +} + +dojo.html.getParentByType = function(/* HTMLElement */node, /* string */type) { + // summary + // Returns the first ancestor of node with tagName type. + var _document = dojo.doc(); + var parent = dojo.byId(node); + type = type.toLowerCase(); + while((parent)&&(parent.nodeName.toLowerCase()!=type)){ + if(parent==(_document["body"]||_document["documentElement"])){ + return null; + } + parent = parent.parentNode; + } + return parent; // HTMLElement +} + +dojo.html.getAttribute = function(/* HTMLElement */node, /* string */attr){ + // summary + // Returns the value of attribute attr from node. + node = dojo.byId(node); + // FIXME: need to add support for attr-specific accessors + if((!node)||(!node.getAttribute)){ + // if(attr !== 'nwType'){ + // alert("getAttr of '" + attr + "' with bad node"); + // } + return null; + } + var ta = typeof attr == 'string' ? attr : new String(attr); + + // first try the approach most likely to succeed + var v = node.getAttribute(ta.toUpperCase()); + if((v)&&(typeof v == 'string')&&(v!="")){ + return v; // string + } + + // try returning the attributes value, if we couldn't get it as a string + if(v && v.value){ + return v.value; // string + } + + // this should work on Opera 7, but it's a little on the crashy side + if((node.getAttributeNode)&&(node.getAttributeNode(ta))){ + return (node.getAttributeNode(ta)).value; // string + }else if(node.getAttribute(ta)){ + return node.getAttribute(ta); // string + }else if(node.getAttribute(ta.toLowerCase())){ + return node.getAttribute(ta.toLowerCase()); // string + } + return null; // string +} + +dojo.html.hasAttribute = function(/* HTMLElement */node, /* string */attr){ + // summary + // Determines whether or not the specified node carries a value for the attribute in question. + return dojo.html.getAttribute(dojo.byId(node), attr) ? true : false; // boolean +} + +dojo.html.getCursorPosition = function(/* DOMEvent */e){ + // summary + // Returns the mouse position relative to the document (not the viewport). + // For example, if you have a document that is 10000px tall, + // but your browser window is only 100px tall, + // if you scroll to the bottom of the document and call this function it + // will return {x: 0, y: 10000} + // NOTE: for events delivered via dojo.event.connect() and/or dojoAttachEvent (for widgets), + // you can just access evt.pageX and evt.pageY, rather than calling this function. + e = e || dojo.global().event; + var cursor = {x:0, y:0}; + if(e.pageX || e.pageY){ + cursor.x = e.pageX; + cursor.y = e.pageY; + }else{ + var de = dojo.doc().documentElement; + var db = dojo.body(); + cursor.x = e.clientX + ((de||db)["scrollLeft"]) - ((de||db)["clientLeft"]); + cursor.y = e.clientY + ((de||db)["scrollTop"]) - ((de||db)["clientTop"]); + } + return cursor; // object +} + +dojo.html.isTag = function(/* HTMLElement */node) { + // summary + // Like dojo.dom.isTag, except case-insensitive + node = dojo.byId(node); + if(node && node.tagName) { + for (var i=1; i, + //which will be treated as an external javascript file in IE + var xscript = dojo.doc().createElement('script'); + xscript.src = "javascript:'dojo.html.createExternalElement=function(doc, tag){ return doc.createElement(tag); }'"; + dojo.doc().getElementsByTagName("head")[0].appendChild(xscript); + })(); + } +}else{ + //for other browsers, simply use document.createElement + //is enough + dojo.html.createExternalElement = function(/* HTMLDocument */doc, /* string */tag){ + // summary + // Creates an element in the HTML document, here for ActiveX activation workaround. + return doc.createElement(tag); // HTMLElement + } +} + +dojo.html._callDeprecated = function(inFunc, replFunc, args, argName, retValue){ + dojo.deprecated("dojo.html." + inFunc, + "replaced by dojo.html." + replFunc + "(" + (argName ? "node, {"+ argName + ": " + argName + "}" : "" ) + ")" + (retValue ? "." + retValue : ""), "0.5"); + var newArgs = []; + if(argName){ var argsIn = {}; argsIn[argName] = args[1]; newArgs.push(args[0]); newArgs.push(argsIn); } + else { newArgs = args } + var ret = dojo.html[replFunc].apply(dojo.html, args); + if(retValue){ return ret[retValue]; } + else { return ret; } +} + +dojo.html.getViewportWidth = function(){ + return dojo.html._callDeprecated("getViewportWidth", "getViewport", arguments, null, "width"); +} +dojo.html.getViewportHeight = function(){ + return dojo.html._callDeprecated("getViewportHeight", "getViewport", arguments, null, "height"); +} +dojo.html.getViewportSize = function(){ + return dojo.html._callDeprecated("getViewportSize", "getViewport", arguments); +} +dojo.html.getScrollTop = function(){ + return dojo.html._callDeprecated("getScrollTop", "getScroll", arguments, null, "top"); +} +dojo.html.getScrollLeft = function(){ + return dojo.html._callDeprecated("getScrollLeft", "getScroll", arguments, null, "left"); +} +dojo.html.getScrollOffset = function(){ + return dojo.html._callDeprecated("getScrollOffset", "getScroll", arguments, null, "offset"); +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/display.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/Attic/display.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/display.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,196 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.html.display"); +dojo.require("dojo.html.style"); + +dojo.html._toggle = function(node, tester, setter){ + node = dojo.byId(node); + setter(node, !tester(node)); + return tester(node); +} + +dojo.html.show = function(/* HTMLElement */node){ + // summary + // Show the passed element by reverting display property set by dojo.html.hide + node = dojo.byId(node); + if(dojo.html.getStyleProperty(node, 'display')=='none'){ + dojo.html.setStyle(node, 'display', (node.dojoDisplayCache||'')); + node.dojoDisplayCache = undefined; // cannot use delete on a node in IE6 + } +} + +dojo.html.hide = function(/* HTMLElement */node){ + // summary + // Hide the passed element by setting display:none + node = dojo.byId(node); + if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount + var d = dojo.html.getStyleProperty(node, 'display') + if(d!='none'){ + node.dojoDisplayCache = d; + } + } + dojo.html.setStyle(node, 'display', 'none'); +} + +dojo.html.setShowing = function(/* HTMLElement */node, /* boolean? */showing){ + // summary + // Calls show() if showing is true, hide() otherwise + dojo.html[(showing ? 'show' : 'hide')](node); +} + +dojo.html.isShowing = function(/* HTMLElement */node){ + // summary + // Returns whether the element is displayed or not. + // FIXME: returns true if node is bad, isHidden would be easier to make correct + return (dojo.html.getStyleProperty(node, 'display') != 'none'); // boolean +} + +dojo.html.toggleShowing = function(/* HTMLElement */node){ + // summary + // Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing() + return dojo.html._toggle(node, dojo.html.isShowing, dojo.html.setShowing); // boolean +} + +// Simple mapping of tag names to display values +// FIXME: simplistic +dojo.html.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' }; + +dojo.html.suggestDisplayByTagName = function(/* HTMLElement */node){ + // summary + // Suggest a value for the display property that will show 'node' based on it's tag + node = dojo.byId(node); + if(node && node.tagName){ + var tag = node.tagName.toLowerCase(); + return (tag in dojo.html.displayMap ? dojo.html.displayMap[tag] : 'block'); // string + } +} + +dojo.html.setDisplay = function(/* HTMLElement */node, /* string */display){ + // summary + // Sets the value of style.display to value of 'display' parameter if it is a string. + // Otherwise, if 'display' is false, set style.display to 'none'. + // Finally, set 'display' to a suggested display value based on the node's tag + dojo.html.setStyle(node, 'display', ((display instanceof String || typeof display == "string") ? display : (display ? dojo.html.suggestDisplayByTagName(node) : 'none'))); +} + +dojo.html.isDisplayed = function(/* HTMLElement */node){ + // summary + // Is true if the the computed display style for node is not 'none' + // FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct + return (dojo.html.getComputedStyle(node, 'display') != 'none'); // boolean +} + +dojo.html.toggleDisplay = function(/* HTMLElement */node){ + // summary + // Call setDisplay() on node with the complement of isDisplayed(), then + // return the new value of isDisplayed() + return dojo.html._toggle(node, dojo.html.isDisplayed, dojo.html.setDisplay); // boolean +} + +dojo.html.setVisibility = function(/* HTMLElement */node, /* string */visibility){ + // summary + // Sets the value of style.visibility to value of 'visibility' parameter if it is a string. + // Otherwise, if 'visibility' is false, set style.visibility to 'hidden'. Finally, set style.visibility to 'visible'. + dojo.html.setStyle(node, 'visibility', ((visibility instanceof String || typeof visibility == "string") ? visibility : (visibility ? 'visible' : 'hidden'))); +} + +dojo.html.isVisible = function(/* HTMLElement */node){ + // summary + // Returns true if the the computed visibility style for node is not 'hidden' + // FIXME: returns true if node is bad, isInvisible would be easier to make correct + return (dojo.html.getComputedStyle(node, 'visibility') != 'hidden'); // boolean +} + +dojo.html.toggleVisibility = function(node){ + // summary + // Call setVisibility() on node with the complement of isVisible(), then return the new value of isVisible() + return dojo.html._toggle(node, dojo.html.isVisible, dojo.html.setVisibility); // boolean +} + +dojo.html.setOpacity = function(/* HTMLElement */node, /* float */opacity, /* boolean? */dontFixOpacity){ + // summary + // Sets the opacity of node in a cross-browser way. + // float between 0.0 (transparent) and 1.0 (opaque) + node = dojo.byId(node); + var h = dojo.render.html; + if(!dontFixOpacity){ + if( opacity >= 1.0){ + if(h.ie){ + dojo.html.clearOpacity(node); + return; + }else{ + opacity = 0.999999; + } + }else if( opacity < 0.0){ opacity = 0; } + } + if(h.ie){ + if(node.nodeName.toLowerCase() == "tr"){ + // FIXME: is this too naive? will we get more than we want? + var tds = node.getElementsByTagName("td"); + for(var x=0; x= 0.999999 ? 1.0 : Number(opac); // float +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/iframe.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/Attic/iframe.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/html/iframe.js 6 Nov 2006 14:50:08 -0000 1.1 @@ -0,0 +1,117 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.html.iframe"); +dojo.require("dojo.html.util"); + +// thanks burstlib! +dojo.html.iframeContentWindow = function(/* HTMLIFrameElement */iframe_el) { + // summary + // returns the window reference of the passed iframe + var win = dojo.html.getDocumentWindow(dojo.html.iframeContentDocument(iframe_el)) || + // Moz. TODO: is this available when defaultView isn't? + dojo.html.iframeContentDocument(iframe_el).__parent__ || + (iframe_el.name && document.frames[iframe_el.name]) || null; + return win; // Window +} + +dojo.html.iframeContentDocument = function(/* HTMLIFrameElement */iframe_el){ + // summary + // returns a reference to the document object inside iframe_el + var doc = iframe_el.contentDocument // W3 + || ((iframe_el.contentWindow)&&(iframe_el.contentWindow.document)) // IE + || ((iframe_el.name)&&(document.frames[iframe_el.name])&&(document.frames[iframe_el.name].document)) + || null; + return doc; // HTMLDocument +} + +dojo.html.BackgroundIframe = function(/* HTMLElement */node) { + // summary + // For IE z-index schenanigans + // Two possible uses: + // 1. new dojo.html.BackgroundIframe(node) + // Makes a background iframe as a child of node, that fills area (and position) of node + // 2. new dojo.html.BackgroundIframe() + // Attaches frame to dojo.body(). User must call size() to set size. + if(dojo.render.html.ie55 || dojo.render.html.ie60) { + var html="" + }else{ + this.rcvNode = dojo.io.createIFrame(this.rcvNodeName, "", initUrl); + // dojo.io.setIFrameSrc(this.rcvNode, initUrl); + // we're still waiting on the iframe to call back up to use and + // advertise that it's been initialized via tunnelInit + } + } +} + +cometd.mimeReplaceTransport = new function(){ + this.connected = false; + this.connectionId = null; + this.xhr = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + return ((!xdomain)&& + (dojo.render.html.mozilla)&& // seems only Moz really supports this right now = ( + (dojo.lang.inArray(types, "mime-message-block"))); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "mime-message-block" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(this.connected){ + // try to restart the tunnel + this.connected = false; + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.handleOnLoad = function(resp){ + cometd.deliver(dojo.json.evalJson(this.xhr.responseText)); + } + + this.openTunnelWith = function(content, url){ + // set up the XHR object and register the multipart callbacks + this.xhr = dojo.hostenv.getXmlhttpObject(); + this.xhr.multipart = true; // FIXME: do Opera and Safari support this flag? + if(dojo.render.html.mozilla){ + this.xhr.addEventListener("load", dojo.lang.hitch(this, "handleOnLoad"), false); + }else if(dojo.render.html.safari){ + // Blah. WebKit doesn't actually populate responseText and/or responseXML. Useless. + dojo.debug("Webkit is broken with multipart responses over XHR = ("); + this.xhr.onreadystatechange = dojo.lang.hitch(this, "handleOnLoad"); + }else{ + this.xhr.onload = dojo.lang.hitch(this, "handleOnLoad"); + } + this.xhr.open("POST", (url||cometd.url), true); // async post + this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + dojo.debug(dojo.json.serialize(content)); + this.xhr.send(dojo.io.argsFromMap(content, "utf8")); + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + method: "POST", + mimetype: "text/json", + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + dojo.debugShallow(handshakeData); + if(this.connected){ return; } + this.tunnelInit(); + } +} + +cometd.longPollTransport = new function(){ + this.connected = false; + this.connectionId = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + return ((!xdomain)&&(dojo.lang.inArray(types, "long-polling"))); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "long-polling" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(!this.connected){ + // try to restart the tunnel + this.connected = false; + dojo.debug("clientId:", cometd.clientId); + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + connectionType: "long-polling", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.openTunnelWith = function(content, url){ + dojo.io.bind({ + url: (url||cometd.url), + method: "post", + content: content, + mimetype: "text/json", + load: dojo.lang.hitch(this, function(type, data, evt, args){ + // dojo.debug(evt.responseText); + cometd.deliver(data); + this.connected = false; + this.tunnelCollapse(); + }), + error: function(){ dojo.debug("tunnel opening failed"); } + }); + this.connected = true; + } + + this.processBacklog = function(){ + while(this.backlog.length > 0){ + this.sendMessage(this.backlog.shift(), true); + } + } + + this.sendMessage = function(message, bypassBacklog){ + // FIXME: what about auth fields? + if((bypassBacklog)||(this.connected)){ + message.connectionId = this.connectionId; + message.clientId = cometd.clientId; + var bindArgs = { + url: cometd.url||djConfig["cometdRoot"], + method: "post", + mimetype: "text/json", + content: { message: dojo.json.serialize([ message ]) } + }; + return dojo.io.bind(bindArgs); + }else{ + this.backlog.push(message); + } + } + + this.startup = function(handshakeData){ + if(this.connected){ return; } + this.tunnelInit(); + } +} + +cometd.callbackPollTransport = new function(){ + this.connected = false; + this.connectionId = null; + + this.authToken = null; + this.lastTimestamp = null; + this.lastId = null; + this.backlog = []; + + this.check = function(types, version, xdomain){ + // we handle x-domain! + return dojo.lang.inArray(types, "callback-polling"); + } + + this.tunnelInit = function(){ + if(this.connected){ return; } + // FIXME: open up the connection here + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/connect", + clientId: cometd.clientId, + connectionType: "callback-polling" + // FIXME: auth not passed here! + // "authToken": this.authToken + } + ]) + }); + this.connected = true; + } + + this.tunnelCollapse = function(){ + if(!this.connected){ + // try to restart the tunnel + this.connected = false; + this.openTunnelWith({ + message: dojo.json.serialize([ + { + channel: "/meta/reconnect", + connectionType: "long-polling", + clientId: cometd.clientId, + connectionId: this.connectionId, + timestamp: this.lastTimestamp, + id: this.lastId + // FIXME: no authToken provision! + } + ]) + }); + } + } + + this.deliver = cometd.iframeTransport.deliver; + // the logic appears to be the same + + this.openTunnelWith = function(content, url){ + // create a + + +

The Dojo Toolkit -- xip_client.html

+ +

This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the "client" file used + internally by dojo.io.XhrIframeProxy.

+ + + + Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/io/xip_server.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/io/Attic/xip_server.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/io/xip_server.html 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,337 @@ + + + + + + + + + + + +

The Dojo Toolkit -- xip_server.html

+ +

This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the the file + that should go on the server that will actually be doing the XHR request.

+ + Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/__package__.js 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,23 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [ + "dojo.lang.common", + "dojo.lang.assert", + "dojo.lang.array", + "dojo.lang.type", + "dojo.lang.func", + "dojo.lang.extras", + "dojo.lang.repr", + "dojo.lang.declare" + ] +}); +dojo.provide("dojo.lang.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/array.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/Attic/array.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/array.js 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,186 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lang.array"); + +dojo.require("dojo.lang.common"); + +// FIXME: Is this worthless since you can do: if(name in obj) +// is this the right place for this? +dojo.lang.has = function(/*Object*/obj, /*String*/name){ + try{ + return typeof obj[name] != "undefined"; + }catch(e){ return false; } +} + +dojo.lang.isEmpty = function(/*Object*/obj){ + if(dojo.lang.isObject(obj)){ + var tmp = {}; + var count = 0; + for(var x in obj){ + if(obj[x] && (!tmp[x])){ + count++; + break; + } + } + return count == 0; + }else if(dojo.lang.isArrayLike(obj) || dojo.lang.isString(obj)){ + return obj.length == 0; + } +} + +dojo.lang.map = function(/*Array*/arr, /*Object|Function*/obj, /*Function?*/unary_func){ + var isString = dojo.lang.isString(arr); + if(isString){ + // arr: String + arr = arr.split(""); + } + if(dojo.lang.isFunction(obj)&&(!unary_func)){ + unary_func = obj; + obj = dj_global; + }else if(dojo.lang.isFunction(obj) && unary_func){ + // ff 1.5 compat + var tmpObj = obj; + obj = unary_func; + unary_func = tmpObj; + } + if(Array.map){ + var outArr = Array.map(arr, unary_func, obj); + }else{ + var outArr = []; + for(var i=0;i= 3){ dojo.raise("thisObject doesn't exist!"); } + thisObject = dj_global; + } + + outArr = []; + for(var i = 0; i < arr.length; i++){ + if(callback.call(thisObject, arr[i], i, arr)){ + outArr.push(arr[i]); + } + } + } + if(isString){ + return outArr.join(""); // String + } else { + return outArr; // Array + } +} + +dojo.lang.unnest = function(/* ... */){ + // summary: + // Creates a 1-D array out of all the arguments passed, + // unravelling any array-like objects in the process + // + // usage: + // unnest(1, 2, 3) ==> [1, 2, 3] + // unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4] + + var out = []; + for(var i = 0; i < arguments.length; i++){ + if(dojo.lang.isArrayLike(arguments[i])){ + var add = dojo.lang.unnest.apply(this, arguments[i]); + out = out.concat(add); + }else{ + out.push(arguments[i]); + } + } + return out; // Array +} + +dojo.lang.toArray = function(/*Object*/arrayLike, /*Number*/startOffset){ + // summary: + // Converts an array-like object (i.e. arguments, DOMCollection) + // to an array + var array = []; + for(var i = startOffset||0; i < arrayLike.length; i++){ + array.push(arrayLike[i]); + } + return array; // Array +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/assert.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/Attic/assert.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/assert.js 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,116 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lang.assert"); + +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.type"); + +dojo.lang.assert = function(/* boolean */ booleanValue, /* string? */ message){ + /* summary: + * Throws an exception if the assertion fails. + * description: + * If the asserted condition is true, this method does nothing. If the + * condition is false, we throw an error with a error message. + * booleanValue: Must be true for the assertion to succeed. + * message: A string describing the assertion. + */ + + // throws: Throws an Error if 'booleanValue' is false. + if(!booleanValue){ + var errorMessage = "An assert statement failed.\n" + + "The method dojo.lang.assert() was called with a 'false' value.\n"; + if(message){ + errorMessage += "Here's the assert message:\n" + message + "\n"; + } + // Use throw instead of dojo.raise, until bug #264 is fixed: + // dojo.raise(errorMessage); + throw new Error(errorMessage); + } +} + +dojo.lang.assertType = function(/* anything */ value, /* misc. */ type, /* object? */ keywordParameters){ + /* summary: + * Throws an exception if 'value' is not of type 'type' + * description: + * Given a value and a data type, this method checks the type of the value + * to make sure it matches the data type, and throws an exception if there + * is a mismatch. + * value: Any literal value or object instance. + * type: A class of object, or a literal type, or the string name of a type, or an array with a list of types. + * keywordParameters: {optional: boolean} + */ + + /* examples: + * dojo.lang.assertType("foo", String); + * dojo.lang.assertType(12345, Number); + * dojo.lang.assertType(false, Boolean); + * dojo.lang.assertType([6, 8], Array); + * dojo.lang.assertType(dojo.lang.assertType, Function); + * dojo.lang.assertType({foo: "bar"}, Object); + * dojo.lang.assertType(new Date(), Date); + * dojo.lang.assertType(null, Array, {optional: true}); + * throws: Throws an Error if 'value' is not of type 'type'. + */ + if (dojo.lang.isString(keywordParameters)) { + dojo.deprecated('dojo.lang.assertType(value, type, "message")', 'use dojo.lang.assertType(value, type) instead', "0.5"); + } + if(!dojo.lang.isOfType(value, type, keywordParameters)){ + if(!dojo.lang.assertType._errorMessage){ + dojo.lang.assertType._errorMessage = "Type mismatch: dojo.lang.assertType() failed."; + } + dojo.lang.assert(false, dojo.lang.assertType._errorMessage); + } +} + +dojo.lang.assertValidKeywords = function(/* object */ object, /* array */ expectedProperties, /* string? */ message){ + /* summary: + * Throws an exception 'object' has any properties other than the 'expectedProperties'. + * description: + * Given an anonymous object and a list of expected property names, this + * method check to make sure the object does not have any properties + * that aren't on the list of expected properties, and throws an Error + * if there are unexpected properties. This is useful for doing error + * checking on keyword arguments, to make sure there aren't typos. + * object: An anonymous object. + * expectedProperties: An array of strings (or an object with all the expected properties). + * message: A message describing the assertion. + */ + + /* examples: + * dojo.lang.assertValidKeywords({a: 1, b: 2}, ["a", "b"]); + * dojo.lang.assertValidKeywords({a: 1, b: 2}, ["a", "b", "c"]); + * dojo.lang.assertValidKeywords({foo: "iggy"}, ["foo"]); + * dojo.lang.assertValidKeywords({foo: "iggy"}, ["foo", "bar"]); + * dojo.lang.assertValidKeywords({foo: "iggy"}, {foo: null, bar: null}); + * throws: Throws an Error if 'object' has unexpected properties. + */ + var key; + if(!message){ + if(!dojo.lang.assertValidKeywords._errorMessage){ + dojo.lang.assertValidKeywords._errorMessage = "In dojo.lang.assertValidKeywords(), found invalid keyword:"; + } + message = dojo.lang.assertValidKeywords._errorMessage; + } + if(dojo.lang.isArray(expectedProperties)){ + for(key in object){ + if(!dojo.lang.inArray(expectedProperties, key)){ + dojo.lang.assert(false, message + " " + key); + } + } + }else{ + for(key in object){ + if(!(key in expectedProperties)){ + dojo.lang.assert(false, message + " " + key); + } + } + } +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/common.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/Attic/common.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/common.js 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,230 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lang.common"); + +dojo.lang.inherits = function(/*Function*/ subclass, /*Function*/ superclass){ + // summary: Set up inheritance between two classes. + if(typeof superclass != 'function'){ + dojo.raise("dojo.inherits: superclass argument ["+superclass+"] must be a function (subclass: ["+subclass+"']"); + } + subclass.prototype = new superclass(); + subclass.prototype.constructor = subclass; + subclass.superclass = superclass.prototype; + // DEPRECATED: super is a reserved word, use 'superclass' + subclass['super'] = superclass.prototype; +} + +dojo.lang._mixin = function(/*Object*/ obj, /*Object*/ props){ + // summary: Adds all properties and methods of props to obj. + var tobj = {}; + for(var x in props){ + // the "tobj" condition avoid copying properties in "props" + // inherited from Object.prototype. For example, if obj has a custom + // toString() method, don't overwrite it with the toString() method + // that props inherited from Object.protoype + if((typeof tobj[x] == "undefined") || (tobj[x] != props[x])){ + obj[x] = props[x]; + } + } + // IE doesn't recognize custom toStrings in for..in + if(dojo.render.html.ie + && (typeof(props["toString"]) == "function") + && (props["toString"] != obj["toString"]) + && (props["toString"] != tobj["toString"])) + { + obj.toString = props.toString; + } + return obj; // Object +} + +dojo.lang.mixin = function(/*Object*/ obj, /*Object...*/props){ + // summary: Adds all properties and methods of props to obj. + for(var i=1, l=arguments.length; i -1; // boolean +} + +/** + * Partial implmentation of is* functions from + * http://www.crockford.com/javascript/recommend.html + * NOTE: some of these may not be the best thing to use in all situations + * as they aren't part of core JS and therefore can't work in every case. + * See WARNING messages inline for tips. + * + * The following is* functions are fairly "safe" + */ + +dojo.lang.isObject = function(/*anything*/ it){ + // summary: Return true if it is an Object, Array or Function. + if(typeof it == "undefined"){ return false; } + return (typeof it == "object" || it === null || dojo.lang.isArray(it) || dojo.lang.isFunction(it)); // Boolean +} + +dojo.lang.isArray = function(/*anything*/ it){ + // summary: Return true if it is an Array. + return (it && it instanceof Array || typeof it == "array"); // Boolean +} + +dojo.lang.isArrayLike = function(/*anything*/ it){ + // summary: Return true if it can be used as an array (i.e. is an object with an integer length property). + if((!it)||(dojo.lang.isUndefined(it))){ return false; } + if(dojo.lang.isString(it)){ return false; } + if(dojo.lang.isFunction(it)){ return false; } // keeps out built-in constructors (Number, String, ...) which have length properties + if(dojo.lang.isArray(it)){ return true; } + // form node itself is ArrayLike, but not always iterable. Use form.elements instead. + if((it.tagName)&&(it.tagName.toLowerCase()=='form')){ return false; } + if(dojo.lang.isNumber(it.length) && isFinite(it.length)){ return true; } + return false; // Boolean +} + +dojo.lang.isFunction = function(/*anything*/ it){ + // summary: Return true if it is a Function. + if(!it){ return false; } + // webkit treats NodeList as a function, which is bad + if((typeof(it) == "function") && (it == "[object NodeList]")) { return false; } + return (it instanceof Function || typeof it == "function"); // Boolean +} + +dojo.lang.isString = function(/*anything*/ it){ + // summary: Return true if it is a String. + return (typeof it == "string" || it instanceof String); +} + +dojo.lang.isAlien = function(/*anything*/ it){ + // summary: Return true if it is not a built-in function. + if(!it){ return false; } + return !dojo.lang.isFunction() && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean +} + +dojo.lang.isBoolean = function(/*anything*/ it){ + // summary: Return true if it is a Boolean. + return (it instanceof Boolean || typeof it == "boolean"); // Boolean +} + +/** + * The following is***() functions are somewhat "unsafe". Fortunately, + * there are workarounds the the language provides and are mentioned + * in the WARNING messages. + * + */ +dojo.lang.isNumber = function(/*anything*/ it){ + // summary: Return true if it is a number. + // description: + // WARNING - In most cases, isNaN(it) is sufficient to determine whether or not + // something is a number or can be used as such. For example, a number or string + // can be used interchangably when accessing array items (array["1"] is the same as + // array[1]) and isNaN will return false for both values ("1" and 1). However, + // isNumber("1") will return false, which is generally not too useful. + // Also, isNumber(NaN) returns true, again, this isn't generally useful, but there + // are corner cases (like when you want to make sure that two things are really + // the same type of thing). That is really where isNumber "shines". + // + // Recommendation - Use isNaN(it) when possible + + return (it instanceof Number || typeof it == "number"); // Boolean +} + +/* + * FIXME: Should isUndefined go away since it is error prone? + */ +dojo.lang.isUndefined = function(/*anything*/ it){ + // summary: Return true if it is not defined. + // description: + // WARNING - In some cases, isUndefined will not behave as you + // might expect. If you do isUndefined(foo) and there is no earlier + // reference to foo, an error will be thrown before isUndefined is + // called. It behaves correctly if you scope yor object first, i.e. + // isUndefined(foo.bar) where foo is an object and bar isn't a + // property of the object. + // + // Recommendation - Use typeof foo == "undefined" when possible + + return ((typeof(it) == "undefined")&&(it == undefined)); // Boolean +} + +// end Crockford functions Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/declare.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/Attic/declare.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lang/declare.js 6 Nov 2006 14:50:09 -0000 1.1 @@ -0,0 +1,161 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lang.declare"); + +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.extras"); + +dojo.lang.declare = function(/*String*/ className, /*Function|Array*/ superclass, /*Function?*/ init, /*Object|Array*/ props){ +/* + * summary: Create a feature-rich constructor with a compact notation + * + * className: the name of the constructor (loosely, a "class") + * + * superclass: may be a Function, or an Array of Functions. + * If "superclass" is an array, the first element is used + * as the prototypical ancestor and any following Functions + * become mixin ancestors. + * + * init: an initializer function + * + * props: an object (or array of objects) whose properties are copied to the created prototype + * + * description: Create a constructor using a compact notation for inheritance and prototype extension. + * + * "superclass" argument may be a Function, or an array of + * Functions. + * + * If "superclass" is an array, the first element is used + * as the prototypical ancestor and any following Functions + * become mixin ancestors. + * + * All "superclass(es)" must be Functions (not mere Objects). + * + * Using mixin ancestors provides a type of multiple + * inheritance. Mixin ancestors prototypical + * properties are copied to the subclass, and any + * inializater/constructor is invoked. + * + * Properties of object "props" are copied to the constructor + * prototype. If "props" is an array, properties of each + * object in the array are copied to the constructor prototype. + * + * name of the class ("className" argument) is stored in + * "declaredClass" property + * + * Initializer functions are called when an object + * is instantiated from this constructor. + * + * Aliased as "dojo.declare" + * + * Usage: + * + * dojo.declare("my.classes.bar", my.classes.foo, + * function() { + * // initialization function + * this.myComplicatedObject = new ReallyComplicatedObject(); + * },{ + * someValue: 2, + * someMethod: function() { + * doStuff(); + * } + * }); + * + */ + if((dojo.lang.isFunction(props))||((!props)&&(!dojo.lang.isFunction(init)))){ + // parameter juggling to support omitting init param (also allows reordering init and props arguments) + var temp = props; + props = init; + init = temp; + } + var mixins = [ ]; + if(dojo.lang.isArray(superclass)){ + mixins = superclass; + superclass = mixins.shift(); + } + if(!init){ + init = dojo.evalObjPath(className, false); + if((init)&&(!dojo.lang.isFunction(init))){ init = null }; + } + var ctor = dojo.lang.declare._makeConstructor(); + var scp = (superclass ? superclass.prototype : null); + if(scp){ + scp.prototyping = true; + ctor.prototype = new superclass(); + scp.prototyping = false; + } + ctor.superclass = scp; + ctor.mixins = mixins; + for(var i=0,l=mixins.length; i 0){ this.duration = duration; } + if(repeatCount){ this.repeatCount = repeatCount; } + if(rate){ this.rate = rate; } + if(handlers){ + dojo.lang.forEach([ + "handler", "beforeBegin", "onBegin", + "onEnd", "onPlay", "onStop", "onAnimate" + ], function(item){ + if(handlers[item]){ + this.connect(item, handlers[item]); + } + }, this); + } + if(easing && dojo.lang.isFunction(easing)){ + this.easing=easing; + } +} +dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation); +dojo.lang.extend(dojo.lfx.Animation, { + // "private" properties + _startTime: null, + _endTime: null, + _timer: null, + _percent: 0, + _startRepeatCount: 0, + + // public methods + play: function(/*int?*/ delay, /*bool?*/ gotoStart){ + // summary: Start the animation. + // delay: How many milliseconds to delay before starting. + // gotoStart: If true, starts the animation from the beginning; otherwise, + // starts it from its current position. + if(gotoStart){ + clearTimeout(this._timer); + this._active = false; + this._paused = false; + this._percent = 0; + }else if(this._active && !this._paused){ + return this; // dojo.lfx.Animation + } + + this.fire("handler", ["beforeBegin"]); + this.fire("beforeBegin"); + + if(delay > 0){ + setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); + return this; // dojo.lfx.Animation + } + + this._startTime = new Date().valueOf(); + if(this._paused){ + this._startTime -= (this.duration * this._percent / 100); + } + this._endTime = this._startTime + this.duration; + + this._active = true; + this._paused = false; + + var step = this._percent / 100; + var value = this.curve.getValue(step); + if(this._percent == 0 ){ + if(!this._startRepeatCount){ + this._startRepeatCount = this.repeatCount; + } + this.fire("handler", ["begin", value]); + this.fire("onBegin", [value]); + } + + this.fire("handler", ["play", value]); + this.fire("onPlay", [value]); + + this._cycle(); + return this; // dojo.lfx.Animation + }, + + pause: function(){ + // summary: Pauses a running animation. + clearTimeout(this._timer); + if(!this._active){ return this; /*dojo.lfx.Animation*/} + this._paused = true; + var value = this.curve.getValue(this._percent / 100); + this.fire("handler", ["pause", value]); + this.fire("onPause", [value]); + return this; // dojo.lfx.Animation + }, + + gotoPercent: function(/*Decimal*/ pct, /*bool?*/ andPlay){ + // summary: Sets the progress of the animation. + // pct: A percentage in decimal notation (between and including 0.0 and 1.0). + // andPlay: If true, play the animation after setting the progress. + clearTimeout(this._timer); + this._active = true; + this._paused = true; + this._percent = pct; + if(andPlay){ this.play(); } + return this; // dojo.lfx.Animation + }, + + stop: function(/*bool?*/ gotoEnd){ + // summary: Stops a running animation. + // gotoEnd: If true, the animation will end. + clearTimeout(this._timer); + var step = this._percent / 100; + if(gotoEnd){ + step = 1; + } + var value = this.curve.getValue(step); + this.fire("handler", ["stop", value]); + this.fire("onStop", [value]); + this._active = false; + this._paused = false; + return this; // dojo.lfx.Animation + }, + + status: function(){ + // summary: Returns a string representation of the status of + // the animation. + if(this._active){ + return this._paused ? "paused" : "playing"; // String + }else{ + return "stopped"; // String + } + return this; + }, + + // "private" methods + _cycle: function(){ + clearTimeout(this._timer); + if(this._active){ + var curr = new Date().valueOf(); + var step = (curr - this._startTime) / (this._endTime - this._startTime); + + if(step >= 1){ + step = 1; + this._percent = 100; + }else{ + this._percent = step * 100; + } + + // Perform easing + if((this.easing)&&(dojo.lang.isFunction(this.easing))){ + step = this.easing(step); + } + + var value = this.curve.getValue(step); + this.fire("handler", ["animate", value]); + this.fire("onAnimate", [value]); + + if( step < 1 ){ + this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate); + }else{ + this._active = false; + this.fire("handler", ["end"]); + this.fire("onEnd"); + + if(this.repeatCount > 0){ + this.repeatCount--; + this.play(null, true); + }else if(this.repeatCount == -1){ + this.play(null, true); + }else{ + if(this._startRepeatCount){ + this.repeatCount = this._startRepeatCount; + this._startRepeatCount = 0; + } + } + } + } + return this; // dojo.lfx.Animation + } +}); + +dojo.lfx.Combine = function(/*dojo.lfx.IAnimation...*/ animations){ + // summary: An animation object to play animations passed to it at the same time. + dojo.lfx.IAnimation.call(this); + this._anims = []; + this._animsEnded = 0; + + var anims = arguments; + if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){ + /* animations: dojo.lfx.IAnimation[] + pId: a */ + anims = anims[0]; + } + + dojo.lang.forEach(anims, function(anim){ + this._anims.push(anim); + anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded")); + }, this); +} +dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation); +dojo.lang.extend(dojo.lfx.Combine, { + // private members + _animsEnded: 0, + + // public methods + play: function(/*int?*/ delay, /*bool?*/ gotoStart){ + // summary: Start the animations. + // delay: How many milliseconds to delay before starting. + // gotoStart: If true, starts the animations from the beginning; otherwise, + // starts them from their current position. + if( !this._anims.length ){ return this; /*dojo.lfx.Combine*/} + + this.fire("beforeBegin"); + + if(delay > 0){ + setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); + return this; // dojo.lfx.Combine + } + + if(gotoStart || this._anims[0].percent == 0){ + this.fire("onBegin"); + } + this.fire("onPlay"); + this._animsCall("play", null, gotoStart); + return this; // dojo.lfx.Combine + }, + + pause: function(){ + // summary: Pauses the running animations. + this.fire("onPause"); + this._animsCall("pause"); + return this; // dojo.lfx.Combine + }, + + stop: function(/*bool?*/ gotoEnd){ + // summary: Stops the running animations. + // gotoEnd: If true, the animations will end. + this.fire("onStop"); + this._animsCall("stop", gotoEnd); + return this; // dojo.lfx.Combine + }, + + // private methods + _onAnimsEnded: function(){ + this._animsEnded++; + if(this._animsEnded >= this._anims.length){ + this.fire("onEnd"); + } + return this; // dojo.lfx.Combine + }, + + _animsCall: function(/*String*/ funcName){ + var args = []; + if(arguments.length > 1){ + for(var i = 1 ; i < arguments.length ; i++){ + args.push(arguments[i]); + } + } + var _this = this; + dojo.lang.forEach(this._anims, function(anim){ + anim[funcName](args); + }, _this); + return this; // dojo.lfx.Combine + } +}); + +dojo.lfx.Chain = function(/*dojo.lfx.IAnimation...*/ animations) { + // summary: An animation object to play animations passed to it + // one after another. + dojo.lfx.IAnimation.call(this); + this._anims = []; + this._currAnim = -1; + + var anims = arguments; + if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){ + /* animations: dojo.lfx.IAnimation[] + pId: a */ + anims = anims[0]; + } + + var _this = this; + dojo.lang.forEach(anims, function(anim, i, anims_arr){ + this._anims.push(anim); + if(i < anims_arr.length - 1){ + anim.connect("onEnd", dojo.lang.hitch(this, "_playNext") ); + }else{ + anim.connect("onEnd", dojo.lang.hitch(this, function(){ this.fire("onEnd"); }) ); + } + }, this); +} +dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation); +dojo.lang.extend(dojo.lfx.Chain, { + // private members + _currAnim: -1, + + // public methods + play: function(/*int?*/ delay, /*bool?*/ gotoStart){ + // summary: Start the animation sequence. + // delay: How many milliseconds to delay before starting. + // gotoStart: If true, starts the sequence from the beginning; otherwise, + // starts it from its current position. + if( !this._anims.length ) { return this; /*dojo.lfx.Chain*/} + if( gotoStart || !this._anims[this._currAnim] ) { + this._currAnim = 0; + } + + var currentAnimation = this._anims[this._currAnim]; + + this.fire("beforeBegin"); + if(delay > 0){ + setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay); + return this; // dojo.lfx.Chain + } + + if(currentAnimation){ + if(this._currAnim == 0){ + this.fire("handler", ["begin", this._currAnim]); + this.fire("onBegin", [this._currAnim]); + } + this.fire("onPlay", [this._currAnim]); + currentAnimation.play(null, gotoStart); + } + return this; // dojo.lfx.Chain + }, + + pause: function(){ + // summary: Pauses the running animation sequence. + if( this._anims[this._currAnim] ) { + this._anims[this._currAnim].pause(); + this.fire("onPause", [this._currAnim]); + } + return this; // dojo.lfx.Chain + }, + + playPause: function(){ + // summary: If the animation sequence is playing, pause it; otherwise, + // play it. + if(this._anims.length == 0){ return this; } + if(this._currAnim == -1){ this._currAnim = 0; } + var currAnim = this._anims[this._currAnim]; + if( currAnim ) { + if( !currAnim._active || currAnim._paused ) { + this.play(); + } else { + this.pause(); + } + } + return this; // dojo.lfx.Chain + }, + + stop: function(){ + // summary: Stops the running animations. + var currAnim = this._anims[this._currAnim]; + if(currAnim){ + currAnim.stop(); + this.fire("onStop", [this._currAnim]); + } + return currAnim; // dojo.lfx.IAnimation + }, + + // private methods + _playNext: function(){ + if( this._currAnim == -1 || this._anims.length == 0 ) { return this; } + this._currAnim++; + if( this._anims[this._currAnim] ){ + this._anims[this._currAnim].play(null, true); + } + return this; // dojo.lfx.Chain + } +}); + +dojo.lfx.combine = function(/*dojo.lfx.IAnimation...*/ animations){ + // summary: Convenience function. Returns a dojo.lfx.Combine created + // using the animations passed in. + var anims = arguments; + if(dojo.lang.isArray(arguments[0])){ + /* animations: dojo.lfx.IAnimation[] + pId: a */ + anims = arguments[0]; + } + if(anims.length == 1){ return anims[0]; } + return new dojo.lfx.Combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.chain = function(/*dojo.lfx.IAnimation...*/ animations){ + // summary: Convenience function. Returns a dojo.lfx.Chain created + // using the animations passed in. + var anims = arguments; + if(dojo.lang.isArray(arguments[0])){ + /* animations: dojo.lfx.IAnimation[] + pId: a */ + anims = arguments[0]; + } + if(anims.length == 1){ return anims[0]; } + return new dojo.lfx.Chain(anims); // dojo.lfx.Combine +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/__package__.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,15 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + browser: ["dojo.lfx.html"], + dashboard: ["dojo.lfx.html"] +}); +dojo.provide("dojo.lfx.*"); \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/extras.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/Attic/extras.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/extras.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,148 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lfx.extras"); + +dojo.require("dojo.lfx.html"); +dojo.require("dojo.lfx.Animation"); + +dojo.lfx.html.fadeWipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from its current + // opacity to fully opaque while wiping it in. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anim = dojo.lfx.combine( + dojo.lfx.fadeIn(nodes, duration, easing), + dojo.lfx.wipeIn(nodes, duration, easing) + ); + + if(callback){ + anim.connect("onEnd", function(){ + callback(nodes, anim); + }); + } + + return anim; // dojo.lfx.Combine +} + +dojo.lfx.html.fadeWipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from its current + // opacity to fully transparent while wiping it out. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anim = dojo.lfx.combine( + dojo.lfx.fadeOut(nodes, duration, easing), + dojo.lfx.wipeOut(nodes, duration, easing) + ); + + if(callback){ + /* callback: Function + pId: f */ + anim.connect("onEnd", function(){ + callback(nodes, anim); + }); + } + + return anim; // dojo.lfx.Combine +} + +dojo.lfx.html.scale = function(/*DOMNode[]*/nodes, + /*int*/ percentage, + /*bool?*/ scaleContent, + /*bool?*/ fromCenter, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will scale "nodes" by "percentage". + // nodes: An array of DOMNodes or one DOMNode. + // percentage: A whole number representing the percentage to scale "nodes". + // scaleContent: If true, will scale the contents of "nodes". + // fromCenter: If true, will scale "nodes" from its center rather than the + // lower right corner. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + + dojo.lang.forEach(nodes, function(node){ + var outer = dojo.html.getMarginBox(node); + + var actualPct = percentage/100.0; + var props = [ + { property: "width", + start: outer.width, + end: outer.width * actualPct + }, + { property: "height", + start: outer.height, + end: outer.height * actualPct + }]; + + if(scaleContent){ + var fontSize = dojo.html.getStyle(node, 'font-size'); + var fontSizeType = null; + if(!fontSize){ + fontSize = parseFloat('100%'); + fontSizeType = '%'; + }else{ + dojo.lang.some(['em','px','%'], function(item, index, arr){ + if(fontSize.indexOf(item)>0){ + fontSize = parseFloat(fontSize); + fontSizeType = item; + return true; + } + }); + } + props.push({ + property: "font-size", + start: fontSize, + end: fontSize * actualPct, + units: fontSizeType }); + } + + if(fromCenter){ + var positioning = dojo.html.getStyle(node, "position"); + var originalTop = node.offsetTop; + var originalLeft = node.offsetLeft; + var endTop = ((outer.height * actualPct) - outer.height)/2; + var endLeft = ((outer.width * actualPct) - outer.width)/2; + props.push({ + property: "top", + start: originalTop, + end: (positioning == "absolute" ? originalTop - endTop : (-1*endTop)) + }); + props.push({ + property: "left", + start: originalLeft, + end: (positioning == "absolute" ? originalLeft - endLeft : (-1*endLeft)) + }); + } + + var anim = dojo.lfx.propertyAnimation(node, props, duration, easing); + if(callback){ + anim.connect("onEnd", function(){ + callback(node, anim); + }); + } + + anims.push(anim); + }); + + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lang.mixin(dojo.lfx, dojo.lfx.html); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/html.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/Attic/html.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/html.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,734 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lfx.html"); + +dojo.require("dojo.gfx.color"); +dojo.require("dojo.lfx.Animation"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.html.display"); +dojo.require("dojo.html.color"); +dojo.require("dojo.html.layout"); + +dojo.lfx.html._byId = function(nodes){ + if(!nodes){ return []; } + if(dojo.lang.isArrayLike(nodes)){ + if(!nodes.alreadyChecked){ + var n = []; + dojo.lang.forEach(nodes, function(node){ + n.push(dojo.byId(node)); + }); + n.alreadyChecked = true; + return n; + }else{ + return nodes; + } + }else{ + var n = []; + n.push(dojo.byId(nodes)); + n.alreadyChecked = true; + return n; + } +} + +dojo.lfx.html.propertyAnimation = function( /*DOMNode[]*/ nodes, + /*Object[]*/ propertyMap, + /*int*/ duration, + /*function*/ easing, + /*Object*/ handlers){ + // summary: Returns an animation that will transition the properties of "nodes" + // depending how they are defined in "propertyMap". + // nodes: An array of DOMNodes or one DOMNode. + // propertyMap: { property: String, start: Decimal?, end: Decimal?, units: String? } + // An array of objects defining properties to change. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? } + nodes = dojo.lfx.html._byId(nodes); + + var targs = { + "propertyMap": propertyMap, + "nodes": nodes, + "duration": duration, + "easing": easing||dojo.lfx.easeDefault + }; + + var setEmUp = function(args){ + if(args.nodes.length==1){ + // FIXME: we're only supporting start-value filling when one node is + // passed + + var pm = args.propertyMap; + if(!dojo.lang.isArray(args.propertyMap)){ + // it's stupid to have to pack an array with a set of objects + // when you can just pass in an object list + var parr = []; + for(var pname in pm){ + pm[pname].property = pname; + parr.push(pm[pname]); + } + pm = args.propertyMap = parr; + } + dojo.lang.forEach(pm, function(prop){ + if(dj_undef("start", prop)){ + if(prop.property != "opacity"){ + prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property)); + }else{ + prop.start = dojo.html.getOpacity(args.nodes[0]); + } + } + }); + } + } + + var coordsAsInts = function(coords){ + var cints = []; + dojo.lang.forEach(coords, function(c){ + cints.push(Math.round(c)); + }); + return cints; + } + + var setStyle = function(n, style){ + n = dojo.byId(n); + if(!n || !n.style){ return; } + for(var s in style){ + if(s == "opacity"){ + dojo.html.setOpacity(n, style[s]); + }else{ + n.style[s] = style[s]; + } + } + } + + var propLine = function(properties){ + this._properties = properties; + this.diffs = new Array(properties.length); + dojo.lang.forEach(properties, function(prop, i){ + // calculate the end - start to optimize a bit + if(dojo.lang.isFunction(prop.start)){ + prop.start = prop.start(prop, i); + } + if(dojo.lang.isFunction(prop.end)){ + prop.end = prop.end(prop, i); + } + if(dojo.lang.isArray(prop.start)){ + // don't loop through the arrays + this.diffs[i] = null; + }else if(prop.start instanceof dojo.gfx.color.Color){ + // save these so we don't have to call toRgb() every getValue() call + prop.startRgb = prop.start.toRgb(); + prop.endRgb = prop.end.toRgb(); + }else{ + this.diffs[i] = prop.end - prop.start; + } + }, this); + + this.getValue = function(n){ + var ret = {}; + dojo.lang.forEach(this._properties, function(prop, i){ + var value = null; + if(dojo.lang.isArray(prop.start)){ + // FIXME: what to do here? + }else if(prop.start instanceof dojo.gfx.color.Color){ + value = (prop.units||"rgb") + "("; + for(var j = 0 ; j < prop.startRgb.length ; j++){ + value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : ""); + } + value += ")"; + }else{ + value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : ""); + } + ret[dojo.html.toCamelCase(prop.property)] = value; + }, this); + return ret; + } + } + + var anim = new dojo.lfx.Animation({ + beforeBegin: function(){ + setEmUp(targs); + anim.curve = new propLine(targs.propertyMap); + }, + onAnimate: function(propValues){ + dojo.lang.forEach(targs.nodes, function(node){ + setStyle(node, propValues); + }); + } + }, + targs.duration, + null, + targs.easing + ); + if(handlers){ + for(var x in handlers){ + if(dojo.lang.isFunction(handlers[x])){ + anim.connect(x, anim, handlers[x]); + } + } + } + + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html._makeFadeable = function(nodes){ + var makeFade = function(node){ + if(dojo.render.html.ie){ + // only set the zoom if the "tickle" value would be the same as the + // default + if( (node.style.zoom.length == 0) && + (dojo.html.getStyle(node, "zoom") == "normal") ){ + // make sure the node "hasLayout" + // NOTE: this has been tested with larger and smaller user-set text + // sizes and works fine + node.style.zoom = "1"; + // node.style.zoom = "normal"; + } + // don't set the width to auto if it didn't already cascade that way. + // We don't want to f anyones designs + if( (node.style.width.length == 0) && + (dojo.html.getStyle(node, "width") == "auto") ){ + node.style.width = "auto"; + } + } + } + if(dojo.lang.isArrayLike(nodes)){ + dojo.lang.forEach(nodes, makeFade); + }else{ + makeFade(nodes); + } +} + +dojo.lfx.html.fade = function(/*DOMNode[]*/ nodes, + /*Object*/values, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary:Returns an animation that will fade the "nodes" from the start to end values passed. + // nodes: An array of DOMNodes or one DOMNode. + // values: { start: Decimal?, end: Decimal? } + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var props = { property: "opacity" }; + if(!dj_undef("start", values)){ + props.start = values.start; + }else{ + props.start = function(){ return dojo.html.getOpacity(nodes[0]); }; + } + + if(!dj_undef("end", values)){ + props.end = values.end; + }else{ + dojo.raise("dojo.lfx.html.fade needs an end value"); + } + + var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing); + anim.connect("beforeBegin", function(){ + dojo.lfx.html._makeFadeable(nodes); + }); + if(callback){ + anim.connect("onEnd", function(){ callback(nodes, anim); }); + } + + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html.fadeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from its current opacity to fully opaque. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); // dojo.lfx.Animation +} + +dojo.lfx.html.fadeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from its current opacity to fully transparent. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); // dojo.lfx.Animation +} + +dojo.lfx.html.fadeShow = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from transparent to opaque and shows + // "nodes" at the end if it is hidden. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes=dojo.lfx.html._byId(nodes); + dojo.lang.forEach(nodes, function(node){ + dojo.html.setOpacity(node, 0.0); + }); + + var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback); + anim.connect("beforeBegin", function(){ + if(dojo.lang.isArrayLike(nodes)){ + dojo.lang.forEach(nodes, dojo.html.show); + }else{ + dojo.html.show(nodes); + } + }); + + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html.fadeHide = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will fade "nodes" from its current opacity to opaque and hides + // "nodes" at the end. + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){ + if(dojo.lang.isArrayLike(nodes)){ + dojo.lang.forEach(nodes, dojo.html.hide); + }else{ + dojo.html.hide(nodes); + } + if(callback){ callback(nodes, anim); } + }); + + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html.wipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will show and wipe in "nodes". + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + + dojo.lang.forEach(nodes, function(node){ + var oprop = { }; // old properties of node (before we mucked w/them) + + // get node height, either it's natural height or it's height specified via style or class attributes + // (for FF, the node has to be (temporarily) rendered to measure height) + dojo.html.show(node); + var height = dojo.html.getBorderBox(node).height; + dojo.html.hide(node); + + var anim = dojo.lfx.propertyAnimation(node, + { "height": { + start: 1, // 0 causes IE to display the whole panel + end: function(){ return height; } + } + }, + duration, + easing); + + anim.connect("beforeBegin", function(){ + oprop.overflow = node.style.overflow; + oprop.height = node.style.height; + with(node.style){ + overflow = "hidden"; + height = "1px"; // 0 causes IE to display the whole panel + } + dojo.html.show(node); + }); + + anim.connect("onEnd", function(){ + with(node.style){ + overflow = oprop.overflow; + height = oprop.height; + } + if(callback){ callback(node, anim); } + }); + anims.push(anim); + }); + + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.html.wipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will wipe out and hide "nodes". + // nodes: An array of DOMNodes or one DOMNode. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + + dojo.lang.forEach(nodes, function(node){ + var oprop = { }; // old properties of node (before we mucked w/them) + var anim = dojo.lfx.propertyAnimation(node, + { "height": { + start: function(){ return dojo.html.getContentBox(node).height; }, + end: 1 // 0 causes IE to display the whole panel + } + }, + duration, + easing, + { + "beforeBegin": function(){ + oprop.overflow = node.style.overflow; + oprop.height = node.style.height; + with(node.style){ + overflow = "hidden"; + } + dojo.html.show(node); + }, + + "onEnd": function(){ + dojo.html.hide(node); + with(node.style){ + overflow = oprop.overflow; + height = oprop.height; + } + if(callback){ callback(node, anim); } + } + } + ); + anims.push(anim); + }); + + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.html.slideTo = function(/*DOMNode*/ nodes, + /*Object*/ coords, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will slide "nodes" from its current position to + // the position defined in "coords". + // nodes: An array of DOMNodes or one DOMNode. + // coords: { top: Decimal?, left: Decimal? } + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + var compute = dojo.html.getComputedStyle; + + if(dojo.lang.isArray(coords)){ + /* coords: Array + pId: a */ + dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5'); + coords = { top: coords[0], left: coords[1] }; + } + dojo.lang.forEach(nodes, function(node){ + var top = null; + var left = null; + + var init = (function(){ + var innerNode = node; + return function(){ + var pos = compute(innerNode, 'position'); + top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); + left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); + + if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { + var ret = dojo.html.abs(innerNode, true); + dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); + top = ret.y; + left = ret.x; + } + } + })(); + init(); + + var anim = dojo.lfx.propertyAnimation(node, + { "top": { start: top, end: (coords.top||0) }, + "left": { start: left, end: (coords.left||0) } + }, + duration, + easing, + { "beforeBegin": init } + ); + + if(callback){ + anim.connect("onEnd", function(){ callback(nodes, anim); }); + } + + anims.push(anim); + }); + + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.html.slideBy = function(/*DOMNode*/ nodes, /*Object*/ coords, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ + // summary: Returns an animation that will slide "nodes" from its current position + // to its current position plus the numbers defined in "coords". + // nodes: An array of DOMNodes or one DOMNode. + // coords: { top: Decimal?, left: Decimal? } + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + var compute = dojo.html.getComputedStyle; + + if(dojo.lang.isArray(coords)){ + /* coords: Array + pId: a */ + dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5'); + coords = { top: coords[0], left: coords[1] }; + } + + dojo.lang.forEach(nodes, function(node){ + var top = null; + var left = null; + + var init = (function(){ + var innerNode = node; + return function(){ + var pos = compute(innerNode, 'position'); + top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); + left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); + + if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { + var ret = dojo.html.abs(innerNode, true); + dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); + top = ret.y; + left = ret.x; + } + } + })(); + init(); + + var anim = dojo.lfx.propertyAnimation(node, + { + "top": { start: top, end: top+(coords.top||0) }, + "left": { start: left, end: left+(coords.left||0) } + }, + duration, + easing).connect("beforeBegin", init); + + if(callback){ + anim.connect("onEnd", function(){ callback(nodes, anim); }); + } + + anims.push(anim); + }); + + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.html.explode = function(/*DOMNode*/ start, + /*DOMNode*/ endNode, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will + // start: + // endNode: + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + var h = dojo.html; + start = dojo.byId(start); + endNode = dojo.byId(endNode); + var startCoords = h.toCoordinateObject(start, true); + var outline = document.createElement("div"); + h.copyStyle(outline, endNode); + if (endNode.explodeClassName) { outline.className = endNode.explodeClassName; } + with(outline.style){ + position = "absolute"; + display = "none"; + // border = "1px solid black"; + } + dojo.body().appendChild(outline); + + with(endNode.style){ + visibility = "hidden"; + display = "block"; + } + var endCoords = h.toCoordinateObject(endNode, true); + with(endNode.style){ + display = "none"; + visibility = "visible"; + } + + var props = { opacity: { start: 0.5, end: 1.0 } }; + dojo.lang.forEach(["height", "width", "top", "left"], function(type){ + props[type] = { start: startCoords[type], end: endCoords[type] } + }); + + var anim = new dojo.lfx.propertyAnimation(outline, + props, + duration, + easing, + { + "beforeBegin": function(){ + h.setDisplay(outline, "block"); + }, + "onEnd": function(){ + h.setDisplay(endNode, "block"); + outline.parentNode.removeChild(outline); + } + } + ); + + if(callback){ + anim.connect("onEnd", function(){ callback(endNode, anim); }); + } + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html.implode = function(/*DOMNode*/ startNode, + /*DOMNode*/ end, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will + // startNode: + // end: + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + var h = dojo.html; + startNode = dojo.byId(startNode); + end = dojo.byId(end); + var startCoords = dojo.html.toCoordinateObject(startNode, true); + var endCoords = dojo.html.toCoordinateObject(end, true); + + var outline = document.createElement("div"); + dojo.html.copyStyle(outline, startNode); + if (startNode.explodeClassName) { outline.className = startNode.explodeClassName; } + dojo.html.setOpacity(outline, 0.3); + with(outline.style){ + position = "absolute"; + display = "none"; + backgroundColor = h.getStyle(startNode, "background-color").toLowerCase(); + } + dojo.body().appendChild(outline); + + var props = { opacity: { start: 1.0, end: 0.5 } }; + dojo.lang.forEach(["height", "width", "top", "left"], function(type){ + props[type] = { start: startCoords[type], end: endCoords[type] } + }); + + var anim = new dojo.lfx.propertyAnimation(outline, + props, + duration, + easing, + { + "beforeBegin": function(){ + dojo.html.hide(startNode); + dojo.html.show(outline); + }, + "onEnd": function(){ + outline.parentNode.removeChild(outline); + } + } + ); + + if(callback){ + anim.connect("onEnd", function(){ callback(startNode, anim); }); + } + return anim; // dojo.lfx.Animation +} + +dojo.lfx.html.highlight = function(/*DOMNode[]*/ nodes, + /*dojo.gfx.color.Color*/ startColor, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will set the background color + // of "nodes" to startColor and transition it to "nodes" + // original color. + // startColor: Color to transition from. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + + dojo.lang.forEach(nodes, function(node){ + var color = dojo.html.getBackgroundColor(node); + var bg = dojo.html.getStyle(node, "background-color").toLowerCase(); + var bgImage = dojo.html.getStyle(node, "background-image"); + var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)"); + while(color.length > 3) { color.pop(); } + + var rgb = new dojo.gfx.color.Color(startColor); + var endRgb = new dojo.gfx.color.Color(color); + + var anim = dojo.lfx.propertyAnimation(node, + { "background-color": { start: rgb, end: endRgb } }, + duration, + easing, + { + "beforeBegin": function(){ + if(bgImage){ + node.style.backgroundImage = "none"; + } + node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")"; + }, + "onEnd": function(){ + if(bgImage){ + node.style.backgroundImage = bgImage; + } + if(wasTransparent){ + node.style.backgroundColor = "transparent"; + } + if(callback){ + callback(node, anim); + } + } + } + ); + + anims.push(anim); + }); + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lfx.html.unhighlight = function(/*DOMNode[]*/ nodes, + /*dojo.gfx.color.Color*/ endColor, + /*int?*/ duration, + /*Function?*/ easing, + /*Function?*/ callback){ + // summary: Returns an animation that will transition "nodes" background color + // from its current color to "endColor". + // endColor: Color to transition to. + // duration: Duration of the animation in milliseconds. + // easing: An easing function. + // callback: Function to run at the end of the animation. + nodes = dojo.lfx.html._byId(nodes); + var anims = []; + + dojo.lang.forEach(nodes, function(node){ + var color = new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node)); + var rgb = new dojo.gfx.color.Color(endColor); + + var bgImage = dojo.html.getStyle(node, "background-image"); + + var anim = dojo.lfx.propertyAnimation(node, + { "background-color": { start: color, end: rgb } }, + duration, + easing, + { + "beforeBegin": function(){ + if(bgImage){ + node.style.backgroundImage = "none"; + } + node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")"; + }, + "onEnd": function(){ + if(callback){ + callback(node, anim); + } + } + } + ); + anims.push(anim); + }); + return dojo.lfx.combine(anims); // dojo.lfx.Combine +} + +dojo.lang.mixin(dojo.lfx, dojo.lfx.html); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/rounded.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/Attic/rounded.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/lfx/rounded.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,512 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.lfx.rounded"); + +dojo.require("dojo.lang.common"); +dojo.require("dojo.html.common"); +dojo.require("dojo.html.style"); +dojo.require("dojo.html.display"); +dojo.require("dojo.html.layout"); + +/* Port of curvyCorners, by Cameron Cooke and Tim Hutchison. + * Original port done by Brian Lucas. + * Refactor and function by trt. + */ +dojo.lfx.rounded = function(/* object */settings /* ... */){ + // summary + // Creates a set of rounded corners based on settings. + var options={ + validTags:settings.validTags || ["div"], // tags we can apply this to + autoPad:settings.autoPad!=null ? settings.autoPad : true, // automatically pad + antiAlias:settings.antiAlias!=null ? settings.antiAlias : true, // anti-alias corners + radii:{ // corner radii + tl:(settings.tl && settings.tl.radius!=null) ? settings.tl.radius:5, + tr:(settings.tr && settings.tr.radius!=null) ? settings.tr.radius:5, + bl:(settings.bl && settings.bl.radius!=null) ? settings.bl.radius:5, + br:(settings.br && settings.br.radius!=null) ? settings.br.radius:5 + } + }; + + // get the node list to operate on. + var nodes; + if(typeof(arguments[1]) == "string"){ + // a CSS classname was passed, grab a node list. + nodes=dojo.html.getElementsByClass(arguments[1]); + } else if(dojo.lang.isArrayLike(arguments[1])){ + // we assume that the second argument is an array of nodes to apply this to. + nodes=arguments[1]; + for(var i=0; i0){ + node.innerHTML=""; + } + + var topHeight=Math.max(options.radii.tl, options.radii.tr); + var bottomHeight=Math.max(options.radii.bl, options.radii.br); + + // build the containers. + if(options.radii.tl || options.radii.tr){ + top = document.createElement("div"); + top.style.width="100%"; + top.style.fontSize="1px"; + top.style.overflow="hidden"; + top.style.position="absolute"; + top.style.paddingLeft=format.borderWidth+"px"; + top.style.paddingRight=format.borderWidth+"px"; + top.style.height=topHeight+"px"; + top.style.top=(0-topHeight)+"px"; + top.style.left=(0-format.borderWidth)+"px"; + node.appendChild(top); + } + if(options.radii.bl || options.radii.br){ // bottom + bottom = document.createElement("div"); + bottom.style.width="100%"; + bottom.style.fontSize="1px"; + bottom.style.overflow="hidden"; + bottom.style.position="absolute"; + bottom.style.paddingLeft=format.borderWidth+"px"; + bottom.style.paddingRight=format.borderWidth+"px"; + bottom.style.height=bottomHeight+"px"; + bottom.style.bottom=(0-bottomHeight)+"px"; + bottom.style.left=(0-format.borderWidth)+"px"; + node.appendChild(bottom); + } + + // turn off the borders + if(top){ node.style.borderTopWidth = "0px"; } + if(bottom){ node.style.borderBottomWidth = "0px"; } + + // do the corners + var corners = ["tr", "tl", "br", "bl"]; + for(var i=0; i= borderRadius){ var y1=-1; } + var y2=Math.ceil(Math.sqrt(Math.pow(borderRadius,2)-Math.pow(x,2))); + if(x >= borderRadius){ y2=-1; } + var y3=Math.floor(Math.sqrt(Math.pow(j,2)-Math.pow((x+1),2)))-1; + if((x+1) >= j){ y3=-1; } + var y4=Math.ceil(Math.sqrt(Math.pow(j, 2)-Math.pow(x, 2))); + if(x >= j){ y4=-1; } + + // start drawing + if(y1 > -1){ + fns.draw(x, 0, format.color, 100, (y1+1), corner, -1, j, topHeight, format); + } + + // cycle the y-axis + for(var y=(y1+1); y= y2){ + if(y2 == -1){ y2 = 0; } + fns.draw(x, y2, format.borderColor, 100, (y3-y2+1), corner, 0, 0, topHeight, format) + } else { + if(y3 >= y1){ + fns.draw(x, (y1+1), format.borderColor, 100, (y3-y1), corner, 0, 0, topHeight, format); + } + } + for(var y=(y3+1); y0 ? 0:-1), options.radii[cc], topHeight, format); + } + } else { + y3=y1; + } + } + + // reposition pixels if not the bottom right. + if(cc != "br"){ + for(var t=0, k=corner.childNodes.length; t0){ + var content=document.createElement("div"); + content.style.position="relative"; + content.innerHTML=format.content; + content.className="autoPadDiv"; + if(topHeight < format.padding){ + content.style.paddingTop = Math.abs(topHeight-format.padding)+"px"; + } + if(bottomHeight < format.padding){ + content.style.paddingBottom = Math.abs(bottomHeight-format.padding)+"px"; + } + content.style.paddingLeft=format.padding+"px"; + content.style.paddingRight=format.padding+"px"; + node.appendChild(content); + } +}; + +var count=0; + +// helper methods. +dojo.lfx.rounded._fns={ + blend:function(clr1, clr2, frac){ + var c1={ + r:parseInt(clr1.substr(1,2),16), + g:parseInt(clr1.substr(3,2),16), + b:parseInt(clr1.substr(5,2),16) + }; + var c2={ + r:parseInt(clr2.substr(1,2),16), + g:parseInt(clr2.substr(3,2),16), + b:parseInt(clr2.substr(5,2),16) + }; + if(frac>1||frac<0){ frac=1; } + var ret=[ + Math.min(Math.max(Math.round((c1.r*frac)+(c2.r*(1-frac))),0),255), + Math.min(Math.max(Math.round((c1.g*frac)+(c2.g*(1-frac))),0),255), + Math.min(Math.max(Math.round((c1.b*frac)+(c2.b*(1-frac))),0),255) + ]; + for(var i=0; i=y && intersect < (y+1)){ + whatsides="Left"; + xval[point]=0; + yval[point++]=intersect-y; + } + + intersect=Math.sqrt((Math.pow(r,2)-Math.pow(y+1,2))); + if(intersect >=x && intersect < (x+1)){ + whatsides += "Top"; + xval[point]=intersect-x; + yval[point++]=1; + } + + intersect=Math.sqrt((Math.pow(r,2)-Math.pow(x+1,2))); + if(intersect >= y && intersect < (y+1)){ + whatsides += "Right"; + xval[point]=1; + yval[point++] = intersect-y; + } + + intersect=Math.sqrt((Math.pow(r,2)-Math.pow(y,2))); + if(intersect >=x && intersect < (x+1)){ + whatsides += "Bottom"; + xval[point]=intersect-x; + yval[point]=1; + } + + switch(whatsides){ + case "LeftRight": + return Math.min(yval[0],yval[1]) + ((Math.max(yval[0],yval[1])-Math.min(yval[0],yval[1]))/2); + case "TopRight": + return 1-(((1-xval[0])*(1-yval[1]))/2); + case "TopBottom": + return Math.min(xval[0],xval[1]) + ((Math.max(xval[0],xval[1])-Math.min(xval[0],xval[1]))/2); + case "LeftBottom": + return (yval[0]*xval[1])/2; + default: return 1; + } + }, + draw:function(x, y, color, opac, height, corner, image, radius, top, format){ + var px=document.createElement("div"); + px.style.height=height+"px" + px.style.width="1px"; + px.style.position="absolute"; + px.style.fontSize="1px"; + px.style.overflow="hidden"; + if(image==-1 && format.bgImage!=""){ + px.style.backgroundImage=format.bgImage; + px.style.backgroundPosition="-"+(format.width-(radius-x)+format.borderWidth) + +"px -"+((format.height+top+y)-format.borderWidth)+"px"; + } else { + px.style.backgroundColor=color; + } + if(opac!=100){ dojo.html.setOpacity(px, (opac/100)); } + px.style.top=y+"px"; + px.style.left=x+"px"; + corner.appendChild(px); + }, + getRGB:function(clr){ + var ret="#ffffff"; + if(clr!="" && clr!="transparent"){ + if(clr.substr(0,3)=="rgb"){ + var t=clr.substring(4, clr.indexOf(")")); + t=t.split(","); + for(var i=0; i 0){ + this[funcName].call(this, logStr, record.msgArgs); + } else { + this[funcName].call(this, logStr); + } + + this.data.push(record); + if(this.numRecords != -1){ + while(this.data.length>this.numRecords){ + this.data.shift(); + } + } + } +}); + +if(!dj_undef("console") && !dj_undef("info", console)){ +dojo.lang.extend(dojo.logging.MemoryLogHandler,{ + debug:function(){ + console.debug.apply(this, arguments); + }, + info:function(){ + console.info.apply(this, arguments); + }, + warn:function(){ + console.warn.apply(this, arguments); + }, + error:function(){ + console.error.apply(this, arguments); + }, + critical:function(){ + console.error.apply(this, arguments); + } +}); + +dojo.lang.extend(dojo.logging.Logger,{ + exception: function(msg, e, squelch){ + var args=[msg]; + + if(e){ + msg+=" : "+ e.name + " " + (e.description||e.message); + args.push(e); + } + + this.logType("ERROR", args); + if(!squelch){ + throw e; + } + } +}); + +} Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/Logger.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/Attic/Logger.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/Logger.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,387 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +/* This is the dojo logging facility, which is imported from nWidgets + (written by Alex Russell, CLA on file), which is patterned on the + Python logging module, which in turn has been heavily influenced by + log4j (execpt with some more pythonic choices, which we adopt as well). + + While the dojo logging facilities do provide a set of familiar + interfaces, many of the details are changed to reflect the constraints + of the browser environment. Mainly, file and syslog-style logging + facilites are not provided, with HTTP POST and GET requests being the + only ways of getting data from the browser back to a server. Minimal + support for this (and XML serialization of logs) is provided, but may + not be of practical use in a deployment environment. + + The Dojo logging classes are agnostic of any environment, and while + default loggers are provided for browser-based interpreter + environments, this file and the classes it define are explicitly + designed to be portable to command-line interpreters and other + ECMA-262v3 envrionments. + + the logger needs to accomidate: + log "levels" + type identifiers + file? + message + tic/toc? + + The logger should ALWAYS record: + time/date logged + message + type + level +*/ +// TODO: conver documentation to javadoc style once we confirm that is our choice +// TODO: define DTD for XML-formatted log messages +// TODO: write XML Formatter class +// TODO: write HTTP Handler which uses POST to send log lines/sections + +// Filename: LogCore.js +// Purpose: a common logging infrastructure for dojo +// Classes: dojo.logging, dojo.logging.Logger, dojo.logging.Record, dojo.logging.LogFilter +// Global Objects: dojo.logging +// Dependencies: none + +dojo.provide("dojo.logging.Logger"); +dojo.require("dojo.lang.common"); + +/* + A simple data structure class that stores information for and about + a logged event. Objects of this type are created automatically when + an event is logged and are the internal format in which information + about log events is kept. +*/ + +dojo.logging.Record = function(lvl, msg){ + this.level = lvl; + this.message = ""; + this.msgArgs = []; + this.time = new Date(); + + if(dojo.lang.isArray(msg)){ + if(msg.length > 0 && dojo.lang.isString(msg[0])){ + this.message=msg.shift(); + } + this.msgArgs=msg; + }else{ + this.message=msg; + } + // FIXME: what other information can we receive/discover here? +} + +// an empty parent (abstract) class which concrete filters should inherit from. +dojo.logging.LogFilter = function(loggerChain){ + this.passChain = loggerChain || ""; + this.filter = function(record){ + // FIXME: need to figure out a way to enforce the loggerChain + // restriction + return true; // pass all records + } +} + +dojo.logging.Logger = function(){ + this.cutOffLevel = 0; + this.propagate = true; + this.parent = null; + // storage for dojo.logging.Record objects seen and accepted by this logger + this.data = []; + this.filters = []; + this.handlers = []; +} + +dojo.extend(dojo.logging.Logger,{ + argsToArr: function(args){ + // utility function, reproduced from __util__ here to remove dependency + var ret = []; + for(var x=0; x= this.cutOffLevel; + }, + + getEffectiveLevel: function(){ + if((this.cutOffLevel==0)&&(this.parent)){ + return this.parent.getEffectiveLevel(); + } + return this.cutOffLevel; + }, + + addFilter: function(flt){ + this.filters.push(flt); + return this.filters.length-1; + }, + + removeFilterByIndex: function(fltIndex){ + if(this.filters[fltIndex]){ + delete this.filters[fltIndex]; + return true; + } + return false; + }, + + removeFilter: function(fltRef){ + for(var x=0; x=this.cutOffLevel)){ + this.parent.log(lvl, msg); + return false; + } + // FIXME: need to call logging providers here! + this.handle(new dojo.logging.Record(lvl, msg)); + return true; + }, + + // logger helpers + debug:function(msg){ + return this.logType("DEBUG", this.argsToArr(arguments)); + }, + + info: function(msg){ + return this.logType("INFO", this.argsToArr(arguments)); + }, + + warning: function(msg){ + return this.logType("WARNING", this.argsToArr(arguments)); + }, + + error: function(msg){ + return this.logType("ERROR", this.argsToArr(arguments)); + }, + + critical: function(msg){ + return this.logType("CRITICAL", this.argsToArr(arguments)); + }, + + exception: function(msg, e, squelch){ + // FIXME: this needs to be modified to put the exception in the msg + // if we're on Moz, we can get the following from the exception object: + // lineNumber + // message + // fileName + // stack + // name + // on IE, we get: + // name + // message (from MDA?) + // number + // description (same as message!) + if(e){ + var eparts = [e.name, (e.description||e.message)]; + if(e.fileName){ + eparts.push(e.fileName); + eparts.push("line "+e.lineNumber); + // eparts.push(e.stack); + } + msg += " "+eparts.join(" : "); + } + + this.logType("ERROR", msg); + if(!squelch){ + throw e; + } + }, + + logType: function(type, args){ + return this.log.apply(this, [dojo.logging.log.getLevel(type), + args]); + }, + + warn:function(){ + this.warning.apply(this,arguments); + }, + err:function(){ + this.error.apply(this,arguments); + }, + crit:function(){ + this.critical.apply(this,arguments); + } +}); + +// the Handler class +dojo.logging.LogHandler = function(level){ + this.cutOffLevel = (level) ? level : 0; + this.formatter = null; // FIXME: default formatter? + this.data = []; + this.filters = []; +} +dojo.lang.extend(dojo.logging.LogHandler,{ + + setFormatter:function(formatter){ + dojo.unimplemented("setFormatter"); + }, + + flush:function(){}, + close:function(){}, + handleError:function(){}, + + handle:function(record){ + if((this.filter(record))&&(record.level>=this.cutOffLevel)){ + this.emit(record); + } + }, + + emit:function(record){ + dojo.unimplemented("emit"); + } +}); + +// set aliases since we don't want to inherit from dojo.logging.Logger +void(function(){ // begin globals protection closure + var names = [ + "setLevel", "addFilter", "removeFilterByIndex", "removeFilter", + "removeAllFilters", "filter" + ]; + var tgt = dojo.logging.LogHandler.prototype; + var src = dojo.logging.Logger.prototype; + for(var x=0; xthis.numRecords){ + this.data.shift(); + } + } + } +}); + +dojo.logging.logQueueHandler = new dojo.logging.MemoryLogHandler(0,50,0,10000); + +dojo.logging.log.addHandler(dojo.logging.logQueueHandler); +dojo.log = dojo.logging.log; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/logging/__package__.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,15 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [["dojo.logging.Logger", false, false]], + rhino: ["dojo.logging.RhinoLogger"] +}); +dojo.provide("dojo.logging.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/__package__.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/Attic/__package__.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/__package__.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,18 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.kwCompoundRequire({ + common: [ + ["dojo.math", false, false], + ["dojo.math.curves", false, false], + ["dojo.math.points", false, false] + ] +}); +dojo.provide("dojo.math.*"); Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/curves.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/Attic/curves.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/curves.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,242 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.math.curves"); +dojo.require("dojo.math"); + +/* Curves from Dan's 13th lib stuff. + * See: http://pupius.co.uk/js/Toolkit.Drawing.js + * http://pupius.co.uk/dump/dojo/Dojo.Math.js + */ + +dojo.math.curves = { + Line: function(/* array */start, /* array */end) { + // summary + // Creates a straight line object + this.start = start; + this.end = end; + this.dimensions = start.length; + + for(var i = 0; i < start.length; i++) { + start[i] = Number(start[i]); + } + + for(var i = 0; i < end.length; i++) { + end[i] = Number(end[i]); + } + + //simple function to find point on an n-dimensional, straight line + this.getValue = function(/* float */n){ + // summary + // Returns the point at point N (in terms of percentage) on this line. + var retVal = new Array(this.dimensions); + for(var i=0;i= 1) return this.p[this.p.length-1]; // if step>=1 we must be at the end of the curve + if(step <= 0) return this.p[0]; // if step<=0 we must be at the start of the curve + var retVal = new Array(this.p[0].length); + for(var k=0;j= this.p.length) i1 = this.p.length-1; + var i2 = node+2; if(i2 >= this.p.length) i2 = this.p.length-1; + + var u = progress; + var u2 = progress*progress; + var u3 = progress*progress*progress; + + var retVal = new Array(this.p[0].length); + for(var k=0;k 2D point for center of arc + // radius => scalar quantity for radius of arc + // start => to define an arc specify start angle (default: 0) + // end => to define an arc specify start angle + this.center = center; + this.radius = radius; + this.start = start || 0; + this.end = end; + + this.getValue = function(/* float */n) { + // summary + // Returns the point at point N (in terms of percentage) on this curve. + var retVal = new Array(2); + var theta = dojo.math.degToRad(this.start+((this.end-this.start)*n)); + + retVal[0] = this.center[0] + this.radius*Math.sin(theta); + retVal[1] = this.center[1] - this.radius*Math.cos(theta); + + return retVal; // array + } + + return this; // dojo.math.curves.CenteredArc + }, + + Circle : function(/* array */center, /* float */radius) { + // summary + // Special case of Arc (start = 0, end = 360) + dojo.math.curves.CenteredArc.call(this, center, radius, 0, 360); + return this; // dojo.math.curves.Circle + }, + + Path : function() { + // summary + // Generic path shape, created from curve segments + var curves = []; + var weights = []; + var ranges = []; + var totalWeight = 0; + + this.add = function(/* dojo.math.curves.* */curve, /* float */weight) { + // summary + // Add a curve segment to this path + if( weight < 0 ) { dojo.raise("dojo.math.curves.Path.add: weight cannot be less than 0"); } + curves.push(curve); + weights.push(weight); + totalWeight += weight; + computeRanges(); + } + + this.remove = function(/* dojo.math.curves.* */curve) { + // summary + // Remove a curve segment from this path + for(var i = 0; i < curves.length; i++) { + if( curves[i] == curve ) { + curves.splice(i, 1); + totalWeight -= weights.splice(i, 1)[0]; + break; + } + } + computeRanges(); + } + + this.removeAll = function() { + // summary + // Remove all curve segments + curves = []; + weights = []; + totalWeight = 0; + } + + this.getValue = function(/* float */n) { + // summary + // Returns the point at point N (in terms of percentage) on this curve. + var found = false, value = 0; + for(var i = 0; i < ranges.length; i++) { + var r = ranges[i]; + //w(r.join(" ... ")); + if( n >= r[0] && n < r[1] ) { + var subN = (n - r[0]) / r[2]; + value = curves[i].getValue(subN); + found = true; + break; + } + } + + // FIXME: Do we want to assume we're at the end? + if( !found ) { + value = curves[curves.length-1].getValue(1); + } + + for(var j = 0; j < i; j++) { + value = dojo.math.points.translate(value, curves[j].getValue(1)); + } + return value; // array + } + + function computeRanges() { + var start = 0; + for(var i = 0; i < weights.length; i++) { + var end = start + weights[i] / totalWeight; + var len = end - start; + ranges[i] = [start, end, len]; + start = end; + } + } + + return this; // dojo.math.curves.Path + } +}; Index: openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/matrix.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/Attic/matrix.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/resources/dojo-ajax/src/math/matrix.js 6 Nov 2006 14:50:10 -0000 1.1 @@ -0,0 +1,377 @@ +/* + Copyright (c) 2004-2006, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +dojo.provide("dojo.math.matrix"); + +// some of this code is based on +// http://www.mkaz.com/math/MatrixCalculator.java +// (published under a BSD Open Source License) +// +// the rest is from my vague memory of matricies in school [cal] +// +// the copying of arguments is a little excessive, and could be trimmed back in +// the case where a function doesn't modify them at all (but some do!) +// +// 2006-06-25: Some enhancements submitted by Erel Segal: +// * addition: a tolerance constant for determinant calculations. +// * performance fix: removed unnecessary argument copying. +// * addition: function "product" for multiplying more than 2 matrices +// * addition: function "sum" for adding any number of matrices +// * bug fix: inversion of a 1x1 matrix without using the adjoint +// * performance fixes: upperTriangle +// * addition: argument "value" to function create, to initialize the matrix with a custom val +// * addition: functions "ones" and "zeros" - like Matlab[TM] functions with the same name. +// * addition: function "identity" for creating an identity matrix of a given size. +// * addition: argument "decimal_points" to function format +// * bug fix: adjoint of a 0-size matrix +// * performance fixes: adjoint +// + +dojo.math.matrix.iDF = 0; + +// Erel: values lower than this value are considered zero (in detereminant calculations). +// It is analogous to Maltab[TM]'s "eps". +dojo.math.matrix.ALMOST_ZERO = 1e-10; +dojo.math.matrix.multiply = function(a, b){ + var ay = a.length; + var ax = a[0].length; + var by = b.length; + var bx = b[0].length; + + if (ax != by){ + dojo.debug("Can't multiply matricies of sizes "+ax+','+ay+' and '+bx+','+by); + return [[0]]; + } + + var c = []; + for(var k=0; k0? a[0].length: 0; + var buffer = ''; + for (var y=0; y