";
+var _d=p.firstChild;
+_2.body().appendChild(_d);
+var _e=_2.contentBox(_d).h;
+_2.style(_d,"overflow","scroll");
+var _f=_e-_2.contentBox(_d).h;
+_2.destroy(_d);
+this.getScrollWidth=function(){
+return _f;
+};
+return _f;
+}});
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/Canvas.js.uncompressed.js b/js/libs/dojox/drawing/manager/Canvas.js.uncompressed.js
new file mode 100644
index 0000000..5db1a25
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Canvas.js.uncompressed.js
@@ -0,0 +1,165 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/Canvas", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.Canvas");
+
+(function(){
+
+ dojox.drawing.manager.Canvas = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx.surface to be used for Drawing. Note that
+ // The 'surface' that Drawing uses is actually a dojox.gfx.group.
+ // This allows for more versatility.
+ //
+ // Called internally from a dojox.Drawing.
+ //
+ // Note: Surface creation is asynchrous. Connect to
+ // onSurfaceReady in Drawing.
+ //
+ function(/*Object*/options){
+ dojo.mixin(this, options);
+
+ var dim = dojo.contentBox(this.srcRefNode);
+ this.height = this.parentHeight = dim.h;
+ this.width = this.parentWidth = dim.w;
+ this.domNode = dojo.create("div", {id:"canvasNode"}, this.srcRefNode);
+ dojo.style(this.domNode, {
+ width:this.width,
+ height:"auto"
+ });
+
+ dojo.setSelectable(this.domNode, false);
+
+ this.id = this.id || this.util.uid("surface");
+
+ console.info("create canvas");
+ this.gfxSurface = dojox.gfx.createSurface(this.domNode, this.width, this.height);
+ this.gfxSurface.whenLoaded(this, function(){
+ setTimeout(dojo.hitch(this, function(){
+ this.surfaceReady = true;
+ if(dojo.isIE){
+ //this.gfxSurface.rawNode.parentNode.id = this.id;
+ }else if(dojox.gfx.renderer == "silverlight"){
+ this.id = this.domNode.firstChild.id
+ }else{
+ //this.gfxSurface.rawNode.id = this.id;
+ }
+
+ this.underlay = this.gfxSurface.createGroup();
+ this.surface = this.gfxSurface.createGroup();
+ this.overlay = this.gfxSurface.createGroup();
+ this.surface.setTransform({dx:0, dy:0,xx:1,yy:1});
+
+ this.gfxSurface.getDimensions = dojo.hitch(this.gfxSurface, "getDimensions");
+ if(options.callback){
+ options.callback(this.domNode);
+ }
+ }),500);
+ });
+ this._mouseHandle = this.mouse.register(this);
+ },
+ {
+ // zoom: [readonly] Number
+ // The amount the canvas is zoomed
+ zoom:1,
+
+ useScrollbars: true,
+ baseClass:"drawingCanvas",
+
+ resize: function(width, height){
+ // summary:
+ // Method used to change size of canvas. Potentially
+ // called from a container like ContentPane. May be
+ // called directly.
+ //
+ this.parentWidth = width;
+ this.parentHeight = height;
+ this.setDimensions(width, height);
+ },
+
+ setDimensions: function(width, height, scrollx, scrolly){
+ // summary:
+ // Internal. Changes canvas size and sets scroll position.
+ // Do not call this, use resize().
+ //
+ // changing the size of the surface and setting scroll
+ // if items are off screen
+ var sw = this.getScrollWidth(); //+ 10;
+ this.width = Math.max(width, this.parentWidth);
+ this.height = Math.max(height, this.parentHeight);
+
+ if(this.height>this.parentHeight){
+ this.width -= sw;
+ }
+ if(this.width>this.parentWidth){
+ this.height -= sw;
+ }
+
+ this.mouse.resize(this.width,this.height);
+ this.gfxSurface.setDimensions(this.width, this.height);
+
+
+ this.domNode.parentNode.scrollTop = scrolly || 0;
+ this.domNode.parentNode.scrollLeft = scrollx || 0;
+
+
+ if(this.useScrollbars){
+ //console.info("Set Canvas Scroll", (this.height > this.parentHeight), this.height, this.parentHeight)
+ dojo.style(this.domNode.parentNode, {
+ overflowY: this.height > this.parentHeight ? "scroll" : "hidden",
+ overflowX: this.width > this.parentWidth ? "scroll" : "hidden"
+ });
+ }else{
+ dojo.style(this.domNode.parentNode, {
+ overflowY: "hidden",
+ overflowX: "hidden"
+ });
+ }
+ },
+
+
+ setZoom: function(zoom){
+ // summary:
+ // Internal. Zooms canvas in and out.
+ this.zoom = zoom;
+ this.surface.setTransform({xx:zoom, yy:zoom});
+ this.setDimensions(this.width*zoom, this.height*zoom)
+ },
+
+ onScroll: function(){
+ // summary:
+ // Event fires on scroll.NOT IMPLEMENTED
+ },
+
+ getScrollOffset: function(){
+ // summary:
+ // Get the scroll position of the canvas
+ return {
+ top:this.domNode.parentNode.scrollTop,
+ left:this.domNode.parentNode.scrollLeft
+ }; // Object
+ },
+
+ getScrollWidth: function(){
+ // summary:
+ // Special method used to detect the width (and height)
+ // of the browser scrollbars. Becomes memoized.
+ //
+ var p = dojo.create('div');
+ p.innerHTML = '
';
+ var div = p.firstChild;
+ dojo.body().appendChild(div);
+ var noscroll = dojo.contentBox(div).h;
+ dojo.style(div, "overflow", "scroll");
+ var scrollWidth = noscroll - dojo.contentBox(div).h;
+ dojo.destroy(div);
+ this.getScrollWidth = function(){
+ return scrollWidth;
+ };
+ return scrollWidth; // Object
+ }
+ }
+ );
+
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/Mouse.js b/js/libs/dojox/drawing/manager/Mouse.js
new file mode 100644
index 0000000..7654f7f
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Mouse.js
@@ -0,0 +1,211 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager.Mouse");
+_3.drawing.manager.Mouse=_3.drawing.util.oo.declare(function(_4){
+this.util=_4.util;
+this.keys=_4.keys;
+this.id=_4.id||this.util.uid("mouse");
+this.currentNodeId="";
+this.registered={};
+},{doublClickSpeed:400,_lastx:0,_lasty:0,__reg:0,_downOnCanvas:false,init:function(_5){
+this.container=_5;
+this.setCanvas();
+var c;
+var _6=false;
+_2.connect(this.container,"rightclick",this,function(_7){
+console.warn("RIGHTCLICK");
+});
+_2.connect(document.body,"mousedown",this,function(_8){
+});
+_2.connect(this.container,"mousedown",this,function(_9){
+this.down(_9);
+if(_9.button!=_2.mouseButtons.RIGHT){
+_6=true;
+c=_2.connect(document,"mousemove",this,"drag");
+}
+});
+_2.connect(document,"mouseup",this,function(_a){
+_2.disconnect(c);
+_6=false;
+this.up(_a);
+});
+_2.connect(document,"mousemove",this,function(_b){
+if(!_6){
+this.move(_b);
+}
+});
+_2.connect(this.keys,"onEsc",this,function(_c){
+this._dragged=false;
+});
+},setCanvas:function(){
+var _d=_2.coords(this.container.parentNode);
+this.origin=_2.clone(_d);
+},scrollOffset:function(){
+return {top:this.container.parentNode.scrollTop,left:this.container.parentNode.scrollLeft};
+},resize:function(_e,_f){
+if(this.origin){
+this.origin.w=_e;
+this.origin.h=_f;
+}
+},register:function(_10){
+var _11=_10.id||"reg_"+(this.__reg++);
+if(!this.registered[_11]){
+this.registered[_11]=_10;
+}
+return _11;
+},unregister:function(_12){
+if(!this.registered[_12]){
+return;
+}
+delete this.registered[_12];
+},_broadcastEvent:function(_13,obj){
+for(var nm in this.registered){
+if(this.registered[nm][_13]){
+this.registered[nm][_13](obj);
+}
+}
+},onDown:function(obj){
+this._broadcastEvent(this.eventName("down"),obj);
+},onDrag:function(obj){
+var nm=this.eventName("drag");
+if(this._selected&&nm=="onDrag"){
+nm="onStencilDrag";
+}
+this._broadcastEvent(nm,obj);
+},onMove:function(obj){
+this._broadcastEvent("onMove",obj);
+},overName:function(obj,evt){
+var nm=obj.id.split(".");
+evt=evt.charAt(0).toUpperCase()+evt.substring(1);
+if(nm[0]=="dojox"&&(_3.drawing.defaults.clickable||!_3.drawing.defaults.clickMode)){
+return "onStencil"+evt;
+}else{
+return "on"+evt;
+}
+},onOver:function(obj){
+this._broadcastEvent(this.overName(obj,"over"),obj);
+},onOut:function(obj){
+this._broadcastEvent(this.overName(obj,"out"),obj);
+},onUp:function(obj){
+var nm=this.eventName("up");
+if(nm=="onStencilUp"){
+this._selected=true;
+}else{
+if(this._selected&&nm=="onUp"){
+nm="onStencilUp";
+this._selected=false;
+}
+}
+this._broadcastEvent(nm,obj);
+if(_3.gfx.renderer=="silverlight"){
+return;
+}
+this._clickTime=new Date().getTime();
+if(this._lastClickTime){
+if(this._clickTime-this._lastClickTime
=0&&y>=0&&x<=o.w&&y<=o.h;
+x*=this.zoom;
+y*=this.zoom;
+o.startx=x;
+o.starty=y;
+this._lastx=x;
+this._lasty=y;
+this.drawingType=this.util.attr(evt,"drawingType")||"";
+var id=this._getId(evt);
+if(evt.button==_2.mouseButtons.RIGHT&&this.id=="mse"){
+}else{
+evt.preventDefault();
+_2.stopEvent(evt);
+}
+this.onDown({mid:this.id,x:x,y:y,pageX:dim.x,pageY:dim.y,withinCanvas:_17,id:id});
+},over:function(obj){
+this.onOver(obj);
+},out:function(obj){
+this.onOut(obj);
+},move:function(evt){
+var obj=this.create(evt);
+if(this.id=="MUI"){
+}
+if(obj.id!=this.currentNodeId){
+var _18={};
+for(var nm in obj){
+_18[nm]=obj[nm];
+}
+_18.id=this.currentNodeId;
+this.currentNodeId&&this.out(_18);
+obj.id&&this.over(obj);
+this.currentNodeId=obj.id;
+}
+this.onMove(obj);
+},drag:function(evt){
+this.onDrag(this.create(evt,true));
+},create:function(evt,_19){
+var sc=this.scrollOffset();
+var dim=this._getXY(evt);
+var _1a=dim.x;
+var _1b=dim.y;
+var o=this.origin;
+var x=dim.x-o.x+sc.left;
+var y=dim.y-o.y+sc.top;
+var _1c=x>=0&&y>=0&&x<=o.w&&y<=o.h;
+x*=this.zoom;
+y*=this.zoom;
+var id=_1c?this._getId(evt,_19):"";
+var ret={mid:this.id,x:x,y:y,pageX:dim.x,pageY:dim.y,page:{x:dim.x,y:dim.y},orgX:o.x,orgY:o.y,last:{x:this._lastx,y:this._lasty},start:{x:this.origin.startx,y:this.origin.starty},move:{x:_1a-this._lastpagex,y:_1b-this._lastpagey},scroll:sc,id:id,withinCanvas:_1c};
+this._lastx=x;
+this._lasty=y;
+this._lastpagex=_1a;
+this._lastpagey=_1b;
+_2.stopEvent(evt);
+return ret;
+},_getId:function(evt,_1d){
+return this.util.attr(evt,"id",null,_1d);
+},_getXY:function(evt){
+return {x:evt.pageX,y:evt.pageY};
+},setCursor:function(_1e,_1f){
+if(!_1f){
+_2.style(this.container,"cursor",_1e);
+}else{
+_2.style(_1f,"cursor",_1e);
+}
+}});
+});
diff --git a/js/libs/dojox/drawing/manager/Mouse.js.uncompressed.js b/js/libs/dojox/drawing/manager/Mouse.js.uncompressed.js
new file mode 100644
index 0000000..ea8b105
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Mouse.js.uncompressed.js
@@ -0,0 +1,519 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/Mouse", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.Mouse");
+
+dojox.drawing.manager.Mouse = dojox.drawing.util.oo.declare(
+ // summary:
+ // Master object (instance) that tracks mouse
+ // events. A new instance is created for each
+ // Drawing object.
+ // description:
+ // You could connect to any method or event in this
+ // class, but it is designed to have the object
+ // 'registered'. All objects with the current event
+ // will be called directly.
+ //
+ // Custom events are used often. In addition to
+ // standard events onDown, onUp, onDrag, etc, if
+ // a certain object is clicked upon (or dragged, etc),
+ // that object's drawingType will create the custom event,
+ // such as onAnchorDown, or onStencilDown.
+ //
+ function(/* Object */options){
+ this.util = options.util;
+ this.keys = options.keys;
+ this.id = options.id || this.util.uid("mouse");
+ this.currentNodeId = "";
+ this.registered = {};
+ },
+
+ {
+ // doublClickSpeed: Number
+ // Milliseconds between clicks to
+ // register as for onDoubleClick
+ doublClickSpeed:400,
+
+ // private properties
+
+ _lastx:0,
+ _lasty:0,
+ __reg:0,
+ _downOnCanvas:false,
+
+/*=====
+CustomEventMethod: function(){
+ // summary:
+ // The custom event method that an Object that has
+ // registered with manager.Mouse can receive.
+ // Can contain any or all of the following methods
+ // and they will be called as mouse events. All events
+ // will be sent a EventObject event object.
+ // NOTE:
+ // Events happen anywhere in the document unless
+ // otherwise noted.
+ //
+ // onMove
+ // Fires on mousemove when mouse is up
+ // onDown
+ // Fires on mousedown *on the canvas*
+ // onDrag
+ // Fires on mousemove when mouse is down
+ // onUp
+ // Fires on mouseup, anywhere in the document
+ // onStencilDown
+ // Fired on mousedown on a Stencil
+ // onStencilDrag
+ // Fired when mouse moves and mose is down on a Stencil
+ // onStencilUp
+ // Fired on mouseup off of a Stencil
+ // on[Custom]Up|Down|Move
+ // Custom events can bet set and fired by setting a
+ // different drawingType on a Stencil, or by calling
+ // setEventMode(customEventName)
+},
+EventObject: function(){
+ // summary:
+ // The custom event object that is sent to registered objects
+ // and their respective methods.
+ // NOTE: Most event objects are the same with the exception
+ // of the onDown events, which have fewer.
+ //
+ // All event properties included onDown:
+ //
+ // id: String
+ // Id of the focused object
+ // pageX: Number
+ // The X coordinate of the mouse from the left side of
+ // the document.
+ // pageY: Number
+ // The Y coordinate of the mouse from the top of
+ // the document.
+ // x: Number
+ // The X coordinate of the mouse from the left side
+ // of the canvas
+ // y: Number
+ // The Y coordinate of the mouse from the top
+ // of the canvas
+ //
+ // These event properties are *not* in onDown:
+ //
+ // last: Object
+ // The x and y coordinates of the last mousemove
+ // relative to the canvas
+ // move: Object
+ // The x and y amounts the mouse moved since the last event
+ // orgX: Number
+ // The left side of the canvas from the side of the document
+ // orgY: Number
+ // The top of the canvas from the top of the document
+ // scroll: Object
+ // The 'top' and 'left' scroll amounts of the canvas.
+ // start: Object
+ // The x and y coordinates of the mousedown event
+ // withinCanvas: Boolean
+ // Whether the event happened within the Canvas or not
+
+},
+=====*/
+
+ init: function(/* HTMLNode*/node){
+ // summary:
+ // Internal. Initializes mouse.
+ //
+ this.container = node;
+ this.setCanvas();
+ var c;
+ var _isDown = false;
+ dojo.connect(this.container, "rightclick", this, function(evt){
+ console.warn("RIGHTCLICK")
+ });
+
+ dojo.connect(document.body, "mousedown", this, function(evt){
+ //evt.preventDefault();
+ //dojo.stopEvent(evt);
+ });
+
+ dojo.connect(this.container, "mousedown", this, function(evt){
+ this.down(evt);
+ // Right click shouldn't trigger drag
+ if(evt.button != dojo.mouseButtons.RIGHT){
+ _isDown = true;
+ c = dojo.connect(document, "mousemove", this, "drag");
+ }
+ });
+ dojo.connect(document, "mouseup", this, function(evt){
+ dojo.disconnect(c);
+ _isDown = false;
+ this.up(evt);
+ });
+ dojo.connect(document, "mousemove", this, function(evt){
+ if(!_isDown){
+ this.move(evt);
+ }
+ });
+ dojo.connect(this.keys, "onEsc", this, function(evt){
+ this._dragged = false;
+ });
+ },
+
+ setCanvas: function(){
+ // summary:
+ // Internal. Sets canvas position
+ var pos = dojo.coords(this.container.parentNode);
+ this.origin = dojo.clone(pos);
+ },
+
+ scrollOffset: function(){
+ // summary:
+ // Gets scroll offset of canvas
+ return {
+ top:this.container.parentNode.scrollTop,
+ left:this.container.parentNode.scrollLeft
+ }; // Object
+ },
+
+ resize: function(width,height){
+ if(this.origin){
+ this.origin.w=width;
+ this.origin.h=height;
+ }
+ },
+
+ register: function(/* Object*/scope){
+ // summary:
+ // All objects (Stencils) should register here if they
+ // use mouse events. When registering, the object will
+ // be called if it has that method.
+ // argument:
+ // The object to be called
+ // Returns: handle
+ // Keep the handle to be used for disconnection.
+ // See: CustomEventMethod and EventObject
+ //
+ var handle = scope.id || "reg_"+(this.__reg++);
+ if(!this.registered[handle]){ this.registered[handle] = scope; }
+ return handle; // String
+ },
+ unregister: function(handle){
+ // summary:
+ // Disconnects object. Mouse events are no longer
+ // called for it.
+ if(!this.registered[handle]){ return; }
+ delete this.registered[handle];
+ },
+
+ _broadcastEvent:function(strEvt, obj){
+ // summary:
+ // Fire events to all registered objects.
+ //
+ //console.log("mouse.broadcast:", strEvt, obj)
+ for(var nm in this.registered){
+ if(this.registered[nm][strEvt]) this.registered[nm][strEvt](obj);
+ }
+ },
+
+ onDown: function(obj){
+ // summary:
+ // Create on[xx]Down event and send to broadcaster.
+ // Could be connected to.
+ //console.info("onDown:", this.eventName("down"))
+ this._broadcastEvent(this.eventName("down"), obj);
+ },
+
+ onDrag: function(obj){
+ // summary:
+ // Create on[xx]Drag event and send to broadcaster.
+ // Could be connected to.
+ //
+ var nm = this.eventName("drag");
+ if(this._selected && nm == "onDrag"){
+ nm = "onStencilDrag"
+ }
+ this._broadcastEvent(nm, obj);
+ },
+
+ onMove: function(obj){
+ // summary:
+ // Create onMove event and send to broadcaster.
+ // Could be connected to.
+ // Note: onMove never uses a custom event
+ // Note: onMove is currently not enabled in the app.
+ //
+ this._broadcastEvent("onMove", obj);
+ },
+
+ overName: function(obj,evt){
+ var nm = obj.id.split(".");
+ evt = evt.charAt(0).toUpperCase() + evt.substring(1);
+ if(nm[0] == "dojox" && (dojox.drawing.defaults.clickable || !dojox.drawing.defaults.clickMode)){
+ return "onStencil"+evt;
+ }else{
+ return "on"+evt;
+ }
+
+ },
+
+ onOver: function(obj){
+ // summary:
+ //
+ this._broadcastEvent(this.overName(obj,"over"), obj);
+ },
+
+ onOut: function(obj){
+ // summary:
+ //
+ this._broadcastEvent(this.overName(obj,"out"), obj);
+ },
+
+ onUp: function(obj){
+ // summary:
+ // Create on[xx]Up event and send to broadcaster.
+ // Could be connected to.
+ //
+ // blocking first click-off (deselect), largely for TextBlock
+ // TODO: should have param to make this optional?
+ var nm = this.eventName("up");
+
+ if(nm == "onStencilUp"){
+ this._selected = true;
+ }else if(this._selected && nm == "onUp"){ //////////////////////////////////////////
+ nm = "onStencilUp";
+ this._selected = false;
+ }
+
+ console.info("Up Event:", this.id, nm, "id:", obj.id);
+ this._broadcastEvent(nm, obj);
+
+ // Silverlight double-click handled in Silverlight class
+ if(dojox.gfx.renderer == "silverlight"){ return; }
+
+ // Check Double Click
+ // If a double click is detected, the onDoubleClick event fires,
+ // but does not replace the normal event. They both fire.
+ this._clickTime = new Date().getTime();
+ if(this._lastClickTime){
+ if(this._clickTime-this._lastClickTime=0 && y>=0 && x<=o.w && y<=o.h;
+ x*= this.zoom;
+ y*= this.zoom;
+
+ o.startx = x;
+ o.starty = y;
+ this._lastx = x;
+ this._lasty = y;
+
+ this.drawingType = this.util.attr(evt, "drawingType") || "";
+ var id = this._getId(evt);
+ //console.log("DOWN:", this.id, id, withinCanvas);
+ //console.log("this.drawingType:", this.drawingType);
+
+ if(evt.button == dojo.mouseButtons.RIGHT && this.id == "mse"){
+ //Allow right click events to bubble for context menus
+ }else{
+ evt.preventDefault();
+ dojo.stopEvent(evt);
+ }
+ this.onDown({
+ mid:this.id,
+ x:x,
+ y:y,
+ pageX:dim.x,
+ pageY:dim.y,
+ withinCanvas:withinCanvas,
+ id:id
+ });
+
+ },
+ over: function(obj){
+ // summary:
+ // Internal.
+ //
+ this.onOver(obj);
+ },
+ out: function(obj){
+ // summary:
+ // Internal.
+ //
+ this.onOut(obj);
+ },
+ move: function(evt){
+ // summary:
+ // Internal.
+ //
+ var obj = this.create(evt);
+ if(this.id=="MUI"){
+ //console.log("obj.id:", obj.id, "was:", this.currentNodeId)
+ }
+ if(obj.id != this.currentNodeId){
+ // TODO: I wonder if an ID is good enough
+ // that would avoid the mixin
+ var outObj = {};
+ for(var nm in obj){
+ outObj[nm] = obj[nm];
+ }
+ outObj.id = this.currentNodeId;
+ this.currentNodeId && this.out(outObj);
+ obj.id && this.over(obj);
+ this.currentNodeId = obj.id;
+ }
+ this.onMove(obj);
+ },
+ drag: function(evt){
+ // summary:
+ // Internal. Create onDrag event
+ this.onDrag(this.create(evt, true));
+ },
+ create: function(evt, squelchErrors){
+ // summary:
+ // Internal. Create EventObject
+ //
+ var sc = this.scrollOffset();
+ var dim = this._getXY(evt);
+
+ var pagex = dim.x;
+ var pagey = dim.y;
+
+ var o = this.origin;
+ var x = dim.x - o.x + sc.left;
+ var y = dim.y - o.y + sc.top;
+
+ var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h;
+ x*= this.zoom;
+ y*= this.zoom;
+
+ var id = withinCanvas ? this._getId(evt, squelchErrors) : "";
+ var ret = {
+ mid:this.id,
+ x:x,
+ y:y,
+ pageX:dim.x,
+ pageY:dim.y,
+ page:{
+ x:dim.x,
+ y:dim.y
+ },
+ orgX:o.x,
+ orgY:o.y,
+ last:{
+ x: this._lastx,
+ y: this._lasty
+ },
+ start:{
+ x: this.origin.startx, //+ sc.left,
+ y: this.origin.starty //+ sc.top
+ },
+ move:{
+ x:pagex - this._lastpagex,
+ y:pagey - this._lastpagey
+ },
+ scroll:sc,
+ id:id,
+ withinCanvas:withinCanvas
+ };
+
+ //console.warn("MSE LAST:", x-this._lastx, y-this._lasty)
+ this._lastx = x;
+ this._lasty = y;
+ this._lastpagex = pagex;
+ this._lastpagey = pagey;
+ dojo.stopEvent(evt);
+ return ret; //Object
+ },
+ _getId: function(evt, squelchErrors){
+ // summary:
+ // Internal. Gets ID of focused node.
+ return this.util.attr(evt, "id", null, squelchErrors); // String
+ },
+ _getXY: function(evt){
+ // summary:
+ // Internal. Gets mouse coords to page.
+ return {x:evt.pageX, y:evt.pageY}; // Object
+ },
+
+ setCursor: function(cursor,/* HTMLNode*/node){
+ // summary:
+ // Sets the cursor for a given node. If no
+ // node is specified the containing node is used.
+ if(!node){
+ dojo.style(this.container, "cursor", cursor);
+ }else{
+ dojo.style(node, "cursor", cursor);
+ }
+ }
+ }
+);
+
+});
diff --git a/js/libs/dojox/drawing/manager/Stencil.js b/js/libs/dojox/drawing/manager/Stencil.js
new file mode 100644
index 0000000..70eeda9
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Stencil.js
@@ -0,0 +1,326 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager.Stencil");
+(function(){
+var _4,_5;
+_3.drawing.manager.Stencil=_3.drawing.util.oo.declare(function(_6){
+_4=_6.surface;
+this.canvas=_6.canvas;
+this.defaults=_3.drawing.defaults.copy();
+this.undo=_6.undo;
+this.mouse=_6.mouse;
+this.keys=_6.keys;
+this.anchors=_6.anchors;
+this.stencils={};
+this.selectedStencils={};
+this._mouseHandle=this.mouse.register(this);
+_2.connect(this.keys,"onArrow",this,"onArrow");
+_2.connect(this.keys,"onEsc",this,"deselect");
+_2.connect(this.keys,"onDelete",this,"onDelete");
+},{_dragBegun:false,_wasDragged:false,_secondClick:false,_isBusy:false,setRecentStencil:function(_7){
+this.recent=_7;
+},getRecentStencil:function(){
+return this.recent;
+},register:function(_8){
+if(_8.isText&&!_8.editMode&&_8.deleteEmptyCreate&&!_8.getText()){
+console.warn("EMPTY CREATE DELETE",_8);
+_8.destroy();
+return false;
+}
+this.stencils[_8.id]=_8;
+this.setRecentStencil(_8);
+if(_8.execText){
+if(_8._text&&!_8.editMode){
+this.selectItem(_8);
+}
+_8.connect("execText",this,function(){
+if(_8.isText&&_8.deleteEmptyModify&&!_8.getText()){
+console.warn("EMPTY MOD DELETE",_8);
+this.deleteItem(_8);
+}else{
+if(_8.selectOnExec){
+this.selectItem(_8);
+}
+}
+});
+}
+_8.connect("deselect",this,function(){
+if(!this._isBusy&&this.isSelected(_8)){
+this.deselectItem(_8);
+}
+});
+_8.connect("select",this,function(){
+if(!this._isBusy&&!this.isSelected(_8)){
+this.selectItem(_8);
+}
+});
+return _8;
+},unregister:function(_9){
+if(_9){
+_9.selected&&this.onDeselect(_9);
+delete this.stencils[_9.id];
+}
+},onArrow:function(_a){
+if(this.hasSelected()){
+this.saveThrottledState();
+this.group.applyTransform({dx:_a.x,dy:_a.y});
+}
+},_throttleVrl:null,_throttle:false,throttleTime:400,_lastmxx:-1,_lastmxy:-1,saveMoveState:function(){
+var mx=this.group.getTransform();
+if(mx.dx==this._lastmxx&&mx.dy==this._lastmxy){
+return;
+}
+this._lastmxx=mx.dx;
+this._lastmxy=mx.dy;
+this.undo.add({before:_2.hitch(this.group,"setTransform",mx)});
+},saveThrottledState:function(){
+clearTimeout(this._throttleVrl);
+clearInterval(this._throttleVrl);
+this._throttleVrl=setTimeout(_2.hitch(this,function(){
+this._throttle=false;
+this.saveMoveState();
+}),this.throttleTime);
+if(this._throttle){
+return;
+}
+this._throttle=true;
+this.saveMoveState();
+},unDelete:function(_b){
+for(var s in _b){
+_b[s].render();
+this.onSelect(_b[s]);
+}
+},onDelete:function(_c){
+if(_c!==true){
+this.undo.add({before:_2.hitch(this,"unDelete",this.selectedStencils),after:_2.hitch(this,"onDelete",true)});
+}
+this.withSelected(function(m){
+this.anchors.remove(m);
+var id=m.id;
+m.destroy();
+delete this.stencils[id];
+});
+this.selectedStencils={};
+},deleteItem:function(_d){
+if(this.hasSelected()){
+var _e=[];
+for(var m in this.selectedStencils){
+if(this.selectedStencils.id==_d.id){
+if(this.hasSelected()==1){
+this.onDelete();
+return;
+}
+}else{
+_e.push(this.selectedStencils.id);
+}
+}
+this.deselect();
+this.selectItem(_d);
+this.onDelete();
+_2.forEach(_e,function(id){
+this.selectItem(id);
+},this);
+}else{
+this.selectItem(_d);
+this.onDelete();
+}
+},removeAll:function(){
+this.selectAll();
+this._isBusy=true;
+this.onDelete();
+this.stencils={};
+this._isBusy=false;
+},setSelectionGroup:function(){
+this.withSelected(function(m){
+this.onDeselect(m,true);
+});
+if(this.group){
+_4.remove(this.group);
+this.group.removeShape();
+}
+this.group=_4.createGroup();
+this.group.setTransform({dx:0,dy:0});
+this.withSelected(function(m){
+this.group.add(m.container);
+m.select();
+});
+},setConstraint:function(){
+var t=Infinity,l=Infinity;
+this.withSelected(function(m){
+var o=m.getBounds();
+t=Math.min(o.y1,t);
+l=Math.min(o.x1,l);
+});
+this.constrain={l:-l,t:-t};
+},onDeselect:function(_f,_10){
+if(!_10){
+delete this.selectedStencils[_f.id];
+}
+this.anchors.remove(_f);
+_4.add(_f.container);
+_f.selected&&_f.deselect();
+_f.applyTransform(this.group.getTransform());
+},deselectItem:function(_11){
+this.onDeselect(_11);
+},deselect:function(){
+this.withSelected(function(m){
+this.onDeselect(m);
+});
+this._dragBegun=false;
+this._wasDragged=false;
+},onSelect:function(_12){
+if(!_12){
+console.error("null stencil is not selected:",this.stencils);
+}
+if(this.selectedStencils[_12.id]){
+return;
+}
+this.selectedStencils[_12.id]=_12;
+this.group.add(_12.container);
+_12.select();
+if(this.hasSelected()==1){
+this.anchors.add(_12,this.group);
+}
+},selectAll:function(){
+this._isBusy=true;
+for(var m in this.stencils){
+this.selectItem(m);
+}
+this._isBusy=false;
+},selectItem:function(_13){
+var id=typeof (_13)=="string"?_13:_13.id;
+var _14=this.stencils[id];
+this.setSelectionGroup();
+this.onSelect(_14);
+this.group.moveToFront();
+this.setConstraint();
+},onLabelDoubleClick:function(obj){
+if(this.selectedStencils[obj.id]){
+this.deselect();
+}
+},onStencilDoubleClick:function(obj){
+if(this.selectedStencils[obj.id]){
+if(this.selectedStencils[obj.id].edit){
+var m=this.selectedStencils[obj.id];
+m.editMode=true;
+this.deselect();
+m.edit();
+}
+}
+},onAnchorUp:function(){
+this.setConstraint();
+},onStencilDown:function(obj,evt){
+if(!this.stencils[obj.id]){
+return;
+}
+this.setRecentStencil(this.stencils[obj.id]);
+this._isBusy=true;
+if(this.selectedStencils[obj.id]&&this.keys.meta){
+if(_2.isMac&&this.keys.cmmd){
+}
+this.onDeselect(this.selectedStencils[obj.id]);
+if(this.hasSelected()==1){
+this.withSelected(function(m){
+this.anchors.add(m,this.group);
+});
+}
+this.group.moveToFront();
+this.setConstraint();
+return;
+}else{
+if(this.selectedStencils[obj.id]){
+var mx=this.group.getTransform();
+this._offx=obj.x-mx.dx;
+this._offy=obj.y-mx.dy;
+return;
+}else{
+if(!this.keys.meta){
+this.deselect();
+}else{
+}
+}
+}
+this.selectItem(obj.id);
+mx=this.group.getTransform();
+this._offx=obj.x-mx.dx;
+this._offy=obj.y-mx.dx;
+this.orgx=obj.x;
+this.orgy=obj.y;
+this._isBusy=false;
+this.undo.add({before:function(){
+},after:function(){
+}});
+},onLabelDown:function(obj,evt){
+this.onStencilDown(obj,evt);
+},onStencilUp:function(obj){
+},onLabelUp:function(obj){
+this.onStencilUp(obj);
+},onStencilDrag:function(obj){
+if(!this._dragBegun){
+this.onBeginDrag(obj);
+this._dragBegun=true;
+}else{
+this.saveThrottledState();
+var x=obj.x-obj.last.x,y=obj.y-obj.last.y,c=this.constrain,mz=this.defaults.anchors.marginZero;
+x=obj.x-this._offx;
+y=obj.y-this._offy;
+if(x>built
+// wrapped by build app
+define("dojox/drawing/manager/Stencil", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.Stencil");
+
+(function(){
+ var surface, surfaceNode;
+ dojox.drawing.manager.Stencil = dojox.drawing.util.oo.declare(
+ // summary:
+ // The main class for tracking Stencils that are cretaed, added,
+ // selected, or deleted. Also handles selections, multiple
+ // selections, adding and removing from selections, and dragging
+ // selections. It's this class that triggers the anchors to
+ // appear on a Stencil and whther there are anchor on a multiple
+ // select or not (currently not)
+ //
+ function(options){
+ //
+ // TODO: mixin props
+ //
+ surface = options.surface;
+ this.canvas = options.canvas;
+
+ this.defaults = dojox.drawing.defaults.copy();
+ this.undo = options.undo;
+ this.mouse = options.mouse;
+ this.keys = options.keys;
+ this.anchors = options.anchors;
+ this.stencils = {};
+ this.selectedStencils = {};
+ this._mouseHandle = this.mouse.register(this);
+
+ dojo.connect(this.keys, "onArrow", this, "onArrow");
+ dojo.connect(this.keys, "onEsc", this, "deselect");
+ dojo.connect(this.keys, "onDelete", this, "onDelete");
+
+ },
+ {
+ _dragBegun: false,
+ _wasDragged:false,
+ _secondClick:false,
+ _isBusy:false,
+
+ setRecentStencil: function(stencil){
+ // summary:
+ // Keeps track of the most recent stencil interacted
+ // with, whether created or selected.
+ this.recent = stencil;
+ },
+
+ getRecentStencil: function(){
+ // summary:
+ // Returns the stencil most recently interacted
+ // with whether it's last created or last selected
+ return this.recent;
+ },
+
+ register: function(/*Object*/stencil){
+ // summary:
+ // Key method for adding Stencils. Stencils
+ // can be added to the canvas without adding
+ // them to this, but they won't have selection
+ // or drag ability.
+ //
+ console.log("Selection.register ::::::", stencil.id);
+ if(stencil.isText && !stencil.editMode && stencil.deleteEmptyCreate && !stencil.getText()){
+ // created empty text field
+ // defaults say to delete
+ console.warn("EMPTY CREATE DELETE", stencil);
+ stencil.destroy();
+ return false;
+ }
+
+ this.stencils[stencil.id] = stencil;
+ this.setRecentStencil(stencil);
+
+ if(stencil.execText){
+ if(stencil._text && !stencil.editMode){
+ console.log("select text");
+ this.selectItem(stencil);
+ }
+ stencil.connect("execText", this, function(){
+ if(stencil.isText && stencil.deleteEmptyModify && !stencil.getText()){
+ console.warn("EMPTY MOD DELETE", stencil);
+ // text deleted
+ // defaults say to delete
+ this.deleteItem(stencil);
+ }else if(stencil.selectOnExec){
+ this.selectItem(stencil);
+ }
+ });
+ }
+
+ stencil.connect("deselect", this, function(){
+ if(!this._isBusy && this.isSelected(stencil)){
+ // called from within stencil. do action.
+ this.deselectItem(stencil);
+ }
+ });
+
+ stencil.connect("select", this, function(){
+ if(!this._isBusy && !this.isSelected(stencil)){
+ // called from within stencil. do action.
+ this.selectItem(stencil);
+ }
+ });
+
+ return stencil;
+ },
+ unregister: function(/*Object*/stencil){
+ // summary:
+ // Method for removing Stencils from the manager.
+ // This doesn't delete them, only removes them from
+ // the list.
+ //
+ console.log("Selection.unregister ::::::", stencil.id, "sel:", stencil.selected);
+ if(stencil){
+ stencil.selected && this.onDeselect(stencil);
+ delete this.stencils[stencil.id];
+ }
+ },
+
+ onArrow: function(/*Key Event*/evt){
+ // summary:
+ // Moves selection based on keyboard arrow keys
+ //
+ // FIXME: Check constraints
+ if(this.hasSelected()){
+ this.saveThrottledState();
+ this.group.applyTransform({dx:evt.x, dy: evt.y});
+ }
+ },
+
+ _throttleVrl:null,
+ _throttle: false,
+ throttleTime:400,
+ _lastmxx:-1,
+ _lastmxy:-1,
+ saveMoveState: function(){
+ // summary:
+ // Internal. Used for the prototype undo stack.
+ // Saves selection position.
+ //
+ var mx = this.group.getTransform();
+ if(mx.dx == this._lastmxx && mx.dy == this._lastmxy){ return; }
+ this._lastmxx = mx.dx;
+ this._lastmxy = mx.dy;
+ //console.warn("SAVE MOVE!", mx.dx, mx.dy);
+ this.undo.add({
+ before:dojo.hitch(this.group, "setTransform", mx)
+ });
+ },
+
+ saveThrottledState: function(){
+ // summary:
+ // Internal. Used for the prototype undo stack.
+ // Prevents an undo point on every mouse move.
+ // Only does a point when the mouse hesitates.
+ //
+ clearTimeout(this._throttleVrl);
+ clearInterval(this._throttleVrl);
+ this._throttleVrl = setTimeout(dojo.hitch(this, function(){
+ this._throttle = false;
+ this.saveMoveState();
+ }), this.throttleTime);
+ if(this._throttle){ return; }
+ this._throttle = true;
+
+ this.saveMoveState();
+
+ },
+ unDelete: function(/*Array*/stencils){
+ // summary:
+ // Undeletes a stencil. Used in undo stack.
+ //
+ console.log("unDelete:", stencils);
+ for(var s in stencils){
+ stencils[s].render();
+ this.onSelect(stencils[s]);
+ }
+ },
+ onDelete: function(/*Boolean*/noundo){
+ // summary:
+ // Event fired on deletion of a stencil
+ //
+ console.log("Stencil onDelete", noundo);
+ if(noundo!==true){
+ this.undo.add({
+ before:dojo.hitch(this, "unDelete", this.selectedStencils),
+ after:dojo.hitch(this, "onDelete", true)
+ });
+ }
+ this.withSelected(function(m){
+ this.anchors.remove(m);
+ var id = m.id;
+ console.log("delete:", m);
+ m.destroy();
+ delete this.stencils[id];
+ });
+ this.selectedStencils = {};
+ },
+
+ deleteItem: function(/*Object*/stencil){
+ // summary:
+ // Deletes a stencil.
+ // NOTE: supports limited undo.
+ //
+ // manipulating the selection to fire onDelete properly
+ if(this.hasSelected()){
+ // there is a selection
+ var sids = [];
+ for(var m in this.selectedStencils){
+ if(this.selectedStencils.id == stencil.id){
+ if(this.hasSelected()==1){
+ // the deleting stencil is the only one selected
+ this.onDelete();
+ return;
+ }
+ }else{
+ sids.push(this.selectedStencils.id);
+ }
+ }
+ // remove selection, delete, restore selection
+ this.deselect();
+ this.selectItem(stencil);
+ this.onDelete();
+ dojo.forEach(sids, function(id){
+ this.selectItem(id);
+ }, this);
+ }else{
+ // there is not a selection. select it, delete it
+ this.selectItem(stencil);
+ // now delete selection
+ this.onDelete();
+ }
+ },
+
+ removeAll: function(){
+ // summary:
+ // Deletes all Stencils on the canvas.
+
+ this.selectAll();
+ this._isBusy = true;
+ this.onDelete();
+ this.stencils = {};
+ this._isBusy = false;
+ },
+
+ setSelectionGroup: function(){
+ // summary:
+ // Internal. Creates a new selection group
+ // used to hold selected stencils.
+ //
+ this.withSelected(function(m){
+ this.onDeselect(m, true);
+ });
+
+ if(this.group){
+ surface.remove(this.group);
+ this.group.removeShape();
+ }
+ this.group = surface.createGroup();
+ this.group.setTransform({dx:0, dy: 0});
+
+ this.withSelected(function(m){
+ this.group.add(m.container);
+ m.select();
+ });
+ },
+
+ setConstraint: function(){
+ // summary:
+ // Internal. Gets all selected stencils' coordinates
+ // and determines how far left and up the selection
+ // can go without going below zero
+ //
+ var t = Infinity, l = Infinity;
+ this.withSelected(function(m){
+ var o = m.getBounds();
+ t = Math.min(o.y1, t);
+ l = Math.min(o.x1, l);
+ });
+ this.constrain = {l:-l, t:-t};
+ },
+
+
+
+ onDeselect: function(stencil, keepObject){
+ // summary:
+ // Event fired on deselection of a stencil
+ //
+ if(!keepObject){
+ delete this.selectedStencils[stencil.id];
+ }
+ //console.log('onDeselect, keep:', keepObject, "stencil:", stencil.type)
+
+ this.anchors.remove(stencil);
+
+ surface.add(stencil.container);
+ stencil.selected && stencil.deselect();
+ stencil.applyTransform(this.group.getTransform());
+ },
+
+ deselectItem: function(/*Object*/stencil){
+ // summary:
+ // Deselect passed stencil
+ //
+ // note: just keeping with standardized methods
+ this.onDeselect(stencil);
+ },
+
+ deselect: function(){ // all stencils
+ // summary:
+ // Deselect all stencils
+ //
+ this.withSelected(function(m){
+ this.onDeselect(m);
+ });
+ this._dragBegun = false;
+ this._wasDragged = false;
+ },
+
+ onSelect: function(/*Object*/stencil){
+ // summary:
+ // Event fired on selection of a stencil
+ //
+ //console.log("stencil.onSelect", stencil);
+ if(!stencil){
+ console.error("null stencil is not selected:", this.stencils)
+ }
+ if(this.selectedStencils[stencil.id]){ return; }
+ this.selectedStencils[stencil.id] = stencil;
+ this.group.add(stencil.container);
+ stencil.select();
+ if(this.hasSelected()==1){
+ this.anchors.add(stencil, this.group);
+ }
+ },
+
+ selectAll: function(){
+ // summary:
+ // Selects all items
+ this._isBusy = true;
+ for(var m in this.stencils){
+ //if(!this.stencils[m].selected){
+ this.selectItem(m);
+ //}
+ }
+ this._isBusy = false;
+ },
+
+ selectItem: function(/*String|Object*/ idOrItem){
+ // summary:
+ // Method used to select a stencil.
+ //
+ var id = typeof(idOrItem)=="string" ? idOrItem : idOrItem.id;
+ var stencil = this.stencils[id];
+ this.setSelectionGroup();
+ this.onSelect(stencil);
+ this.group.moveToFront();
+ this.setConstraint();
+ },
+
+ onLabelDoubleClick: function(/*EventObject*/obj){
+ // summary:
+ // Event to connect a textbox to
+ // for label edits
+ console.info("mgr.onLabelDoubleClick:", obj);
+ if(this.selectedStencils[obj.id]){
+ this.deselect();
+ }
+ },
+
+ onStencilDoubleClick: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on the double-click of a stencil
+ //
+ console.info("mgr.onStencilDoubleClick:", obj);
+ if(this.selectedStencils[obj.id]){
+ if(this.selectedStencils[obj.id].edit){
+ console.info("Mgr Stencil Edit -> ", this.selectedStencils[obj.id]);
+ var m = this.selectedStencils[obj.id];
+ // deselect must happen first to set the transform
+ // then edit knows where to set the text box
+ m.editMode = true;
+ this.deselect();
+ m.edit();
+ }
+ }
+
+ },
+
+ onAnchorUp: function(){
+ // summary:
+ // Event fire on mouseup off of an anchor point
+ this.setConstraint();
+ },
+
+ onStencilDown: function(/*EventObject*/obj, evt){
+ // summary:
+ // Event fired on mousedown on a stencil
+ //
+ console.info(" >>> onStencilDown:", obj.id, this.keys.meta);
+ if(!this.stencils[obj.id]){ return; }
+ this.setRecentStencil(this.stencils[obj.id]);
+ this._isBusy = true;
+
+
+ if(this.selectedStencils[obj.id] && this.keys.meta){
+ if(dojo.isMac && this.keys.cmmd){
+ // block context menu
+
+ }
+ console.log(" shift remove");
+ this.onDeselect(this.selectedStencils[obj.id]);
+ if(this.hasSelected()==1){
+ this.withSelected(function(m){
+ this.anchors.add(m, this.group);
+ });
+ }
+ this.group.moveToFront();
+ this.setConstraint();
+ return;
+
+ }else if(this.selectedStencils[obj.id]){
+ console.log(" clicked on selected");
+ // clicking on same selected item(s)
+ // RESET OFFSETS
+ var mx = this.group.getTransform();
+ this._offx = obj.x - mx.dx;
+ this._offy = obj.y - mx.dy;
+ return;
+
+ }else if(!this.keys.meta){
+
+ console.log(" deselect all");
+ this.deselect();
+
+ }else{
+ // meta-key add
+ //console.log("reset sel and add stencil")
+ }
+ console.log(" add stencil to selection");
+ // add a stencil
+ this.selectItem(obj.id);
+
+ mx = this.group.getTransform();
+ this._offx = obj.x - mx.dx;
+ this._offy = obj.y - mx.dx;
+
+ this.orgx = obj.x;
+ this.orgy = obj.y;
+
+ this._isBusy = false;
+
+ // TODO:
+ // dojo.style(surfaceNode, "cursor", "pointer");
+
+ // TODO:
+ this.undo.add({
+ before:function(){
+
+ },
+ after: function(){
+
+ }
+ });
+ },
+
+ onLabelDown: function(/*EventObject*/obj, evt){
+ // summary:
+ // Event fired on mousedown of a stencil's label
+ // Because it's an annotation the id will be the
+ // master stencil.
+ //console.info("===============>>>Label click: ",obj, " evt: ",evt);
+ this.onStencilDown(obj,evt);
+ },
+
+ onStencilUp: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mouseup off of a stencil
+ //
+ },
+
+ onLabelUp: function(/*EventObject*/obj){
+ this.onStencilUp(obj);
+ },
+
+ onStencilDrag: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on every mousemove of a stencil drag
+ //
+ if(!this._dragBegun){
+ // bug, in FF anyway - first mouse move shows x=0
+ // the 'else' fixes it
+ this.onBeginDrag(obj);
+ this._dragBegun = true;
+ }else{
+ this.saveThrottledState();
+
+ var x = obj.x - obj.last.x,
+ y = obj.y - obj.last.y,
+ c = this.constrain,
+ mz = this.defaults.anchors.marginZero;
+
+
+ x = obj.x - this._offx;
+ y = obj.y - this._offy;
+
+ if(x < c.l + mz){
+ x = c.l + mz;
+ }
+ if(y < c.t + mz){
+ y = c.t + mz;
+ }
+
+ this.group.setTransform({
+ dx: x,
+ dy: y
+ });
+
+
+ }
+ },
+
+ onLabelDrag: function(/*EventObject*/obj){
+ this.onStencilDrag(obj);
+ },
+
+ onDragEnd: function(/*EventObject*/obj){
+ // summary:
+ // Event fired at the end of a stencil drag
+ //
+ this._dragBegun = false;
+ },
+ onBeginDrag: function(/*EventObject*/obj){
+ // summary:
+ // Event fired at the beginning of a stencil drag
+ //
+ this._wasDragged = true;
+ },
+
+ onDown: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mousedown on the canvas
+ //
+ this.deselect();
+ },
+
+
+ onStencilOver: function(obj){
+ // summary:
+ // This changes the cursor when hovering over
+ // a selectable stencil.
+ //console.log("OVER")
+ dojo.style(obj.id, "cursor", "move");
+ },
+
+ onStencilOut: function(obj){
+ // summary:
+ // This restores the cursor.
+ //console.log("OUT")
+ dojo.style(obj.id, "cursor", "crosshair");
+ },
+
+ exporter: function(){
+ // summary:
+ // Collects all Stencil data and returns an
+ // Array of objects.
+ var items = [];
+ for(var m in this.stencils){
+ this.stencils[m].enabled && items.push(this.stencils[m].exporter());
+ }
+ return items; // Array
+ },
+
+ listStencils: function(){
+ return this.stencils;
+ },
+
+ toSelected: function(/*String*/func){
+ // summary:
+ // Convenience function calls function *within*
+ // all selected stencils
+ var args = Array.prototype.slice.call(arguments).splice(1);
+ for(var m in this.selectedStencils){
+ var item = this.selectedStencils[m];
+ item[func].apply(item, args);
+ }
+ },
+
+ withSelected: function(/*Function*/func){
+ // summary:
+ // Convenience function calls function on
+ // all selected stencils
+ var f = dojo.hitch(this, func);
+ for(var m in this.selectedStencils){
+ f(this.selectedStencils[m]);
+ }
+ },
+
+ withUnselected: function(/*Function*/func){
+ // summary:
+ // Convenience function calls function on
+ // all stencils that are not selected
+ var f = dojo.hitch(this, func);
+ for(var m in this.stencils){
+ !this.stencils[m].selected && f(this.stencils[m]);
+ }
+ },
+
+ withStencils: function(/*Function*/func){
+ // summary:
+ // Convenience function calls function on
+ // all stencils
+ var f = dojo.hitch(this, func);
+ for(var m in this.stencils){
+ f(this.stencils[m]);
+ }
+ },
+
+ hasSelected: function(){
+ // summary:
+ // Returns number of selected (generally used
+ // as truthy or falsey)
+ //
+ // FIXME: should be areSelected?
+ var ln = 0;
+ for(var m in this.selectedStencils){ ln++; }
+ return ln; // Number
+ },
+
+ isSelected: function(/*Object*/stencil){
+ // summary:
+ // Returns if passed stencil is selected or not
+ // based on internal collection, not on stencil
+ // boolean
+ return !!this.selectedStencils[stencil.id]; // Boolean
+ }
+ }
+
+ );
+})();
+
+});
diff --git a/js/libs/dojox/drawing/manager/StencilUI.js b/js/libs/dojox/drawing/manager/StencilUI.js
new file mode 100644
index 0000000..2c6f0f3
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/StencilUI.js
@@ -0,0 +1,41 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager.StencilUI");
+(function(){
+var _4,_5;
+_3.drawing.manager.StencilUI=_3.drawing.util.oo.declare(function(_6){
+_4=_6.surface;
+this.canvas=_6.canvas;
+this.defaults=_3.drawing.defaults.copy();
+this.mouse=_6.mouse;
+this.keys=_6.keys;
+this._mouseHandle=this.mouse.register(this);
+this.stencils={};
+},{register:function(_7){
+this.stencils[_7.id]=_7;
+return _7;
+},onUiDown:function(_8){
+if(!this._isStencil(_8)){
+return;
+}
+this.stencils[_8.id].onDown(_8);
+},onUiUp:function(_9){
+if(!this._isStencil(_9)){
+return;
+}
+this.stencils[_9.id].onUp(_9);
+},onOver:function(_a){
+if(!this._isStencil(_a)){
+return;
+}
+this.stencils[_a.id].onOver(_a);
+},onOut:function(_b){
+if(!this._isStencil(_b)){
+return;
+}
+this.stencils[_b.id].onOut(_b);
+},_isStencil:function(_c){
+return !!_c.id&&!!this.stencils[_c.id]&&this.stencils[_c.id].type=="drawing.library.UI.Button";
+}});
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/StencilUI.js.uncompressed.js b/js/libs/dojox/drawing/manager/StencilUI.js.uncompressed.js
new file mode 100644
index 0000000..7fdaa14
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/StencilUI.js.uncompressed.js
@@ -0,0 +1,69 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/StencilUI", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.StencilUI");
+
+(function(){
+ var surface, surfaceNode;
+ dojox.drawing.manager.StencilUI = dojox.drawing.util.oo.declare(
+ // summary:
+ // Used for handling Stencils as UI components.
+ // description:
+ // Replaces manager.Stencil. Handles basic UI mouse
+ // events like onmouseover. Does not handle selections
+ // or support delete, etc.
+ //
+ function(options){
+ //
+ // TODO: mixin props
+ //
+ surface = options.surface;
+ this.canvas = options.canvas;
+
+ this.defaults = dojox.drawing.defaults.copy();
+ this.mouse = options.mouse;
+ this.keys = options.keys;
+ this._mouseHandle = this.mouse.register(this);
+ this.stencils = {};
+ },
+ {
+ register: function(/*Object*/stencil){
+ this.stencils[stencil.id] = stencil;
+ return stencil;
+ },
+ onUiDown: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mousedown on a stencil
+ //
+ if(!this._isStencil(obj)){ return; }
+ this.stencils[obj.id].onDown(obj);
+ },
+ onUiUp: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mousedown on a stencil
+ //
+ if(!this._isStencil(obj)){ return; }
+ this.stencils[obj.id].onUp(obj);
+ },
+ onOver: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mousedown on a stencil
+ //
+ if(!this._isStencil(obj)){ return; }
+ this.stencils[obj.id].onOver(obj);
+ },
+ onOut: function(/*EventObject*/obj){
+ // summary:
+ // Event fired on mousedown on a stencil
+ //
+ if(!this._isStencil(obj)){ return; }
+ this.stencils[obj.id].onOut(obj);
+ },
+ _isStencil: function(/*EventObject*/obj){
+ return !!obj.id && !!this.stencils[obj.id] && this.stencils[obj.id].type == "drawing.library.UI.Button";
+ }
+ }
+ );
+
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/Undo.js b/js/libs/dojox/drawing/manager/Undo.js
new file mode 100644
index 0000000..10cc38f
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Undo.js
@@ -0,0 +1,44 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager.Undo");
+_3.drawing.manager.Undo=_3.drawing.util.oo.declare(function(_4){
+this.keys=_4.keys;
+this.undostack=[];
+this.redostack=[];
+_2.connect(this.keys,"onKeyDown",this,"onKeyDown");
+},{onKeyDown:function(_5){
+if(!_5.cmmd){
+return;
+}
+if(_5.keyCode==90&&!_5.shift){
+this.undo();
+}else{
+if((_5.keyCode==90&&_5.shift)||_5.keyCode==89){
+this.redo();
+}
+}
+},add:function(_6){
+_6.args=_2.mixin({},_6.args);
+this.undostack.push(_6);
+},apply:function(_7,_8,_9){
+_2.hitch(_7,_8)(_9);
+},undo:function(){
+var o=this.undostack.pop();
+if(!o){
+return;
+}
+o.before();
+this.redostack.push(o);
+},redo:function(){
+var o=this.redostack.pop();
+if(!o){
+return;
+}
+if(o.after){
+o.after();
+}else{
+o.before();
+}
+this.undostack.push(o);
+}});
+});
diff --git a/js/libs/dojox/drawing/manager/Undo.js.uncompressed.js b/js/libs/dojox/drawing/manager/Undo.js.uncompressed.js
new file mode 100644
index 0000000..c904240
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/Undo.js.uncompressed.js
@@ -0,0 +1,61 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/Undo", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.Undo");
+
+dojox.drawing.manager.Undo = dojox.drawing.util.oo.declare(
+ // summary
+ // Handles the Undo in drawing.
+ // NOTE: Only partially implemented!!! There is very
+ // little actual undo functionality!
+ //
+ function(options){
+ this.keys = options.keys;
+ this.undostack = [];
+ this.redostack = [];
+ dojo.connect(this.keys, "onKeyDown", this, "onKeyDown");
+ },
+ {
+ onKeyDown: function(evt){
+ if(!evt.cmmd){ return; }
+
+ if(evt.keyCode==90 && !evt.shift){
+ this.undo();
+ }else if((evt.keyCode == 90 && evt.shift) || evt.keyCode==89){
+ this.redo();
+ }
+
+ },
+ add: function(stack){
+ //console.log("undo add", stack)
+ stack.args = dojo.mixin({}, stack.args);
+ this.undostack.push(stack);
+ },
+ apply: function(scope, method, args){
+ dojo.hitch(scope, method)(args);
+ },
+ undo: function(){
+
+ var o = this.undostack.pop();
+ console.log("undo!", o);
+ if(!o){ return; }
+
+ o.before();
+
+ this.redostack.push(o);
+ },
+ redo: function(){
+ console.log("redo!");
+ var o = this.redostack.pop();
+ if(!o){ return; }
+ if(o.after){
+ o.after();
+ }else{
+ o.before(); ///??????
+ }
+
+ this.undostack.push(o);
+ }
+ }
+);
+});
diff --git a/js/libs/dojox/drawing/manager/_registry.js b/js/libs/dojox/drawing/manager/_registry.js
new file mode 100644
index 0000000..498d60e
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/_registry.js
@@ -0,0 +1,31 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager._registry");
+(function(){
+var _4={tool:{},stencil:{},drawing:{},plugin:{},button:{}};
+_3.drawing.register=function(_5,_6){
+if(_6=="drawing"){
+_4.drawing[_5.id]=_5;
+}else{
+if(_6=="tool"){
+_4.tool[_5.name]=_5;
+}else{
+if(_6=="stencil"){
+_4.stencil[_5.name]=_5;
+}else{
+if(_6=="plugin"){
+_4.plugin[_5.name]=_5;
+}else{
+if(_6=="button"){
+_4.button[_5.toolType]=_5;
+}
+}
+}
+}
+}
+};
+_3.drawing.getRegistered=function(_7,id){
+return id?_4[_7][id]:_4[_7];
+};
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/_registry.js.uncompressed.js b/js/libs/dojox/drawing/manager/_registry.js.uncompressed.js
new file mode 100644
index 0000000..53c5a7e
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/_registry.js.uncompressed.js
@@ -0,0 +1,35 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/_registry", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager._registry");
+
+(function(){
+
+ var _registered = {
+ tool:{},
+ stencil:{},
+ drawing:{},
+ plugin:{},
+ button:{}
+ };
+
+ dojox.drawing.register = function(item, type){
+ if(type=="drawing"){
+ _registered.drawing[item.id] = item;
+ }else if(type=="tool"){
+ _registered.tool[item.name] = item;
+ }else if(type=="stencil"){
+ _registered.stencil[item.name] = item;
+ }else if(type=="plugin"){
+ _registered.plugin[item.name] = item;
+ }else if(type=="button"){
+ _registered.button[item.toolType] = item;
+ }
+ };
+
+ dojox.drawing.getRegistered = function(type, id){
+ return id ? _registered[type][id] : _registered[type];
+ }
+
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/keys.js b/js/libs/dojox/drawing/manager/keys.js
new file mode 100644
index 0000000..4252d27
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/keys.js
@@ -0,0 +1,147 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.manager.keys");
+(function(){
+var _4=false;
+var _5=true;
+var _6="abcdefghijklmnopqrstuvwxyz";
+_3.drawing.manager.keys={arrowIncrement:1,arrowShiftIncrement:10,shift:false,ctrl:false,alt:false,cmmd:false,meta:false,onDelete:function(_7){
+},onEsc:function(_8){
+},onEnter:function(_9){
+},onArrow:function(_a){
+},onKeyDown:function(_b){
+},onKeyUp:function(_c){
+},listeners:[],register:function(_d){
+var _e=_3.drawing.util.common.uid("listener");
+this.listeners.push({handle:_e,scope:_d.scope||window,callback:_d.callback,keyCode:_d.keyCode});
+},_getLetter:function(_f){
+if(!_f.meta&&_f.keyCode>=65&&_f.keyCode<=90){
+return _6.charAt(_f.keyCode-65);
+}
+return null;
+},_mixin:function(evt){
+evt.meta=this.meta;
+evt.shift=this.shift;
+evt.alt=this.alt;
+evt.cmmd=this.cmmd;
+evt.letter=this._getLetter(evt);
+return evt;
+},editMode:function(_10){
+_4=_10;
+},enable:function(_11){
+_5=_11;
+},scanForFields:function(){
+if(this._fieldCons){
+_2.forEach(this._fieldCons,_2.disconnect,_2);
+}
+this._fieldCons=[];
+_2.query("input").forEach(function(n){
+var a=_2.connect(n,"focus",this,function(evt){
+this.enable(false);
+});
+var b=_2.connect(n,"blur",this,function(evt){
+this.enable(true);
+});
+this._fieldCons.push(a);
+this._fieldCons.push(b);
+},this);
+},init:function(){
+setTimeout(_2.hitch(this,"scanForFields"),500);
+_2.connect(document,"blur",this,function(evt){
+this.meta=this.shift=this.ctrl=this.cmmd=this.alt=false;
+});
+_2.connect(document,"keydown",this,function(evt){
+if(!_5){
+return;
+}
+if(evt.keyCode==16){
+this.shift=true;
+}
+if(evt.keyCode==17){
+this.ctrl=true;
+}
+if(evt.keyCode==18){
+this.alt=true;
+}
+if(evt.keyCode==224){
+this.cmmd=true;
+}
+this.meta=this.shift||this.ctrl||this.cmmd||this.alt;
+if(!_4){
+this.onKeyDown(this._mixin(evt));
+if(evt.keyCode==8||evt.keyCode==46){
+_2.stopEvent(evt);
+}
+}
+});
+_2.connect(document,"keyup",this,function(evt){
+if(!_5){
+return;
+}
+var _12=false;
+if(evt.keyCode==16){
+this.shift=false;
+}
+if(evt.keyCode==17){
+this.ctrl=false;
+}
+if(evt.keyCode==18){
+this.alt=false;
+}
+if(evt.keyCode==224){
+this.cmmd=false;
+}
+this.meta=this.shift||this.ctrl||this.cmmd||this.alt;
+!_4&&this.onKeyUp(this._mixin(evt));
+if(evt.keyCode==13){
+console.warn("KEY ENTER");
+this.onEnter(evt);
+_12=true;
+}
+if(evt.keyCode==27){
+this.onEsc(evt);
+_12=true;
+}
+if(evt.keyCode==8||evt.keyCode==46){
+this.onDelete(evt);
+_12=true;
+}
+if(_12&&!_4){
+_2.stopEvent(evt);
+}
+});
+_2.connect(document,"keypress",this,function(evt){
+if(!_5){
+return;
+}
+var inc=this.shift?this.arrowIncrement*this.arrowShiftIncrement:this.arrowIncrement;
+var x=0,y=0;
+if(evt.keyCode==32&&!_4){
+_2.stopEvent(evt);
+}
+if(evt.keyCode==37){
+x=-inc;
+}
+if(evt.keyCode==38){
+y=-inc;
+}
+if(evt.keyCode==39){
+x=inc;
+}
+if(evt.keyCode==40){
+y=inc;
+}
+if(x||y){
+evt.x=x;
+evt.y=y;
+evt.shift=this.shift;
+if(!_4){
+this.onArrow(evt);
+_2.stopEvent(evt);
+}
+}
+});
+}};
+_2.addOnLoad(_3.drawing.manager.keys,"init");
+})();
+});
diff --git a/js/libs/dojox/drawing/manager/keys.js.uncompressed.js b/js/libs/dojox/drawing/manager/keys.js.uncompressed.js
new file mode 100644
index 0000000..1acb06b
--- /dev/null
+++ b/js/libs/dojox/drawing/manager/keys.js.uncompressed.js
@@ -0,0 +1,269 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/manager/keys", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.manager.keys");
+
+(function(){
+
+ // Ref: isEdit allows events to happen in Drawing, like TextBlocks
+ var isEdit = false;
+
+ // Ref: enabled = false allows inputs outside of drawing to function
+ var enabled = true;
+
+ var alphabet = "abcdefghijklmnopqrstuvwxyz";
+
+ dojox.drawing.manager.keys = {
+ // summary:
+ // A singleton, master object that detects
+ // keyboard keys and events
+ // Connect to it like:
+ // dojo.connect(this.keys, "onEnter", ....);
+ //
+ // arrowIncrement:Number
+ // The amount, in pixels, a selected Stencil will
+ // move on an arrow key event
+ arrowIncrement:1,
+ //
+ // arrowShiftIncrement: Number
+ // The amount, in pixels, a selected Stencil will
+ // move on an arrow key + SHIFT event
+ arrowShiftIncrement:10,
+ //
+ // shift: [readonly] Boolean
+ // Indicates whether the Shift key is currently pressed
+ shift:false,
+ //
+ // ctrl: [readonly] Boolean
+ // Indicates whether the Control key is currently pressed
+ ctrl:false,
+ //
+ // alt: [readonly] Boolean
+ // Indicates whether the Alt or Option key is currently pressed
+ alt:false,
+ //
+ // cmmd: [readonly] Boolean
+ // Indicates whether the Apple Command key is currently pressed
+ cmmd:false, // apple key
+ //
+ // meta: [readonly] Boolean
+ // Indicates whether any 'meta' key is currently pressed:
+ // shift || ctrl || cmmd || alt
+ meta:false, // any meta key
+
+ onDelete: function(/* Event */evt){
+ // summary:
+ // Event fires when Delete key is released
+ },
+ onEsc: function(/* Event */evt){
+ // summary:
+ // Event fires when ESC key is released
+ },
+ onEnter: function(/* Event */evt){
+ // summary:
+ // Event fires when Enter key is released
+ },
+ onArrow: function(/* Event */evt){
+ // summary:
+ // Event fires when an Arrow key is released
+ // You will have to further check if evt.keyCode
+ // is 37,38,39, or 40
+ },
+ onKeyDown: function(/* Event */evt){
+ // summary:
+ // Event fires when any key is pressed
+ },
+ onKeyUp: function(/* Event */evt){
+ // summary:
+ // Event fires when any key is released
+ },
+
+ listeners:[],
+ register: function(options){
+ // summary:
+ // Register an object and callback to be notified
+ // of events.
+ // NOTE: Not really used in code, but should work.
+ // See manager.mouse for similar usage
+ //
+ var _handle = dojox.drawing.util.common.uid("listener");
+ this.listeners.push({
+ handle:_handle,
+ scope: options.scope || window,
+ callback:options.callback,
+ keyCode:options.keyCode
+ });
+ },
+
+ _getLetter: function(evt){
+ if(!evt.meta && evt.keyCode>=65 && evt.keyCode<=90){
+ return alphabet.charAt(evt.keyCode-65);
+ }
+ return null;
+ },
+
+ _mixin: function(evt){
+ // summary:
+ // Internal. Mixes in key events.
+ evt.meta = this.meta;
+ evt.shift = this.shift;
+ evt.alt = this.alt;
+ evt.cmmd = this.cmmd;
+ evt.letter = this._getLetter(evt);
+ return evt;
+ },
+
+ editMode: function(_isedit){
+ // summary:
+ // Relinquishes control of events to another portion
+ // of Drawing; namely the TextBlock.
+ isEdit = _isedit;
+ },
+
+ enable: function(_enabled){
+ // summary:
+ // Enables or disables key events, to relinquish
+ // control to something outside of Drawing; input
+ // fields for example.
+ // You may need to call this directly if you are
+ // using textareas or contenteditables.
+ // NOTE: See scanForFields
+ enabled = _enabled;
+ },
+
+ scanForFields: function(){
+ // summary:
+ // Scans the document for inputs
+ // and calls this automatically. However you may need
+ // to call this if you create inputs after the fact.
+ //
+ if(this._fieldCons){
+ dojo.forEach(this._fieldCons, dojo.disconnect, dojo);
+ }
+ this._fieldCons = [];
+ dojo.query("input").forEach(function(n){
+ var a = dojo.connect(n, "focus", this, function(evt){
+ this.enable(false);
+ });
+ var b = dojo.connect(n, "blur", this, function(evt){
+ this.enable(true);
+ });
+ this._fieldCons.push(a);
+ this._fieldCons.push(b);
+ }, this);
+
+ },
+
+ init: function(){
+ // summary:
+ // Initialize the keys object
+ //
+ // a little extra time is needed in some browsers
+ setTimeout(dojo.hitch(this, "scanForFields"), 500);
+
+ dojo.connect(document, "blur", this, function(evt){
+ // when command tabbing to another application, the key "sticks"
+ // this clears any key used for such activity
+ this.meta = this.shift = this.ctrl = this.cmmd = this.alt = false;
+ });
+
+ dojo.connect(document, "keydown", this, function(evt){
+ if(!enabled){ return; }
+ if(evt.keyCode==16){
+ this.shift = true;
+ }
+ if(evt.keyCode==17){
+ this.ctrl = true;
+ }
+ if(evt.keyCode==18){
+ this.alt = true;
+ }
+ if(evt.keyCode==224){
+ this.cmmd = true;
+ }
+
+ this.meta = this.shift || this.ctrl || this.cmmd || this.alt;
+
+ if(!isEdit){
+ this.onKeyDown(this._mixin(evt));
+ if(evt.keyCode==8 || evt.keyCode==46){
+ dojo.stopEvent(evt);
+ }
+ }
+ });
+ dojo.connect(document, "keyup", this, function(evt){
+ if(!enabled){ return; }
+ //console.log("KEY UP:", evt.keyCode);
+ var _stop = false;
+ if(evt.keyCode==16){
+ this.shift = false;
+ }
+ if(evt.keyCode==17){
+ this.ctrl = false;
+ }
+ if(evt.keyCode==18){
+ this.alt = false;
+ }
+ if(evt.keyCode==224){
+ this.cmmd = false;
+ }
+
+ this.meta = this.shift || this.ctrl || this.cmmd || this.alt;
+
+ !isEdit && this.onKeyUp(this._mixin(evt));
+
+ if(evt.keyCode==13){
+ console.warn("KEY ENTER");
+ this.onEnter(evt);
+ _stop = true;
+ }
+ if(evt.keyCode==27){
+ this.onEsc(evt);
+ _stop = true;
+ }
+ if(evt.keyCode==8 || evt.keyCode==46){
+ this.onDelete(evt);
+ _stop = true;
+ }
+
+ if(_stop && !isEdit){
+ dojo.stopEvent(evt);
+ }
+ });
+
+ dojo.connect(document, "keypress", this, function(evt){
+ if(!enabled){ return; }
+ var inc = this.shift ? this.arrowIncrement*this.arrowShiftIncrement : this.arrowIncrement;
+
+ var x =0, y =0;
+ if(evt.keyCode==32 && !isEdit){ //space
+ dojo.stopEvent(evt);
+ }
+ if(evt.keyCode==37){ //left
+ x = -inc;
+ }
+ if(evt.keyCode==38){ //up
+ y = -inc;
+ }
+ if(evt.keyCode==39){ //right
+ x = inc;
+ }
+ if(evt.keyCode==40){ //down
+ y = inc;
+ }
+ if(x || y){
+ evt.x = x;
+ evt.y = y;
+ evt.shift = this.shift;
+ if(!isEdit){
+ this.onArrow(evt);
+ dojo.stopEvent(evt);
+ }
+ }
+ });
+ }
+ };
+ dojo.addOnLoad(dojox.drawing.manager.keys, "init");
+})();
+
+});
diff --git a/js/libs/dojox/drawing/plugins/_Plugin.js b/js/libs/dojox/drawing/plugins/_Plugin.js
new file mode 100644
index 0000000..cbb4914
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/_Plugin.js
@@ -0,0 +1,21 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins._Plugin");
+_3.drawing.plugins._Plugin=_3.drawing.util.oo.declare(function(_4){
+this._cons=[];
+_2.mixin(this,_4);
+if(this.button&&this.onClick){
+this.connect(this.button,"onClick",this,"onClick");
+}
+},{util:null,keys:null,mouse:null,drawing:null,stencils:null,anchors:null,canvas:null,node:null,button:null,type:"dojox.drawing.plugins._Plugin",connect:function(){
+this._cons.push(_2.connect.apply(_2,arguments));
+},disconnect:function(_5){
+if(!_5){
+return;
+}
+if(!_2.isArray(_5)){
+_5=[_5];
+}
+_2.forEach(_5,_2.disconnect,_2);
+}});
+});
diff --git a/js/libs/dojox/drawing/plugins/_Plugin.js.uncompressed.js b/js/libs/dojox/drawing/plugins/_Plugin.js.uncompressed.js
new file mode 100644
index 0000000..44ebd51
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/_Plugin.js.uncompressed.js
@@ -0,0 +1,43 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/_Plugin", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins._Plugin");
+
+dojox.drawing.plugins._Plugin = dojox.drawing.util.oo.declare(
+ // summary:
+ // Base class for plugins.
+ // description:
+ // When creating a plugin, use this class as the
+ // base to ensure full functionality.
+ function(options){
+ this._cons = [];
+ dojo.mixin(this, options);
+ if(this.button && this.onClick){
+ this.connect(this.button, "onClick", this, "onClick")
+ }
+ },
+ {
+ util:null,
+ keys:null,
+ mouse:null,
+ drawing:null,
+ stencils:null,
+ anchors:null,
+ canvas:null,
+ node:null,
+ button:null,//gfx button
+ type:"dojox.drawing.plugins._Plugin",
+ connect: function(){
+ this._cons.push(dojo.connect.apply(dojo, arguments));
+ },
+ disconnect: function(/*handle | Array*/handles){
+ // summary:
+ // Removes connections based on passed
+ // handles arguments
+ if(!handles){ return };
+ if(!dojo.isArray(handles)){ handles=[handles]; }
+ dojo.forEach(handles, dojo.disconnect, dojo);
+ }
+ }
+);
+});
diff --git a/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js b/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js
new file mode 100644
index 0000000..f964e1b
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js
@@ -0,0 +1,134 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/i18n!dojox/editor/plugins/nls/latinEntities","dojo/require!dojox/drawing/library/greek,dijit/focus,dijit/_Widget,dijit/_TemplatedMixin,dijit/_PaletteMixin,dojo/i18n"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.drawing.GreekPalette");
+_2.require("dojox.drawing.library.greek");
+_2.require("dijit.focus");
+_2.require("dijit._Widget");
+_2.require("dijit._TemplatedMixin");
+_2.require("dijit._PaletteMixin");
+_2.require("dojo.i18n");
+_2.requireLocalization("dojox.editor.plugins","latinEntities");
+_2.declare("dojox.drawing.plugins.drawing.GreekPalette",[_1._Widget,_1._TemplatedMixin,_1._PaletteMixin],{postMixInProperties:function(){
+var _4=_3.drawing.library.greek;
+var _5=0;
+var _6;
+for(_6 in _4){
+_5++;
+}
+var _7=Math.floor(Math.sqrt(_5));
+var _8=_7;
+var _9=0;
+var _a=[];
+var _b=[];
+for(_6 in _4){
+_9++;
+_b.push(_6);
+if(_9%_8===0){
+_a.push(_b);
+_b=[];
+}
+}
+if(_b.length>0){
+_a.push(_b);
+}
+this._palette=_a;
+},show:function(_c){
+_2.mixin(_c,{popup:this});
+_1.popup.open(_c);
+},onChange:function(_d){
+var _e=this._textBlock;
+_1.popup.hide(this);
+_e.insertText(this._pushChangeTo,_d);
+_e._dropMode=false;
+},onCancel:function(_f){
+_1.popup.hide(this);
+this._textBlock._dropMode=false;
+},templateString:"\n"+"\t
\n"+"\t\t\n"+"\t\t\t\n"+"\t\t\t\t\n"+"\t\t\t\t\t\n"+"\t\t\t\t\t\t\n"+"\t\t\t\t \n"+"\t\t\t\t | \n"+"\t\t\t
\n"+"\t\t\t\n"+"\t\t\t\t\n"+"\t\t\t\t\t\n"+"\t\t\t\t\t\t\n"+"\t\t\t\t\t\t\t\n"+"\t\t\t\t\t\t\t\tType: | \n"+"\t\t\t\t\t\t\t \n"+"\t\t\t\t\t\t\n"+"\t\t\t\t\t \n"+"\t\t\t\t | \n"+"\t\t\t
\n"+"\t\t\n"+"\t
\n"+"
",baseClass:"dojoxEntityPalette",showPreview:true,dyeClass:"dojox.drawing.plugins.Greeks",paletteClass:"editorLatinEntityPalette",cellClass:"dojoxEntityPaletteCell",buildRendering:function(){
+this.inherited(arguments);
+var _10=_2.i18n.getLocalization("dojox.editor.plugins","latinEntities");
+this._preparePalette(this._palette,_10);
+var _11=_2.query(".dojoxEntityPaletteCell",this.gridNode);
+_2.forEach(_11,function(_12){
+this.connect(_12,"onmouseenter","_onCellMouseEnter");
+},this);
+},_onCellMouseEnter:function(e){
+if(this.showPreview){
+this._displayDetails(e.target);
+}
+},_onCellClick:function(evt){
+var _13=evt.type=="click"?evt.currentTarget:this._currentFocus,_14=this._getDye(_13).getValue();
+this._setCurrent(_13);
+setTimeout(_2.hitch(this,function(){
+_1.focus(_13);
+this._setValueAttr(_14,true);
+}));
+_2.removeClass(_13,"dijitPaletteCellHover");
+_2.stopEvent(evt);
+},postCreate:function(){
+this.inherited(arguments);
+if(!this.showPreview){
+_2.style(this.previewNode,"display","none");
+}
+_1.popup.moveOffScreen(this);
+},_setCurrent:function(_15){
+if("_currentFocus" in this){
+_2.attr(this._currentFocus,"tabIndex","-1");
+_2.removeClass(this._currentFocus,"dojoxEntityPaletteCellHover");
+}
+this._currentFocus=_15;
+if(_15){
+_2.attr(_15,"tabIndex",this.tabIndex);
+_2.addClass(this._currentFocus,"dojoxEntityPaletteCellHover");
+}
+if(this.showPreview){
+this._displayDetails(_15);
+}
+},_displayDetails:function(_16){
+var dye=this._getDye(_16);
+if(dye){
+var _17=dye.getValue();
+var _18=dye._alias;
+this.previewNode.innerHTML=_17;
+}else{
+this.previewNode.innerHTML="";
+this.descNode.innerHTML="";
+}
+},_preparePalette:function(_19,_1a){
+this._cells=[];
+var url=this._blankGif;
+var _1b=_2.getObject(this.dyeClass);
+for(var row=0;row<_19.length;row++){
+var _1c=_2.create("tr",{tabIndex:"-1"},this.gridNode);
+for(var col=0;col<_19[row].length;col++){
+var _1d=_19[row][col];
+if(_1d){
+var _1e=new _1b(_1d);
+var _1f=_2.create("td",{"class":this.cellClass,tabIndex:"-1",title:_1a[_1d]});
+_1e.fillCell(_1f,url);
+this.connect(_1f,"ondijitclick","_onCellClick");
+this._trackMouseState(_1f,this.cellClass);
+_2.place(_1f,_1c);
+_1f.index=this._cells.length;
+this._cells.push({node:_1f,dye:_1e});
+}
+}
+}
+this._xDim=_19[0].length;
+this._yDim=_19.length;
+},_navigateByArrow:function(evt){
+var _20={38:-this._xDim,40:this._xDim,39:this.isLeftToRight()?1:-1,37:this.isLeftToRight()?-1:1};
+var _21=_20[evt.keyCode];
+var _22=this._currentFocus.index+_21;
+if(_22-1){
+var _23=this._cells[_22].node;
+this._setCurrent(_23);
+}
+}});
+_2.declare("dojox.drawing.plugins.Greeks",null,{constructor:function(_24){
+this._alias=_24;
+},getValue:function(){
+return this._alias;
+},fillCell:function(_25){
+_25.innerHTML="&"+this._alias+";";
+}});
+});
diff --git a/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js.uncompressed.js b/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js.uncompressed.js
new file mode 100644
index 0000000..66f21f8
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/drawing/GreekPalette.js.uncompressed.js
@@ -0,0 +1,340 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/drawing/GreekPalette", ["dijit","dojo","dojox","dojo/i18n!dojox/editor/plugins/nls/latinEntities","dojo/require!dojox/drawing/library/greek,dijit/focus,dijit/_Widget,dijit/_TemplatedMixin,dijit/_PaletteMixin,dojo/i18n"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.drawing.GreekPalette");
+
+dojo.require("dojox.drawing.library.greek");
+dojo.require("dijit.focus");
+dojo.require("dijit._Widget");
+dojo.require("dijit._TemplatedMixin");
+dojo.require("dijit._PaletteMixin");
+dojo.require("dojo.i18n");
+
+dojo.requireLocalization("dojox.editor.plugins", "latinEntities");
+
+dojo.declare("dojox.drawing.plugins.drawing.GreekPalette",
+ [dijit._Widget, dijit._TemplatedMixin, dijit._PaletteMixin],
+ {
+ // summary:
+ // This plugin uses the palette dijit in order to give tips for
+ // non-english (mostly greek for now) letters.
+ //
+ // IMPORTANT! Because it is a full blown dijit it is NOT loaded
+ // like the other plugins. INSTEAD currently it is instantiated
+ // in markup. TextBlock LOOKS FOR IT by ID - "greekPalette"
+ // and if it finds it does the necessary initialization/connections.
+ // description:
+ // Grid showing all available entity options which the
+ // user can pick from. The library loaded for use by the picker
+ // is found in dojox.drawing.library.greek. Adding characters
+ // there will automatically add them to the palette.
+ //
+ // This works as a popup and as such its onChange and onCancel
+ // close it. TextBlock manages it, since it's what uses the assist
+ // so it calls show (all actual popup management happens here).
+ // In order to activate the plugin require it and then include the
+ // markup in the example:
+ //
+ // example:
+ // |
+ // |
+
+ postMixInProperties: function(){
+ // Convert hash of entities into two-dimensional rows/columns table (array of arrays)
+ var choices = dojox.drawing.library.greek;
+ var numChoices = 0;
+ var entityKey;
+ for(entityKey in choices){numChoices++;}
+ var choicesPerRow = Math.floor(Math.sqrt(numChoices));
+ var numRows = choicesPerRow;
+ var currChoiceIdx = 0;
+ var rows = [];
+ var row = [];
+ for(entityKey in choices){
+ currChoiceIdx++;
+ row.push(entityKey);
+ if(currChoiceIdx % numRows === 0){
+ rows.push(row);
+ row = [];
+ }
+ }
+ if(row.length > 0){
+ rows.push(row);
+ }
+ this._palette = rows;
+ },
+
+ show: function(obj){
+ dojo.mixin(obj, {popup: this});
+ dijit.popup.open(obj);
+ },
+
+ onChange: function(val){
+ var textBlock = this._textBlock;
+ dijit.popup.hide(this);
+ textBlock.insertText(this._pushChangeTo,val);
+ textBlock._dropMode = false;
+ },
+
+ onCancel: function(/*Boolean*/ closeAll){
+ // summary:
+ // attach point for notification about when the user cancels the current menu
+ dijit.popup.hide(this);
+ this._textBlock._dropMode = false;
+ },
+
+ // templateString: String
+ // The template of this widget. Using dojoxEntityPalette classes
+ // in order to allow easy transfer of css
+ templateString: '\n' +
+ '
\n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' | \n' +
+ '
\n' +
+ ' \n' +
+ ' \n'+
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' Type: | \n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' | \n' +
+ '
\n' +
+ ' \n' +
+ '
\n' +
+ '
',
+
+
+ baseClass: "dojoxEntityPalette",
+
+ // showPreview: [public] Boolean
+ // Whether the preview pane will be displayed, to show details about the selected entity.
+ showPreview: true,
+
+ dyeClass: 'dojox.drawing.plugins.Greeks',
+
+ // domNodeClass [protected] String
+ paletteClass: 'editorLatinEntityPalette',
+
+ cellClass: "dojoxEntityPaletteCell",
+
+ buildRendering: function(){
+ this.inherited(arguments);
+
+ var i18n = dojo.i18n.getLocalization("dojox.editor.plugins", "latinEntities");
+
+ this._preparePalette(
+ this._palette,
+ i18n
+ );
+
+ var cells = dojo.query(".dojoxEntityPaletteCell", this.gridNode);
+ dojo.forEach(cells, function(cellNode){
+ this.connect(cellNode, "onmouseenter", "_onCellMouseEnter");
+ }, this);
+ },
+
+ _onCellMouseEnter: function(e){
+ // summary:
+ // Simple function to handle updating the display at the bottom of
+ // the palette.
+ // e:
+ // The event.
+ // tags:
+ // private
+ if(this.showPreview){
+ this._displayDetails(e.target);
+ }
+ },
+
+ _onCellClick: function(/*Event*/ evt){
+ // summary:
+ // Handler for click, enter key & space key. Selects the cell.
+ // evt:
+ // The event.
+ // tags:
+ // private
+ var target = evt.type == "click" ? evt.currentTarget : this._currentFocus,
+ value = this._getDye(target).getValue();
+
+ // First focus the clicked cell, and then send onChange() notification.
+ // onChange() (via _setValueAttr) must be after the focus call, because
+ // it may trigger a refocus to somewhere else (like the Editor content area), and that
+ // second focus should win.
+ // Use setTimeout because IE doesn't like changing focus inside of an event handler.
+ this._setCurrent(target);
+ setTimeout(dojo.hitch(this, function(){
+ dijit.focus(target);
+ this._setValueAttr(value, true);
+ }));
+
+ // workaround bug where hover class is not removed on popup because the popup is
+ // closed and then there's no onblur event on the cell
+ dojo.removeClass(target, "dijitPaletteCellHover");
+
+ dojo.stopEvent(evt);
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+
+ if(!this.showPreview){
+ dojo.style(this.previewNode,"display","none");
+ }
+ dijit.popup.moveOffScreen(this);
+ },
+
+ _setCurrent: function(/*DOMNode*/ node){
+ // summary:
+ // Sets which node is the focused cell.
+ // description:
+ // At any point in time there's exactly one
+ // cell with tabIndex != -1. If focus is inside the palette then
+ // focus is on that cell.
+ //
+ // After calling this method, arrow key handlers and mouse click handlers
+ // should focus the cell in a setTimeout().
+ // tags:
+ // protected
+ if("_currentFocus" in this){
+ // Remove tabIndex on old cell
+ dojo.attr(this._currentFocus, "tabIndex", "-1");
+ dojo.removeClass(this._currentFocus,"dojoxEntityPaletteCellHover");
+ }
+
+ // Set tabIndex of new cell
+ this._currentFocus = node;
+ if(node){
+ dojo.attr(node, "tabIndex", this.tabIndex);
+ dojo.addClass(this._currentFocus,"dojoxEntityPaletteCellHover");
+ }
+ if(this.showPreview){
+ this._displayDetails(node);
+ }
+ },
+
+ _displayDetails: function(/*DOMNode*/ cell){
+ // summary:
+ // Display the details of the currently focused entity in the preview pane
+ var dye = this._getDye(cell);
+ if(dye){
+ var ehtml = dye.getValue();
+ var ename = dye._alias;
+ //console.warn("Greek help: ",dye._alias);
+ this.previewNode.innerHTML=ehtml;
+ }else{
+ this.previewNode.innerHTML="";
+ this.descNode.innerHTML="";
+ }
+ },
+
+ _preparePalette: function(choices, titles) {
+ // summary:
+ // Subclass must call _preparePalette() from postCreate(), passing in the tooltip
+ // for each cell
+ // choices: String[][]
+ // id's for each cell of the palette, used to create Dye JS object for each cell
+ // titles: String[]
+ // Localized tooltip for each cell
+
+ this._cells = [];
+ var url = this._blankGif;
+
+ var dyeClassObj = dojo.getObject(this.dyeClass);
+
+ for(var row=0; row < choices.length; row++){
+ var rowNode = dojo.create("tr", {tabIndex: "-1"}, this.gridNode);
+ for(var col=0; col < choices[row].length; col++){
+ var value = choices[row][col];
+ if(value){
+ var cellObject = new dyeClassObj(value);
+
+ var cellNode = dojo.create("td", {
+ "class": this.cellClass,
+ tabIndex: "-1",
+ title: titles[value]
+ });
+
+ // prepare cell inner structure
+ cellObject.fillCell(cellNode, url);
+
+ this.connect(cellNode, "ondijitclick", "_onCellClick");
+ this._trackMouseState(cellNode, this.cellClass);
+
+ dojo.place(cellNode, rowNode);
+
+ cellNode.index = this._cells.length;
+
+ // save cell info into _cells
+ this._cells.push({node:cellNode, dye:cellObject});
+ }
+ }
+ }
+ this._xDim = choices[0].length;
+ this._yDim = choices.length;
+
+ },
+
+ _navigateByArrow: function(evt){
+ // summary:
+ // This is a departure from the dijit, the textBlock needs
+ // navigation without losing focus, this allows that
+ // increment:
+ // How much the key is navigated.
+ // tags:
+ // private
+ var keyIncrementMap = {
+ 38: -this._xDim,
+ // The down key the index is increase by the x dimension.
+ 40: this._xDim,
+ // Right and left move the index by 1.
+ 39: this.isLeftToRight() ? 1 : -1,
+ 37: this.isLeftToRight() ? -1 : 1
+ };
+
+ var increment = keyIncrementMap[evt.keyCode];
+ var newFocusIndex = this._currentFocus.index + increment;
+ if(newFocusIndex < this._cells.length && newFocusIndex > -1){
+ var focusNode = this._cells[newFocusIndex].node;
+ this._setCurrent(focusNode);
+ }
+ }
+});
+
+dojo.declare("dojox.drawing.plugins.Greeks",
+ null,
+{
+ // summary:
+ // Represents a character.
+ // Initialized using an alias for the character (like cent) rather
+ // than with the character itself.
+
+ constructor: function(/*String*/ alias){
+ // summary:
+ // Construct JS object representing an entity (associated w/a cell
+ // in the palette)
+ // value: String
+ // alias name: 'cent', 'pound' ..
+ this._alias = alias;
+ },
+
+ getValue: function(){
+ // summary:
+ // Returns HTML representing the character, like &
+ //
+ return this._alias;
+ },
+
+ fillCell: function(/*DOMNode*/ cell){
+ // Deal with entities that have keys which are reserved words.
+ cell.innerHTML = "&"+this._alias+";";
+ }
+});
+});
diff --git a/js/libs/dojox/drawing/plugins/drawing/Grid.js b/js/libs/dojox/drawing/plugins/drawing/Grid.js
new file mode 100644
index 0000000..a34009e
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/drawing/Grid.js
@@ -0,0 +1,47 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.drawing.Grid");
+_2.require("dojox.drawing.plugins._Plugin");
+_3.drawing.plugins.drawing.Grid=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_4){
+if(_4.gap){
+this.major=_4.gap;
+}
+this.majorColor=_4.majorColor||this.majorColor;
+this.minorColor=_4.minorColor||this.minorColor;
+this.setGrid();
+_2.connect(this.canvas,"setZoom",this,"setZoom");
+},{type:"dojox.drawing.plugins.drawing.Grid",gap:100,major:100,minor:0,majorColor:"#00ffff",minorColor:"#d7ffff",zoom:1,setZoom:function(_5){
+this.zoom=_5;
+this.setGrid();
+},setGrid:function(_6){
+var _7=Math.floor(this.major*this.zoom);
+var _8=this.minor?Math.floor(this.minor*this.zoom):_7;
+this.grid&&this.grid.removeShape();
+var x1,x2,y1,y2,i,_9,_a;
+var s=this.canvas.underlay.createGroup();
+var w=2000;
+var h=1000;
+var b=1;
+var mj=this.majorColor;
+var mn=this.minorColor;
+var _b=function(x1,y1,x2,y2,c){
+s.createLine({x1:x1,y1:y1,x2:x2,y2:y2}).setStroke({style:"Solid",width:b,cap:"round",color:c});
+};
+for(i=1,_a=h/_8;i<_a;i++){
+x1=0,x2=w;
+y1=_8*i,y2=y1;
+_9=y1%_7?mn:mj;
+_b(x1,y1,x2,y2,_9);
+}
+for(i=1,_a=w/_8;i<_a;i++){
+y1=0,y2=h;
+x1=_8*i,x2=x1;
+_9=x1%_7?mn:mj;
+_b(x1,y1,x2,y2,_9);
+}
+s.moveToBack();
+this.grid=s;
+this.util.attr(s,"id","grid");
+return s;
+}});
+});
diff --git a/js/libs/dojox/drawing/plugins/drawing/Grid.js.uncompressed.js b/js/libs/dojox/drawing/plugins/drawing/Grid.js.uncompressed.js
new file mode 100644
index 0000000..5ee6109
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/drawing/Grid.js.uncompressed.js
@@ -0,0 +1,102 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/drawing/Grid", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.drawing.Grid");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+dojox.drawing.plugins.drawing.Grid = dojox.drawing.util.oo.declare(
+ // summary:
+ // Plugin that displays a grid on the Drawing canvas.
+ // example:
+ // |
+ // |
+ //
+ dojox.drawing.plugins._Plugin,
+ function(options){
+ if(options.gap){
+ this.major = options.gap;
+ }
+ this.majorColor = options.majorColor || this.majorColor;
+ this.minorColor = options.minorColor || this.minorColor;
+
+ this.setGrid();
+ dojo.connect(this.canvas, "setZoom", this, "setZoom");
+ },
+ {
+ type:"dojox.drawing.plugins.drawing.Grid",
+ //
+ // gap: Number
+ // How far apart to set the grid lines
+ gap:100,
+ major:100,
+ minor:0,
+ //
+ // majorColor: String
+ // Major lines color
+ majorColor: "#00ffff",
+ //
+ // minorColor: String
+ // Minor lines color
+ minorColor: "#d7ffff",
+ //
+ // zoom: [readonly] Number
+ // The current zoom of the grid
+ zoom:1,
+
+ setZoom: function(zoom){
+ // summary:
+ // Set's the zoom of the canvas
+ this.zoom = zoom;
+ this.setGrid();
+ },
+ setGrid: function(options){
+ // summary:
+ // Renders grid
+ //
+ // TODO: major minor lines
+ // minors dont show on zoom out
+ // draw minors first
+ //
+ var mjr = Math.floor(this.major * this.zoom);
+ var mnr = this.minor ? Math.floor(this.minor * this.zoom) : mjr;
+
+ this.grid && this.grid.removeShape();
+
+ var x1,x2,y1,y2,i,clr,len;
+ var s = this.canvas.underlay.createGroup();
+ var w = 2000;//this.canvas.width;
+ var h = 1000;//this.canvas.height;
+ var b = 1;
+ var mj = this.majorColor;
+ var mn = this.minorColor;
+
+ var createGridLine = function(x1,y1,x2,y2, c){
+ s.createLine({x1: x1, y1: y1, x2: x2, y2: y2}).setStroke({style: "Solid", width: b, cap: "round", color:c});
+ };
+
+ // horz
+ for(i=1,len = h/mnr; i>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.drawing.Silverlight");
+_3.drawing.plugins.drawing.Silverlight=_3.drawing.util.oo.declare(function(_4){
+if(_3.gfx.renderer!="silverlight"){
+return;
+}
+this.mouse=_4.mouse;
+this.stencils=_4.stencils;
+this.anchors=_4.anchors;
+this.canvas=_4.canvas;
+this.util=_4.util;
+_2.connect(this.stencils,"register",this,function(_5){
+var c1,c2,c3,c4,c5,_6=this;
+var _7=function(){
+c1=_5.container.connect("onmousedown",function(_8){
+_8.superTarget=_5;
+_6.mouse.down(_8);
+});
+};
+_7();
+c2=_2.connect(_5,"setTransform",this,function(){
+});
+c3=_2.connect(_5,"onBeforeRender",function(){
+});
+c4=_2.connect(_5,"onRender",this,function(){
+});
+c5=_2.connect(_5,"destroy",this,function(){
+_2.forEach([c1,c2,c3,c4,c5],_2.disconnect,_2);
+});
+});
+_2.connect(this.anchors,"onAddAnchor",this,function(_9){
+var c1=_9.shape.connect("onmousedown",this.mouse,function(_a){
+_a.superTarget=_9;
+this.down(_a);
+});
+var c2=_2.connect(_9,"disconnectMouse",this,function(){
+_2.disconnect(c1);
+_2.disconnect(c2);
+});
+});
+this.mouse._down=function(_b){
+var _c=this._getXY(_b);
+var x=_c.x-this.origin.x;
+var y=_c.y-this.origin.y;
+x*=this.zoom;
+y*=this.zoom;
+this.origin.startx=x;
+this.origin.starty=y;
+this._lastx=x;
+this._lasty=y;
+this.drawingType=this.util.attr(_b,"drawingType")||"";
+var id=this._getId(_b);
+var _d={x:x,y:y,id:id};
+this.onDown(_d);
+this._clickTime=new Date().getTime();
+if(this._lastClickTime){
+if(this._clickTime-this._lastClickTime>built
+// wrapped by build app
+define("dojox/drawing/plugins/drawing/Silverlight", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.drawing.Silverlight");
+
+dojox.drawing.plugins.drawing.Silverlight = dojox.drawing.util.oo.declare(
+ // summary:
+ // "Plugin" to allow the Silverlight plugin to work
+ // with DojoX Drawing.
+ //
+ // WARNING: This is not completely implemented. For the most
+ // part, DojoX Drawing does not support Silverlight. This class
+ // was created in an attempt for support, but there were too many
+ // obstacles and not enough time. The basic functionality is here
+ // and there's a good head start if anyone elase wishes to pick up
+ // where I left off.
+ //
+ function(options){
+ // summary:
+ // The constructor is the only method in this class.
+ // What is happening here is other methods in other
+ // classes are being overridden to adapt to Silverlight.
+ //
+
+ if(dojox.gfx.renderer != "silverlight"){ return; }
+ this.mouse = options.mouse;
+ this.stencils = options.stencils;
+ this.anchors = options.anchors;
+ this.canvas = options.canvas;
+ this.util = options.util;
+
+
+ dojo.connect(this.stencils, "register", this, function(item){
+ var c1, c2, c3, c4, c5, self = this;
+ var conMouse = function(){
+ //console.info("------connect shape", item.id)
+
+ // Connect to PARENT (SL Canvas) , not SHAPE
+ c1 = item.container.connect("onmousedown", function(evt){
+ //console.info("----------------------------------SHAPE DOWN", item.container)
+ evt.superTarget = item;
+ self.mouse.down(evt);
+ });
+ }
+ conMouse();
+
+ c2 = dojo.connect(item, "setTransform", this, function(){
+ //dojo.disconnect(c1);
+ });
+
+ c3 = dojo.connect(item, "onBeforeRender", function(){
+ //dojo.disconnect(c1);
+ });
+
+
+ c4 = dojo.connect(item, "onRender", this, function(){
+ //conMouse();
+ });
+
+ c5 = dojo.connect(item, "destroy", this, function(){
+ dojo.forEach([c1,c2,c3,c4,c5], dojo.disconnect, dojo);
+ });
+ });
+
+ dojo.connect(this.anchors, "onAddAnchor", this, function(anchor){
+ var c1 = anchor.shape.connect("onmousedown", this.mouse, function(evt){
+ evt.superTarget = anchor;
+ this.down(evt)
+ });
+ var c2 = dojo.connect(anchor, "disconnectMouse", this, function(){
+ dojo.disconnect(c1);
+ dojo.disconnect(c2);
+ });
+
+ });
+
+
+ this.mouse._down = function(evt){
+ var dim = this._getXY(evt);
+ var x = dim.x - this.origin.x;
+ var y = dim.y - this.origin.y;
+
+ x*= this.zoom;
+ y*= this.zoom;
+
+ this.origin.startx = x;
+ this.origin.starty = y;
+ this._lastx = x;
+ this._lasty = y;
+
+ this.drawingType = this.util.attr(evt, "drawingType") || "";
+ var id = this._getId(evt);
+ var obj = {x:x,y:y, id:id};
+ console.log(" > > > id:", id, "drawingType:", this.drawingType, "evt:", evt)
+
+ this.onDown(obj);
+
+ this._clickTime = new Date().getTime();
+ if(this._lastClickTime){
+ if(this._clickTime-this._lastClickTime>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.tools.Iconize");
+_2.require("dojox.drawing.plugins._Plugin");
+_3.drawing.plugins.tools.Iconize=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_4){
+},{onClick:function(){
+var _5;
+for(var nm in this.stencils.stencils){
+if(this.stencils.stencils[nm].shortType=="path"){
+_5=this.stencils.stencils[nm];
+break;
+}
+}
+if(_5){
+this.makeIcon(_5.points);
+}
+},makeIcon:function(p){
+var _6=function(n){
+return Number(n.toFixed(1));
+};
+var x=10000;
+var y=10000;
+p.forEach(function(pt){
+if(pt.x!==undefined&&!isNaN(pt.x)){
+x=Math.min(x,pt.x);
+y=Math.min(y,pt.y);
+}
+});
+var _7=0;
+var _8=0;
+p.forEach(function(pt){
+if(pt.x!==undefined&&!isNaN(pt.x)){
+pt.x=_6(pt.x-x);
+pt.y=_6(pt.y-y);
+_7=Math.max(_7,pt.x);
+_8=Math.max(_8,pt.y);
+}
+});
+var s=60;
+var m=20;
+p.forEach(function(pt){
+pt.x=_6(pt.x/_7)*s+m;
+pt.y=_6(pt.y/_8)*s+m;
+});
+var _9="[\n";
+_2.forEach(p,function(pt,i){
+_9+="{\t";
+if(pt.t){
+_9+="t:'"+pt.t+"'";
+}
+if(pt.x!==undefined&&!isNaN(pt.x)){
+if(pt.t){
+_9+=", ";
+}
+_9+="x:"+pt.x+",\t\ty:"+pt.y;
+}
+_9+="\t}";
+if(i!=p.length-1){
+_9+=",";
+}
+_9+="\n";
+});
+_9+="]";
+var n=_2.byId("data");
+if(n){
+n.value=_9;
+}
+}});
+_3.drawing.plugins.tools.Iconize.setup={name:"dojox.drawing.plugins.tools.Iconize",tooltip:"Iconize Tool",iconClass:"iconPan"};
+_3.drawing.register(_3.drawing.plugins.tools.Iconize.setup,"plugin");
+});
diff --git a/js/libs/dojox/drawing/plugins/tools/Iconize.js.uncompressed.js b/js/libs/dojox/drawing/plugins/tools/Iconize.js.uncompressed.js
new file mode 100644
index 0000000..6d2437c
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/tools/Iconize.js.uncompressed.js
@@ -0,0 +1,104 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/tools/Iconize", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.tools.Iconize");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+dojox.drawing.plugins.tools.Iconize = dojox.drawing.util.oo.declare(
+ // summary:
+ // Somewhat of internal use...
+ // Outputs a path to be used as an icon. Will end up being a
+ // sub-icon under Export options
+
+ dojox.drawing.plugins._Plugin,
+ function(options){
+
+ },
+ {
+ onClick: function(){
+ var item;
+ for(var nm in this.stencils.stencils){
+ console.log(" stanceil item:", this.stencils.stencils[nm].id, this.stencils.stencils[nm])
+ if(this.stencils.stencils[nm].shortType=="path"){
+ item = this.stencils.stencils[nm];
+ break;
+ }
+ }
+ if(item){
+ console.log("click Iconize plugin", item.points);
+ this.makeIcon(item.points);
+ }
+ },
+ makeIcon: function(/*Array*/p){
+ var rnd = function(n){
+ return Number(n.toFixed(1));
+ }
+
+ var x = 10000;
+ var y = 10000;
+ p.forEach(function(pt){
+ if(pt.x!==undefined && !isNaN(pt.x)){
+ x = Math.min(x, pt.x);
+ y = Math.min(y, pt.y);
+ }
+ });
+
+ var xmax = 0;
+ var ymax = 0;
+ p.forEach(function(pt){
+ if(pt.x!==undefined && !isNaN(pt.x)){
+ pt.x = rnd(pt.x - x);
+ //console.log("Y:", pt.y, y, pt.y - y)
+ pt.y = rnd(pt.y - y);
+ xmax = Math.max(xmax, pt.x);
+ ymax = Math.max(ymax, pt.y);
+ }
+ });
+
+ console.log("xmax:", xmax, "ymax:", ymax)
+
+ var s = 60
+ var m = 20
+
+ p.forEach(function(pt){
+ pt.x = rnd(pt.x / xmax) * s + m;
+ pt.y = rnd(pt.y / ymax) * s + m;
+ });
+
+ var txt = "[\n";
+ dojo.forEach(p, function(pt, i){
+ txt += "{\t"
+ if(pt.t){
+ txt += "t:'"+pt.t+"'"
+ }
+ if(pt.x!==undefined && !isNaN(pt.x)){
+ if(pt.t){
+ txt += ", ";
+ }
+ txt += "x:"+pt.x+",\t\ty:"+pt.y;
+ }
+ txt += "\t}";
+ if(i!=p.length-1){
+ txt += ","
+ }
+ txt += "\n"
+ });
+ txt+="]"
+
+ console.log(txt)
+ var n = dojo.byId("data");
+ if(n){
+ n.value = txt;
+ }
+ }
+ }
+);
+
+dojox.drawing.plugins.tools.Iconize.setup = {
+ name:"dojox.drawing.plugins.tools.Iconize",
+ tooltip:"Iconize Tool",
+ iconClass:"iconPan"
+};
+
+dojox.drawing.register(dojox.drawing.plugins.tools.Iconize.setup, "plugin");
+});
diff --git a/js/libs/dojox/drawing/plugins/tools/Pan.js b/js/libs/dojox/drawing/plugins/tools/Pan.js
new file mode 100644
index 0000000..29cf9fc
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/tools/Pan.js
@@ -0,0 +1,141 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.tools.Pan");
+_2.require("dojox.drawing.plugins._Plugin");
+_3.drawing.plugins.tools.Pan=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_4){
+this.domNode=_4.node;
+var _5;
+this.toolbar=_4.scope;
+this.connect(this.toolbar,"onToolClick",this,function(){
+this.onSetPan(false);
+});
+this.connect(this.keys,"onKeyUp",this,"onKeyUp");
+this.connect(this.keys,"onKeyDown",this,"onKeyDown");
+this.connect(this.keys,"onArrow",this,"onArrow");
+this.connect(this.anchors,"onAnchorUp",this,"checkBounds");
+this.connect(this.stencils,"register",this,"checkBounds");
+this.connect(this.canvas,"resize",this,"checkBounds");
+this.connect(this.canvas,"setZoom",this,"checkBounds");
+this.connect(this.canvas,"onScroll",this,function(){
+if(this._blockScroll){
+this._blockScroll=false;
+return;
+}
+_5&&clearTimeout(_5);
+_5=setTimeout(_2.hitch(this,"checkBounds"),200);
+});
+this._mouseHandle=this.mouse.register(this);
+},{selected:false,keyScroll:false,type:"dojox.drawing.plugins.tools.Pan",onPanUp:function(_6){
+if(_6.id==this.button.id){
+this.onSetPan(false);
+}
+},onKeyUp:function(_7){
+switch(_7.keyCode){
+case 32:
+this.onSetPan(false);
+break;
+case 39:
+case 37:
+case 38:
+case 40:
+clearInterval(this._timer);
+break;
+}
+},onKeyDown:function(_8){
+if(_8.keyCode==32){
+this.onSetPan(true);
+}
+},interval:20,onArrow:function(_9){
+if(this._timer){
+clearInterval(this._timer);
+}
+this._timer=setInterval(_2.hitch(this,function(_a){
+this.canvas.domNode.parentNode.scrollLeft+=_a.x*10;
+this.canvas.domNode.parentNode.scrollTop+=_a.y*10;
+},_9),this.interval);
+},onSetPan:function(_b){
+if(_b===true||_b===false){
+this.selected=!_b;
+}
+if(this.selected){
+this.selected=false;
+this.button.deselect();
+}else{
+this.selected=true;
+this.button.select();
+}
+this.mouse.setEventMode(this.selected?"pan":"");
+},onPanDrag:function(_c){
+var x=_c.x-_c.last.x;
+var y=_c.y-_c.last.y;
+this.canvas.domNode.parentNode.scrollTop-=_c.move.y;
+this.canvas.domNode.parentNode.scrollLeft-=_c.move.x;
+this.canvas.onScroll();
+},onUp:function(_d){
+if(_d.withinCanvas){
+this.keyScroll=true;
+}else{
+this.keyScroll=false;
+}
+},onStencilUp:function(_e){
+this.checkBounds();
+},onStencilDrag:function(_f){
+},checkBounds:function(){
+var log=function(){
+};
+var _10=function(){
+};
+var t=Infinity,r=-Infinity,b=-10000,l=10000,sx=0,sy=0,dy=0,dx=0,mx=this.stencils.group?this.stencils.group.getTransform():{dx:0,dy:0},sc=this.mouse.scrollOffset(),scY=sc.left?10:0,scX=sc.top?10:0,ch=this.canvas.height,cw=this.canvas.width,z=this.canvas.zoom,pch=this.canvas.parentHeight,pcw=this.canvas.parentWidth;
+this.stencils.withSelected(function(m){
+var o=m.getBounds();
+_10("SEL BOUNDS:",o);
+t=Math.min(o.y1+mx.dy,t);
+r=Math.max(o.x2+mx.dx,r);
+b=Math.max(o.y2+mx.dy,b);
+l=Math.min(o.x1+mx.dx,l);
+});
+this.stencils.withUnselected(function(m){
+var o=m.getBounds();
+_10("UN BOUNDS:",o);
+t=Math.min(o.y1,t);
+r=Math.max(o.x2,r);
+b=Math.max(o.y2,b);
+l=Math.min(o.x1,l);
+log("----------- B:",b,o.y2);
+});
+b*=z;
+var _11=0,_12=0;
+log("Bottom test","b:",b,"z:",z,"ch:",ch,"pch:",pch,"top:",sc.top,"sy:",sy,"mx.dy:",mx.dy);
+if(b>pch||sc.top){
+log("*bottom scroll*");
+ch=Math.max(b,pch+sc.top);
+sy=sc.top;
+_11+=this.canvas.getScrollWidth();
+}else{
+if(!sy&&ch>pch){
+log("*bottom remove*");
+ch=pch;
+}
+}
+r*=z;
+if(r>pcw||sc.left){
+cw=Math.max(r,pcw+sc.left);
+sx=sc.left;
+_12+=this.canvas.getScrollWidth();
+}else{
+if(!sx&&cw>pcw){
+cw=pcw;
+}
+}
+cw+=_11*2;
+ch+=_12*2;
+this._blockScroll=true;
+this.stencils.group&&this.stencils.group.applyTransform({dx:dx,dy:dy});
+this.stencils.withUnselected(function(m){
+m.transformPoints({dx:dx,dy:dy});
+});
+this.canvas.setDimensions(cw,ch,sx,sy);
+}});
+_3.drawing.plugins.tools.Pan.setup={name:"dojox.drawing.plugins.tools.Pan",tooltip:"Pan Tool",iconClass:"iconPan",button:false};
+_3.drawing.register(_3.drawing.plugins.tools.Pan.setup,"plugin");
+});
diff --git a/js/libs/dojox/drawing/plugins/tools/Pan.js.uncompressed.js b/js/libs/dojox/drawing/plugins/tools/Pan.js.uncompressed.js
new file mode 100644
index 0000000..2cd3d68
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/tools/Pan.js.uncompressed.js
@@ -0,0 +1,246 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/tools/Pan", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.tools.Pan");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+dojox.drawing.plugins.tools.Pan = dojox.drawing.util.oo.declare(
+ // summary:
+ // A plugin that allows for a scrolling canvas. An action
+ // tool is added to the toolbar that allows for panning. Holding
+ // the space bar is a shortcut to that action. The canvas will
+ // only pan and scroll if there are objects out of the viewable
+ // area.
+ // example:
+ // |
+ //
+ dojox.drawing.plugins._Plugin,
+ function(options){
+ this.domNode = options.node;
+ var _scrollTimeout;
+ this.toolbar = options.scope;
+ this.connect(this.toolbar, "onToolClick", this, function(){
+ this.onSetPan(false)
+ });
+ this.connect(this.keys, "onKeyUp", this, "onKeyUp");
+ this.connect(this.keys, "onKeyDown", this, "onKeyDown");
+ this.connect(this.keys, "onArrow", this, "onArrow");
+ this.connect(this.anchors, "onAnchorUp", this, "checkBounds");
+ this.connect(this.stencils, "register", this, "checkBounds");
+ this.connect(this.canvas, "resize", this, "checkBounds");
+ this.connect(this.canvas, "setZoom", this, "checkBounds");
+ this.connect(this.canvas, "onScroll", this, function(){
+ if(this._blockScroll){
+ this._blockScroll = false;
+ return;
+ }
+ _scrollTimeout && clearTimeout(_scrollTimeout);
+ _scrollTimeout = setTimeout(dojo.hitch(this, "checkBounds"), 200);
+ });
+ this._mouseHandle = this.mouse.register(this);
+ // This HAS to be called after setting initial objects or things get screwy.
+ //this.checkBounds();
+
+ },{
+ selected:false,
+ keyScroll:false,
+ type:"dojox.drawing.plugins.tools.Pan",
+
+ onPanUp: function(obj){
+ if(obj.id == this.button.id){
+ this.onSetPan(false);
+ }
+ },
+
+ onKeyUp: function(evt){
+ switch(evt.keyCode){
+ case 32:
+ this.onSetPan(false);
+ break;
+ case 39: case 37: case 38: case 40:
+ clearInterval(this._timer);
+ break;
+ }
+ },
+
+ onKeyDown: function(evt){
+ if(evt.keyCode == 32){
+ this.onSetPan(true);
+ }
+ },
+
+ interval: 20,
+
+ onArrow: function(evt){
+ if(this._timer){ clearInterval(this._timer); }
+ this._timer = setInterval(dojo.hitch(this,function(evt){
+ this.canvas.domNode.parentNode.scrollLeft += evt.x*10;
+ this.canvas.domNode.parentNode.scrollTop += evt.y*10;
+ },evt), this.interval);
+ },
+
+ onSetPan: function(/*Boolean | Event*/ bool){
+ if(bool === true || bool === false){
+ this.selected = !bool;
+ }
+ console.log('ON SET PAN:', this.selected)
+ if(this.selected){
+ this.selected = false;
+ this.button.deselect();
+ }else{
+ this.selected = true;
+ this.button.select();
+ }
+ this.mouse.setEventMode(this.selected ? "pan" : "");
+ },
+
+ onPanDrag: function(obj){
+ var x = obj.x - obj.last.x;
+ var y = obj.y - obj.last.y;
+ this.canvas.domNode.parentNode.scrollTop -= obj.move.y;
+ this.canvas.domNode.parentNode.scrollLeft -= obj.move.x;
+ this.canvas.onScroll();
+ },
+
+ onUp: function(obj){
+ if(obj.withinCanvas){
+ this.keyScroll = true;
+ }else{
+ this.keyScroll = false;
+ }
+ },
+
+ onStencilUp: function(obj){
+ // this gets called even on click-off because of the
+ // issues with TextBlock deselection
+ this.checkBounds();
+ },
+ onStencilDrag: function(obj){
+ // this gets called even on click-off because of the
+ // issues with TextBlock deselection
+ //this.checkBounds();
+ },
+
+ checkBounds: function(){
+
+ //watch("CHECK BOUNDS DISABLED", true); return;
+
+
+ // summary:
+ // Scans all items on the canvas and checks if they are out of
+ // bounds. If so, a scroll bar (in Canvas) is shown. If the position
+ // is left or top, the canvas is scrolled all items are relocated
+ // the distance of the scroll. Ideally, it should look as if the
+ // items do not move.
+
+ // logging stuff here so it can be turned on and off. This method is
+ // very high maintenance.
+ var log = function(){
+ //console.log.apply(console, arguments);
+ }
+ var warn = function(){
+ //console.warn.apply(console, arguments);
+ }
+ //console.clear();
+ //console.time("check bounds");
+
+ // initialize a shot-tin of vars
+ var t=Infinity, r=-Infinity, b=-10000, l=10000,
+ sx=0, sy=0, dy=0, dx=0,
+ mx = this.stencils.group ? this.stencils.group.getTransform() : {dx:0, dy:0},
+ sc = this.mouse.scrollOffset(),
+ // scY, scX: the scrollbar creates the need for extra dimension
+ scY = sc.left ? 10 : 0,
+ scX = sc.top ? 10 : 0,
+ // ch, cw: the current size of the canvas
+ ch = this.canvas.height,
+ cw = this.canvas.width,
+ z = this.canvas.zoom,
+ // pch, pcw: the normal size of the canvas (not scrolled)
+ // these could change if the container resizes.
+ pch = this.canvas.parentHeight,
+ pcw = this.canvas.parentWidth;
+
+
+ this.stencils.withSelected(function(m){
+ var o = m.getBounds();
+ warn("SEL BOUNDS:", o);
+ t = Math.min(o.y1 + mx.dy, t);
+ r = Math.max(o.x2 + mx.dx, r);
+ b = Math.max(o.y2 + mx.dy, b);
+ l = Math.min(o.x1 + mx.dx, l);
+ });
+
+ this.stencils.withUnselected(function(m){
+ var o = m.getBounds();
+ warn("UN BOUNDS:", o);
+ t = Math.min(o.y1, t);
+ r = Math.max(o.x2, r);
+ b = Math.max(o.y2, b);
+ l = Math.min(o.x1, l);
+ log("----------- B:", b, o.y2)
+ });
+
+ b *= z;
+ var xscroll = 0, yscroll = 0;
+ log("Bottom test", "b:", b, "z:", z, "ch:", ch, "pch:", pch, "top:", sc.top, "sy:", sy, "mx.dy:", mx.dy);
+ if(b > pch || sc.top ){
+ log("*bottom scroll*");
+ // item off bottom
+ ch = Math.max(b, pch + sc.top);
+ sy = sc.top;
+ xscroll += this.canvas.getScrollWidth();
+ }else if(!sy && ch>pch){
+ log("*bottom remove*");
+ // item moved from bottom
+ ch = pch;
+ }
+
+ r *= z;
+ if(r > pcw || sc.left){
+ //log("*right scroll*");
+ // item off right
+ cw = Math.max(r, pcw + sc.left);
+ sx = sc.left;
+ yscroll += this.canvas.getScrollWidth();
+ }else if(!sx && cw>pcw){
+ //log("*right remove*");
+ // item moved from right
+ cw = pcw;
+ }
+
+ // add extra space for scrollbars
+ // double it to give some breathing room
+ cw += xscroll*2;
+ ch += yscroll*2;
+
+ this._blockScroll = true;
+
+ // selected items are not transformed. The selection itself is
+ // and the items are on de-select
+ this.stencils.group && this.stencils.group.applyTransform({dx:dx, dy:dy});
+
+ // non-selected items are transformed
+ this.stencils.withUnselected(function(m){
+ m.transformPoints({dx:dx, dy:dy});
+ });
+
+ this.canvas.setDimensions(cw, ch, sx, sy);
+
+ //console.timeEnd("check bounds");
+ }
+ }
+);
+
+dojox.drawing.plugins.tools.Pan.setup = {
+ name:"dojox.drawing.plugins.tools.Pan",
+ tooltip:"Pan Tool",
+ iconClass:"iconPan",
+ button:false
+};
+
+dojox.drawing.register(dojox.drawing.plugins.tools.Pan.setup, "plugin");
+});
diff --git a/js/libs/dojox/drawing/plugins/tools/Zoom.js b/js/libs/dojox/drawing/plugins/tools/Zoom.js
new file mode 100644
index 0000000..e7efa23
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/tools/Zoom.js
@@ -0,0 +1,42 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.plugins.tools.Zoom");
+_2.require("dojox.drawing.plugins._Plugin");
+(function(){
+var _4=Math.pow(2,0.25),_5=10,_6=0.1,_7=1,dt=_3.drawing.plugins.tools;
+dt.ZoomIn=_3.drawing.util.oo.declare(function(_8){
+},{});
+dt.ZoomIn=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_9){
+},{type:"dojox.drawing.plugins.tools.ZoomIn",onZoomIn:function(){
+_7*=_4;
+_7=Math.min(_7,_5);
+this.canvas.setZoom(_7);
+this.mouse.setZoom(_7);
+},onClick:function(){
+this.onZoomIn();
+}});
+dt.Zoom100=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_a){
+},{type:"dojox.drawing.plugins.tools.Zoom100",onZoom100:function(){
+_7=1;
+this.canvas.setZoom(_7);
+this.mouse.setZoom(_7);
+},onClick:function(){
+this.onZoom100();
+}});
+dt.ZoomOut=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_b){
+},{type:"dojox.drawing.plugins.tools.ZoomOut",onZoomOut:function(){
+_7/=_4;
+_7=Math.max(_7,_6);
+this.canvas.setZoom(_7);
+this.mouse.setZoom(_7);
+},onClick:function(){
+this.onZoomOut();
+}});
+dt.ZoomIn.setup={name:"dojox.drawing.plugins.tools.ZoomIn",tooltip:"Zoom In"};
+_3.drawing.register(dt.ZoomIn.setup,"plugin");
+dt.Zoom100.setup={name:"dojox.drawing.plugins.tools.Zoom100",tooltip:"Zoom to 100%"};
+_3.drawing.register(dt.Zoom100.setup,"plugin");
+dt.ZoomOut.setup={name:"dojox.drawing.plugins.tools.ZoomOut",tooltip:"Zoom In"};
+_3.drawing.register(dt.ZoomOut.setup,"plugin");
+})();
+});
diff --git a/js/libs/dojox/drawing/plugins/tools/Zoom.js.uncompressed.js b/js/libs/dojox/drawing/plugins/tools/Zoom.js.uncompressed.js
new file mode 100644
index 0000000..a35073f
--- /dev/null
+++ b/js/libs/dojox/drawing/plugins/tools/Zoom.js.uncompressed.js
@@ -0,0 +1,129 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/plugins/tools/Zoom", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.plugins.tools.Zoom");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+(function(){
+ //
+ // zoomInc: Float
+ // The amount of zoom that will occur upon each click.
+ var zoomInc = Math.pow(2.0,0.25),
+ //
+ // maxZoom: Number
+ // The maximum the canvas can be zoomed in. 10 = 1000%
+ maxZoom = 10,
+ //
+ // minZoom: Float
+ // The most the canvas can be zoomed out. .1 = 10%
+ minZoom = 0.1,
+ //
+ // zoomFactor: [readonly] Float
+ // The current zoom amount
+ zoomFactor = 1,
+
+ dt = dojox.drawing.plugins.tools;
+
+ dt.ZoomIn = dojox.drawing.util.oo.declare(
+ // summary:
+ // A plugin that allows for zooming the canvas in and out. An
+ // action-tool is added to the toolbar with plus, minus and 100%
+ // buttons.
+ //
+ function(options){
+ // mix in private vars
+
+ },
+ {}
+ );
+
+
+ dt.ZoomIn = dojox.drawing.util.oo.declare(
+ // summary:
+ dojox.drawing.plugins._Plugin,
+ function(options){
+
+ },
+ {
+ type:"dojox.drawing.plugins.tools.ZoomIn",
+ onZoomIn: function(){
+ // summary:
+ // Handles zoom in.
+ //
+ zoomFactor *= zoomInc;
+ zoomFactor = Math.min(zoomFactor, maxZoom);
+ this.canvas.setZoom(zoomFactor);
+ this.mouse.setZoom(zoomFactor);
+ },
+ onClick: function(){
+ this.onZoomIn();
+ }
+ }
+ );
+
+ dt.Zoom100 = dojox.drawing.util.oo.declare(
+ // summary:
+ dojox.drawing.plugins._Plugin,
+ function(options){
+
+ },
+ {
+ type:"dojox.drawing.plugins.tools.Zoom100",
+ onZoom100: function(){
+ // summary:
+ // Zooms to 100%
+ //
+ zoomFactor = 1;
+ this.canvas.setZoom(zoomFactor);
+ this.mouse.setZoom(zoomFactor);
+ },
+ onClick: function(){
+ this.onZoom100();
+ }
+ }
+ );
+
+ dt.ZoomOut = dojox.drawing.util.oo.declare(
+ // summary:
+ dojox.drawing.plugins._Plugin,
+ function(options){
+
+ },
+ {
+ type:"dojox.drawing.plugins.tools.ZoomOut",
+ onZoomOut: function(){
+ // summary:
+ // Handles zoom out.
+ //
+ zoomFactor /= zoomInc;
+ zoomFactor = Math.max(zoomFactor, minZoom);
+ this.canvas.setZoom(zoomFactor);
+ this.mouse.setZoom(zoomFactor);
+ },
+ onClick: function(){
+ this.onZoomOut();
+ }
+ }
+ );
+
+
+ dt.ZoomIn.setup = {
+ name:"dojox.drawing.plugins.tools.ZoomIn",
+ tooltip:"Zoom In"
+ };
+ dojox.drawing.register(dt.ZoomIn.setup, "plugin");
+
+ dt.Zoom100.setup = {
+ name:"dojox.drawing.plugins.tools.Zoom100",
+ tooltip:"Zoom to 100%"
+ };
+ dojox.drawing.register(dt.Zoom100.setup, "plugin");
+
+ dt.ZoomOut.setup = {
+ name:"dojox.drawing.plugins.tools.ZoomOut",
+ tooltip:"Zoom In"
+ };
+ dojox.drawing.register(dt.ZoomOut.setup, "plugin");
+
+})();
+});
diff --git a/js/libs/dojox/drawing/resources/CrazyTruck.jpg b/js/libs/dojox/drawing/resources/CrazyTruck.jpg
new file mode 100644
index 0000000..bc270ec
Binary files /dev/null and b/js/libs/dojox/drawing/resources/CrazyTruck.jpg differ
diff --git a/js/libs/dojox/drawing/resources/GreekPalette.css b/js/libs/dojox/drawing/resources/GreekPalette.css
new file mode 100644
index 0000000..9cead7e
--- /dev/null
+++ b/js/libs/dojox/drawing/resources/GreekPalette.css
@@ -0,0 +1,44 @@
+
+.dojoxEntityPalette {
+
+ border: 1px solid #999;
+ background: #fff;
+ -moz-border-radius: 3pt;
+}
+.dojoxEntityPaletteCell {
+
+ border: 1px dotted gray;
+ width: 20px;
+ line-height: 18px;
+ overflow: hidden;
+ z-index: 10;
+ text-align: center;
+}
+.dojoxEntityPaletteCell:hover, .dojoxEntityPaletteCell:active, .dojoxEntityPaletteCell:focus {
+ width: 18px;
+ line-height: 16px;
+ overflow: hidden;
+ cursor: default;
+ border:1px dashed #000;
+ outline:1px dashed #dedede;
+}
+.dojoxEntityPalettePreviewTable {
+ table-layout: auto;
+ font-size: 1em;
+ width: 100%;
+}
+.dojoxEntityPalettePreviewHeader {
+ font-size: .8em;
+ padding: 3px 3px 3px 3px;
+}
+.dojoxEntityPalettePreviewDetailEntity {
+ font-size: .8em;
+ font-weight: bold;
+}
+.dojoxEntityPalettePreviewDetail {
+ font-size: .8em;
+ padding: 3px 3px 3px 3px;
+}
+.dijit_a11y .dojoxEntityPaletteCell {
+ background-color:transparent !important;
+}
diff --git a/js/libs/dojox/drawing/resources/drawing.css b/js/libs/dojox/drawing/resources/drawing.css
new file mode 100644
index 0000000..e8db91e
--- /dev/null
+++ b/js/libs/dojox/drawing/resources/drawing.css
@@ -0,0 +1,36 @@
+html, body{
+ width:100%;
+ height:100%;
+ font-family:sans-serif;
+}
+.textAnnotation{
+ position:absolute;
+ border:1px solid #ccc;
+ background-color:#ffff00;
+ color:#0000ff;
+ padding:3px;
+ font-family:sans-serif;
+ font-size:12px;
+ margin-top:-10px;
+ z-index:501;
+}
+#conEdit{
+ border:0;
+
+ padding:3px;
+ margin:0;
+}
+.drawingTooltip{
+ font-family:sans-serif;
+ font-family:sans-serif;
+ font-weight:normal;
+ padding:5px;
+}
+.drawingTipTitle{
+ font-size:12px;
+ font-weight:bold;
+}
+.drawingTipDesc{
+ font-size:11px;
+ padding-left:10px;
+}
\ No newline at end of file
diff --git a/js/libs/dojox/drawing/resources/images/tool_icons.png b/js/libs/dojox/drawing/resources/images/tool_icons.png
new file mode 100755
index 0000000..74eaee9
Binary files /dev/null and b/js/libs/dojox/drawing/resources/images/tool_icons.png differ
diff --git a/js/libs/dojox/drawing/resources/images/tool_sprites.png b/js/libs/dojox/drawing/resources/images/tool_sprites.png
new file mode 100644
index 0000000..d80bd4d
Binary files /dev/null and b/js/libs/dojox/drawing/resources/images/tool_sprites.png differ
diff --git a/js/libs/dojox/drawing/resources/toolbar.css b/js/libs/dojox/drawing/resources/toolbar.css
new file mode 100644
index 0000000..e964938
--- /dev/null
+++ b/js/libs/dojox/drawing/resources/toolbar.css
@@ -0,0 +1,179 @@
+
+.horizontal.drawingToolbar{
+ position:relative;
+ width:auto;
+ height:32px;
+ padding:5px;
+ left:5px;
+}
+.vertical.drawingToolbar{
+ width:32px;
+ padding:5px;
+ position:absolute;
+ left:5px;
+ margin-top:5px;
+ background:#fff;
+}
+.drawingToolbar .drawingButton{
+ position:relative;
+ padding:0;
+ width:32px;
+ height:32px;
+ background-image:url("images/tool_sprites.png");
+ background-position:0px 0px;
+ border:0;
+ cursor:pointer;
+}
+.horizontal.drawingToolbar .drawingButton{
+ float:left;
+ margin-right:5px;
+}
+.dj_ie6 .drawingToolbar .drawingButton {
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale src='images/tool_sprites.png');
+}
+.vertical.drawingToolbar .drawingButton{
+ margin-bottom:5px;
+ margin-right:0px;
+}
+.drawingToolbar .drawingButton.hover{
+ background-position:-32px 0px;
+}
+.drawingToolbar .drawingButton.active{
+ background-position:-64px 0px;
+}
+.drawingToolbar .drawingButton.selected{
+ background-position:-96px 0px;
+}
+.drawingToolbar .drawingButton.selected:hover{}
+.drawingToolbar.vertical{}
+.drawingToolbar .drawingButton .icon{
+ background-image:url("images/tool_icons.png");
+ width:32px;
+ height:64px;
+ position:absolute;
+ left:0px;
+ top:0px;
+ margin:0;
+ padding:0;
+ clip: rect(0px 32px 32px 0px);
+}
+.drawingToolbar .drawingButton.selected .icon{
+
+ top:-32px;
+ clip: rect(32px 32px 64px 0px);
+}
+.drawingToolbar .drawingButton .icon.iconLine{
+ background-position:-64px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconRect{
+ background-position: 0px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconEllipse{
+ background-position:-32px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconText{
+ background-position:-224px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconArrow{
+ background-position:-96px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconVector{
+ background-position:-128px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconAxes{
+ background-position:-160px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconPan{
+ background-position:-192px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconEq{
+ background-position:-351px 0px;
+}
+.dj_ie6 .drawingToolbar .drawingButton .icon {
+
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale src='images/tool_icons.png');
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboTop{
+ background-position:-128px 0px;
+ margin:0;
+ margin-top:10px;
+ border-bottom:1px solid #d6d6d6;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboTop.hover{
+ background-position:-160px 0px;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboTop.active{
+ background-position:-192px 0px;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboMid{
+ background-position:-384px 0px;
+ border-style:solid;
+ border-width:1px;
+ border-color:#fff #cccccc #d6d6d6 #cccccc;
+ height:24px;
+ width:30px;
+ margin:0;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboMid.hover,
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboMid.hover{
+ background-position:-416px 0px;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboMid.active,
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboMid.active{
+ background-position:-448px 0px;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboBot{
+ background-position:-256px 0px;
+ border-top:1px solid #fff;
+ margin:0;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboBot.hover{
+ background-position:-288px 0px;
+}
+.drawingToolbar.vertical .toolCombo .drawingButton.toolComboBot.active{
+ background-position:-320px 0px;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop{
+ background-position:-512px 0px;
+ margin:0;
+ margin-left:10px;
+ border:0px;
+ border-right:1px solid #d6d6d6;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop.hover{
+ background-position:-544px 0px;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop.active{
+ background-position:-576px 0px;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboMid{
+ background-position:-384px 0px;
+ border-style:solid;
+ border-width:1px;
+ border-color:#cccccc #d6d6d6 #cccccc #fff;
+ height:30px;
+ width:31px;
+ margin:0;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboBot{
+ background-position:-640px 0px;
+ border-left:1px solid #fff;
+ margin:0;
+ margin-top:-1px;
+ margin-right:-1px;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboBot.hover{
+ background-position:-673px 0px;
+}
+.drawingToolbar.horizontal .toolCombo .drawingButton.toolComboBot.active{
+ background-position:-704px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconZoomIn{
+ background-position:-256px 0px;
+}
+.drawingToolbar .drawingButton .icon.iconZoom100{
+ background-position:-320px -4px;
+}
+.drawingToolbar .drawingButton .icon.iconZoomOut{
+ background-position:-288px 0px;
+}
diff --git a/js/libs/dojox/drawing/stencil/Ellipse.js b/js/libs/dojox/drawing/stencil/Ellipse.js
new file mode 100644
index 0000000..a2ecb1b
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Ellipse.js
@@ -0,0 +1,26 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Ellipse");
+_3.drawing.stencil.Ellipse=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+},{type:"dojox.drawing.stencil.Ellipse",anchorType:"group",baseRender:true,dataToPoints:function(o){
+o=o||this.data;
+var x=o.cx-o.rx,y=o.cy-o.ry,w=o.rx*2,h=o.ry*2;
+this.points=[{x:x,y:y},{x:x+w,y:y},{x:x+w,y:y+h},{x:x,y:y+h}];
+return this.points;
+},pointsToData:function(p){
+p=p||this.points;
+var s=p[0];
+var e=p[2];
+this.data={cx:s.x+(e.x-s.x)/2,cy:s.y+(e.y-s.y)/2,rx:(e.x-s.x)*0.5,ry:(e.y-s.y)*0.5};
+return this.data;
+},_create:function(_5,d,_6){
+this.remove(this[_5]);
+this[_5]=this.container.createEllipse(d).setStroke(_6).setFill(_6.fill);
+this._setNodeAtts(this[_5]);
+},render:function(){
+this.onBeforeRender(this);
+this.renderHit&&this._create("hit",this.data,this.style.currentHit);
+this._create("shape",this.data,this.style.current);
+}});
+_3.drawing.register({name:"dojox.drawing.stencil.Ellipse"},"stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Ellipse.js.uncompressed.js b/js/libs/dojox/drawing/stencil/Ellipse.js.uncompressed.js
new file mode 100644
index 0000000..66ecad7
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Ellipse.js.uncompressed.js
@@ -0,0 +1,104 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/stencil/Ellipse", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Ellipse");
+
+/*=====
+__StencilData = {
+ // summary:
+ // the data used to create the dojox.gfx Shape
+ //
+
+ // cx: Number
+ // Center point x
+ cx:0,
+ // cy: Number
+ // Center point y
+ cy:0,
+ // rx: Number
+ // Horizontal radius
+ rx:0,
+ // ry: Number
+ // Vertical radius
+ ry:0
+}
+=====*/
+
+dojox.drawing.stencil.Ellipse = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx Ellipse based on data or points provided.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ // summary:
+ // constructor
+ },
+ {
+
+ type:"dojox.drawing.stencil.Ellipse",
+ anchorType: "group",
+ baseRender:true,
+ dataToPoints: function(/*Object*/o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ var x = o.cx - o.rx,
+ y = o.cy - o.ry,
+ w = o.rx*2,
+ h = o.ry*2
+ this.points = [
+ {x:x, y:y}, // TL
+ {x:x+w, y:y}, // TR
+ {x:x+w, y:y+h}, // BR
+ {x:x, y:y+h} // BL
+ ];
+ return this.points; //Array
+ },
+
+ pointsToData: function(/*Array*/p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ var s = p[0];
+ var e = p[2];
+ this.data = {
+ cx: s.x + (e.x - s.x)/2,
+ cy: s.y + (e.y - s.y)/2,
+ rx: (e.x - s.x)*.5,
+ ry: (e.y - s.y)*.5
+ };
+ return this.data; //Object
+
+ },
+
+ _create: function(/*String*/shp, /*__StencilData*/d, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ this.remove(this[shp]);
+ this[shp] = this.container.createEllipse(d)
+ .setStroke(sty)
+ .setFill(sty.fill);
+ this._setNodeAtts(this[shp]);
+ },
+
+ render: function(){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object).
+ //
+ this.onBeforeRender(this);
+ this.renderHit && this._create("hit", this.data, this.style.currentHit);
+ this._create("shape", this.data, this.style.current);
+ }
+
+ }
+);
+
+dojox.drawing.register({
+ name:"dojox.drawing.stencil.Ellipse"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Image.js b/js/libs/dojox/drawing/stencil/Image.js
new file mode 100644
index 0000000..080de1b
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Image.js
@@ -0,0 +1,55 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Image");
+_3.drawing.stencil.Image=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+},{type:"dojox.drawing.stencil.Image",anchorType:"group",baseRender:true,dataToPoints:function(o){
+o=o||this.data;
+this.points=[{x:o.x,y:o.y},{x:o.x+o.width,y:o.y},{x:o.x+o.width,y:o.y+o.height},{x:o.x,y:o.y+o.height}];
+return this.points;
+},pointsToData:function(p){
+p=p||this.points;
+var s=p[0];
+var e=p[2];
+this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y,src:this.src||this.data.src};
+return this.data;
+},_createHilite:function(){
+this.remove(this.hit);
+this.hit=this.container.createRect(this.data).setStroke(this.style.current).setFill(this.style.current.fill);
+this._setNodeAtts(this.hit);
+},_create:function(_5,d,_6){
+this.remove(this[_5]);
+var s=this.container.getParent();
+this[_5]=s.createImage(d);
+this.container.add(this[_5]);
+this._setNodeAtts(this[_5]);
+},render:function(_7){
+if(this.data.width=="auto"||isNaN(this.data.width)){
+this.getImageSize(true);
+console.warn("Image size not provided. Acquiring...");
+return;
+}
+this.onBeforeRender(this);
+this.renderHit&&this._createHilite();
+this._create("shape",this.data,this.style.current);
+},getImageSize:function(_8){
+if(this._gettingSize){
+return;
+}
+this._gettingSize=true;
+var _9=_2.create("img",{src:this.data.src},_2.body());
+var _a=_2.connect(_9,"error",this,function(){
+_2.disconnect(c);
+_2.disconnect(_a);
+console.error("Error loading image:",this.data.src);
+console.warn("Error image:",this.data);
+});
+var c=_2.connect(_9,"load",this,function(){
+var _b=_2.marginBox(_9);
+this.setData({x:this.data.x,y:this.data.y,src:this.data.src,width:_b.w,height:_b.h});
+_2.disconnect(c);
+_2.destroy(_9);
+_8&&this.render(true);
+});
+}});
+_3.drawing.register({name:"dojox.drawing.stencil.Image"},"stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Image.js.uncompressed.js b/js/libs/dojox/drawing/stencil/Image.js.uncompressed.js
new file mode 100644
index 0000000..6b23db7
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Image.js.uncompressed.js
@@ -0,0 +1,159 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/stencil/Image", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Image");
+
+
+dojox.drawing.stencil.Image = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates an dojox.gfx Image based on the data
+ // provided.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ // summary:
+ // constructor
+ },
+ {
+ type:"dojox.drawing.stencil.Image",
+ anchorType: "group",
+ baseRender:true,
+
+/*=====
+StencilData: {
+ // summary:
+ // The data used to create the dojox.gfx Shape
+ // x: Number
+ // Left point x
+ // y: Number
+ // Top point y
+ // width: ? Number
+ // Optional width of Image. If not provided, it is obtained
+ // height: ? Number
+ // Optional height of Image. If not provided, it is obtained
+ // src: String
+ // The location of the source image
+},
+
+StencilPoints: [
+ // summary:
+ // An Array of dojox.__StencilPoint objects that describe the Stencil
+ // 0: Object
+ // Top left point
+ // 1: Object
+ // Top right point
+ // 2: Object
+ // Bottom right point
+ // 3: Object
+ // Bottom left point
+],
+=====*/
+
+ dataToPoints: function(/*Object*/o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ this.points = [
+ {x:o.x, y:o.y}, // TL
+ {x:o.x + o.width, y:o.y}, // TR
+ {x:o.x + o.width, y:o.y + o.height}, // BR
+ {x:o.x, y:o.y + o.height} // BL
+ ];
+ return this.points;
+ },
+
+ pointsToData: function(/*Array*/p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ var s = p[0];
+ var e = p[2];
+ this.data = {
+ x: s.x,
+ y: s.y,
+ width: e.x-s.x,
+ height: e.y-s.y,
+ src: this.src || this.data.src
+ };
+ return this.data;
+
+ },
+
+ _createHilite: function(){
+ // summary:
+ // Create the hit and highlight area
+ // for the Image.
+ this.remove(this.hit);
+ this.hit = this.container.createRect(this.data)
+ .setStroke(this.style.current)
+ .setFill(this.style.current.fill);
+ this._setNodeAtts(this.hit);
+ },
+ _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ this.remove(this[shp]);
+ var s = this.container.getParent();
+ this[shp] = s.createImage(d)
+ this.container.add(this[shp]);
+ this._setNodeAtts(this[shp]);
+ },
+
+ render: function(dbg){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object). Image is slightly different than other
+ // implementations. Instead of calling render twice, it calls
+ // _createHilite for the 'hit'
+ //
+ if(this.data.width == "auto" || isNaN(this.data.width)){
+ this.getImageSize(true);
+ console.warn("Image size not provided. Acquiring...")
+ return;
+ }
+ this.onBeforeRender(this);
+ this.renderHit && this._createHilite();
+ this._create("shape", this.data, this.style.current);
+ },
+ getImageSize: function(render){
+ // summary:
+ // Internal. If no image size is passed in with the data
+ // create a dom node, insert and image, gets its dimensions
+ // record them - then destroy everything.
+ //
+ if(this._gettingSize){ return; } // IE gets it twice (will need to mod if src changes)
+ this._gettingSize = true;
+ var img = dojo.create("img", {src:this.data.src}, dojo.body());
+ var err = dojo.connect(img, "error", this, function(){
+ dojo.disconnect(c);
+ dojo.disconnect(err);
+ console.error("Error loading image:", this.data.src)
+ console.warn("Error image:", this.data)
+
+ });
+ var c = dojo.connect(img, "load", this, function(){
+ var dim = dojo.marginBox(img);
+ this.setData({
+ x:this.data.x,
+ y:this.data.y,
+ src:this.data.src,
+ width:dim.w,
+ height:dim.h
+ });
+ dojo.disconnect(c);
+ dojo.destroy(img);
+ render && this.render(true);
+ });
+ }
+ }
+);
+
+
+dojox.drawing.register({
+ name:"dojox.drawing.stencil.Image"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Line.js b/js/libs/dojox/drawing/stencil/Line.js
new file mode 100644
index 0000000..b92a56d
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Line.js
@@ -0,0 +1,27 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Line");
+_3.drawing.stencil.Line=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+},{type:"dojox.drawing.stencil.Line",anchorType:"single",baseRender:true,dataToPoints:function(o){
+o=o||this.data;
+if(o.radius||o.angle){
+var pt=this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+this.data=o={x1:o.x,y1:o.y,x2:pt.x,y2:pt.y};
+}
+this.points=[{x:o.x1,y:o.y1},{x:o.x2,y:o.y2}];
+return this.points;
+},pointsToData:function(p){
+p=p||this.points;
+this.data={x1:p[0].x,y1:p[0].y,x2:p[1].x,y2:p[1].y};
+return this.data;
+},_create:function(_5,d,_6){
+this.remove(this[_5]);
+this[_5]=this.container.createLine(d).setStroke(_6);
+this._setNodeAtts(this[_5]);
+},render:function(){
+this.onBeforeRender(this);
+this.renderHit&&this._create("hit",this.data,this.style.currentHit);
+this._create("shape",this.data,this.style.current);
+}});
+_3.drawing.register({name:"dojox.drawing.stencil.Line"},"stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Line.js.uncompressed.js b/js/libs/dojox/drawing/stencil/Line.js.uncompressed.js
new file mode 100644
index 0000000..78bfbec
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Line.js.uncompressed.js
@@ -0,0 +1,122 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/stencil/Line", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Line");
+
+dojox.drawing.stencil.Line = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx Line based on data or points provided.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ // summary:
+ // constructor
+ },
+ {
+ type:"dojox.drawing.stencil.Line",
+ anchorType: "single",
+ baseRender:true,
+
+/*=====
+StencilData: {
+ // summary:
+ // The data used to create the dojox.gfx Shape
+ // x1: Number
+ // First point x
+ // y1: Number
+ // First point y
+ // x2: Number
+ // Second point x
+ // y2: Number
+ // Second point y
+
+ // ALTERNATIVE:
+
+ // x: Number
+ // First point x
+ // y: Number
+ // First point y
+ // angle: Number
+ // angle of line
+ // radius: Number
+ // length of line
+},
+
+StencilPoints: [
+ // summary:
+ // An Array of dojox.__StencilPoint objects that describe the Stencil
+ // 0: Object
+ // First point
+ // 1: Object
+ // Second point
+],
+=====*/
+
+ dataToPoints: function(o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ if(o.radius || o.angle){
+ // instead of using x1,x2,y1,y1,
+ // it's been set as x,y,angle,radius
+
+ var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+ //console.log(" ---- pts:", pt.x, pt.y);
+ this.data = o = {
+ x1:o.x,
+ y1:o.y,
+ x2:pt.x,
+ y2:pt.y
+ }
+
+ }
+ this.points = [
+ {x:o.x1, y:o.y1},
+ {x:o.x2, y:o.y2}
+ ];
+ return this.points;
+ },
+ pointsToData: function(p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ this.data = {
+ x1: p[0].x,
+ y1: p[0].y,
+ x2: p[1].x,
+ y2: p[1].y
+ };
+ return this.data;
+ },
+
+ _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ this.remove(this[shp]);
+ this[shp] = this.container.createLine(d)
+ .setStroke(sty);
+ this._setNodeAtts(this[shp]);
+ },
+
+ render: function(){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object).
+ //
+ this.onBeforeRender(this);
+ this.renderHit && this._create("hit", this.data, this.style.currentHit);
+ this._create("shape", this.data, this.style.current);
+
+ }
+
+ }
+);
+
+dojox.drawing.register({
+ name:"dojox.drawing.stencil.Line"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Path.js b/js/libs/dojox/drawing/stencil/Path.js
new file mode 100644
index 0000000..803249d
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Path.js
@@ -0,0 +1,83 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Path");
+_3.drawing.stencil.Path=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+_2.disconnect(this._postRenderCon);
+},{type:"dojox.drawing.stencil.Path",closePath:true,baseRender:true,closeRadius:10,closeColor:{r:255,g:255,b:0,a:0.5},_create:function(_5,_6){
+this.remove(this[_5]);
+if(!this.points.length){
+return;
+}
+if(_3.gfx.renderer=="svg"){
+var _7=[];
+_2.forEach(this.points,function(o,i){
+if(!o.skip){
+if(i==0){
+_7.push("M "+o.x+" "+o.y);
+}else{
+var _8=(o.t||"")+" ";
+if(o.x===undefined){
+_7.push(_8);
+}else{
+_7.push(_8+o.x+" "+o.y);
+}
+}
+}
+},this);
+if(this.closePath){
+_7.push("Z");
+}
+this.stringPath=_7.join(" ");
+this[_5]=this.container.createPath(_7.join(" ")).setStroke(_6);
+this.closePath&&this[_5].setFill(_6.fill);
+}else{
+this[_5]=this.container.createPath({}).setStroke(_6);
+this.closePath&&this[_5].setFill(_6.fill);
+_2.forEach(this.points,function(o,i){
+if(!o.skip){
+if(i==0||o.t=="M"){
+this[_5].moveTo(o.x,o.y);
+}else{
+if(o.t=="Z"){
+this.closePath&&this[_5].closePath();
+}else{
+this[_5].lineTo(o.x,o.y);
+}
+}
+}
+},this);
+this.closePath&&this[_5].closePath();
+}
+this._setNodeAtts(this[_5]);
+},render:function(){
+this.onBeforeRender(this);
+this.renderHit&&this._create("hit",this.style.currentHit);
+this._create("shape",this.style.current);
+},getBounds:function(_9){
+var _a=10000,_b=10000,_c=0,_d=0;
+_2.forEach(this.points,function(p){
+if(p.x!==undefined&&!isNaN(p.x)){
+_a=Math.min(_a,p.x);
+_b=Math.min(_b,p.y);
+_c=Math.max(_c,p.x);
+_d=Math.max(_d,p.y);
+}
+});
+return {x1:_a,y1:_b,x2:_c,y2:_d,x:_a,y:_b,w:_c-_a,h:_d-_b};
+},checkClosePoint:function(_e,_f,_10){
+var _11=this.util.distance(_e.x,_e.y,_f.x,_f.y);
+if(this.points.length>1){
+if(_11this.closeRadius&&this.closeGuide){
+this.remove(this.closeGuide);
+this.closeGuide=null;
+}
+}
+}
+return _11>built
+// wrapped by build app
+define("dojox/drawing/stencil/Path", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Path");
+
+
+dojox.drawing.stencil.Path = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx Path based on points provided.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ dojo.disconnect(this._postRenderCon);
+ },
+ {
+ type:"dojox.drawing.stencil.Path",
+ closePath: true,
+ baseRender:true,
+ closeRadius:10,
+ closeColor:{r:255,g:255,b:0,a:.5},
+
+/*=====
+StencilData: {
+ // NOT SUPPORTED FOR PATH
+},
+
+StencilPoints: [
+ // summary:
+ // An Array of StencilPoint objects that describe the Stencil
+ // 0: Object
+ // First point
+ // [1, 2, 3...] more points
+],
+=====*/
+
+ _create: function(/*String*/shp, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ this.remove(this[shp]);
+ if(!this.points.length){ return; }
+
+ if(dojox.gfx.renderer=="svg"){
+ // NOTE:
+ // In order to avoid the Safari d="" errors,
+ // we'll need to build a string and set that.
+ var strAr = [];
+ dojo.forEach(this.points, function(o, i){
+ if(!o.skip){
+ if(i==0){
+ strAr.push("M " + o.x +" "+ o.y);
+ }else{
+ var cmd = (o.t || "") + " ";
+ if(o.x===undefined){// Z + undefined works here, but checking anyway
+ strAr.push(cmd);
+ }else{
+ strAr.push(cmd + o.x +" "+ o.y);
+ }
+ }
+ }
+ }, this);
+ if(this.closePath){
+ strAr.push("Z");
+ }
+
+ this.stringPath = strAr.join(" ");
+
+ this[shp] = this.container.createPath(strAr.join(" ")).setStroke(sty);
+ this.closePath && this[shp].setFill(sty.fill);
+
+ }else{
+ // Leaving this code for VML. It seems slightly faster but times vary.
+ this[shp] = this.container.createPath({}).setStroke(sty);
+
+ this.closePath && this[shp].setFill(sty.fill);
+
+ dojo.forEach(this.points, function(o, i){
+ if(!o.skip){
+ if(i==0 || o.t=="M"){
+ this[shp].moveTo(o.x, o.y);
+ }else if(o.t=="Z"){
+ this.closePath && this[shp].closePath();
+ }else{
+ this[shp].lineTo(o.x, o.y);
+ }
+ }
+ }, this);
+
+ this.closePath && this[shp].closePath();
+ }
+
+ this._setNodeAtts(this[shp]);
+ },
+
+ render: function(){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object).
+ //
+ this.onBeforeRender(this);
+ this.renderHit && this._create("hit", this.style.currentHit);
+ this._create("shape", this.style.current);
+ //console.log("path render")
+
+
+ //console.log("---------------------rend hit", this.renderHit, this.id)
+ },
+ getBounds: function(/* ? Boolean*/absolute){
+ // summary:
+ // Overwriting _Base.getBounds. Not sure how absolute should
+ // work for a path.
+ var minx = 10000, miny = 10000, maxx = 0, maxy = 0;
+ dojo.forEach(this.points, function(p){
+ if(p.x!==undefined && !isNaN(p.x)){
+ minx = Math.min(minx, p.x);
+ miny = Math.min(miny, p.y);
+ maxx = Math.max(maxx, p.x);
+ maxy = Math.max(maxy, p.y);
+ }
+ });
+
+ return {
+ x1:minx,
+ y1:miny,
+ x2:maxx,
+ y2:maxy,
+ x:minx,
+ y:miny,
+ w:maxx-minx,
+ h:maxy-miny
+ };
+ },
+
+ checkClosePoint: function(/*Object*/firstPt, /*Object*/currPt, /*Boolean*/remove){
+ // summary:
+ // Checks if points are close enough to indicate that
+ // path should be close. Provides a visual cue.
+ // description:
+ // Not actually used in stencil.path - this is used for
+ // drawable tools that extend it. Note that those tools
+ // need to remove the shape created: this.closeGuide, or
+ // add arg: remove
+ //
+ var dist = this.util.distance(firstPt.x, firstPt.y, currPt.x, currPt.y);
+ if(this.points.length>1){
+ if(dist this.closeRadius && this.closeGuide){
+ this.remove(this.closeGuide);
+ this.closeGuide = null;
+ }
+ }
+ // return if we are within close distance
+ return dist < this.closeRadius; // Boolean
+ }
+ }
+);
+
+dojox.drawing.register({
+ name:"dojox.drawing.stencil.Path"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Rect.js b/js/libs/dojox/drawing/stencil/Rect.js
new file mode 100644
index 0000000..0c07330
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Rect.js
@@ -0,0 +1,27 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Rect");
+_3.drawing.stencil.Rect=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+if(this.points.length){
+}
+},{type:"dojox.drawing.stencil.Rect",anchorType:"group",baseRender:true,dataToPoints:function(d){
+d=d||this.data;
+this.points=[{x:d.x,y:d.y},{x:d.x+d.width,y:d.y},{x:d.x+d.width,y:d.y+d.height},{x:d.x,y:d.y+d.height}];
+return this.points;
+},pointsToData:function(p){
+p=p||this.points;
+var s=p[0];
+var e=p[2];
+this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y,r:this.data.r||0};
+return this.data;
+},_create:function(_5,d,_6){
+this.remove(this[_5]);
+this[_5]=this.container.createRect(d).setStroke(_6).setFill(_6.fill);
+this._setNodeAtts(this[_5]);
+},render:function(){
+this.onBeforeRender(this);
+this.renderHit&&this._create("hit",this.data,this.style.currentHit);
+this._create("shape",this.data,this.style.current);
+}});
+_3.drawing.register({name:"dojox.drawing.stencil.Rect"},"stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Rect.js.uncompressed.js b/js/libs/dojox/drawing/stencil/Rect.js.uncompressed.js
new file mode 100644
index 0000000..454c7d8
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Rect.js.uncompressed.js
@@ -0,0 +1,86 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/stencil/Rect", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Rect");
+
+
+dojox.drawing.stencil.Rect = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx rectangle based on data or points provided.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ // summary:
+ // constructor
+ if(this.points.length){
+ //this.render();
+ }
+ },
+ {
+ type:"dojox.drawing.stencil.Rect",
+ anchorType: "group",
+ baseRender:true,
+
+ dataToPoints: function(/*Object*/d){
+ //summary:
+ // Converts data to points.
+ d = d || this.data;
+ this.points = [
+ {x:d.x, y:d.y}, // TL
+ {x:d.x + d.width, y:d.y}, // TR
+ {x:d.x + d.width, y:d.y + d.height}, // BR
+ {x:d.x, y:d.y + d.height} // BL
+ ];
+ return this.points;
+ },
+
+ pointsToData: function(/*Array*/p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ var s = p[0];
+ var e = p[2];
+ this.data = {
+ x: s.x,
+ y: s.y,
+ width: e.x-s.x,
+ height: e.y-s.y,
+ r:this.data.r || 0
+ };
+ return this.data;
+
+ },
+
+ _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ //console.log("render rect", d)
+ //console.log("rect sty:", sty)
+ this.remove(this[shp]);
+ this[shp] = this.container.createRect(d)
+ .setStroke(sty)
+ .setFill(sty.fill);
+
+ this._setNodeAtts(this[shp]);
+ },
+
+ render: function(){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object).
+ //
+ this.onBeforeRender(this);
+ this.renderHit && this._create("hit", this.data, this.style.currentHit);
+ this._create("shape", this.data, this.style.current);
+ }
+ }
+);
+
+dojox.drawing.register({
+ name:"dojox.drawing.stencil.Rect"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/stencil/Text.js b/js/libs/dojox/drawing/stencil/Text.js
new file mode 100644
index 0000000..f582a1f
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/Text.js
@@ -0,0 +1,92 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil.Text");
+_3.drawing.stencil.Text=_3.drawing.util.oo.declare(_3.drawing.stencil._Base,function(_4){
+},{type:"dojox.drawing.stencil.Text",anchorType:"none",baseRender:true,align:"start",valign:"top",_lineHeight:1,typesetter:function(_5){
+if(_3.drawing.util.typeset){
+this._rawText=_5;
+return _3.drawing.util.typeset.convertLaTeX(_5);
+}
+return _5;
+},setText:function(_6){
+if(this.enabled){
+_6=this.typesetter(_6);
+}
+this._text=_6;
+this._textArray=[];
+this.created&&this.render(_6);
+},getText:function(){
+return this._rawText||this._text;
+},dataToPoints:function(o){
+o=o||this.data;
+var w=o.width=="auto"?1:o.width;
+var h=o.height||this._lineHeight;
+this.points=[{x:o.x,y:o.y},{x:o.x+w,y:o.y},{x:o.x+w,y:o.y+h},{x:o.x,y:o.y+h}];
+return this.points;
+},pointsToData:function(p){
+p=p||this.points;
+var s=p[0];
+var e=p[2];
+this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y};
+return this.data;
+},render:function(_7){
+this.remove(this.shape,this.hit);
+!this.annotation&&this.renderHit&&this._renderOutline();
+if(_7!=undefined){
+this._text=_7;
+this._textArray=this._text.split("\n");
+}
+var d=this.pointsToData();
+var h=this._lineHeight;
+var x=d.x+this.style.text.pad*2;
+var y=d.y+this._lineHeight-(this.textSize*0.4);
+if(this.valign=="middle"){
+y-=h/2;
+}
+this.shape=this.container.createGroup();
+_2.forEach(this._textArray,function(_8,i){
+var tb=this.shape.createText({x:x,y:y+(h*i),text:unescape(_8),align:this.align}).setFont(this.style.currentText).setFill(this.style.currentText.color);
+this._setNodeAtts(tb);
+},this);
+this._setNodeAtts(this.shape);
+},_renderOutline:function(){
+if(this.annotation){
+return;
+}
+var d=this.pointsToData();
+if(this.align=="middle"){
+d.x-=d.width/2-this.style.text.pad*2;
+}else{
+if(this.align=="start"){
+d.x+=this.style.text.pad;
+}else{
+if(this.align=="end"){
+d.x-=d.width-this.style.text.pad*3;
+}
+}
+}
+if(this.valign=="middle"){
+d.y-=(this._lineHeight)/2-this.style.text.pad;
+}
+this.hit=this.container.createRect(d).setStroke(this.style.currentHit).setFill(this.style.currentHit.fill);
+this._setNodeAtts(this.hit);
+this.hit.moveToBack();
+},makeFit:function(_9,w){
+var _a=_2.create("span",{innerHTML:_9,id:"foo"},document.body);
+var sz=1;
+_2.style(_a,"fontSize",sz+"px");
+var _b=30;
+while(_2.marginBox(_a).w>built
+// wrapped by build app
+define("dojox/drawing/stencil/Text", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil.Text");
+
+dojox.drawing.stencil.Text = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a dojox.gfx Text (SVG or VML) based on data provided.
+ // description:
+ // There are two text classes. TextBlock extends this one and
+ // adds editable functionality, discovers text width etc.
+ // This class displays text only. There is no line wrapping.
+ // Multiple lines can be acheived by inserting \n linebreaks
+ // in the text.
+ //
+ dojox.drawing.stencil._Base,
+ function(options){
+ // summary:
+ // constructor.
+ },
+ {
+ type:"dojox.drawing.stencil.Text",
+ anchorType:"none",
+ baseRender:true,
+
+ // align: String
+ // Text horizontal alignment.
+ // Options: start, middle, end
+ align:"start",
+ //
+ // valign:String
+ // Text vertical alignment
+ // Options: top, middle, bottom (FIXME: bottom not supported)
+ valign:"top",
+ //
+ // _lineHeight: [readonly] Number
+ // The height of each line of text. Based on style information
+ // and font size.
+ _lineHeight:1,
+
+/*=====
+StencilData: {
+ // summary:
+ // The data used to create the dojox.gfx Text
+ // x: Number
+ // Left point x
+ // y: Number
+ // Top point y
+ // width: ? Number
+ // Optional width of Text. Not required but reccommended.
+ // for auto-sizing, use TextBlock
+ // height: ? Number
+ // Optional height of Text. If not provided, _lineHeight is used.
+ // text: String
+ // The string content. If not provided, may auto-delete depending on defaults.
+},
+
+StencilPoints: [
+ // summary:
+ // An Array of dojox.__StencilPoint objects that describe the Stencil
+ // 0: Object
+ // Top left point
+ // 1: Object
+ // Top right point
+ // 2: Object
+ // Bottom right point
+ // 3: Object
+ // Bottom left point
+],
+=====*/
+
+ typesetter: function(text){
+ // summary:
+ // Register raw text, returning typeset form.
+ // Uses function dojox.drawing.stencil.Text.typeset
+ // for typesetting, if it exists.
+ //
+ if(dojox.drawing.util.typeset){
+ this._rawText = text;
+ return dojox.drawing.util.typeset.convertLaTeX(text);
+ }
+ return text;
+ },
+
+ setText: function(text){
+ // summary:
+ // Setter for text.
+ //
+ // Only apply typesetting to objects that the user can modify.
+ // Else, it is assumed that typesetting is done elsewhere.
+ if(this.enabled){
+ text = this.typesetter(text);
+ }
+ // This only has an effect if text is null or this.created is false.
+ this._text = text;
+
+ this._textArray = [];
+ this.created && this.render(text);
+ },
+
+ getText: function(){
+ // summary:
+ // Getter for text.
+ //
+ return this._rawText || this._text;
+ },
+
+ dataToPoints: function(/*Object*/o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ var w = o.width =="auto" ? 1 : o.width;
+ var h = o.height || this._lineHeight;
+ this.points = [
+ {x:o.x, y:o.y}, // TL
+ {x:o.x + w, y:o.y}, // TR
+ {x:o.x + w, y:o.y + h}, // BR
+ {x:o.x, y:o.y + h} // BL
+ ];
+ return this.points;
+ },
+ pointsToData: function(/*Array*/p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ var s = p[0];
+ var e = p[2];
+ this.data = {
+ x: s.x,
+ y: s.y,
+ width: e.x-s.x,
+ height: e.y-s.y
+ };
+ return this.data;
+ },
+
+ render: function(/* String*/text){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object). Text is slightly different than other
+ // implementations. Instead of calling render twice, it calls
+ // _createHilite for the 'hit'
+ // arguments:
+ // text String
+ // Changes text if sent. Be sure to use the setText and
+ // not to call this directly.
+ //
+ this.remove(this.shape, this.hit);
+ //console.log("text render, outline:", !this.annotation, this.renderHit, (!this.annotation && this.renderHit))
+ !this.annotation && this.renderHit && this._renderOutline();
+ if(text!=undefined){
+ this._text = text;
+ this._textArray = this._text.split("\n");
+ }
+
+ var d = this.pointsToData();
+ var h = this._lineHeight;
+ var x = d.x + this.style.text.pad*2;
+ var y = d.y + this._lineHeight - (this.textSize*.4);
+ if(this.valign=="middle"){
+ y -= h/2;
+ }
+ this.shape = this.container.createGroup();
+
+ /*console.log(" render ", this.type, this.id)
+ console.log(" render Y:", d.y, "textSize:", this.textSize, "LH:", this._lineHeight)
+ console.log(" render text:", y, " ... ", this._text, "enabled:", this.enabled);
+ console.log(" render text:", this.style.currentText);
+ */
+ dojo.forEach(this._textArray, function(txt, i){
+ var tb = this.shape.createText({x: x, y: y+(h*i), text: unescape(txt), align: this.align})
+ .setFont(this.style.currentText)
+ .setFill(this.style.currentText.color);
+
+ this._setNodeAtts(tb);
+
+ }, this);
+
+ this._setNodeAtts(this.shape);
+
+ },
+ _renderOutline: function(){
+ // summary:
+ // Create the hit and highlight area
+ // for the Text.
+ //
+ if(this.annotation){ return; }
+ var d = this.pointsToData();
+
+ if(this.align=="middle"){
+ d.x -= d.width/2 - this.style.text.pad * 2;
+ }else if(this.align=="start"){
+ d.x += this.style.text.pad;
+ }else if(this.align=="end"){
+ d.x -= d.width - this.style.text.pad * 3;
+ }
+
+ if(this.valign=="middle"){
+ d.y -= (this._lineHeight )/2 - this.style.text.pad;
+ }
+
+ this.hit = this.container.createRect(d)
+ .setStroke(this.style.currentHit)
+ .setFill(this.style.currentHit.fill);
+ //.setFill("#ffff00");
+
+ this._setNodeAtts(this.hit);
+ this.hit.moveToBack();
+ },
+ makeFit: function(text, w){
+ var span = dojo.create('span', {innerHTML:text, id:"foo"}, document.body);
+ var sz = 1;
+ dojo.style(span, "fontSize", sz+"px");
+ var cnt = 30;
+ while(dojo.marginBox(span).w>built
+define(["dijit","dojo","dojox","dojo/require!dojo/fx/easing"],function(_1,_2,_3){
+_2.provide("dojox.drawing.stencil._Base");
+_2.require("dojo.fx.easing");
+_3.drawing.stencil._Base=_3.drawing.util.oo.declare(function(_4){
+_2.mixin(this,_4);
+this.style=_4.style||_3.drawing.defaults.copy();
+if(_4.stencil){
+this.stencil=_4.stencil;
+this.util=_4.stencil.util;
+this.mouse=_4.stencil.mouse;
+this.container=_4.stencil.container;
+this.style=_4.stencil.style;
+}
+var _5=/Line|Vector|Axes|Arrow/;
+var _6=/Text/;
+this.shortType=this.util.abbr(this.type);
+this.isText=_6.test(this.type);
+this.isLine=_5.test(this.type);
+this.renderHit=this.style.renderHitLayer;
+if(!this.renderHit&&this.style.renderHitLines&&this.isLine){
+this.renderHit=true;
+}
+if(!this.renderHit&&this.style.useSelectedStyle){
+this.useSelectedStyle=true;
+this.selCopy=_2.clone(this.style.selected);
+for(var nm in this.style.norm){
+if(this.style.selected[nm]===undefined){
+this.style.selected[nm]=this.style.norm[nm];
+}
+}
+this.textSelected=_2.clone(this.style.text);
+this.textSelected.color=this.style.selected.fill;
+}
+this.angleSnap=this.style.angleSnap||1;
+this.marginZero=_4.marginZero||this.style.anchors.marginZero;
+this.id=_4.id||this.util.uid(this.type);
+this._cons=[];
+if(!this.annotation&&!this.subShape){
+this.util.attr(this.container,"id",this.id);
+}
+this.connect(this,"onBeforeRender","preventNegativePos");
+this._offX=this.mouse.origin.x;
+this._offY=this.mouse.origin.y;
+if(this.isText){
+this.align=_4.align||this.align;
+this.valign=_4.valign||this.valign;
+if(_4.data&&_4.data.makeFit){
+var _7=this.makeFit(_4.data.text,_4.data.width);
+this.textSize=this.style.text.size=_7.size;
+this._lineHeight=_7.box.h;
+}else{
+this.textSize=parseInt(this.style.text.size,10);
+this._lineHeight=this.textSize*1.4;
+}
+this.deleteEmptyCreate=_4.deleteEmptyCreate!==undefined?_4.deleteEmptyCreate:this.style.text.deleteEmptyCreate;
+this.deleteEmptyModify=_4.deleteEmptyModify!==undefined?_4.deleteEmptyModify:this.style.text.deleteEmptyModify;
+}
+this.attr(_4.data);
+if(this.noBaseRender){
+return;
+}
+if(_4.points){
+if(_4.data&&_4.data.closePath===false){
+this.closePath=false;
+}
+this.setPoints(_4.points);
+this.connect(this,"render",this,"onRender",true);
+this.baseRender&&this.enabled&&this.render();
+_4.label&&this.setLabel(_4.label);
+_4.shadow&&this.addShadow(_4.shadow);
+}else{
+if(_4.data){
+_4.data.width=_4.data.width?_4.data.width:this.style.text.minWidth;
+_4.data.height=_4.data.height?_4.data.height:this._lineHeight;
+this.setData(_4.data);
+this.connect(this,"render",this,"onRender",true);
+this.baseRender&&this.enabled&&this.render(_4.data.text);
+this.baseRender&&_4.label&&this.setLabel(_4.label);
+this.baseRender&&_4.shadow&&this.addShadow(_4.shadow);
+}else{
+if(this.draws){
+this.points=[];
+this.data={};
+this.connectMouse();
+this._postRenderCon=_2.connect(this,"render",this,"_onPostRender");
+}
+}
+}
+if(this.showAngle){
+this.angleLabel=new _3.drawing.annotations.Angle({stencil:this});
+}
+if(!this.enabled){
+this.disable();
+this.moveToBack();
+this.render(_4.data.text);
+}
+},{type:"dojox.drawing.stencil",minimumSize:10,enabled:true,drawingType:"stencil",setData:function(_8){
+this.data=_8;
+this.points=this.dataToPoints();
+},setPoints:function(_9){
+this.points=_9;
+if(this.pointsToData){
+this.data=this.pointsToData();
+}
+},onDelete:function(_a){
+},onBeforeRender:function(_b){
+},onModify:function(_c){
+},onChangeData:function(_d){
+},onChangeText:function(_e){
+},onRender:function(_f){
+this._postRenderCon=_2.connect(this,"render",this,"_onPostRender");
+this.created=true;
+this.disconnectMouse();
+if(this.shape){
+this.shape.superClass=this;
+}else{
+this.container.superClass=this;
+}
+this._setNodeAtts(this);
+},onChangeStyle:function(_10){
+this._isBeingModified=true;
+if(!this.enabled){
+this.style.current=this.style.disabled;
+this.style.currentText=this.style.textDisabled;
+this.style.currentHit=this.style.hitNorm;
+}else{
+this.style.current=this.style.norm;
+this.style.currentHit=this.style.hitNorm;
+this.style.currentText=this.style.text;
+}
+if(this.selected){
+if(this.useSelectedStyle){
+this.style.current=this.style.selected;
+this.style.currentText=this.textSelected;
+}
+this.style.currentHit=this.style.hitSelected;
+}else{
+if(this.highlighted){
+this.style.currentHit=this.style.hitHighlighted;
+}
+}
+this.render();
+},animate:function(_11,_12){
+console.warn("ANIMATE..........................");
+var d=_11.d||_11.duration||1000;
+var ms=_11.ms||20;
+var _13=_11.ease||_2.fx.easing.linear;
+var _14=_11.steps;
+var ts=new Date().getTime();
+var w=100;
+var cnt=0;
+var _15=true;
+var sp,ep;
+if(_2.isArray(_11.start)){
+sp=_11.start;
+ep=_11.end;
+}else{
+if(_2.isObject(_11.start)){
+sp=_11.start;
+ep=_11.end;
+_15=false;
+}else{
+console.warn("No data provided to animate");
+}
+}
+var v=setInterval(_2.hitch(this,function(){
+var t=new Date().getTime()-ts;
+var p=_13(1-t/d);
+if(t>d||cnt++>100){
+clearInterval(v);
+return;
+}
+if(_15){
+var _16=[];
+_2.forEach(sp,function(pt,i){
+var o={x:(ep[i].x-sp[i].x)*p+sp[i].x,y:(ep[i].y-sp[i].y)*p+sp[i].y};
+_16.push(o);
+});
+this.setPoints(_16);
+this.render();
+}else{
+var o={};
+for(var nm in sp){
+o[nm]=(ep[nm]-sp[nm])*p+sp[nm];
+}
+this.attr(o);
+}
+}),ms);
+},attr:function(key,_17){
+var n=this.enabled?this.style.norm:this.style.disabled;
+var t=this.enabled?this.style.text:this.style.textDisabled;
+var ts=this.textSelected||{},o,nm,_18,_19=_2.toJson(n),_1a=_2.toJson(t);
+var _1b={x:true,y:true,r:true,height:true,width:true,radius:true,angle:true};
+var _1c=false;
+if(typeof (key)!="object"){
+o={};
+o[key]=_17;
+}else{
+o=_2.clone(key);
+}
+if(o.width){
+_18=o.width;
+delete o.width;
+}
+for(nm in o){
+if(nm in n){
+n[nm]=o[nm];
+}
+if(nm in t){
+t[nm]=o[nm];
+}
+if(nm in ts){
+ts[nm]=o[nm];
+}
+if(nm in _1b){
+_1b[nm]=o[nm];
+_1c=true;
+if(nm=="radius"&&o.angle===undefined){
+o.angle=_1b.angle=this.getAngle();
+}else{
+if(nm=="angle"&&o.radius===undefined){
+o.radius=_1b.radius=this.getRadius();
+}
+}
+}
+if(nm=="text"){
+this.setText(o.text);
+}
+if(nm=="label"){
+this.setLabel(o.label);
+}
+}
+if(o.borderWidth!==undefined){
+n.width=o.borderWidth;
+}
+if(this.useSelectedStyle){
+for(nm in this.style.norm){
+if(this.selCopy[nm]===undefined){
+this.style.selected[nm]=this.style.norm[nm];
+}
+}
+this.textSelected.color=this.style.selected.color;
+}
+if(!this.created){
+return;
+}
+if(o.x!==undefined||o.y!==undefined){
+var box=this.getBounds(true);
+var mx={dx:0,dy:0};
+for(nm in o){
+if(nm=="x"||nm=="y"||nm=="r"){
+mx["d"+nm]=o[nm]-box[nm];
+}
+}
+this.transformPoints(mx);
+}
+var p=this.points;
+if(o.angle!==undefined){
+this.dataToPoints({x:this.data.x1,y:this.data.y1,angle:o.angle,radius:o.radius});
+}else{
+if(_18!==undefined){
+p[1].x=p[2].x=p[0].x+_18;
+this.pointsToData(p);
+}
+}
+if(o.height!==undefined&&o.angle===undefined){
+p[2].y=p[3].y=p[0].y+o.height;
+this.pointsToData(p);
+}
+if(o.r!==undefined){
+this.data.r=Math.max(0,o.r);
+}
+if(_1c||_1a!=_2.toJson(t)||_19!=_2.toJson(n)){
+this.onChangeStyle(this);
+}
+o.width=_18;
+if(o.cosphi!=undefined){
+!this.data?this.data={cosphi:o.cosphi}:this.data.cosphi=o.cosphi;
+this.style.zAxis=o.cosphi!=0?true:false;
+}
+},exporter:function(){
+var _1d=this.type.substring(this.type.lastIndexOf(".")+1).charAt(0).toLowerCase()+this.type.substring(this.type.lastIndexOf(".")+2);
+var o=_2.clone(this.style.norm);
+o.borderWidth=o.width;
+delete o.width;
+if(_1d=="path"){
+o.points=this.points;
+}else{
+o=_2.mixin(o,this.data);
+}
+o.type=_1d;
+if(this.isText){
+o.text=this.getText();
+o=_2.mixin(o,this.style.text);
+delete o.minWidth;
+delete o.deleteEmptyCreate;
+delete o.deleteEmptyModify;
+}
+var lbl=this.getLabel();
+if(lbl){
+o.label=lbl;
+}
+return o;
+},disable:function(){
+this.enabled=false;
+this.renderHit=false;
+this.onChangeStyle(this);
+},enable:function(){
+this.enabled=true;
+this.renderHit=true;
+this.onChangeStyle(this);
+},select:function(){
+this.selected=true;
+this.onChangeStyle(this);
+},deselect:function(_1e){
+if(_1e){
+setTimeout(_2.hitch(this,function(){
+this.selected=false;
+this.onChangeStyle(this);
+}),200);
+}else{
+this.selected=false;
+this.onChangeStyle(this);
+}
+},_toggleSelected:function(){
+if(!this.selected){
+return;
+}
+this.deselect();
+setTimeout(_2.hitch(this,"select"),0);
+},highlight:function(){
+this.highlighted=true;
+this.onChangeStyle(this);
+},unhighlight:function(){
+this.highlighted=false;
+this.onChangeStyle(this);
+},moveToFront:function(){
+this.container&&this.container.moveToFront();
+},moveToBack:function(){
+this.container&&this.container.moveToBack();
+},onTransformBegin:function(_1f){
+this._isBeingModified=true;
+},onTransformEnd:function(_20){
+this._isBeingModified=false;
+this.onModify(this);
+},onTransform:function(_21){
+if(!this._isBeingModified){
+this.onTransformBegin();
+}
+this.setPoints(this.points);
+this.render();
+},transformPoints:function(mx){
+if(!mx.dx&&!mx.dy){
+return;
+}
+var _22=_2.clone(this.points),_23=false;
+_2.forEach(this.points,function(o){
+o.x+=mx.dx;
+o.y+=mx.dy;
+if(o.x1){
+this._cons.push(this.connect.apply(this,arguments));
+}else{
+if(_2.isArray(arguments[0][0])){
+_2.forEach(arguments[0],function(ar){
+this._cons.push(this.connect.apply(this,ar));
+},this);
+}else{
+this._cons.push(this.connect.apply(this,arguments[0]));
+}
+}
+},connect:function(o,e,s,m,_2d){
+var c;
+if(typeof (o)!="object"){
+if(s){
+m=s;
+s=e;
+e=o;
+o=this;
+}else{
+m=e;
+e=o;
+o=s=this;
+}
+}else{
+if(!m){
+m=s;
+s=this;
+}else{
+if(_2d){
+c=_2.connect(o,e,function(evt){
+_2.hitch(s,m)(evt);
+_2.disconnect(c);
+});
+this._cons.push(c);
+return c;
+}else{
+}
+}
+}
+c=_2.connect(o,e,s,m);
+this._cons.push(c);
+return c;
+},disconnect:function(_2e){
+if(!_2e){
+return;
+}
+if(!_2.isArray(_2e)){
+_2e=[_2e];
+}
+_2.forEach(_2e,_2.disconnect,_2);
+},connectMouse:function(){
+this._mouseHandle=this.mouse.register(this);
+},disconnectMouse:function(){
+this.mouse.unregister(this._mouseHandle);
+},render:function(){
+},dataToPoints:function(_2f){
+},pointsToData:function(_30){
+},onDown:function(obj){
+this._downOnCanvas=true;
+_2.disconnect(this._postRenderCon);
+this._postRenderCon=null;
+},onMove:function(obj){
+},onDrag:function(obj){
+},onUp:function(obj){
+}});
+});
diff --git a/js/libs/dojox/drawing/stencil/_Base.js.uncompressed.js b/js/libs/dojox/drawing/stencil/_Base.js.uncompressed.js
new file mode 100644
index 0000000..3b77e52
--- /dev/null
+++ b/js/libs/dojox/drawing/stencil/_Base.js.uncompressed.js
@@ -0,0 +1,1212 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/stencil/_Base", ["dijit","dojo","dojox","dojo/require!dojo/fx/easing"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.stencil._Base");
+dojo.require("dojo.fx.easing");
+
+/*=====
+StencilArgs = {
+// container: [readonly] dojo.gfx.group
+// The parent shape that contains all
+// shapes used in a Stencil
+container:null,
+//
+// anchorType: String
+// Optionally blank or 'group'. 'group' tells
+// an anchor point that it must constrain
+// itself to other anchor points.
+anchorType:"",
+//
+// isText: Boolean
+// Whether this is a text object or not
+// (either stencil.text or tools.TextBlock)
+isText:false,
+//
+// shortType: String
+// The type of stencil that corresponds with the types and
+// constructors used in Drawing.registerTool
+shortType:"",
+//
+// annotation: Boolean
+// A Stencil used within a Stencil. An annotation
+// is not selectable or clickable. A Label would
+// be one example.
+annotation:false,
+//
+// subShape: Boolean
+// A Stencil used within a Stencil. A subShape
+// is clickable. An arrow head would be an example.
+subShape:false,
+//
+// style: Object
+// An instance of the styles and defaults used within
+// the Stencil.
+style:null,
+//
+// util: Object
+// Pointer to util.common
+util:null,
+//
+// mouse: Object
+// Pointer to the mouse instance
+mouse:null,
+//
+// keys: Object
+// Pointer to the keys class
+keys:null,
+//
+// points: StencilPoints
+// Points is an array of objects that make up the
+// description of a Stencil. The points to a Rect
+// that is 100x100 and at x:10 and y:10 would look like:
+// [{x:10,y:10}, {x:110, y:10}, {x:110, y:110}, {x:10, y:110}]
+// Points go clockwise from the top left. In the case of Paths,
+// they would go in the order that the Stencil would be drawn.
+// Always when the points Array is set, a data Object is created
+// as well. So never set points directly, always use setPoints().
+// See:
+// setPoints()
+points:[],
+//
+// data: StencilData
+// A data object typically (but not always) resembles the data
+// that is used to create the dojox.gfx Shape. The same Rect
+// example shown in points above would look like:
+// {x:10, y:10, width:100, height:100}
+// And an Ellipse with the same coordinates:
+// {cx:55, cy:55, rx:50, ry:50}
+// The only Stencil that does not support data (at this time)
+// is the Path. While x1,x2,x3... culd be used in a data object
+// it doesn't provide much benefit.
+// Always when a data object is set, a set of points is created
+// as well. So never set data directly, always use setData().
+// See:
+// setData()
+data:null,
+//
+// marginZero [readonly] Number
+// How closely shape can get to y:0 or x:0. Less than zero has
+// bugs in VML. This is set with defaults, and should be equal
+// to half the size of an anchor point (5 px)
+marginZero:0,
+//
+// created [readonly] Boolean
+// Whether the Stencil has been rendered for the first time or
+// not.
+created: false,
+//
+// highlighted [readonly] Boolean
+// Whether the Stencil is highlighted or not.
+highlighted:false,
+//
+// selected [readonly] Boolean
+// Whether the Stencil is selected or not.
+selected:false,
+//
+// draws [readonly] Boolean
+// Whether the Stencil can draw with a mouse drag or can just
+// be created programmtically. If the Stencil comes from the
+// stencil package, it should be draw:false. If it comes from
+// the tools package it should be draw:true.
+draws:false
+}
+
+StencilPoint = {
+// summary:
+// One point Object in the points Array
+// x: Number
+// x position of point
+// y: Number
+// y position of point
+}
+
+ToolsSetup = {
+// summary:
+// An object attached to a Tool's constructor
+// used to inform the toolbar of its information
+// and properties.
+// description:
+// This object is inserted into the *function* of
+// a tool (not a stencil). Like: function.ToolsSetup
+// It must be attached after constructr creation, so
+// this object is found at the botton of the file.
+//
+// name:String
+// Fully qualified name of constructor
+// tooltip: Stirng
+// Text to display on toolbar button hover
+// iconClass: String
+// CSS class with icon information to attach
+// to toolbar button.
+}
+=====*/
+
+dojox.drawing.stencil._Base = dojox.drawing.util.oo.declare(
+ // summary:
+ // The base class used for all Stencils.
+ // description:
+ // All stencils extend this base class.
+ // Most methods and events can be found here.
+ //
+ function(options){
+ //console.log("______Base", this.type, options)
+ // clone style so changes are reflected in future shapes
+ dojo.mixin(this, options);
+ this.style = options.style || dojox.drawing.defaults.copy();
+ if(options.stencil){
+ this.stencil = options.stencil;
+ this.util = options.stencil.util;
+ this.mouse = options.stencil.mouse;
+ this.container = options.stencil.container;
+ this.style = options.stencil.style;
+ }
+
+ // don't use the 'g' on these, it affects
+ // the global RegExp
+ var lineTypes = /Line|Vector|Axes|Arrow/;
+ var textTypes = /Text/;
+
+ this.shortType = this.util.abbr(this.type);
+ this.isText = textTypes.test(this.type);
+ this.isLine = lineTypes.test(this.type);
+
+ this.renderHit = this.style.renderHitLayer;
+ if(!this.renderHit && this.style.renderHitLines && this.isLine){
+ this.renderHit = true;
+ }
+ if(!this.renderHit && this.style.useSelectedStyle){
+ this.useSelectedStyle = true;
+ this.selCopy = dojo.clone(this.style.selected);
+ for(var nm in this.style.norm){
+ if(this.style.selected[nm]===undefined){
+ this.style.selected[nm] = this.style.norm[nm];
+ }
+ }
+ this.textSelected = dojo.clone(this.style.text);
+ this.textSelected.color = this.style.selected.fill;
+
+ }
+
+
+ this.angleSnap = this.style.angleSnap || 1;
+
+ this.marginZero = options.marginZero || this.style.anchors.marginZero;
+ this.id = options.id || this.util.uid(this.type);
+ this._cons = [];
+
+ if(!this.annotation && !this.subShape){
+ this.util.attr(this.container, "id", this.id);
+ }
+
+ this.connect(this, "onBeforeRender", "preventNegativePos");
+
+ this._offX = this.mouse.origin.x;
+ this._offY = this.mouse.origin.y;
+
+ if(this.isText){
+ this.align = options.align || this.align;
+ this.valign = options.valign || this.valign;
+ if(options.data && options.data.makeFit){
+ var textObj = this.makeFit(options.data.text, options.data.width);
+ this.textSize = this.style.text.size = textObj.size;
+ this._lineHeight = textObj.box.h;
+ }else{
+ this.textSize = parseInt(this.style.text.size, 10);
+ this._lineHeight = this.textSize * 1.4;
+ }
+
+
+ // TODO: thinner text selection
+ //this.style.hitSelected.width *= 0.5;
+ //
+ // ouch. how verbose. My mixin is weak....
+ this.deleteEmptyCreate = options.deleteEmptyCreate!==undefined ? options.deleteEmptyCreate : this.style.text.deleteEmptyCreate;
+ this.deleteEmptyModify = options.deleteEmptyModify!==undefined ? options.deleteEmptyModify : this.style.text.deleteEmptyModify;
+ }
+
+ //this.drawingType
+
+ this.attr(options.data);
+
+ // make truthy
+ // add to renders below
+ // this.baseRender && render()
+ //if(this.type == "dojox.drawing.tools.TextBlock"){
+ if(this.noBaseRender){
+ // TextBlock will handle rendering itself
+ return;
+ }
+
+ //console.log("BASE OPTS:", options)
+ if(options.points){
+ //console.log("__________Base.constr >>>> ", this.type, "points", options.points)
+ if(options.data && options.data.closePath===false){
+ this.closePath = false;
+ }
+ this.setPoints(options.points);
+ this.connect(this, "render", this, "onRender", true);
+ this.baseRender && this.enabled && this.render();
+ options.label && this.setLabel(options.label);
+ options.shadow && this.addShadow(options.shadow);
+
+ }else if(options.data){
+ //console.log("___________Base.constr", this.type, "options data", options.data)
+ options.data.width = options.data.width ? options.data.width : this.style.text.minWidth;
+ options.data.height = options.data.height ? options.data.height : this._lineHeight;
+ this.setData(options.data);
+ this.connect(this, "render", this, "onRender", true);
+ this.baseRender && this.enabled && this.render(options.data.text);
+ this.baseRender && options.label && this.setLabel(options.label);
+ this.baseRender && options.shadow && this.addShadow(options.shadow);
+
+ }else if(this.draws){
+ //console.log("_____________Base.constr", this.type, "draws")
+ this.points = [];
+ this.data = {};
+ this.connectMouse();
+ this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+ }
+ if(this.showAngle){
+ this.angleLabel = new dojox.drawing.annotations.Angle({stencil:this});
+ }
+
+ if(!this.enabled){
+ this.disable();
+ this.moveToBack();
+ // some things render some don't...
+ this.render(options.data.text);
+ }
+
+ },
+ {
+
+ // type: String
+ // The type of Stencil this is. Should be overridden
+ // by extending classes.
+ // FIXME: should this be declaredClass?
+ type:"dojox.drawing.stencil",
+ //
+ // minimumSize: Number
+ // The minimum size allowed for a render. If the size
+ // is less, the shape is destroyed.
+ minimumSize:10,
+ //
+ // enabled [readonly] Boolean
+ // Whether the Stencil is enabled or not.
+ enabled:true,
+
+
+ drawingType:"stencil",
+
+ //points:[],
+
+ setData: function(/*StencilData*/data){
+ // summary:
+ // Setter for Stencil data; also converts
+ // data to points. See individual Stencils
+ // for specific data properties.
+ this.data = data;
+ this.points = this.dataToPoints();
+ },
+
+ setPoints: function(/*StencilPoints*/points){
+ // summary:
+ // Setter for Stencil points; also converts
+ // points to data. See individual Stencils
+ // for specific points properties.
+ this.points = points;
+ // Path doesn't do data
+ if(this.pointsToData){
+ this.data = this.pointsToData();
+ }
+ },
+
+ onDelete: function(/* Stencil */ stencil){
+ // summary:
+ // Stub - fires before this is destroyed
+ console.info("onDelete", this.id);
+ },
+
+ onBeforeRender: function(/*Object*/ stencil){
+ // summary:
+ // Stub - Fires before render occurs.
+ },
+
+ onModify: function(/*Object*/stencil){
+ // summary:
+ // Stub - fires on change of any property,
+ // including style properties
+
+ },
+
+ onChangeData: function(/*Object*/ stencil){
+ // summary:
+ // Stub - fires on change of dimensional
+ // properties or a text change
+ },
+
+ onChangeText: function(value){ // value or 'this' ?
+ // summary:
+ // Stub - fires on change of text in a
+ // TextBlock tool only
+ },
+
+ onRender: function(/*Object*/ stencil){
+ // summary:
+ // Stub - Fires on creation.
+ // Drawing connects to this (once!) to be
+ // notified of drag completion. But only if it
+ // was registered as a Tool. Creating Stencil in and of
+ // itself does not register it.
+ //
+ // This should fire
+ // at the *end* of creation (not during drag)
+ //
+ // FIXME:
+ // This should probably be onCreate. It should
+ // only fire once. But the mechanism for determining
+ // this is more complicated than it sounds.
+ //
+ this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+ this.created = true;
+ this.disconnectMouse();
+
+ // for Silverlight
+ if(this.shape){
+ this.shape.superClass = this;
+ }else{
+ this.container.superClass = this;
+ }
+ this._setNodeAtts(this);
+ //console.warn("ONRENDER", this.id, this)
+ },
+
+ onChangeStyle: function(/*Object*/stencil){
+ // summary:
+ // Fires when styles of shape has changed
+ //
+ this._isBeingModified = true; // need this to prevent onRender
+ if(!this.enabled){
+ this.style.current = this.style.disabled;
+ this.style.currentText = this.style.textDisabled;
+ this.style.currentHit = this.style.hitNorm;
+
+ }else{
+ this.style.current = this.style.norm;
+ this.style.currentHit = this.style.hitNorm;
+ this.style.currentText = this.style.text;
+ }
+
+ if(this.selected){
+ if(this.useSelectedStyle){
+ this.style.current = this.style.selected;
+ this.style.currentText = this.textSelected;
+ }
+ this.style.currentHit = this.style.hitSelected;
+
+ }else if(this.highlighted){
+ //this.style.current = this.style.highlighted;
+ this.style.currentHit = this.style.hitHighlighted;
+ //this.style.currentText = this.style.textHighlighted;
+ }
+
+ // NOTE: Can't just change props like setStroke
+ // because Silverlight throws error
+ this.render();
+ },
+
+ animate: function(options, create){
+ console.warn("ANIMATE..........................")
+ var d = options.d || options.duration || 1000;
+ var ms = options.ms || 20;
+ var ease = options.ease || dojo.fx.easing.linear;
+ var steps = options.steps;
+ var ts = new Date().getTime();
+ var w = 100;
+ var cnt = 0;
+ var isArray = true;
+ var sp, ep;
+
+ if(dojo.isArray(options.start)){
+ sp = options.start;
+ ep = options.end;
+
+ }else if(dojo.isObject(options.start)){
+ sp = options.start;
+ ep = options.end;
+ isArray = false;
+ }else{
+
+ console.warn("No data provided to animate")
+ }
+
+ var v = setInterval(dojo.hitch(this, function(){
+ var t = new Date().getTime() - ts;
+ var p = ease(1-t/d);
+ if(t > d || cnt++ > 100){
+ clearInterval(v);
+ return;
+ }
+
+ if(isArray){
+ var pnts = [];
+ dojo.forEach(sp, function(pt, i){
+
+ var o = {
+ x: (ep[i].x-sp[i].x)*p + sp[i].x,
+ y: (ep[i].y-sp[i].y)*p + sp[i].y
+ };
+ pnts.push(o);
+ });
+ this.setPoints(pnts);
+ this.render();
+
+ }else{
+
+ var o = {};
+ for(var nm in sp){
+ o[nm] = (ep[nm] - sp[nm]) * p + sp[nm];
+ }
+
+ this.attr(o);
+
+ }
+ //console.dir(pnts)
+
+
+ //this.attr("height", w);
+ ////console.log("W:", w)
+ //w += 5;
+
+ }), ms);
+ },
+
+ attr: function(/*String | Object*/key, /* ? String | Number */value){
+ // summary
+ // Changes properties in the style or disabled styles,
+ // depending on whether the object is enabled.
+ // Also can be used to change most position and size props.
+
+ // NOTE: JUST A SETTTER!! TODO!
+
+ // WARNING:
+ // Not doing any Stencil-type checking here. Setting a height
+ // on a line or an angle on a rectangle will just not render.
+
+ // FIXME
+ // 'width' attr is used for line width. How to change the width of a stencil?
+ var n = this.enabled?this.style.norm:this.style.disabled;
+ var t = this.enabled?this.style.text:this.style.textDisabled;
+ var ts = this.textSelected || {},
+ o,
+ nm,
+ width,
+ styleWas = dojo.toJson(n),
+ textWas = dojo.toJson(t);
+
+ var coords = {
+ x:true,
+ y:true,
+ r:true,
+ height:true,
+ width:true,
+ radius:true,
+ angle:true
+ };
+ var propChange = false;
+ if(typeof(key)!="object"){
+ o = {};
+ o[key] = value;
+ }else{
+ // prevent changing actual data
+ o = dojo.clone(key);
+ }
+
+ if(o.width){
+ // using width for size,
+ // borderWidth should be used
+ // for line thickness
+ width = o.width;
+ delete o.width;
+ }
+
+ for(nm in o){
+ if(nm in n){ n[nm] = o[nm]; }
+ if(nm in t){ t[nm] = o[nm]; }
+ if(nm in ts){ ts[nm] = o[nm]; }
+
+ if(nm in coords){
+ coords[nm] = o[nm];
+ propChange = true;
+ if(nm == "radius" && o.angle===undefined){
+ o.angle = coords.angle = this.getAngle();
+ }else if(nm == "angle" && o.radius===undefined){
+ o.radius = coords.radius = this.getRadius();
+ }
+
+ }
+ if(nm == "text"){
+ this.setText(o.text);
+ }
+ if(nm == "label"){
+ this.setLabel(o.label);
+ }
+ }
+ if(o.borderWidth!==undefined){
+ n.width = o.borderWidth;
+ }
+
+ if(this.useSelectedStyle){
+ // using the orginal selected style copy as
+ // a reference map of what props to copy
+ for(nm in this.style.norm){
+ if(this.selCopy[nm]===undefined){
+ this.style.selected[nm] = this.style.norm[nm];
+ }
+ }
+ this.textSelected.color = this.style.selected.color;
+
+ }
+
+ if(!this.created){
+ return;
+ }
+
+ // basic transform
+ if(o.x!==undefined || o.y!==undefined){
+ var box = this.getBounds(true);
+ var mx = { dx:0, dy:0 };
+ for(nm in o){
+ if(nm=="x" || nm =="y" || nm =="r"){
+ mx["d"+nm] = o[nm] - box[nm];
+ }
+ }
+ this.transformPoints(mx);
+ }
+
+
+ var p = this.points;
+ if(o.angle!==undefined){
+ this.dataToPoints({
+ x:this.data.x1,
+ y:this.data.y1,
+ angle:o.angle,
+ radius:o.radius
+ });
+
+ } else if(width!==undefined){
+ p[1].x = p[2].x = p[0].x + width;
+ this.pointsToData(p);
+ }
+
+ if(o.height!==undefined && o.angle===undefined){
+ console.log("Doing P2D-2");
+ p[2].y = p[3].y = p[0].y + o.height;
+ this.pointsToData(p);
+ }
+
+ if(o.r!==undefined){
+ this.data.r = Math.max(0, o.r);
+ }
+
+ //console.dir(this.data);
+ if(propChange || textWas!=dojo.toJson(t) || styleWas != dojo.toJson(n)){
+ // to trigger the render
+ // other events will be called post render
+ this.onChangeStyle(this);
+ }
+ o.width = width;
+
+ if(o.cosphi!=undefined){
+ !this.data? this.data = {cosphi:o.cosphi} : this.data.cosphi = o.cosphi;
+ this.style.zAxis = o.cosphi!=0 ? true : false;
+ }
+ },
+
+ exporter: function(){
+ // summary:
+ // Exports Stencil data
+ //
+ var type = this.type.substring(this.type.lastIndexOf(".")+1).charAt(0).toLowerCase()
+ + this.type.substring(this.type.lastIndexOf(".")+2);
+ var o = dojo.clone(this.style.norm);
+ o.borderWidth = o.width;
+ delete o.width;
+ if(type=="path"){
+ o.points = this.points;
+ }else{
+ o = dojo.mixin(o, this.data);
+ }
+ o.type = type;
+ if(this.isText){
+ o.text = this.getText();
+ o = dojo.mixin(o, this.style.text);
+ delete o.minWidth;
+ delete o.deleteEmptyCreate;
+ delete o.deleteEmptyModify;
+ }
+ var lbl = this.getLabel();
+ if(lbl){
+ o.label = lbl;
+ }
+ return o;
+ },
+
+
+ // TODO:
+ // Makes these all called by att()
+ // Should points and data be?
+ //
+ disable: function(){
+ // summary:
+ // Disables Stencil so it is not selectable.
+ // Changes the color to the disabled style.
+ this.enabled = false;
+ this.renderHit = false;
+ this.onChangeStyle(this);
+ },
+
+ enable: function(){
+ // summary:
+ // Enables Stencil so it is not selectable (if
+ // it was selectable to begin with). Changes the
+ // color to the current style.
+ this.enabled = true;
+ this.renderHit = true;
+ this.onChangeStyle(this);
+ },
+
+ select: function(){
+ // summary:
+ // Called when the Stencil is selected.
+ // NOTE: Calling this will not select the Stencil
+ // calling this just sets the style to the 'selected'
+ // theme. 'manager.Stencil' should be used for selecting
+ // Stencils.
+ //
+ this.selected = true;
+ this.onChangeStyle(this);
+ },
+
+ deselect: function(/*Boolean*/useDelay){
+ // summary:
+ // Called when the Stencil is deselected.
+ // NOTE: Calling this will not deselect the Stencil
+ // calling this just sets the style to the current
+ // theme. 'manager.Stencil' should be used for selecting
+ // and deselecting Stencils.
+ //
+ // arguments:
+ // useDelay: Boolean
+ // Adds slight delay before the style is set.
+ //
+ // should not have to render here because the deselection
+ // re-renders after the transform
+ // but... oh well.
+ if(useDelay){
+ setTimeout(dojo.hitch(this, function(){
+ this.selected = false;
+ this.onChangeStyle(this);
+ }),200);
+ }else{
+ this.selected = false;
+ this.onChangeStyle(this);
+ }
+ },
+ _toggleSelected: function(){
+ if(!this.selected){ return; }
+ this.deselect();
+ setTimeout(dojo.hitch(this, "select"), 0);
+ },
+
+ highlight: function(){
+ // summary:
+ // Changes style to the highlight theme.
+ this.highlighted = true;
+ this.onChangeStyle(this);
+ },
+
+ unhighlight: function(){
+ // summary:
+ // Changes style to the current theme.
+ this.highlighted = false;
+ this.onChangeStyle(this);
+ },
+
+ moveToFront: function(){
+ // summary:
+ // Moves Stencil to the front of all other items
+ // on the canvas.
+ this.container && this.container.moveToFront();
+ },
+
+ moveToBack: function(){
+ // summary:
+ // Moves Stencil to the back of all other items
+ // on the canvas.
+ this.container && this.container.moveToBack();
+ },
+
+ onTransformBegin: function(/* ? manager.Anchor */anchor){
+ // summary:
+ // Fired at the start of a transform. This would be
+ // an anchor drag or a selection.
+ //
+ this._isBeingModified = true;
+ },
+
+ onTransformEnd: function(/* manager.Anchor */anchor){
+ // summary:
+ // Called from anchor point up mouse up
+ this._isBeingModified = false;
+ this.onModify(this);
+ },
+
+ onTransform: function(/* ? manager.Anchor */anchor){
+ // summary:
+ // Called from anchor point mouse drag
+ // also called from plugins.Pan.checkBounds
+ if(!this._isBeingModified){
+ this.onTransformBegin();
+ }
+ // this is not needed for anchor moves, but it
+ // is for stencil move:
+ this.setPoints(this.points);
+ this.render();
+ },
+
+ transformPoints: function(mx){
+ // summary:
+ // Moves object to a new X Y location
+ // mx is additive. So mx.dx=1 will move the stencil
+ // 1 pixel to the right from wherever it was.
+ //
+ // An attempt is made to prevent < 0 errors, but
+ // this won't work on all shapes (like Axes)
+ //
+ if(!mx.dx && !mx.dy){
+ // no change
+ return;
+ }
+ var backup = dojo.clone(this.points), abort = false;
+ dojo.forEach(this.points, function(o){
+ o.x += mx.dx;
+ o.y += mx.dy;
+ if(o.x 180, -90 -> 270
+ angle<0 ? angle = 360 + angle : angle;
+ return angle;
+ },
+ getRadius: function(){
+ // summary:
+ // Gets radius (length) of Stencil
+ // NOTE: Only works for Lines, Arrows and Vectors
+ // (not for Ellipse, Axes has its own version)
+ //
+ var box = this.getBounds(true);
+ var line = {start:{x:box.x1, y:box.y1}, x:box.x2, y:box.y2};
+ return this.util.length(line);
+ },
+ getBounds: function(/* ? Boolean*/absolute){
+ // summary:
+ // Returns the coordinates of the Stencil. This is often
+ // different than the data or the points.
+ // arguments:
+ // absolute: Boolean
+ // Keeps lines from flipping (see note).
+ //
+ // NOTE: Won't work for paths or annotations (labels, Axes, arrow tips)
+ // They should overwrite.
+ // NOTE: Primarily used for checking for if shape is off
+ // canvas. Therefore Lines could get flipped. Use absolute
+ // to prevent this.
+ //
+ var p = this.points, x1, y1, x2, y2;
+ if(p.length==2){
+ if(absolute){
+ x1 = p[0].x;
+ y1 = p[0].y;
+ x2 = p[1].x;
+ y2 = p[1].y
+ }else{
+ x1 = p[0].x < p[1].x ? p[0].x : p[1].x;
+ y1 = p[0].y < p[1].y ? p[0].y : p[1].y;
+ x2 = p[0].x < p[1].x ? p[1].x : p[0].x;
+ y2 = p[0].y < p[1].y ? p[1].y : p[0].y;
+ }
+ return {
+ x1:x1,
+ y1:y1,
+ x2:x2,
+ y2:y2,
+ x:x1,
+ y:y1,
+ w:x2-x1,
+ h:y2-y1
+ }; // Object
+ }else{
+ return {
+ x1:p[0].x,
+ y1:p[0].y,
+ x2:p[2].x,
+ y2:p[2].y,
+ x:p[0].x,
+ y:p[0].y,
+ w:p[2].x - p[0].x,
+ h:p[2].y - p[0].y
+ }; // Object
+ }
+ },
+
+
+ preventNegativePos: function(){
+ // summary:
+ // Internal. Prevent item from being drawn/rendered less
+ // than zero on the X or Y.
+ //
+ // if being modified anchors will prevent less than zero.
+ if(this._isBeingModified){ return; }
+ // FIXME: why is this sometimes empty?
+ if(!this.points || !this.points.length){ return; }
+
+ if(this.type=="dojox.drawing.tools.custom.Axes"){
+ // this scenario moves all points if < 0
+ var minY = this.marginZero, minX = this.marginZero;
+ dojo.forEach(this.points, function(p){ minY = Math.min(p.y, minY); });
+ dojo.forEach(this.points, function(p){ minX = Math.min(p.x, minX); });
+
+ if(minY : this.editMode:", this.editMode)
+ this.onChangeData(this);
+ this._prevData = dojo.clone(this.data);
+
+ }else if(!this._prevData && (!this.isText || this.getText())){
+ //console.info("_Base no prevData..........................");
+ this._prevData = dojo.clone(this.data);
+
+ }
+
+ },
+
+ _setNodeAtts: function(shape){
+ // summary:
+ // Internal. Sets the rawNode attribute. (Or in Silverlight
+ // an "object attribute". "stencil" is
+ // used by the application to determine if
+ // something is selectable or not. This also
+ // sets the mouse custom events like:
+ // "onStencilUp". To disable the selectability,
+ // make the att "", which causes a standard
+ // mouse event.
+ // Labels are special and used to select master stencils.
+ var att = this.enabled && (!this.annotation || this.drawingType=="label") ? this.drawingType : "";
+ this.util.attr(shape, "drawingType", att);
+ },
+
+
+ destroy: function(){
+ // summary:
+ // Destroys this Stencil
+ // Note:
+ // Can connect to this, but it's better to
+ // connect to onDelete
+ //
+ // prevent loops:
+ if(this.destroyed){ return; }
+ if(this.data || this.points && this.points.length){
+ this.onDelete(this);
+ }
+
+ this.disconnectMouse();
+ this.disconnect(this._cons);
+ dojo.disconnect(this._postRenderCon);
+ this.remove(this.shape, this.hit);
+ this.destroyed = true;
+ },
+
+ remove: function(/*Shape...*/){
+ // summary:
+ // Removes shape(s), typically before a re-render
+ // No args defaults to this.shape
+ // Pass in multiple args to remove multiple shapes
+ //
+ // FIXME: Use an Array of all shapes
+ //
+ var a = arguments;
+ if(!a.length){
+ if(!this.shape){ return; }
+ a = [this.shape];
+ }
+ for(var i=0;i1){
+ // arguments are the connect params
+ this._cons.push(this.connect.apply(this, arguments));
+ }else if(dojo.isArray(arguments[0][0])){
+ // an array of arrays of params
+ dojo.forEach(arguments[0], function(ar){
+ this._cons.push(this.connect.apply(this, ar));
+ }, this);
+ }else{
+ //one array of params
+ this._cons.push(this.connect.apply(this, arguments[0]));
+ }
+
+ },
+
+ // TODO: connect to a Shape event from outside class
+ connect: function(o, e, s, m, /* Boolean*/once){
+ // summary:
+ // Convenience method for quick connects
+ // See comments below for possiblities
+ // functions can be strings
+ // once:
+ // If true, the connection happens only
+ // once then disconnects. Five args are required
+ // for this functionality.
+ //
+ var c;
+ if(typeof(o)!="object"){
+ if(s){
+ // ** function object function **
+ m = s; s = e; e=o; o = this;
+ }else{
+ // ** function function **
+ m = e; e = o; o = s = this;
+ }
+ }else if(!m){
+ // ** object function function **
+ m = s; s = this;
+ }else if(once){
+ // ** object function object function Boolean **
+ c = dojo.connect(o, e, function(evt){
+ dojo.hitch(s, m)(evt);
+ dojo.disconnect(c);
+ });
+ this._cons.push(c);
+ return c;
+ }else{
+ // ** object function object function **
+ }
+ c = dojo.connect(o, e, s, m);
+ this._cons.push(c);
+ return c;
+ },
+
+ disconnect: function(/*handle | Array*/handles){
+ // summary:
+ // Removes connections based on passed
+ // handles arguments
+ if(!handles){ return }
+ if(!dojo.isArray(handles)){ handles=[handles]; }
+ dojo.forEach(handles, dojo.disconnect, dojo);
+ },
+
+ connectMouse: function(){
+ // summary:
+ // Internal. Registers this Stencil to receive
+ // mouse events.
+ this._mouseHandle = this.mouse.register(this);
+ },
+ disconnectMouse: function(){
+ // summary:
+ // Internal. Unregisters this Stencil from receiving
+ // mouse events.
+ this.mouse.unregister(this._mouseHandle);
+ },
+
+ // Should be overwritten by sub class:
+ render: function(){
+ // summary:
+ // This Stencil's render description. Often
+ // calls 'sub render' methods.
+ },
+ //renderOutline: function(){},
+ dataToPoints: function(/*Object*/data){
+ // summary:
+ // Converts data to points.
+ },
+ pointsToData: function(/*Array*/points){
+ // summary:
+ // Converts points to data
+ },
+ onDown: function(/*EventObject*/obj){
+ // summary:
+ // Mouse event, fired on mousedown on canvas
+ //
+ // by default, object is ready to accept data
+ // turn this off for dragging or onRender will
+ // keep firing and register the shape
+ // NOTE: Not needed for all stencils. Axes needs it.
+ this._downOnCanvas = true;
+ dojo.disconnect(this._postRenderCon);
+ this._postRenderCon = null;
+ },
+ onMove: function(/*EventObject*/obj){
+ // summary:
+ // Mouse event, fired on mousemove while mouse
+ // is not down.
+ // NOTE: Not currently implemented
+ },
+ onDrag: function(/*EventObject*/obj){
+ // summary:
+ // Mouse event, fired on mousemove while mouse
+ // is down on canvas
+ },
+ onUp: function(/*EventObject*/obj){
+ // summary:
+ // Mouse event, fired on mouseup
+ }
+ }
+);
+
+
+});
diff --git a/js/libs/dojox/drawing/tools/Arrow.js b/js/libs/dojox/drawing/tools/Arrow.js
new file mode 100644
index 0000000..4cbc3c7
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/Arrow.js
@@ -0,0 +1,36 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Arrow");
+_3.drawing.tools.Arrow=_3.drawing.util.oo.declare(_3.drawing.tools.Line,function(_4){
+if(this.arrowStart){
+this.begArrow=new _3.drawing.annotations.Arrow({stencil:this,idx1:0,idx2:1});
+}
+if(this.arrowEnd){
+this.endArrow=new _3.drawing.annotations.Arrow({stencil:this,idx1:1,idx2:0});
+}
+if(this.points.length){
+this.render();
+_4.label&&this.setLabel(_4.label);
+}
+},{draws:true,type:"dojox.drawing.tools.Arrow",baseRender:false,arrowStart:false,arrowEnd:true,labelPosition:function(){
+var d=this.data;
+var pt=_3.drawing.util.positioning.label({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
+return {x:pt.x,y:pt.y};
+},onUp:function(_5){
+if(this.created||!this.shape){
+return;
+}
+var p=this.points;
+var _6=this.util.distance(p[0].x,p[0].y,p[1].x,p[1].y);
+if(_6>built
+// wrapped by build app
+define("dojox/drawing/tools/Arrow", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Arrow");
+
+dojox.drawing.tools.Arrow = dojox.drawing.util.oo.declare(
+ // summary:
+ // Extends stencil.Line and adds an arrow head
+ // to the end and or start.
+ //
+ dojox.drawing.tools.Line,
+ function(options){
+ // summary: constructor
+ if(this.arrowStart){
+ this.begArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:0, idx2:1});
+ }
+ if(this.arrowEnd){
+ this.endArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:1, idx2:0});
+ }
+ if(this.points.length){
+ // This is protecting against cases when there are no points
+ // not sure how that would ever happen
+ // Render & label here instead of in base because of Arrow annotation
+ this.render();
+ options.label && this.setLabel(options.label);
+ }
+ },
+ {
+ draws:true,
+ type:"dojox.drawing.tools.Arrow",
+ baseRender:false,
+
+ // arrowStart: Boolean
+ // Whether or not to place an arrow on start.
+ arrowStart:false,
+ //
+ // arrowEnd: Boolean
+ // Whether or not to place an arrow on end.
+ arrowEnd:true,
+
+ labelPosition: function(){
+ // summary:
+ // The custom position used for the label
+ //
+ var d = this.data;
+ var pt = dojox.drawing.util.positioning.label({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
+ return {
+ x:pt.x,
+ y:pt.y
+ }
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(this.created || !this.shape){ return; }
+
+ // if too small, need to reset
+ var p = this.points;
+ var len = this.util.distance(p[0].x,p[0].y,p[1].x,p[1].y);
+ if(len>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Ellipse");
+_3.drawing.tools.Ellipse=_3.drawing.util.oo.declare(_3.drawing.stencil.Ellipse,function(){
+},{draws:true,onDrag:function(_4){
+var s=_4.start,e=_4;
+var x=s.x>built
+// wrapped by build app
+define("dojox/drawing/tools/Ellipse", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Ellipse");
+
+dojox.drawing.tools.Ellipse = dojox.drawing.util.oo.declare(
+ // summary:
+ // A drawable Ellipse.
+ //
+ dojox.drawing.stencil.Ellipse,
+ function(){
+ // summary: constructor
+ },
+ {
+ draws:true,
+ onDrag: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDrag
+ //
+ var s = obj.start, e = obj;
+ var x = s.x < e.x ? s.x : e.x,
+ y = s.y < e.y ? s.y : e.y,
+ w = s.x < e.x ? e.x-s.x : s.x-e.x,
+ h = s.y < e.y ? e.y-s.y : s.y-e.y;
+
+ if(this.keys.shift){ w = h = Math.max(w,h); }
+ if(!this.keys.alt){ // ellipse is normally on center
+ x+=w/2; y+=h/2; w/=2; h/=2;
+ } else{
+ if(y - h < 0){ h = y; }
+ if(x - w < 0){ w = x; }
+ }
+
+ this.points = [
+ {x:x-w, y:y-h}, // TL
+ {x:x+w, y:y-h}, // TR
+ {x:x+w, y:y+h}, // BR
+ {x:x-w, y:y+h} // BL
+ ];
+ this.render();
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(this.created || !this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+ //Default shape on single click
+ if(!this.shape){
+ var s = obj.start, e = this.minimumSize*2;
+ this.data = {
+ cx: s.x+e,
+ cy: s.y+e,
+ rx: e,
+ ry: e
+ };
+ this.dataToPoints();
+ this.render();
+ }else{
+ // if too small, need to reset
+ var o = this.pointsToData();
+ console.log("Create a default shape here, pt to data: ",o);
+ if(o.rx*2>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Line");
+_3.drawing.tools.Line=_3.drawing.util.oo.declare(_3.drawing.stencil.Line,function(){
+},{draws:true,showAngle:true,onTransformEnd:function(_4){
+this._toggleSelected();
+if(this.getRadius()x1?((x2-x1)/2):((x1-x2)/-2);
+var dy=y2>y1?((y2-y1)/2):((y1-y2)/-2);
+x1-=dx;
+x2-=dx;
+y1-=dy;
+y2-=dy;
+}
+this.setPoints([{x:x1,y:y1},{x:x2,y:y2}]);
+this.render();
+},onUp:function(_7){
+if(this.created||!this._downOnCanvas){
+return;
+}
+this._downOnCanvas=false;
+if(!this.shape){
+var s=_7.start,e=this.minimumSize*4;
+this.setPoints([{x:s.x,y:s.y+e},{x:s.x,y:s.y}]);
+this.render();
+}else{
+if(this.getRadius()>built
+// wrapped by build app
+define("dojox/drawing/tools/Line", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Line");
+
+dojox.drawing.tools.Line = dojox.drawing.util.oo.declare(
+ // summary:
+ // Class for a drawable Line
+ dojox.drawing.stencil.Line,
+ function(){
+ // summary: constructor
+ },
+ {
+ draws:true,
+ showAngle:true,
+ onTransformEnd: function(/*manager.Anchor*/anchor){
+ // summary:
+ // Overwrites _Base.onTransformEnd
+ //
+ this._toggleSelected();
+ if(this.getRadius()x1 ? ((x2-x1)/2) : ((x1-x2)/-2);
+ var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2);
+ x1 -= dx;
+ x2 -= dx;
+ y1 -= dy;
+ y2 -= dy;
+ }
+
+ this.setPoints([
+ {x:x1, y:y1},
+ {x:x2, y:y2}
+ ]);
+ this.render();
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(this.created || !this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+ //Default shape on single click
+ if(!this.shape){
+ var s = obj.start, e = this.minimumSize*4;
+ this.setPoints([
+ {x:s.x, y:s.y+e},
+ {x:s.x, y:s.y}
+ ]);
+ this.render();
+
+ }else{
+ // if too small, need to reset
+
+ if(this.getRadius()>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Path");
+_3.drawing.tools.Path=_3.drawing.util.oo.declare(_3.drawing.stencil.Path,function(){
+this.pathMode="";
+this.currentPathMode="";
+this._started=false;
+this.oddEvenClicks=0;
+},{draws:true,onDown:function(_4){
+if(!this._started){
+this.onStartPath(_4);
+}
+},makeSubPath:function(_5){
+if(_5){
+if(this.currentPathMode=="Q"){
+this.points.push({x:this.points[0].x,y:this.points[0].y});
+}
+this.points.push({t:"Z"});
+this.render();
+}
+this.currentPathMode="";
+this.pathMode="M";
+},onStartPath:function(_6){
+this._started=true;
+this.revertRenderHit=this.renderHit;
+this.renderHit=false;
+this.closePath=false;
+this.mouse.setEventMode("PathEdit");
+this.closePoint={x:_6.x,y:_6.y};
+this._kc1=this.connect(this.keys,"onEsc",this,function(){
+this.onCompletePath(false);
+});
+this._kc2=this.connect(this.keys,"onKeyUp",this,function(_7){
+switch(_7.letter){
+case "c":
+this.onCompletePath(true);
+break;
+case "l":
+this.pathMode="L";
+break;
+case "m":
+this.makeSubPath(false);
+break;
+case "q":
+this.pathMode="Q";
+break;
+case "s":
+this.pathMode="S";
+break;
+case "z":
+this.makeSubPath(true);
+break;
+}
+});
+},onCompletePath:function(_8){
+this.remove(this.closeGuide,this.guide);
+var _9=this.getBounds();
+if(_9.w2&&this.closeRadius>this.util.distance(_a.x,_a.y,this.closePoint.x,this.closePoint.y)){
+this.onCompletePath(true);
+}else{
+var p={x:_a.x,y:_a.y};
+this.oddEvenClicks++;
+if(this.currentPathMode!=this.pathMode){
+if(this.pathMode=="Q"){
+p.t="Q";
+this.oddEvenClicks=0;
+}else{
+if(this.pathMode=="L"){
+p.t="L";
+}else{
+if(this.pathMode=="M"){
+p.t="M";
+this.closePoint={x:_a.x,y:_a.y};
+}
+}
+}
+this.currentPathMode=this.pathMode;
+}
+this.points.push(p);
+if(this.points.length>1){
+this.remove(this.guide);
+this.render();
+}
+}
+},createGuide:function(_b){
+if(!this.points.length){
+return;
+}
+var _c=[].concat(this.points);
+var pt={x:_b.x,y:_b.y};
+if(this.currentPathMode=="Q"&&this.oddEvenClicks%2){
+pt.t="L";
+}
+this.points.push(pt);
+this.render();
+this.points=_c;
+var _d=this.util.distance(_b.x,_b.y,this.closePoint.x,this.closePoint.y);
+if(this.points.length>1){
+if(_dthis.closeRadius&&this.closeGuide){
+this.remove(this.closeGuide);
+this.closeGuide=null;
+}
+}
+}
+},onMove:function(_e){
+if(!this._started){
+return;
+}
+this.createGuide(_e);
+},onDrag:function(_f){
+if(!this._started){
+return;
+}
+this.createGuide(_f);
+}});
+_3.drawing.tools.Path.setup={name:"dojox.drawing.tools.Path",tooltip:"Path Tool",iconClass:"iconLine"};
+_3.drawing.register(_3.drawing.tools.Path.setup,"tool");
+});
diff --git a/js/libs/dojox/drawing/tools/Path.js.uncompressed.js b/js/libs/dojox/drawing/tools/Path.js.uncompressed.js
new file mode 100644
index 0000000..c9a01af
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/Path.js.uncompressed.js
@@ -0,0 +1,207 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/tools/Path", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Path");
+
+dojox.drawing.tools.Path = dojox.drawing.util.oo.declare(
+ // summary:
+ // Class for a drawable Path
+ //
+ dojox.drawing.stencil.Path,
+ function(){
+ // summary: constructor
+
+ this.pathMode = "";
+ this.currentPathMode = "";
+ this._started = false;
+ this.oddEvenClicks = 0;
+
+ },
+ {
+ draws:true,
+ onDown: function(obj){
+ if(!this._started){
+ this.onStartPath(obj);
+ }
+
+ },
+
+ makeSubPath: function(_closePath){
+ if(_closePath){
+ if(this.currentPathMode=="Q"){
+ this.points.push({
+ x:this.points[0].x,
+ y:this.points[0].y
+ });
+ }
+ this.points.push({t:"Z"});
+ this.render();
+ }
+ this.currentPathMode = "";
+ this.pathMode = "M";
+ },
+
+ onStartPath: function(obj){
+ this._started = true;
+ this.revertRenderHit = this.renderHit;
+ this.renderHit = false;
+ this.closePath = false;
+
+
+ this.mouse.setEventMode("PathEdit");
+
+ this.closePoint = {x:obj.x, y:obj.y};
+
+ this._kc1 = this.connect(this.keys, "onEsc", this, function(){
+ this.onCompletePath(false);
+ });
+
+ this._kc2 = this.connect(this.keys, "onKeyUp", this, function(evt){
+
+ switch(evt.letter){
+ case "c":
+ this.onCompletePath(true); break;
+ case "l": this.pathMode = "L"; break;
+ case "m": this.makeSubPath(false); break;
+ case "q": this.pathMode = "Q"; break;
+ case "s": this.pathMode = "S"; break;
+ case "z": this.makeSubPath(true); break;
+ }
+
+ //console.log("KEY:", evt.letter);
+ });
+ },
+
+ onCompletePath:function(_closePath){
+ this.remove(this.closeGuide, this.guide);
+ var box = this.getBounds();
+ if(box.w2 && this.closeRadius>this.util.distance(obj.x, obj.y, this.closePoint.x, this.closePoint.y)){
+ this.onCompletePath(true);
+
+ }else {
+ var p = {
+ x:obj.x,
+ y:obj.y
+ };
+ this.oddEvenClicks++;
+ if(this.currentPathMode != this.pathMode){
+ if(this.pathMode=="Q"){
+ p.t = "Q";
+ this.oddEvenClicks = 0;
+ }else if(this.pathMode=="L"){
+ p.t = "L";
+ }else if(this.pathMode=="M"){
+ p.t = "M";
+ this.closePoint = {x:obj.x, y:obj.y};
+ }
+ this.currentPathMode = this.pathMode;
+ }
+
+
+ this.points.push(p);
+ if(this.points.length>1){
+ this.remove(this.guide);
+ this.render();
+ }
+
+ }
+
+ //console.log(this.stringPath);
+ },
+ createGuide: function(obj){
+ if(!this.points.length){ return; }
+ var realPoints = [].concat(this.points);
+
+ var pt = {
+ x:obj.x,
+ y:obj.y
+ };
+ if(this.currentPathMode=="Q" && this.oddEvenClicks % 2){
+ // On a Q curve, every other click needs to be a
+ // straight line - the inbetween Q coords don't render
+ pt.t = "L"; // this is not permanent
+ }
+
+ this.points.push(pt);
+
+ this.render();
+ this.points = realPoints;
+
+
+ var dist = this.util.distance(obj.x, obj.y, this.closePoint.x, this.closePoint.y);
+ if(this.points.length>1){
+ if(distthis.closeRadius && this.closeGuide){
+ this.remove(this.closeGuide);
+ this.closeGuide = null;
+ }
+ }
+
+ },
+
+ onMove: function(obj){
+ if(!this._started){ return; }
+ this.createGuide(obj);
+ },
+ onDrag: function(obj){
+ if(!this._started){ return; }
+ this.createGuide(obj);
+ }
+ }
+);
+
+dojox.drawing.tools.Path.setup = {
+ // summary: See Base ToolsSetup
+ //
+ name:"dojox.drawing.tools.Path",
+ tooltip:"Path Tool",
+ iconClass:"iconLine"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Path.setup, "tool");
+});
diff --git a/js/libs/dojox/drawing/tools/Pencil.js b/js/libs/dojox/drawing/tools/Pencil.js
new file mode 100644
index 0000000..d5fe9fd
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/Pencil.js
@@ -0,0 +1,49 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Pencil");
+_3.drawing.tools.Pencil=_3.drawing.util.oo.declare(_3.drawing.stencil.Path,function(){
+this._started=false;
+},{draws:true,minDist:15,onDown:function(_4){
+this._started=true;
+var p={x:_4.x,y:_4.y};
+this.points=[p];
+this.lastPoint=p;
+this.revertRenderHit=this.renderHit;
+this.renderHit=false;
+this.closePath=false;
+},onDrag:function(_5){
+if(!this._started||this.minDist>this.util.distance(_5.x,_5.y,this.lastPoint.x,this.lastPoint.y)){
+return;
+}
+var p={x:_5.x,y:_5.y};
+this.points.push(p);
+this.render();
+this.checkClosePoint(this.points[0],_5);
+this.lastPoint=p;
+},onUp:function(_6){
+if(!this._started){
+return;
+}
+if(!this.points||this.points.length<2){
+this._started=false;
+this.points=[];
+return;
+}
+var _7=this.getBounds();
+if(_7.w>built
+// wrapped by build app
+define("dojox/drawing/tools/Pencil", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Pencil");
+
+dojox.drawing.tools.Pencil = dojox.drawing.util.oo.declare(
+ // summary:
+ // Class for a drawable, continous Path
+ //
+ dojox.drawing.stencil.Path,
+ function(){
+ // summary: constructor
+ this._started = false;
+ },
+ {
+ draws:true,
+ // minDist: Number
+ // The distance the mouse must travel before rendering
+ // a path segment. Lower number is a higher definition
+ // path but more points.
+ minDist: 15, // how to make this more dynamic? Settable?
+
+ onDown: function(obj){
+ this._started = true;
+ var p = {
+ x:obj.x,
+ y:obj.y
+ };
+ this.points = [p];
+ this.lastPoint = p;
+ this.revertRenderHit = this.renderHit;
+ this.renderHit = false;
+ this.closePath = false;
+ },
+
+ onDrag: function(obj){
+ if(
+ !this._started
+ || this.minDist > this.util.distance(obj.x, obj.y, this.lastPoint.x, this.lastPoint.y)
+ ){ return; }
+
+ var p = {
+ x:obj.x,
+ y:obj.y
+ };
+ this.points.push(p);
+ this.render();
+ this.checkClosePoint(this.points[0], obj);
+ this.lastPoint = p;
+ },
+
+ onUp: function(obj){
+ if(!this._started){ return; }
+ if(!this.points || this.points.length<2){
+ this._started = false;
+ this.points = [];
+ return;
+ }
+ var box = this.getBounds();
+ if(box.w>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.Rect");
+_3.drawing.tools.Rect=_3.drawing.util.oo.declare(_3.drawing.stencil.Rect,function(){
+},{draws:true,onDrag:function(_4){
+var s=_4.start,e=_4;
+var x=s.xRectangle Tool
"+"SHIFT - constrain to square",iconClass:"iconRect"};
+_3.drawing.register(_3.drawing.tools.Rect.setup,"tool");
+});
diff --git a/js/libs/dojox/drawing/tools/Rect.js.uncompressed.js b/js/libs/dojox/drawing/tools/Rect.js.uncompressed.js
new file mode 100644
index 0000000..75ab4aa
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/Rect.js.uncompressed.js
@@ -0,0 +1,83 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/tools/Rect", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.Rect");
+
+dojox.drawing.tools.Rect = dojox.drawing.util.oo.declare(
+ // summary:
+ // Class for a drawable rectangle
+ //
+ dojox.drawing.stencil.Rect,
+ function(){
+ // summary: constructor
+ },
+ {
+ draws:true,
+
+ onDrag: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDrag
+ //
+ var s = obj.start, e = obj;
+ var x = s.x < e.x ? s.x : e.x,
+ y = s.y < e.y ? s.y : e.y,
+ w = s.x < e.x ? e.x-s.x : s.x-e.x,
+ h = s.y < e.y ? e.y-s.y : s.y-e.y;
+
+ if(this.keys.shift){ w = h = Math.max(w,h); }
+
+ if(this.keys.alt){
+ x-=w; y-=h; w*=2; h*=2;
+ x = Math.max(x, 0);
+ y = Math.max(y, 0);
+ }
+ this.setPoints ([
+ {x:x, y:y}, // TL
+ {x:x+w, y:y}, // TR
+ {x:x+w, y:y+h}, // BR
+ {x:x, y:y+h} // BL
+ ]);
+ this.render();
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(this.created || !this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+
+ //Default shape on single click
+ if(!this.shape){
+ var s = obj.start;
+ var e = this.minimumSize*4;
+ this.setPoints([
+ {x:s.x, y:s.y},
+ {x:s.x+e, y:s.y},
+ {x:s.x+e, y:s.y+e},
+ {x:s.x, y:s.y+e}
+ ]);
+ this.render();
+ }else{
+
+ // if too small, need to reset
+ var o = this.data;
+ if(o.widthRectangle Tool
'
+ + 'SHIFT - constrain to square',
+ iconClass:"iconRect"
+};
+dojox.drawing.register(dojox.drawing.tools.Rect.setup, "tool");
+});
diff --git a/js/libs/dojox/drawing/tools/TextBlock.js b/js/libs/dojox/drawing/tools/TextBlock.js
new file mode 100644
index 0000000..1d5055e
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/TextBlock.js
@@ -0,0 +1,484 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/stencil/Text"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.TextBlock");
+_2.require("dojox.drawing.stencil.Text");
+(function(){
+var _4;
+_2.addOnLoad(function(){
+_4=_2.byId("conEdit");
+if(!_4){
+console.error("A contenteditable div is missing from the main document. See 'dojox.drawing.tools.TextBlock'");
+}else{
+_4.parentNode.removeChild(_4);
+}
+});
+_3.drawing.tools.TextBlock=_3.drawing.util.oo.declare(_3.drawing.stencil.Text,function(_5){
+if(_5.data){
+var d=_5.data;
+var _6=d.text?this.typesetter(d.text):d.text;
+var w=!d.width?this.style.text.minWidth:d.width=="auto"?"auto":Math.max(d.width,this.style.text.minWidth);
+var h=this._lineHeight;
+if(_6&&w=="auto"){
+var o=this.measureText(this.cleanText(_6,false),w);
+w=o.w;
+h=o.h;
+}else{
+this._text="";
+}
+this.points=[{x:d.x,y:d.y},{x:d.x+w,y:d.y},{x:d.x+w,y:d.y+h},{x:d.x,y:d.y+h}];
+if(d.showEmpty||_6){
+this.editMode=true;
+_2.disconnect(this._postRenderCon);
+this._postRenderCon=null;
+this.connect(this,"render",this,"onRender",true);
+if(d.showEmpty){
+this._text=_6||"";
+this.edit();
+}else{
+if(_6&&d.editMode){
+this._text="";
+this.edit();
+}else{
+if(_6){
+this.render(_6);
+}
+}
+}
+setTimeout(_2.hitch(this,function(){
+this.editMode=false;
+}),100);
+}else{
+this.render();
+}
+}else{
+this.connectMouse();
+this._postRenderCon=_2.connect(this,"render",this,"_onPostRender");
+}
+},{draws:true,baseRender:false,type:"dojox.drawing.tools.TextBlock",_caretStart:0,_caretEnd:0,_blockExec:false,selectOnExec:true,showEmpty:false,onDrag:function(_7){
+if(!this.parentNode){
+this.showParent(_7);
+}
+var s=this._startdrag,e=_7.page;
+this._box.left=(s.x8?_9.height:this._lineHeight,border:d.width+"px "+d.style+" "+d.color,position:"absolute",zIndex:500,toPx:function(){
+var o={};
+for(var nm in this){
+o[nm]=typeof (this[nm])=="number"&&nm!="zIndex"?this[nm]+"px":this[nm];
+}
+return o;
+}};
+_2.style(this.parentNode,this._box);
+document.body.appendChild(this.parentNode);
+},createTextField:function(_a){
+var d=this.style.textMode.edit;
+this._box.border=d.width+"px "+d.style+" "+d.color;
+this._box.height="auto";
+this._box.width=Math.max(this._box.width,this.style.text.minWidth*this.mouse.zoom);
+_2.style(this.parentNode,this._box.toPx());
+this.parentNode.appendChild(_4);
+_2.style(_4,{height:_a?"auto":this._lineHeight+"px",fontSize:(this.textSize/this.mouse.zoom)+"px",fontFamily:this.style.text.family});
+_4.innerHTML=_a||"";
+return _4;
+},connectTextField:function(){
+if(this._textConnected){
+return;
+}
+var _b=_1.byId("greekPalette");
+var _c=_b==undefined?false:true;
+if(_c){
+_2.mixin(_b,{_pushChangeTo:_4,_textBlock:this});
+}
+this._textConnected=true;
+this._dropMode=false;
+this.mouse.setEventMode("TEXT");
+this.keys.editMode(true);
+var _d,_e,_f,kc4,_10=this,_11=false,_12=function(){
+if(_10._dropMode){
+return;
+}
+_2.forEach([_d,_e,_f,kc4],function(c){
+_2.disconnect(c);
+});
+_10._textConnected=false;
+_10.keys.editMode(false);
+_10.mouse.setEventMode();
+_10.execText();
+};
+_d=_2.connect(_4,"keyup",this,function(evt){
+if(_2.trim(_4.innerHTML)&&!_11){
+_2.style(_4,"height","auto");
+_11=true;
+}else{
+if(_2.trim(_4.innerHTML).length<2&&_11){
+_2.style(_4,"height",this._lineHeight+"px");
+_11=false;
+}
+}
+if(!this._blockExec){
+if(evt.keyCode==13||evt.keyCode==27){
+_2.stopEvent(evt);
+_12();
+}
+}else{
+if(evt.keyCode==_2.keys.SPACE){
+_2.stopEvent(evt);
+_c&&_b.onCancel();
+}
+}
+});
+_e=_2.connect(_4,"keydown",this,function(evt){
+if(evt.keyCode==13||evt.keyCode==27){
+_2.stopEvent(evt);
+}
+if(evt.keyCode==220){
+if(!_c){
+return;
+}
+_2.stopEvent(evt);
+this.getSelection(_4);
+this.insertText(_4,"\\");
+this._dropMode=true;
+this._blockExec=true;
+_b.show({around:this.parentNode,orient:{"BL":"TL"}});
+}
+if(!this._dropMode){
+this._blockExec=false;
+}else{
+switch(evt.keyCode){
+case _2.keys.UP_ARROW:
+case _2.keys.DOWN_ARROW:
+case _2.keys.LEFT_ARROW:
+case _2.keys.RIGHT_ARROW:
+_2.stopEvent(evt);
+_b._navigateByArrow(evt);
+break;
+case _2.keys.ENTER:
+_2.stopEvent(evt);
+_b._onCellClick(evt);
+break;
+case _2.keys.BACKSPACE:
+case _2.keys.DELETE:
+_2.stopEvent(evt);
+_b.onCancel();
+break;
+}
+}
+});
+_f=_2.connect(document,"mouseup",this,function(evt){
+if(!this._onAnchor&&evt.target.id!="conEdit"){
+_2.stopEvent(evt);
+_12();
+}else{
+if(evt.target.id=="conEdit"&&_4.innerHTML==""){
+_4.blur();
+setTimeout(function(){
+_4.focus();
+},200);
+}
+}
+});
+this.createAnchors();
+kc4=_2.connect(this.mouse,"setZoom",this,function(evt){
+_12();
+});
+_4.focus();
+this.onDown=function(){
+};
+this.onDrag=function(){
+};
+setTimeout(_2.hitch(this,function(){
+_4.focus();
+this.onUp=function(){
+if(!_10._onAnchor&&this.parentNode){
+_10.disconnectMouse();
+_12();
+_10.onUp=function(){
+};
+}
+};
+}),500);
+},execText:function(){
+var d=_2.marginBox(this.parentNode);
+var w=Math.max(d.w,this.style.text.minWidth);
+var txt=this.cleanText(_4.innerHTML,true);
+_4.innerHTML="";
+_4.blur();
+this.destroyAnchors();
+txt=this.typesetter(txt);
+var o=this.measureText(txt,w);
+var sc=this.mouse.scrollOffset();
+var org=this.mouse.origin;
+var x=this._box.left+sc.left-org.x;
+var y=this._box.top+sc.top-org.y;
+x*=this.mouse.zoom;
+y*=this.mouse.zoom;
+w*=this.mouse.zoom;
+o.h*=this.mouse.zoom;
+this.points=[{x:x,y:y},{x:x+w,y:y},{x:x+w,y:y+o.h},{x:x,y:y+o.h}];
+this.editMode=false;
+if(!o.text){
+this._text="";
+this._textArray=[];
+}
+this.render(o.text);
+this.onChangeText(this.getText());
+},edit:function(){
+this.editMode=true;
+var _13=this.getText()||"";
+if(this.parentNode||!this.points){
+return;
+}
+var d=this.pointsToData();
+var sc=this.mouse.scrollOffset();
+var org=this.mouse.origin;
+var obj={pageX:(d.x)/this.mouse.zoom-sc.left+org.x,pageY:(d.y)/this.mouse.zoom-sc.top+org.y,width:d.width/this.mouse.zoom,height:d.height/this.mouse.zoom};
+this.remove(this.shape,this.hit);
+this.showParent(obj);
+this.createTextField(_13.replace("/n"," "));
+this.connectTextField();
+if(_13){
+this.setSelection(_4,"end");
+}
+},cleanText:function(txt,_14){
+var _15=function(str){
+var _16={"<":"<",">":">","&":"&"};
+for(var nm in _16){
+str=str.replace(new RegExp(nm,"gi"),_16[nm]);
+}
+return str;
+};
+if(_14){
+_2.forEach(["
","
","
","\\n","\\r"],function(br){
+txt=txt.replace(new RegExp(br,"gi")," ");
+});
+}
+txt=txt.replace(/ /g," ");
+txt=_15(txt);
+txt=_2.trim(txt);
+txt=txt.replace(/\s{2,}/g," ");
+return txt;
+},measureText:function(str,_17){
+var r="(
)|(\\n)|(\\r)";
+this.showParent({width:_17||"auto",height:"auto"});
+this.createTextField(str);
+var txt="";
+var el=_4;
+el.innerHTML="X";
+var h=_2.marginBox(el).h;
+el.innerHTML=str;
+if(!_17||new RegExp(r,"gi").test(str)){
+txt=str.replace(new RegExp(r,"gi"),"\n");
+el.innerHTML=str.replace(new RegExp(r,"gi"),"
");
+}else{
+if(_2.marginBox(el).h==h){
+txt=str;
+}else{
+var ar=str.split(" ");
+var _18=[[]];
+var _19=0;
+el.innerHTML="";
+while(ar.length){
+var _1a=ar.shift();
+el.innerHTML+=_1a+" ";
+if(_2.marginBox(el).h>h){
+_19++;
+_18[_19]=[];
+el.innerHTML=_1a+" ";
+}
+_18[_19].push(_1a);
+}
+_2.forEach(_18,function(ar,i){
+_18[i]=ar.join(" ");
+});
+txt=_18.join("\n");
+el.innerHTML=txt.replace("\n","
");
+}
+}
+var dim=_2.marginBox(el);
+_4.parentNode.removeChild(_4);
+_2.destroy(this.parentNode);
+this.parentNode=null;
+return {h:dim.h,w:dim.w,text:txt};
+},_downOnCanvas:false,onDown:function(obj){
+this._startdrag={x:obj.pageX,y:obj.pageY};
+_2.disconnect(this._postRenderCon);
+this._postRenderCon=null;
+this._downOnCanvas=true;
+},createAnchors:function(){
+this._anchors={};
+var _1b=this;
+var d=this.style.anchors,b=d.width,w=d.size-b*2,h=d.size-b*2,p=(d.size)/2*-1+"px";
+var s={position:"absolute",width:w+"px",height:h+"px",backgroundColor:d.fill,border:b+"px "+d.style+" "+d.color};
+if(_2.isIE){
+s.paddingLeft=w+"px";
+s.fontSize=w+"px";
+}
+var ss=[{top:p,left:p},{top:p,right:p},{bottom:p,right:p},{bottom:p,left:p}];
+for(var i=0;i<4;i++){
+var _1c=(i==0)||(i==3);
+var id=this.util.uid(_1c?"left_anchor":"right_anchor");
+var a=_2.create("div",{id:id},this.parentNode);
+_2.style(a,_2.mixin(_2.clone(s),ss[i]));
+var md,mm,mu;
+var md=_2.connect(a,"mousedown",this,function(evt){
+_1c=evt.target.id.indexOf("left")>-1;
+_1b._onAnchor=true;
+var _1d=evt.pageX;
+var _1e=this._box.width;
+_2.stopEvent(evt);
+mm=_2.connect(document,"mousemove",this,function(evt){
+var x=evt.pageX;
+if(_1c){
+this._box.left=x;
+this._box.width=_1e+_1d-x;
+}else{
+this._box.width=x+_1e-_1d;
+}
+_2.style(this.parentNode,this._box.toPx());
+});
+mu=_2.connect(document,"mouseup",this,function(evt){
+_1d=this._box.left;
+_1e=this._box.width;
+_2.disconnect(mm);
+_2.disconnect(mu);
+_1b._onAnchor=false;
+_4.focus();
+_2.stopEvent(evt);
+});
+});
+this._anchors[id]={a:a,cons:[md]};
+}
+},destroyAnchors:function(){
+for(var n in this._anchors){
+_2.forEach(this._anchors[n].con,_2.disconnect,_2);
+_2.destroy(this._anchors[n].a);
+}
+},setSavedCaret:function(val){
+this._caretStart=this._caretEnd=val;
+},getSavedCaret:function(){
+return {start:this._caretStart,end:this._caretEnd};
+},insertText:function(_1f,val){
+var t,_20=_1f.innerHTML;
+var _21=this.getSavedCaret();
+_20=_20.replace(/ /g," ");
+t=_20.substr(0,_21.start)+val+_20.substr(_21.end);
+t=this.cleanText(t,true);
+this.setSavedCaret(Math.min(t.length,(_21.end+val.length)));
+_1f.innerHTML=t;
+this.setSelection(_1f,"stored");
+},getSelection:function(_22){
+var _23,end;
+if(_2.doc.selection){
+var r=_2.doc.selection.createRange();
+var rs=_2.body().createTextRange();
+rs.moveToElementText(_22);
+var re=rs.duplicate();
+rs.moveToBookmark(r.getBookmark());
+re.setEndPoint("EndToStart",rs);
+_23=this._caretStart=re.text.length;
+end=this._caretEnd=re.text.length+r.text.length;
+console.warn("Caret start: ",_23," end: ",end," length: ",re.text.length," text: ",re.text);
+}else{
+this._caretStart=_2.global.getSelection().getRangeAt(_22).startOffset;
+this._caretEnd=_2.global.getSelection().getRangeAt(_22).endOffset;
+}
+},setSelection:function(_24,_25){
+console.warn("setSelection:");
+if(_2.doc.selection){
+var rs=_2.body().createTextRange();
+rs.moveToElementText(_24);
+switch(_25){
+case "end":
+rs.collapse(false);
+break;
+case "beg"||"start":
+rs.collapse();
+break;
+case "all":
+rs.collapse();
+rs.moveStart("character",0);
+rs.moveEnd("character",_24.text.length);
+break;
+case "stored":
+rs.collapse();
+var dif=this._caretStart-this._caretEnd;
+rs.moveStart("character",this._caretStart);
+rs.moveEnd("character",dif);
+break;
+}
+rs.select();
+}else{
+var _26=function(_27,_28){
+_28=_28||[];
+for(var i=0;i<_27.childNodes.length;i++){
+var n=_27.childNodes[i];
+if(n.nodeType==3){
+_28.push(n);
+}else{
+if(n.tagName&&n.tagName.toLowerCase()=="img"){
+_28.push(n);
+}
+}
+if(n.childNodes&&n.childNodes.length){
+_26(n,_28);
+}
+}
+return _28;
+};
+_24.focus();
+var _29=_2.global.getSelection();
+_29.removeAllRanges();
+var r=_2.doc.createRange();
+var _2a=_26(_24);
+switch(_25){
+case "end":
+undefined;
+r.setStart(_2a[_2a.length-1],_2a[_2a.length-1].textContent.length);
+r.setEnd(_2a[_2a.length-1],_2a[_2a.length-1].textContent.length);
+break;
+case "beg"||"start":
+r.setStart(_2a[0],0);
+r.setEnd(_2a[0],0);
+break;
+case "all":
+r.setStart(_2a[0],0);
+r.setEnd(_2a[_2a.length-1],_2a[_2a.length-1].textContent.length);
+break;
+case "stored":
+undefined;
+r.setStart(_2a[0],this._caretStart);
+r.setEnd(_2a[0],this._caretEnd);
+}
+_29.addRange(r);
+}
+}});
+_3.drawing.tools.TextBlock.setup={name:"dojox.drawing.tools.TextBlock",tooltip:"Text Tool",iconClass:"iconText"};
+_3.drawing.register(_3.drawing.tools.TextBlock.setup,"tool");
+})();
+});
diff --git a/js/libs/dojox/drawing/tools/TextBlock.js.uncompressed.js b/js/libs/dojox/drawing/tools/TextBlock.js.uncompressed.js
new file mode 100644
index 0000000..4584e5e
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/TextBlock.js.uncompressed.js
@@ -0,0 +1,808 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/tools/TextBlock", ["dijit","dojo","dojox","dojo/require!dojox/drawing/stencil/Text"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.TextBlock");
+dojo.require("dojox.drawing.stencil.Text");
+
+(function(){
+ var conEdit;
+ dojo.addOnLoad(function(){
+ // In order to use VML in IE, it's necessary to remove the
+ // DOCTYPE. But this has the side effect that causes a bug
+ // where contenteditable divs cannot be made dynamically.
+ // The solution is to include one in the main document
+ // that can be appended and removed as necessary:
+ //
+ //
+ // console.log("Removing conedit");
+ conEdit = dojo.byId("conEdit");
+ if(!conEdit){
+ console.error("A contenteditable div is missing from the main document. See 'dojox.drawing.tools.TextBlock'")
+ }else{
+ conEdit.parentNode.removeChild(conEdit);
+ }
+ });
+
+ dojox.drawing.tools.TextBlock = dojox.drawing.util.oo.declare(
+ // summary:
+ // A tool to create text fields on a canvas.
+ // description:
+ // Extends stencil.Text by adding an HTML layer that
+ // can be dragged out to a certain size, and accept
+ // a text entry. Will wrap text to the width of the
+ // html field.
+ // When created programmtically, use 'auto' to shrink
+ // the width to the size of the text. Use line breaks
+ // ( \n ) to create new lines.
+ //
+ // TODO - disable zoom while showing?
+ //
+ // FIXME:
+ // Handles width: auto, align:middle, etc. but for
+ // display only, edit is out of whack
+ //
+ dojox.drawing.stencil.Text,
+ function(options){
+ // summary: constructor
+ //
+ if(options.data){
+ var d = options.data;
+ var text = d.text ? this.typesetter(d.text) : d.text;
+ var w = !d.width ? this.style.text.minWidth : d.width=="auto" ? "auto" : Math.max(d.width, this.style.text.minWidth);
+ var h = this._lineHeight;
+
+ if(text && w=="auto"){
+ var o = this.measureText(this.cleanText(text, false), w);
+ w = o.w;
+ h = o.h;
+ }else{
+ // w = this.style.text.minWidth;
+ this._text = "";
+ }
+
+ this.points = [
+ {x:d.x, y:d.y},
+ {x:d.x+w, y:d.y},
+ {x:d.x+w, y:d.y+h},
+ {x:d.x, y:d.y+h}
+ ];
+
+ if(d.showEmpty || text){
+ this.editMode = true;
+
+
+ dojo.disconnect(this._postRenderCon);
+ this._postRenderCon = null;
+ this.connect(this, "render", this, "onRender", true);
+
+ if(d.showEmpty){
+ this._text = text || "";
+ this.edit();
+ }else if(text && d.editMode){
+ this._text = "";
+ this.edit();
+ }else if(text){
+ this.render(text);
+ }
+ setTimeout(dojo.hitch(this, function(){
+ this.editMode = false;
+ }),100)
+
+ }else{
+ // Why make it if it won't render...
+ this.render();
+ }
+
+ }else{
+ this.connectMouse();
+ this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+ }
+ //console.log("TextBlock:", this.id)
+ },
+ {
+ draws:true,
+ baseRender:false,
+ type:"dojox.drawing.tools.TextBlock",
+ _caretStart: 0,
+ _caretEnd: 0,
+ _blockExec: false,
+
+/*=====
+StencilData: {
+ // summary:
+ // The data used to create the dojox.gfx Text
+ // x: Number
+ // Left point x
+ // y: Number
+ // Top point y
+ // width: ? Number|String
+ // Optional width of Text. Not required but reccommended.
+ // for auto-sizing, use 'auto'
+ // height: ? Number
+ // Optional height of Text. If not provided, _lineHeight is used.
+ // text: String
+ // The string content. If not provided, may auto-delete depending on defaults.
+},
+=====*/
+
+ // selectOnExec: Boolean
+ // Whether the Stencil is selected when the text field
+ // is executed or not
+ selectOnExec:true,
+ //
+ // showEmpty: Boolean
+ // If true and there is no text in the data, the TextBlock
+ // Is displayed and focused and awaits input.
+ showEmpty: false,
+
+ onDrag: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDrag
+ //
+ if(!this.parentNode){
+ this.showParent(obj);
+ }
+ var s = this._startdrag, e = obj.page;
+ this._box.left = (s.x < e.x ? s.x : e.x);
+ this._box.top = s.y;
+ this._box.width = (s.x < e.x ? e.x-s.x : s.x-e.x) + this.style.text.pad;
+
+ dojo.style(this.parentNode, this._box.toPx());
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+
+ if(!this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+
+ var c = dojo.connect(this, "render", this, function(){
+ dojo.disconnect(c);
+ this.onRender(this);
+
+ });
+ this.editMode = true;
+ this.showParent(obj);
+ this.created = true;
+ this.createTextField();
+ this.connectTextField();
+ },
+
+ showParent: function(/*EventObject*/obj){
+ // summary:
+ // Internal. Builds the parent node for the
+ // contenteditable HTML node.
+ //
+ if(this.parentNode){ return; }
+ var x = obj.pageX || 10;
+ var y = obj.pageY || 10;
+ this.parentNode = dojo.doc.createElement("div");
+ this.parentNode.id = this.id;
+ var d = this.style.textMode.create;
+ this._box = {
+ left:x,
+ top:y,
+ width:obj.width || 1,
+ height:obj.height && obj.height>8 ? obj.height : this._lineHeight,
+ border:d.width+"px "+d.style+" "+d.color,
+ position:"absolute",
+ zIndex:500,
+ toPx: function(){
+ var o = {};
+ for(var nm in this){
+ o[nm] = typeof(this[nm])=="number" && nm!="zIndex" ? this[nm] + "px" : this[nm];
+ }
+ return o;
+ }
+ };
+
+ dojo.style(this.parentNode, this._box);
+
+ document.body.appendChild(this.parentNode);
+ },
+ createTextField: function(/*String*/txt){
+ // summary:
+ // Internal. Inserts the contenteditable HTML node
+ // into its parent node, and styles it.
+ //
+ // style parent
+ var d = this.style.textMode.edit;
+ this._box.border = d.width+"px "+d.style+" "+d.color;
+ this._box.height = "auto";
+ this._box.width = Math.max(this._box.width, this.style.text.minWidth*this.mouse.zoom);
+ dojo.style(this.parentNode, this._box.toPx());
+ // style input
+ this.parentNode.appendChild(conEdit);
+ dojo.style(conEdit, {
+ height: txt ? "auto" : this._lineHeight+"px",
+ fontSize:(this.textSize/this.mouse.zoom)+"px",
+ fontFamily:this.style.text.family
+ });
+ // FIXME:
+ // In Safari, if the txt ends with '&' it gets stripped
+ conEdit.innerHTML = txt || "";
+
+ return conEdit; //HTMLNode
+ },
+ connectTextField: function(){
+ // summary:
+ // Internal. Creates the connections to the
+ // contenteditable HTML node.
+ //
+ if(this._textConnected){ return; } // good ol' IE and its double events
+ // FIXME:
+ // Ouch-getting greekPalette by id. At the minimum this should
+ // be from the plugin manager
+ var greekPalette = dijit.byId("greekPalette");
+ var greekHelp = greekPalette==undefined ? false : true;
+ if(greekHelp){
+ //set it up
+ dojo.mixin(greekPalette,{
+ _pushChangeTo: conEdit,
+ _textBlock: this
+ });
+ };
+
+ this._textConnected = true;
+ this._dropMode = false;
+ this.mouse.setEventMode("TEXT");
+ this.keys.editMode(true);
+ var kc1, kc2, kc3, kc4, self = this, _autoSet = false,
+ exec = function(){
+ if(self._dropMode){ return; }
+ dojo.forEach([kc1,kc2,kc3,kc4], function(c){
+ dojo.disconnect(c)
+ });
+ self._textConnected = false;
+ self.keys.editMode(false);
+ self.mouse.setEventMode();
+ self.execText();
+ };
+
+ kc1 = dojo.connect(conEdit, "keyup", this, function(evt){
+ // if text is empty, we need a height so the field's height
+ // doesn't collapse
+ if(dojo.trim(conEdit.innerHTML) && !_autoSet){
+ dojo.style(conEdit, "height", "auto"); _autoSet = true;
+ }else if(dojo.trim(conEdit.innerHTML).length<2 && _autoSet){
+ dojo.style(conEdit, "height", this._lineHeight+"px"); _autoSet = false;
+ }
+
+ if(!this._blockExec){
+ if(evt.keyCode==13 || evt.keyCode==27){
+ dojo.stopEvent(evt);
+ exec();
+ }
+ } else {
+ if(evt.keyCode==dojo.keys.SPACE){
+ dojo.stopEvent(evt);
+ greekHelp && greekPalette.onCancel();
+ }
+ }
+ });
+ kc2 = dojo.connect(conEdit, "keydown", this, function(evt){
+ if(evt.keyCode==13 || evt.keyCode==27){ // TODO: make escape an option
+ dojo.stopEvent(evt);
+ }
+ // if backslash, user is inputting a special character
+ // This gives popup help.
+ if(evt.keyCode==220){
+ if(!greekHelp){
+ console.info("For greek letter assistance instantiate: dojox.drawing.plugins.drawing.GreekPalette");
+ return;
+ }
+ dojo.stopEvent(evt);
+ this.getSelection(conEdit);
+ // Differences in how browsers handle events made it necessary
+ // to stop the evt and add the backslash here.
+ this.insertText(conEdit,"\\");
+ this._dropMode = true;
+ this._blockExec = true;
+ greekPalette.show({
+ around:this.parentNode,
+ orient:{'BL':'TL'}
+ });
+ }
+ if(!this._dropMode){
+ this._blockExec = false;
+ } else {
+ // Controls for when we have a character helper and it's active
+ switch(evt.keyCode){
+ case dojo.keys.UP_ARROW:
+ case dojo.keys.DOWN_ARROW:
+ case dojo.keys.LEFT_ARROW:
+ case dojo.keys.RIGHT_ARROW:
+ dojo.stopEvent(evt);
+ greekPalette._navigateByArrow(evt);
+ break;
+ case dojo.keys.ENTER:
+ dojo.stopEvent(evt);
+ greekPalette._onCellClick(evt);
+ break;
+ case dojo.keys.BACKSPACE:
+ case dojo.keys.DELETE:
+ dojo.stopEvent(evt);
+ greekPalette.onCancel();
+ break;
+ }
+ }
+
+ });
+
+ kc3 = dojo.connect(document, "mouseup", this, function(evt){
+ // note: _onAnchor means an anchor has been clicked upon
+ if(!this._onAnchor && evt.target.id != "conEdit"){
+ dojo.stopEvent(evt);
+ exec();
+ }else if(evt.target.id == "conEdit" && conEdit.innerHTML == ""){
+ // wonky stuff happens when you click on the
+ // field when its empty.
+ conEdit.blur();
+ setTimeout(function(){
+ conEdit.focus();
+ },200)
+ }
+ });
+
+ this.createAnchors();
+
+ kc4 = dojo.connect(this.mouse, "setZoom", this, function(evt){
+ exec();
+ });
+
+
+ conEdit.focus();
+
+ this.onDown = function(){};
+ this.onDrag = function(){};
+
+ setTimeout(dojo.hitch(this, function(){
+ // once again for Silverlight:
+ conEdit.focus();
+
+ // this is a pretty odd chunk of code here.
+ // specifcally need to overwrite old onUp
+ // however, this still gets called. its
+ // not disconnecting.
+ this.onUp = function(){
+ if(!self._onAnchor && this.parentNode){
+ self.disconnectMouse();
+ exec();
+ self.onUp = function(){}
+ }
+ }
+ }), 500);
+ },
+
+
+ execText: function(){
+ // summary:
+ // Internal. Method fired when text is executed,
+ // via mouse-click-off, ESC key or Enter key.
+ //
+ var d = dojo.marginBox(this.parentNode);
+ var w = Math.max(d.w, this.style.text.minWidth);
+
+ var txt = this.cleanText(conEdit.innerHTML, true);
+ conEdit.innerHTML = "";
+ conEdit.blur();
+ this.destroyAnchors();
+
+ // need to convert characters before measuring width.
+ txt = this.typesetter(txt);
+
+ var o = this.measureText(txt, w);
+ var sc = this.mouse.scrollOffset();
+ var org = this.mouse.origin;
+
+ var x = this._box.left + sc.left - org.x;
+ var y = this._box.top + sc.top - org.y;
+
+ x *= this.mouse.zoom;
+ y *= this.mouse.zoom;
+ w *= this.mouse.zoom;
+ o.h *= this.mouse.zoom;
+
+
+ this.points = [
+ {x:x, y:y},
+ {x:x+w, y:y},
+ {x:x+w, y:y+o.h},
+ {x:x, y:y+o.h}
+ ];
+ this.editMode = false;
+
+
+ console.log("EXEC TEXT::::", this._postRenderCon);
+
+ if(!o.text){
+ this._text = "";
+ this._textArray = [];
+ }
+ // Only for Combo objects (vectors, rectangle, or ellipse).
+ this.render(o.text);
+ this.onChangeText(this.getText());
+ },
+
+ edit: function(){
+ // summary:
+ // Internal?
+ // Method used to instantiate the contenteditable HTML node.
+ //
+ this.editMode = true;
+ var text = this.getText() || "";
+ console.log("EDIT TEXT:",text, " ",text.replace("/n", " "));
+ // NOTE: no mouse obj
+ if(this.parentNode || !this.points){ return; }
+ var d = this.pointsToData();
+
+ var sc = this.mouse.scrollOffset();
+ var org = this.mouse.origin;
+
+ var obj = {
+ pageX: (d.x ) / this.mouse.zoom - sc.left + org.x,
+ pageY: (d.y ) / this.mouse.zoom- sc.top + org.y,
+ width:d.width / this.mouse.zoom,
+ height:d.height / this.mouse.zoom
+ };
+
+ this.remove(this.shape, this.hit);
+ this.showParent(obj);
+ this.createTextField(text.replace("/n", " "));
+ this.connectTextField();
+ if(text){
+ //setTimeout(dojo.hitch(this, function(){
+ this.setSelection(conEdit, "end");
+ //}), 500)
+ }
+ },
+ cleanText: function(/*String*/txt, /*Boolean*/removeBreaks){
+ // summary:
+ // Cleans text. Strings HTML chars and double spaces
+ // and optionally removes line breaks.
+ var replaceHtmlCodes = function(str){
+ var chars = {
+ "<":"<",
+ ">":">",
+ "&":"&"
+ };
+ for(var nm in chars){
+ str = str.replace(new RegExp(nm, "gi"), chars[nm])
+ }
+ return str
+ };
+
+ if(removeBreaks){
+ dojo.forEach(['
', '
', '
', '\\n', '\\r'], function(br){
+ txt = txt.replace(new RegExp(br, 'gi'), " ");
+ });
+ }
+ txt = txt.replace(/ /g, " ");
+ txt = replaceHtmlCodes(txt);
+ txt = dojo.trim(txt);
+ // remove double spaces, since SVG doesn't show them anyway
+ txt = txt.replace(/\s{2,}/g, " ");
+ return txt; //String
+ },
+
+ measureText: function(/* String */ str, /* ? Number */width){
+ // summary:
+ // Mechanism for measuring text.
+ // SVG nor VML have a way of determining the width or
+ // height of a block of text. This method creates an
+ // HTML text block and those measurements are used for
+ // displaying the SVG/VML text.
+ // arguments:
+ // str: String
+ // The text to display and measure.
+ // width: [optional] Number
+ // If the width is not provided, it will be assumed
+ // that the text is one line and the width will be
+ // measured and the _lineHeight used for th height.
+ // If width is provided, word-wrap is assumed, and
+ // line breaks will be inserted into the text at each
+ // point where a word wraps in the HTML. The height is
+ // then measured.
+ //
+ var r = "(
)|(\\n)|(\\r)";
+ this.showParent({width:width || "auto", height:"auto"});
+ this.createTextField(str);
+ var txt = "";
+ var el = conEdit;
+ el.innerHTML = "X";
+ var h = dojo.marginBox(el).h;
+
+ el.innerHTML = str;
+
+ if(!width || new RegExp(r, "gi").test(str)){
+ // has line breaks in text
+ txt = str.replace(new RegExp(r, "gi"), "\n");
+ el.innerHTML = str.replace(new RegExp(r, "gi"), "
");
+
+ }else if(dojo.marginBox(el).h == h){
+ // one line
+ txt = str;
+
+ }else{
+ // text wraps
+ var ar = str.split(" ");
+ var strAr = [[]];
+ var line = 0;
+ el.innerHTML = "";
+ while(ar.length){
+ var word = ar.shift();
+ el.innerHTML += word+" "; //urk, always an extra space
+ if(dojo.marginBox(el).h > h){
+ line++;
+ strAr[line] = [];
+ el.innerHTML = word+" ";
+ }
+ strAr[line].push(word)
+ }
+
+ dojo.forEach(strAr, function(ar, i){
+ strAr[i] = ar.join(" ");
+ });
+ txt = strAr.join("\n");
+
+ // get the resultant height
+ el.innerHTML = txt.replace("\n", "
");
+
+ }
+
+ var dim = dojo.marginBox(el);
+
+ conEdit.parentNode.removeChild(conEdit);
+ dojo.destroy(this.parentNode);
+ this.parentNode = null;
+
+ return {h:dim.h, w:dim.w, text:txt}; //Object
+ },
+
+ _downOnCanvas:false,
+ onDown: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDown
+ //
+ this._startdrag = {
+ x: obj.pageX,
+ y: obj.pageY
+ };
+ dojo.disconnect(this._postRenderCon);
+ this._postRenderCon = null;
+ this._downOnCanvas = true;
+ },
+
+ createAnchors: function(){
+ // summary:
+ // Internal. Creates HTML nodes at each corner
+ // of the contenteditable div. These nodes are
+ // draggable and will resize the div horizontally.
+ //
+ this._anchors = {};
+ var self = this;
+ var d = this.style.anchors,
+ b = d.width,
+ w = d.size-b*2,
+ h = d.size-b*2,
+ p = (d.size)/2*-1 + "px";
+
+ var s = {
+ position:"absolute",
+ width:w+"px",
+ height:h+"px",
+ backgroundColor:d.fill,
+ border:b+"px " + d.style + " "+d.color
+ };
+ if(dojo.isIE){
+ s.paddingLeft = w + "px";
+ s.fontSize = w + "px"
+ }
+ var ss = [
+ {top: p, left:p},
+ {top:p, right:p},
+ {bottom:p, right:p},
+ {bottom:p,left:p}
+ ];
+ for(var i=0;i<4;i++){
+ var isLeft = (i==0) || (i==3);
+ var id = this.util.uid(isLeft ? "left_anchor" : "right_anchor");
+
+ var a = dojo.create("div", {id:id}, this.parentNode);
+ dojo.style(a, dojo.mixin(dojo.clone(s), ss[i]));
+
+ var md, mm, mu;
+ var md = dojo.connect(a, "mousedown", this, function(evt){
+ isLeft = evt.target.id.indexOf("left")>-1;
+ self._onAnchor = true;
+ var orgX = evt.pageX;
+ var orgW = this._box.width;
+ dojo.stopEvent(evt);
+
+
+ mm = dojo.connect(document, "mousemove", this, function(evt){
+ var x = evt.pageX;
+ if(isLeft){
+ this._box.left = x;
+ this._box.width = orgW + orgX - x;
+ }else{
+ this._box.width = x + orgW - orgX;
+ }
+ dojo.style(this.parentNode, this._box.toPx());
+ });
+
+ mu = dojo.connect(document, "mouseup", this, function(evt){
+ orgX = this._box.left;
+ orgW = this._box.width;
+ dojo.disconnect(mm);
+ dojo.disconnect(mu);
+ self._onAnchor = false;
+ conEdit.focus();
+ dojo.stopEvent(evt);
+ });
+ });
+
+ this._anchors[id] = {
+ a:a,
+ cons:[md]
+ }
+ }
+ },
+
+ destroyAnchors: function(){
+ // summary:
+ // Internal. Destroys HTML anchors.
+ for(var n in this._anchors){
+ dojo.forEach(this._anchors[n].con, dojo.disconnect, dojo);
+ dojo.destroy(this._anchors[n].a);
+ };
+ },
+
+ setSavedCaret: function(val){
+ // summary:
+ // Internal, called when caret needs to
+ // be moved into position after text is added
+ this._caretStart = this._caretEnd = val;
+ },
+
+ getSavedCaret: function(){
+ return {start: this._caretStart, end: this._caretEnd}
+ },
+
+ insertText: function(node,val){
+ // summary:
+ // Uses saved caret position to insert text
+ // into position and place caret at the end of
+ // insertion
+ //
+ var t, text = node.innerHTML;
+ var caret = this.getSavedCaret();
+
+ text = text.replace(/ /g, " ");
+ t = text.substr(0,caret.start) + val + text.substr(caret.end);
+ t = this.cleanText(t,true);
+ this.setSavedCaret(Math.min(t.length,(caret.end + val.length)));
+ node.innerHTML = t;
+ this.setSelection(node,"stored");
+ },
+
+ getSelection: function(node){
+ // summary:
+ // This gets and stores the caret position
+ // in the contentEditable div (conEdit).
+ // NOTE: Doesn't work with html nodes inside
+ // the div.
+ //
+ var start, end;
+ if(dojo.doc.selection){
+ //debugger;
+ var r = dojo.doc.selection.createRange();
+ var rs = dojo.body().createTextRange();
+ rs.moveToElementText(node);
+ var re = rs.duplicate();
+ rs.moveToBookmark(r.getBookmark());
+ re.setEndPoint('EndToStart', rs);
+ start = this._caretStart = re.text.length;
+ end = this._caretEnd = re.text.length+r.text.length;
+ console.warn("Caret start: ",start," end: ",end," length: ",re.text.length," text: ",re.text);
+ } else {
+ this._caretStart = dojo.global.getSelection().getRangeAt(node).startOffset;
+ this._caretEnd = dojo.global.getSelection().getRangeAt(node).endOffset;
+ console.log("Caret start: ", this._caretStart," end: ", this._caretEnd);
+ }
+ },
+
+ setSelection: function(node, what){
+ // summary:
+ // Used for placing the cursor during edits and character help.
+ // Takes the values: end, beg, start, all or any numerical value
+ // (in which case the number will constitute the caret position)
+ //
+ console.warn("setSelection:");
+ if(dojo.doc.selection){ // IE
+ //debugger;
+ var rs = dojo.body().createTextRange();
+ rs.moveToElementText(node);
+
+ switch(what){
+ case "end":
+ rs.collapse(false);
+ break;
+ case "beg" || "start":
+ rs.collapse();
+ break;
+ case "all":
+ rs.collapse();
+ rs.moveStart("character", 0);
+ rs.moveEnd("character",node.text.length);
+ break;
+ case "stored":
+ rs.collapse();
+ var dif = this._caretStart-this._caretEnd;
+ //console.log("start: ",this._caretStart, " end: ",this._caretEnd," dif: ",dif);
+ rs.moveStart("character",this._caretStart);
+ rs.moveEnd("character",dif);
+ break;
+ };
+ rs.select();
+
+ }else{
+ var getAllChildren = function(node, children){
+ children = children || [];
+ for(var i=0;i>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/stencil/Path"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.custom.Axes");
+_2.require("dojox.drawing.stencil.Path");
+_3.drawing.tools.custom.Axes=_3.drawing.util.oo.declare(_3.drawing.stencil.Path,function(_4){
+this.closePath=false;
+this.xArrow=new _3.drawing.annotations.Arrow({stencil:this,idx1:0,idx2:1});
+this.yArrow=new _3.drawing.annotations.Arrow({stencil:this,idx1:2,idx2:1});
+if(_4.data){
+this.style.zAxisEnabled=_4.data.cosphi==1?true:false;
+this.setData(_4.data);
+}
+if(this.style.zAxisEnabled){
+this.data.cosphi=1;
+var _5={};
+_2.mixin(_5,_4);
+_2.mixin(_5,{container:this.container.createGroup(),style:this.style,showAngle:false,label:null});
+if(_4.data&&(!_5.data.radius||!_5.data.angle)){
+_5.data.x2=_5.data.x4;
+_5.data.y2=_5.data.y4;
+}
+_5.style.zAxis=true;
+this.zAxis=new _3.drawing.tools.custom.Vector(_5);
+this.zAxis.minimumSize=5;
+this.connectMult([[this,"onChangeStyle",this.zAxis,"onChangeStyle"],[this,"select",this.zAxis,"select"],[this,"deselect",this.zAxis,"deselect"],[this,"onDelete",this.zAxis,"destroy"],[this,"onDrag",this,"zSet"],[this,"onTransform",this,"zSet"],[this.zAxis,"onBeforeRender",this,"zSet"],[this,"_onPostRender",this.zAxis,"render"]]);
+}
+if(this.points&&this.points.length){
+this.setPoints=this._postSetPoints;
+this.render();
+_4.label&&this.setLabel(_4.label);
+_4.shadow&&this.addShadow(_4.shadow);
+}
+},{draws:true,type:"dojox.drawing.tools.custom.Axes",minimumSize:30,showAngle:true,closePath:false,baseRender:false,zScale:0.5,zPoint:function(_6){
+_6.radius=this.util.length(_6);
+var pt=this.util.pointOnCircle(_6.start.x,_6.start.y,_6.radius*this.zScale,this.style.zAngle);
+return {x:pt.x,y:pt.y,skip:true,noAnchor:true};
+},zSet:function(){
+if(!this.zAxis){
+return;
+}
+var c=this.points[1];
+var z=this.points[3];
+var p=[{x:c.x,y:c.y},{x:z.x,y:z.y}];
+var _7=this.util.length({start:{x:c.x,y:c.y},x:z.x,y:z.y});
+_7>this.zAxis.minimumSize?this.zAxis.setPoints(p):false;
+this.zAxis.cosphi=1;
+},createLabels:function(){
+var _8={align:"middle",valign:"middle",util:this.util,annotation:true,container:this.container,mouse:this.mouse,stencil:this};
+this.labelX=new _3.drawing.annotations.Label(_2.mixin(_8,{labelPosition:this.setLabelX}));
+this.labelY=new _3.drawing.annotations.Label(_2.mixin(_8,{labelPosition:this.setLabelY}));
+if(this.style.zAxisEnabled){
+this.labelZ=new _3.drawing.annotations.Label(_2.mixin(_8,{labelPosition:this.setLabelZ}));
+}
+},setLabelX:function(){
+var ax=this.points[0];
+var c=this.points[1];
+var _9=40;
+var _a=20;
+var pt,px,py,_b;
+pt=this.util.lineSub(c.x,c.y,ax.x,ax.y,_9);
+px=pt.x+(pt.y-ax.y);
+py=pt.y+(ax.x-pt.x);
+_b=this.util.lineSub(pt.x,pt.y,px,py,(_9-_a));
+return {x:_b.x,y:_b.y,width:20};
+},setLabelY:function(){
+var c=this.points[1];
+var ay=this.points[2];
+var _c=40;
+var _d=20;
+var pt,px,py,_e;
+pt=this.util.lineSub(c.x,c.y,ay.x,ay.y,_c);
+px=pt.x+(ay.y-pt.y);
+py=pt.y+(pt.x-ay.x);
+_e=this.util.lineSub(pt.x,pt.y,px,py,(_c-_d));
+return {x:_e.x,y:_e.y,width:20};
+},setLabelZ:function(){
+var c=this.points[1];
+var z=this.points[3];
+var _f=40;
+var _10=20;
+var pt,px,py,pt2;
+pt=this.util.lineSub(c.x,c.y,z.x,z.y,_f);
+px=pt.x+(pt.y-z.y);
+py=pt.y+(z.x-pt.x);
+pt2=this.util.lineSub(pt.x,pt.y,px,py,(_f-_10));
+return {x:pt2.x,y:pt2.y,width:20};
+},setLabel:function(_11){
+if(this._labelsCreated){
+return;
+}
+!this.labelX&&this.createLabels();
+var x="x";
+var y="y";
+var z="z";
+if(_11){
+if(this.labelZ){
+var _12=_11.match(/(.*?)(and|&)(.*?)(and|&)(.*)/i);
+if(_12.length>4){
+x=_12[1].replace(/^\s+/,"").replace(/\s+$/,"");
+y=_12[3].replace(/^\s+/,"").replace(/\s+$/,"");
+z=_12[5].replace(/^\s+/,"").replace(/\s+$/,"");
+}
+}else{
+var _12=_11.match(/(.*?)(and|&)(.*)/i);
+if(_12.length>2){
+x=_12[1].replace(/^\s+/,"").replace(/\s+$/,"");
+y=_12[3].replace(/^\s+/,"").replace(/\s+$/,"");
+}
+}
+}
+this.labelX.setLabel(x);
+this.labelY.setLabel(y);
+if(this.labelZ){
+this.labelZ.setLabel(z);
+}
+this._labelsCreated=true;
+},getLabel:function(){
+if(!this.labelX){
+return null;
+}
+return {x:this.labelX.getText(),y:this.labelY.getText(),z:this.labelZ?this.labelZ.getText():null};
+},anchorPositionCheck:function(x,y,_13){
+var pm=this.container.getParent().getTransform();
+var am=_13.shape.getTransform();
+var p=this.points;
+var o={x:am.dx+_13.org.x+pm.dx,y:am.dy+_13.org.y+pm.dy};
+var c={x:p[1].x+pm.dx,y:p[1].y+pm.dy};
+var ox=c.x-(c.y-o.y);
+var oy=c.y-(o.x-c.x);
+return {x:ox,y:oy};
+},onTransformBegin:function(_14){
+this._isBeingModified=true;
+},onTransformEnd:function(_15){
+if(!_15){
+return;
+}
+this._isBeingModified=false;
+this._toggleSelected();
+var o=this.points[0];
+var c=this.points[1];
+var obj={start:{x:c.x,y:c.y},x:o.x,y:o.y};
+var pt=this.util.constrainAngle(obj,0,89);
+var zpt=this.style.zAxisEnabled?this.zPoint(obj):null;
+if(pt.x==o.x&&pt.y==o.y){
+pt=this.util.snapAngle(obj,this.angleSnap/180);
+obj.x=pt.x;
+obj.y=pt.y;
+var ox=obj.start.x-(obj.start.y-obj.y);
+var oy=obj.start.y-(obj.x-obj.start.x);
+if(ox<0||oy<0){
+console.warn("AXES ERROR LESS THAN ZERO - ABORT");
+return;
+}
+this.points=[{x:obj.x,y:obj.y},{x:obj.start.x,y:obj.start.y,noAnchor:true}];
+this.points.push({x:ox,y:oy,noAnchor:true});
+if(zpt){
+this.points.push(zpt);
+}
+this.setPoints(this.points);
+this.onModify(this);
+return;
+}
+this.points[0].x=pt.x;
+this.points[0].y=pt.y;
+o=this.points[0];
+var ox=c.x-(c.y-o.y);
+var oy=c.y-(o.x-c.x);
+this.points[2]={x:ox,y:oy,noAnchor:true};
+if(zpt){
+this.points.push(zpt);
+}
+this.setPoints(this.points);
+this.labelX.setLabel();
+this.labelY.setLabel();
+if(this.labelZ){
+this.labelZ.setLabel();
+}
+this.onModify(this);
+},getBounds:function(_16){
+var px=this.points[0],pc=this.points[1],py=this.points[2];
+if(this.style.zAxisEnabled){
+var pz=this.points[3];
+}
+if(_16){
+var _17={x:pc.x,y:pc.y,x1:pc.x,y1:pc.y,x2:px.x,y2:px.y,x3:py.x,y3:py.y};
+if(this.style.zAxisEnabled){
+_17.x4=pz.x;
+_17.y4=pz.y;
+}
+return _17;
+}
+var x1=this.style.zAxisEnabled?(py.x>built
+// wrapped by build app
+define("dojox/drawing/tools/custom/Axes", ["dijit","dojo","dojox","dojo/require!dojox/drawing/stencil/Path"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.custom.Axes");
+dojo.require("dojox.drawing.stencil.Path");
+
+
+dojox.drawing.tools.custom.Axes = dojox.drawing.util.oo.declare(
+ // summary:
+ // Draws a right-angle Axes (shaped like an L, not a +)
+ // description:
+ // This Stencil is created with a Path so that the L shape
+ // is one continuous piece. Arrow heads are placed at the end
+ // of each axis. The Axes can be rotated. There are custom
+ // label methods.
+ //
+ dojox.drawing.stencil.Path,
+ function(options){
+ this.closePath = false;
+
+ this.xArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:0, idx2:1});
+ this.yArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:2, idx2:1});
+ if(options.data){
+ //Allows import of z-axis in non-enabled canvas and xy-axis in
+ //enabled canvas
+ this.style.zAxisEnabled = options.data.cosphi == 1 ? true : false;
+ this.setData(options.data);
+ }
+ if(this.style.zAxisEnabled){
+ // If the z-axis is enabled, all axes will be created with a z-axis on the canvas.
+ // there is no switching back and forth for the axis, only for vectors.
+ this.data.cosphi = 1;
+ var ops = {};
+ dojo.mixin(ops,options);
+ dojo.mixin(ops,{
+ container:this.container.createGroup(),
+ style: this.style,
+ showAngle: false,
+ label: null
+ });
+ if(options.data && (!ops.data.radius || !ops.data.angle)){
+ ops.data.x2 = ops.data.x4;
+ ops.data.y2 = ops.data.y4;
+ }
+ ops.style.zAxis = true;
+ this.zAxis = new dojox.drawing.tools.custom.Vector(ops);
+ this.zAxis.minimumSize = 5;
+ //console.log("-----constructing axes: ",this.zAxis);
+ this.connectMult([
+ [this, "onChangeStyle", this.zAxis, "onChangeStyle"],
+ [this, "select", this.zAxis, "select"],
+ [this, "deselect", this.zAxis, "deselect"],
+ [this, "onDelete", this.zAxis, "destroy"],
+ [this, "onDrag", this, "zSet"],
+ [this, "onTransform", this, "zSet"],
+ [this.zAxis, "onBeforeRender", this, "zSet"],
+ [this, "_onPostRender", this.zAxis, "render"]
+ ]);
+
+ }
+
+ if(this.points && this.points.length){
+ this.setPoints = this._postSetPoints;
+ // render isn't called yet because baseRender is false
+ // instead it is called here
+ this.render();
+ options.label && this.setLabel(options.label);
+ options.shadow && this.addShadow(options.shadow);
+ }
+ },
+ {
+ draws:true,
+ type:"dojox.drawing.tools.custom.Axes",
+ minimumSize:30,
+ showAngle:true,
+ closePath:false,
+ baseRender:false,
+ zScale:.5,
+
+ zPoint: function(obj){
+ // summary:
+ // Finds the point for the z axis.
+ obj.radius = this.util.length(obj);
+ var pt = this.util.pointOnCircle(obj.start.x, obj.start.y, obj.radius*this.zScale, this.style.zAngle);
+ return {x:pt.x, y:pt.y, skip:true, noAnchor:true};
+ },
+
+ zSet: function(){
+ if(!this.zAxis){ return; };
+ var c = this.points[1];
+ var z = this.points[3];
+ var p = [
+ {x:c.x, y:c.y},
+ {x:z.x, y:z.y}
+ ];
+ var len = this.util.length({start:{x:c.x, y:c.y}, x:z.x, y:z.y});
+ len > this.zAxis.minimumSize ? this.zAxis.setPoints(p) : false;
+ this.zAxis.cosphi = 1;
+ },
+
+ createLabels: function(){
+ // summary:
+ // Creates the label for each axis.
+ //
+ // NOTE: Not passing style into text because it's changing it
+ var props = {align:"middle", valign:"middle", util:this.util, annotation:true, container:this.container, mouse:this.mouse, stencil:this};
+ this.labelX = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+ labelPosition:this.setLabelX
+ }));
+ this.labelY = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+ labelPosition:this.setLabelY
+ }));
+ if(this.style.zAxisEnabled){
+ this.labelZ = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+ labelPosition:this.setLabelZ
+ }));
+ }
+
+ },
+
+ setLabelX: function(){
+ // summary:
+ // Custom placement for x-axis label
+ //
+ var ax = this.points[0];
+ var c = this.points[1];
+
+ var dist = 40;
+ var offdist = 20;
+ var pt, px, py, pt2;
+
+ pt = this.util.lineSub(c.x, c.y, ax.x, ax.y, dist);
+ px = pt.x + (pt.y -ax.y);
+ py = pt.y + (ax.x - pt.x);
+ pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+
+ return {
+ x: pt2.x,
+ y: pt2.y,
+ width:20
+ };
+ },
+ setLabelY: function(){
+ // summary:
+ // Custom placement for y-axis label
+ //
+ var c = this.points[1];
+ var ay = this.points[2];
+
+ var dist = 40;
+ var offdist = 20;
+ var pt, px, py, pt2;
+ pt = this.util.lineSub(c.x, c.y, ay.x, ay.y, dist);
+ px = pt.x + (ay.y - pt.y);
+ py = pt.y + (pt.x - ay.x);
+ pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+ return {
+ x: pt2.x,
+ y: pt2.y,
+ width:20
+ };
+ },
+ setLabelZ: function(){
+ // summary:
+ // Custom placement for z-axis label
+ //
+ var c = this.points[1];
+ var z = this.points[3];
+
+ var dist = 40;
+ var offdist = 20;
+ var pt, px, py, pt2;
+ pt = this.util.lineSub(c.x, c.y, z.x, z.y, dist);
+ px = pt.x + (pt.y - z.y);
+ py = pt.y + (z.x - pt.x);
+ pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+
+ return {
+ x:pt2.x,
+ y:pt2.y,
+ width:20
+ }
+ },
+ setLabel: function(/* ? String*/value){
+ // summary:
+ // Set the text of the labels. The text would be
+ // broken up into the two labels.
+ // arguments:
+ // value: [optional] String
+ // If no argument is passed, defaults to two labels
+ // 'x' and 'y'. If an argument is passed, that
+ // text will be split on the word 'and' to determine
+ // the two labels.
+ //
+ if(this._labelsCreated){ return; }
+ !this.labelX && this.createLabels();
+ var x = "x";
+ var y = "y";
+ var z = "z";
+ if(value){
+ // match first "and" or "&" and trim whitespace.
+ // Non-greedy matches are not supported in older
+ // browsers such as Netscape Navigator 4 or
+ // Microsoft Internet Explorer 5.0.
+ if(this.labelZ){
+ var lbls = value.match(/(.*?)(and|&)(.*?)(and|&)(.*)/i);
+ if(lbls.length>4){
+ x = lbls[1].replace(/^\s+/,"").replace(/\s+$/,"");
+ y = lbls[3].replace(/^\s+/,"").replace(/\s+$/,"");
+ z = lbls[5].replace(/^\s+/,"").replace(/\s+$/,"");
+ }
+ }else{
+ var lbls = value.match(/(.*?)(and|&)(.*)/i);
+ if(lbls.length>2){
+ x = lbls[1].replace(/^\s+/,"").replace(/\s+$/,"");
+ y = lbls[3].replace(/^\s+/,"").replace(/\s+$/,"");
+ }
+ }
+ }
+ this.labelX.setLabel(x);
+ this.labelY.setLabel(y);
+ if(this.labelZ){
+ this.labelZ.setLabel(z);
+ }
+ this._labelsCreated = true;
+ },
+ getLabel: function(){
+ // summary:
+ // Getter for the labels. returns an object.
+ //
+ if(!this.labelX){ return null; }
+ return {
+ x:this.labelX.getText(),
+ y:this.labelY.getText(),
+ z:this.labelZ?this.labelZ.getText():null
+ }; // Object
+ },
+
+ anchorPositionCheck: function(/*Number*/x, /*Number*/y, /*manager.Anchor*/anchor){
+ // summary:
+ // Gets called from anchor to check if its current
+ // position is ok. If not, its x or y transform will
+ // be changed until this passes.
+ //
+ var pm = this.container.getParent().getTransform();
+ var am = anchor.shape.getTransform();
+
+ // the xaxis point has changed and is not yet set as a point
+ // - but the center should be good (except for the transform).
+ // Now check the yaxis point.
+
+ var p = this.points;
+ var o = {x:am.dx+anchor.org.x+pm.dx, y:am.dy+anchor.org.y+pm.dy};
+ var c = {x:p[1].x+pm.dx, y:p[1].y+pm.dy};
+ var ox = c.x - (c.y - o.y);
+ var oy = c.y - (o.x - c.x);
+
+ return {x:ox, y:oy};
+
+ },
+
+ onTransformBegin: function(/*manager.Anchor*/anchor){
+ // summary:
+ // Overwrites _Base.onTransformBegin
+ //
+ // called from anchor point up mouse down
+ this._isBeingModified = true;
+ },
+
+ onTransformEnd: function(/*manager.Anchor*/anchor){
+ // summary:
+ // Overwrites _Base.onTransformEnd
+ //
+ // Gets called on anchor mouseup
+ // also gets called by checkBounds - we don't want that.
+ if(!anchor){ return; }
+
+ // tell anchor to go to prev point if wrong
+ // called from anchor point up mouse up
+
+ this._isBeingModified = false;
+ //this.deselect();
+ this._toggleSelected();
+ console.log("before:", Math.ceil(this.points[1].x), " x ", Math.ceil(this.points[1].y))
+
+ var o = this.points[0];
+ var c = this.points[1];
+ var obj = {start:{x:c.x,y:c.y},x:o.x, y:o.y};
+ var pt = this.util.constrainAngle(obj, 0, 89);
+ var zpt = this.style.zAxisEnabled ? this.zPoint(obj) : null;
+
+ if(pt.x==o.x && pt.y == o.y){
+ // we're within the constraint, so now we snap
+ pt = this.util.snapAngle(obj, this.angleSnap/180);
+
+ obj.x = pt.x;
+ obj.y = pt.y;
+ var ox = obj.start.x - (obj.start.y - obj.y);
+ var oy = obj.start.y - (obj.x - obj.start.x);
+
+ if(ox<0 || oy<0){
+ console.warn("AXES ERROR LESS THAN ZERO - ABORT");
+ return;
+ }
+ this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+ this.points.push({x:ox, y:oy, noAnchor:true});
+ if(zpt){ this.points.push(zpt);}
+ this.setPoints(this.points);
+
+ //this.select();
+ this.onModify(this);
+ return;
+ }
+
+ // we're outside of the constraint. Set to the low or high.
+ this.points[0].x = pt.x
+ this.points[0].y = pt.y;
+ o = this.points[0];
+
+ var ox = c.x - (c.y - o.y);
+ var oy = c.y - (o.x - c.x);
+
+ this.points[2] = {x:ox, y:oy, noAnchor:true};
+ if(zpt){ this.points.push(zpt); }
+ this.setPoints(this.points);
+
+ // reset handles render
+ //anchor.reset(this);
+
+ this.labelX.setLabel();
+ this.labelY.setLabel();
+ if(this.labelZ){
+ this.labelZ.setLabel();
+ }
+
+ //this.select();
+ this.onModify(this);
+
+ },
+
+ getBounds: function(/*Boolean*/absolute){
+ // summary:
+ // Custom getBounds overwrites _Base.getBounds
+ //
+ var px = this.points[0],
+ pc = this.points[1],
+ py = this.points[2];
+ if(this.style.zAxisEnabled){ var pz = this.points[3]; }
+
+ if(absolute){
+ var bounds = {
+ x:pc.x,
+ y:pc.y,
+ x1:pc.x,
+ y1:pc.y,
+ x2:px.x,
+ y2:px.y,
+ x3:py.x,
+ y3:py.y
+ };
+ if(this.style.zAxisEnabled){
+ bounds.x4 = pz.x;
+ bounds.y4 = pz.y;
+ }
+ return bounds;
+ }
+
+ var x1 = this.style.zAxisEnabled ? (py.x < pz.x ? py.x : pz.x) : py.x;
+ y1 = py.y < px.y ? py.y : px.y,
+ x2 = px.x,
+ y2 = this.style.zAxisEnabled ? pz.y : pc.y;
+
+ return {
+ x1:x1,
+ y1:y1,
+ x2:x2,
+ y2:y2,
+ x:x1,
+ y:y1,
+ w:x2-x1,
+ h:y2-y1
+ };
+ },
+
+ _postSetPoints: function(/*Array*/pts){
+ // summary:
+ // Because Axes only has one anchor,
+ // we substitute a special setPoints method
+ //
+ this.points[0] = pts[0];
+ if(this.pointsToData){
+ this.data = this.pointsToData();
+ }
+ },
+
+ onTransform: function(/*Number*/anchor){
+ // summary:
+ // Overwrites _Base.onTransform
+ //
+ // the xaxis point has changed - the center will not.
+ // need to find the yaxis point.
+ var o = this.points[0];
+ var c = this.points[1];
+ var ox = c.x - (c.y - o.y);
+ var oy = c.y - (o.x - c.x);
+
+ // 'noAnchor' on a point indicates an anchor should
+ // not be rendered. This is the Y point being set.
+ this.points[2] = {x:ox, y:oy, noAnchor:true};
+ if(this.style.zAxisEnabled){
+ this.points[3] = this.zPoint({start:{x:c.x, y:c.y}, x:o.x, y:o.y});
+ }
+ this.setPoints(this.points);
+ if(!this._isBeingModified){
+ this.onTransformBegin();
+ }
+ this.render();
+ },
+
+ pointsToData: function(){
+ //summary:
+ // Converts points to data.
+ var p = this.points;
+ var d = {
+ x1:p[1].x,
+ y1:p[1].y,
+ x2:p[0].x,
+ y2:p[0].y,
+ x3:p[2].x,
+ y3:p[2].y
+ }
+ if(this.style.zAxisEnabled){
+ d.x4 = p[3].x;
+ d.y4 = p[3].y;
+ d.cosphi = 1;
+ }
+ return d;
+
+ },
+
+ getRadius: function(){
+ //summary:
+ // Possibility of z-axis makes bounds unreliable.
+ // Use these points instead.
+ var p = this.points;
+ var line = {start:{x:p[1].x, y:p[1].y}, x:p[0].x, y:p[0].y};
+ return this.util.length(line);
+ },
+
+ dataToPoints: function(/* ? Object*/o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ if(o.radius || o.angle){
+ // instead of using x1,x2,y1,y1,
+ // it's been set as x,y,angle,radius
+ var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle), zpt;
+ var ox = o.x - (o.y - pt.y);
+ var oy = o.y - (pt.x - o.x);
+ if((o.cosphi && o.cosphi==1) || this.style.zAxisEnabled){
+ this.style.zAxisEnabled = true;
+ zpt = this.util.pointOnCircle(o.x, o.y, o.radius*this.zScale, this.style.zAngle);
+ }
+ this.data = o = {
+ x1:o.x,
+ y1:o.y,
+ x2:pt.x,
+ y2:pt.y,
+ x3:ox,
+ y3:oy
+ }
+ if(this.style.zAxisEnabled){
+ this.data.x4 = o.x4 = zpt.x;
+ this.data.y4 = o.y4 = zpt.y;
+ this.data.cosphi = 1;
+ }
+
+ }
+ this.points = [
+ {x:o.x2, y:o.y2},
+ {x:o.x1, y:o.y1, noAnchor:true},
+ {x:o.x3, y:o.y3, noAnchor:true}
+ ];
+ if(this.style.zAxisEnabled){ this.points.push({x:o.x4, y:o.y4, skip:true, noAnchor:true}); }
+ return this.points;
+ },
+
+ onDrag: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDrag
+ //
+ var pt = this.util.constrainAngle(obj, 0, 89);
+ obj.x = pt.x;
+ obj.y = pt.y;
+ var ox = obj.start.x - (obj.start.y - obj.y);
+ var oy = obj.start.y - (obj.x - obj.start.x);
+
+ if(ox<0 || oy<0){
+ return;
+ }
+ this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+
+ this.points.push({x:ox, y:oy, noAnchor:true});
+ if(this.style.zAxisEnabled){
+ var zpt = this.zPoint(obj);
+ this.points.push(zpt);
+ }
+ this.render();
+ },
+
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(!this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+ var p = this.points;
+ if(!p.length){
+ var s = obj.start, d = 100;
+ this.points = [
+ {x:s.x+d, y:s.y+d},
+ {x:s.x, y:s.y+d, noAnchor:true},
+ {x:s.x, y:s.y, noAnchor:true}
+ ];
+ if(this.style.zAxisEnabled){
+ var zpt = this.zPoint({start:{x:s.x, y:s.y+d}, x:s.x+d, y:s.y+d});
+ this.points.push(zpt);
+ }
+ this.setPoints = this._postSetPoints;
+ this.pointsToData();
+ this.render();
+ this.onRender(this);
+ return;
+ }
+
+ var len = this.util.distance(p[1].x ,p[1].y ,p[0].x ,p[0].y );
+ if(!p || !p.length){
+ return;
+ }else if(len < this.minimumSize){
+ this.remove(this.shape, this.hit);
+ this.xArrow.remove(this.xArrow.shape, this.xArrow.hit);
+ this.yArrow.remove(this.yArrow.shape, this.yArrow.hit);
+ if(this.zArrow){
+ this.zArrow.remove(this.zArrow.shape, this.zArrow.hit);
+ }
+ return;
+ }
+
+ var o = p[0];
+ var c = p[1];
+ obj = {start:{x:c.x,y:c.y},x:o.x,y:o.y};
+ var pt = this.util.snapAngle(obj, this.angleSnap/180);
+ obj.x = pt.x;
+ obj.y = pt.y;
+ var ox = obj.start.x - (obj.start.y - obj.y);
+ var oy = obj.start.y - (obj.x - obj.start.x);
+
+ if(ox<0 || oy<0){
+ return;
+ }
+ this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+
+ this.points.push({x:ox, y:oy, noAnchor:true});
+ if(this.style.zAxisEnabled){ this.points.push(this.zPoint(obj)); }
+ this.onRender(this);
+ this.setPoints = this._postSetPoints;
+ }
+ }
+);
+
+dojox.drawing.tools.custom.Axes.setup = {
+ // summary: See stencil._Base ToolsSetup
+ //
+ name:"dojox.drawing.tools.custom.Axes",
+ tooltip:"Axes Tool",
+ iconClass:"iconAxes"
+};
+dojox.drawing.register(dojox.drawing.tools.custom.Axes.setup, "tool");
+});
diff --git a/js/libs/dojox/drawing/tools/custom/Equation.js b/js/libs/dojox/drawing/tools/custom/Equation.js
new file mode 100644
index 0000000..248bd6e
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/custom/Equation.js
@@ -0,0 +1,9 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/TextBlock"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.custom.Equation");
+_2.require("dojox.drawing.tools.TextBlock");
+_3.drawing.tools.custom.Equation=_3.drawing.util.oo.declare(_3.drawing.tools.TextBlock,function(_4){
+},{customType:"equation"});
+_3.drawing.tools.custom.Equation.setup={name:"dojox.drawing.tools.custom.Equation",tooltip:"Equation Tool",iconClass:"iconEq"};
+_3.drawing.register(_3.drawing.tools.custom.Equation.setup,"tool");
+});
diff --git a/js/libs/dojox/drawing/tools/custom/Equation.js.uncompressed.js b/js/libs/dojox/drawing/tools/custom/Equation.js.uncompressed.js
new file mode 100644
index 0000000..b9b5f40
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/custom/Equation.js.uncompressed.js
@@ -0,0 +1,30 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/tools/custom/Equation", ["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/TextBlock"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.custom.Equation");
+dojo.require("dojox.drawing.tools.TextBlock");
+
+dojox.drawing.tools.custom.Equation = dojox.drawing.util.oo.declare(
+ // summary:
+ // Essentially the same as the TextBlock tool, but
+ // allows for a different icon and tooltip title.
+ //
+ dojox.drawing.tools.TextBlock,
+ function(options){
+
+ },
+ {
+ customType:"equation"
+ }
+
+);
+
+dojox.drawing.tools.custom.Equation.setup = {
+ // summary: See stencil._Base ToolsSetup
+ //
+ name:"dojox.drawing.tools.custom.Equation",
+ tooltip:"Equation Tool",
+ iconClass:"iconEq"
+};
+dojox.drawing.register(dojox.drawing.tools.custom.Equation.setup, "tool");
+});
diff --git a/js/libs/dojox/drawing/tools/custom/Vector.js b/js/libs/dojox/drawing/tools/custom/Vector.js
new file mode 100644
index 0000000..34407f4
--- /dev/null
+++ b/js/libs/dojox/drawing/tools/custom/Vector.js
@@ -0,0 +1,221 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/Arrow,dojox/drawing/util/positioning"],function(_1,_2,_3){
+_2.provide("dojox.drawing.tools.custom.Vector");
+_2.require("dojox.drawing.tools.Arrow");
+_2.require("dojox.drawing.util.positioning");
+_3.drawing.tools.custom.Vector=_3.drawing.util.oo.declare(_3.drawing.tools.Arrow,function(_4){
+this.minimumSize=this.style.arrows.length;
+this.addShadow({size:3,mult:2});
+},{draws:true,type:"dojox.drawing.tools.custom.Vector",minimumSize:30,showAngle:true,changeAxis:function(_5){
+_5=_5!==undefined?_5:this.style.zAxis?0:1;
+if(_5==0){
+this.style.zAxis=false;
+this.data.cosphi=0;
+}else{
+this.style.zAxis=true;
+var p=this.points;
+var pt=this.zPoint();
+this.setPoints([{x:p[0].x,y:p[0].y},{x:pt.x,y:pt.y}]);
+}
+this.render();
+},_createZeroVector:function(_6,d,_7){
+var s=_6=="hit"?this.minimumSize:this.minimumSize/6;
+var f=_6=="hit"?_7.fill:null;
+d={cx:this.data.x1,cy:this.data.y1,rx:s,ry:s};
+this.remove(this[_6]);
+this[_6]=this.container.createEllipse(d).setStroke(_7).setFill(f);
+this.util.attr(this[_6],"drawingType","stencil");
+},_create:function(_8,d,_9){
+this.remove(this[_8]);
+this[_8]=this.container.createLine(d).setStroke(_9);
+this._setNodeAtts(this[_8]);
+},onDrag:function(_a){
+if(this.created){
+return;
+}
+var x1=_a.start.x,y1=_a.start.y,x2=_a.x,y2=_a.y;
+if(this.keys.shift&&!this.style.zAxis){
+var pt=this.util.snapAngle(_a,45/180);
+x2=pt.x;
+y2=pt.y;
+}
+if(this.keys.alt){
+var dx=x2>x1?((x2-x1)/2):((x1-x2)/-2);
+var dy=y2>y1?((y2-y1)/2):((y1-y2)/-2);
+x1-=dx;
+x2-=dx;
+y1-=dy;
+y2-=dy;
+}
+if(this.style.zAxis){
+var _b=this.zPoint(_a);
+x2=_b.x;
+y2=_b.y;
+}
+this.setPoints([{x:x1,y:y1},{x:x2,y:y2}]);
+this.render();
+},onTransform:function(_c){
+if(!this._isBeingModified){
+this.onTransformBegin();
+}
+this.setPoints(this.points);
+this.render();
+},anchorConstrain:function(x,y){
+if(!this.style.zAxis){
+return null;
+}
+var _d=this.style.zAngle*Math.PI/180;
+var _e=x<0?x>-y:x<-y;
+var dx=_e?x:-y/Math.tan(_d);
+var dy=!_e?y:-Math.tan(_d)*x;
+return {x:dx,y:dy};
+},zPoint:function(_f){
+if(_f===undefined){
+if(!this.points[0]){
+return null;
+}
+var d=this.pointsToData();
+_f={start:{x:d.x1,y:d.y1},x:d.x2,y:d.y2};
+}
+var _10=this.util.length(_f);
+var _11=this.util.angle(_f);
+_11<0?_11=360+_11:_11;
+_11=_11>135&&_11<315?this.style.zAngle:this.util.oppAngle(this.style.zAngle);
+return this.util.pointOnCircle(_f.start.x,_f.start.y,_10,_11);
+},pointsToData:function(p){
+p=p||this.points;
+var _12=0;
+var obj={start:{x:p[0].x,y:p[0].y},x:p[1].x,y:p[1].y};
+if(this.style.zAxis&&(this.util.length(obj)>this.minimumSize)){
+var _13=this.util.angle(obj);
+_13<0?_13=360+_13:_13;
+_12=_13>135&&_13<315?1:-1;
+}
+this.data={x1:p[0].x,y1:p[0].y,x2:p[1].x,y2:p[1].y,cosphi:_12};
+return this.data;
+},dataToPoints:function(o){
+o=o||this.data;
+if(o.radius||o.angle){
+var _14=0;
+var pt=this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+if(this.style.zAxis||(o.cosphi&&o.cosphi!=0)){
+this.style.zAxis=true;
+_14=o.angle>135&&o.angle<315?1:-1;
+}
+this.data=o={x1:o.x,y1:o.y,x2:pt.x,y2:pt.y,cosphi:_14};
+}
+this.points=[{x:o.x1,y:o.y1},{x:o.x2,y:o.y2}];
+return this.points;
+},render:function(){
+this.onBeforeRender(this);
+if(this.getRadius()>=this.minimumSize){
+this._create("hit",this.data,this.style.currentHit);
+this._create("shape",this.data,this.style.current);
+}else{
+this.data.cosphi=0;
+this._createZeroVector("hit",this.data,this.style.currentHit);
+this._createZeroVector("shape",this.data,this.style.current);
+}
+},onUp:function(obj){
+if(this.created||!this._downOnCanvas){
+return;
+}
+this._downOnCanvas=false;
+if(!this.shape){
+var d=100;
+obj.start.x=this.style.zAxis?obj.start.x+d:obj.start.x;
+obj.y=obj.y+d;
+this.setPoints([{x:obj.start.x,y:obj.start.y},{x:obj.x,y:obj.y}]);
+this.render();
+}
+if(this.getRadius()>built
+// wrapped by build app
+define("dojox/drawing/tools/custom/Vector", ["dijit","dojo","dojox","dojo/require!dojox/drawing/tools/Arrow,dojox/drawing/util/positioning"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.tools.custom.Vector");
+dojo.require("dojox.drawing.tools.Arrow");
+dojo.require("dojox.drawing.util.positioning");
+
+dojox.drawing.tools.custom.Vector = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a Vector Stencil.
+ // description:
+ // Generally the same as an arrow, except that the arrow
+ // head is only at the end. There is additionaly functionality
+ // to allow for a 'zero vector' - one with no length.
+ //
+ //
+ dojox.drawing.tools.Arrow,
+ function(options){
+ this.minimumSize = this.style.arrows.length;
+ this.addShadow({size:3, mult:2});
+ },
+ {
+ draws:true,
+ type:"dojox.drawing.tools.custom.Vector",
+ minimumSize:30,
+ showAngle:true,
+
+
+
+ changeAxis: function(cosphi){
+ // summary:
+ // Converts a vector to and from the z axis.
+ // If passed a cosphi value that is used to set
+ // the axis, otherwise it is the opp of what it is.
+ cosphi = cosphi!==undefined?cosphi:this.style.zAxis? 0 : 1;
+ if(cosphi == 0){
+ this.style.zAxis = false;
+ this.data.cosphi = 0;
+ }else{
+ this.style.zAxis = true;
+ var p = this.points;
+ var pt = this.zPoint();
+ this.setPoints([
+ {x:p[0].x, y:p[0].y},
+ {x:pt.x, y:pt.y}
+ ]);
+ }
+ this.render();
+ },
+
+ _createZeroVector: function(shp, d, sty){
+ // summary:
+ // Special creation function for the zero-vector shape
+ //
+ var s = shp=="hit" ? this.minimumSize : this.minimumSize/6;
+ var f = shp=="hit" ? sty.fill : null;
+ d = {
+ cx:this.data.x1,
+ cy:this.data.y1,
+ rx:s,
+ ry:s
+ };
+
+ this.remove(this[shp]);
+ this[shp] = this.container.createEllipse(d)
+ .setStroke(sty)
+ .setFill(f);
+ this.util.attr(this[shp], "drawingType", "stencil");
+ },
+
+ _create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+ // summary:
+ // Creates a dojox.gfx.shape based on passed arguments.
+ // Can be called many times by implementation to create
+ // multiple shapes in one stencil.
+ //
+ this.remove(this[shp]);
+ this[shp] = this.container.createLine(d)
+ .setStroke(sty);
+ this._setNodeAtts(this[shp]);
+ },
+
+ onDrag: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onDrag
+ //
+ if(this.created){ return; }
+
+ var x1 = obj.start.x,
+ y1 = obj.start.y,
+ x2 = obj.x,
+ y2 = obj.y;
+
+ if(this.keys.shift && !this.style.zAxis){
+ var pt = this.util.snapAngle(obj, 45/180);
+ x2 = pt.x;
+ y2 = pt.y;
+ }
+
+ if(this.keys.alt){
+ // FIXME:
+ // should double the length of the line
+ // FIXME:
+ // if alt dragging past ZERO it seems to work
+ // but select/deselect shows bugs
+ var dx = x2>x1 ? ((x2-x1)/2) : ((x1-x2)/-2);
+ var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2);
+ x1 -= dx;
+ x2 -= dx;
+ y1 -= dy;
+ y2 -= dy;
+ }
+
+ if(this.style.zAxis){
+ var pts = this.zPoint(obj);
+ x2 = pts.x;
+ y2 = pts.y;
+ }
+
+ this.setPoints([
+ {x:x1, y:y1},
+ {x:x2, y:y2}
+ ]);
+ this.render();
+ },
+
+ onTransform: function(/* ? manager.Anchor */anchor){
+ // summary:
+ // Called from anchor point mouse drag
+ // also called from plugins.Pan.checkBounds
+ if(!this._isBeingModified){
+ this.onTransformBegin();
+ }
+ // this is not needed for anchor moves, but it
+ // is for stencil move:
+
+ this.setPoints(this.points);
+ this.render();
+ },
+
+ anchorConstrain: function(x, y){
+ // summary:
+ // Called from anchor point mouse drag
+ if(!this.style.zAxis){ return null; }
+ var radians = this.style.zAngle*Math.PI/180;
+ //Constrain to angle
+ var test = x<0 ? x>-y : x<-y;
+ var dx = test ? x : -y/Math.tan(radians);
+ var dy = !test ? y : -Math.tan(radians)*x;
+ return {x:dx, y:dy}
+ },
+
+ zPoint: function(obj){
+ // summary:
+ // Takes any point and converts it to
+ // be on the z-axis.
+ if(obj===undefined){
+ if(!this.points[0]){ return null; };
+ var d = this.pointsToData();
+ obj = {
+ start:{
+ x:d.x1,
+ y:d.y1
+ },
+ x:d.x2,
+ y:d.y2
+ };
+ }
+ var radius = this.util.length(obj);
+ var angle = this.util.angle(obj);
+ angle<0 ? angle = 360 + angle : angle;
+
+ angle = angle > 135 && angle < 315 ? this.style.zAngle : this.util.oppAngle(this.style.zAngle);
+
+ return this.util.pointOnCircle(obj.start.x, obj.start.y, radius, angle);
+ },
+
+ pointsToData: function(p){
+ // summary:
+ // Converts points to data
+ p = p || this.points;
+ var cosphi = 0;
+ var obj = {start:{x:p[0].x, y:p[0].y}, x:p[1].x, y:p[1].y};
+ if(this.style.zAxis && (this.util.length(obj)>this.minimumSize)){
+
+ var angle = this.util.angle(obj);
+ angle<0 ? angle = 360 + angle : angle;
+ cosphi = angle > 135 && angle < 315 ? 1 : -1;
+ }
+ this.data = {
+ x1: p[0].x,
+ y1: p[0].y,
+ x2: p[1].x,
+ y2: p[1].y,
+ cosphi: cosphi
+ };
+ return this.data;
+ },
+
+ dataToPoints: function(o){
+ //summary:
+ // Converts data to points.
+ o = o || this.data;
+ if(o.radius || o.angle){
+ // instead of using x1,x2,y1,y1,
+ // it's been set as x,y,angle,radius
+ var cosphi = 0;
+ var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+ if(this.style.zAxis || (o.cosphi && o.cosphi!=0)){
+ this.style.zAxis = true;
+ cosphi = o.angle > 135 && o.angle < 315 ? 1 : -1;
+ }
+ //console.log(" ---- pts:", pt.x, pt.y);
+ this.data = o = {
+ x1:o.x,
+ y1:o.y,
+ x2:pt.x,
+ y2:pt.y,
+ cosphi:cosphi
+ }
+
+ }
+ this.points = [
+ {x:o.x1, y:o.y1},
+ {x:o.x2, y:o.y2}
+ ];
+ return this.points;
+ },
+
+ render: function(){
+ // summary:
+ // Renders the 'hit' object (the shape used for an expanded
+ // hit area and for highlighting) and the'shape' (the actual
+ // display object). Additionally checks if Vector should be
+ // drawn as an arrow or a circle (zero-length)
+ //
+ this.onBeforeRender(this);
+ if(this.getRadius() >= this.minimumSize){
+ this._create("hit", this.data, this.style.currentHit);
+ this._create("shape", this.data, this.style.current);
+
+ }else{
+ this.data.cosphi = 0;
+ this._createZeroVector("hit", this.data, this.style.currentHit);
+ this._createZeroVector("shape", this.data, this.style.current);
+ }
+ },
+ onUp: function(/*EventObject*/obj){
+ // summary: See stencil._Base.onUp
+ //
+ if(this.created || !this._downOnCanvas){ return; }
+ this._downOnCanvas = false;
+ //Default vector for single click
+ if(!this.shape){
+ var d = 100;
+ obj.start.x = this.style.zAxis ? obj.start.x + d : obj.start.x;
+ obj.y = obj.y+d;
+ this.setPoints([
+ {x:obj.start.x, y:obj.start.y},
+ {x:obj.x, y:obj.y}
+ ]);
+ this.render();
+ }
+
+ // When within minimum size this sets zero vector length to zero
+ if(this.getRadius()>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.Button");
+_3.drawing.ui.Button=_3.drawing.util.oo.declare(function(_4){
+_4.subShape=true;
+_2.mixin(this,_4);
+this.width=_4.data.width||_4.data.rx*2;
+this.height=_4.data.height||_4.data.ry*2;
+this.y=_4.data.y||_4.data.cy-_4.data.ry;
+this.id=this.id||this.util.uid(this.type);
+this.util.attr(this.container,"id",this.id);
+if(this.callback){
+this.hitched=_2.hitch(this.scope||window,this.callback,this);
+}
+_4.drawingType="ui";
+if(_4.data.width&&_4.data.height){
+this.shape=new _3.drawing.stencil.Rect(_4);
+}else{
+this.shape=new _3.drawing.stencil.Ellipse(_4);
+}
+var _5=function(s,p,v){
+_2.forEach(["norm","over","down","selected"],function(nm){
+s[nm].fill[p]=v;
+});
+};
+_5(this.style.button,"y2",this.height+this.y);
+_5(this.style.button,"y1",this.y);
+if(_4.icon&&!_4.icon.text){
+var _6=this.drawing.getConstructor(_4.icon.type);
+var o=this.makeOptions(_4.icon);
+o.data=_2.mixin(o.data,this.style.button.icon.norm);
+if(o.data&&o.data.borderWidth===0){
+o.data.fill=this.style.button.icon.norm.fill=o.data.color;
+}else{
+if(_4.icon.type=="line"||(_4.icon.type=="path"&&!_4.icon.closePath)){
+this.style.button.icon.selected.color=this.style.button.icon.selected.fill;
+}else{
+}
+}
+this.icon=new _6(o);
+}else{
+if(_4.text||(_4.icon&&_4.icon.text)){
+o=this.makeOptions(_4.text||_4.icon.text);
+o.data.color=this.style.button.icon.norm.color;
+this.style.button.icon.selected.color=this.style.button.icon.selected.fill;
+this.icon=new _3.drawing.stencil.Text(o);
+this.icon.attr({height:this.icon._lineHeight,y:((this.height-this.icon._lineHeight)/2)+this.y});
+}
+}
+var c=this.drawing.getConstructor(this.toolType);
+if(c){
+this.drawing.addUI("tooltip",{data:{text:c.setup.tooltip},button:this});
+}
+this.onOut();
+},{callback:null,scope:null,hitched:null,toolType:"",onClick:function(_7){
+},makeOptions:function(d,s){
+s=s||1;
+d=_2.clone(d);
+var o={util:this.util,mouse:this.mouse,container:this.container,subShape:true};
+if(typeof (d)=="string"){
+o.data={x:this.data.x-5,y:this.data.y+2,width:this.data.width,height:this.data.height,text:d,makeFit:true};
+}else{
+if(d.points){
+_2.forEach(d.points,function(pt){
+pt.x=pt.x*this.data.width*0.01*s+this.data.x;
+pt.y=pt.y*this.data.height*0.01*s+this.data.y;
+},this);
+o.data={};
+for(var n in d){
+if(n!="points"){
+o.data[n]=d[n];
+}
+}
+o.points=d.points;
+}else{
+for(n in d){
+if(/x|width/.test(n)){
+d[n]=d[n]*this.data.width*0.01*s;
+}else{
+if(/y|height/.test(n)){
+d[n]=d[n]*this.data.height*0.01*s;
+}
+}
+if(/x/.test(n)&&!/r/.test(n)){
+d[n]+=this.data.x;
+}else{
+if(/y/.test(n)&&!/r/.test(n)){
+d[n]+=this.data.y;
+}
+}
+}
+delete d.type;
+o.data=d;
+}
+}
+o.drawingType="ui";
+return o;
+if(d.borderWidth!==undefined){
+o.data.borderWidth=d.borderWidth;
+}
+return o;
+},enabled:true,selected:false,type:"drawing.library.UI.Button",select:function(){
+this.selected=true;
+if(this.icon){
+this.icon.attr(this.style.button.icon.selected);
+}
+this._change(this.style.button.selected);
+this.shape.shadow&&this.shape.shadow.hide();
+},deselect:function(){
+this.selected=false;
+if(this.icon){
+this.icon.attr(this.style.button.icon.norm);
+}
+this.shape.shadow&&this.shape.shadow.show();
+this._change(this.style.button.norm);
+},disable:function(){
+if(!this.enabled){
+return;
+}
+this.enabled=false;
+this._change(this.style.button.disabled);
+this.icon.attr({color:this.style.button.norm.color});
+},enable:function(){
+if(this.enabled){
+return;
+}
+this.enabled=true;
+this._change(this.style.button.norm);
+this.icon.attr({color:this.style.button.icon.norm.color});
+},_change:function(_8){
+this.shape.attr(_8);
+this.shape.shadow&&this.shape.shadow.container.moveToBack();
+if(this.icon){
+this.icon.shape.moveToFront();
+}
+},onOver:function(){
+if(this.selected||!this.enabled){
+return;
+}
+this._change(this.style.button.over);
+},onOut:function(){
+if(this.selected){
+return;
+}
+this._change(this.style.button.norm);
+},onDown:function(){
+if(this.selected||!this.enabled){
+return;
+}
+this._change(this.style.button.selected);
+},onUp:function(){
+if(!this.enabled){
+return;
+}
+this._change(this.style.button.over);
+if(this.hitched){
+this.hitched();
+}
+this.onClick(this);
+},attr:function(_9){
+if(this.icon){
+this.icon.attr(_9);
+}
+}});
+_3.drawing.register({name:"dojox.drawing.ui.Button"},"stencil");
+});
diff --git a/js/libs/dojox/drawing/ui/Button.js.uncompressed.js b/js/libs/dojox/drawing/ui/Button.js.uncompressed.js
new file mode 100644
index 0000000..7407610
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/Button.js.uncompressed.js
@@ -0,0 +1,230 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/ui/Button", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.Button");
+
+dojox.drawing.ui.Button = dojox.drawing.util.oo.declare(
+ // summary:
+ // Creates a clickable button in "UI" mode of the drawing.
+ // description:
+ // Creates a 4-state button: normal, hover, active, selected.
+ // Optionally may include button text or an icon.
+ function(options){
+ options.subShape = true;
+ dojo.mixin(this, options);
+ //console.log(" button:", this);
+ this.width = options.data.width || options.data.rx*2;
+ this.height = options.data.height || options.data.ry*2;
+ this.y = options.data.y || options.data.cy - options.data.ry;
+ //
+ this.id = this.id || this.util.uid(this.type);
+ this.util.attr(this.container, "id", this.id);
+ if(this.callback){
+ this.hitched = dojo.hitch(this.scope || window, this.callback, this);
+ }
+
+ // Rectangle itself must be "ui" for radio buttons to work.
+ // This is a work-around for messy code associated with drawingType;
+ // see http://www.andestutor.org/bugzilla/show_bug.cgi?id=1745
+ options.drawingType="ui";
+ // Choose between rectangle and ellipse based on options
+ if(options.data.width && options.data.height){
+ this.shape = new dojox.drawing.stencil.Rect(options);
+ }else{
+ this.shape = new dojox.drawing.stencil.Ellipse(options);
+ }
+
+ var setGrad = function(s, p, v){
+ dojo.forEach(["norm", "over", "down", "selected"], function(nm){
+ s[nm].fill[p] = v;
+ });
+ };
+ // for button backs, not for icons
+ setGrad(this.style.button, "y2", this.height + this.y);
+ setGrad(this.style.button, "y1", this.y);
+
+ if(options.icon && !options.icon.text){
+ var constr = this.drawing.getConstructor(options.icon.type);
+ var o = this.makeOptions(options.icon);
+ o.data = dojo.mixin(o.data, this.style.button.icon.norm);
+
+ if(o.data && o.data.borderWidth===0){
+ o.data.fill = this.style.button.icon.norm.fill = o.data.color;
+ }else if(options.icon.type=="line" || (options.icon.type=="path" && !options.icon.closePath)){
+ this.style.button.icon.selected.color = this.style.button.icon.selected.fill;
+ }else{
+ //o.data.fill = this.style.button.icon.norm.fill = o.data.color;
+ }
+ this.icon = new constr(o);
+ //console.log(" button:", this.toolType, this.style.button.icon)
+ }else if(options.text || (options.icon && options.icon.text)){
+ //console.warn("button text:", options.text || options.icon.text)
+ o = this.makeOptions(options.text || options.icon.text);
+ o.data.color = this.style.button.icon.norm.color; //= o.data.fill;
+ this.style.button.icon.selected.color = this.style.button.icon.selected.fill;
+ this.icon = new dojox.drawing.stencil.Text(o);
+ this.icon.attr({
+ height: this.icon._lineHeight,
+ y:((this.height-this.icon._lineHeight)/2)+this.y
+ });
+ }
+
+ var c = this.drawing.getConstructor(this.toolType);
+ if(c){
+ this.drawing.addUI("tooltip", {data:{text:c.setup.tooltip}, button:this});
+ }
+
+ this.onOut();
+
+ },{
+
+ callback:null,
+ scope:null,
+ hitched:null,
+ toolType:"",
+
+ onClick: function(/*Object*/button){
+ // summary:
+ // Stub to connect. Event is 'this'
+ // Alternatively can pass in a scope and a callback
+ // on creation.
+ },
+
+ makeOptions: function(/*Object*/d, /*Float*/s){
+
+ s = s || 1;
+ d = dojo.clone(d);
+ var o = {
+ util: this.util,
+ mouse: this.mouse,
+ container: this.container,
+ subShape:true
+ };
+
+ if(typeof(d)=="string"){
+
+ o.data = {
+ x:this.data.x - 5,
+ y: this.data.y + 2,
+ width:this.data.width,
+ height:this.data.height,
+ text:d,
+ makeFit:true
+ };
+
+ }else if(d.points){
+ //console.warn("points")
+ dojo.forEach(d.points, function(pt){
+ pt.x = pt.x * this.data.width * .01 * s + this.data.x;
+ pt.y = pt.y * this.data.height * .01 * s + this.data.y;
+ }, this);
+ o.data = {};
+ for(var n in d){
+ if(n!="points"){
+ o.data[n] = d[n];
+ }
+ }
+ o.points = d.points;
+
+ }else{
+ //console.warn("data")
+ for(n in d){
+ if(/x|width/.test(n)){
+ d[n] = d[n] * this.data.width * .01 * s;
+ }else if(/y|height/.test(n)){
+ d[n] = d[n] * this.data.height * .01 * s;
+ }
+ if(/x/.test(n) && !/r/.test(n)){
+ d[n] += this.data.x;
+ }else if(/y/.test(n) && !/r/.test(n)){
+ d[n] += this.data.y;
+ }
+ }
+ delete d.type;
+ o.data = d;
+
+ }
+ o.drawingType = "ui";
+ return o;
+
+ // do style
+ if(d.borderWidth!==undefined){
+ //console.log(" -------- bw data:", o.data)
+ o.data.borderWidth = d.borderWidth;
+ }
+
+ return o;
+ },
+
+ enabled:true,
+ selected:false,
+ type:"drawing.library.UI.Button",
+
+ // note:
+ // need to move the Stencil's shape to front, not
+ // its container. Therefore we can't use the Stencil's
+ // moveTo.. methods.
+ select: function(){
+ this.selected = true;
+ if(this.icon){this.icon.attr(this.style.button.icon.selected);}
+ this._change(this.style.button.selected);
+ this.shape.shadow && this.shape.shadow.hide();
+ },
+ deselect: function(){
+ this.selected = false;
+ if(this.icon){this.icon.attr(this.style.button.icon.norm);}
+ this.shape.shadow && this.shape.shadow.show();
+ this._change(this.style.button.norm);
+
+ },
+ disable: function(){
+ if(!this.enabled){ return; }
+ this.enabled = false;
+ this._change(this.style.button.disabled);
+ this.icon.attr({color:this.style.button.norm.color});
+ },
+ enable: function(){
+ if(this.enabled){ return; }
+ this.enabled = true;
+ this._change(this.style.button.norm);
+ this.icon.attr({color:this.style.button.icon.norm.color});
+ },
+
+ _change: function(/*Object*/sty){
+ this.shape.attr(sty);
+ this.shape.shadow && this.shape.shadow.container.moveToBack();
+ if(this.icon){this.icon.shape.moveToFront();};
+ },
+ onOver: function(){
+ //console.log("BUTTON OVER")
+ if(this.selected || !this.enabled){ return; }
+ this._change(this.style.button.over);
+ },
+ onOut: function(){
+ if(this.selected){ return; }
+ this._change(this.style.button.norm);
+ },
+ onDown: function(){
+ if(this.selected || !this.enabled){ return; }
+ this._change(this.style.button.selected);
+ },
+ onUp: function(){
+ //console.log("BUTTON UP")
+ if(!this.enabled){ return; }
+ this._change(this.style.button.over);
+ if(this.hitched){
+ this.hitched();
+ }
+ this.onClick(this);
+ },
+ attr: function(options){
+ if(this.icon){this.icon.attr(options);}
+ }
+ }
+
+);
+
+dojox.drawing.register({
+ name:"dojox.drawing.ui.Button"
+}, "stencil");
+});
diff --git a/js/libs/dojox/drawing/ui/Toolbar.js b/js/libs/dojox/drawing/ui/Toolbar.js
new file mode 100644
index 0000000..0d09cba
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/Toolbar.js
@@ -0,0 +1,183 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/library/icons"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.Toolbar");
+_2.require("dojox.drawing.library.icons");
+_2.declare("dojox.drawing.ui.Toolbar",[],{constructor:function(_4,_5){
+this.util=_3.drawing.util.common;
+if(_4.drawing){
+this.toolDrawing=_4.drawing;
+this.drawing=this.toolDrawing;
+this.width=this.toolDrawing.width;
+this.height=this.toolDrawing.height;
+this.strSelected=_4.selected;
+this.strTools=_4.tools;
+this.strPlugs=_4.plugs;
+this._mixprops(["padding","margin","size","radius"],_4);
+this.addBack();
+this.orient=_4.orient?_4.orient:false;
+}else{
+var _6=_2.marginBox(_5);
+this.width=_6.w;
+this.height=_6.h;
+this.strSelected=_2.attr(_5,"selected");
+this.strTools=_2.attr(_5,"tools");
+this.strPlugs=_2.attr(_5,"plugs");
+this._mixprops(["padding","margin","size","radius"],_5);
+this.toolDrawing=new _3.drawing.Drawing({mode:"ui"},_5);
+this.orient=_2.attr(_5,"orient");
+}
+this.horizontal=this.orient?this.orient=="H":this.width>this.height;
+if(this.toolDrawing.ready){
+this.makeButtons();
+if(!this.strSelected&&this.drawing.defaults.clickMode){
+this.drawing.mouse.setCursor("default");
+}
+}else{
+var c=_2.connect(this.toolDrawing,"onSurfaceReady",this,function(){
+_2.disconnect(c);
+this.drawing=_3.drawing.getRegistered("drawing",_2.attr(_5,"drawingId"));
+this.makeButtons();
+if(!this.strSelected&&this.drawing.defaults.clickMode){
+var c=_2.connect(this.drawing,"onSurfaceReady",this,function(){
+_2.disconnect(c);
+this.drawing.mouse.setCursor("default");
+});
+}
+});
+}
+},padding:10,margin:5,size:30,radius:3,toolPlugGap:20,strSelected:"",strTools:"",strPlugs:"",makeButtons:function(){
+this.buttons=[];
+this.plugins=[];
+var x=this.padding,y=this.padding,w=this.size,h=this.size,r=this.radius,g=this.margin,_7=_3.drawing.library.icons,s={place:"BR",size:2,mult:4};
+if(this.strTools){
+var _8=[];
+var _9=_3.drawing.getRegistered("tool");
+var _a={};
+for(var nm in _9){
+var _b=this.util.abbr(nm);
+_a[_b]=_9[nm];
+if(this.strTools=="all"){
+_8.push(_b);
+var _c=_3.drawing.getRegistered("tool",nm);
+if(_c.secondary){
+_8.push(_c.secondary.name);
+}
+}
+}
+if(this.strTools!="all"){
+var _d=this.strTools.split(",");
+_2.forEach(_d,function(_e){
+_e=_2.trim(_e);
+_8.push(_e);
+var _f=_3.drawing.getRegistered("tool",_a[_e].name);
+if(_f.secondary){
+_8.push(_f.secondary.name);
+}
+},this);
+}
+_2.forEach(_8,function(t){
+t=_2.trim(t);
+var _10=false;
+if(t.indexOf("Secondary")>-1){
+var _11=t.substring(0,t.indexOf("Secondary"));
+var sec=_3.drawing.getRegistered("tool",_a[_11].name).secondary;
+var _12=sec.label;
+this[t]=sec.funct;
+if(sec.setup){
+_2.hitch(this,sec.setup)();
+}
+var btn=this.toolDrawing.addUI("button",{data:{x:x,y:y,width:w,height:h/2,r:r},toolType:t,secondary:true,text:_12,shadow:s,scope:this,callback:this[t]});
+if(sec.postSetup){
+_2.hitch(this,sec.postSetup,btn)();
+}
+_10=true;
+}else{
+var btn=this.toolDrawing.addUI("button",{data:{x:x,y:y,width:w,height:h,r:r},toolType:t,icon:_7[t],shadow:s,scope:this,callback:"onToolClick"});
+}
+_3.drawing.register(btn,"button");
+this.buttons.push(btn);
+if(this.strSelected==t){
+btn.select();
+this.selected=btn;
+this.drawing.setTool(btn.toolType);
+}
+if(this.horizontal){
+x+=h+g;
+}else{
+var _13=_10?h/2+g:h+g;
+y+=_13;
+}
+},this);
+}
+if(this.horizontal){
+x+=this.toolPlugGap;
+}else{
+y+=this.toolPlugGap;
+}
+if(this.strPlugs){
+var _14=[];
+var _15=_3.drawing.getRegistered("plugin");
+var _16={};
+for(var nm in _15){
+var _17=this.util.abbr(nm);
+_16[_17]=_15[nm];
+if(this.strPlugs=="all"){
+_14.push(_17);
+}
+}
+if(this.strPlugs!="all"){
+_14=this.strPlugs.split(",");
+_2.map(_14,function(p){
+return _2.trim(p);
+});
+}
+_2.forEach(_14,function(p){
+var t=_2.trim(p);
+if(_16[p].button!=false){
+var btn=this.toolDrawing.addUI("button",{data:{x:x,y:y,width:w,height:h,r:r},toolType:t,icon:_7[t],shadow:s,scope:this,callback:"onPlugClick"});
+_3.drawing.register(btn,"button");
+this.plugins.push(btn);
+if(this.horizontal){
+x+=h+g;
+}else{
+y+=h+g;
+}
+}
+var _18={};
+_16[p].button==false?_18={name:this.drawing.stencilTypeMap[p]}:_18={name:this.drawing.stencilTypeMap[p],options:{button:btn}};
+this.drawing.addPlugin(_18);
+},this);
+}
+_2.connect(this.drawing,"onRenderStencil",this,"onRenderStencil");
+},onRenderStencil:function(_19){
+if(this.drawing.defaults.clickMode){
+this.drawing.mouse.setCursor("default");
+this.selected&&this.selected.deselect();
+this.selected=null;
+}
+},addTool:function(){
+},addPlugin:function(){
+},addBack:function(){
+this.toolDrawing.addUI("rect",{data:{x:0,y:0,width:this.width,height:this.size+(this.padding*2),fill:"#ffffff",borderWidth:0}});
+},onToolClick:function(_1a){
+if(this.drawing.defaults.clickMode){
+this.drawing.mouse.setCursor("crosshair");
+}
+_2.forEach(this.buttons,function(b){
+if(b.id==_1a.id){
+b.select();
+this.selected=b;
+this.drawing.setTool(_1a.toolType);
+}else{
+if(!b.secondary){
+b.deselect();
+}
+}
+},this);
+},onPlugClick:function(_1b){
+},_mixprops:function(_1c,_1d){
+_2.forEach(_1c,function(p){
+this[p]=_1d.tagName?_2.attr(_1d,p)===null?this[p]:_2.attr(_1d,p):_1d[p]===undefined?this[p]:_1d[p];
+},this);
+}});
+});
diff --git a/js/libs/dojox/drawing/ui/Toolbar.js.uncompressed.js b/js/libs/dojox/drawing/ui/Toolbar.js.uncompressed.js
new file mode 100644
index 0000000..20bc781
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/Toolbar.js.uncompressed.js
@@ -0,0 +1,284 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/ui/Toolbar", ["dijit","dojo","dojox","dojo/require!dojox/drawing/library/icons"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.Toolbar");
+dojo.require("dojox.drawing.library.icons");
+
+dojo.declare("dojox.drawing.ui.Toolbar", [], {
+ // summary:
+ // A Toolbar used for holding buttons; typically representing the Stencils
+ // used for a DojoX Drawing.
+ // description:
+ // Creates a GFX-based toobar that holds GFX-based buttons. Can be either created
+ // within the actual drawing or within a seperate DOM element. When within the
+ // drawing, the toolbar will cover a portion of the drawing; hence the option.
+ //
+ // A Toolbar can be created programmtically or in markup. Currently markup is as
+ // a separate DOM element and programmtic is within the drawing.
+ // examples:
+ // | dojo.connect(myDrawing, "onSurfaceReady", function(){
+ // | new dojox.drawing.ui.Toolbar({
+ // | drawing:myDrawing,
+ // | tools:"all",
+ // | plugs:"all",
+ // | selected:"ellipse"
+ // | });
+ // | });
+ //
+ // |
+ //
+ //
+ constructor: function(props, node){
+ //console.warn("GFX Toolbar:", props, node)
+ this.util = dojox.drawing.util.common;
+
+ // no mixin. painful.
+ if(props.drawing){
+ // programmatic
+ this.toolDrawing = props.drawing;
+ this.drawing = this.toolDrawing;
+ this.width = this.toolDrawing.width;
+ this.height = this.toolDrawing.height;
+ this.strSelected = props.selected;
+ this.strTools = props.tools;
+ this.strPlugs = props.plugs;
+ this._mixprops(["padding", "margin", "size", "radius"], props);
+ this.addBack();
+ this.orient = props.orient ? props.orient : false;
+ }else{
+ // markup
+ var box = dojo.marginBox(node);
+ this.width = box.w;
+ this.height = box.h;
+ this.strSelected = dojo.attr(node, "selected");
+ this.strTools = dojo.attr(node, "tools");
+ this.strPlugs = dojo.attr(node, "plugs");
+ this._mixprops(["padding", "margin", "size", "radius"], node);
+ this.toolDrawing = new dojox.drawing.Drawing({mode:"ui"}, node);
+ this.orient = dojo.attr(node, "orient");
+ }
+
+ this.horizontal = this.orient ? this.orient == "H" : this.width > this.height;
+ console.log("this.hor: ",this.horizontal," orient: ",this.orient);
+ if(this.toolDrawing.ready){
+ this.makeButtons();
+ if(!this.strSelected && this.drawing.defaults.clickMode){ this.drawing.mouse.setCursor('default'); };
+ }else{
+ var c = dojo.connect(this.toolDrawing, "onSurfaceReady", this, function(){
+ //console.log("TB built")
+ dojo.disconnect(c);
+ this.drawing = dojox.drawing.getRegistered("drawing", dojo.attr(node, "drawingId")); //
+ this.makeButtons();
+ if(!this.strSelected && this.drawing.defaults.clickMode){
+ var c = dojo.connect(this.drawing, "onSurfaceReady", this, function(){
+ dojo.disconnect(c);
+ this.drawing.mouse.setCursor('default');
+ });
+ }
+ });
+ }
+
+ },
+
+ // padding:Number
+ // The amount of spce between the top and left of the toolbar and the buttons.
+ padding:10,
+ // margin: Number
+ // The space between each button.
+ margin:5,
+ // size: Number
+ // The width and height of the button
+ size:30,
+ // radius: Number
+ // The size of the button's rounded corner
+ radius:3,
+ //
+ // toolPlugGap: number
+ // The distnce between the tool buttons and plug buttons
+ toolPlugGap:20,
+
+ // strSlelected | selected: String
+ // The button that should be selected at startup.
+ strSelected:"",
+ // strTools | tools: String
+ // A comma delineated list of the Stencil-tools to include in the Toolbar.
+ // If "all" is used, all registered tools are included.
+ strTools:"",
+ // strPlugs | plugs: String
+ // A comma delineated list of the plugins to include in the Toolbar.
+ // If "all" is used, all registered plugins are included.
+ strPlugs:"",
+
+ makeButtons: function(){
+ // summary:
+ // Internal. create buttons.
+ this.buttons = [];
+ this.plugins = [];
+
+ var x = this.padding, y = this.padding, w = this.size, h = this.size, r = this.radius, g = this.margin,
+ sym = dojox.drawing.library.icons,
+ s = {place:"BR", size:2, mult:4};
+
+ if(this.strTools){
+ var toolAr = [];
+ var tools = dojox.drawing.getRegistered("tool");
+ var toolMap = {};
+ for(var nm in tools){
+ var tool = this.util.abbr(nm);
+ toolMap[tool] = tools[nm];
+ if(this.strTools=="all"){
+ toolAr.push(tool);
+ var details = dojox.drawing.getRegistered("tool",nm);
+ if(details.secondary){
+ toolAr.push(details.secondary.name);
+ }
+ }
+ }
+ if(this.strTools!="all"){
+ var toolTmp = this.strTools.split(",");
+ dojo.forEach(toolTmp, function(tool){
+ tool = dojo.trim(tool);
+ toolAr.push(tool);
+ var details = dojox.drawing.getRegistered("tool",toolMap[tool].name);
+ if(details.secondary){
+ toolAr.push(details.secondary.name);
+ }
+ }, this);
+ //dojo.map(toolAr, function(t){ return dojo.trim(t); });
+ }
+
+ dojo.forEach(toolAr, function(t){
+ t = dojo.trim(t);
+ var secondary = false;
+ if(t.indexOf("Secondary")>-1){
+ var prim = t.substring(0,t.indexOf("Secondary"));
+ var sec = dojox.drawing.getRegistered("tool",toolMap[prim].name).secondary;
+ var label = sec.label;
+ this[t] = sec.funct;
+ if(sec.setup){ dojo.hitch(this, sec.setup)(); };
+ var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h/2, r:r}, toolType:t, secondary:true, text:label, shadow:s, scope:this, callback:this[t]});
+ if(sec.postSetup){ dojo.hitch(this, sec.postSetup, btn)(); };
+ secondary = true;
+ } else {
+ var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h, r:r}, toolType:t, icon:sym[t], shadow:s, scope:this, callback:"onToolClick"});
+ }
+ dojox.drawing.register(btn, "button");
+ this.buttons.push(btn);
+ if(this.strSelected==t){
+ btn.select();
+ this.selected = btn;
+ this.drawing.setTool(btn.toolType);
+ }
+ if(this.horizontal){
+ x += h + g;
+ }else{
+ var space = secondary ? h/2 + g : h + g;
+ y += space;
+ }
+ }, this);
+ }
+
+ if(this.horizontal){
+ x += this.toolPlugGap;
+ }else{
+ y += this.toolPlugGap;
+ }
+
+ if(this.strPlugs){
+ var plugAr = [];
+ var plugs = dojox.drawing.getRegistered("plugin");
+ var plugMap = {};
+ for(var nm in plugs){
+ var abbr = this.util.abbr(nm);
+ plugMap[abbr] = plugs[nm];
+ if(this.strPlugs=="all"){ plugAr.push(abbr); }
+ }
+ if(this.strPlugs!="all"){
+ plugAr = this.strPlugs.split(",");
+ dojo.map(plugAr, function(p){ return dojo.trim(p); });
+ }
+
+ dojo.forEach(plugAr, function(p){
+ var t = dojo.trim(p);
+ //console.log(" plugin:", p);
+ if(plugMap[p].button != false){
+ var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h, r:r}, toolType:t, icon:sym[t], shadow:s, scope:this, callback:"onPlugClick"});
+ dojox.drawing.register(btn, "button");
+ this.plugins.push(btn);
+
+ if(this.horizontal){
+ x += h + g;
+ }else{
+ y += h + g;
+ }
+ }
+
+ var addPlug = {}
+ plugMap[p].button == false ? addPlug = {name:this.drawing.stencilTypeMap[p]} : addPlug = {name:this.drawing.stencilTypeMap[p], options:{button:btn}};
+ this.drawing.addPlugin(addPlug);
+ }, this);
+ }
+
+ dojo.connect(this.drawing, "onRenderStencil", this, "onRenderStencil");
+ },
+
+ onRenderStencil: function(/* Object */stencil){
+ // summary:
+ // Stencil render event.
+ if(this.drawing.defaults.clickMode){
+ this.drawing.mouse.setCursor("default");
+ this.selected && this.selected.deselect();
+ this.selected = null;
+ }
+
+ },
+
+ addTool: function(){
+ // TODO: add button here
+ },
+
+ addPlugin: function(){
+ // TODO: add button here
+ },
+
+ addBack: function(){
+ // summary:
+ // Internal. Adds the back, behind the toolbar.
+ this.toolDrawing.addUI("rect", {data:{x:0, y:0, width:this.width, height:this.size + (this.padding*2), fill:"#ffffff", borderWidth:0}});
+ },
+
+ onToolClick: function(/*Object*/button){
+ // summary:
+ // Tool click event. May be connected to.
+ //
+ if(this.drawing.defaults.clickMode){ this.drawing.mouse.setCursor("crosshair"); }
+ dojo.forEach(this.buttons, function(b){
+ if(b.id==button.id){
+ b.select();
+ this.selected = b;
+ this.drawing.setTool(button.toolType)
+ }else{
+ if(!b.secondary){ b.deselect(); }
+ }
+ },this)
+ },
+
+ onPlugClick: function(/*Object*/button){
+ // summary:
+ // Plugin click event. May be connected to.
+ },
+
+ _mixprops: function(/*Array*/props, /*Object | Node*/objNode){
+ // summary:
+ // Internally used for mixing in props from an object or
+ // from a dom node.
+ dojo.forEach(props, function(p){
+ this[p] = objNode.tagName
+ ? dojo.attr(objNode, p)===null ? this[p] : dojo.attr(objNode, p)
+ : objNode[p]===undefined ? this[p] : objNode[p];
+ }, this);
+ }
+
+});
+});
diff --git a/js/libs/dojox/drawing/ui/Tooltip.js b/js/libs/dojox/drawing/ui/Tooltip.js
new file mode 100644
index 0000000..748655d
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/Tooltip.js
@@ -0,0 +1,57 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.Tooltip");
+_2.require("dojox.drawing.plugins._Plugin");
+(function(){
+var _4=null;
+var _5=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_6){
+this.createDom();
+},{show:function(_7,_8){
+this.domNode.innerHTML=_8;
+var dx=30;
+var px=_7.data.x+_7.data.width;
+var py=_7.data.y+_7.data.height;
+var x=px+this.mouse.origin.x+dx;
+var y=py+this.mouse.origin.y+dx;
+_2.style(this.domNode,{display:"inline",left:x+"px",top:y+"px"});
+var _9=_2.marginBox(this.domNode);
+this.createShape(x-this.mouse.origin.x,y-this.mouse.origin.y,_9.w,_9.h);
+},createShape:function(x,y,w,h){
+this.balloon&&this.balloon.destroy();
+var r=5,x2=x+w,y2=y+h,_a=[];
+var _b=function(){
+for(var i=0;i>built
+// wrapped by build app
+define("dojox/drawing/ui/Tooltip", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.Tooltip");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+
+(function(){
+
+ // summary:
+ // Used for UI tooltips. Buttons in the toolbar.
+ // This file is not complete.
+ //
+ var master = null;
+ var MasterC = dojox.drawing.util.oo.declare(
+
+ dojox.drawing.plugins._Plugin,
+ function(options){
+ this.createDom();
+ },
+ {
+ show: function(button, text){
+ this.domNode.innerHTML = text;
+
+ var dx = 30;
+ var px = button.data.x + button.data.width;
+ var py = button.data.y + button.data.height;
+ var x = px + this.mouse.origin.x + dx;
+ var y = py + this.mouse.origin.y + dx;
+
+ dojo.style(this.domNode, {
+ display: "inline",
+ left:x +"px",
+ top:y+"px"
+ });
+
+ var box = dojo.marginBox(this.domNode);
+
+ this.createShape(x-this.mouse.origin.x, y-this.mouse.origin.y, box.w, box.h);
+ },
+
+
+ createShape: function(x,y,w,h){
+ this.balloon && this.balloon.destroy();
+ var r = 5, x2 = x+w, y2 = y+h, points = [];
+ var add = function(){
+ for(var i=0;i>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.dom.Pan");
+_2.require("dojox.drawing.plugins._Plugin");
+_2.deprecated("dojox.drawing.ui.dom.Pan","It may not even make it to the 1.4 release.",1.4);
+_3.drawing.ui.dom.Pan=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_4){
+this.domNode=_4.node;
+var _5;
+_2.connect(this.domNode,"click",this,"onSetPan");
+_2.connect(this.keys,"onKeyUp",this,"onKeyUp");
+_2.connect(this.keys,"onKeyDown",this,"onKeyDown");
+_2.connect(this.anchors,"onAnchorUp",this,"checkBounds");
+_2.connect(this.stencils,"register",this,"checkBounds");
+_2.connect(this.canvas,"resize",this,"checkBounds");
+_2.connect(this.canvas,"setZoom",this,"checkBounds");
+_2.connect(this.canvas,"onScroll",this,function(){
+if(this._blockScroll){
+this._blockScroll=false;
+return;
+}
+_5&&clearTimeout(_5);
+_5=setTimeout(_2.hitch(this,"checkBounds"),200);
+});
+this._mouseHandle=this.mouse.register(this);
+},{selected:false,type:"dojox.drawing.ui.dom.Pan",onKeyUp:function(_6){
+if(_6.keyCode==32){
+this.onSetPan(false);
+}
+},onKeyDown:function(_7){
+if(_7.keyCode==32){
+this.onSetPan(true);
+}
+},onSetPan:function(_8){
+if(_8===true||_8===false){
+this.selected=!_8;
+}
+if(this.selected){
+this.selected=false;
+_2.removeClass(this.domNode,"selected");
+}else{
+this.selected=true;
+_2.addClass(this.domNode,"selected");
+}
+this.mouse.setEventMode(this.selected?"pan":"");
+},onPanDrag:function(_9){
+var x=_9.x-_9.last.x;
+var y=_9.y-_9.last.y;
+this.canvas.domNode.parentNode.scrollTop-=_9.move.y;
+this.canvas.domNode.parentNode.scrollLeft-=_9.move.x;
+this.canvas.onScroll();
+},onStencilUp:function(_a){
+this.checkBounds();
+},onStencilDrag:function(_b){
+},checkBounds:function(){
+var _c=function(){
+};
+var _d=function(){
+};
+var t=Infinity,r=-Infinity,b=-Infinity,l=Infinity,sx=0,sy=0,dy=0,dx=0,mx=this.stencils.group?this.stencils.group.getTransform():{dx:0,dy:0},sc=this.mouse.scrollOffset(),_e=sc.left?10:0,_f=sc.top?10:0,ch=this.canvas.height,cw=this.canvas.width,z=this.canvas.zoom,pch=this.canvas.parentHeight,pcw=this.canvas.parentWidth;
+this.stencils.withSelected(function(m){
+var o=m.getBounds();
+_d("SEL BOUNDS:",o);
+t=Math.min(o.y1+mx.dy,t);
+r=Math.max(o.x2+mx.dx,r);
+b=Math.max(o.y2+mx.dy,b);
+l=Math.min(o.x1+mx.dx,l);
+});
+this.stencils.withUnselected(function(m){
+var o=m.getBounds();
+_d("UN BOUNDS:",o);
+t=Math.min(o.y1,t);
+r=Math.max(o.x2,r);
+b=Math.max(o.y2,b);
+l=Math.min(o.x1,l);
+});
+b*=z;
+var _10=0,_11=0;
+_c("Bottom test","b:",b,"z:",z,"ch:",ch,"pch:",pch,"top:",sc.top,"sy:",sy);
+if(b>pch||sc.top){
+_c("*bottom scroll*");
+ch=Math.max(b,pch+sc.top);
+sy=sc.top;
+_10+=this.canvas.getScrollWidth();
+}else{
+if(!sy&&ch>pch){
+_c("*bottom remove*");
+ch=pch;
+}
+}
+r*=z;
+if(r>pcw||sc.left){
+cw=Math.max(r,pcw+sc.left);
+sx=sc.left;
+_11+=this.canvas.getScrollWidth();
+}else{
+if(!sx&&cw>pcw){
+cw=pcw;
+}
+}
+cw+=_10*2;
+ch+=_11*2;
+this._blockScroll=true;
+this.stencils.group&&this.stencils.group.applyTransform({dx:dx,dy:dy});
+this.stencils.withUnselected(function(m){
+m.transformPoints({dx:dx,dy:dy});
+});
+this.canvas.setDimensions(cw,ch,sx,sy);
+}});
+_3.drawing.ui.dom.Pan.setup={name:"dojox.drawing.ui.dom.Pan",tooltip:"Pan Tool",iconClass:"iconPan"};
+_3.drawing.register(_3.drawing.ui.dom.Pan.setup,"plugin");
+});
diff --git a/js/libs/dojox/drawing/ui/dom/Pan.js.uncompressed.js b/js/libs/dojox/drawing/ui/dom/Pan.js.uncompressed.js
new file mode 100644
index 0000000..5911abc
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/dom/Pan.js.uncompressed.js
@@ -0,0 +1,213 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/ui/dom/Pan", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.dom.Pan");
+dojo.require("dojox.drawing.plugins._Plugin");
+dojo.deprecated("dojox.drawing.ui.dom.Pan", "It may not even make it to the 1.4 release.", 1.4);
+
+dojox.drawing.ui.dom.Pan = dojox.drawing.util.oo.declare(
+ // NOTE:
+ // dojox.drawing.ui.dom.Pan is DEPRECATED.
+ // This was a temporary DOM solution. Use the non-dom
+ // tools for Toobar and Plugins.
+ //
+ // summary:
+ // A plugin that allows for a scrolling canvas. An action
+ // tool is added to the toolbar that allows for panning. Holding
+ // the space bar is a shortcut to that action. The canvas will
+ // only pan and scroll if there are objects out of the viewable
+ // area.
+ // example:
+ // |
+ //
+ dojox.drawing.plugins._Plugin,
+ function(options){
+
+ this.domNode = options.node;
+ var _scrollTimeout;
+ dojo.connect(this.domNode, "click", this, "onSetPan");
+ dojo.connect(this.keys, "onKeyUp", this, "onKeyUp");
+ dojo.connect(this.keys, "onKeyDown", this, "onKeyDown");
+ dojo.connect(this.anchors, "onAnchorUp", this, "checkBounds");
+ dojo.connect(this.stencils, "register", this, "checkBounds");
+ dojo.connect(this.canvas, "resize", this, "checkBounds");
+ dojo.connect(this.canvas, "setZoom", this, "checkBounds");
+ dojo.connect(this.canvas, "onScroll", this, function(){
+ if(this._blockScroll){
+ this._blockScroll = false;
+ return;
+ }
+ _scrollTimeout && clearTimeout(_scrollTimeout);
+ _scrollTimeout = setTimeout(dojo.hitch(this, "checkBounds"), 200);
+ });
+ this._mouseHandle = this.mouse.register(this);
+ // This HAS to be called after setting initial objects or things get screwy.
+ //this.checkBounds();
+ },{
+ selected:false,
+ type:"dojox.drawing.ui.dom.Pan",
+
+ onKeyUp: function(evt){
+ if(evt.keyCode == 32){
+ this.onSetPan(false);
+ }
+ },
+
+ onKeyDown: function(evt){
+ if(evt.keyCode == 32){
+ this.onSetPan(true);
+ }
+ },
+
+ onSetPan: function(/*Boolean | Event*/ bool){
+ if(bool === true || bool === false){
+ this.selected = !bool;
+ }
+ if(this.selected){
+ this.selected = false;
+ dojo.removeClass(this.domNode, "selected");
+ }else{
+ this.selected = true;
+ dojo.addClass(this.domNode, "selected");
+ }
+ this.mouse.setEventMode(this.selected ? "pan" : "");
+ },
+
+ onPanDrag: function(obj){
+ var x = obj.x - obj.last.x;
+ var y = obj.y - obj.last.y;
+ this.canvas.domNode.parentNode.scrollTop -= obj.move.y;
+ this.canvas.domNode.parentNode.scrollLeft -= obj.move.x;
+ this.canvas.onScroll();
+ },
+
+ onStencilUp: function(obj){
+ // this gets called even on click-off because of the
+ // issues with TextBlock deselection
+ this.checkBounds();
+ },
+ onStencilDrag: function(obj){
+ // this gets called even on click-off because of the
+ // issues with TextBlock deselection
+ //this.checkBounds();
+ },
+
+ checkBounds: function(){
+
+ //watch("CHECK BOUNDS DISABLED", true); return;
+
+
+ // summary:
+ // Scans all items on the canvas and checks if they are out of
+ // bounds. If so, a scroll bar (in Canvas) is shown. If the position
+ // is left or top, the canvas is scrolled all items are relocated
+ // the distance of the scroll. Ideally, it should look as if the
+ // items do not move.
+
+ // logging stuff here so it can be turned on and off. This method is
+ // very high maintenance.
+ var log = function(){
+ ///console.log.apply(console, arguments);
+ };
+ var warn = function(){
+ //console.warn.apply(console, arguments);
+ };
+ //console.clear();
+ //console.time("check bounds");
+ var t=Infinity, r=-Infinity, b=-Infinity, l=Infinity,
+ sx=0, sy=0, dy=0, dx=0,
+ mx = this.stencils.group ? this.stencils.group.getTransform() : {dx:0, dy:0},
+ sc = this.mouse.scrollOffset(),
+ // scY, scX: the scrollbar creates the need for extra dimension
+ scY = sc.left ? 10 : 0,
+ scX = sc.top ? 10 : 0,
+ // ch, cw: the current size of the canvas
+ ch = this.canvas.height,
+ cw = this.canvas.width,
+ z = this.canvas.zoom,
+ // pch, pcw: the normal size of the canvas (not scrolled)
+ // these could change if the container resizes.
+ pch = this.canvas.parentHeight,
+ pcw = this.canvas.parentWidth;
+
+
+ this.stencils.withSelected(function(m){
+ var o = m.getBounds();
+ warn("SEL BOUNDS:", o);
+ t = Math.min(o.y1 + mx.dy, t);
+ r = Math.max(o.x2 + mx.dx, r);
+ b = Math.max(o.y2 + mx.dy, b);
+ l = Math.min(o.x1 + mx.dx, l);
+ });
+
+ this.stencils.withUnselected(function(m){
+ var o = m.getBounds();
+ warn("UN BOUNDS:", o);
+ t = Math.min(o.y1, t);
+ r = Math.max(o.x2, r);
+ b = Math.max(o.y2, b);
+ l = Math.min(o.x1, l);
+ });
+
+ b *= z;
+ var xscroll = 0, yscroll = 0;
+ log("Bottom test", "b:", b, "z:", z, "ch:", ch, "pch:", pch, "top:", sc.top, "sy:", sy);
+ if(b > pch || sc.top ){
+ log("*bottom scroll*");
+ // item off bottom
+ ch = Math.max(b, pch + sc.top);
+ sy = sc.top;
+ xscroll += this.canvas.getScrollWidth();
+ }else if(!sy && ch>pch){
+ log("*bottom remove*");
+ // item moved from bottom
+ ch = pch;
+ }
+
+ r *= z;
+ if(r > pcw || sc.left){
+ //log("*right scroll*");
+ // item off right
+ cw = Math.max(r, pcw + sc.left);
+ sx = sc.left;
+ yscroll += this.canvas.getScrollWidth();
+ }else if(!sx && cw>pcw){
+ //log("*right remove*");
+ // item moved from right
+ cw = pcw;
+ }
+
+ // add extra space for scrollbars
+ // double it to give some breathing room
+ cw += xscroll*2;
+ ch += yscroll*2;
+
+ this._blockScroll = true;
+
+ // selected items are not transformed. The selection itself is
+ // and the items are on de-select
+ this.stencils.group && this.stencils.group.applyTransform({dx:dx, dy:dy});
+
+ // non-selected items are transformed
+ this.stencils.withUnselected(function(m){
+ m.transformPoints({dx:dx, dy:dy});
+ });
+
+ this.canvas.setDimensions(cw, ch, sx, sy);
+
+ //console.timeEnd("check bounds");
+ }
+ }
+);
+
+dojox.drawing.ui.dom.Pan.setup = {
+ name:"dojox.drawing.ui.dom.Pan",
+ tooltip:"Pan Tool",
+ iconClass:"iconPan"
+};
+
+dojox.drawing.register(dojox.drawing.ui.dom.Pan.setup, "plugin");
+});
diff --git a/js/libs/dojox/drawing/ui/dom/Toolbar.js b/js/libs/dojox/drawing/ui/dom/Toolbar.js
new file mode 100644
index 0000000..eb87954
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/dom/Toolbar.js
@@ -0,0 +1,107 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.dom.Toolbar");
+_2.deprecated("dojox.drawing.ui.dom.Toolbar","It may not even make it to the 1.4 release.",1.4);
+(function(){
+_2.declare("dojox.drawing.ui.dom.Toolbar",[],{baseClass:"drawingToolbar",buttonClass:"drawingButton",iconClass:"icon",constructor:function(_4,_5){
+_2.addOnLoad(this,function(){
+this.domNode=_2.byId(_5);
+_2.addClass(this.domNode,this.baseClass);
+this.parse();
+});
+},createIcon:function(_6,_7){
+var _8=_7&&_7.setup?_7.setup:{};
+if(_8.iconClass){
+var _9=_8.iconClass?_8.iconClass:"iconNone";
+var _a=_8.tooltip?_8.tooltip:"Tool";
+var _b=_2.create("div",{title:_a},_6);
+_2.addClass(_b,this.iconClass);
+_2.addClass(_b,_9);
+_2.connect(_6,"mouseup",function(_c){
+_2.stopEvent(_c);
+_2.removeClass(_6,"active");
+});
+_2.connect(_6,"mouseover",function(_d){
+_2.stopEvent(_d);
+_2.addClass(_6,"hover");
+});
+_2.connect(_6,"mousedown",this,function(_e){
+_2.stopEvent(_e);
+_2.addClass(_6,"active");
+});
+_2.connect(_6,"mouseout",this,function(_f){
+_2.stopEvent(_f);
+_2.removeClass(_6,"hover");
+});
+}
+},createTool:function(_10){
+_10.innerHTML="";
+var _11=_2.attr(_10,"tool");
+this.toolNodes[_11]=_10;
+_2.attr(_10,"tabIndex",1);
+var _12=_2.getObject(_11);
+this.createIcon(_10,_12);
+this.drawing.registerTool(_11,_12);
+_2.connect(_10,"mouseup",this,function(evt){
+_2.stopEvent(evt);
+_2.removeClass(_10,"active");
+this.onClick(_11);
+});
+_2.connect(_10,"mouseover",function(evt){
+_2.stopEvent(evt);
+_2.addClass(_10,"hover");
+});
+_2.connect(_10,"mousedown",this,function(evt){
+_2.stopEvent(evt);
+_2.addClass(_10,"active");
+});
+_2.connect(_10,"mouseout",this,function(evt){
+_2.stopEvent(evt);
+_2.removeClass(_10,"hover");
+});
+},parse:function(){
+var _13=_2.attr(this.domNode,"drawingId");
+this.drawing=_3.drawing.util.common.byId(_13);
+!this.drawing&&console.error("Drawing not found based on 'drawingId' in Toolbar. ");
+this.toolNodes={};
+var _14;
+_2.query(">",this.domNode).forEach(function(_15,i){
+_15.className=this.buttonClass;
+var _16=_2.attr(_15,"tool");
+var _17=_2.attr(_15,"action");
+var _18=_2.attr(_15,"plugin");
+if(_16){
+if(i==0||_2.attr(_15,"selected")=="true"){
+_14=_16;
+}
+this.createTool(_15);
+}else{
+if(_18){
+var p={name:_18,options:{}},opt=_2.attr(_15,"options");
+if(opt){
+p.options=eval("("+opt+")");
+}
+p.options.node=_15;
+_15.innerHTML="";
+this.drawing.addPlugin(p);
+this.createIcon(_15,_2.getObject(_2.attr(_15,"plugin")));
+}
+}
+},this);
+this.drawing.initPlugins();
+_2.connect(this.drawing,"setTool",this,"onSetTool");
+this.drawing.setTool(_14);
+},onClick:function(_19){
+this.drawing.setTool(_19);
+},onSetTool:function(_1a){
+for(var n in this.toolNodes){
+if(n==_1a){
+_2.addClass(this.toolNodes[_1a],"selected");
+this.toolNodes[_1a].blur();
+}else{
+_2.removeClass(this.toolNodes[n],"selected");
+}
+}
+}});
+})();
+});
diff --git a/js/libs/dojox/drawing/ui/dom/Toolbar.js.uncompressed.js b/js/libs/dojox/drawing/ui/dom/Toolbar.js.uncompressed.js
new file mode 100644
index 0000000..d7b0a8c
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/dom/Toolbar.js.uncompressed.js
@@ -0,0 +1,211 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/ui/dom/Toolbar", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.dom.Toolbar");
+dojo.deprecated("dojox.drawing.ui.dom.Toolbar", "It may not even make it to the 1.4 release.", 1.4);
+
+(function(){
+
+ dojo.declare("dojox.drawing.ui.dom.Toolbar", [], {
+ // NOTE:
+ // dojox.drawing.Toolbar is DEPRECATED.
+ // The intention never was to use HTML as buttons for a Drawing.
+ // This was implemented in order to finish the project for which
+ // Drawing was developed.
+ // Instead use: drawing/ui/Toolbar.js
+ //
+ // summary:
+ // Creates a Toolbar to be used with a DojoX Drawing.
+ // description:
+ // Currently works in markup only. A class is required with
+ // either horizontal or vertical as a class (IE prevented using
+ // either as a default). Assign an attribute of 'drawingId' with
+ // the id of the DojoX Drawing to which this is assigned.
+ // The node children will be assigned as the Tools in the toolbar.
+ // Plugins can also be assigned.
+ // The Toolbar is largely self contained and has no real public
+ // methods or events. the Drawing object should be used.
+ //
+ // example:
+ // |
+ //
+ // TODO: Toolbar works in markup only. Need programmatic.
+ // NOTE: There are plans to make the toolbar out of dojox.gfx vectors.
+ // This may change the APIs in the future.
+ //
+ // baseClass:String
+ // The CSS style to apply to the toolbar node
+ baseClass:"drawingToolbar",
+ // buttonClass:String
+ // The CSS style to apply to each button node
+ buttonClass:"drawingButton",
+ // iconClass:String
+ // The CSS style to apply to each button icon node
+ iconClass:"icon",
+ //
+ constructor: function(props, node){
+ // props is null from markup
+ dojo.addOnLoad(this, function(){
+ this.domNode = dojo.byId(node);
+ dojo.addClass(this.domNode, this.baseClass);
+ this.parse();
+ });
+ },
+
+ createIcon: function(/*HTMLNode*/node, /* ? Function*/constr){
+ // summary:
+ // Internal. Creates an icon node for each button.
+ // arguments:
+ // node: HTMLNode
+ // The button node.
+ // constr: [optional] Function
+ // Optional. If not supplied, an icon is not created.
+ // Information for each icon is derived from
+ // the ToolsSetup object defined at the end
+ // of each tool. See: stencil._Base
+ //
+ var setup = constr && constr.setup ? constr.setup : {};
+ if(setup.iconClass){
+ var icon = setup.iconClass ? setup.iconClass : "iconNone";
+ var tip = setup.tooltip ? setup.tooltip : "Tool";
+
+ var iNode = dojo.create("div", {title:tip}, node);
+ dojo.addClass(iNode, this.iconClass);
+ dojo.addClass(iNode, icon);
+
+ dojo.connect(node, "mouseup", function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "active");
+ });
+ dojo.connect(node, "mouseover", function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "hover");
+ });
+ dojo.connect(node, "mousedown", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "active");
+ });
+
+ dojo.connect(node, "mouseout", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "hover");
+ });
+ }
+ },
+
+ createTool: function(/*HTMLNode*/node){
+ // summary:
+ // Creates a button on the Toolbar that is
+ // a Tool, not a Plugin. Tools draw Stencils,
+ // Plugins do actions.
+ // arguments:
+ // node: HTMLNode
+ // The button node.
+ //
+ node.innerHTML = "";
+ var type = dojo.attr(node, "tool");
+ this.toolNodes[type] = node;
+ dojo.attr(node, "tabIndex", 1);
+ var constr = dojo.getObject(type);
+
+ this.createIcon(node, constr);
+
+ this.drawing.registerTool(type, constr);
+ dojo.connect(node, "mouseup", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "active");
+ this.onClick(type);
+ });
+ dojo.connect(node, "mouseover", function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "hover");
+ });
+ dojo.connect(node, "mousedown", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "active");
+ });
+
+ dojo.connect(node, "mouseout", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "hover");
+ });
+ },
+
+ parse: function(){
+ // summary:
+ // Initializing method that reads the dom node and its
+ // children for tools and plugins.
+ //
+ var drawingId = dojo.attr(this.domNode, "drawingId");
+ this.drawing = dojox.drawing.util.common.byId(drawingId);
+ !this.drawing && console.error("Drawing not found based on 'drawingId' in Toolbar. ");
+ this.toolNodes = {};
+ var _sel;
+ dojo.query(">", this.domNode).forEach(function(node, i){
+ node.className = this.buttonClass;
+ var tool = dojo.attr(node, "tool");
+ var action = dojo.attr(node, "action");
+ var plugin = dojo.attr(node, "plugin");
+ if(tool){
+ if(i==0 || dojo.attr(node, "selected")=="true"){
+ _sel = tool;
+ }
+ this.createTool(node);
+
+ }else if(plugin){
+
+
+
+
+ var p = {name:plugin, options:{}},
+ opt = dojo.attr(node, "options");
+ if(opt){
+ p.options = eval("("+opt+")");
+ }
+ p.options.node = node;
+ node.innerHTML = "";
+ this.drawing.addPlugin(p);
+
+
+
+
+
+ this.createIcon(node, dojo.getObject(dojo.attr(node, "plugin")));
+ }
+
+ }, this);
+ this.drawing.initPlugins();
+ dojo.connect(this.drawing, "setTool", this, "onSetTool");
+ this.drawing.setTool(_sel);
+ },
+ onClick: function(/*String*/type){
+ // summary:
+ // Event fired from clicking a Tool, not a PLugin.
+ // Plugin clicks are handled within the plugin's class.
+ // arguments:
+ // type: Fully qualified name of class. ex:
+ // dojox.drawing.tools.Ellipse
+ //
+ this.drawing.setTool(type);
+ },
+ onSetTool: function(/*String*/type){
+ // summary:
+ // handles buttons clicks and selects or deselects
+ for(var n in this.toolNodes){
+ if(n == type){
+ dojo.addClass(this.toolNodes[type], "selected");
+ this.toolNodes[type].blur();
+ }else{
+ dojo.removeClass(this.toolNodes[n], "selected");
+ }
+
+ }
+ }
+ });
+
+})();
+});
diff --git a/js/libs/dojox/drawing/ui/dom/Zoom.js b/js/libs/dojox/drawing/ui/dom/Zoom.js
new file mode 100644
index 0000000..36cb560
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/dom/Zoom.js
@@ -0,0 +1,50 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"],function(_1,_2,_3){
+_2.provide("dojox.drawing.ui.dom.Zoom");
+_2.require("dojox.drawing.plugins._Plugin");
+_3.drawing.ui.dom.Zoom=_3.drawing.util.oo.declare(_3.drawing.plugins._Plugin,function(_4){
+var _5=_4.node.className;
+var _6=_4.node.innerHTML;
+this.domNode=_2.create("div",{id:"btnZoom","class":"toolCombo"},_4.node,"replace");
+this.makeButton("ZoomIn",this.topClass);
+this.makeButton("Zoom100",this.midClass);
+this.makeButton("ZoomOut",this.botClass);
+},{type:"dojox.drawing.ui.dom.Zoom",zoomInc:0.1,maxZoom:10,minZoom:0.1,zoomFactor:1,baseClass:"drawingButton",topClass:"toolComboTop",midClass:"toolComboMid",botClass:"toolComboBot",makeButton:function(_7,_8){
+var _9=_2.create("div",{id:"btn"+_7,"class":this.baseClass+" "+_8,innerHTML:""},this.domNode);
+_2.connect(document,"mouseup",function(_a){
+_2.stopEvent(_a);
+_2.removeClass(_9,"active");
+});
+_2.connect(_9,"mouseup",this,function(_b){
+_2.stopEvent(_b);
+_2.removeClass(_9,"active");
+this["on"+_7]();
+});
+_2.connect(_9,"mouseover",function(_c){
+_2.stopEvent(_c);
+_2.addClass(_9,"hover");
+});
+_2.connect(_9,"mousedown",this,function(_d){
+_2.stopEvent(_d);
+_2.addClass(_9,"active");
+});
+_2.connect(_9,"mouseout",this,function(_e){
+_2.stopEvent(_e);
+_2.removeClass(_9,"hover");
+});
+},onZoomIn:function(_f){
+this.zoomFactor+=this.zoomInc;
+this.zoomFactor=Math.min(this.zoomFactor,this.maxZoom);
+this.canvas.setZoom(this.zoomFactor);
+this.mouse.setZoom(this.zoomFactor);
+},onZoom100:function(evt){
+this.zoomFactor=1;
+this.canvas.setZoom(this.zoomFactor);
+this.mouse.setZoom(this.zoomFactor);
+},onZoomOut:function(evt){
+this.zoomFactor-=this.zoomInc;
+this.zoomFactor=Math.max(this.zoomFactor,this.minZoom);
+this.canvas.setZoom(this.zoomFactor);
+this.mouse.setZoom(this.zoomFactor);
+}});
+});
diff --git a/js/libs/dojox/drawing/ui/dom/Zoom.js.uncompressed.js b/js/libs/dojox/drawing/ui/dom/Zoom.js.uncompressed.js
new file mode 100644
index 0000000..39cdab6
--- /dev/null
+++ b/js/libs/dojox/drawing/ui/dom/Zoom.js.uncompressed.js
@@ -0,0 +1,134 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/ui/dom/Zoom", ["dijit","dojo","dojox","dojo/require!dojox/drawing/plugins/_Plugin"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.ui.dom.Zoom");
+dojo.require("dojox.drawing.plugins._Plugin");
+
+dojox.drawing.ui.dom.Zoom = dojox.drawing.util.oo.declare(
+ // NOTE:
+ // dojox.drawing.ui.dom.Zoom is DEPRECATED.
+ // This was a temporary DOM solution. Use the non-dom
+ // tools for Toobar and Plugins.
+ //
+ // summary:
+ // A plugin that allows for zooming the canvas in and out. An
+ // action-tool is added to the toolbar with plus, minus and 100%
+ // buttons.
+ // example:
+ // |
+ //
+ dojox.drawing.plugins._Plugin,
+ function(options){
+ var cls = options.node.className;
+ var txt = options.node.innerHTML;
+ this.domNode = dojo.create("div", {id:"btnZoom", "class":"toolCombo"}, options.node, "replace");
+
+ this.makeButton("ZoomIn", this.topClass);
+ this.makeButton("Zoom100", this.midClass);
+ this.makeButton("ZoomOut", this.botClass);
+
+ },
+ {
+ type:"dojox.drawing.ui.dom.Zoom",
+ //
+ // zoomInc: Float
+ // The amount of zoom that will occur upon each click.
+ zoomInc:.1,
+ //
+ // maxZoom: Number
+ // The maximum the canvas can be zoomed in. 10 = 1000%
+ maxZoom:10,
+ //
+ // minZoom: Float
+ // The most the canvas can be zoomed out. .1 = 10%
+ minZoom:.1,
+ //
+ // zoomFactor: [readonly] Float
+ // The current zoom amount
+ zoomFactor:1,
+ //
+ // baseClass: String
+ // The CSS class added to the Toolbar buttons
+ baseClass:"drawingButton",
+ //
+ // topClass: String
+ // The CSS class added to the top (or left) Toolbar button
+ topClass:"toolComboTop",
+ //
+ // midClass: String
+ // The CSS class added to the middle Toolbar button
+ midClass:"toolComboMid",
+ //
+ // botClass: String
+ // The CSS class added to the bottom (or right) Toolbar button
+ botClass:"toolComboBot",
+ //
+ makeButton: function(name, cls){
+ // summary:
+ // Internal. Creates one of the buttons in the zoom-button set.
+ //
+ var node = dojo.create("div", {id:"btn"+name, "class":this.baseClass+" "+cls,
+ innerHTML:''}, this.domNode);
+
+ dojo.connect(document, "mouseup", function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "active");
+ });
+ dojo.connect(node, "mouseup", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "active");
+ this["on"+name](); // this is what calls the methods below
+ });
+ dojo.connect(node, "mouseover", function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "hover");
+ });
+ dojo.connect(node, "mousedown", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.addClass(node, "active");
+ });
+
+ dojo.connect(node, "mouseout", this, function(evt){
+ dojo.stopEvent(evt);
+ dojo.removeClass(node, "hover");
+ });
+
+ },
+
+ onZoomIn: function(/*Mouse Event*/evt){
+ // summary:
+ // Handles zoom in.
+ //
+ this.zoomFactor += this.zoomInc;
+ this.zoomFactor = Math.min(this.zoomFactor, this.maxZoom);
+ this.canvas.setZoom(this.zoomFactor);
+ this.mouse.setZoom(this.zoomFactor);
+ },
+ onZoom100: function(/*Mouse Event*/evt){
+ // summary:
+ // Zooms to 100%
+ //
+ this.zoomFactor = 1;
+ this.canvas.setZoom(this.zoomFactor);
+ this.mouse.setZoom(this.zoomFactor);
+ },
+ onZoomOut: function(/*Mouse Event*/evt){
+ // summary:
+ // Handles zoom out.
+ //
+ this.zoomFactor -= this.zoomInc;
+ this.zoomFactor = Math.max(this.zoomFactor, this.minZoom);
+ this.canvas.setZoom(this.zoomFactor);
+ this.mouse.setZoom(this.zoomFactor);
+ }
+ }
+);
+
+
+//dojox.drawing.register(dojox.drawing.plugins.tools.Pan, "plugin");
+
+
+});
diff --git a/js/libs/dojox/drawing/util/common.js b/js/libs/dojox/drawing/util/common.js
new file mode 100644
index 0000000..c75d3cc
--- /dev/null
+++ b/js/libs/dojox/drawing/util/common.js
@@ -0,0 +1,106 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/math/round"],function(_1,_2,_3){
+_2.provide("dojox.drawing.util.common");
+_2.require("dojox.math.round");
+(function(){
+var _4={};
+var _5=0;
+_3.drawing.util.common={radToDeg:function(n){
+return (n*180)/Math.PI;
+},degToRad:function(n){
+return (n*Math.PI)/180;
+},angle:function(_6,_7){
+if(_7){
+_7=_7/180;
+var _8=this.radians(_6),_9=Math.PI*_7,_a=_3.math.round(_8/_9),_b=_a*_9;
+return _3.math.round(this.radToDeg(_b));
+}else{
+return this.radToDeg(this.radians(_6));
+}
+},oppAngle:function(_c){
+(_c+=180)>360?_c=_c-360:_c;
+return _c;
+},radians:function(o){
+return Math.atan2(o.start.y-o.y,o.x-o.start.x);
+},length:function(o){
+return Math.sqrt(Math.pow(o.start.x-o.x,2)+Math.pow(o.start.y-o.y,2));
+},lineSub:function(x1,y1,x2,y2,_d){
+var _e=this.distance(this.argsToObj.apply(this,arguments));
+_e=_e<_d?_d:_e;
+var pc=(_e-_d)/_e;
+var x=x1-(x1-x2)*pc;
+var y=y1-(y1-y2)*pc;
+return {x:x,y:y};
+},argsToObj:function(){
+var a=arguments;
+if(a.length<4){
+return a[0];
+}
+return {start:{x:a[0],y:a[1]},x:a[2],y:a[3]};
+},distance:function(){
+var o=this.argsToObj.apply(this,arguments);
+return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x,2)+Math.pow(o.start.y-o.y,2)));
+},slope:function(p1,p2){
+if(!(p1.x-p2.x)){
+return 0;
+}
+return ((p1.y-p2.y)/(p1.x-p2.x));
+},pointOnCircle:function(cx,cy,_f,_10){
+var _11=_10*Math.PI/180;
+var x=_f*Math.cos(_11);
+var y=_f*Math.sin(_11);
+return {x:cx+x,y:cy-y};
+},constrainAngle:function(obj,min,max){
+var _12=this.angle(obj);
+if(_12>=min&&_12<=max){
+return obj;
+}
+var _13=this.length(obj);
+var _14=_12>max?max:min-_12<100?min:max;
+return this.pointOnCircle(obj.start.x,obj.start.y,_13,_14);
+},snapAngle:function(obj,ca){
+var _15=this.radians(obj),_16=this.length(obj),seg=Math.PI*ca,rnd=Math.round(_15/seg),_17=rnd*seg,_18=this.radToDeg(_17),pt=this.pointOnCircle(obj.start.x,obj.start.y,_16,_18);
+return pt;
+},idSetStart:function(num){
+_5=num;
+},uid:function(str){
+str=str||"shape";
+_4[str]=_4[str]===undefined?_5:_4[str]+1;
+return str+_4[str];
+},abbr:function(_19){
+return _19.substring(_19.lastIndexOf(".")+1).charAt(0).toLowerCase()+_19.substring(_19.lastIndexOf(".")+2);
+},mixin:function(o1,o2){
+},objects:{},register:function(obj){
+this.objects[obj.id]=obj;
+},byId:function(id){
+return this.objects[id];
+},attr:function(_1a,_1b,_1c,_1d){
+if(!_1a){
+return false;
+}
+try{
+if(_1a.shape&&_1a.util){
+_1a=_1a.shape;
+}
+if(!_1c&&_1b=="id"&&_1a.target){
+var n=_1a.target;
+while(!_2.attr(n,"id")){
+n=n.parentNode;
+}
+return _2.attr(n,"id");
+}
+if(_1a.rawNode||_1a.target){
+var _1e=Array.prototype.slice.call(arguments);
+_1e[0]=_1a.rawNode||_1a.target;
+return _2.attr.apply(_2,_1e);
+}
+return _2.attr(_1a,"id");
+}
+catch(e){
+if(!_1d){
+}
+return false;
+}
+}};
+})();
+});
diff --git a/js/libs/dojox/drawing/util/common.js.uncompressed.js b/js/libs/dojox/drawing/util/common.js.uncompressed.js
new file mode 100644
index 0000000..af740a0
--- /dev/null
+++ b/js/libs/dojox/drawing/util/common.js.uncompressed.js
@@ -0,0 +1,284 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/util/common", ["dijit","dojo","dojox","dojo/require!dojox/math/round"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.util.common");
+dojo.require("dojox.math.round");
+
+(function(){
+
+ var uidMap = {};
+ var start = 0;
+ dojox.drawing.util.common = {
+ // summary:
+ // A collection of common methods used for DojoX Drawing.
+ // This singleton is accessible in most Drawing classes
+ // as this.util
+ //
+ // NOTE:
+ // A lot of functions use a EventObject
+ // as an argument. An attempt was made to accept
+ // either that object or a list of numbers. That wasn't
+ // finished (it didn't work well in all cases) but is
+ // likely to happen in the future.
+ // In cases where you are not sending a Mouse object,
+ // form your argument like so:
+ // var obj = {
+ // start:{
+ // x:Number, // start x
+ // y:Number // start y
+ // },
+ // x: Number, // end x
+ // y:Number // end y
+ // }
+ //
+ //
+ radToDeg: function(/*Numer*/n){
+ // summary:
+ // Convert the passed number to degrees.
+ return (n*180)/Math.PI; // Number
+ },
+
+ degToRad: function(/*Numer*/n){
+ // summary:
+ // Convert the passed number to radians.
+ return (n*Math.PI)/180; // Number
+ },
+
+ angle: function(/*EventObject*/obj, /* ? Float */snap){
+ // summary:
+ // Return angle based on mouse object
+ // arguments:
+ // obj: EventObject
+ // Manager.Mouse event.
+ // snap: Float
+ // Returns nearest angle within snap limits
+ //
+ //obj = this.argsToObj.apply(this, arguments);
+ if(snap){
+ snap = snap/180;
+ var radians = this.radians(obj),
+ seg = Math.PI * snap,
+ rnd = dojox.math.round(radians/seg),
+ new_radian = rnd*seg;
+ return dojox.math.round(this.radToDeg(new_radian)); // Whole Number
+
+ }else{
+ return this.radToDeg(this.radians(obj)); // Float
+ }
+ },
+
+ oppAngle: function(/*Angle*/ang){
+ (ang+=180) > 360 ? ang = ang - 360 : ang;
+ return ang;
+ },
+
+ radians: function(/*EventObject*/o){
+ // summary:
+ // Return the radians derived from the coordinates
+ // in the Mouse object.
+ //
+ //var o = this.argsToObj.apply(this, arguments);
+ return Math.atan2(o.start.y-o.y,o.x-o.start.x);
+ },
+
+ length: function(/*EventObject*/o){
+ // summary:
+ // Return the length derived from the coordinates
+ // in the Mouse object.
+ //
+ return Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2));
+ },
+
+ lineSub: function(/*Number*/x1, /*Number*/y1, /*Number*/x2, /*Number*/y2, /*Number*/amt){
+ // summary:
+ // Subtract an amount from a line
+ // description:
+ // x1,y1,x2,y2 represents the Line. 'amt' represents the amount
+ // to subtract from it.
+ //
+ var len = this.distance(this.argsToObj.apply(this, arguments));
+ len = len < amt ? amt : len;
+ var pc = (len-amt)/len;
+ var x = x1 - (x1-x2) * pc;
+ var y = y1 - (y1-y2) * pc;
+ return {x:x, y:y}; // Object
+ },
+
+ argsToObj: function(){
+ // summary:
+ // Attempts to determine in a Mouse Object
+ // was passed or indiviual numbers. Returns
+ // an object.
+ //
+ var a = arguments;
+ if(a.length < 4){ return a[0]; }
+ return {
+ start:{
+ x:a[0],
+ y:a[1]
+ },
+ x:a[2],
+ y:a[3]//,
+ //snap:a[4]
+ }; // Object
+ },
+
+ distance: function(/*EventObject or x1,y1,x2,y2*/){
+ // summary:
+ // Return the length derived from the coordinates
+ // in the Mouse object. Different from util.length
+ // in that this always returns an absolute value.
+ //
+ var o = this.argsToObj.apply(this, arguments);
+ return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2))); // Number
+ },
+
+ slope:function(/*Object*/p1, /*Object*/p2){
+ // summary:
+ // Given two poits of a line, returns the slope.
+ if(!(p1.x-p2.x)){ return 0; }
+ return ((p1.y-p2.y)/(p1.x-p2.x)); // Number
+ },
+
+ pointOnCircle: function(/*Number*/cx, /*Number*/cy, /*Number*/radius, /*Number*/angle){
+ // summary:
+ // A *very* helpful method. If you know the center
+ // (or starting) point, length and angle, find the
+ // x,y point at the end of that line.
+ //
+ var radians = angle * Math.PI / 180.0;
+ var x = radius * Math.cos(radians);
+ var y = radius * Math.sin(radians);
+ return {
+ x:cx+x,
+ y:cy-y
+ }; // Object
+ },
+
+ constrainAngle: function(/*EventObject*/obj, /*Number*/min, /*Number*/max){
+ // summary:
+ // Ensures the angle in the Mouse Object is within the
+ // min and max limits. If not one of those limits is used.
+ // Returns an x,y point for the angle used.
+ //
+ var angle = this.angle(obj);
+ if(angle >= min && angle <= max){
+ return obj; // Object
+ }
+ var radius = this.length(obj);
+ var new_angle = angle > max ? max : min - angle < 100 ? min : max;
+ return this.pointOnCircle(obj.start.x,obj.start.y,radius, new_angle); // Object
+ },
+
+ snapAngle: function(/*EventObject*/obj, /*Float*/ca){
+ // summary:
+ // Snaps a line to the nearest angle
+ // obj: Mouse object (see dojox.drawing.Mouse)
+ // ca: Fractional amount to snap to
+ // A decimal number fraction of a half circle
+ // .5 would snap to 90 degrees
+ // .25 would snap to 45 degrees
+ // .125 would snap to 22.5 degrees, etc.
+ //
+ var radians = this.radians(obj),
+ radius = this.length(obj),
+ seg = Math.PI * ca,
+ rnd = Math.round(radians/seg),
+ new_radian = rnd*seg,
+ new_angle = this.radToDeg(new_radian),
+ pt = this.pointOnCircle(obj.start.x,obj.start.y,radius,new_angle);
+ return pt; // Object
+ },
+
+ // helpers
+ idSetStart: function(num){
+ start=num;
+ },
+
+ uid: function(/* ? String */str){
+ // summary:
+ // Creates a unique ID.
+ // arguments:
+ // str: String
+ // If provided, kept in a map, incremented
+ // and used in the id. Otherwise 'shape' is used.
+ //
+ str = str || "shape";
+ uidMap[str] = uidMap[str]===undefined ? start : uidMap[str] + 1;
+ return str + uidMap[str]; // String
+ },
+
+ abbr: function(type){
+ // summary:
+ // Converts a namespace (typically a tool or a stencil) into
+ // an abbreviation
+ return type.substring(type.lastIndexOf(".")+1).charAt(0).toLowerCase()
+ + type.substring(type.lastIndexOf(".")+2);
+ },
+ mixin: function(o1, o2){
+ // TODO: make faster
+ //return dojo.mixin(dojo.clone(o1), dojo.clone(o2));
+ },
+
+ objects:{}, //private?
+ register: function(/*Object*/obj){
+ // summary:
+ // Since util is the only Singleton in Drawing (besides
+ // keys) it is used to help connect the Drawing object
+ // the Toolbar. Since multiple drawings can be on one
+ // page, this function serves a little more use than
+ // on first apearance.
+ this.objects[obj.id] = obj;
+ },
+ byId: function(/*String*/id){
+ // summary:
+ // Get an object that was registered with util.register
+ //
+ return this.objects[id];
+ },
+ attr: function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){
+ // summary:
+ // Helper function to attach attributes to SVG and VML raw nodes.
+ //
+
+ if(!elem){ return false; }
+ try{
+
+ // util is a crappy check, but we need to tell the diff
+ // between a Drawing shape and a GFX shape
+ if(elem.shape && elem.util){
+ elem = elem.shape;
+ }
+
+ if(!value && prop=="id" && elem.target){
+
+ var n = elem.target;
+ while(!dojo.attr(n, "id")){
+ n = n.parentNode;
+ }
+ return dojo.attr(n, "id");
+ }
+
+ if(elem.rawNode || elem.target){
+ var args = Array.prototype.slice.call(arguments);
+ args[0] = elem.rawNode || elem.target;
+ return dojo.attr.apply(dojo, args);
+ }
+ return dojo.attr(elem, "id");
+
+
+
+ }catch(e){
+ if(!squelchErrors){
+ // For debugging only. These errors actually cause errors in IE's console
+ //console.error("BAD ATTR: prop:", prop, "el:", elem)
+ //console.error(e)
+ //console.trace();
+ }
+ return false;
+ }
+ }
+ };
+
+})();
+});
diff --git a/js/libs/dojox/drawing/util/oo.js b/js/libs/dojox/drawing/util/oo.js
new file mode 100644
index 0000000..3ec89a5
--- /dev/null
+++ b/js/libs/dojox/drawing/util/oo.js
@@ -0,0 +1,47 @@
+//>>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.util.oo");
+_3.drawing.util.oo={declare:function(){
+var f,o,_4=0,a=arguments;
+if(a.length<2){
+console.error("drawing.util.oo.declare; not enough arguments");
+}
+if(a.length==2){
+f=a[0];
+o=a[1];
+}else{
+a=Array.prototype.slice.call(arguments);
+o=a.pop();
+f=a.pop();
+_4=1;
+}
+for(var n in o){
+f.prototype[n]=o[n];
+}
+if(_4){
+a.unshift(f);
+f=this.extend.apply(this,a);
+}
+return f;
+},extend:function(){
+var a=arguments,_5=a[0];
+if(a.length<2){
+console.error("drawing.util.oo.extend; not enough arguments");
+}
+var f=function(){
+for(var i=1;i>built
+// wrapped by build app
+define("dojox/drawing/util/oo", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.util.oo");
+
+// TODO:
+// allow a declare without a mixin
+
+dojox.drawing.util.oo = {
+ // summary:
+ // Inheritance utilities used in DojoX Drawing
+ // description:
+ // Inheritance utilities used in DojoX Drawing.
+ // There were designed in a effort to make Drawing as
+ // fast as possible - especially in a case where thousands
+ // of objects are being loaded. Drawing declare performs
+ // about 3 times faster than Dojo declare and 2 times
+ // faster than Dojox declare. This is not to say Drawing
+ // declare is wthout limitations. It doesn't have the same
+ // syntatic sugar and extensibility of the other two. You
+ // can't inhert methods. It won't work with Dijit. But it
+ // is simple and effective.
+ //
+ declare: function(){
+ // summary:
+ // Creates a constructor Function from a
+ // Function, and collection of methods, and
+ // more Functions that are extended.
+ // description:
+ // Similar in look and feel to Dojo declare as
+ // far as order and number of arguments, although
+ // constructed a little closer to prototypical
+ // inheritance. All arguments passed into the
+ // constructor are passed into all sub constructors.
+ // arguments:
+ // Function, [Object|Function....]
+ // The first argument is always the base
+ // constructor. The last argument is always
+ // an object of methods (or empty object) to
+ // be mixed in (in the future would like to
+ // make that object optional). Remaining
+ // arguments are other constructors mixed in
+ // using extend() (See below).
+ // example:
+ // | MyFunction = dojox.drawing.util.oo.declare(
+ // | MyOtherFunction,
+ // | YetAnotherFunction,
+ // | function(options){
+ // | // This is my constructor. It will fire last.
+ // | // The other constructors will fire before this.
+ // | },
+ // | {
+ // | customType:"equation", // mixed in property
+ // | doThing: function(){ // mixed in method
+ // |
+ // | }
+ // | }
+ // | );
+ // |
+ // | var f = new MyFunction();
+ //
+ var f, o, ext=0, a = arguments;
+
+ if(a.length<2){ console.error("drawing.util.oo.declare; not enough arguments")}
+ if(a.length==2){
+ f = a[0]; o = a[1];
+ }else{
+ a = Array.prototype.slice.call(arguments);
+ o = a.pop();
+ f = a.pop();
+ ext = 1;
+ }
+ for(var n in o){
+ f.prototype[n] = o[n];
+ }
+ if(ext){
+ a.unshift(f);
+ f = this.extend.apply(this, a);
+ }
+ return f; // Function
+ },
+ extend: function(){
+ // summary:
+ // Extends constructors to inherit from other
+ // constructors .
+ // description:
+ // Typically not used by itself - it's used as
+ // part of declare(). Could be used by itself
+ // however, to mix together two or more
+ // constructors.
+ // arguments:
+ // Function, [ Function...]
+ // Any number of arguments, all must be
+ // function constructors. The first is
+ // considered the base object and its
+ // constructor will fire first.
+ // example:
+ // | var A = function(){};
+ // | var B = function(){};
+ // | var C = function(){};
+ // | var D = dojox.drawing.util.oo.extend(A, B, C);
+ // | var e = new D();
+ //
+ var a = arguments, sub = a[0];
+ if(a.length<2){ console.error("drawing.util.oo.extend; not enough arguments")}
+ var f = function (){
+ for(var i=1;i>built
+define(["dijit","dojo","dojox"],function(_1,_2,_3){
+_2.provide("dojox.drawing.util.positioning");
+(function(){
+var _4=4;
+var _5=20;
+_3.drawing.util.positioning.label=function(_6,_7){
+var x=0.5*(_6.x+_7.x);
+var y=0.5*(_6.y+_7.y);
+var _8=_3.drawing.util.common.slope(_6,_7);
+var _9=_4/Math.sqrt(1+_8*_8);
+if(_7.y>_6.y&&_7.x>_6.x||_7.y<_6.y&&_7.x<_6.x){
+_9=-_9;
+y-=_5;
+}
+x+=-_9*_8;
+y+=_9;
+var _a=_7.x<_6.x?"end":"start";
+return {x:x,y:y,foo:"bar",align:_a};
+};
+_3.drawing.util.positioning.angle=function(_b,_c){
+var x=0.7*_b.x+0.3*_c.x;
+var y=0.7*_b.y+0.3*_c.y;
+var _d=_3.drawing.util.common.slope(_b,_c);
+var _e=_4/Math.sqrt(1+_d*_d);
+if(_c.x<_b.x){
+_e=-_e;
+}
+x+=-_e*_d;
+y+=_e;
+var _f=_c.y>_b.y?"end":"start";
+y+=_c.x>_b.x?0.5*_5:-0.5*_5;
+return {x:x,y:y,align:_f};
+};
+})();
+});
diff --git a/js/libs/dojox/drawing/util/positioning.js.uncompressed.js b/js/libs/dojox/drawing/util/positioning.js.uncompressed.js
new file mode 100644
index 0000000..13afcad
--- /dev/null
+++ b/js/libs/dojox/drawing/util/positioning.js.uncompressed.js
@@ -0,0 +1,69 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/util/positioning", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.util.positioning");
+
+(function(){
+
+ var textOffset = 4; // distance from line to text box
+ var textYOffset = 20; // height of text box
+
+
+ dojox.drawing.util.positioning.label = function(/*Object*/start, /*Object*/end){
+ // summary:
+ // Returns the optimal text positions for annotations.Label.
+
+ // label at middle of vector
+ var x = 0.5*(start.x+end.x);
+ var y = 0.5*(start.y+end.y);
+
+ // move label a set distance from the line
+ var slope = dojox.drawing.util.common.slope(start, end);
+ var deltay = textOffset/Math.sqrt(1.0+slope*slope);
+
+ if(end.y>start.y && end.x>start.x || end.ystart.y ? "end" : "start";
+ // box vertical aligned from middle
+ y += end.x > start.x ? 0.5*textYOffset : -0.5*textYOffset;
+
+ return { x:x, y:y, align:align}; // Object
+ }
+
+})();
+
+
+
+
+});
diff --git a/js/libs/dojox/drawing/util/typeset.js b/js/libs/dojox/drawing/util/typeset.js
new file mode 100644
index 0000000..c7ce04c
--- /dev/null
+++ b/js/libs/dojox/drawing/util/typeset.js
@@ -0,0 +1,48 @@
+//>>built
+define(["dijit","dojo","dojox","dojo/require!dojox/drawing/library/greek"],function(_1,_2,_3){
+_2.provide("dojox.drawing.util.typeset");
+_2.require("dojox.drawing.library.greek");
+(function(){
+var _4=_3.drawing.library.greek;
+_3.drawing.util.typeset={convertHTML:function(_5){
+if(_5){
+return _5.replace(/&([^;]+);/g,function(_6,_7){
+if(_7.charAt(0)=="#"){
+var _8=+_7.substr(1);
+if(!isNaN(_8)){
+return String.fromCharCode(_8);
+}
+}else{
+if(_4[_7]){
+return String.fromCharCode(_4[_7]);
+}
+}
+console.warn("no HTML conversion for ",_6);
+return _6;
+});
+}
+return _5;
+},convertLaTeX:function(_9){
+if(_9){
+return _9.replace(/\\([a-zA-Z]+)/g,function(_a,_b){
+if(_4[_b]){
+return String.fromCharCode(_4[_b]);
+}else{
+if(_b.substr(0,2)=="mu"){
+return String.fromCharCode(_4["mu"])+_b.substr(2);
+}else{
+if(_b.substr(0,5)=="theta"){
+return String.fromCharCode(_4["theta"])+_b.substr(5);
+}else{
+if(_b.substr(0,3)=="phi"){
+return String.fromCharCode(_4["phi"])+_b.substr(3);
+}
+}
+}
+}
+}).replace(/\\\\/g,"\\");
+}
+return _9;
+}};
+})();
+});
diff --git a/js/libs/dojox/drawing/util/typeset.js.uncompressed.js b/js/libs/dojox/drawing/util/typeset.js.uncompressed.js
new file mode 100644
index 0000000..c9c81c1
--- /dev/null
+++ b/js/libs/dojox/drawing/util/typeset.js.uncompressed.js
@@ -0,0 +1,72 @@
+//>>built
+// wrapped by build app
+define("dojox/drawing/util/typeset", ["dijit","dojo","dojox","dojo/require!dojox/drawing/library/greek"], function(dijit,dojo,dojox){
+dojo.provide("dojox.drawing.util.typeset");
+dojo.require("dojox.drawing.library.greek");
+// Summary:
+// Singleton used for converting characters and typsetting. Required by _base.
+//
+// Description:
+// Eventually, this is supposed to turn input strings of mathematical
+// expressions into typeset expressions that can be displayed on the
+// canvas. For now, we just generate Greek letters based on LaTeX style
+// entity codes.
+
+(function(){
+
+ var greeks = dojox.drawing.library.greek;
+
+ dojox.drawing.util.typeset = {
+
+ convertHTML: function(inText){
+ if(inText){
+ return inText.replace(/&([^;]+);/g,function(match,code){
+ if(code.charAt(0)=='#'){
+ //coerce remainder of string to int
+ var number=+code.substr(1);
+ if(!isNaN(number)){
+ return String.fromCharCode(number);
+ }
+ }else if(greeks[code]){
+ return String.fromCharCode(greeks[code]);
+ }
+ // This is generally for server code, so there
+ // is no point bothering the user in the case of an error.
+ console.warn("no HTML conversion for ",match);
+ return match;
+ });
+ }
+ return inText;
+ },
+
+ convertLaTeX: function(inText){
+ // console.log("***** convertLaTeX for ",inText);
+ if(inText){
+ return inText.replace(/\\([a-zA-Z]+)/g,function(match,word){
+ if(greeks[word]){
+ return String.fromCharCode(greeks[word]);
+ }else if(word.substr(0,2)=="mu"){
+ // special handling for \mu since it is
+ // a unit prefix for micro.
+ return String.fromCharCode(greeks["mu"])+word.substr(2);
+ }else if(word.substr(0,5)=="theta"){
+ // special handling for \theta since it is
+ // a standard prefix for angle associated with a vector.
+ return String.fromCharCode(greeks["theta"])+word.substr(5);
+ }else if(word.substr(0,3)=="phi"){
+ // special handling for \phi since it is
+ // a standard prefix for angle associated with a z-axis vector.
+ return String.fromCharCode(greeks["phi"])+word.substr(3);
+ }
+ console.log("no match for ",match," in ",inText);
+ console.log("Need user-friendly error handling here!");
+ }).replace(/\\\\/g,'\\');
+ }
+ return inText;
+ }
+
+ };
+
+})();
+
+});
diff --git a/js/libs/dojox/dtl.js b/js/libs/dojox/dtl.js
new file mode 100644
index 0000000..d6f7fef
--- /dev/null
+++ b/js/libs/dojox/dtl.js
@@ -0,0 +1,15 @@
+/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+/*
+ This is an optimized version of Dojo, built for deployment and not for
+ development. To get sources and documentation, please visit:
+
+ http://dojotoolkit.org
+*/
+
+//>>built
+require({cache:{"dojox/dtl/_base":function(){define(["dojo/_base/kernel","dojo/_base/lang","dojox/string/tokenize","dojo/_base/json","dojo/dom","dojo/_base/xhr","dojox/string/Builder","dojo/_base/Deferred"],function(_1,_2,_3,_4,_5,_6,_7,_8){_1.experimental("dojox.dtl");var dd=_2.getObject("dojox.dtl",true);dd._base={};dd.TOKEN_BLOCK=-1;dd.TOKEN_VAR=-2;dd.TOKEN_COMMENT=-3;dd.TOKEN_TEXT=3;dd._Context=_2.extend(function(_9){if(_9){_2._mixin(this,_9);if(_9.get){this._getter=_9.get;delete this.get;}}},{push:function(){var _a=this;var _b=_2.delegate(this);_b.pop=function(){return _a;};return _b;},pop:function(){throw new Error("pop() called on empty Context");},get:function(_c,_d){var n=this._normalize;if(this._getter){var _e=this._getter(_c);if(_e!==undefined){return n(_e);}}if(this[_c]!==undefined){return n(this[_c]);}return _d;},_normalize:function(_f){if(_f instanceof Date){_f.year=_f.getFullYear();_f.month=_f.getMonth()+1;_f.day=_f.getDate();_f.date=_f.year+"-"+("0"+_f.month).slice(-2)+"-"+("0"+_f.day).slice(-2);_f.hour=_f.getHours();_f.minute=_f.getMinutes();_f.second=_f.getSeconds();_f.microsecond=_f.getMilliseconds();}return _f;},update:function(_10){var _11=this.push();if(_10){_2._mixin(this,_10);}return _11;}});var _12=/("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;var _13=/\s+/g;var _14=function(_15,_16){_15=_15||_13;if(!(_15 instanceof RegExp)){_15=new RegExp(_15,"g");}if(!_15.global){throw new Error("You must use a globally flagged RegExp with split "+_15);}_15.exec("");var _17,_18=[],_19=0,i=0;while((_17=_15.exec(this))){_18.push(this.slice(_19,_15.lastIndex-_17[0].length));_19=_15.lastIndex;if(_16&&(++i>_16-1)){break;}}_18.push(this.slice(_19));return _18;};dd.Token=function(_1a,_1b){this.token_type=_1a;this.contents=new String(_2.trim(_1b));this.contents.split=_14;this.split=function(){return String.prototype.split.apply(this.contents,arguments);};};dd.Token.prototype.split_contents=function(_1c){var bit,_1d=[],i=0;_1c=_1c||999;while(i++<_1c&&(bit=_12.exec(this.contents))){bit=bit[0];if(bit.charAt(0)=="\""&&bit.slice(-1)=="\""){_1d.push("\""+bit.slice(1,-1).replace("\\\"","\"").replace("\\\\","\\")+"\"");}else{if(bit.charAt(0)=="'"&&bit.slice(-1)=="'"){_1d.push("'"+bit.slice(1,-1).replace("\\'","'").replace("\\\\","\\")+"'");}else{_1d.push(bit);}}}return _1d;};var ddt=dd.text={_get:function(_1e,_1f,_20){var _21=dd.register.get(_1e,_1f.toLowerCase(),_20);if(!_21){if(!_20){throw new Error("No tag found for "+_1f);}return null;}var fn=_21[1];var _22=_21[2];var _23;if(fn.indexOf(":")!=-1){_23=fn.split(":");fn=_23.pop();}var mod=_22;if(/\./.test(_22)){_22=_22.replace(/\./g,"/");}require([_22],function(){});var _24=_2.getObject(mod);return _24[fn||_1f]||_24[_1f+"_"]||_24[fn+"_"];},getTag:function(_25,_26){return ddt._get("tag",_25,_26);},getFilter:function(_27,_28){return ddt._get("filter",_27,_28);},getTemplate:function(_29){return new dd.Template(ddt.getTemplateString(_29));},getTemplateString:function(_2a){return _6._getText(_2a.toString())||"";},_resolveLazy:function(_2b,_2c,_2d){if(_2c){if(_2d){return _2d.fromJson(_6._getText(_2b))||{};}else{return dd.text.getTemplateString(_2b);}}else{return _6.get({handleAs:_2d?"json":"text",url:_2b});}},_resolveTemplateArg:function(arg,_2e){if(ddt._isTemplate(arg)){if(!_2e){var d=new _8();d.callback(arg);return d;}return arg;}return ddt._resolveLazy(arg,_2e);},_isTemplate:function(arg){return (arg===undefined)||(typeof arg=="string"&&(arg.match(/^\s*[<{]/)||arg.indexOf(" ")!=-1));},_resolveContextArg:function(arg,_2f){if(arg.constructor==Object){if(!_2f){var d=new _8;d.callback(arg);return d;}return arg;}return ddt._resolveLazy(arg,_2f,true);},_re:/(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,tokenize:function(str){return _3(str,ddt._re,ddt._parseDelims);},_parseDelims:function(_30,_31,tag){if(_30){return [dd.TOKEN_VAR,_30];}else{if(_31){var _32=_2.trim(tag).split(/\s+/g);for(var i=0,_33;_33=_32[i];i++){if(/\./.test(_33)){_33=_33.replace(/\./g,"/");}require([_33]);}}else{return [dd.TOKEN_BLOCK,tag];}}}};dd.Template=_2.extend(function(_34,_35){var str=_35?_34:ddt._resolveTemplateArg(_34,true)||"";var _36=ddt.tokenize(str);var _37=new dd._Parser(_36);this.nodelist=_37.parse();},{update:function(_38,_39){return ddt._resolveContextArg(_39).addCallback(this,function(_3a){var _3b=this.render(new dd._Context(_3a));if(_38.forEach){_38.forEach(function(_3c){_3c.innerHTML=_3b;});}else{_5.byId(_38).innerHTML=_3b;}return this;});},render:function(_3d,_3e){_3e=_3e||this.getBuffer();_3d=_3d||new dd._Context({});return this.nodelist.render(_3d,_3e)+"";},getBuffer:function(){return new _7();}});var _3f=/\{\{\s*(.+?)\s*\}\}/g;dd.quickFilter=function(str){if(!str){return new dd._NodeList();}if(str.indexOf("{%")==-1){return new dd._QuickNodeList(_3(str,_3f,function(_40){return new dd._Filter(_40);}));}};dd._QuickNodeList=_2.extend(function(_41){this.contents=_41;},{render:function(_42,_43){for(var i=0,l=this.contents.length;i/g;var _80=/'/g;var _81=/"/g;dd._base.escape=function(_82){return dd.mark_safe(_82.replace(_7d,"&").replace(_7e,"<").replace(_7f,">").replace(_81,""").replace(_80,"'"));};dd._base.safe=function(_83){if(typeof _83=="string"){_83=new String(_83);}if(typeof _83=="object"){_83.safe=true;}return _83;};dd.mark_safe=dd._base.safe;dd.register.tags("dojox.dtl.tag",{"date":["now"],"logic":["if","for","ifequal","ifnotequal"],"loader":["extends","block","include","load","ssi"],"misc":["comment","debug","filter","firstof","spaceless","templatetag","widthratio","with"],"loop":["cycle","ifchanged","regroup"]});dd.register.filters("dojox.dtl.filter",{"dates":["date","time","timesince","timeuntil"],"htmlstrings":["linebreaks","linebreaksbr","removetags","striptags"],"integers":["add","get_digit"],"lists":["dictsort","dictsortreversed","first","join","length","length_is","random","slice","unordered_list"],"logic":["default","default_if_none","divisibleby","yesno"],"misc":["filesizeformat","pluralize","phone2numeric","pprint"],"strings":["addslashes","capfirst","center","cut","fix_ampersands","floatformat","iriencode","linenumbers","ljust","lower","make_list","rjust","slugify","stringformat","title","truncatewords","truncatewords_html","upper","urlencode","urlize","urlizetrunc","wordcount","wordwrap"]});dd.register.filters("dojox.dtl",{"_base":["escape","safe"]});return dd;});},"dojox/dtl/tag/loader":function(){define("dojox/dtl/tag/loader",["dojo/_base/lang","../_base","dojo/_base/array","dojo/_base/connect"],function(_84,dd,_85,_86){_84.getObject("dojox.dtl.tag.loader",true);var _87=dd.tag.loader;_87.BlockNode=_84.extend(function(_88,_89){this.name=_88;this.nodelist=_89;},{"super":function(){if(this.parent){var _8a=this.parent.nodelist.dummyRender(this.context,null,true);if(typeof _8a=="string"){_8a=new String(_8a);}_8a.safe=true;return _8a;}return "";},render:function(_8b,_8c){var _8d=this.name;var _8e=this.nodelist;var _8f;if(_8c.blocks){var _90=_8c.blocks[_8d];if(_90){_8f=_90.parent;_8e=_90.nodelist;_90.used=true;}}this.rendered=_8e;_8b=_8b.push();this.context=_8b;this.parent=null;if(_8e!=this.nodelist){this.parent=this;}_8b.block=this;if(_8c.getParent){var _91=_8c.getParent();var _92=_86.connect(_8c,"onSetParent",function(_93,up,_94){if(up&&_94){_8c.setParent(_91);}});}_8c=_8e.render(_8b,_8c,this);_92&&_86.disconnect(_92);_8b=_8b.pop();return _8c;},unrender:function(_95,_96){return this.rendered.unrender(_95,_96);},clone:function(_97){return new this.constructor(this.name,this.nodelist.clone(_97));},toString:function(){return "dojox.dtl.tag.loader.BlockNode";}});_87.ExtendsNode=_84.extend(function(_98,_99,_9a,_9b,key){this.getTemplate=_98;this.nodelist=_99;this.shared=_9a;this.parent=_9b;this.key=key;},{parents:{},getParent:function(_9c){var _9d=this.parent;if(!_9d){var _9e;_9d=this.parent=_9c.get(this.key,false);if(!_9d){throw new Error("extends tag used a variable that did not resolve");}if(typeof _9d=="object"){var url=_9d.url||_9d.templatePath;if(_9d.shared){this.shared=true;}if(url){_9d=this.parent=url.toString();}else{if(_9d.templateString){_9e=_9d.templateString;_9d=this.parent=" ";}else{_9d=this.parent=this.parent.toString();}}}if(_9d&&_9d.indexOf("shared:")===0){this.shared=true;_9d=this.parent=_9d.substring(7,_9d.length);}}if(!_9d){throw new Error("Invalid template name in 'extends' tag.");}if(_9d.render){return _9d;}if(this.parents[_9d]){return this.parents[_9d];}this.parent=this.getTemplate(_9e||dojox.dtl.text.getTemplateString(_9d));if(this.shared){this.parents[_9d]=this.parent;}return this.parent;},render:function(_9f,_a0){var _a1=this.getParent(_9f);_a1.blocks=_a1.blocks||{};_a0.blocks=_a0.blocks||{};for(var i=0,_a2;_a2=this.nodelist.contents[i];i++){if(_a2 instanceof dojox.dtl.tag.loader.BlockNode){var old=_a1.blocks[_a2.name];if(old&&old.nodelist!=_a2.nodelist){_a0=old.nodelist.unrender(_9f,_a0);}_a1.blocks[_a2.name]=_a0.blocks[_a2.name]={shared:this.shared,nodelist:_a2.nodelist,used:false};}}this.rendered=_a1;return _a1.nodelist.render(_9f,_a0,this);},unrender:function(_a3,_a4){return this.rendered.unrender(_a3,_a4,this);},toString:function(){return "dojox.dtl.block.ExtendsNode";}});_87.IncludeNode=_84.extend(function(_a5,_a6,_a7,_a8,_a9){this._path=_a5;this.constant=_a6;this.path=(_a6)?_a5:new dd._Filter(_a5);this.getTemplate=_a7;this.text=_a8;this.parsed=(arguments.length==5)?_a9:true;},{_cache:[{},{}],render:function(_aa,_ab){var _ac=((this.constant)?this.path:this.path.resolve(_aa)).toString();var _ad=Number(this.parsed);var _ae=false;if(_ac!=this.last){_ae=true;if(this.last){_ab=this.unrender(_aa,_ab);}this.last=_ac;}var _af=this._cache[_ad];if(_ad){if(!_af[_ac]){_af[_ac]=dd.text._resolveTemplateArg(_ac,true);}if(_ae){var _b0=this.getTemplate(_af[_ac]);this.rendered=_b0.nodelist;}return this.rendered.render(_aa,_ab,this);}else{if(this.text instanceof dd._TextNode){if(_ae){this.rendered=this.text;this.rendered.set(dd.text._resolveTemplateArg(_ac,true));}return this.rendered.render(_aa,_ab);}else{if(!_af[_ac]){var _b1=[];var div=document.createElement("div");div.innerHTML=dd.text._resolveTemplateArg(_ac,true);var _b2=div.childNodes;while(_b2.length){var _b3=div.removeChild(_b2[0]);_b1.push(_b3);}_af[_ac]=_b1;}if(_ae){this.nodelist=[];var _b4=true;for(var i=0,_b5;_b5=_af[_ac][i];i++){this.nodelist.push(_b5.cloneNode(true));}}for(var i=0,_b6;_b6=this.nodelist[i];i++){_ab=_ab.concat(_b6);}}}return _ab;},unrender:function(_b7,_b8){if(this.rendered){_b8=this.rendered.unrender(_b7,_b8);}if(this.nodelist){for(var i=0,_b9;_b9=this.nodelist[i];i++){_b8=_b8.remove(_b9);}}return _b8;},clone:function(_ba){return new this.constructor(this._path,this.constant,this.getTemplate,this.text.clone(_ba),this.parsed);}});_84.mixin(_87,{block:function(_bb,_bc){var _bd=_bc.contents.split();var _be=_bd[1];_bb._blocks=_bb._blocks||{};_bb._blocks[_be]=_bb._blocks[_be]||[];_bb._blocks[_be].push(_be);var _bf=_bb.parse(["endblock","endblock "+_be]).rtrim();_bb.next_token();return new dojox.dtl.tag.loader.BlockNode(_be,_bf);},extends_:function(_c0,_c1){var _c2=_c1.contents.split();var _c3=false;var _c4=null;var key=null;if(_c2[1].charAt(0)=="\""||_c2[1].charAt(0)=="'"){_c4=_c2[1].substring(1,_c2[1].length-1);}else{key=_c2[1];}if(_c4&&_c4.indexOf("shared:")==0){_c3=true;_c4=_c4.substring(7,_c4.length);}var _c5=_c0.parse();return new dojox.dtl.tag.loader.ExtendsNode(_c0.getTemplate,_c5,_c3,_c4,key);},include:function(_c6,_c7){var _c8=_c7.contents.split();if(_c8.length!=2){throw new Error(_c8[0]+" tag takes one argument: the name of the template to be included");}var _c9=_c8[1];var _ca=false;if((_c9.charAt(0)=="\""||_c9.slice(-1)=="'")&&_c9.charAt(0)==_c9.slice(-1)){_c9=_c9.slice(1,-1);_ca=true;}return new _87.IncludeNode(_c9,_ca,_c6.getTemplate,_c6.create_text_node());},ssi:function(_cb,_cc){var _cd=_cc.contents.split();var _ce=false;if(_cd.length==3){_ce=(_cd.pop()=="parsed");if(!_ce){throw new Error("Second (optional) argument to ssi tag must be 'parsed'");}}var _cf=_87.include(_cb,new dd.Token(_cc.token_type,_cd.join(" ")));_cf.parsed=_ce;return _cf;}});return dojox.dtl.tag.loader;});},"dojo/date":function(){define(["./_base/kernel","./_base/lang"],function(_d0,_d1){_d1.getObject("date",true,_d0);_d0.date.getDaysInMonth=function(_d2){var _d3=_d2.getMonth();var _d4=[31,28,31,30,31,30,31,31,30,31,30,31];if(_d3==1&&_d0.date.isLeapYear(_d2)){return 29;}return _d4[_d3];};_d0.date.isLeapYear=function(_d5){var _d6=_d5.getFullYear();return !(_d6%400)||(!(_d6%4)&&!!(_d6%100));};_d0.date.getTimezoneName=function(_d7){var str=_d7.toString();var tz="";var _d8;var pos=str.indexOf("(");if(pos>-1){tz=str.substring(++pos,str.indexOf(")"));}else{var pat=/([A-Z\/]+) \d{4}$/;if((_d8=str.match(pat))){tz=_d8[1];}else{str=_d7.toLocaleString();pat=/ ([A-Z\/]+)$/;if((_d8=str.match(pat))){tz=_d8[1];}}}return (tz=="AM"||tz=="PM")?"":tz;};_d0.date.compare=function(_d9,_da,_db){_d9=new Date(+_d9);_da=new Date(+(_da||new Date()));if(_db=="date"){_d9.setHours(0,0,0,0);_da.setHours(0,0,0,0);}else{if(_db=="time"){_d9.setFullYear(0,0,0);_da.setFullYear(0,0,0);}}if(_d9>_da){return 1;}if(_d9<_da){return -1;}return 0;};_d0.date.add=function(_dc,_dd,_de){var sum=new Date(+_dc);var _df=false;var _e0="Date";switch(_dd){case "day":break;case "weekday":var _e1,_e2;var mod=_de%5;if(!mod){_e1=(_de>0)?5:-5;_e2=(_de>0)?((_de-5)/5):((_de+5)/5);}else{_e1=mod;_e2=parseInt(_de/5);}var _e3=_dc.getDay();var adj=0;if(_e3==6&&_de>0){adj=1;}else{if(_e3==0&&_de<0){adj=-1;}}var _e4=_e3+_e1;if(_e4==0||_e4==6){adj=(_de>0)?2:-2;}_de=(7*_e2)+_e1+adj;break;case "year":_e0="FullYear";_df=true;break;case "week":_de*=7;break;case "quarter":_de*=3;case "month":_df=true;_e0="Month";break;default:_e0="UTC"+_dd.charAt(0).toUpperCase()+_dd.substring(1)+"s";}if(_e0){sum["set"+_e0](sum["get"+_e0]()+_de);}if(_df&&(sum.getDate()<_dc.getDate())){sum.setDate(0);}return sum;};_d0.date.difference=function(_e5,_e6,_e7){_e6=_e6||new Date();_e7=_e7||"day";var _e8=_e6.getFullYear()-_e5.getFullYear();var _e9=1;switch(_e7){case "quarter":var m1=_e5.getMonth();var m2=_e6.getMonth();var q1=Math.floor(m1/3)+1;var q2=Math.floor(m2/3)+1;q2+=(_e8*4);_e9=q2-q1;break;case "weekday":var _ea=Math.round(_d0.date.difference(_e5,_e6,"day"));var _eb=parseInt(_d0.date.difference(_e5,_e6,"week"));var mod=_ea%7;if(mod==0){_ea=_eb*5;}else{var adj=0;var _ec=_e5.getDay();var _ed=_e6.getDay();_eb=parseInt(_ea/7);mod=_ea%7;var _ee=new Date(_e5);_ee.setDate(_ee.getDate()+(_eb*7));var _ef=_ee.getDay();if(_ea>0){switch(true){case _ec==6:adj=-1;break;case _ec==0:adj=0;break;case _ed==6:adj=-1;break;case _ed==0:adj=-2;break;case (_ef+mod)>5:adj=-2;}}else{if(_ea<0){switch(true){case _ec==6:adj=0;break;case _ec==0:adj=1;break;case _ed==6:adj=2;break;case _ed==0:adj=1;break;case (_ef+mod)<0:adj=2;}}}_ea+=adj;_ea-=(_eb*2);}_e9=_ea;break;case "year":_e9=_e8;break;case "month":_e9=(_e6.getMonth()-_e5.getMonth())+(_e8*12);break;case "week":_e9=parseInt(_d0.date.difference(_e5,_e6,"day")/7);break;case "day":_e9/=24;case "hour":_e9/=60;case "minute":_e9/=60;case "second":_e9/=1000;case "millisecond":_e9*=_e6.getTime()-_e5.getTime();}return Math.round(_e9);};return _d0.date;});},"dojox/date/php":function(){define("dojox/date/php",["dojo/_base/kernel","dojo/_base/lang","dojo/date","dojox/string/tokenize"],function(_f0,_f1,_f2,_f3){_f0.getObject("date.php",true,dojox);dojox.date.php.format=function(_f4,_f5){var df=new dojox.date.php.DateFormat(_f5);return df.format(_f4);};dojox.date.php.DateFormat=function(_f6){if(!this.regex){var _f7=[];for(var key in this.constructor.prototype){if(_f0.isString(key)&&key.length==1&&_f0.isFunction(this[key])){_f7.push(key);}}this.constructor.prototype.regex=new RegExp("(?:(\\\\.)|(["+_f7.join("")+"]))","g");}var _f8=[];this.tokens=_f3(_f6,this.regex,function(_f9,_fa,i){if(_fa){_f8.push([i,_fa]);return _fa;}if(_f9){return _f9.charAt(1);}});this.replacements=_f8;};_f0.extend(dojox.date.php.DateFormat,{weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],weekdays_3:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],months_3:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],monthdays:[31,28,31,30,31,30,31,31,30,31,30,31],format:function(_fb){this.date=_fb;for(var i=0,_fc;_fc=this.replacements[i];i++){this.tokens[_fc[0]]=this[_fc[1]]();}return this.tokens.join("");},d:function(){var j=this.j();return (j.length==1)?"0"+j:j;},D:function(){return this.weekdays_3[this.date.getDay()];},j:function(){return this.date.getDate()+"";},l:function(){return this.weekdays[this.date.getDay()];},N:function(){var w=this.w();return (!w)?7:w;},S:function(){switch(this.date.getDate()){case 11:case 12:case 13:return "th";case 1:case 21:case 31:return "st";case 2:case 22:return "nd";case 3:case 23:return "rd";default:return "th";}},w:function(){return this.date.getDay()+"";},z:function(){var _fd=this.date.getTime()-new Date(this.date.getFullYear(),0,1).getTime();return Math.floor(_fd/86400000)+"";},W:function(){var _fe;var _ff=new Date(this.date.getFullYear(),0,1).getDay()+1;var w=this.date.getDay()+1;var z=parseInt(this.z());if(z<=(8-_ff)&&_ff>4){var _100=new Date(this.date.getFullYear()-1,this.date.getMonth(),this.date.getDate());if(_ff==5||(_ff==6&&_f2.isLeapYear(_100))){_fe=53;}else{_fe=52;}}else{var i;if(Boolean(this.L())){i=366;}else{i=365;}if((i-z)<(4-w)){_fe=1;}else{var j=z+(7-w)+(_ff-1);_fe=Math.ceil(j/7);if(_ff>4){--_fe;}}}return _fe;},F:function(){return this.months[this.date.getMonth()];},m:function(){var n=this.n();return (n.length==1)?"0"+n:n;},M:function(){return this.months_3[this.date.getMonth()];},n:function(){return this.date.getMonth()+1+"";},t:function(){return (Boolean(this.L())&&this.date.getMonth()==1)?29:this.monthdays[this.getMonth()];},L:function(){return (_f2.isLeapYear(this.date))?"1":"0";},o:function(){},Y:function(){return this.date.getFullYear()+"";},y:function(){return this.Y().slice(-2);},a:function(){return this.date.getHours()>=12?"pm":"am";},b:function(){return this.a().toUpperCase();},B:function(){var off=this.date.getTimezoneOffset()+60;var secs=(this.date.getHours()*3600)+(this.date.getMinutes()*60)+this.getSeconds()+(off*60);var beat=Math.abs(Math.floor(secs/86.4)%1000)+"";while(beat.length<2){beat="0"+beat;}return beat;},g:function(){return (this.date.getHours()>12)?this.date.getHours()-12+"":this.date.getHours()+"";},G:function(){return this.date.getHours()+"";},h:function(){var g=this.g();return (g.length==1)?"0"+g:g;},H:function(){var G=this.G();return (G.length==1)?"0"+G:G;},i:function(){var mins=this.date.getMinutes()+"";return (mins.length==1)?"0"+mins:mins;},s:function(){var secs=this.date.getSeconds()+"";return (secs.length==1)?"0"+secs:secs;},e:function(){return _f2.getTimezoneName(this.date);},I:function(){},O:function(){var off=Math.abs(this.date.getTimezoneOffset());var _101=Math.floor(off/60)+"";var mins=(off%60)+"";if(_101.length==1){_101="0"+_101;}if(mins.length==1){_101="0"+mins;}return ((this.date.getTimezoneOffset()<0)?"+":"-")+_101+mins;},P:function(){var O=this.O();return O.substring(0,2)+":"+O.substring(2,4);},T:function(){return this.e().substring(0,3);},Z:function(){return this.date.getTimezoneOffset()*-60;},c:function(){return this.Y()+"-"+this.m()+"-"+this.d()+"T"+this.h()+":"+this.i()+":"+this.s()+this.P();},r:function(){return this.D()+", "+this.d()+" "+this.M()+" "+this.Y()+" "+this.H()+":"+this.i()+":"+this.s()+" "+this.O();},U:function(){return Math.floor(this.date.getTime()/1000);}});return dojox.date.php;});},"dojox/dtl/ext-dojo/NodeList":function(){define(["dojo/_base/lang","dojo/_base/NodeList","../_base"],function(lang,_102,dd){var nl=lang.getObject("dojox.dtl.ext-dojo.NodeList",true);lang.extend(_102,{dtl:function(_103,_104){var d=dd,self=this;var _105=function(_106,_107){var _108=_106.render(new d._Context(_107));self.forEach(function(node){node.innerHTML=_108;});};d.text._resolveTemplateArg(_103).addCallback(function(_109){_103=new d.Template(_109);d.text._resolveContextArg(_104).addCallback(function(_10a){_105(_103,_10a);});});return this;}});return nl;});},"dojox/dtl/utils/date":function(){define("dojox/dtl/utils/date",["dojo/_base/lang","dojox/date/php","../_base"],function(lang,ddp,dd){lang.getObject("dojox.dtl.utils.date",true);dd.utils.date.DateFormat=ddp.DateFormat;lang.extend(dd.utils.date.DateFormat,ddp.DateFormat.prototype,{f:function(){return (!this.date.getMinutes())?this.g():this.g()+":"+this.i();},N:function(){return dojox.dtl.utils.date._months_ap[this.date.getMonth()];},P:function(){if(!this.date.getMinutes()&&!this.date.getHours()){return "midnight";}if(!this.date.getMinutes()&&this.date.getHours()==12){return "noon";}return this.f()+" "+this.a();}});lang.mixin(dojox.dtl.utils.date,{format:function(date,_10b){var df=new dojox.dtl.utils.date.DateFormat(_10b);return df.format(date);},timesince:function(d,now){if(!(d instanceof Date)){d=new Date(d.year,d.month,d.day);}if(!now){now=new Date();}var _10c=Math.abs(now.getTime()-d.getTime());for(var i=0,_10d;_10d=dojox.dtl.utils.date._chunks[i];i++){var _10e=Math.floor(_10c/_10d[0]);if(_10e){break;}}return _10e+" "+_10d[1](_10e);},_chunks:[[60*60*24*365*1000,function(n){return (n==1)?"year":"years";}],[60*60*24*30*1000,function(n){return (n==1)?"month":"months";}],[60*60*24*7*1000,function(n){return (n==1)?"week":"weeks";}],[60*60*24*1000,function(n){return (n==1)?"day":"days";}],[60*60*1000,function(n){return (n==1)?"hour":"hours";}],[60*1000,function(n){return (n==1)?"minute":"minutes";}]],_months_ap:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."]});return dojox.dtl.utils.date;});},"dojox/dtl/tag/loop":function(){define("dojox/dtl/tag/loop",["dojo/_base/lang","dojo/_base/array","dojo/_base/json","../_base","dojox/string/tokenize"],function(lang,_10f,json,dd,_110){lang.getObject("dojox.dtl.tag.loop",true);var ddtl=dd.tag.loop;ddtl.CycleNode=lang.extend(function(_111,name,text,_112){this.cyclevars=_111;this.name=name;this.contents=text;this.shared=_112||{counter:-1,map:{}};},{render:function(_113,_114){if(_113.forloop&&!_113.forloop.counter0){this.shared.counter=-1;}++this.shared.counter;var _115=this.cyclevars[this.shared.counter%this.cyclevars.length];var map=this.shared.map;if(!map[_115]){map[_115]=new dd._Filter(_115);}_115=map[_115].resolve(_113,_114);if(this.name){_113[this.name]=_115;}this.contents.set(_115);return this.contents.render(_113,_114);},unrender:function(_116,_117){return this.contents.unrender(_116,_117);},clone:function(_118){return new this.constructor(this.cyclevars,this.name,this.contents.clone(_118),this.shared);}});ddtl.IfChangedNode=lang.extend(function(_119,vars,_11a){this.nodes=_119;this._vars=vars;this.shared=_11a||{last:null,counter:0};this.vars=_10f.map(vars,function(item){return new dojox.dtl._Filter(item);});},{render:function(_11b,_11c){if(_11b.forloop){if(_11b.forloop.counter<=this.shared.counter){this.shared.last=null;}this.shared.counter=_11b.forloop.counter;}var _11d;if(this.vars.length){_11d=json.toJson(_10f.map(this.vars,function(item){return item.resolve(_11b);}));}else{_11d=this.nodes.dummyRender(_11b,_11c);}if(_11d!=this.shared.last){var _11e=(this.shared.last===null);this.shared.last=_11d;_11b=_11b.push();_11b.ifchanged={firstloop:_11e};_11c=this.nodes.render(_11b,_11c);_11b=_11b.pop();}else{_11c=this.nodes.unrender(_11b,_11c);}return _11c;},unrender:function(_11f,_120){return this.nodes.unrender(_11f,_120);},clone:function(_121){return new this.constructor(this.nodes.clone(_121),this._vars,this.shared);}});ddtl.RegroupNode=lang.extend(function(_122,key,_123){this._expression=_122;this.expression=new dd._Filter(_122);this.key=key;this.alias=_123;},{_push:function(_124,_125,_126){if(_126.length){_124.push({grouper:_125,list:_126});}},render:function(_127,_128){_127[this.alias]=[];var list=this.expression.resolve(_127);if(list){var last=null;var _129=[];for(var i=0;i4&&args[args.length-2]=="as"){var name=args[args.length-1];var node=new ddtl.CycleNode(args.slice(1,args.length-2),name,_12e.create_text_node());if(!_12e._namedCycleNodes){_12e._namedCycleNodes={};}_12e._namedCycleNodes[name]=node;}else{node=new ddtl.CycleNode(args.slice(1),null,_12e.create_text_node());}return node;},ifchanged:function(_130,_131){var _132=_131.contents.split();var _133=_130.parse(["endifchanged"]);_130.delete_first_token();return new ddtl.IfChangedNode(_133,_132.slice(1));},regroup:function(_134,_135){var _136=_110(_135.contents,/(\s+)/g,function(_137){return _137;});if(_136.length<11||_136[_136.length-3]!="as"||_136[_136.length-7]!="by"){throw new Error("Expected the format: regroup list by key as newList");}var _138=_136.slice(2,-8).join("");var key=_136[_136.length-5];var _139=_136[_136.length-1];return new ddtl.RegroupNode(_138,key,_139);}});return dojox.dtl.tag.loop;});},"dojox/string/Builder":function(){define("dojox/string/Builder",["dojo/_base/lang"],function(lang){lang.getObject("string",true,dojox).Builder=function(str){var b="";this.length=0;this.append=function(s){if(arguments.length>1){var tmp="",l=arguments.length;switch(l){case 9:tmp=""+arguments[8]+tmp;case 8:tmp=""+arguments[7]+tmp;case 7:tmp=""+arguments[6]+tmp;case 6:tmp=""+arguments[5]+tmp;case 5:tmp=""+arguments[4]+tmp;case 4:tmp=""+arguments[3]+tmp;case 3:tmp=""+arguments[2]+tmp;case 2:b+=""+arguments[0]+arguments[1]+tmp;break;default:var i=0;while(i\s+<"));_160=this.contents.render(_15f,_160);}return _160;},unrender:function(_163,_164){return this.nodelist.unrender(_163,_164);},clone:function(_165){return new this.constructor(this.nodelist.clone(_165),this.contents.clone(_165));},_isEmpty:function(node){return (node.nodeType==3&&!node.data.match(/[^\s\n]/));},_watch:function(node){if(this._isEmpty(node)){var _166=false;if(node.parentNode.firstChild==node){node.parentNode.removeChild(node);}}else{var _167=node.parentNode.childNodes;if(node.nodeType==1&&_167.length>2){for(var i=2,_168;_168=_167[i];i++){if(_167[i-2].nodeType==1&&this._isEmpty(_167[i-1])){node.parentNode.removeChild(_167[i-1]);return;}}}}},_watchParent:function(node){var _169=node.childNodes;if(_169.length){while(node.childNodes.length){var last=node.childNodes[node.childNodes.length-1];if(!this._isEmpty(last)){return;}node.removeChild(last);}}}});ddtm.TemplateTagNode=lang.extend(function(tag,text){this.tag=tag;this.contents=text;},{mapping:{openblock:"{%",closeblock:"%}",openvariable:"{{",closevariable:"}}",openbrace:"{",closebrace:"}",opencomment:"{#",closecomment:"#}"},render:function(_16a,_16b){this.contents.set(this.mapping[this.tag]);return this.contents.render(_16a,_16b);},unrender:function(_16c,_16d){return this.contents.unrender(_16c,_16d);},clone:function(_16e){return new this.constructor(this.tag,this.contents.clone(_16e));}});ddtm.WidthRatioNode=lang.extend(function(_16f,max,_170,text){this.current=new dd._Filter(_16f);this.max=new dd._Filter(max);this.width=_170;this.contents=text;},{render:function(_171,_172){var _173=+this.current.resolve(_171);var max=+this.max.resolve(_171);if(typeof _173!="number"||typeof max!="number"||!max){this.contents.set("");}else{this.contents.set(""+Math.round((_173/max)*this.width));}return this.contents.render(_171,_172);},unrender:function(_174,_175){return this.contents.unrender(_174,_175);},clone:function(_176){return new this.constructor(this.current.getExpression(),this.max.getExpression(),this.width,this.contents.clone(_176));}});ddtm.WithNode=lang.extend(function(_177,_178,_179){this.target=new dd._Filter(_177);this.alias=_178;this.nodelist=_179;},{render:function(_17a,_17b){var _17c=this.target.resolve(_17a);_17a=_17a.push();_17a[this.alias]=_17c;_17b=this.nodelist.render(_17a,_17b);_17a=_17a.pop();return _17b;},unrender:function(_17d,_17e){return _17e;},clone:function(_17f){return new this.constructor(this.target.getExpression(),this.alias,this.nodelist.clone(_17f));}});lang.mixin(ddtm,{comment:function(_180,_181){_180.skip_past("endcomment");return dd._noOpNode;},debug:function(_182,_183){return new ddtm.DebugNode(_182.create_text_node());},filter:function(_184,_185){var rest=_185.contents.split(null,1)[1];var _186=_184.create_variable_node("var|"+rest);var _187=_184.parse(["endfilter"]);_184.next_token();return new ddtm.FilterNode(_186,_187);},firstof:function(_188,_189){var _18a=_189.split_contents().slice(1);if(!_18a.length){throw new Error("'firstof' statement requires at least one argument");}return new ddtm.FirstOfNode(_18a,_188.create_text_node());},spaceless:function(_18b,_18c){var _18d=_18b.parse(["endspaceless"]);_18b.delete_first_token();return new ddtm.SpacelessNode(_18d,_18b.create_text_node());},templatetag:function(_18e,_18f){var _190=_18f.contents.split();if(_190.length!=2){throw new Error("'templatetag' statement takes one argument");}var tag=_190[1];var _191=ddtm.TemplateTagNode.prototype.mapping;if(!_191[tag]){var keys=[];for(var key in _191){keys.push(key);}throw new Error("Invalid templatetag argument: '"+tag+"'. Must be one of: "+keys.join(", "));}return new ddtm.TemplateTagNode(tag,_18e.create_text_node());},widthratio:function(_192,_193){var _194=_193.contents.split();if(_194.length!=4){throw new Error("widthratio takes three arguments");}var _195=+_194[3];if(typeof _195!="number"){throw new Error("widthratio final argument must be an integer");}return new ddtm.WidthRatioNode(_194[1],_194[2],_195,_192.create_text_node());},with_:function(_196,_197){var _198=_197.split_contents();if(_198.length!=4||_198[2]!="as"){throw new Error("do_width expected format as 'with value as name'");}var _199=_196.parse(["endwith"]);_196.next_token();return new ddtm.WithNode(_198[1],_198[3],_199);}});return dojox.dtl.tag.misc;});},"dojox/dtl/Context":function(){define("dojox/dtl/Context",["dojo/_base/lang","./_base"],function(lang,dd){dd.Context=lang.extend(function(dict){this._this={};dd._Context.call(this,dict);},dd._Context.prototype,{getKeys:function(){var keys=[];for(var key in this){if(this.hasOwnProperty(key)&&key!="_this"){keys.push(key);}}return keys;},extend:function(obj){return lang.delegate(this,obj);},filter:function(_19a){var _19b=new dd.Context();var keys=[];var i,arg;if(_19a instanceof dd.Context){keys=_19a.getKeys();}else{if(typeof _19a=="object"){for(var key in _19a){keys.push(key);}}else{for(i=0;arg=arguments[i];i++){if(typeof arg=="string"){keys.push(arg);}}}}for(i=0,key;key=keys[i];i++){_19b[key]=this[key];}return _19b;},setThis:function(_19c){this._this=_19c;},getThis:function(){return this._this;},hasKey:function(key){if(this._getter){var got=this._getter(key);if(typeof got!="undefined"){return true;}}if(typeof this[key]!="undefined"){return true;}return false;}});return dojox.dtl.Context;});},"dojox/dtl/tag/logic":function(){define(["dojo/_base/lang","../_base"],function(lang,dd){lang.getObject("dojox.dtl.tag.logic",true);var ddt=dd.text;var ddtl=dd.tag.logic;ddtl.IfNode=lang.extend(function(_19d,_19e,_19f,type){this.bools=_19d;this.trues=_19e;this.falses=_19f;this.type=type;},{render:function(_1a0,_1a1){var i,bool,_1a2,_1a3,_1a4;if(this.type=="or"){for(i=0;bool=this.bools[i];i++){_1a2=bool[0];_1a3=bool[1];_1a4=_1a3.resolve(_1a0);if((_1a4&&!_1a2)||(_1a2&&!_1a4)){if(this.falses){_1a1=this.falses.unrender(_1a0,_1a1);}return (this.trues)?this.trues.render(_1a0,_1a1,this):_1a1;}}if(this.trues){_1a1=this.trues.unrender(_1a0,_1a1);}return (this.falses)?this.falses.render(_1a0,_1a1,this):_1a1;}else{for(i=0;bool=this.bools[i];i++){_1a2=bool[0];_1a3=bool[1];_1a4=_1a3.resolve(_1a0);if(_1a4==_1a2){if(this.trues){_1a1=this.trues.unrender(_1a0,_1a1);}return (this.falses)?this.falses.render(_1a0,_1a1,this):_1a1;}}if(this.falses){_1a1=this.falses.unrender(_1a0,_1a1);}return (this.trues)?this.trues.render(_1a0,_1a1,this):_1a1;}return _1a1;},unrender:function(_1a5,_1a6){_1a6=(this.trues)?this.trues.unrender(_1a5,_1a6):_1a6;_1a6=(this.falses)?this.falses.unrender(_1a5,_1a6):_1a6;return _1a6;},clone:function(_1a7){var _1a8=(this.trues)?this.trues.clone(_1a7):null;var _1a9=(this.falses)?this.falses.clone(_1a7):null;return new this.constructor(this.bools,_1a8,_1a9,this.type);}});ddtl.IfEqualNode=lang.extend(function(var1,var2,_1aa,_1ab,_1ac){this.var1=new dd._Filter(var1);this.var2=new dd._Filter(var2);this.trues=_1aa;this.falses=_1ab;this.negate=_1ac;},{render:function(_1ad,_1ae){var var1=this.var1.resolve(_1ad);var var2=this.var2.resolve(_1ad);var1=(typeof var1!="undefined")?var1:"";var2=(typeof var1!="undefined")?var2:"";if((this.negate&&var1!=var2)||(!this.negate&&var1==var2)){if(this.falses){_1ae=this.falses.unrender(_1ad,_1ae,this);}return (this.trues)?this.trues.render(_1ad,_1ae,this):_1ae;}if(this.trues){_1ae=this.trues.unrender(_1ad,_1ae,this);}return (this.falses)?this.falses.render(_1ad,_1ae,this):_1ae;},unrender:function(_1af,_1b0){return ddtl.IfNode.prototype.unrender.call(this,_1af,_1b0);},clone:function(_1b1){var _1b2=this.trues?this.trues.clone(_1b1):null;var _1b3=this.falses?this.falses.clone(_1b1):null;return new this.constructor(this.var1.getExpression(),this.var2.getExpression(),_1b2,_1b3,this.negate);}});ddtl.ForNode=lang.extend(function(_1b4,loop,_1b5,_1b6){this.assign=_1b4;this.loop=new dd._Filter(loop);this.reversed=_1b5;this.nodelist=_1b6;this.pool=[];},{render:function(_1b7,_1b8){var i,j,k;var _1b9=false;var _1ba=this.assign;for(k=0;k<_1ba.length;k++){if(typeof _1b7[_1ba[k]]!="undefined"){_1b9=true;_1b7=_1b7.push();break;}}if(!_1b9&&_1b7.forloop){_1b9=true;_1b7=_1b7.push();}var _1bb=this.loop.resolve(_1b7)||[];for(i=_1bb.length;i1&&lang.isArrayLike(item)){if(!_1b9){_1b9=true;_1b7=_1b7.push();}var _1bf={};for(k=0;kthis.pool.length){this.pool.push(this.nodelist.clone(_1b8));}_1b8=this.pool[j++].render(_1b7,_1b8,this);}delete _1b7.forloop;if(_1b9){_1b7=_1b7.pop();}else{for(k=0;k<_1ba.length;k++){delete _1b7[_1ba[k]];}}return _1b8;},unrender:function(_1c0,_1c1){for(var i=0,pool;pool=this.pool[i];i++){_1c1=pool.unrender(_1c0,_1c1);}return _1c1;},clone:function(_1c2){return new this.constructor(this.assign,this.loop.getExpression(),this.reversed,this.nodelist.clone(_1c2));}});lang.mixin(ddtl,{if_:function(_1c3,_1c4){var i,part,type,_1c5=[],_1c6=_1c4.contents.split();_1c6.shift();_1c4=_1c6.join(" ");_1c6=_1c4.split(" and ");if(_1c6.length==1){type="or";_1c6=_1c4.split(" or ");}else{type="and";for(i=0;i<_1c6.length;i++){if(_1c6[i].indexOf(" or ")!=-1){throw new Error("'if' tags can't mix 'and' and 'or'");}}}for(i=0;part=_1c6[i];i++){var not=false;if(part.indexOf("not ")==0){part=part.slice(4);not=true;}_1c5.push([not,new dd._Filter(part)]);}var _1c7=_1c3.parse(["else","endif"]);var _1c8=false;var _1c4=_1c3.next_token();if(_1c4.contents=="else"){_1c8=_1c3.parse(["endif"]);_1c3.next_token();}return new ddtl.IfNode(_1c5,_1c7,_1c8,type);},_ifequal:function(_1c9,_1ca,_1cb){var _1cc=_1ca.split_contents();if(_1cc.length!=3){throw new Error(_1cc[0]+" takes two arguments");}var end="end"+_1cc[0];var _1cd=_1c9.parse(["else",end]);var _1ce=false;var _1ca=_1c9.next_token();if(_1ca.contents=="else"){_1ce=_1c9.parse([end]);_1c9.next_token();}return new ddtl.IfEqualNode(_1cc[1],_1cc[2],_1cd,_1ce,_1cb);},ifequal:function(_1cf,_1d0){return ddtl._ifequal(_1cf,_1d0);},ifnotequal:function(_1d1,_1d2){return ddtl._ifequal(_1d1,_1d2,true);},for_:function(_1d3,_1d4){var _1d5=_1d4.contents.split();if(_1d5.length<4){throw new Error("'for' statements should have at least four words: "+_1d4.contents);}var _1d6=_1d5[_1d5.length-1]=="reversed";var _1d7=(_1d6)?-3:-2;if(_1d5[_1d5.length+_1d7]!="in"){throw new Error("'for' tag received an invalid argument: "+_1d4.contents);}var _1d8=_1d5.slice(1,_1d7).join(" ").split(/ *, */);for(var i=0;i<_1d8.length;i++){if(!_1d8[i]||_1d8[i].indexOf(" ")!=-1){throw new Error("'for' tag received an invalid argument: "+_1d4.contents);}}var _1d9=_1d3.parse(["endfor"]);_1d3.next_token();return new ddtl.ForNode(_1d8,_1d5[_1d5.length+_1d7+1],_1d6,_1d9);}});return dojox.dtl.tag.logic;});},"dojox/dtl/tag/date":function(){define("dojox/dtl/tag/date",["dojo/_base/lang","../_base","../utils/date"],function(lang,dd,ddud){lang.getObject("dojox.dtl.tag.date",true);dojox.dtl.tag.date.NowNode=function(_1da,node){this._format=_1da;this.format=new ddud.DateFormat(_1da);this.contents=node;};lang.extend(dd.tag.date.NowNode,{render:function(_1db,_1dc){this.contents.set(this.format.format(new Date()));return this.contents.render(_1db,_1dc);},unrender:function(_1dd,_1de){return this.contents.unrender(_1dd,_1de);},clone:function(_1df){return new this.constructor(this._format,this.contents.clone(_1df));}});dojox.dtl.tag.date.now=function(_1e0,_1e1){var _1e2=_1e1.split_contents();if(_1e2.length!=2){throw new Error("'now' statement takes one argument");}return new dojox.dtl.tag.date.NowNode(_1e2[1].slice(1,-1),_1e0.create_text_node());};return dojox.dtl.tag.date;});}}});require(["dojo/i18n"],function(i18n){i18n._preloadLocalizations("dojox/nls/dtl",[]);});define("dojox/dtl",["./dtl/_base"],function(_1e3){return _1e3;});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl.js.uncompressed.js b/js/libs/dojox/dtl.js.uncompressed.js
new file mode 100644
index 0000000..0987165
--- /dev/null
+++ b/js/libs/dojox/dtl.js.uncompressed.js
@@ -0,0 +1,2974 @@
+/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+/*
+ This is an optimized version of Dojo, built for deployment and not for
+ development. To get sources and documentation, please visit:
+
+ http://dojotoolkit.org
+*/
+
+//>>built
+require({cache:{
+'dojox/dtl/_base':function(){
+define([
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojox/string/tokenize",
+ "dojo/_base/json",
+ "dojo/dom",
+ "dojo/_base/xhr",
+ "dojox/string/Builder",
+ "dojo/_base/Deferred"],
+ function(kernel, lang, Tokenize, json, dom, xhr, StringBuilder, deferred){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ StringBuilder = dojox.string.Builder;
+ =====*/
+ kernel.experimental("dojox.dtl");
+ var dd = lang.getObject("dojox.dtl", true);
+ dd._base = {};
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ dd.TOKEN_BLOCK = -1;
+ dd.TOKEN_VAR = -2;
+ dd.TOKEN_COMMENT = -3;
+ dd.TOKEN_TEXT = 3;
+
+ /*=====
+ dd._Context = function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ }
+ =====*/
+ dd._Context = lang.extend(function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ if(dict){
+ lang._mixin(this, dict);
+ if(dict.get){
+ // Preserve passed getter and restore prototype get
+ this._getter = dict.get;
+ delete this.get;
+ }
+ }
+ },
+ {
+ push: function(){
+ var last = this;
+ var context = lang.delegate(this);
+ context.pop = function(){ return last; }
+ return context;
+ },
+ pop: function(){
+ throw new Error("pop() called on empty Context");
+ },
+ get: function(key, otherwise){
+ var n = this._normalize;
+
+ if(this._getter){
+ var got = this._getter(key);
+ if(got !== undefined){
+ return n(got);
+ }
+ }
+
+ if(this[key] !== undefined){
+ return n(this[key]);
+ }
+
+ return otherwise;
+ },
+ _normalize: function(value){
+ if(value instanceof Date){
+ value.year = value.getFullYear();
+ value.month = value.getMonth() + 1;
+ value.day = value.getDate();
+ value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
+ value.hour = value.getHours();
+ value.minute = value.getMinutes();
+ value.second = value.getSeconds();
+ value.microsecond = value.getMilliseconds();
+ }
+ return value;
+ },
+ update: function(dict){
+ var context = this.push();
+ if(dict){
+ lang._mixin(this, dict);
+ }
+ return context;
+ }
+ });
+
+ var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
+ var split_re = /\s+/g;
+ var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
+ splitter = splitter || split_re;
+ if(!(splitter instanceof RegExp)){
+ splitter = new RegExp(splitter, "g");
+ }
+ if(!splitter.global){
+ throw new Error("You must use a globally flagged RegExp with split " + splitter);
+ }
+ splitter.exec(""); // Reset the global
+
+ var part, parts = [], lastIndex = 0, i = 0;
+ while((part = splitter.exec(this))){
+ parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
+ lastIndex = splitter.lastIndex;
+ if(limit && (++i > limit - 1)){
+ break;
+ }
+ }
+ parts.push(this.slice(lastIndex));
+ return parts;
+ }
+
+ dd.Token = function(token_type, contents){
+ this.token_type = token_type;
+ this.contents = new String(lang.trim(contents));
+ this.contents.split = split;
+ this.split = function(){
+ return String.prototype.split.apply(this.contents, arguments);
+ }
+ }
+ dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
+ var bit, bits = [], i = 0;
+ limit = limit || 999;
+ while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
+ bit = bit[0];
+ if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
+ bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
+ }else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
+ bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
+ }else{
+ bits.push(bit);
+ }
+ }
+ return bits;
+ }
+
+ var ddt = dd.text = {
+ _get: function(module, name, errorless){
+ // summary: Used to find both tags and filters
+ var params = dd.register.get(module, name.toLowerCase(), errorless);
+ if(!params){
+ if(!errorless){
+ throw new Error("No tag found for " + name);
+ }
+ return null;
+ }
+
+ var fn = params[1];
+ var deps = params[2];
+
+ var parts;
+ if(fn.indexOf(":") != -1){
+ parts = fn.split(":");
+ fn = parts.pop();
+ }
+
+// FIXME: THIS DESIGN DOES NOT WORK WITH ASYNC LOADERS!
+ var mod = deps;
+ if (/\./.test(deps)) {
+ deps = deps.replace(/\./g, "/");
+ }
+ require([deps], function(){});
+
+ var parent = lang.getObject(mod);
+
+ return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
+ },
+ getTag: function(name, errorless){
+ return ddt._get("tag", name, errorless);
+ },
+ getFilter: function(name, errorless){
+ return ddt._get("filter", name, errorless);
+ },
+ getTemplate: function(file){
+ return new dd.Template(ddt.getTemplateString(file));
+ },
+ getTemplateString: function(file){
+ return xhr._getText(file.toString()) || "";
+ },
+ _resolveLazy: function(location, sync, json){
+ if(sync){
+ if(json){
+ return json.fromJson(xhr._getText(location)) || {};
+ }else{
+ return dd.text.getTemplateString(location);
+ }
+ }else{
+ return xhr.get({
+ handleAs: json ? "json" : "text",
+ url: location
+ });
+ }
+ },
+ _resolveTemplateArg: function(arg, sync){
+ if(ddt._isTemplate(arg)){
+ if(!sync){
+ var d = new deferred();
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync);
+ },
+ _isTemplate: function(arg){
+ return (arg === undefined) || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
+ },
+ _resolveContextArg: function(arg, sync){
+ if(arg.constructor == Object){
+ if(!sync){
+ var d = new deferred;
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync, true);
+ },
+ _re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
+ tokenize: function(str){
+ return Tokenize(str, ddt._re, ddt._parseDelims);
+ },
+ _parseDelims: function(varr, load, tag){
+ if(varr){
+ return [dd.TOKEN_VAR, varr];
+ }else if(load){
+ var parts = lang.trim(tag).split(/\s+/g);
+ for(var i = 0, part; part = parts[i]; i++){
+ if (/\./.test(part)){
+ part = part.replace(/\./g,"/");
+ }
+ require([part]);
+ }
+ }else{
+ return [dd.TOKEN_BLOCK, tag];
+ }
+ }
+ }
+
+ /*=====
+ dd.Template = function(template, isString){
+ // summary:
+ // The base class for text-based templates.
+ // template: String|dojo._Url
+ // The string or location of the string to
+ // use as a template
+ // isString: Boolean
+ // Indicates whether the template is a string or a url.
+ };
+ dd.Template.prototype.update= function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ }
+ dd.Template.prototype.render= function(context, buffer){
+ // summary:
+ // Renders this template.
+ // context: Object
+ // The runtime context.
+ // buffer: StringBuilder?
+ // A string buffer.
+ }
+
+ =====*/
+ dd.Template = lang.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
+ // template:
+ // The string or location of the string to
+ // use as a template
+ var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
+ var tokens = ddt.tokenize(str);
+ var parser = new dd._Parser(tokens);
+ this.nodelist = parser.parse();
+ },
+ {
+ update: function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
+ var content = this.render(new dd._Context(contextObject));
+ if(node.forEach){
+ node.forEach(function(item){
+ item.innerHTML = content;
+ });
+ }else{
+ dom.byId(node).innerHTML = content;
+ }
+ return this;
+ });
+ },
+ render: function(context, /*concatenatable?*/ buffer){
+ buffer = buffer || this.getBuffer();
+ context = context || new dd._Context({});
+ return this.nodelist.render(context, buffer) + "";
+ },
+ getBuffer: function(){
+ return new StringBuilder();
+ }
+ });
+
+ var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
+ dd.quickFilter = function(str){
+ if(!str){
+ return new dd._NodeList();
+ }
+
+ if(str.indexOf("{%") == -1){
+ return new dd._QuickNodeList(Tokenize(str, qfRe, function(token){
+ return new dd._Filter(token);
+ }));
+ }
+ }
+
+ dd._QuickNodeList = lang.extend(function(contents){
+ this.contents = contents;
+ },
+ {
+ render: function(context, buffer){
+ for(var i = 0, l = this.contents.length; i < l; i++){
+ if(this.contents[i].resolve){
+ buffer = buffer.concat(this.contents[i].resolve(context));
+ }else{
+ buffer = buffer.concat(this.contents[i]);
+ }
+ }
+ return buffer;
+ },
+ dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
+ clone: function(buffer){ return this; }
+ });
+
+ dd._Filter = lang.extend(function(token){
+ // summary: Uses a string to find (and manipulate) a variable
+ if(!token) throw new Error("Filter must be called with variable name");
+ this.contents = token;
+
+ var cache = this._cache[token];
+ if(cache){
+ this.key = cache[0];
+ this.filters = cache[1];
+ }else{
+ this.filters = [];
+ Tokenize(token, this._re, this._tokenize, this);
+ this._cache[token] = [this.key, this.filters];
+ }
+ },
+ {
+ _cache: {},
+ _re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
+ _values: {
+ 0: '"', // _("text")
+ 1: '"', // "text"
+ 2: "", // variable
+ 8: '"' // 'text'
+ },
+ _args: {
+ 4: '"', // :_("text")
+ 5: '"', // :"text"
+ 6: "", // :variable
+ 7: "'"// :'text'
+ },
+ _tokenize: function(){
+ var pos, arg;
+
+ for(var i = 0, has = []; i < arguments.length; i++){
+ has[i] = (arguments[i] !== undefined && typeof arguments[i] == "string" && arguments[i]);
+ }
+
+ if(!this.key){
+ for(pos in this._values){
+ if(has[pos]){
+ this.key = this._values[pos] + arguments[pos] + this._values[pos];
+ break;
+ }
+ }
+ }else{
+ for(pos in this._args){
+ if(has[pos]){
+ var value = arguments[pos];
+ if(this._args[pos] == "'"){
+ value = value.replace(/\\'/g, "'");
+ }else if(this._args[pos] == '"'){
+ value = value.replace(/\\"/g, '"');
+ }
+ arg = [!this._args[pos], value];
+ break;
+ }
+ }
+ // Get a named filter
+ var fn = ddt.getFilter(arguments[3]);
+ if(!lang.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
+ this.filters.push([fn, arg]);
+ }
+ },
+ getExpression: function(){
+ return this.contents;
+ },
+ resolve: function(context){
+ if(this.key === undefined){
+ return "";
+ }
+
+ var str = this.resolvePath(this.key, context);
+
+ for(var i = 0, filter; filter = this.filters[i]; i++){
+ // Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
+ // and [1][1] is either the variable name of the string content.
+ if(filter[1]){
+ if(filter[1][0]){
+ str = filter[0](str, this.resolvePath(filter[1][1], context));
+ }else{
+ str = filter[0](str, filter[1][1]);
+ }
+ }else{
+ str = filter[0](str);
+ }
+ }
+
+ return str;
+ },
+ resolvePath: function(path, context){
+ var current, parts;
+ var first = path.charAt(0);
+ var last = path.slice(-1);
+ if(!isNaN(parseInt(first))){
+ current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
+ }else if(first == '"' && first == last){
+ current = path.slice(1, -1);
+ }else{
+ if(path == "true"){ return true; }
+ if(path == "false"){ return false; }
+ if(path == "null" || path == "None"){ return null; }
+ parts = path.split(".");
+ current = context.get(parts[0]);
+
+ if(lang.isFunction(current)){
+ var self = context.getThis && context.getThis();
+ if(current.alters_data){
+ current = "";
+ }else if(self){
+ current = current.call(self);
+ }else{
+ current = "";
+ }
+ }
+
+ for(var i = 1; i < parts.length; i++){
+ var part = parts[i];
+ if(current){
+ var base = current;
+ if(lang.isObject(current) && part == "items" && current[part] === undefined){
+ var items = [];
+ for(var key in current){
+ items.push([key, current[key]]);
+ }
+ current = items;
+ continue;
+ }
+
+ if(current.get && lang.isFunction(current.get) && current.get.safe){
+ current = current.get(part);
+ }else if(current[part] === undefined){
+ current = current[part];
+ break;
+ }else{
+ current = current[part];
+ }
+
+ if(lang.isFunction(current)){
+ if(current.alters_data){
+ current = "";
+ }else{
+ current = current.call(base);
+ }
+ }else if(current instanceof Date){
+ current = dd._Context.prototype._normalize(current);
+ }
+ }else{
+ return "";
+ }
+ }
+ }
+ return current;
+ }
+ });
+
+ dd._TextNode = dd._Node = lang.extend(function(/*Object*/ obj){
+ // summary: Basic catch-all node
+ this.contents = obj;
+ },
+ {
+ set: function(data){
+ this.contents = data;
+ return this;
+ },
+ render: function(context, buffer){
+ // summary: Adds content onto the buffer
+ return buffer.concat(this.contents);
+ },
+ isEmpty: function(){
+ return !lang.trim(this.contents);
+ },
+ clone: function(){ return this; }
+ });
+
+ dd._NodeList = lang.extend(function(/*Node[]*/ nodes){
+ // summary: Allows us to render a group of nodes
+ this.contents = nodes || [];
+ this.last = "";
+ },
+ {
+ push: function(node){
+ // summary: Add a new node to the list
+ this.contents.push(node);
+ return this;
+ },
+ concat: function(nodes){
+ this.contents = this.contents.concat(nodes);
+ return this;
+ },
+ render: function(context, buffer){
+ // summary: Adds all content onto the buffer
+ for(var i = 0; i < this.contents.length; i++){
+ buffer = this.contents[i].render(context, buffer);
+ if(!buffer) throw new Error("Template must return buffer");
+ }
+ return buffer;
+ },
+ dummyRender: function(context){
+ return this.render(context, dd.Template.prototype.getBuffer()).toString();
+ },
+ unrender: function(){ return arguments[1]; },
+ clone: function(){ return this; },
+ rtrim: function(){
+ while(1){
+ i = this.contents.length - 1;
+ if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
+ this.contents.pop();
+ }else{
+ break;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ dd._VarNode = lang.extend(function(str){
+ // summary: A node to be processed as a variable
+ this.contents = new dd._Filter(str);
+ },
+ {
+ render: function(context, buffer){
+ var str = this.contents.resolve(context);
+ if(!str.safe){
+ str = dd._base.escape("" + str);
+ }
+ return buffer.concat(str);
+ }
+ });
+
+ dd._noOpNode = new function(){
+ // summary: Adds a no-op node. Useful in custom tags
+ this.render = this.unrender = function(){ return arguments[1]; }
+ this.clone = function(){ return this; }
+ }
+
+ dd._Parser = lang.extend(function(tokens){
+ // summary: Parser used during initialization and for tag groups.
+ this.contents = tokens;
+ },
+ {
+ i: 0,
+ parse: function(/*Array?*/ stop_at){
+ // summary: Turns tokens into nodes
+ // description: Steps into tags are they're found. Blocks use the parse object
+ // to find their closing tag (the stop_at array). stop_at is inclusive, it
+ // returns the node that matched.
+ var terminators = {}, token;
+ stop_at = stop_at || [];
+ for(var i = 0; i < stop_at.length; i++){
+ terminators[stop_at[i]] = true;
+ }
+
+ var nodelist = new dd._NodeList();
+ while(this.i < this.contents.length){
+ token = this.contents[this.i++];
+ if(typeof token == "string"){
+ nodelist.push(new dd._TextNode(token));
+ }else{
+ var type = token[0];
+ var text = token[1];
+ if(type == dd.TOKEN_VAR){
+ nodelist.push(new dd._VarNode(text));
+ }else if(type == dd.TOKEN_BLOCK){
+ if(terminators[text]){
+ --this.i;
+ return nodelist;
+ }
+ var cmd = text.split(/\s+/g);
+ if(cmd.length){
+ cmd = cmd[0];
+ var fn = ddt.getTag(cmd);
+ if(fn){
+ nodelist.push(fn(this, new dd.Token(type, text)));
+ }
+ }
+ }
+ }
+ }
+
+ if(stop_at.length){
+ throw new Error("Could not find closing tag(s): " + stop_at.toString());
+ }
+
+ this.contents.length = 0;
+ return nodelist;
+ },
+ next_token: function(){
+ // summary: Returns the next token in the list.
+ var token = this.contents[this.i++];
+ return new dd.Token(token[0], token[1]);
+ },
+ delete_first_token: function(){
+ this.i++;
+ },
+ skip_past: function(endtag){
+ while(this.i < this.contents.length){
+ var token = this.contents[this.i++];
+ if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
+ return;
+ }
+ }
+ throw new Error("Unclosed tag found when looking for " + endtag);
+ },
+ create_variable_node: function(expr){
+ return new dd._VarNode(expr);
+ },
+ create_text_node: function(expr){
+ return new dd._TextNode(expr || "");
+ },
+ getTemplate: function(file){
+ return new dd.Template(file);
+ }
+ });
+
+ dd.register = {
+ _registry: {
+ attributes: [],
+ tags: [],
+ filters: []
+ },
+ get: function(/*String*/ module, /*String*/ name){
+ var registry = dd.register._registry[module + "s"];
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(typeof entry[0] == "string"){
+ if(entry[0] == name){
+ return entry;
+ }
+ }else if(name.match(entry[0])){
+ return entry;
+ }
+ }
+ },
+ getAttributeTags: function(){
+ var tags = [];
+ var registry = dd.register._registry.attributes;
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(entry.length == 3){
+ tags.push(entry);
+ }else{
+ var fn = lang.getObject(entry[1]);
+ if(fn && lang.isFunction(fn)){
+ entry.push(fn);
+ tags.push(entry);
+ }
+ }
+ }
+ return tags;
+ },
+ _any: function(type, base, locations){
+ for(var path in locations){
+ for(var i = 0, fn; fn = locations[path][i]; i++){
+ var key = fn;
+ if(lang.isArray(fn)){
+ key = fn[0];
+ fn = fn[1];
+ }
+ if(typeof key == "string"){
+ if(key.substr(0, 5) == "attr:"){
+ var attr = fn;
+ if(attr.substr(0, 5) == "attr:"){
+ attr = attr.slice(5);
+ }
+ dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
+ }
+ key = key.toLowerCase()
+ }
+ dd.register._registry[type].push([
+ key,
+ fn,
+ base + "." + path
+ ]);
+ }
+ }
+ },
+ tags: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("tags", base, locations);
+ },
+ filters: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("filters", base, locations);
+ }
+ }
+
+ var escapeamp = /&/g;
+ var escapelt = //g;
+ var escapeqt = /'/g;
+ var escapedblqt = /"/g;
+ dd._base.escape = function(value){
+ // summary: Escapes a string's HTML
+ return dd.mark_safe(value.replace(escapeamp, '&').replace(escapelt, '<').replace(escapegt, '>').replace(escapedblqt, '"').replace(escapeqt, '''));
+ }
+
+ dd._base.safe = function(value){
+ if(typeof value == "string"){
+ value = new String(value);
+ }
+ if(typeof value == "object"){
+ value.safe = true;
+ }
+ return value;
+ }
+ dd.mark_safe = dd._base.safe;
+
+ dd.register.tags("dojox.dtl.tag", {
+ "date": ["now"],
+ "logic": ["if", "for", "ifequal", "ifnotequal"],
+ "loader": ["extends", "block", "include", "load", "ssi"],
+ "misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
+ "loop": ["cycle", "ifchanged", "regroup"]
+ });
+ dd.register.filters("dojox.dtl.filter", {
+ "dates": ["date", "time", "timesince", "timeuntil"],
+ "htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
+ "integers": ["add", "get_digit"],
+ "lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
+ "logic": ["default", "default_if_none", "divisibleby", "yesno"],
+ "misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
+ "strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]
+ });
+ dd.register.filters("dojox.dtl", {
+ "_base": ["escape", "safe"]
+ });
+ return dd;
+});
+
+
+},
+'dojox/dtl/tag/loader':function(){
+define("dojox/dtl/tag/loader", [
+ "dojo/_base/lang",
+ "../_base",
+ "dojo/_base/array",
+ "dojo/_base/connect"
+], function(lang,dd,array,connect){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loader", true);
+
+ var ddtl = dd.tag.loader;
+
+ ddtl.BlockNode = lang.extend(function(name, nodelist){
+ this.name = name;
+ this.nodelist = nodelist; // Can be overridden
+ },
+ {
+ "super": function(){
+ if(this.parent){
+ var html = this.parent.nodelist.dummyRender(this.context, null, true);
+ if(typeof html == "string"){
+ html = new String(html);
+ }
+ html.safe = true;
+ return html;
+ }
+ return '';
+ },
+ render: function(context, buffer){
+ var name = this.name;
+ var nodelist = this.nodelist;
+ var parent;
+ if(buffer.blocks){
+ var block = buffer.blocks[name];
+ if(block){
+ parent = block.parent;
+ nodelist = block.nodelist;
+ block.used = true;
+ }
+ }
+
+ this.rendered = nodelist;
+
+ context = context.push();
+ this.context = context;
+ this.parent = null;
+ if(nodelist != this.nodelist){
+ this.parent = this;
+ }
+ context.block = this;
+
+ if(buffer.getParent){
+ var bufferParent = buffer.getParent();
+ var setParent = connect.connect(buffer, "onSetParent", function(node, up, root){
+ if(up && root){
+ buffer.setParent(bufferParent);
+ }
+ });
+ }
+ buffer = nodelist.render(context, buffer, this);
+ setParent && connect.disconnect(setParent);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.name, this.nodelist.clone(buffer));
+ },
+ toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
+ });
+
+ ddtl.ExtendsNode = lang.extend(function(getTemplate, nodelist, shared, parent, key){
+ this.getTemplate = getTemplate;
+ this.nodelist = nodelist;
+ this.shared = shared;
+ this.parent = parent;
+ this.key = key;
+ },
+ {
+ parents: {},
+ getParent: function(context){
+ var parent = this.parent;
+ if(!parent){
+ var string;
+ parent = this.parent = context.get(this.key, false);
+ if(!parent){
+ throw new Error("extends tag used a variable that did not resolve");
+ }
+ if(typeof parent == "object"){
+ var url = parent.url || parent.templatePath;
+ if(parent.shared){
+ this.shared = true;
+ }
+ if(url){
+ parent = this.parent = url.toString();
+ }else if(parent.templateString){
+ // Allow the builder's string interning to work
+ string = parent.templateString;
+ parent = this.parent = " ";
+ }else{
+ parent = this.parent = this.parent.toString();
+ }
+ }
+ if(parent && parent.indexOf("shared:") === 0){
+ this.shared = true;
+ parent = this.parent = parent.substring(7, parent.length);
+ }
+ }
+ if(!parent){
+ throw new Error("Invalid template name in 'extends' tag.");
+ }
+ if(parent.render){
+ return parent;
+ }
+ if(this.parents[parent]){
+ return this.parents[parent];
+ }
+ this.parent = this.getTemplate(string || dojox.dtl.text.getTemplateString(parent));
+ if(this.shared){
+ this.parents[parent] = this.parent;
+ }
+ return this.parent;
+ },
+ render: function(context, buffer){
+ var parent = this.getParent(context);
+
+ parent.blocks = parent.blocks || {};
+ buffer.blocks = buffer.blocks || {};
+
+ for(var i = 0, node; node = this.nodelist.contents[i]; i++){
+ if(node instanceof dojox.dtl.tag.loader.BlockNode){
+ var old = parent.blocks[node.name];
+ if(old && old.nodelist != node.nodelist){
+ // In a shared template, the individual blocks might change
+ buffer = old.nodelist.unrender(context, buffer);
+ }
+ parent.blocks[node.name] = buffer.blocks[node.name] = {
+ shared: this.shared,
+ nodelist: node.nodelist,
+ used: false
+ }
+ }
+ }
+
+ this.rendered = parent;
+ return parent.nodelist.render(context, buffer, this);
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer, this);
+ },
+ toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
+ });
+
+ ddtl.IncludeNode = lang.extend(function(path, constant, getTemplate, text, parsed){
+ this._path = path;
+ this.constant = constant;
+ this.path = (constant) ? path : new dd._Filter(path);
+ this.getTemplate = getTemplate;
+ this.text = text;
+ this.parsed = (arguments.length == 5) ? parsed : true;
+ },
+ {
+ _cache: [{}, {}],
+ render: function(context, buffer){
+ var location = ((this.constant) ? this.path : this.path.resolve(context)).toString();
+ var parsed = Number(this.parsed);
+ var dirty = false;
+ if(location != this.last){
+ dirty = true;
+ if(this.last){
+ buffer = this.unrender(context, buffer);
+ }
+ this.last = location;
+ }
+
+ var cache = this._cache[parsed];
+
+ if(parsed){
+ if(!cache[location]){
+ cache[location] = dd.text._resolveTemplateArg(location, true);
+ }
+ if(dirty){
+ var template = this.getTemplate(cache[location]);
+ this.rendered = template.nodelist;
+ }
+ return this.rendered.render(context, buffer, this);
+ }else{
+ if(this.text instanceof dd._TextNode){
+ if(dirty){
+ this.rendered = this.text;
+ this.rendered.set(dd.text._resolveTemplateArg(location, true));
+ }
+ return this.rendered.render(context, buffer);
+ }else{
+ if(!cache[location]){
+ var nodelist = [];
+ var div = document.createElement("div");
+ div.innerHTML = dd.text._resolveTemplateArg(location, true);
+ var children = div.childNodes;
+ while(children.length){
+ var removed = div.removeChild(children[0]);
+ nodelist.push(removed);
+ }
+ cache[location] = nodelist;
+ }
+ if(dirty){
+ this.nodelist = [];
+ var exists = true;
+ for(var i = 0, child; child = cache[location][i]; i++){
+ this.nodelist.push(child.cloneNode(true));
+ }
+ }
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.concat(node);
+ }
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ if(this.rendered){
+ buffer = this.rendered.unrender(context, buffer);
+ }
+ if(this.nodelist){
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.remove(node);
+ }
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._path, this.constant, this.getTemplate, this.text.clone(buffer), this.parsed);
+ }
+ });
+
+ lang.mixin(ddtl, {
+ block: function(parser, token){
+ var parts = token.contents.split();
+ var name = parts[1];
+
+ parser._blocks = parser._blocks || {};
+ parser._blocks[name] = parser._blocks[name] || [];
+ parser._blocks[name].push(name);
+
+ var nodelist = parser.parse(["endblock", "endblock " + name]).rtrim();
+ parser.next_token();
+ return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
+ },
+ extends_: function(parser, token){
+ var parts = token.contents.split();
+ var shared = false;
+ var parent = null;
+ var key = null;
+ if(parts[1].charAt(0) == '"' || parts[1].charAt(0) == "'"){
+ parent = parts[1].substring(1, parts[1].length - 1);
+ }else{
+ key = parts[1];
+ }
+ if(parent && parent.indexOf("shared:") == 0){
+ shared = true;
+ parent = parent.substring(7, parent.length);
+ }
+ var nodelist = parser.parse();
+ return new dojox.dtl.tag.loader.ExtendsNode(parser.getTemplate, nodelist, shared, parent, key);
+ },
+ include: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error(parts[0] + " tag takes one argument: the name of the template to be included");
+ }
+ var path = parts[1];
+ var constant = false;
+ if((path.charAt(0) == '"' || path.slice(-1) == "'") && path.charAt(0) == path.slice(-1)){
+ path = path.slice(1, -1);
+ constant = true;
+ }
+ return new ddtl.IncludeNode(path, constant, parser.getTemplate, parser.create_text_node());
+ },
+ ssi: function(parser, token){
+ // We're going to treat things a little differently here.
+ // First of all, this tag is *not* portable, so I'm not
+ // concerned about it being a "drop in" replacement.
+
+ // Instead, we'll just replicate the include tag, but with that
+ // optional "parsed" parameter.
+ var parts = token.contents.split();
+ var parsed = false;
+ if(parts.length == 3){
+ parsed = (parts.pop() == "parsed");
+ if(!parsed){
+ throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
+ }
+ }
+ var node = ddtl.include(parser, new dd.Token(token.token_type, parts.join(" ")));
+ node.parsed = parsed;
+ return node;
+ }
+ });
+ return dojox.dtl.tag.loader;
+});
+},
+'dojo/date':function(){
+define(["./_base/kernel", "./_base/lang"], function(dojo, lang) {
+ // module:
+ // dojo/date
+ // summary:
+ // TODOC
+
+lang.getObject("date", true, dojo);
+
+/*=====
+dojo.date = {
+ // summary: Date manipulation utilities
+}
+=====*/
+
+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
+ 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) || (!(year%4) && !!(year%100)); // 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){
+ tz = str.substring(++pos, str.indexOf(')'));
+ }else{
+ // If at first you don't succeed ...
+ // 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];
+ }else{
+ // Some browsers (e.g. Safari) glue the TZ on the end
+ // of toLocaleString instead of putting it in toString
+ 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
+};
+
+// Utility methods to do arithmetic calculations with Dates
+
+dojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
+ // summary:
+ // Compare two date objects by date, time, or both.
+ // description:
+ // Returns 0 if equal, positive if a > b, else negative.
+ // date1:
+ // Date object
+ // date2:
+ // Date object. If not specified, the current Date is used.
+ // portion:
+ // A string indicating the "date" or "time" portion of a Date object.
+ // Compares both "date" and "time" by default. One of the following:
+ // "date", "time", "datetime"
+
+ // Extra step required in copy for IE - see #3112
+ date1 = new Date(+date1);
+ date2 = new Date(+(date2 || new Date()));
+
+ if(portion == "date"){
+ // Ignore times and compare dates.
+ date1.setHours(0, 0, 0, 0);
+ date2.setHours(0, 0, 0, 0);
+ }else if(portion == "time"){
+ // Ignore dates and compare times.
+ date1.setFullYear(0, 0, 0);
+ date2.setFullYear(0, 0, 0);
+ }
+
+ if(date1 > date2){ return 1; } // int
+ if(date1 < date2){ return -1; } // int
+ return 0; // int
+};
+
+dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
+ // summary:
+ // Add to a Date in intervals of different size, from milliseconds to years
+ // date: Date
+ // Date object to start with
+ // interval:
+ // A string representing the interval. One of the following:
+ // "year", "month", "day", "hour", "minute", "second",
+ // "millisecond", "quarter", "week", "weekday"
+ // amount:
+ // How much to add to the date.
+
+ var sum = new Date(+date); // convert to Number before copying to accomodate IE (#3112)
+ var fixOvershoot = false;
+ var property = "Date";
+
+ switch(interval){
+ case "day":
+ break;
+ case "weekday":
+ //i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true. see dojo.cldr.supplemental
+
+ // Divide the increment time span into weekspans plus leftover days
+ // e.g., 8 days is one 5-day weekspan / and two leftover days
+ // Can't have zero leftover days, so numbers divisible by 5 get
+ // a days value of 5, and the remaining days make up the number of weeks
+ var days, weeks;
+ var mod = amount % 5;
+ if(!mod){
+ days = (amount > 0) ? 5 : -5;
+ weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
+ }else{
+ days = mod;
+ weeks = parseInt(amount/5);
+ }
+ // Get weekday value for orig date param
+ var strt = date.getDay();
+ // Orig date is Sat / positive incrementer
+ // Jump over Sun
+ var adj = 0;
+ if(strt == 6 && amount > 0){
+ adj = 1;
+ }else if(strt == 0 && amount < 0){
+ // Orig date is Sun / negative incrementer
+ // Jump back over Sat
+ adj = -1;
+ }
+ // Get weekday val for the new date
+ var trgt = strt + days;
+ // New date is on Sat or Sun
+ if(trgt == 0 || trgt == 6){
+ adj = (amount > 0) ? 2 : -2;
+ }
+ // Increment by number of weeks plus leftover days plus
+ // weekend adjustments
+ amount = (7 * weeks) + days + adj;
+ break;
+ case "year":
+ property = "FullYear";
+ // Keep increment/decrement from 2/29 out of March
+ fixOvershoot = true;
+ break;
+ case "week":
+ amount *= 7;
+ break;
+ case "quarter":
+ // Naive quarter is just three months
+ amount *= 3;
+ // fallthrough...
+ case "month":
+ // Reset to last day of month if you overshoot
+ fixOvershoot = true;
+ property = "Month";
+ break;
+// case "hour":
+// case "minute":
+// case "second":
+// case "millisecond":
+ default:
+ property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
+ }
+
+ if(property){
+ sum["set"+property](sum["get"+property]()+amount);
+ }
+
+ if(fixOvershoot && (sum.getDate() < date.getDate())){
+ sum.setDate(0);
+ }
+
+ return sum; // Date
+};
+
+dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
+ // summary:
+ // Get the difference in a specific unit of time (e.g., number of
+ // months, weeks, days, etc.) between two dates, rounded to the
+ // nearest integer.
+ // date1:
+ // Date object
+ // date2:
+ // Date object. If not specified, the current Date is used.
+ // interval:
+ // A string representing the interval. One of the following:
+ // "year", "month", "day", "hour", "minute", "second",
+ // "millisecond", "quarter", "week", "weekday"
+ // Defaults to "day".
+
+ date2 = date2 || new Date();
+ interval = interval || "day";
+ var yearDiff = date2.getFullYear() - date1.getFullYear();
+ var delta = 1; // Integer return value
+
+ switch(interval){
+ case "quarter":
+ var m1 = date1.getMonth();
+ var m2 = date2.getMonth();
+ // Figure out which quarter the months are in
+ var q1 = Math.floor(m1/3) + 1;
+ var q2 = Math.floor(m2/3) + 1;
+ // Add quarters for any year difference between the dates
+ q2 += (yearDiff * 4);
+ delta = q2 - q1;
+ break;
+ case "weekday":
+ var days = Math.round(dojo.date.difference(date1, date2, "day"));
+ var weeks = parseInt(dojo.date.difference(date1, date2, "week"));
+ var mod = days % 7;
+
+ // Even number of weeks
+ if(mod == 0){
+ days = weeks*5;
+ }else{
+ // Weeks plus spare change (< 7 days)
+ var adj = 0;
+ var aDay = date1.getDay();
+ var bDay = date2.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(date1);
+ dtMark.setDate(dtMark.getDate()+(weeks*7));
+ var dayMark = dtMark.getDay();
+
+ // Spare change days -- 6 or less
+ if(days > 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;
+ }
+ }else if(days < 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;
+ }
+ }
+ days += adj;
+ days -= (weeks*2);
+ }
+ delta = days;
+ break;
+ case "year":
+ delta = yearDiff;
+ break;
+ case "month":
+ delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
+ break;
+ case "week":
+ // Truncate instead of rounding
+ // Don't use Math.floor -- value may be negative
+ delta = parseInt(dojo.date.difference(date1, date2, "day")/7);
+ break;
+ case "day":
+ delta /= 24;
+ // fallthrough
+ case "hour":
+ delta /= 60;
+ // fallthrough
+ case "minute":
+ delta /= 60;
+ // fallthrough
+ case "second":
+ delta /= 1000;
+ // fallthrough
+ case "millisecond":
+ delta *= date2.getTime() - date1.getTime();
+ }
+
+ // Round for fractional values and DST leaps
+ return Math.round(delta); // Number (integer)
+};
+
+return dojo.date;
+});
+
+},
+'dojox/date/php':function(){
+define("dojox/date/php", ["dojo/_base/kernel", "dojo/_base/lang","dojo/date","dojox/string/tokenize"], function(dojo,dlang,ddate,dxst){
+dojo.getObject("date.php", true, dojox);
+
+dojox.date.php.format = function(/*Date*/ date, /*String*/ format){
+ // summary: Get a formatted string for a given date object
+ var df = new dojox.date.php.DateFormat(format);
+ return df.format(date);
+}
+
+dojox.date.php.DateFormat = function(/*String*/ format){
+ // summary: Format the internal date object
+ if(!this.regex){
+ var keys = [];
+ for(var key in this.constructor.prototype){
+ if(dojo.isString(key) && key.length == 1 && dojo.isFunction(this[key])){
+ keys.push(key);
+ }
+ }
+ this.constructor.prototype.regex = new RegExp("(?:(\\\\.)|([" + keys.join("") + "]))", "g");
+ }
+
+ var replacements = [];
+
+ this.tokens = dxst(format, this.regex, function(escape, token, i){
+ if(token){
+ replacements.push([i, token]);
+ return token;
+ }
+ if(escape){
+ return escape.charAt(1);
+ }
+ });
+
+ this.replacements = replacements;
+}
+dojo.extend(dojox.date.php.DateFormat, {
+ weekdays: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ weekdays_3: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ months_3: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ monthdays: [31,28,31,30,31,30,31,31,30,31,30,31],
+
+ format: function(/*Date*/ date){
+ this.date = date;
+ for(var i = 0, replacement; replacement = this.replacements[i]; i++){
+ this.tokens[replacement[0]] = this[replacement[1]]();
+ }
+ return this.tokens.join("");
+ },
+
+ // Day
+
+ d: function(){
+ // summary: Day of the month, 2 digits with leading zeros
+ var j = this.j();
+ return (j.length == 1) ? "0" + j : j;
+ },
+
+ D: function(){
+ // summary: A textual representation of a day, three letters
+ return this.weekdays_3[this.date.getDay()];
+ },
+
+ j: function(){
+ // summary: Day of the month without leading zeros
+ return this.date.getDate() + "";
+ },
+
+ l: function(){
+ // summary: A full textual representation of the day of the week
+ return this.weekdays[this.date.getDay()];
+ },
+
+ N: function(){
+ // summary: ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0)
+ var w = this.w();
+ return (!w) ? 7 : w;
+ },
+
+ S: function(){
+ // summary: English ordinal suffix for the day of the month, 2 characters
+ switch(this.date.getDate()){
+ case 11: case 12: case 13: return "th";
+ case 1: case 21: case 31: return "st";
+ case 2: case 22: return "nd";
+ case 3: case 23: return "rd";
+ default: return "th";
+ }
+ },
+
+ w: function(){
+ // summary: Numeric representation of the day of the week
+ return this.date.getDay() + "";
+ },
+
+ z: function(){
+ // summary: The day of the year (starting from 0)
+ var millis = this.date.getTime() - new Date(this.date.getFullYear(), 0, 1).getTime();
+ return Math.floor(millis/86400000) + "";
+ },
+
+ // Week
+
+ W: function(){
+ // summary: ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
+ var week;
+ var jan1_w = new Date(this.date.getFullYear(), 0, 1).getDay() + 1;
+ var w = this.date.getDay() + 1;
+ var z = parseInt(this.z());
+
+ if(z <= (8 - jan1_w) && jan1_w > 4){
+ var last_year = new Date(this.date.getFullYear() - 1, this.date.getMonth(), this.date.getDate());
+ if(jan1_w == 5 || (jan1_w == 6 && ddate.isLeapYear(last_year))){
+ week = 53;
+ }else{
+ week = 52;
+ }
+ }else{
+ var i;
+ if(Boolean(this.L())){
+ i = 366;
+ }else{
+ i = 365;
+ }
+ if((i - z) < (4 - w)){
+ week = 1;
+ }else{
+ var j = z + (7 - w) + (jan1_w - 1);
+ week = Math.ceil(j / 7);
+ if(jan1_w > 4){
+ --week;
+ }
+ }
+ }
+
+ return week;
+ },
+
+ // Month
+
+ F: function(){
+ // summary: A full textual representation of a month, such as January or March
+ return this.months[this.date.getMonth()];
+ },
+
+ m: function(){
+ // summary: Numeric representation of a month, with leading zeros
+ var n = this.n();
+ return (n.length == 1) ? "0" + n : n;
+ },
+
+ M: function(){
+ // summary: A short textual representation of a month, three letters
+ return this.months_3[this.date.getMonth()];
+ },
+
+ n: function(){
+ // summary: Numeric representation of a month, without leading zeros
+ return this.date.getMonth() + 1 + "";
+ },
+
+ t: function(){
+ // summary: Number of days in the given month
+ return (Boolean(this.L()) && this.date.getMonth() == 1) ? 29 : this.monthdays[this.getMonth()];
+ },
+
+ // Year
+
+ L: function(){
+ // summary: Whether it's a leap year
+ return (ddate.isLeapYear(this.date)) ? "1" : "0";
+ },
+
+ o: function(){
+ // summary:
+ // ISO-8601 year number. This has the same value as Y, except that if
+ // the ISO week number (W) belongs to the previous or next year, that year is used instead. (added in PHP 5.1.0)
+ // TODO: Figure out what this means
+ },
+
+ Y: function(){
+ // summary: A full numeric representation of a year, 4 digits
+ return this.date.getFullYear() + "";
+ },
+
+ y: function(){
+ // summary: A two digit representation of a year
+ return this.Y().slice(-2);
+ },
+
+ // Time
+
+ a: function(){
+ // summary: Lowercase Ante meridiem and Post meridiem
+ return this.date.getHours() >= 12 ? "pm" : "am";
+ },
+
+ b: function(){
+ // summary: Uppercase Ante meridiem and Post meridiem
+ return this.a().toUpperCase();
+ },
+
+ B: function(){
+ // summary:
+ // Swatch Internet time
+ // A day is 1,000 beats. All time is measured from GMT + 1
+ var off = this.date.getTimezoneOffset() + 60;
+ var secs = (this.date.getHours() * 3600) + (this.date.getMinutes() * 60) + this.getSeconds() + (off * 60);
+ var beat = Math.abs(Math.floor(secs / 86.4) % 1000) + "";
+ while(beat.length < 2) beat = "0" + beat;
+ return beat;
+ },
+
+ g: function(){
+ // summary: 12-hour format of an hour without leading zeros
+ return (this.date.getHours() > 12) ? this.date.getHours() - 12 + "" : this.date.getHours() + "";
+ },
+
+ G: function(){
+ // summary: 24-hour format of an hour without leading zeros
+ return this.date.getHours() + "";
+ },
+
+ h: function(){
+ // summary: 12-hour format of an hour with leading zeros
+ var g = this.g();
+ return (g.length == 1) ? "0" + g : g;
+ },
+
+ H: function(){
+ // summary: 24-hour format of an hour with leading zeros
+ var G = this.G();
+ return (G.length == 1) ? "0" + G : G;
+ },
+
+ i: function(){
+ // summary: Minutes with leading zeros
+ var mins = this.date.getMinutes() + "";
+ return (mins.length == 1) ? "0" + mins : mins;
+ },
+
+ s: function(){
+ // summary: Seconds, with leading zeros
+ var secs = this.date.getSeconds() + "";
+ return (secs.length == 1) ? "0" + secs : secs;
+ },
+
+ // Timezone
+
+ e: function(){
+ // summary: Timezone identifier (added in PHP 5.1.0)
+ return ddate.getTimezoneName(this.date);
+ },
+
+ I: function(){
+ // summary: Whether or not the date is in daylight saving time
+ // TODO: Can dojo.date do this?
+ },
+
+ O: function(){
+ // summary: Difference to Greenwich time (GMT) in hours
+ var off = Math.abs(this.date.getTimezoneOffset());
+ var hours = Math.floor(off / 60) + "";
+ var mins = (off % 60) + "";
+ if(hours.length == 1) hours = "0" + hours;
+ if(mins.length == 1) hours = "0" + mins;
+ return ((this.date.getTimezoneOffset() < 0) ? "+" : "-") + hours + mins;
+ },
+
+ P: function(){
+ // summary: Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
+ var O = this.O();
+ return O.substring(0, 2) + ":" + O.substring(2, 4);
+ },
+
+ T: function(){
+ // summary: Timezone abbreviation
+
+ // Guess...
+ return this.e().substring(0, 3);
+ },
+
+ Z: function(){
+ // summary:
+ // Timezone offset in seconds. The offset for timezones west of UTC is always negative,
+ // and for those east of UTC is always positive.
+ return this.date.getTimezoneOffset() * -60;
+ },
+
+ // Full Date/Time
+
+ c: function(){
+ // summary: ISO 8601 date (added in PHP 5)
+ return this.Y() + "-" + this.m() + "-" + this.d() + "T" + this.h() + ":" + this.i() + ":" + this.s() + this.P();
+ },
+
+ r: function(){
+ // summary: RFC 2822 formatted date
+ return this.D() + ", " + this.d() + " " + this.M() + " " + this.Y() + " " + this.H() + ":" + this.i() + ":" + this.s() + " " + this.O();
+ },
+
+ U: function(){
+ // summary: Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
+ return Math.floor(this.date.getTime() / 1000);
+ }
+
+});
+return dojox.date.php;
+});
+},
+'dojox/dtl/ext-dojo/NodeList':function(){
+define([
+ "dojo/_base/lang",
+ "dojo/_base/NodeList",
+ "../_base"
+], function(lang,Nodelist,dd){
+ /*=====
+ Nodelist = dojo.Nodelist;
+ dd = dojox.dtl;
+ =====*/
+
+ var nl = lang.getObject("dojox.dtl.ext-dojo.NodeList", true);
+
+ lang.extend(Nodelist, {
+ dtl: function(template, context){
+ // summary: Renders the specified template in each of the Nodelist entries.
+ // template: dojox.dtl.__StringArgs|String
+ // The template string or location
+ // context: dojox.dtl.__ObjectArgs|Object
+ // The context object or location
+ var d = dd, self = this;
+
+ var render = function(template, context){
+ var content = template.render(new d._Context(context));
+ self.forEach(function(node){
+ node.innerHTML = content;
+ });
+ }
+
+ d.text._resolveTemplateArg(template).addCallback(function(templateString){
+ template = new d.Template(templateString);
+ d.text._resolveContextArg(context).addCallback(function(context){
+ render(template, context);
+ });
+ });
+
+ return this;
+ }
+ });
+ return nl;
+});
+},
+'dojox/dtl/utils/date':function(){
+define("dojox/dtl/utils/date", [
+ "dojo/_base/lang",
+ "dojox/date/php",
+ "../_base"
+], function(lang,ddp,dd){
+ /*=====
+ ddp = dojox.data.php;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.utils.date", true);
+
+ dd.utils.date.DateFormat = ddp.DateFormat;
+ lang.extend(dd.utils.date.DateFormat, ddp.DateFormat.prototype, {
+ f: function(){
+ // summary:
+ // Time, in 12-hour hours and minutes, with minutes left off if they're zero.
+ // description:
+ // Examples: '1', '1:30', '2:05', '2'
+ // Proprietary extension.
+ return (!this.date.getMinutes()) ? this.g() : this.g() + ":" + this.i();
+ },
+ N: function(){
+ // summary: Month abbreviation in Associated Press style. Proprietary extension.
+ return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
+ },
+ P: function(){
+ // summary:
+ // Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
+ // if they're zero and the strings 'midnight' and 'noon' if appropriate.
+ // description:
+ // Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
+ // Proprietary extension.
+ if(!this.date.getMinutes() && !this.date.getHours()){
+ return 'midnight';
+ }
+ if(!this.date.getMinutes() && this.date.getHours() == 12){
+ return 'noon';
+ }
+ return this.f() + " " + this.a();
+ }
+ });
+
+ lang.mixin(dojox.dtl.utils.date, {
+ format: function(/*Date*/ date, /*String*/ format){
+ var df = new dojox.dtl.utils.date.DateFormat(format);
+ return df.format(date);
+ },
+ timesince: function(d, now){
+ // summary:
+ // Takes two datetime objects and returns the time between then and now
+ // as a nicely formatted string, e.g "10 minutes"
+ // description:
+ // Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
+ if(!(d instanceof Date)){
+ d = new Date(d.year, d.month, d.day);
+ }
+ if(!now){
+ now = new Date();
+ }
+
+ var delta = Math.abs(now.getTime() - d.getTime());
+ for(var i = 0, chunk; chunk = dojox.dtl.utils.date._chunks[i]; i++){
+ var count = Math.floor(delta / chunk[0]);
+ if(count) break;
+ }
+ return count + " " + chunk[1](count);
+ },
+ _chunks: [
+ [60 * 60 * 24 * 365 * 1000, function(n){ return (n == 1) ? 'year' : 'years'; }],
+ [60 * 60 * 24 * 30 * 1000, function(n){ return (n == 1) ? 'month' : 'months'; }],
+ [60 * 60 * 24 * 7 * 1000, function(n){ return (n == 1) ? 'week' : 'weeks'; }],
+ [60 * 60 * 24 * 1000, function(n){ return (n == 1) ? 'day' : 'days'; }],
+ [60 * 60 * 1000, function(n){ return (n == 1) ? 'hour' : 'hours'; }],
+ [60 * 1000, function(n){ return (n == 1) ? 'minute' : 'minutes'; }]
+ ],
+ _months_ap: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."]
+ });
+ return dojox.dtl.utils.date;
+});
+
+},
+'dojox/dtl/tag/loop':function(){
+define("dojox/dtl/tag/loop", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojo/_base/json",
+ "../_base",
+ "dojox/string/tokenize"
+], function(lang,array,json,dd,Tokenize){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loop", true);
+
+ var ddtl = dd.tag.loop;
+
+ ddtl.CycleNode = lang.extend(function(cyclevars, name, text, shared){
+ this.cyclevars = cyclevars;
+ this.name = name;
+ this.contents = text;
+ this.shared = shared || {counter: -1, map: {}};
+ },
+ {
+ render: function(context, buffer){
+ if(context.forloop && !context.forloop.counter0){
+ this.shared.counter = -1;
+ }
+
+ ++this.shared.counter;
+ var value = this.cyclevars[this.shared.counter % this.cyclevars.length];
+
+ var map = this.shared.map;
+ if(!map[value]){
+ map[value] = new dd._Filter(value);
+ }
+ value = map[value].resolve(context, buffer);
+
+ if(this.name){
+ context[this.name] = value;
+ }
+ this.contents.set(value);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.cyclevars, this.name, this.contents.clone(buffer), this.shared);
+ }
+ });
+
+ ddtl.IfChangedNode = lang.extend(function(nodes, vars, shared){
+ this.nodes = nodes;
+ this._vars = vars;
+ this.shared = shared || {last: null, counter: 0};
+ this.vars = array.map(vars, function(item){
+ return new dojox.dtl._Filter(item);
+ });
+ }, {
+ render: function(context, buffer){
+ if(context.forloop){
+ if(context.forloop.counter <= this.shared.counter){
+ this.shared.last = null;
+ }
+ this.shared.counter = context.forloop.counter;
+ }
+
+ var change;
+ if(this.vars.length){
+ change = json.toJson(array.map(this.vars, function(item){
+ return item.resolve(context);
+ }));
+ }else{
+ change = this.nodes.dummyRender(context, buffer);
+ }
+
+ if(change != this.shared.last){
+ var firstloop = (this.shared.last === null);
+ this.shared.last = change;
+ context = context.push();
+ context.ifchanged = {firstloop: firstloop};
+ buffer = this.nodes.render(context, buffer);
+ context = context.pop();
+ }else{
+ buffer = this.nodes.unrender(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodes.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodes.clone(buffer), this._vars, this.shared);
+ }
+ });
+
+ ddtl.RegroupNode = lang.extend(function(expression, key, alias){
+ this._expression = expression;
+ this.expression = new dd._Filter(expression);
+ this.key = key;
+ this.alias = alias;
+ },
+ {
+ _push: function(container, grouper, stack){
+ if(stack.length){
+ container.push({ grouper: grouper, list: stack });
+ }
+ },
+ render: function(context, buffer){
+ context[this.alias] = [];
+ var list = this.expression.resolve(context);
+ if(list){
+ var last = null;
+ var stack = [];
+ for(var i = 0; i < list.length; i++){
+ var id = list[i][this.key];
+ if(last !== id){
+ this._push(context[this.alias], last, stack);
+ last = id;
+ stack = [list[i]];
+ }else{
+ stack.push(list[i]);
+ }
+ }
+ this._push(context[this.alias], last, stack);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(context, buffer){
+ return this;
+ }
+ });
+
+ lang.mixin(ddtl, {
+ cycle: function(parser, token){
+ // summary: Cycle among the given strings each time this tag is encountered
+ var args = token.split_contents();
+
+ if(args.length < 2){
+ throw new Error("'cycle' tag requires at least two arguments");
+ }
+
+ if(args[1].indexOf(",") != -1){
+ var vars = args[1].split(",");
+ args = [args[0]];
+ for(var i = 0; i < vars.length; i++){
+ args.push('"' + vars[i] + '"');
+ }
+ }
+
+ if(args.length == 2){
+ var name = args[args.length - 1];
+
+ if(!parser._namedCycleNodes){
+ throw new Error("No named cycles in template: '" + name + "' is not defined");
+ }
+ if(!parser._namedCycleNodes[name]){
+ throw new Error("Named cycle '" + name + "' does not exist");
+ }
+
+ return parser._namedCycleNodes[name];
+ }
+
+ if(args.length > 4 && args[args.length - 2] == "as"){
+ var name = args[args.length - 1];
+
+ var node = new ddtl.CycleNode(args.slice(1, args.length - 2), name, parser.create_text_node());
+
+ if(!parser._namedCycleNodes){
+ parser._namedCycleNodes = {};
+ }
+ parser._namedCycleNodes[name] = node;
+ }else{
+ node = new ddtl.CycleNode(args.slice(1), null, parser.create_text_node());
+ }
+
+ return node;
+ },
+ ifchanged: function(parser, token){
+ var parts = token.contents.split();
+ var nodes = parser.parse(["endifchanged"]);
+ parser.delete_first_token();
+ return new ddtl.IfChangedNode(nodes, parts.slice(1));
+ },
+ regroup: function(parser, token){
+ var tokens = Tokenize(token.contents, /(\s+)/g, function(spaces){
+ return spaces;
+ });
+ if(tokens.length < 11 || tokens[tokens.length - 3] != "as" || tokens[tokens.length - 7] != "by"){
+ throw new Error("Expected the format: regroup list by key as newList");
+ }
+ var expression = tokens.slice(2, -8).join("");
+ var key = tokens[tokens.length - 5];
+ var alias = tokens[tokens.length - 1];
+ return new ddtl.RegroupNode(expression, key, alias);
+ }
+ });
+ return dojox.dtl.tag.loop;
+});
+},
+'dojox/string/Builder':function(){
+define("dojox/string/Builder", ["dojo/_base/lang"],
+ function(lang){
+ lang.getObject("string", true, dojox).Builder =
+ function(/*String?*/str){
+ // summary:
+ // A fast buffer for creating large strings.
+ //
+ // length: Number
+ // The current length of the internal string.
+
+ // N.B. the public nature of the internal buffer is no longer
+ // needed because the IE-specific fork is no longer needed--TRT.
+ var b = "";
+ this.length = 0;
+
+ this.append = function(/* String... */s){
+ // summary: Append all arguments to the end of the buffer
+ if(arguments.length>1){
+ /*
+ This is a loop unroll was designed specifically for Firefox;
+ it would seem that static index access on an Arguments
+ object is a LOT faster than doing dynamic index access.
+ Therefore, we create a buffer string and take advantage
+ of JS's switch fallthrough. The peformance of this method
+ comes very close to straight up string concatenation (+=).
+
+ If the arguments object length is greater than 9, we fall
+ back to standard dynamic access.
+
+ This optimization seems to have no real effect on either
+ Safari or Opera, so we just use it for all.
+
+ It turns out also that this loop unroll can increase performance
+ significantly with Internet Explorer, particularly when
+ as many arguments are provided as possible.
+
+ Loop unroll per suggestion from Kris Zyp, implemented by
+ Tom Trenka.
+
+ Note: added empty string to force a string cast if needed.
+ */
+ var tmp="", l=arguments.length;
+ switch(l){
+ case 9: tmp=""+arguments[8]+tmp;
+ case 8: tmp=""+arguments[7]+tmp;
+ case 7: tmp=""+arguments[6]+tmp;
+ case 6: tmp=""+arguments[5]+tmp;
+ case 5: tmp=""+arguments[4]+tmp;
+ case 4: tmp=""+arguments[3]+tmp;
+ case 3: tmp=""+arguments[2]+tmp;
+ case 2: {
+ b+=""+arguments[0]+arguments[1]+tmp;
+ break;
+ }
+ default: {
+ var i=0;
+ while(i\s+<'));
+ buffer = this.contents.render(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodelist.clone(buffer), this.contents.clone(buffer));
+ },
+ _isEmpty: function(node){
+ return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
+ },
+ _watch: function(node){
+ if(this._isEmpty(node)){
+ var remove = false;
+ if(node.parentNode.firstChild == node){
+ node.parentNode.removeChild(node);
+ }
+ }else{
+ var children = node.parentNode.childNodes;
+ if(node.nodeType == 1 && children.length > 2){
+ for(var i = 2, child; child = children[i]; i++){
+ if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
+ node.parentNode.removeChild(children[i - 1]);
+ return;
+ }
+ }
+ }
+ }
+ },
+ _watchParent: function(node){
+ var children = node.childNodes;
+ if(children.length){
+ while(node.childNodes.length){
+ var last = node.childNodes[node.childNodes.length - 1];
+ if(!this._isEmpty(last)){
+ return;
+ }
+ node.removeChild(last);
+ }
+ }
+ }
+ });
+
+ ddtm.TemplateTagNode = lang.extend(function(tag, text){
+ this.tag = tag;
+ this.contents = text;
+ },
+ {
+ mapping: {
+ openblock: "{%",
+ closeblock: "%}",
+ openvariable: "{{",
+ closevariable: "}}",
+ openbrace: "{",
+ closebrace: "}",
+ opencomment: "{#",
+ closecomment: "#}"
+ },
+ render: function(context, buffer){
+ this.contents.set(this.mapping[this.tag]);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.tag, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WidthRatioNode = lang.extend(function(current, max, width, text){
+ this.current = new dd._Filter(current);
+ this.max = new dd._Filter(max);
+ this.width = width;
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ var current = +this.current.resolve(context);
+ var max = +this.max.resolve(context);
+ if(typeof current != "number" || typeof max != "number" || !max){
+ this.contents.set("");
+ }else{
+ this.contents.set("" + Math.round((current / max) * this.width));
+ }
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WithNode = lang.extend(function(target, alias, nodelist){
+ this.target = new dd._Filter(target);
+ this.alias = alias;
+ this.nodelist = nodelist;
+ },
+ {
+ render: function(context, buffer){
+ var target = this.target.resolve(context);
+ context = context.push();
+ context[this.alias] = target;
+ buffer = this.nodelist.render(context, buffer);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtm, {
+ comment: function(parser, token){
+ // summary: Ignore everything between {% comment %} and {% endcomment %}
+ parser.skip_past("endcomment");
+ return dd._noOpNode;
+ },
+ debug: function(parser, token){
+ // summary: Output the current context, maybe add more stuff later.
+ return new ddtm.DebugNode(parser.create_text_node());
+ },
+ filter: function(parser, token){
+ // summary: Filter the contents of the blog through variable filters.
+ var rest = token.contents.split(null, 1)[1];
+ var varnode = parser.create_variable_node("var|" + rest);
+ var nodelist = parser.parse(["endfilter"]);
+ parser.next_token();
+ return new ddtm.FilterNode(varnode, nodelist);
+ },
+ firstof: function(parser, token){
+ var parts = token.split_contents().slice(1);
+ if(!parts.length){
+ throw new Error("'firstof' statement requires at least one argument");
+ }
+ return new ddtm.FirstOfNode(parts, parser.create_text_node());
+ },
+ spaceless: function(parser, token){
+ var nodelist = parser.parse(["endspaceless"]);
+ parser.delete_first_token();
+ return new ddtm.SpacelessNode(nodelist, parser.create_text_node());
+ },
+ templatetag: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error("'templatetag' statement takes one argument");
+ }
+ var tag = parts[1];
+ var mapping = ddtm.TemplateTagNode.prototype.mapping;
+ if(!mapping[tag]){
+ var keys = [];
+ for(var key in mapping){
+ keys.push(key);
+ }
+ throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
+ }
+ return new ddtm.TemplateTagNode(tag, parser.create_text_node());
+ },
+ widthratio: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 4){
+ throw new Error("widthratio takes three arguments");
+ }
+ var width = +parts[3];
+ if(typeof width != "number"){
+ throw new Error("widthratio final argument must be an integer");
+ }
+ return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.create_text_node());
+ },
+ with_: function(parser, token){
+ var parts = token.split_contents();
+ if(parts.length != 4 || parts[2] != "as"){
+ throw new Error("do_width expected format as 'with value as name'");
+ }
+ var nodelist = parser.parse(["endwith"]);
+ parser.next_token();
+ return new ddtm.WithNode(parts[1], parts[3], nodelist);
+ }
+ });
+ return dojox.dtl.tag.misc;
+});
+},
+'dojox/dtl/Context':function(){
+define("dojox/dtl/Context", [
+ "dojo/_base/lang",
+ "./_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ /*=====
+ dd.Context = function(dict){
+ // summary: Represents a runtime context used by DTL templates.
+ }
+
+ =====*/
+ dd.Context = lang.extend(function(dict){
+ this._this = {};
+ dd._Context.call(this, dict);
+ }, dd._Context.prototype,
+ {
+ getKeys: function(){
+ // summary: Returns the set of keys exported by this context.
+ var keys = [];
+ for(var key in this){
+ if(this.hasOwnProperty(key) && key != "_this"){
+ keys.push(key);
+ }
+ }
+ return keys;
+ },
+ extend: function(/*dojox.dtl.Context|Object*/ obj){
+ // summary: Returns a clone of this context object, with the items from the
+ // passed objecct mixed in.
+ return lang.delegate(this, obj);
+ },
+ filter: function(/*dojox.dtl.Context|Object|String...*/ filter){
+ // summary: Returns a clone of this context, only containing the items
+ // defined in the filter.
+ var context = new dd.Context();
+ var keys = [];
+ var i, arg;
+ if(filter instanceof dd.Context){
+ keys = filter.getKeys();
+ }else if(typeof filter == "object"){
+ for(var key in filter){
+ keys.push(key);
+ }
+ }else{
+ for(i = 0; arg = arguments[i]; i++){
+ if(typeof arg == "string"){
+ keys.push(arg);
+ }
+ }
+ }
+
+ for(i = 0, key; key = keys[i]; i++){
+ context[key] = this[key];
+ }
+
+ return context;
+ },
+ setThis: function(/*Object*/ _this){
+ // summary: Sets the object on which to perform operations.
+ // _this: the this ref.
+ this._this = _this;
+ },
+ getThis: function(){
+ // summary: Gets the object on which to perform operations.
+ return this._this;
+ },
+ hasKey: function(/*String*/key){
+ // summary: Indicates whether the specified key is defined on this context.
+ // key: The key to look up.
+ if(this._getter){
+ var got = this._getter(key);
+ if(typeof got != "undefined"){
+ return true;
+ }
+ }
+
+ if(typeof this[key] != "undefined"){
+ return true;
+ }
+
+ return false;
+ }
+});
+return dojox.dtl.Context;
+});
+},
+'dojox/dtl/tag/logic':function(){
+define([
+ "dojo/_base/lang",
+ "../_base"
+], function(lang, dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.logic", true);
+
+ var ddt = dd.text;
+ var ddtl = dd.tag.logic;
+
+ ddtl.IfNode = lang.extend(function(bools, trues, falses, type){
+ this.bools = bools;
+ this.trues = trues;
+ this.falses = falses;
+ this.type = type;
+ },
+ {
+ render: function(context, buffer){
+ var i, bool, ifnot, filter, value;
+ if(this.type == "or"){
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ if((value && !ifnot) || (ifnot && !value)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }else{
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ // If we ever encounter a false value
+ if(value == ifnot){
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ buffer = (this.trues) ? this.trues.unrender(context, buffer) : buffer;
+ buffer = (this.falses) ? this.falses.unrender(context, buffer) : buffer;
+ return buffer;
+ },
+ clone: function(buffer){
+ var trues = (this.trues) ? this.trues.clone(buffer) : null;
+ var falses = (this.falses) ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.bools, trues, falses, this.type);
+ }
+ });
+
+ ddtl.IfEqualNode = lang.extend(function(var1, var2, trues, falses, negate){
+ this.var1 = new dd._Filter(var1);
+ this.var2 = new dd._Filter(var2);
+ this.trues = trues;
+ this.falses = falses;
+ this.negate = negate;
+ },
+ {
+ render: function(context, buffer){
+ var var1 = this.var1.resolve(context);
+ var var2 = this.var2.resolve(context);
+ var1 = (typeof var1 != "undefined") ? var1 : "";
+ var2 = (typeof var1 != "undefined") ? var2 : "";
+ if((this.negate && var1 != var2) || (!this.negate && var1 == var2)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer, this);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer, this);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ },
+ unrender: function(context, buffer){
+ return ddtl.IfNode.prototype.unrender.call(this, context, buffer);
+ },
+ clone: function(buffer){
+ var trues = this.trues ? this.trues.clone(buffer) : null;
+ var falses = this.falses ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.var1.getExpression(), this.var2.getExpression(), trues, falses, this.negate);
+ }
+ });
+
+ ddtl.ForNode = lang.extend(function(assign, loop, reversed, nodelist){
+ this.assign = assign;
+ this.loop = new dd._Filter(loop);
+ this.reversed = reversed;
+ this.nodelist = nodelist;
+ this.pool = [];
+ },
+ {
+ render: function(context, buffer){
+ var i, j, k;
+ var dirty = false;
+ var assign = this.assign;
+
+ for(k = 0; k < assign.length; k++){
+ if(typeof context[assign[k]] != "undefined"){
+ dirty = true;
+ context = context.push();
+ break;
+ }
+ }
+ if(!dirty && context.forloop){
+ dirty = true;
+ context = context.push();
+ }
+
+ var items = this.loop.resolve(context) || [];
+ for(i = items.length; i < this.pool.length; i++){
+ this.pool[i].unrender(context, buffer, this);
+ }
+ if(this.reversed){
+ items = items.slice(0).reverse();
+ }
+
+ var isObject = lang.isObject(items) && !lang.isArrayLike(items);
+ var arred = [];
+ if(isObject){
+ for(var key in items){
+ arred.push(items[key]);
+ }
+ }else{
+ arred = items;
+ }
+
+ var forloop = context.forloop = {
+ parentloop: context.get("forloop", {})
+ };
+ var j = 0;
+ for(i = 0; i < arred.length; i++){
+ var item = arred[i];
+
+ forloop.counter0 = j;
+ forloop.counter = j + 1;
+ forloop.revcounter0 = arred.length - j - 1;
+ forloop.revcounter = arred.length - j;
+ forloop.first = !j;
+ forloop.last = (j == arred.length - 1);
+
+ if(assign.length > 1 && lang.isArrayLike(item)){
+ if(!dirty){
+ dirty = true;
+ context = context.push();
+ }
+ var zipped = {};
+ for(k = 0; k < item.length && k < assign.length; k++){
+ zipped[assign[k]] = item[k];
+ }
+ lang.mixin(context, zipped);
+ }else{
+ context[assign[0]] = item;
+ }
+
+ if(j + 1 > this.pool.length){
+ this.pool.push(this.nodelist.clone(buffer));
+ }
+ buffer = this.pool[j++].render(context, buffer, this);
+ }
+
+ delete context.forloop;
+ if(dirty){
+ context = context.pop();
+ }else{
+ for(k = 0; k < assign.length; k++){
+ delete context[assign[k]];
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ for(var i = 0, pool; pool = this.pool[i]; i++){
+ buffer = pool.unrender(context, buffer);
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.assign, this.loop.getExpression(), this.reversed, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtl, {
+ if_: function(parser, token){
+ var i, part, type, bools = [], parts = token.contents.split();
+ parts.shift();
+ token = parts.join(" ");
+ parts = token.split(" and ");
+ if(parts.length == 1){
+ type = "or";
+ parts = token.split(" or ");
+ }else{
+ type = "and";
+ for(i = 0; i < parts.length; i++){
+ if(parts[i].indexOf(" or ") != -1){
+ // Note, since we split by and, this is the only place we need to error check
+ throw new Error("'if' tags can't mix 'and' and 'or'");
+ }
+ }
+ }
+ for(i = 0; part = parts[i]; i++){
+ var not = false;
+ if(part.indexOf("not ") == 0){
+ part = part.slice(4);
+ not = true;
+ }
+ bools.push([not, new dd._Filter(part)]);
+ }
+ var trues = parser.parse(["else", "endif"]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse(["endif"]);
+ parser.next_token();
+ }
+ return new ddtl.IfNode(bools, trues, falses, type);
+ },
+ _ifequal: function(parser, token, negate){
+ var parts = token.split_contents();
+ if(parts.length != 3){
+ throw new Error(parts[0] + " takes two arguments");
+ }
+ var end = 'end' + parts[0];
+ var trues = parser.parse(["else", end]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse([end]);
+ parser.next_token();
+ }
+ return new ddtl.IfEqualNode(parts[1], parts[2], trues, falses, negate);
+ },
+ ifequal: function(parser, token){
+ return ddtl._ifequal(parser, token);
+ },
+ ifnotequal: function(parser, token){
+ return ddtl._ifequal(parser, token, true);
+ },
+ for_: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length < 4){
+ throw new Error("'for' statements should have at least four words: " + token.contents);
+ }
+ var reversed = parts[parts.length - 1] == "reversed";
+ var index = (reversed) ? -3 : -2;
+ if(parts[parts.length + index] != "in"){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ var loopvars = parts.slice(1, index).join(" ").split(/ *, */);
+ for(var i = 0; i < loopvars.length; i++){
+ if(!loopvars[i] || loopvars[i].indexOf(" ") != -1){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ }
+ var nodelist = parser.parse(["endfor"]);
+ parser.next_token();
+ return new ddtl.ForNode(loopvars, parts[parts.length + index + 1], reversed, nodelist);
+ }
+ });
+ return dojox.dtl.tag.logic;
+});
+},
+'dojox/dtl/tag/date':function(){
+define("dojox/dtl/tag/date", [
+ "dojo/_base/lang",
+ "../_base",
+ "../utils/date"
+], function(lang,dd,ddud){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.date", true);
+
+ dojox.dtl.tag.date.NowNode = function(format, node){
+ this._format = format;
+ this.format = new ddud.DateFormat(format);
+ this.contents = node;
+ }
+ lang.extend(dd.tag.date.NowNode, {
+ render: function(context, buffer){
+ this.contents.set(this.format.format(new Date()));
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this._format, this.contents.clone(buffer));
+ }
+ });
+
+ dojox.dtl.tag.date.now = function(parser, token){
+ // Split by either :" or :'
+ var parts = token.split_contents();
+ if(parts.length != 2){
+ throw new Error("'now' statement takes one argument");
+ }
+ return new dojox.dtl.tag.date.NowNode(parts[1].slice(1, -1), parser.create_text_node());
+ };
+ return dojox.dtl.tag.date;
+});
+
+}}});
+
+require(["dojo/i18n"], function(i18n){
+i18n._preloadLocalizations("dojox/nls/dtl", []);
+});
+define("dojox/dtl", ["./dtl/_base"], function(dxdtl){
+ return dxdtl;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/Context.js b/js/libs/dojox/dtl/Context.js
new file mode 100644
index 0000000..e029fe4
--- /dev/null
+++ b/js/libs/dojox/dtl/Context.js
@@ -0,0 +1,56 @@
+//>>built
+define("dojox/dtl/Context",["dojo/_base/lang","./_base"],function(_1,dd){
+dd.Context=_1.extend(function(_2){
+this._this={};
+dd._Context.call(this,_2);
+},dd._Context.prototype,{getKeys:function(){
+var _3=[];
+for(var _4 in this){
+if(this.hasOwnProperty(_4)&&_4!="_this"){
+_3.push(_4);
+}
+}
+return _3;
+},extend:function(_5){
+return _1.delegate(this,_5);
+},filter:function(_6){
+var _7=new dd.Context();
+var _8=[];
+var i,_9;
+if(_6 instanceof dd.Context){
+_8=_6.getKeys();
+}else{
+if(typeof _6=="object"){
+for(var _a in _6){
+_8.push(_a);
+}
+}else{
+for(i=0;_9=arguments[i];i++){
+if(typeof _9=="string"){
+_8.push(_9);
+}
+}
+}
+}
+for(i=0,_a;_a=_8[i];i++){
+_7[_a]=this[_a];
+}
+return _7;
+},setThis:function(_b){
+this._this=_b;
+},getThis:function(){
+return this._this;
+},hasKey:function(_c){
+if(this._getter){
+var _d=this._getter(_c);
+if(typeof _d!="undefined"){
+return true;
+}
+}
+if(typeof this[_c]!="undefined"){
+return true;
+}
+return false;
+}});
+return dojox.dtl.Context;
+});
diff --git a/js/libs/dojox/dtl/Context.js.uncompressed.js b/js/libs/dojox/dtl/Context.js.uncompressed.js
new file mode 100644
index 0000000..b9de03b
--- /dev/null
+++ b/js/libs/dojox/dtl/Context.js.uncompressed.js
@@ -0,0 +1,89 @@
+//>>built
+define("dojox/dtl/Context", [
+ "dojo/_base/lang",
+ "./_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ /*=====
+ dd.Context = function(dict){
+ // summary: Represents a runtime context used by DTL templates.
+ }
+
+ =====*/
+ dd.Context = lang.extend(function(dict){
+ this._this = {};
+ dd._Context.call(this, dict);
+ }, dd._Context.prototype,
+ {
+ getKeys: function(){
+ // summary: Returns the set of keys exported by this context.
+ var keys = [];
+ for(var key in this){
+ if(this.hasOwnProperty(key) && key != "_this"){
+ keys.push(key);
+ }
+ }
+ return keys;
+ },
+ extend: function(/*dojox.dtl.Context|Object*/ obj){
+ // summary: Returns a clone of this context object, with the items from the
+ // passed objecct mixed in.
+ return lang.delegate(this, obj);
+ },
+ filter: function(/*dojox.dtl.Context|Object|String...*/ filter){
+ // summary: Returns a clone of this context, only containing the items
+ // defined in the filter.
+ var context = new dd.Context();
+ var keys = [];
+ var i, arg;
+ if(filter instanceof dd.Context){
+ keys = filter.getKeys();
+ }else if(typeof filter == "object"){
+ for(var key in filter){
+ keys.push(key);
+ }
+ }else{
+ for(i = 0; arg = arguments[i]; i++){
+ if(typeof arg == "string"){
+ keys.push(arg);
+ }
+ }
+ }
+
+ for(i = 0, key; key = keys[i]; i++){
+ context[key] = this[key];
+ }
+
+ return context;
+ },
+ setThis: function(/*Object*/ _this){
+ // summary: Sets the object on which to perform operations.
+ // _this: the this ref.
+ this._this = _this;
+ },
+ getThis: function(){
+ // summary: Gets the object on which to perform operations.
+ return this._this;
+ },
+ hasKey: function(/*String*/key){
+ // summary: Indicates whether the specified key is defined on this context.
+ // key: The key to look up.
+ if(this._getter){
+ var got = this._getter(key);
+ if(typeof got != "undefined"){
+ return true;
+ }
+ }
+
+ if(typeof this[key] != "undefined"){
+ return true;
+ }
+
+ return false;
+ }
+});
+return dojox.dtl.Context;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/DomInline.js b/js/libs/dojox/dtl/DomInline.js
new file mode 100644
index 0000000..7184126
--- /dev/null
+++ b/js/libs/dojox/dtl/DomInline.js
@@ -0,0 +1,26 @@
+//>>built
+define("dojox/dtl/DomInline",["dojo/_base/lang","./dom","./_base","dijit/_WidgetBase"],function(_1,_2,dd,_3){
+dd.DomInline=_1.extend(function(_4,_5){
+this.create(_4,_5);
+},_3.prototype,{context:null,render:function(_6){
+this.context=_6||this.context;
+this.postMixInProperties();
+var _7=this.template.render(this.context).getRootNode();
+if(_7!=this.containerNode){
+this.containerNode.parentNode.replaceChild(_7,this.containerNode);
+this.containerNode=_7;
+}
+},declaredClass:"dojox.dtl.Inline",buildRendering:function(){
+var _8=this.domNode=document.createElement("div");
+this.containerNode=_8.appendChild(document.createElement("div"));
+var _9=this.srcNodeRef;
+if(_9.parentNode){
+_9.parentNode.replaceChild(_8,_9);
+}
+this.template=new dojox.dtl.DomTemplate(_1.trim(_9.text),true);
+this.render();
+},postMixInProperties:function(){
+this.context=(this.context.get===dojox.dtl._Context.prototype.get)?this.context:new dojox.dtl.Context(this.context);
+}});
+return dojox.dtl.DomInline;
+});
diff --git a/js/libs/dojox/dtl/DomInline.js.uncompressed.js b/js/libs/dojox/dtl/DomInline.js.uncompressed.js
new file mode 100644
index 0000000..2250c81
--- /dev/null
+++ b/js/libs/dojox/dtl/DomInline.js.uncompressed.js
@@ -0,0 +1,44 @@
+//>>built
+define("dojox/dtl/DomInline", [
+ "dojo/_base/lang",
+ "./dom",
+ "./_base",
+ "dijit/_WidgetBase"
+], function(lang,ddd,dd,Widget){
+ /*=====
+ dd = dojox.dtl;
+ Widget = dijit._WidgetBase;
+ =====*/
+ dd.DomInline = lang.extend(function(args, node){
+ this.create(args, node);
+ },
+ Widget.prototype,
+ {
+ context: null,
+ render: function(/*dojox.dtl.Context?*/ context){
+ this.context = context || this.context;
+ this.postMixInProperties();
+ var root = this.template.render(this.context).getRootNode();
+ if(root != this.containerNode){
+ this.containerNode.parentNode.replaceChild(root, this.containerNode);
+ this.containerNode = root;
+ }
+ },
+ declaredClass: "dojox.dtl.Inline",
+ buildRendering: function(){
+ var div = this.domNode = document.createElement("div");
+ this.containerNode = div.appendChild(document.createElement("div"));
+ var node = this.srcNodeRef;
+ if(node.parentNode){
+ node.parentNode.replaceChild(div, node);
+ }
+
+ this.template = new dojox.dtl.DomTemplate(lang.trim(node.text), true);
+ this.render();
+ },
+ postMixInProperties: function(){
+ this.context = (this.context.get === dojox.dtl._Context.prototype.get) ? this.context : new dojox.dtl.Context(this.context);
+ }
+ });
+ return dojox.dtl.DomInline;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/Inline.js b/js/libs/dojox/dtl/Inline.js
new file mode 100644
index 0000000..1fbb218
--- /dev/null
+++ b/js/libs/dojox/dtl/Inline.js
@@ -0,0 +1,22 @@
+//>>built
+define("dojox/dtl/Inline",["dojo/_base/lang","./_base","dijit/_WidgetBase","dojo/query"],function(_1,dd,_2,_3){
+dd.Inline=_1.extend(function(_4,_5){
+this.create(_4,_5);
+},_2.prototype,{context:null,render:function(_6){
+this.context=_6||this.context;
+this.postMixInProperties();
+_3("*",this.domNode).orphan();
+this.domNode.innerHTML=this.template.render(this.context);
+},declaredClass:"dojox.dtl.Inline",buildRendering:function(){
+var _7=this.domNode=document.createElement("div");
+var _8=this.srcNodeRef;
+if(_8.parentNode){
+_8.parentNode.replaceChild(_7,_8);
+}
+this.template=new dd.Template(_1.trim(_8.text),true);
+this.render();
+},postMixInProperties:function(){
+this.context=(this.context.get===dd._Context.prototype.get)?this.context:new dd._Context(this.context);
+}});
+return dojox.dtl.Inline;
+});
diff --git a/js/libs/dojox/dtl/Inline.js.uncompressed.js b/js/libs/dojox/dtl/Inline.js.uncompressed.js
new file mode 100644
index 0000000..56b1d05
--- /dev/null
+++ b/js/libs/dojox/dtl/Inline.js.uncompressed.js
@@ -0,0 +1,41 @@
+//>>built
+define("dojox/dtl/Inline", [
+ "dojo/_base/lang",
+ "./_base",
+ "dijit/_WidgetBase",
+ "dojo/query" // dojo.query
+], function(lang,dd,Widget,Query){
+ /*=====
+ Widget = dijit._WidgetBase;
+ Query = dojo.query;
+ dd = dojox.dtl;
+ =====*/
+ dd.Inline = lang.extend(function(args, node){
+ this.create(args, node);
+ },
+ Widget.prototype,
+ {
+ context: null,
+ render: function(/*Object|dojox.dtl.Context?*/ context){
+ this.context = context || this.context;
+ this.postMixInProperties();
+ Query("*", this.domNode).orphan();
+ this.domNode.innerHTML = this.template.render(this.context);
+ },
+ declaredClass: "dojox.dtl.Inline",
+ buildRendering: function(){
+ var div = this.domNode = document.createElement("div");
+ var node = this.srcNodeRef;
+ if(node.parentNode){
+ node.parentNode.replaceChild(div, node);
+ }
+
+ this.template = new dd.Template(lang.trim(node.text), true);
+ this.render();
+ },
+ postMixInProperties: function(){
+ this.context = (this.context.get === dd._Context.prototype.get) ? this.context : new dd._Context(this.context);
+ }
+ });
+ return dojox.dtl.Inline;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/README b/js/libs/dojox/dtl/README
new file mode 100644
index 0000000..54dd4f3
--- /dev/null
+++ b/js/libs/dojox/dtl/README
@@ -0,0 +1,207 @@
+-------------------------------------------------------------------------------
+DojoX Django Template Language
+-------------------------------------------------------------------------------
+Version 0.0
+Release date: 09/20/2007
+-------------------------------------------------------------------------------
+Project state: experimental/feature incomplete
+-------------------------------------------------------------------------------
+Project authors
+ Neil Roberts (pottedmeat@dojotoolkit.org)
+-------------------------------------------------------------------------------
+Project description
+
+The Django Template language uses a system of templates that can be compiled
+once and rendered indefinitely afterwards. It uses a simple system of tags
+and filters.
+
+This is a 1:1 match with the Django Template Language as outlined in
+http://www.djangoproject.com/documentation/templates/. All applicable tags and
+filters have been implemented (see below), along with new filters and tags as
+necessary (see below).
+
+The Django Template Language is intended within Django to only handle text.
+Our implementation is able to handle HTML in addition to text. Actually, the
+text and HTML portions of dojox.dtl are two separate layers, the HTML layer
+sits on top of the text layer (base). It's also been implemented in such a way
+that you have little to fear when moving your code from Django to dojox.dtl.
+Your existing templates should work, and will benefit from the massive
+performance gain of being able to manipulate nodes, rather than having to do
+clunky innerHTML swaps you would have to do with a text-only system. It also
+allows for new HTML-centric abilities, outlined below.
+
+Despite having two levels of complexity, if you write your tags correctly, they
+will work in both environments.
+-------------------------------------------------------------------------------
+Dependencies
+
+Base:
+dojox.string.Builder
+
+Date filters and tags:
+dojox.date.php
+
+Widget:
+dijit._Widget
+dijit._Container
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/dtl.js
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/dtl/*
+
+Install into the following directory structure:
+/dojox/dtl/
+
+...which should be at the same level as your Dojo checkout.
+-------------------------------------------------------------------------------
+What's Been Done
+
+Note: HTML Unit Tests should only be around for the oddities of HTML, tag/filter
+code is the same for each environment with minor exceptions. Cloning of all tags
+should be tested inside a for loop.
+
+| Implemented | Tag | Text Unit Test | HTML Unit Test |
+| X | block | X | |
+| X | comment | X | |
+| X | cycle | X | |
+| X | debug | X | |
+| X | extends | X | |
+| X | filter | X | |
+| X | firstof | X | |
+| X | for | X | |
+| X | if | X | |
+| X | ifchanged | X | X |
+| X | ifequal | X | |
+| X | ifnotequal | X | |
+| X | include | X | X |
+| X | load | X | |
+| X | now | X | |
+| X | regroup | X | |
+| X | spaceless | X | X |
+| X | ssi | X | X |
+| X | templatetag | X | |
+| N/A | url | | |
+| X | widthratio | X | |
+| X | with | X | |
+
+| Implemented | Filter | Text Unit Test | HTML Unit Test |
+| X | add | X | |
+| X | addslashes | X | |
+| X | capfirst | X | |
+| X | center | X | |
+| X | cut | X | |
+| X | date | X | |
+| X | default | X | |
+| X | default_if_none | X | |
+| X | dictsort | X | |
+| X | dictsort_reversed | X | |
+| X | divisibleby | X | |
+| X | escape | X | |
+| X | filesizeformat | X | |
+| X | first | X | |
+| X | fix_ampersands | X | |
+| X | floatformat | X | |
+| X | get_digit | X | |
+| X | iriencode | X | |
+| X | join | X | |
+| X | length | X | |
+| X | length_is | X | |
+| X | linebreaks | X | |
+| X | linebreaksbr | X | |
+| X | linenumbers | X | |
+| X | ljust | X | |
+| X | lower | X | |
+| X | make_list | X | |
+| X | phone2numeric | X | |
+| X | pluralize | X | |
+| X | pprint | X | |
+| X | random | X | |
+| X | removetags | X | |
+| X | rjust | X | |
+| X | slice | X | |
+| X | slugify | X | |
+| X | stringformat | X | |
+| X | striptags | X | |
+| X | time | X | |
+| X | timesince | X | |
+| X | timeuntil | X | |
+| X | title | X | |
+| X | truncatewords | X | |
+| X | truncatewords_html | X | |
+| X | unordered_list | X | |
+| X | upper | X | |
+| X | urlencode | X | |
+| X | urlize | X | |
+| X | urlizetrunc | X | |
+| X | wordcount | X | |
+| X | wordwrap | X | |
+| X | yesno | X | |
+-------------------------------------------------------------------------------
+HTML-Specific Additions
+-------------------------------------------------------------------------------
+{%extends "shared:templates/template.html" %}
+
+When using the {% extends %} tag, we don't always want to replace the parent
+node in DOM. For example, if we have a list view and a detail view, but both
+share the same base template, we want it to share the parent template. This
+basically means that the same nodes will be used in the parent for both views.
+
+To use this, simply add "shared:" to the beginning of the specified template.
+-------------------------------------------------------------------------------
+
+
+Some browsers treat comment nodes as full fledged nodes. If performance is
+important to you, you can wrap your markup in comments. The comments will be
+automatically stripped for browsers that cannot support this.
+-------------------------------------------------------------------------------
+Attribute Tags
+
+If a tag name begins with "attr:" then it will be able to inject an object
+into the parsed template. (See dojox.dtl.tag.event.EventNode)
+
+onclick/onmouseover/etc attributes work by attaching to the rendering object.
+
+tstyle attribute allows for styles to be changed dynamically. Use them just
+like a "style" attribute.
+
+attach attribute attaches the node to the rendering object.
+-------------------------------------------------------------------------------
+New Context Functions
+
+setThis() and getThis() returns the object "in charge" of the current rendering.
+This is used so that we can attach events.
+
+mixin() and filter() clone the current context, and either add to or reduce
+the keys in the context.
+-------------------------------------------------------------------------------
+Buffers
+
+Both the base and HTML versions of dojox.dtl use buffers. The base version uses
+dojox.string.Builder and the HTML version uses dojox.dtl.DomBuffer.
+
+The HTML buffer has several calls important to rendering:
+
+setParent/getParent/concat/remove:
+
+setParent and concat are used in order to render our HTML. As we move through
+the parsed template, different nodes change the parent or add on to the
+current parent. getParent is useful in things like the attribute tags, since
+they can use getParent to find the node that they're an attribute on. remove is
+used during unrendering.
+
+setAttribute:
+
+Sets an attribute on the current parent
+-------------------------------------------------------------------------------
+Tags Need clone/unrender Functions.
+
+One of the biggest challenges of getting dojox.dtl to work in an HTML
+environment was logic blocks. Nodes and objects inside a for loop need to be
+cloned, they can't simply be re-rendered, especially if they involve a Node.
+Also, in the case of an if/else block, we need to be able to not just render
+one of the blocks, but also unrender the second.
+
+This is really simple code, a good example is the dojox.dtl.DomNode
+object. Each function in this object is only one line long.
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/_DomTemplated.js b/js/libs/dojox/dtl/_DomTemplated.js
new file mode 100644
index 0000000..c0a833e
--- /dev/null
+++ b/js/libs/dojox/dtl/_DomTemplated.js
@@ -0,0 +1,58 @@
+//>>built
+define("dojox/dtl/_DomTemplated",["dojo/dom-construct",".","./contrib/dijit","./render/dom","dojo/cache","dijit/_TemplatedMixin"],function(_1,_2,_3,_4,_5,_6){
+_2._DomTemplated=function(){
+};
+_2._DomTemplated.prototype={_dijitTemplateCompat:false,buildRendering:function(){
+this.domNode=this.srcNodeRef;
+if(!this._render){
+var _7=_3.widgetsInTemplate;
+_3.widgetsInTemplate=this.widgetsInTemplate;
+this.template=this.template||this._getCachedTemplate(this.templatePath,this.templateString);
+this._render=new _4.Render(this.domNode,this.template);
+_3.widgetsInTemplate=_7;
+}
+var _8=this._getContext();
+if(!this._created){
+delete _8._getter;
+}
+this.render(_8);
+this.domNode=this.template.getRootNode();
+if(this.srcNodeRef&&this.srcNodeRef.parentNode){
+_1.destroy(this.srcNodeRef);
+delete this.srcNodeRef;
+}
+},setTemplate:function(_9,_a){
+if(dojox.dtl.text._isTemplate(_9)){
+this.template=this._getCachedTemplate(null,_9);
+}else{
+this.template=this._getCachedTemplate(_9);
+}
+this.render(_a);
+},render:function(_b,_c){
+if(_c){
+this.template=_c;
+}
+this._render.render(this._getContext(_b),this.template);
+},_getContext:function(_d){
+if(!(_d instanceof dojox.dtl.Context)){
+_d=false;
+}
+_d=_d||new dojox.dtl.Context(this);
+_d.setThis(this);
+return _d;
+},_getCachedTemplate:function(_e,_f){
+if(!this._templates){
+this._templates={};
+}
+if(!_f){
+_f=_5(_e,{sanitize:true});
+}
+var key=_f;
+var _10=this._templates;
+if(_10[key]){
+return _10[key];
+}
+return (_10[key]=new dojox.dtl.DomTemplate(_6.getCachedTemplate(_f,true)));
+}};
+return dojox.dtl._DomTemplated;
+});
diff --git a/js/libs/dojox/dtl/_DomTemplated.js.uncompressed.js b/js/libs/dojox/dtl/_DomTemplated.js.uncompressed.js
new file mode 100644
index 0000000..0c952f9
--- /dev/null
+++ b/js/libs/dojox/dtl/_DomTemplated.js.uncompressed.js
@@ -0,0 +1,100 @@
+//>>built
+define("dojox/dtl/_DomTemplated", [
+ "dojo/dom-construct",
+ ".",
+ "./contrib/dijit",
+ "./render/dom",
+ "dojo/cache",
+ "dijit/_TemplatedMixin"
+ ], function(domConstruct,dtl,ddcd,ddrd,cache,TemplatedMixin){
+ /*=====
+ dtl = dojox.dtl;
+ cache = dojo.cache;
+ TemplatedMixin = dijit._TemplatedMixin
+ =====*/
+ dtl._DomTemplated = function(){};
+ dtl._DomTemplated.prototype = {
+ _dijitTemplateCompat: false,
+ buildRendering: function(){
+ // summary:
+ // Construct the UI for this widget, setting this.domNode.
+
+ //render needs a domNode to work with
+ this.domNode = this.srcNodeRef;
+
+ if(!this._render){
+ var old = ddcd.widgetsInTemplate;
+ ddcd.widgetsInTemplate = this.widgetsInTemplate;
+ this.template = this.template || this._getCachedTemplate(this.templatePath, this.templateString);
+ this._render = new ddrd.Render(this.domNode, this.template);
+ ddcd.widgetsInTemplate = old;
+ }
+
+ var context = this._getContext();
+ if(!this._created){
+ delete context._getter;
+ }
+ this.render(context);
+
+ this.domNode = this.template.getRootNode();
+ if(this.srcNodeRef && this.srcNodeRef.parentNode){
+ domConstruct.destroy(this.srcNodeRef);
+ delete this.srcNodeRef;
+ }
+ },
+ setTemplate: function(/*String|dojo._Url*/ template, /*dojox.dtl.Context?*/ context){
+ // summary:
+ // Quickly switch between templated by location
+ // template: The new template.
+ // context:
+ // The runtime context.
+ if(dojox.dtl.text._isTemplate(template)){
+ this.template = this._getCachedTemplate(null, template);
+ }else{
+ this.template = this._getCachedTemplate(template);
+ }
+ this.render(context);
+ },
+ render: function(/*dojox.dtl.Context?*/ context, /*dojox.dtl.DomTemplate?*/ tpl){
+ // summary:
+ // Renders this template.
+ // context:
+ // The runtime context.
+ // tpl:
+ // The template to render. Optional.
+ if(tpl){
+ this.template = tpl;
+ }
+ this._render.render(this._getContext(context), this.template);
+ },
+ _getContext: function(context){
+ if(!(context instanceof dojox.dtl.Context)){
+ context = false;
+ }
+ context = context || new dojox.dtl.Context(this);
+ context.setThis(this);
+ return context;
+ },
+ _getCachedTemplate: function(templatePath, templateString){
+ if(!this._templates){
+ this._templates = {};
+ }
+ if(!templateString){
+ templateString = cache(templatePath, {sanitize: true});
+ }
+ var key = templateString;
+ var tmplts = this._templates;
+ if(tmplts[key]){
+ return tmplts[key];
+ }
+ return (tmplts[key] = new dojox.dtl.DomTemplate(
+ TemplatedMixin.getCachedTemplate(
+ templateString,
+ true
+ )
+ ));
+ }
+ };
+ return dojox.dtl._DomTemplated;
+});
+
diff --git a/js/libs/dojox/dtl/_Templated.js b/js/libs/dojox/dtl/_Templated.js
new file mode 100644
index 0000000..f10cdfa
--- /dev/null
+++ b/js/libs/dojox/dtl/_Templated.js
@@ -0,0 +1,86 @@
+//>>built
+define("dojox/dtl/_Templated",["dojo/_base/declare","./_base","dijit/_TemplatedMixin","dojo/dom-construct","dojo/cache","dojo/_base/array","dojo/string","dojo/parser","dijit/_base/manager"],function(_1,dd,_2,_3,_4,_5,_6,_7,_8){
+return _1("dojox.dtl._Templated",_2,{_dijitTemplateCompat:false,buildRendering:function(){
+var _9;
+if(this.domNode&&!this._template){
+return;
+}
+if(!this._template){
+var t=this.getCachedTemplate(this.templatePath,this.templateString,this._skipNodeCache);
+if(t instanceof dd.Template){
+this._template=t;
+}else{
+_9=t;
+}
+}
+if(!_9){
+var _a=new dd._Context(this);
+if(!this._created){
+delete _a._getter;
+}
+var _b=_3.toDom(this._template.render(_a));
+if(_b.nodeType!==1&&_b.nodeType!==3){
+for(var i=0,l=_b.childNodes.length;i>built
+define("dojox/dtl/_Templated", [
+ "dojo/_base/declare",
+ "./_base",
+ "dijit/_TemplatedMixin",
+ "dojo/dom-construct",
+ "dojo/cache",
+ "dojo/_base/array",
+ "dojo/string",
+ "dojo/parser",
+ "dijit/_base/manager"
+], function(declare,dd,TemplatedMixin, domConstruct,Cache,Array,dString,Parser,dijitMgr){
+ /*=====
+ Cache = dojo.cache;
+ dString = dojo.string;
+ Parser = dojo.parser;
+ TemplatedMixin = dijit._TemplatedMixin;
+ dd = dojox.dtl;
+ =====*/
+ return declare("dojox.dtl._Templated", TemplatedMixin, {
+ // summary: The base-class for DTL-templated widgets.
+
+ _dijitTemplateCompat: false,
+ buildRendering: function(){
+ // summary: The method overrides dijit._TemplatedMixin.startup.
+ var node;
+
+ if(this.domNode && !this._template){
+ return;
+ }
+
+ if(!this._template){
+ var t = this.getCachedTemplate(
+ this.templatePath,
+ this.templateString,
+ this._skipNodeCache
+ );
+ if(t instanceof dd.Template) {
+ this._template = t;
+ }else{
+ node = t;
+ }
+ }
+ if(!node){
+ var context = new dd._Context(this);
+ if(!this._created){
+ delete context._getter;
+ }
+ var nodes = domConstruct.toDom(
+ this._template.render(context)
+ );
+ // TODO: is it really necessary to look for the first node?
+ if(nodes.nodeType !== 1 && nodes.nodeType !== 3){
+ // nodes.nodeType === 11
+ // the node is a document fragment
+ for(var i = 0, l = nodes.childNodes.length; i < l; ++i){
+ node = nodes.childNodes[i];
+ if(node.nodeType == 1){
+ break;
+ }
+ }
+ }else{
+ // the node is an element or a text
+ node = nodes;
+ }
+ }
+ this._attachTemplateNodes(node, function(n,p){
+ return n.getAttribute(p);
+ });
+ if(this.widgetsInTemplate){
+ //Make sure dojoType is used for parsing widgets in template.
+ //The Parser.query could be changed from multiversion support.
+ var parser = Parser, qry, attr;
+ if(parser._query != "[dojoType]"){
+ qry = parser._query;
+ attr = parser._attrName;
+ parser._query = "[dojoType]";
+ parser._attrName = "dojoType";
+ }
+
+ //Store widgets that we need to start at a later point in time
+ var cw = (this._startupWidgets = Parser.parse(node, {
+ noStart: !this._earlyTemplatedStartup,
+ inherited: {dir: this.dir, lang: this.lang}
+ }));
+
+ //Restore the query.
+ if(qry){
+ parser._query = qry;
+ parser._attrName = attr;
+ }
+
+ this._supportingWidgets = dijitMgr.findWidgets(node);
+
+ this._attachTemplateNodes(cw, function(n,p){
+ return n[p];
+ });
+ }
+
+ if(this.domNode){
+ domConstruct.place(node, this.domNode, "before");
+ this.destroyDescendants();
+ domConstruct.destroy(this.domNode);
+ }
+ this.domNode = node;
+
+ this._fillContent(this.srcNodeRef);
+ },
+ _templateCache: {},
+ getCachedTemplate: function(templatePath, templateString, alwaysUseString){
+ // summary:
+ // Layer for dijit._Templated.getCachedTemplate
+ var tmplts = this._templateCache;
+ var key = templateString || templatePath;
+ if(tmplts[key]){
+ return tmplts[key];
+ }
+
+ templateString = dString.trim(templateString || Cache(templatePath, {sanitize: true}));
+
+ if( this._dijitTemplateCompat &&
+ (alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g))
+ ){
+ templateString = this._stringRepl(templateString);
+ }
+
+ // If we always use a string, or find no variables, just store it as a node
+ if(alwaysUseString || !templateString.match(/\{[{%]([^\}]+)[%}]\}/g)){
+ return tmplts[key] = domConstruct.toDom(templateString);
+ }else{
+ return tmplts[key] = new dd.Template(templateString);
+ }
+ },
+ render: function(){
+ // summary: Renders the widget.
+ this.buildRendering();
+ },
+ startup: function(){
+ // summary: The method overrides dijit._TemplatedMixin.startup.
+ Array.forEach(this._startupWidgets, function(w){
+ if(w && !w._started && w.startup){
+ w.startup();
+ }
+ });
+ this.inherited(arguments);
+ }
+ });
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/_base.js b/js/libs/dojox/dtl/_base.js
new file mode 100644
index 0000000..6f65019
--- /dev/null
+++ b/js/libs/dojox/dtl/_base.js
@@ -0,0 +1,578 @@
+//>>built
+define("dojox/dtl/_base",["dojo/_base/kernel","dojo/_base/lang","dojox/string/tokenize","dojo/_base/json","dojo/dom","dojo/_base/xhr","dojox/string/Builder","dojo/_base/Deferred"],function(_1,_2,_3,_4,_5,_6,_7,_8){
+_1.experimental("dojox.dtl");
+var dd=_2.getObject("dojox.dtl",true);
+dd._base={};
+dd.TOKEN_BLOCK=-1;
+dd.TOKEN_VAR=-2;
+dd.TOKEN_COMMENT=-3;
+dd.TOKEN_TEXT=3;
+dd._Context=_2.extend(function(_9){
+if(_9){
+_2._mixin(this,_9);
+if(_9.get){
+this._getter=_9.get;
+delete this.get;
+}
+}
+},{push:function(){
+var _a=this;
+var _b=_2.delegate(this);
+_b.pop=function(){
+return _a;
+};
+return _b;
+},pop:function(){
+throw new Error("pop() called on empty Context");
+},get:function(_c,_d){
+var n=this._normalize;
+if(this._getter){
+var _e=this._getter(_c);
+if(_e!==undefined){
+return n(_e);
+}
+}
+if(this[_c]!==undefined){
+return n(this[_c]);
+}
+return _d;
+},_normalize:function(_f){
+if(_f instanceof Date){
+_f.year=_f.getFullYear();
+_f.month=_f.getMonth()+1;
+_f.day=_f.getDate();
+_f.date=_f.year+"-"+("0"+_f.month).slice(-2)+"-"+("0"+_f.day).slice(-2);
+_f.hour=_f.getHours();
+_f.minute=_f.getMinutes();
+_f.second=_f.getSeconds();
+_f.microsecond=_f.getMilliseconds();
+}
+return _f;
+},update:function(_10){
+var _11=this.push();
+if(_10){
+_2._mixin(this,_10);
+}
+return _11;
+}});
+var _12=/("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
+var _13=/\s+/g;
+var _14=function(_15,_16){
+_15=_15||_13;
+if(!(_15 instanceof RegExp)){
+_15=new RegExp(_15,"g");
+}
+if(!_15.global){
+throw new Error("You must use a globally flagged RegExp with split "+_15);
+}
+_15.exec("");
+var _17,_18=[],_19=0,i=0;
+while((_17=_15.exec(this))){
+_18.push(this.slice(_19,_15.lastIndex-_17[0].length));
+_19=_15.lastIndex;
+if(_16&&(++i>_16-1)){
+break;
+}
+}
+_18.push(this.slice(_19));
+return _18;
+};
+dd.Token=function(_1a,_1b){
+this.token_type=_1a;
+this.contents=new String(_2.trim(_1b));
+this.contents.split=_14;
+this.split=function(){
+return String.prototype.split.apply(this.contents,arguments);
+};
+};
+dd.Token.prototype.split_contents=function(_1c){
+var bit,_1d=[],i=0;
+_1c=_1c||999;
+while(i++<_1c&&(bit=_12.exec(this.contents))){
+bit=bit[0];
+if(bit.charAt(0)=="\""&&bit.slice(-1)=="\""){
+_1d.push("\""+bit.slice(1,-1).replace("\\\"","\"").replace("\\\\","\\")+"\"");
+}else{
+if(bit.charAt(0)=="'"&&bit.slice(-1)=="'"){
+_1d.push("'"+bit.slice(1,-1).replace("\\'","'").replace("\\\\","\\")+"'");
+}else{
+_1d.push(bit);
+}
+}
+}
+return _1d;
+};
+var ddt=dd.text={_get:function(_1e,_1f,_20){
+var _21=dd.register.get(_1e,_1f.toLowerCase(),_20);
+if(!_21){
+if(!_20){
+throw new Error("No tag found for "+_1f);
+}
+return null;
+}
+var fn=_21[1];
+var _22=_21[2];
+var _23;
+if(fn.indexOf(":")!=-1){
+_23=fn.split(":");
+fn=_23.pop();
+}
+var mod=_22;
+if(/\./.test(_22)){
+_22=_22.replace(/\./g,"/");
+}
+require([_22],function(){
+});
+var _24=_2.getObject(mod);
+return _24[fn||_1f]||_24[_1f+"_"]||_24[fn+"_"];
+},getTag:function(_25,_26){
+return ddt._get("tag",_25,_26);
+},getFilter:function(_27,_28){
+return ddt._get("filter",_27,_28);
+},getTemplate:function(_29){
+return new dd.Template(ddt.getTemplateString(_29));
+},getTemplateString:function(_2a){
+return _6._getText(_2a.toString())||"";
+},_resolveLazy:function(_2b,_2c,_2d){
+if(_2c){
+if(_2d){
+return _2d.fromJson(_6._getText(_2b))||{};
+}else{
+return dd.text.getTemplateString(_2b);
+}
+}else{
+return _6.get({handleAs:_2d?"json":"text",url:_2b});
+}
+},_resolveTemplateArg:function(arg,_2e){
+if(ddt._isTemplate(arg)){
+if(!_2e){
+var d=new _8();
+d.callback(arg);
+return d;
+}
+return arg;
+}
+return ddt._resolveLazy(arg,_2e);
+},_isTemplate:function(arg){
+return (arg===undefined)||(typeof arg=="string"&&(arg.match(/^\s*[<{]/)||arg.indexOf(" ")!=-1));
+},_resolveContextArg:function(arg,_2f){
+if(arg.constructor==Object){
+if(!_2f){
+var d=new _8;
+d.callback(arg);
+return d;
+}
+return arg;
+}
+return ddt._resolveLazy(arg,_2f,true);
+},_re:/(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,tokenize:function(str){
+return _3(str,ddt._re,ddt._parseDelims);
+},_parseDelims:function(_30,_31,tag){
+if(_30){
+return [dd.TOKEN_VAR,_30];
+}else{
+if(_31){
+var _32=_2.trim(tag).split(/\s+/g);
+for(var i=0,_33;_33=_32[i];i++){
+if(/\./.test(_33)){
+_33=_33.replace(/\./g,"/");
+}
+require([_33]);
+}
+}else{
+return [dd.TOKEN_BLOCK,tag];
+}
+}
+}};
+dd.Template=_2.extend(function(_34,_35){
+var str=_35?_34:ddt._resolveTemplateArg(_34,true)||"";
+var _36=ddt.tokenize(str);
+var _37=new dd._Parser(_36);
+this.nodelist=_37.parse();
+},{update:function(_38,_39){
+return ddt._resolveContextArg(_39).addCallback(this,function(_3a){
+var _3b=this.render(new dd._Context(_3a));
+if(_38.forEach){
+_38.forEach(function(_3c){
+_3c.innerHTML=_3b;
+});
+}else{
+_5.byId(_38).innerHTML=_3b;
+}
+return this;
+});
+},render:function(_3d,_3e){
+_3e=_3e||this.getBuffer();
+_3d=_3d||new dd._Context({});
+return this.nodelist.render(_3d,_3e)+"";
+},getBuffer:function(){
+return new _7();
+}});
+var _3f=/\{\{\s*(.+?)\s*\}\}/g;
+dd.quickFilter=function(str){
+if(!str){
+return new dd._NodeList();
+}
+if(str.indexOf("{%")==-1){
+return new dd._QuickNodeList(_3(str,_3f,function(_40){
+return new dd._Filter(_40);
+}));
+}
+};
+dd._QuickNodeList=_2.extend(function(_41){
+this.contents=_41;
+},{render:function(_42,_43){
+for(var i=0,l=this.contents.length;i/g;
+var _80=/'/g;
+var _81=/"/g;
+dd._base.escape=function(_82){
+return dd.mark_safe(_82.replace(_7d,"&").replace(_7e,"<").replace(_7f,">").replace(_81,""").replace(_80,"'"));
+};
+dd._base.safe=function(_83){
+if(typeof _83=="string"){
+_83=new String(_83);
+}
+if(typeof _83=="object"){
+_83.safe=true;
+}
+return _83;
+};
+dd.mark_safe=dd._base.safe;
+dd.register.tags("dojox.dtl.tag",{"date":["now"],"logic":["if","for","ifequal","ifnotequal"],"loader":["extends","block","include","load","ssi"],"misc":["comment","debug","filter","firstof","spaceless","templatetag","widthratio","with"],"loop":["cycle","ifchanged","regroup"]});
+dd.register.filters("dojox.dtl.filter",{"dates":["date","time","timesince","timeuntil"],"htmlstrings":["linebreaks","linebreaksbr","removetags","striptags"],"integers":["add","get_digit"],"lists":["dictsort","dictsortreversed","first","join","length","length_is","random","slice","unordered_list"],"logic":["default","default_if_none","divisibleby","yesno"],"misc":["filesizeformat","pluralize","phone2numeric","pprint"],"strings":["addslashes","capfirst","center","cut","fix_ampersands","floatformat","iriencode","linenumbers","ljust","lower","make_list","rjust","slugify","stringformat","title","truncatewords","truncatewords_html","upper","urlencode","urlize","urlizetrunc","wordcount","wordwrap"]});
+dd.register.filters("dojox.dtl",{"_base":["escape","safe"]});
+return dd;
+});
diff --git a/js/libs/dojox/dtl/_base.js.uncompressed.js b/js/libs/dojox/dtl/_base.js.uncompressed.js
new file mode 100644
index 0000000..3f11bb1
--- /dev/null
+++ b/js/libs/dojox/dtl/_base.js.uncompressed.js
@@ -0,0 +1,766 @@
+//>>built
+define("dojox/dtl/_base", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojox/string/tokenize",
+ "dojo/_base/json",
+ "dojo/dom",
+ "dojo/_base/xhr",
+ "dojox/string/Builder",
+ "dojo/_base/Deferred"],
+ function(kernel, lang, Tokenize, json, dom, xhr, StringBuilder, deferred){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ StringBuilder = dojox.string.Builder;
+ =====*/
+ kernel.experimental("dojox.dtl");
+ var dd = lang.getObject("dojox.dtl", true);
+ dd._base = {};
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ dd.TOKEN_BLOCK = -1;
+ dd.TOKEN_VAR = -2;
+ dd.TOKEN_COMMENT = -3;
+ dd.TOKEN_TEXT = 3;
+
+ /*=====
+ dd._Context = function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ }
+ =====*/
+ dd._Context = lang.extend(function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ if(dict){
+ lang._mixin(this, dict);
+ if(dict.get){
+ // Preserve passed getter and restore prototype get
+ this._getter = dict.get;
+ delete this.get;
+ }
+ }
+ },
+ {
+ push: function(){
+ var last = this;
+ var context = lang.delegate(this);
+ context.pop = function(){ return last; }
+ return context;
+ },
+ pop: function(){
+ throw new Error("pop() called on empty Context");
+ },
+ get: function(key, otherwise){
+ var n = this._normalize;
+
+ if(this._getter){
+ var got = this._getter(key);
+ if(got !== undefined){
+ return n(got);
+ }
+ }
+
+ if(this[key] !== undefined){
+ return n(this[key]);
+ }
+
+ return otherwise;
+ },
+ _normalize: function(value){
+ if(value instanceof Date){
+ value.year = value.getFullYear();
+ value.month = value.getMonth() + 1;
+ value.day = value.getDate();
+ value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
+ value.hour = value.getHours();
+ value.minute = value.getMinutes();
+ value.second = value.getSeconds();
+ value.microsecond = value.getMilliseconds();
+ }
+ return value;
+ },
+ update: function(dict){
+ var context = this.push();
+ if(dict){
+ lang._mixin(this, dict);
+ }
+ return context;
+ }
+ });
+
+ var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
+ var split_re = /\s+/g;
+ var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
+ splitter = splitter || split_re;
+ if(!(splitter instanceof RegExp)){
+ splitter = new RegExp(splitter, "g");
+ }
+ if(!splitter.global){
+ throw new Error("You must use a globally flagged RegExp with split " + splitter);
+ }
+ splitter.exec(""); // Reset the global
+
+ var part, parts = [], lastIndex = 0, i = 0;
+ while((part = splitter.exec(this))){
+ parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
+ lastIndex = splitter.lastIndex;
+ if(limit && (++i > limit - 1)){
+ break;
+ }
+ }
+ parts.push(this.slice(lastIndex));
+ return parts;
+ }
+
+ dd.Token = function(token_type, contents){
+ this.token_type = token_type;
+ this.contents = new String(lang.trim(contents));
+ this.contents.split = split;
+ this.split = function(){
+ return String.prototype.split.apply(this.contents, arguments);
+ }
+ }
+ dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
+ var bit, bits = [], i = 0;
+ limit = limit || 999;
+ while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
+ bit = bit[0];
+ if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
+ bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
+ }else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
+ bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
+ }else{
+ bits.push(bit);
+ }
+ }
+ return bits;
+ }
+
+ var ddt = dd.text = {
+ _get: function(module, name, errorless){
+ // summary: Used to find both tags and filters
+ var params = dd.register.get(module, name.toLowerCase(), errorless);
+ if(!params){
+ if(!errorless){
+ throw new Error("No tag found for " + name);
+ }
+ return null;
+ }
+
+ var fn = params[1];
+ var deps = params[2];
+
+ var parts;
+ if(fn.indexOf(":") != -1){
+ parts = fn.split(":");
+ fn = parts.pop();
+ }
+
+// FIXME: THIS DESIGN DOES NOT WORK WITH ASYNC LOADERS!
+ var mod = deps;
+ if (/\./.test(deps)) {
+ deps = deps.replace(/\./g, "/");
+ }
+ require([deps], function(){});
+
+ var parent = lang.getObject(mod);
+
+ return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
+ },
+ getTag: function(name, errorless){
+ return ddt._get("tag", name, errorless);
+ },
+ getFilter: function(name, errorless){
+ return ddt._get("filter", name, errorless);
+ },
+ getTemplate: function(file){
+ return new dd.Template(ddt.getTemplateString(file));
+ },
+ getTemplateString: function(file){
+ return xhr._getText(file.toString()) || "";
+ },
+ _resolveLazy: function(location, sync, json){
+ if(sync){
+ if(json){
+ return json.fromJson(xhr._getText(location)) || {};
+ }else{
+ return dd.text.getTemplateString(location);
+ }
+ }else{
+ return xhr.get({
+ handleAs: json ? "json" : "text",
+ url: location
+ });
+ }
+ },
+ _resolveTemplateArg: function(arg, sync){
+ if(ddt._isTemplate(arg)){
+ if(!sync){
+ var d = new deferred();
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync);
+ },
+ _isTemplate: function(arg){
+ return (arg === undefined) || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
+ },
+ _resolveContextArg: function(arg, sync){
+ if(arg.constructor == Object){
+ if(!sync){
+ var d = new deferred;
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync, true);
+ },
+ _re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
+ tokenize: function(str){
+ return Tokenize(str, ddt._re, ddt._parseDelims);
+ },
+ _parseDelims: function(varr, load, tag){
+ if(varr){
+ return [dd.TOKEN_VAR, varr];
+ }else if(load){
+ var parts = lang.trim(tag).split(/\s+/g);
+ for(var i = 0, part; part = parts[i]; i++){
+ if (/\./.test(part)){
+ part = part.replace(/\./g,"/");
+ }
+ require([part]);
+ }
+ }else{
+ return [dd.TOKEN_BLOCK, tag];
+ }
+ }
+ }
+
+ /*=====
+ dd.Template = function(template, isString){
+ // summary:
+ // The base class for text-based templates.
+ // template: String|dojo._Url
+ // The string or location of the string to
+ // use as a template
+ // isString: Boolean
+ // Indicates whether the template is a string or a url.
+ };
+ dd.Template.prototype.update= function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ }
+ dd.Template.prototype.render= function(context, buffer){
+ // summary:
+ // Renders this template.
+ // context: Object
+ // The runtime context.
+ // buffer: StringBuilder?
+ // A string buffer.
+ }
+
+ =====*/
+ dd.Template = lang.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
+ // template:
+ // The string or location of the string to
+ // use as a template
+ var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
+ var tokens = ddt.tokenize(str);
+ var parser = new dd._Parser(tokens);
+ this.nodelist = parser.parse();
+ },
+ {
+ update: function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
+ var content = this.render(new dd._Context(contextObject));
+ if(node.forEach){
+ node.forEach(function(item){
+ item.innerHTML = content;
+ });
+ }else{
+ dom.byId(node).innerHTML = content;
+ }
+ return this;
+ });
+ },
+ render: function(context, /*concatenatable?*/ buffer){
+ buffer = buffer || this.getBuffer();
+ context = context || new dd._Context({});
+ return this.nodelist.render(context, buffer) + "";
+ },
+ getBuffer: function(){
+ return new StringBuilder();
+ }
+ });
+
+ var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
+ dd.quickFilter = function(str){
+ if(!str){
+ return new dd._NodeList();
+ }
+
+ if(str.indexOf("{%") == -1){
+ return new dd._QuickNodeList(Tokenize(str, qfRe, function(token){
+ return new dd._Filter(token);
+ }));
+ }
+ }
+
+ dd._QuickNodeList = lang.extend(function(contents){
+ this.contents = contents;
+ },
+ {
+ render: function(context, buffer){
+ for(var i = 0, l = this.contents.length; i < l; i++){
+ if(this.contents[i].resolve){
+ buffer = buffer.concat(this.contents[i].resolve(context));
+ }else{
+ buffer = buffer.concat(this.contents[i]);
+ }
+ }
+ return buffer;
+ },
+ dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
+ clone: function(buffer){ return this; }
+ });
+
+ dd._Filter = lang.extend(function(token){
+ // summary: Uses a string to find (and manipulate) a variable
+ if(!token) throw new Error("Filter must be called with variable name");
+ this.contents = token;
+
+ var cache = this._cache[token];
+ if(cache){
+ this.key = cache[0];
+ this.filters = cache[1];
+ }else{
+ this.filters = [];
+ Tokenize(token, this._re, this._tokenize, this);
+ this._cache[token] = [this.key, this.filters];
+ }
+ },
+ {
+ _cache: {},
+ _re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
+ _values: {
+ 0: '"', // _("text")
+ 1: '"', // "text"
+ 2: "", // variable
+ 8: '"' // 'text'
+ },
+ _args: {
+ 4: '"', // :_("text")
+ 5: '"', // :"text"
+ 6: "", // :variable
+ 7: "'"// :'text'
+ },
+ _tokenize: function(){
+ var pos, arg;
+
+ for(var i = 0, has = []; i < arguments.length; i++){
+ has[i] = (arguments[i] !== undefined && typeof arguments[i] == "string" && arguments[i]);
+ }
+
+ if(!this.key){
+ for(pos in this._values){
+ if(has[pos]){
+ this.key = this._values[pos] + arguments[pos] + this._values[pos];
+ break;
+ }
+ }
+ }else{
+ for(pos in this._args){
+ if(has[pos]){
+ var value = arguments[pos];
+ if(this._args[pos] == "'"){
+ value = value.replace(/\\'/g, "'");
+ }else if(this._args[pos] == '"'){
+ value = value.replace(/\\"/g, '"');
+ }
+ arg = [!this._args[pos], value];
+ break;
+ }
+ }
+ // Get a named filter
+ var fn = ddt.getFilter(arguments[3]);
+ if(!lang.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
+ this.filters.push([fn, arg]);
+ }
+ },
+ getExpression: function(){
+ return this.contents;
+ },
+ resolve: function(context){
+ if(this.key === undefined){
+ return "";
+ }
+
+ var str = this.resolvePath(this.key, context);
+
+ for(var i = 0, filter; filter = this.filters[i]; i++){
+ // Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
+ // and [1][1] is either the variable name of the string content.
+ if(filter[1]){
+ if(filter[1][0]){
+ str = filter[0](str, this.resolvePath(filter[1][1], context));
+ }else{
+ str = filter[0](str, filter[1][1]);
+ }
+ }else{
+ str = filter[0](str);
+ }
+ }
+
+ return str;
+ },
+ resolvePath: function(path, context){
+ var current, parts;
+ var first = path.charAt(0);
+ var last = path.slice(-1);
+ if(!isNaN(parseInt(first))){
+ current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
+ }else if(first == '"' && first == last){
+ current = path.slice(1, -1);
+ }else{
+ if(path == "true"){ return true; }
+ if(path == "false"){ return false; }
+ if(path == "null" || path == "None"){ return null; }
+ parts = path.split(".");
+ current = context.get(parts[0]);
+
+ if(lang.isFunction(current)){
+ var self = context.getThis && context.getThis();
+ if(current.alters_data){
+ current = "";
+ }else if(self){
+ current = current.call(self);
+ }else{
+ current = "";
+ }
+ }
+
+ for(var i = 1; i < parts.length; i++){
+ var part = parts[i];
+ if(current){
+ var base = current;
+ if(lang.isObject(current) && part == "items" && current[part] === undefined){
+ var items = [];
+ for(var key in current){
+ items.push([key, current[key]]);
+ }
+ current = items;
+ continue;
+ }
+
+ if(current.get && lang.isFunction(current.get) && current.get.safe){
+ current = current.get(part);
+ }else if(current[part] === undefined){
+ current = current[part];
+ break;
+ }else{
+ current = current[part];
+ }
+
+ if(lang.isFunction(current)){
+ if(current.alters_data){
+ current = "";
+ }else{
+ current = current.call(base);
+ }
+ }else if(current instanceof Date){
+ current = dd._Context.prototype._normalize(current);
+ }
+ }else{
+ return "";
+ }
+ }
+ }
+ return current;
+ }
+ });
+
+ dd._TextNode = dd._Node = lang.extend(function(/*Object*/ obj){
+ // summary: Basic catch-all node
+ this.contents = obj;
+ },
+ {
+ set: function(data){
+ this.contents = data;
+ return this;
+ },
+ render: function(context, buffer){
+ // summary: Adds content onto the buffer
+ return buffer.concat(this.contents);
+ },
+ isEmpty: function(){
+ return !lang.trim(this.contents);
+ },
+ clone: function(){ return this; }
+ });
+
+ dd._NodeList = lang.extend(function(/*Node[]*/ nodes){
+ // summary: Allows us to render a group of nodes
+ this.contents = nodes || [];
+ this.last = "";
+ },
+ {
+ push: function(node){
+ // summary: Add a new node to the list
+ this.contents.push(node);
+ return this;
+ },
+ concat: function(nodes){
+ this.contents = this.contents.concat(nodes);
+ return this;
+ },
+ render: function(context, buffer){
+ // summary: Adds all content onto the buffer
+ for(var i = 0; i < this.contents.length; i++){
+ buffer = this.contents[i].render(context, buffer);
+ if(!buffer) throw new Error("Template must return buffer");
+ }
+ return buffer;
+ },
+ dummyRender: function(context){
+ return this.render(context, dd.Template.prototype.getBuffer()).toString();
+ },
+ unrender: function(){ return arguments[1]; },
+ clone: function(){ return this; },
+ rtrim: function(){
+ while(1){
+ i = this.contents.length - 1;
+ if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
+ this.contents.pop();
+ }else{
+ break;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ dd._VarNode = lang.extend(function(str){
+ // summary: A node to be processed as a variable
+ this.contents = new dd._Filter(str);
+ },
+ {
+ render: function(context, buffer){
+ var str = this.contents.resolve(context);
+ if(!str.safe){
+ str = dd._base.escape("" + str);
+ }
+ return buffer.concat(str);
+ }
+ });
+
+ dd._noOpNode = new function(){
+ // summary: Adds a no-op node. Useful in custom tags
+ this.render = this.unrender = function(){ return arguments[1]; }
+ this.clone = function(){ return this; }
+ }
+
+ dd._Parser = lang.extend(function(tokens){
+ // summary: Parser used during initialization and for tag groups.
+ this.contents = tokens;
+ },
+ {
+ i: 0,
+ parse: function(/*Array?*/ stop_at){
+ // summary: Turns tokens into nodes
+ // description: Steps into tags are they're found. Blocks use the parse object
+ // to find their closing tag (the stop_at array). stop_at is inclusive, it
+ // returns the node that matched.
+ var terminators = {}, token;
+ stop_at = stop_at || [];
+ for(var i = 0; i < stop_at.length; i++){
+ terminators[stop_at[i]] = true;
+ }
+
+ var nodelist = new dd._NodeList();
+ while(this.i < this.contents.length){
+ token = this.contents[this.i++];
+ if(typeof token == "string"){
+ nodelist.push(new dd._TextNode(token));
+ }else{
+ var type = token[0];
+ var text = token[1];
+ if(type == dd.TOKEN_VAR){
+ nodelist.push(new dd._VarNode(text));
+ }else if(type == dd.TOKEN_BLOCK){
+ if(terminators[text]){
+ --this.i;
+ return nodelist;
+ }
+ var cmd = text.split(/\s+/g);
+ if(cmd.length){
+ cmd = cmd[0];
+ var fn = ddt.getTag(cmd);
+ if(fn){
+ nodelist.push(fn(this, new dd.Token(type, text)));
+ }
+ }
+ }
+ }
+ }
+
+ if(stop_at.length){
+ throw new Error("Could not find closing tag(s): " + stop_at.toString());
+ }
+
+ this.contents.length = 0;
+ return nodelist;
+ },
+ next_token: function(){
+ // summary: Returns the next token in the list.
+ var token = this.contents[this.i++];
+ return new dd.Token(token[0], token[1]);
+ },
+ delete_first_token: function(){
+ this.i++;
+ },
+ skip_past: function(endtag){
+ while(this.i < this.contents.length){
+ var token = this.contents[this.i++];
+ if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
+ return;
+ }
+ }
+ throw new Error("Unclosed tag found when looking for " + endtag);
+ },
+ create_variable_node: function(expr){
+ return new dd._VarNode(expr);
+ },
+ create_text_node: function(expr){
+ return new dd._TextNode(expr || "");
+ },
+ getTemplate: function(file){
+ return new dd.Template(file);
+ }
+ });
+
+ dd.register = {
+ _registry: {
+ attributes: [],
+ tags: [],
+ filters: []
+ },
+ get: function(/*String*/ module, /*String*/ name){
+ var registry = dd.register._registry[module + "s"];
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(typeof entry[0] == "string"){
+ if(entry[0] == name){
+ return entry;
+ }
+ }else if(name.match(entry[0])){
+ return entry;
+ }
+ }
+ },
+ getAttributeTags: function(){
+ var tags = [];
+ var registry = dd.register._registry.attributes;
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(entry.length == 3){
+ tags.push(entry);
+ }else{
+ var fn = lang.getObject(entry[1]);
+ if(fn && lang.isFunction(fn)){
+ entry.push(fn);
+ tags.push(entry);
+ }
+ }
+ }
+ return tags;
+ },
+ _any: function(type, base, locations){
+ for(var path in locations){
+ for(var i = 0, fn; fn = locations[path][i]; i++){
+ var key = fn;
+ if(lang.isArray(fn)){
+ key = fn[0];
+ fn = fn[1];
+ }
+ if(typeof key == "string"){
+ if(key.substr(0, 5) == "attr:"){
+ var attr = fn;
+ if(attr.substr(0, 5) == "attr:"){
+ attr = attr.slice(5);
+ }
+ dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
+ }
+ key = key.toLowerCase()
+ }
+ dd.register._registry[type].push([
+ key,
+ fn,
+ base + "." + path
+ ]);
+ }
+ }
+ },
+ tags: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("tags", base, locations);
+ },
+ filters: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("filters", base, locations);
+ }
+ }
+
+ var escapeamp = /&/g;
+ var escapelt = //g;
+ var escapeqt = /'/g;
+ var escapedblqt = /"/g;
+ dd._base.escape = function(value){
+ // summary: Escapes a string's HTML
+ return dd.mark_safe(value.replace(escapeamp, '&').replace(escapelt, '<').replace(escapegt, '>').replace(escapedblqt, '"').replace(escapeqt, '''));
+ }
+
+ dd._base.safe = function(value){
+ if(typeof value == "string"){
+ value = new String(value);
+ }
+ if(typeof value == "object"){
+ value.safe = true;
+ }
+ return value;
+ }
+ dd.mark_safe = dd._base.safe;
+
+ dd.register.tags("dojox.dtl.tag", {
+ "date": ["now"],
+ "logic": ["if", "for", "ifequal", "ifnotequal"],
+ "loader": ["extends", "block", "include", "load", "ssi"],
+ "misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
+ "loop": ["cycle", "ifchanged", "regroup"]
+ });
+ dd.register.filters("dojox.dtl.filter", {
+ "dates": ["date", "time", "timesince", "timeuntil"],
+ "htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
+ "integers": ["add", "get_digit"],
+ "lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
+ "logic": ["default", "default_if_none", "divisibleby", "yesno"],
+ "misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
+ "strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]
+ });
+ dd.register.filters("dojox.dtl", {
+ "_base": ["escape", "safe"]
+ });
+ return dd;
+});
+
diff --git a/js/libs/dojox/dtl/contrib/data.js b/js/libs/dojox/dtl/contrib/data.js
new file mode 100644
index 0000000..d1977ea
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/data.js
@@ -0,0 +1,111 @@
+//>>built
+define("dojox/dtl/contrib/data",["dojo/_base/kernel","dojo/_base/lang","../_base","dojo/_base/array"],function(_1,_2,dd,_3){
+_2.getObject("dojox.dtl.contrib.data",true);
+var _4=dd.contrib.data;
+var _5=true;
+_4._BoundItem=_2.extend(function(_6,_7){
+this.item=_6;
+this.store=_7;
+},{get:function(_8){
+var _9=this.store;
+var _a=this.item;
+if(_8=="getLabel"){
+return _9.getLabel(_a);
+}else{
+if(_8=="getAttributes"){
+return _9.getAttributes(_a);
+}else{
+if(_8=="getIdentity"){
+if(_9.getIdentity){
+return _9.getIdentity(_a);
+}
+return "Store has no identity API";
+}else{
+if(!_9.hasAttribute(_a,_8)){
+if(_8.slice(-1)=="s"){
+if(_5){
+_5=false;
+_1.deprecated("You no longer need an extra s to call getValues, it can be figured out automatically");
+}
+_8=_8.slice(0,-1);
+}
+if(!_9.hasAttribute(_a,_8)){
+return;
+}
+}
+var _b=_9.getValues(_a,_8);
+if(!_b){
+return;
+}
+if(!_2.isArray(_b)){
+return new _4._BoundItem(_b,_9);
+}
+_b=_3.map(_b,function(_c){
+if(_2.isObject(_c)&&_9.isItem(_c)){
+return new _4._BoundItem(_c,_9);
+}
+return _c;
+});
+_b.get=_4._get;
+return _b;
+}
+}
+}
+}});
+_4._BoundItem.prototype.get.safe=true;
+_4.BindDataNode=_2.extend(function(_d,_e,_f,_10){
+this.items=_d&&new dd._Filter(_d);
+this.query=_e&&new dd._Filter(_e);
+this.store=new dd._Filter(_f);
+this.alias=_10;
+},{render:function(_11,_12){
+var _13=this.items&&this.items.resolve(_11);
+var _14=this.query&&this.query.resolve(_11);
+var _15=this.store.resolve(_11);
+if(!_15||!_15.getFeatures){
+throw new Error("data_bind didn't receive a store");
+}
+if(_14){
+var _16=false;
+_15.fetch({query:_14,sync:true,scope:this,onComplete:function(it){
+_16=true;
+_13=it;
+}});
+if(!_16){
+throw new Error("The bind_data tag only works with a query if the store executed synchronously");
+}
+}
+var _17=[];
+if(_13){
+for(var i=0,_18;_18=_13[i];i++){
+_17.push(new _4._BoundItem(_18,_15));
+}
+}
+_11[this.alias]=_17;
+return _12;
+},unrender:function(_19,_1a){
+return _1a;
+},clone:function(){
+return this;
+}});
+_2.mixin(_4,{_get:function(key){
+if(this.length){
+return (this[0] instanceof _4._BoundItem)?this[0].get(key):this[0][key];
+}
+},bind_data:function(_1b,_1c){
+var _1d=_1c.contents.split();
+if(_1d[2]!="to"||_1d[4]!="as"||!_1d[5]){
+throw new Error("data_bind expects the format: 'data_bind items to store as varName'");
+}
+return new _4.BindDataNode(_1d[1],null,_1d[3],_1d[5]);
+},bind_query:function(_1e,_1f){
+var _20=_1f.contents.split();
+if(_20[2]!="to"||_20[4]!="as"||!_20[5]){
+throw new Error("data_bind expects the format: 'bind_query query to store as varName'");
+}
+return new _4.BindDataNode(null,_20[1],_20[3],_20[5]);
+}});
+_4._get.safe=true;
+dd.register.tags("dojox.dtl.contrib",{"data":["bind_data","bind_query"]});
+return dojox.dtl.contrib.data;
+});
diff --git a/js/libs/dojox/dtl/contrib/data.js.uncompressed.js b/js/libs/dojox/dtl/contrib/data.js.uncompressed.js
new file mode 100644
index 0000000..490119c
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/data.js.uncompressed.js
@@ -0,0 +1,165 @@
+//>>built
+define("dojox/dtl/contrib/data", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "../_base",
+ "dojo/_base/array"
+], function(kernel,lang,dd,array){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.data", true);
+
+ var ddcd = dd.contrib.data;
+ var first = true;
+
+ ddcd._BoundItem = lang.extend(function(item, store){
+ this.item = item;
+ this.store = store;
+ },
+ {
+ get: function(key){
+ var store = this.store;
+ var item = this.item;
+
+ if(key == "getLabel"){
+ return store.getLabel(item);
+ }else if(key == "getAttributes"){
+ return store.getAttributes(item);
+ }else if(key == "getIdentity"){
+ if(store.getIdentity){
+ return store.getIdentity(item);
+ }
+ return "Store has no identity API";
+ }else{
+ if(!store.hasAttribute(item, key)){
+ if(key.slice(-1) == "s"){
+ if(first){
+ first = false;
+ kernel.deprecated("You no longer need an extra s to call getValues, it can be figured out automatically");
+ }
+ key = key.slice(0, -1);
+ }
+ if(!store.hasAttribute(item, key)){
+ return;
+ }
+ }
+
+ var values = store.getValues(item, key);
+ if(!values){
+ return;
+ }
+ if(!lang.isArray(values)){
+ return new ddcd._BoundItem(values, store);
+ }
+
+ values = array.map(values, function(value){
+ if(lang.isObject(value) && store.isItem(value)){
+ return new ddcd._BoundItem(value, store);
+ }
+ return value;
+ });
+ values.get = ddcd._get;
+ return values;
+ }
+ }
+ });
+ ddcd._BoundItem.prototype.get.safe = true;
+
+ ddcd.BindDataNode = lang.extend(function(items, query, store, alias){
+ this.items = items && new dd._Filter(items);
+ this.query = query && new dd._Filter(query);
+ this.store = new dd._Filter(store);
+ this.alias = alias;
+ },
+ {
+ render: function(context, buffer){
+ var items = this.items && this.items.resolve(context);
+ var query = this.query && this.query.resolve(context);
+ var store = this.store.resolve(context);
+ if(!store || !store.getFeatures){
+ throw new Error("data_bind didn't receive a store");
+ }
+
+ if(query){
+ var sync = false;
+
+ store.fetch({
+ query: query,
+ sync: true,
+ scope: this,
+ onComplete: function(it){
+ sync = true;
+ items = it;
+ }
+ });
+
+ if(!sync){
+ throw new Error("The bind_data tag only works with a query if the store executed synchronously");
+ }
+ }
+
+ var list = [];
+
+ if(items){
+ for(var i = 0, item; item = items[i]; i++){
+ list.push(new ddcd._BoundItem(item, store));
+ }
+ }
+
+ context[this.alias] = list;
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(){
+ return this;
+ }
+ });
+
+ lang.mixin(ddcd, {
+ _get: function(key){
+ if(this.length){
+ return (this[0] instanceof ddcd._BoundItem) ? this[0].get(key) : this[0][key];
+ }
+ },
+ bind_data: function(parser, token){
+ // summary: Turns a list of data store items into DTL compatible items
+ // example:
+ // `contextItems` and `contextStore` should be an item list
+ // and a data store that get assigned to `newVariable`
+ //
+ // | {% bind_data contextItems to contextStore as newVariable %}
+ var parts = token.contents.split();
+
+ if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+ throw new Error("data_bind expects the format: 'data_bind items to store as varName'");
+ }
+
+ return new ddcd.BindDataNode(parts[1], null, parts[3], parts[5]);
+ },
+ bind_query: function(parser, token){
+ // summary: Queries a data store and makes the returned items DTL compatible
+ // example:
+ // You can only use this with data stores that work in a synchronous
+ // way (meaning that `onComplete` is fired during the `fetch` call).
+ // A `sync` flag is sent to the fetch call so that stores that usually
+ // work asynchronously make themselves syncrhonous if possible.
+ // | {% bind_query contextQuery to contextStore as newVariable %}
+ var parts = token.contents.split();
+
+ if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+ throw new Error("data_bind expects the format: 'bind_query query to store as varName'");
+ }
+
+ return new ddcd.BindDataNode(null, parts[1], parts[3], parts[5]);
+ }
+ });
+ ddcd._get.safe = true;
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "data": ["bind_data", "bind_query"]
+ });
+ return dojox.dtl.contrib.data;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/contrib/dijit.js b/js/libs/dojox/dtl/contrib/dijit.js
new file mode 100644
index 0000000..6244554
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/dijit.js
@@ -0,0 +1,176 @@
+//>>built
+define("dojox/dtl/contrib/dijit",["dojo/_base/lang","dojo/_base/connect","dojo/_base/array","dojo/query","../_base","../dom","dojo/parser","dojo/_base/sniff"],function(_1,_2,_3,_4,dd,_5,_6,_7){
+_1.getObject("dojox.dtl.contrib.dijit",true);
+var _8=dd.contrib.dijit;
+_8.AttachNode=_1.extend(function(_9,_a){
+this._keys=_9;
+this._object=_a;
+},{render:function(_b,_c){
+if(!this._rendered){
+this._rendered=true;
+for(var i=0,_d;_d=this._keys[i];i++){
+_b.getThis()[_d]=this._object||_c.getParent();
+}
+}
+return _c;
+},unrender:function(_e,_f){
+if(this._rendered){
+this._rendered=false;
+for(var i=0,key;key=this._keys[i];i++){
+if(_e.getThis()[key]===(this._object||_f.getParent())){
+delete _e.getThis()[key];
+}
+}
+}
+return _f;
+},clone:function(_10){
+return new this.constructor(this._keys,this._object);
+}});
+_8.EventNode=_1.extend(function(_11,obj){
+this._command=_11;
+var _12,_13=_11.split(/\s*,\s*/);
+var _14=_1.trim;
+var _15=[];
+var fns=[];
+while(_12=_13.pop()){
+if(_12){
+var fn=null;
+if(_12.indexOf(":")!=-1){
+var _16=_12.split(":");
+_12=_14(_16[0]);
+fn=_14(_16.slice(1).join(":"));
+}else{
+_12=_14(_12);
+}
+if(!fn){
+fn=_12;
+}
+_15.push(_12);
+fns.push(fn);
+}
+}
+this._types=_15;
+this._fns=fns;
+this._object=obj;
+this._rendered=[];
+},{_clear:false,render:function(_17,_18){
+for(var i=0,_19;_19=this._types[i];i++){
+if(!this._clear&&!this._object){
+_18.getParent()[_19]=null;
+}
+var fn=this._fns[i];
+var _1a;
+if(fn.indexOf(" ")!=-1){
+if(this._rendered[i]){
+_2.disconnect(this._rendered[i]);
+this._rendered[i]=false;
+}
+_1a=_3.map(fn.split(" ").slice(1),function(_1b){
+return new dd._Filter(_1b).resolve(_17);
+});
+fn=fn.split(" ",2)[0];
+}
+if(!this._rendered[i]){
+if(!this._object){
+this._rendered[i]=_18.addEvent(_17,_19,fn,_1a);
+}else{
+this._rendered[i]=_2.connect(this._object,_19,_17.getThis(),fn);
+}
+}
+}
+this._clear=true;
+return _18;
+},unrender:function(_1c,_1d){
+while(this._rendered.length){
+_2.disconnect(this._rendered.pop());
+}
+return _1d;
+},clone:function(){
+return new this.constructor(this._command,this._object);
+}});
+function _1e(n1){
+var n2=n1.cloneNode(true);
+if(_7("ie")){
+_4("script",n2).forEach("item.text = this[index].text;",_4("script",n1));
+}
+return n2;
+};
+_8.DojoTypeNode=_1.extend(function(_1f,_20){
+this._node=_1f;
+this._parsed=_20;
+var _21=_1f.getAttribute("dojoAttachEvent")||_1f.getAttribute("data-dojo-attach-event");
+if(_21){
+this._events=new _8.EventNode(_1.trim(_21));
+}
+var _22=_1f.getAttribute("dojoAttachPoint")||_1f.getAttribute("data-dojo-attach-point");
+if(_22){
+this._attach=new _8.AttachNode(_1.trim(_22).split(/\s*,\s*/));
+}
+if(!_20){
+this._dijit=_6.instantiate([_1e(_1f)])[0];
+}else{
+_1f=_1e(_1f);
+var old=_8.widgetsInTemplate;
+_8.widgetsInTemplate=false;
+this._template=new dd.DomTemplate(_1f);
+_8.widgetsInTemplate=old;
+}
+},{render:function(_23,_24){
+if(this._parsed){
+var _25=new dd.DomBuffer();
+this._template.render(_23,_25);
+var _26=_1e(_25.getRootNode());
+var div=document.createElement("div");
+div.appendChild(_26);
+var _27=div.innerHTML;
+div.removeChild(_26);
+if(_27!=this._rendered){
+this._rendered=_27;
+if(this._dijit){
+this._dijit.destroyRecursive();
+}
+this._dijit=_6.instantiate([_26])[0];
+}
+}
+var _28=this._dijit.domNode;
+if(this._events){
+this._events._object=this._dijit;
+this._events.render(_23,_24);
+}
+if(this._attach){
+this._attach._object=this._dijit;
+this._attach.render(_23,_24);
+}
+return _24.concat(_28);
+},unrender:function(_29,_2a){
+return _2a.remove(this._dijit.domNode);
+},clone:function(){
+return new this.constructor(this._node,this._parsed);
+}});
+_1.mixin(_8,{widgetsInTemplate:true,dojoAttachPoint:function(_2b,_2c){
+return new _8.AttachNode(_2c.contents.slice(_2c.contents.indexOf("data-")!==-1?23:16).split(/\s*,\s*/));
+},dojoAttachEvent:function(_2d,_2e){
+return new _8.EventNode(_2e.contents.slice(_2e.contents.indexOf("data-")!==-1?23:16));
+},dojoType:function(_2f,_30){
+var _31=false;
+if(_30.contents.slice(-7)==" parsed"){
+_31=true;
+}
+var _32=_30.contents.indexOf("data-")!==-1?_30.contents.slice(15):_30.contents.slice(9);
+var _33=_31?_32.slice(0,-7):_32.toString();
+if(_8.widgetsInTemplate){
+var _34=_2f.swallowNode();
+_34.setAttribute("data-dojo-type",_33);
+return new _8.DojoTypeNode(_34,_31);
+}
+return new dd.AttributeNode("data-dojo-type",_33);
+},on:function(_35,_36){
+var _37=_36.contents.split();
+return new _8.EventNode(_37[0]+":"+_37.slice(1).join(" "));
+}});
+_8["data-dojo-type"]=_8.dojoType;
+_8["data-dojo-attach-point"]=_8.dojoAttachPoint;
+_8["data-dojo-attach-event"]=_8.dojoAttachEvent;
+dd.register.tags("dojox.dtl.contrib",{"dijit":["attr:dojoType","attr:data-dojo-type","attr:dojoAttachPoint","attr:data-dojo-attach-point",["attr:attach","dojoAttachPoint"],["attr:attach","data-dojo-attach-point"],"attr:dojoAttachEvent","attr:data-dojo-attach-event",[/(attr:)?on(click|key(up))/i,"on"]]});
+return dojox.dtl.contrib.dijit;
+});
diff --git a/js/libs/dojox/dtl/contrib/dijit.js.uncompressed.js b/js/libs/dojox/dtl/contrib/dijit.js.uncompressed.js
new file mode 100644
index 0000000..6b54320
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/dijit.js.uncompressed.js
@@ -0,0 +1,234 @@
+//>>built
+define("dojox/dtl/contrib/dijit", [
+ "dojo/_base/lang",
+ "dojo/_base/connect",
+ "dojo/_base/array",
+ "dojo/query",
+ "../_base",
+ "../dom",
+ "dojo/parser",
+ "dojo/_base/sniff"
+], function(lang,connect,array,Query,dd,dxdom,Parser,has){
+ /*=====
+ Query = dojo.query;
+ Parser = dojo.parser;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.dijit", true);
+ var ddcd = dd.contrib.dijit;
+ ddcd.AttachNode = lang.extend(function(keys, object){
+ this._keys = keys;
+ this._object = object;
+ },
+ {
+ render: function(context, buffer){
+ if(!this._rendered){
+ this._rendered = true;
+ for(var i = 0, key; key = this._keys[i]; i++){
+ context.getThis()[key] = this._object || buffer.getParent();
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ if(this._rendered){
+ this._rendered = false;
+ for(var i = 0, key; key = this._keys[i]; i++){
+ if(context.getThis()[key] === (this._object || buffer.getParent())){
+ delete context.getThis()[key];
+ }
+ }
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._keys, this._object);
+ }
+ });
+
+ ddcd.EventNode = lang.extend(function(command, obj){
+ this._command = command;
+
+ var type, events = command.split(/\s*,\s*/);
+ var trim = lang.trim;
+ var types = [];
+ var fns = [];
+ while(type = events.pop()){
+ if(type){
+ var fn = null;
+ if(type.indexOf(":") != -1){
+ // oh, if only JS had tuple assignment
+ var funcNameArr = type.split(":");
+ type = trim(funcNameArr[0]);
+ fn = trim(funcNameArr.slice(1).join(":"));
+ }else{
+ type = trim(type);
+ }
+ if(!fn){
+ fn = type;
+ }
+ types.push(type);
+ fns.push(fn);
+ }
+ }
+
+ this._types = types;
+ this._fns = fns;
+ this._object = obj;
+ this._rendered = [];
+ },
+ {
+ // _clear: Boolean
+ // Make sure we kill the actual tags (onclick problems, etc)
+ _clear: false,
+ render: function(context, buffer){
+ for(var i = 0, type; type = this._types[i]; i++){
+ if(!this._clear && !this._object){
+ buffer.getParent()[type] = null;
+ }
+ var fn = this._fns[i];
+ var args;
+ if(fn.indexOf(" ") != -1){
+ if(this._rendered[i]){
+ connect.disconnect(this._rendered[i]);
+ this._rendered[i] = false;
+ }
+ args = array.map(fn.split(" ").slice(1), function(item){
+ return new dd._Filter(item).resolve(context);
+ });
+ fn = fn.split(" ", 2)[0];
+ }
+ if(!this._rendered[i]){
+ if(!this._object){
+ this._rendered[i] = buffer.addEvent(context, type, fn, args);
+ }else{
+ this._rendered[i] = connect.connect(this._object, type, context.getThis(), fn);
+ }
+ }
+ }
+ this._clear = true;
+
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ while(this._rendered.length){
+ connect.disconnect(this._rendered.pop());
+ }
+ return buffer;
+ },
+ clone: function(){
+ return new this.constructor(this._command, this._object);
+ }
+ });
+
+ function cloneNode(n1){
+ var n2 = n1.cloneNode(true);
+ if(has("ie")){
+ Query("script", n2).forEach("item.text = this[index].text;", Query("script", n1));
+ }
+ return n2;
+ }
+
+ ddcd.DojoTypeNode = lang.extend(function(node, parsed){
+ this._node = node;
+ this._parsed = parsed;
+
+ var events = node.getAttribute("dojoAttachEvent") || node.getAttribute("data-dojo-attach-event");
+ if(events){
+ this._events = new ddcd.EventNode(lang.trim(events));
+ }
+ var attach = node.getAttribute("dojoAttachPoint") || node.getAttribute("data-dojo-attach-point");
+ if(attach){
+ this._attach = new ddcd.AttachNode(lang.trim(attach).split(/\s*,\s*/));
+ }
+
+ if(!parsed){
+ this._dijit = Parser.instantiate([cloneNode(node)])[0];
+ }else{
+ node = cloneNode(node);
+ var old = ddcd.widgetsInTemplate;
+ ddcd.widgetsInTemplate = false;
+ this._template = new dd.DomTemplate(node);
+ ddcd.widgetsInTemplate = old;
+ }
+ },
+ {
+ render: function(context, buffer){
+ if(this._parsed){
+ var _buffer = new dd.DomBuffer();
+ this._template.render(context, _buffer);
+ var root = cloneNode(_buffer.getRootNode());
+ var div = document.createElement("div");
+ div.appendChild(root);
+ var rendered = div.innerHTML;
+ div.removeChild(root);
+ if(rendered != this._rendered){
+ this._rendered = rendered;
+ if(this._dijit){
+ this._dijit.destroyRecursive();
+ }
+ this._dijit = Parser.instantiate([root])[0];
+ }
+ }
+
+ var node = this._dijit.domNode;
+
+ if(this._events){
+ this._events._object = this._dijit;
+ this._events.render(context, buffer);
+ }
+ if(this._attach){
+ this._attach._object = this._dijit;
+ this._attach.render(context, buffer);
+ }
+
+ return buffer.concat(node);
+ },
+ unrender: function(context, buffer){
+ return buffer.remove(this._dijit.domNode);
+ },
+ clone: function(){
+ return new this.constructor(this._node, this._parsed);
+ }
+ });
+
+ lang.mixin(ddcd, {
+ widgetsInTemplate: true,
+ dojoAttachPoint: function(parser, token){
+ return new ddcd.AttachNode(token.contents.slice(token.contents.indexOf("data-") !== -1 ? 23 : 16).split(/\s*,\s*/));
+ },
+ dojoAttachEvent: function(parser, token){
+ return new ddcd.EventNode(token.contents.slice(token.contents.indexOf("data-") !== -1 ? 23 : 16));
+ },
+ dojoType: function(parser, token){
+ var parsed = false;
+ if(token.contents.slice(-7) == " parsed"){
+ parsed = true;
+ }
+ var contents = token.contents.indexOf("data-") !== -1 ? token.contents.slice(15) : token.contents.slice(9);
+ var dojoType = parsed ? contents.slice(0, -7) : contents.toString();
+
+ if(ddcd.widgetsInTemplate){
+ var node = parser.swallowNode();
+ node.setAttribute("data-dojo-type", dojoType);
+ return new ddcd.DojoTypeNode(node, parsed);
+ }
+
+ return new dd.AttributeNode("data-dojo-type", dojoType);
+ },
+ on: function(parser, token){
+ // summary: Associates an event type to a function (on the current widget) by name
+ var parts = token.contents.split();
+ return new ddcd.EventNode(parts[0] + ":" + parts.slice(1).join(" "));
+ }
+ });
+ ddcd["data-dojo-type"] = ddcd.dojoType;
+ ddcd["data-dojo-attach-point"] = ddcd.dojoAttachPoint;
+ ddcd["data-dojo-attach-event"] = ddcd.dojoAttachEvent;
+
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "dijit": ["attr:dojoType", "attr:data-dojo-type", "attr:dojoAttachPoint", "attr:data-dojo-attach-point", ["attr:attach", "dojoAttachPoint"], ["attr:attach", "data-dojo-attach-point"], "attr:dojoAttachEvent", "attr:data-dojo-attach-event", [/(attr:)?on(click|key(up))/i, "on"]]
+ });
+ return dojox.dtl.contrib.dijit;
+});
diff --git a/js/libs/dojox/dtl/contrib/dom.js b/js/libs/dojox/dtl/contrib/dom.js
new file mode 100644
index 0000000..0647409
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/dom.js
@@ -0,0 +1,120 @@
+//>>built
+define("dojox/dtl/contrib/dom",["dojo/_base/kernel","dojo/_base/lang","dojo/_base/connect","dojo/dom-style","dojo/dom-construct","../_base","../dom"],function(_1,_2,_3,_4,_5,dd,_6){
+var _7=_2.getObject("dojox.dtl.contrib.dom",true);
+var _8={render:function(){
+return this.contents;
+}};
+_7.StyleNode=_2.extend(function(_9){
+this.contents={};
+this._current={};
+this._styles=_9;
+for(var _a in _9){
+if(_9[_a].indexOf("{{")!=-1){
+var _b=new dd.Template(_9[_a]);
+}else{
+var _b=_2.delegate(_8);
+_b.contents=_9[_a];
+}
+this.contents[_a]=_b;
+}
+},{render:function(_c,_d){
+for(var _e in this.contents){
+var _f=this.contents[_e].render(_c);
+if(this._current[_e]!=_f){
+_4.set(_d.getParent(),_e,this._current[_e]=_f);
+}
+}
+return _d;
+},unrender:function(_10,_11){
+this._current={};
+return _11;
+},clone:function(_12){
+return new this.constructor(this._styles);
+}});
+_7.BufferNode=_2.extend(function(_13,_14){
+this.nodelist=_13;
+this.options=_14;
+},{_swap:function(_15,_16){
+if(!this.swapped&&this.parent.parentNode){
+if(_15=="node"){
+if((_16.nodeType==3&&!this.options.text)||(_16.nodeType==1&&!this.options.node)){
+return;
+}
+}else{
+if(_15=="class"){
+if(_15!="class"){
+return;
+}
+}
+}
+this.onAddNode&&_3.disconnect(this.onAddNode);
+this.onRemoveNode&&_3.disconnect(this.onRemoveNode);
+this.onChangeAttribute&&_3.disconnect(this.onChangeAttribute);
+this.onChangeData&&_3.disconnect(this.onChangeData);
+this.swapped=this.parent.cloneNode(true);
+this.parent.parentNode.replaceChild(this.swapped,this.parent);
+}
+},render:function(_17,_18){
+this.parent=_18.getParent();
+if(this.options.node){
+this.onAddNode=_3.connect(_18,"onAddNode",_2.hitch(this,"_swap","node"));
+this.onRemoveNode=_3.connect(_18,"onRemoveNode",_2.hitch(this,"_swap","node"));
+}
+if(this.options.text){
+this.onChangeData=_3.connect(_18,"onChangeData",_2.hitch(this,"_swap","node"));
+}
+if(this.options["class"]){
+this.onChangeAttribute=_3.connect(_18,"onChangeAttribute",_2.hitch(this,"_swap","class"));
+}
+_18=this.nodelist.render(_17,_18);
+if(this.swapped){
+this.swapped.parentNode.replaceChild(this.parent,this.swapped);
+_5.destroy(this.swapped);
+}else{
+this.onAddNode&&_3.disconnect(this.onAddNode);
+this.onRemoveNode&&_3.disconnect(this.onRemoveNode);
+this.onChangeAttribute&&_3.disconnect(this.onChangeAttribute);
+this.onChangeData&&_3.disconnect(this.onChangeData);
+}
+delete this.parent;
+delete this.swapped;
+return _18;
+},unrender:function(_19,_1a){
+return this.nodelist.unrender(_19,_1a);
+},clone:function(_1b){
+return new this.constructor(this.nodelist.clone(_1b),this.options);
+}});
+_2.mixin(_7,{buffer:function(_1c,_1d){
+var _1e=_1d.contents.split().slice(1);
+var _1f={};
+var _20=false;
+for(var i=_1e.length;i--;){
+_20=true;
+_1f[_1e[i]]=true;
+}
+if(!_20){
+_1f.node=true;
+}
+var _21=_1c.parse(["endbuffer"]);
+_1c.next_token();
+return new _7.BufferNode(_21,_1f);
+},html:function(_22,_23){
+_1.deprecated("{% html someVariable %}","Use {{ someVariable|safe }} instead");
+return _22.create_variable_node(_23.contents.slice(5)+"|safe");
+},style_:function(_24,_25){
+var _26={};
+_25=_25.contents.replace(/^style\s+/,"");
+var _27=_25.split(/\s*;\s*/g);
+for(var i=0,_28;_28=_27[i];i++){
+var _29=_28.split(/\s*:\s*/g);
+var key=_29[0];
+var _2a=_2.trim(_29[1]);
+if(_2a){
+_26[key]=_2a;
+}
+}
+return new _7.StyleNode(_26);
+}});
+dd.register.tags("dojox.dtl.contrib",{"dom":["html","attr:style","buffer"]});
+return dojox.dtl.contrib.dom;
+});
diff --git a/js/libs/dojox/dtl/contrib/dom.js.uncompressed.js b/js/libs/dojox/dtl/contrib/dom.js.uncompressed.js
new file mode 100644
index 0000000..d2e181f
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/dom.js.uncompressed.js
@@ -0,0 +1,177 @@
+//>>built
+define("dojox/dtl/contrib/dom", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/connect",
+ "dojo/dom-style",
+ "dojo/dom-construct",
+ "../_base",
+ "../dom"
+], function(kernel,lang,connect,domStyle,domConstruct,dd,dddom){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ var ddch = lang.getObject("dojox.dtl.contrib.dom", true);
+
+ var simple = {render: function(){ return this.contents; }};
+
+ ddch.StyleNode = lang.extend(function(styles){
+ this.contents = {};
+ this._current = {};
+ this._styles = styles;
+ for(var key in styles){
+ if(styles[key].indexOf("{{") != -1){
+ var node = new dd.Template(styles[key]);
+ }else{
+ var node = lang.delegate(simple);
+ node.contents = styles[key];
+ }
+ this.contents[key] = node;
+ }
+ },
+ {
+ render: function(context, buffer){
+ for(var key in this.contents){
+ var value = this.contents[key].render(context);
+ if(this._current[key] != value){
+ domStyle.set(buffer.getParent(), key, this._current[key] = value);
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ this._current = {};
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._styles);
+ }
+ });
+
+ ddch.BufferNode = lang.extend(function(nodelist, options){
+ this.nodelist = nodelist;
+ this.options = options;
+ },
+ {
+ _swap: function(type, node){
+ if(!this.swapped && this.parent.parentNode){
+ if(type == "node"){
+ if((node.nodeType == 3 && !this.options.text) || (node.nodeType == 1 && !this.options.node)){
+ return;
+ }
+ }else if(type == "class"){
+ if(type != "class"){
+ return;
+ }
+ }
+
+ this.onAddNode && connect.disconnect(this.onAddNode);
+ this.onRemoveNode && connect.disconnect(this.onRemoveNode);
+ this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
+ this.onChangeData && connect.disconnect(this.onChangeData);
+
+ this.swapped = this.parent.cloneNode(true);
+ this.parent.parentNode.replaceChild(this.swapped, this.parent);
+ }
+ },
+ render: function(context, buffer){
+ this.parent = buffer.getParent();
+ if(this.options.node){
+ this.onAddNode = connect.connect(buffer, "onAddNode", lang.hitch(this, "_swap", "node"));
+ this.onRemoveNode = connect.connect(buffer, "onRemoveNode", lang.hitch(this, "_swap", "node"));
+ }
+ if(this.options.text){
+ this.onChangeData = connect.connect(buffer, "onChangeData", lang.hitch(this, "_swap", "node"));
+ }
+ if(this.options["class"]){
+ this.onChangeAttribute = connect.connect(buffer, "onChangeAttribute", lang.hitch(this, "_swap", "class"));
+ }
+
+ buffer = this.nodelist.render(context, buffer);
+
+ if(this.swapped){
+ this.swapped.parentNode.replaceChild(this.parent, this.swapped);
+ domConstruct.destroy(this.swapped);
+ }else{
+ this.onAddNode && connect.disconnect(this.onAddNode);
+ this.onRemoveNode && connect.disconnect(this.onRemoveNode);
+ this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
+ this.onChangeData && connect.disconnect(this.onChangeData);
+ }
+
+ delete this.parent;
+ delete this.swapped;
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodelist.clone(buffer), this.options);
+ }
+ });
+
+ lang.mixin(ddch, {
+ buffer: function(parser, token){
+ // summary:
+ // Buffer large DOM manipulations during re-render.
+ // description:
+ // When using DomTemplate, wrap any content
+ // that you expect to change often during
+ // re-rendering. It will then remove its parent
+ // from the main document while it re-renders that
+ // section of code. It will only remove it from
+ // the main document if a mainpulation of somes sort
+ // happens. ie It won't swap out if it diesn't have to.
+ // example:
+ // By default, it considers only node addition/removal
+ // to be "changing"
+ //
+ // | {% buffer %}{% for item in items %}{{ item }}{% endfor %}{% endbuffer %}
+ // example:
+ // You can explicitly declare options:
+ //
+ // * node: Watch node removal/addition
+ // * class: Watch for a classname to be changed
+ // * text: Watch for any text to be changed
+ //
+ // | {% buffer node class %}{% for item in items %}{{ item }}{% endfor %}{% endbuffer %}
+ var parts = token.contents.split().slice(1);
+ var options = {};
+ var found = false;
+ for(var i = parts.length; i--;){
+ found = true;
+ options[parts[i]] = true;
+ }
+ if(!found){
+ options.node = true;
+ }
+ var nodelist = parser.parse(["endbuffer"]);
+ parser.next_token();
+ return new ddch.BufferNode(nodelist, options);
+ },
+ html: function(parser, token){
+ kernel.deprecated("{% html someVariable %}", "Use {{ someVariable|safe }} instead");
+ return parser.create_variable_node(token.contents.slice(5) + "|safe");
+ },
+ style_: function(parser, token){
+ var styles = {};
+ token = token.contents.replace(/^style\s+/, "");
+ var rules = token.split(/\s*;\s*/g);
+ for(var i = 0, rule; rule = rules[i]; i++){
+ var parts = rule.split(/\s*:\s*/g);
+ var key = parts[0];
+ var value = lang.trim(parts[1]);
+ if(value){
+ styles[key] = value;
+ }
+ }
+ return new ddch.StyleNode(styles);
+ }
+ });
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "dom": ["html", "attr:style", "buffer"]
+ });
+ return dojox.dtl.contrib.dom;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/contrib/objects.js b/js/libs/dojox/dtl/contrib/objects.js
new file mode 100644
index 0000000..b77d510
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/objects.js
@@ -0,0 +1,9 @@
+//>>built
+define("dojox/dtl/contrib/objects",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.contrib.objects",true);
+_1.mixin(dd.contrib.objects,{key:function(_2,_3){
+return _2[_3];
+}});
+dd.register.filters("dojox.dtl.contrib",{"objects":["key"]});
+return dojox.dtl.contrib.objects;
+});
diff --git a/js/libs/dojox/dtl/contrib/objects.js.uncompressed.js b/js/libs/dojox/dtl/contrib/objects.js.uncompressed.js
new file mode 100644
index 0000000..ea1d07b
--- /dev/null
+++ b/js/libs/dojox/dtl/contrib/objects.js.uncompressed.js
@@ -0,0 +1,21 @@
+//>>built
+define("dojox/dtl/contrib/objects", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.objects", true);
+
+ lang.mixin(dd.contrib.objects, {
+ key: function(value, arg){
+ return value[arg];
+ }
+ });
+
+ dd.register.filters("dojox.dtl.contrib", {
+ "objects": ["key"]
+ });
+ return dojox.dtl.contrib.objects;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/dom.js b/js/libs/dojox/dtl/dom.js
new file mode 100644
index 0000000..a6517cb
--- /dev/null
+++ b/js/libs/dojox/dtl/dom.js
@@ -0,0 +1,858 @@
+//>>built
+define("dojox/dtl/dom",["dojo/_base/lang","./_base","dojox/string/tokenize","./Context","dojo/dom","dojo/dom-construct","dojo/_base/html","dojo/_base/array","dojo/_base/connect","dojo/_base/sniff"],function(_1,dd,_2,_3,_4,_5,_6,_7,_8,_9){
+dd.BOOLS={checked:1,disabled:1,readonly:1};
+dd.TOKEN_CHANGE=-11;
+dd.TOKEN_ATTR=-12;
+dd.TOKEN_CUSTOM=-13;
+dd.TOKEN_NODE=1;
+var _a=dd.text;
+var _b=dd.dom={_attributes:{},_uppers:{},_re4:/^function anonymous\(\)\s*{\s*(.*)\s*}$/,_reTrim:/(?:^[\n\s]*(\{%)?\s*|\s*(%\})?[\n\s]*$)/g,_reSplit:/\s*%\}[\n\s]*\{%\s*/g,getTemplate:function(_c){
+if(typeof this._commentable=="undefined"){
+this._commentable=false;
+var _d=document.createElement("div"),_e="Test comment handling, and long comments, using comments whenever possible.";
+_d.innerHTML="";
+if(_d.childNodes.length&&_d.firstChild.nodeType==8&&_d.firstChild.data==_e){
+this._commentable=true;
+}
+}
+if(!this._commentable){
+_c=_c.replace(//g,"$1");
+}
+if(_9("ie")){
+_c=_c.replace(/\b(checked|disabled|readonly|style)="/g,"t$1=\"");
+}
+_c=_c.replace(/\bstyle="/g,"tstyle=\"");
+var _f;
+var _10=_9("webkit");
+var _11=[[true,"select","option"],[_10,"tr","td|th"],[_10,"thead","tr","th"],[_10,"tbody","tr","td"],[_10,"table","tbody|thead|tr","tr","td"]];
+var _12=[];
+for(var i=0,_13;_13=_11[i];i++){
+if(!_13[0]){
+continue;
+}
+if(_c.indexOf("<"+_13[1])!=-1){
+var _14=new RegExp("<"+_13[1]+"(?:.|\n)*?>((?:.|\n)+?)"+_13[1]+">","ig");
+tagLoop:
+while(_f=_14.exec(_c)){
+var _15=_13[2].split("|");
+var _16=[];
+for(var j=0,_17;_17=_15[j];j++){
+_16.push("<"+_17+"(?:.|\n)*?>(?:.|\n)*?"+_17+">");
+}
+var _18=[];
+var _19=_2(_f[1],new RegExp("("+_16.join("|")+")","ig"),function(_1a){
+var tag=/<(\w+)/.exec(_1a)[1];
+if(!_18[tag]){
+_18[tag]=true;
+_18.push(tag);
+}
+return {data:_1a};
+});
+if(_18.length){
+var tag=(_18.length==1)?_18[0]:_13[2].split("|")[0];
+var _1b=[];
+for(var j=0,jl=_19.length;j";
+}else{
+if(tag==_13[p]){
+continue;
+}else{
+_1e+="<"+_13[p]+">";
+}
+}
+}
+_1e+="DTL";
+for(var p=_13.length-1;p>1;p--){
+if(p==2){
+_1e+=""+tag+">";
+}else{
+if(tag==_13[p]){
+continue;
+}else{
+_1e+=""+_13[p]+">";
+}
+}
+}
+_1b.push("ÿ"+_12.length);
+_12.push(_1e);
+}
+}
+}
+_c=_c.replace(_f[1],_1b.join(""));
+}
+}
+}
+}
+for(var i=_12.length;i--;){
+_c=_c.replace("ÿ"+i,_12[i]);
+}
+var re=/\b([a-zA-Z_:][a-zA-Z0-9_\-\.:]*)=['"]/g;
+while(_f=re.exec(_c)){
+var _1f=_f[1].toLowerCase();
+if(_1f=="dtlinstruction"){
+continue;
+}
+if(_1f!=_f[1]){
+this._uppers[_1f]=_f[1];
+}
+this._attributes[_1f]=true;
+}
+var _d=document.createElement("div");
+_d.innerHTML=_c;
+var _20={nodes:[]};
+while(_d.childNodes.length){
+_20.nodes.push(_d.removeChild(_d.childNodes[0]));
+}
+return _20;
+},tokenize:function(_21){
+var _22=[];
+for(var i=0,_23;_23=_21[i++];){
+if(_23.nodeType!=1){
+this.__tokenize(_23,_22);
+}else{
+this._tokenize(_23,_22);
+}
+}
+return _22;
+},_swallowed:[],_tokenize:function(_24,_25){
+var _26=false;
+var _27=this._swallowed;
+var i,j,tag,_28;
+if(!_25.first){
+_26=_25.first=true;
+var _29=dd.register.getAttributeTags();
+for(i=0;tag=_29[i];i++){
+try{
+(tag[2])({swallowNode:function(){
+throw 1;
+}},new dd.Token(dd.TOKEN_ATTR,""));
+}
+catch(e){
+_27.push(tag);
+}
+}
+}
+for(i=0;tag=_27[i];i++){
+var _2a=_24.getAttribute(tag[0]);
+if(_2a){
+var _27=false;
+var _2b=(tag[2])({swallowNode:function(){
+_27=true;
+return _24;
+}},new dd.Token(dd.TOKEN_ATTR,tag[0]+" "+_2a));
+if(_27){
+if(_24.parentNode&&_24.parentNode.removeChild){
+_24.parentNode.removeChild(_24);
+}
+_25.push([dd.TOKEN_CUSTOM,_2b]);
+return;
+}
+}
+}
+var _2c=[];
+if(_9("ie")&&_24.tagName=="SCRIPT"){
+_2c.push({nodeType:3,data:_24.text});
+_24.text="";
+}else{
+for(i=0;_28=_24.childNodes[i];i++){
+_2c.push(_28);
+}
+}
+_25.push([dd.TOKEN_NODE,_24]);
+var _2d=false;
+if(_2c.length){
+_25.push([dd.TOKEN_CHANGE,_24]);
+_2d=true;
+}
+for(var key in this._attributes){
+var _2e=false;
+var _2f="";
+if(key=="class"){
+_2f=_24.className||_2f;
+}else{
+if(key=="for"){
+_2f=_24.htmlFor||_2f;
+}else{
+if(key=="value"&&_24.value==_24.innerHTML){
+continue;
+}else{
+if(_24.getAttribute){
+_2f=_24.getAttribute(key,2)||_2f;
+if(key=="href"||key=="src"){
+if(_9("ie")){
+var _30=location.href.lastIndexOf(location.hash);
+var _31=location.href.substring(0,_30).split("/");
+_31.pop();
+_31=_31.join("/")+"/";
+if(_2f.indexOf(_31)==0){
+_2f=_2f.replace(_31,"");
+}
+_2f=decodeURIComponent(_2f);
+}
+}else{
+if(key=="tstyle"){
+_2e=key;
+key="style";
+}else{
+if(dd.BOOLS[key.slice(1)]&&_1.trim(_2f)){
+key=key.slice(1);
+}else{
+if(this._uppers[key]&&_1.trim(_2f)){
+_2e=this._uppers[key];
+}
+}
+}
+}
+}
+}
+}
+}
+if(_2e){
+_24.setAttribute(_2e,"");
+_24.removeAttribute(_2e);
+}
+if(typeof _2f=="function"){
+_2f=_2f.toString().replace(this._re4,"$1");
+}
+if(!_2d){
+_25.push([dd.TOKEN_CHANGE,_24]);
+_2d=true;
+}
+_25.push([dd.TOKEN_ATTR,_24,key,_2f]);
+}
+for(i=0,_28;_28=_2c[i];i++){
+if(_28.nodeType==1){
+var _32=_28.getAttribute("dtlinstruction");
+if(_32){
+_28.parentNode.removeChild(_28);
+_28={nodeType:8,data:_32};
+}
+}
+this.__tokenize(_28,_25);
+}
+if(!_26&&_24.parentNode&&_24.parentNode.tagName){
+if(_2d){
+_25.push([dd.TOKEN_CHANGE,_24,true]);
+}
+_25.push([dd.TOKEN_CHANGE,_24.parentNode]);
+_24.parentNode.removeChild(_24);
+}else{
+_25.push([dd.TOKEN_CHANGE,_24,true,true]);
+}
+},__tokenize:function(_33,_34){
+var _35=_33.data;
+switch(_33.nodeType){
+case 1:
+this._tokenize(_33,_34);
+return;
+case 3:
+if(_35.match(/[^\s\n]/)&&(_35.indexOf("{{")!=-1||_35.indexOf("{%")!=-1)){
+var _36=_a.tokenize(_35);
+for(var j=0,_37;_37=_36[j];j++){
+if(typeof _37=="string"){
+_34.push([dd.TOKEN_TEXT,_37]);
+}else{
+_34.push(_37);
+}
+}
+}else{
+_34.push([_33.nodeType,_33]);
+}
+if(_33.parentNode){
+_33.parentNode.removeChild(_33);
+}
+return;
+case 8:
+if(_35.indexOf("{%")==0){
+var _37=_1.trim(_35.slice(2,-2));
+if(_37.substr(0,5)=="load "){
+var _38=_1.trim(_37).split(/\s+/g);
+for(var i=1,_39;_39=_38[i];i++){
+if(/\./.test(_39)){
+_39=_39.replace(/\./g,"/");
+}
+require([_39]);
+}
+}
+_34.push([dd.TOKEN_BLOCK,_37]);
+}
+if(_35.indexOf("{{")==0){
+_34.push([dd.TOKEN_VAR,_1.trim(_35.slice(2,-2))]);
+}
+if(_33.parentNode){
+_33.parentNode.removeChild(_33);
+}
+return;
+}
+}};
+dd.DomTemplate=_1.extend(function(obj){
+if(!obj.nodes){
+var _3a=_4.byId(obj);
+if(_3a&&_3a.nodeType==1){
+_7.forEach(["class","src","href","name","value"],function(_3b){
+_b._attributes[_3b]=true;
+});
+obj={nodes:[_3a]};
+}else{
+if(typeof obj=="object"){
+obj=_a.getTemplateString(obj);
+}
+obj=_b.getTemplate(obj);
+}
+}
+var _3c=_b.tokenize(obj.nodes);
+if(dd.tests){
+this.tokens=_3c.slice(0);
+}
+var _3d=new dd._DomParser(_3c);
+this.nodelist=_3d.parse();
+},{_count:0,_re:/\bdojo:([a-zA-Z0-9_]+)\b/g,setClass:function(str){
+this.getRootNode().className=str;
+},getRootNode:function(){
+return this.buffer.rootNode;
+},getBuffer:function(){
+return new dd.DomBuffer();
+},render:function(_3e,_3f){
+_3f=this.buffer=_3f||this.getBuffer();
+this.rootNode=null;
+var _40=this.nodelist.render(_3e||new dd.Context({}),_3f);
+for(var i=0,_41;_41=_3f._cache[i];i++){
+if(_41._cache){
+_41._cache.length=0;
+}
+}
+return _40;
+},unrender:function(_42,_43){
+return this.nodelist.unrender(_42,_43);
+}});
+dd.DomBuffer=_1.extend(function(_44){
+this._parent=_44;
+this._cache=[];
+},{concat:function(_45){
+var _46=this._parent;
+if(_46&&_45.parentNode&&_45.parentNode===_46&&!_46._dirty){
+return this;
+}
+if(_45.nodeType==1&&!this.rootNode){
+this.rootNode=_45||true;
+return this;
+}
+if(!_46){
+if(_45.nodeType==3&&_1.trim(_45.data)){
+throw new Error("Text should not exist outside of the root node in template");
+}
+return this;
+}
+if(this._closed){
+if(_45.nodeType==3&&!_1.trim(_45.data)){
+return this;
+}else{
+throw new Error("Content should not exist outside of the root node in template");
+}
+}
+if(_46._dirty){
+if(_45._drawn&&_45.parentNode==_46){
+var _47=_46._cache;
+if(_47){
+for(var i=0,_48;_48=_47[i];i++){
+this.onAddNode&&this.onAddNode(_48);
+_46.insertBefore(_48,_45);
+this.onAddNodeComplete&&this.onAddNodeComplete(_48);
+}
+_47.length=0;
+}
+}
+_46._dirty=false;
+}
+if(!_46._cache){
+_46._cache=[];
+this._cache.push(_46);
+}
+_46._dirty=true;
+_46._cache.push(_45);
+return this;
+},remove:function(obj){
+if(typeof obj=="string"){
+if(this._parent){
+this._parent.removeAttribute(obj);
+}
+}else{
+if(obj.nodeType==1&&!this.getRootNode()&&!this._removed){
+this._removed=true;
+return this;
+}
+if(obj.parentNode){
+this.onRemoveNode&&this.onRemoveNode(obj);
+if(obj.parentNode){
+obj.parentNode.removeChild(obj);
+}
+}
+}
+return this;
+},setAttribute:function(key,_49){
+var old=_6.attr(this._parent,key);
+if(this.onChangeAttribute&&old!=_49){
+this.onChangeAttribute(this._parent,key,old,_49);
+}
+if(key=="style"){
+this._parent.style.cssText=_49;
+}else{
+_6.attr(this._parent,key,_49);
+if(key=="value"){
+this._parent.setAttribute(key,_49);
+}
+}
+return this;
+},addEvent:function(_4a,_4b,fn,_4c){
+if(!_4a.getThis()){
+throw new Error("You must use Context.setObject(instance)");
+}
+this.onAddEvent&&this.onAddEvent(this.getParent(),_4b,fn);
+var _4d=fn;
+if(_1.isArray(_4c)){
+_4d=function(e){
+this[fn].apply(this,[e].concat(_4c));
+};
+}
+return _8.connect(this.getParent(),_4b,_4a.getThis(),_4d);
+},setParent:function(_4e,up,_4f){
+if(!this._parent){
+this._parent=this._first=_4e;
+}
+if(up&&_4f&&_4e===this._first){
+this._closed=true;
+}
+if(up){
+var _50=this._parent;
+var _51="";
+var ie=_9("ie")&&_50.tagName=="SCRIPT";
+if(ie){
+_50.text="";
+}
+if(_50._dirty){
+var _52=_50._cache;
+var _53=(_50.tagName=="SELECT"&&!_50.options.length);
+for(var i=0,_54;_54=_52[i];i++){
+if(_54!==_50){
+this.onAddNode&&this.onAddNode(_54);
+if(ie){
+_51+=_54.data;
+}else{
+_50.appendChild(_54);
+if(_53&&_54.defaultSelected&&i){
+_53=i;
+}
+}
+this.onAddNodeComplete&&this.onAddNodeComplete(_54);
+}
+}
+if(_53){
+_50.options.selectedIndex=(typeof _53=="number")?_53:0;
+}
+_52.length=0;
+_50._dirty=false;
+}
+if(ie){
+_50.text=_51;
+}
+}
+this._parent=_4e;
+this.onSetParent&&this.onSetParent(_4e,up,_4f);
+return this;
+},getParent:function(){
+return this._parent;
+},getRootNode:function(){
+return this.rootNode;
+}});
+dd._DomNode=_1.extend(function(_55){
+this.contents=_55;
+},{render:function(_56,_57){
+this._rendered=true;
+return _57.concat(this.contents);
+},unrender:function(_58,_59){
+if(!this._rendered){
+return _59;
+}
+this._rendered=false;
+return _59.remove(this.contents);
+},clone:function(_5a){
+return new this.constructor(this.contents);
+}});
+dd._DomNodeList=_1.extend(function(_5b){
+this.contents=_5b||[];
+},{push:function(_5c){
+this.contents.push(_5c);
+},unshift:function(_5d){
+this.contents.unshift(_5d);
+},render:function(_5e,_5f,_60){
+_5f=_5f||dd.DomTemplate.prototype.getBuffer();
+if(_60){
+var _61=_5f.getParent();
+}
+for(var i=0;i>built
+define("dojox/dtl/dom", [
+ "dojo/_base/lang",
+ "./_base",
+ "dojox/string/tokenize",
+ "./Context",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/html",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/sniff"
+], function(lang,dd,Tokenize,context,dom,domconstruct,html,array,connect,has){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ dd = dojox.dtl;
+ =====*/
+ dd.BOOLS = {checked: 1, disabled: 1, readonly: 1};
+ dd.TOKEN_CHANGE = -11;
+ dd.TOKEN_ATTR = -12;
+ dd.TOKEN_CUSTOM = -13;
+ dd.TOKEN_NODE = 1;
+
+ var ddt = dd.text;
+ var ddh = dd.dom = {
+ _attributes: {},
+ _uppers: {},
+ _re4: /^function anonymous\(\)\s*{\s*(.*)\s*}$/,
+ _reTrim: /(?:^[\n\s]*(\{%)?\s*|\s*(%\})?[\n\s]*$)/g,
+ _reSplit: /\s*%\}[\n\s]*\{%\s*/g,
+ getTemplate: function(text){
+ if(typeof this._commentable == "undefined"){
+ // Check to see if the browser can handle comments
+ this._commentable = false;
+ var div = document.createElement("div"), comment = "Test comment handling, and long comments, using comments whenever possible.";
+ div.innerHTML = "";
+ if(div.childNodes.length && div.firstChild.nodeType == 8 && div.firstChild.data == comment){
+ this._commentable = true;
+ }
+ }
+
+ if(!this._commentable){
+ // Strip comments
+ text = text.replace(//g, "$1");
+ }
+
+ if(has("ie")){
+ text = text.replace(/\b(checked|disabled|readonly|style)="/g, 't$1="');
+ }
+ text = text.replace(/\bstyle="/g, 'tstyle="');
+
+ var match;
+ var table = has("webkit");
+ var pairs = [ // Format: [enable, parent, allowed children (first for nesting), nestings]
+ [true, "select", "option"],
+ [table, "tr", "td|th"],
+ [table, "thead", "tr", "th"],
+ [table, "tbody", "tr", "td"],
+ [table, "table", "tbody|thead|tr", "tr", "td"]
+ ];
+ var replacements = [];
+ // Some tags can't contain text. So we wrap the text in tags that they can have.
+ for(var i = 0, pair; pair = pairs[i]; i++){
+ if(!pair[0]){
+ continue;
+ }
+ if(text.indexOf("<" + pair[1]) != -1){
+ var selectRe = new RegExp("<" + pair[1] + "(?:.|\n)*?>((?:.|\n)+?)" + pair[1] + ">", "ig");
+ tagLoop: while(match = selectRe.exec(text)){
+ // Do it like this to make sure we don't double-wrap
+ var inners = pair[2].split("|");
+ var innerRe = [];
+ for(var j = 0, inner; inner = inners[j]; j++){
+ innerRe.push("<" + inner + "(?:.|\n)*?>(?:.|\n)*?" + inner + ">");
+ }
+ var tags = [];
+ var tokens = Tokenize(match[1], new RegExp("(" + innerRe.join("|") + ")", "ig"), function(data){
+ var tag = /<(\w+)/.exec(data)[1];
+ if(!tags[tag]){
+ tags[tag] = true;
+ tags.push(tag);
+ }
+ return {data: data};
+ });
+ if(tags.length){
+ var tag = (tags.length == 1) ? tags[0] : pair[2].split("|")[0];
+
+ var replace = [];
+ for(var j = 0, jl = tokens.length; j < jl; j++) {
+ var token = tokens[j];
+ if(lang.isObject(token)){
+ replace.push(token.data);
+ }else{
+ var stripped = token.replace(this._reTrim, "");
+ if(!stripped){ continue; }
+ token = stripped.split(this._reSplit);
+ for(var k = 0, kl = token.length; k < kl; k++){
+ var replacement = "";
+ for(var p = 2, pl = pair.length; p < pl; p++){
+ if(p == 2){
+ replacement += "<" + tag + ' dtlinstruction="{% ' + token[k].replace('"', '\\"') + ' %}">';
+ }else if(tag == pair[p]) {
+ continue;
+ }else{
+ replacement += "<" + pair[p] + ">";
+ }
+ }
+ replacement += "DTL";
+ for(var p = pair.length - 1; p > 1; p--){
+ if(p == 2){
+ replacement += "" + tag + ">";
+ }else if(tag == pair[p]) {
+ continue;
+ }else{
+ replacement += "" + pair[p] + ">";
+ }
+ }
+ replace.push("\xFF" + replacements.length);
+ replacements.push(replacement);
+ }
+ }
+ }
+ text = text.replace(match[1], replace.join(""));
+ }
+ }
+ }
+ }
+
+ for(var i = replacements.length; i--;){
+ text = text.replace("\xFF" + i, replacements[i]);
+ }
+
+ var re = /\b([a-zA-Z_:][a-zA-Z0-9_\-\.:]*)=['"]/g;
+ while(match = re.exec(text)){
+ var lower = match[1].toLowerCase();
+ if(lower == "dtlinstruction"){ continue; }
+ if(lower != match[1]){
+ this._uppers[lower] = match[1];
+ }
+ this._attributes[lower] = true;
+ }
+ var div = document.createElement("div");
+ div.innerHTML = text;
+ var output = {nodes: []};
+ while(div.childNodes.length){
+ output.nodes.push(div.removeChild(div.childNodes[0]))
+ }
+
+ return output;
+ },
+ tokenize: function(/*Node*/ nodes){
+ var tokens = [];
+
+ for(var i = 0, node; node = nodes[i++];){
+ if(node.nodeType != 1){
+ this.__tokenize(node, tokens);
+ }else{
+ this._tokenize(node, tokens);
+ }
+ }
+
+ return tokens;
+ },
+ _swallowed: [],
+ _tokenize: function(/*Node*/ node, /*Array*/ tokens){
+ var first = false;
+ var swallowed = this._swallowed;
+ var i, j, tag, child;
+
+ if(!tokens.first){
+ // Try to efficiently associate tags that use an attribute to
+ // remove the node from DOM (eg dojoType) so that we can efficiently
+ // locate them later in the tokenizing.
+ first = tokens.first = true;
+ var tags = dd.register.getAttributeTags();
+ for(i = 0; tag = tags[i]; i++){
+ try{
+ (tag[2])({ swallowNode: function(){ throw 1; }}, new dd.Token(dd.TOKEN_ATTR, ""));
+ }catch(e){
+ swallowed.push(tag);
+ }
+ }
+ }
+
+ for(i = 0; tag = swallowed[i]; i++){
+ var text = node.getAttribute(tag[0]);
+ if(text){
+ var swallowed = false;
+ var custom = (tag[2])({ swallowNode: function(){ swallowed = true; return node; }}, new dd.Token(dd.TOKEN_ATTR, tag[0] + " " + text));
+ if(swallowed){
+ if(node.parentNode && node.parentNode.removeChild){
+ node.parentNode.removeChild(node);
+ }
+ tokens.push([dd.TOKEN_CUSTOM, custom]);
+ return;
+ }
+ }
+ }
+
+ var children = [];
+ if(has("ie") && node.tagName == "SCRIPT"){
+ children.push({
+ nodeType: 3,
+ data: node.text
+ });
+ node.text = "";
+ }else{
+ for(i = 0; child = node.childNodes[i]; i++){
+ children.push(child);
+ }
+ }
+
+ tokens.push([dd.TOKEN_NODE, node]);
+
+ var change = false;
+ if(children.length){
+ // Only do a change request if we need to
+ tokens.push([dd.TOKEN_CHANGE, node]);
+ change = true;
+ }
+
+ for(var key in this._attributes){
+ var clear = false;
+
+ var value = "";
+ if(key == "class"){
+ value = node.className || value;
+ }else if(key == "for"){
+ value = node.htmlFor || value;
+ }else if(key == "value" && node.value == node.innerHTML){
+ // Sometimes .value is set the same as the contents of the item (button)
+ continue;
+ }else if(node.getAttribute){
+ value = node.getAttribute(key, 2) || value;
+ if(key == "href" || key == "src"){
+ if(has("ie")){
+ var hash = location.href.lastIndexOf(location.hash);
+ var href = location.href.substring(0, hash).split("/");
+ href.pop();
+ href = href.join("/") + "/";
+ if(value.indexOf(href) == 0){
+ value = value.replace(href, "");
+ }
+ value = decodeURIComponent(value);
+ }
+ }else if(key == "tstyle"){
+ clear = key; // Placeholder because we can't use style
+ key = "style";
+ }else if(dd.BOOLS[key.slice(1)] && lang.trim(value)){
+ key = key.slice(1);
+ }else if(this._uppers[key] && lang.trim(value)){
+ clear = this._uppers[key]; // Replaced by lowercase
+ }
+ }
+
+ if(clear){
+ // Clear out values that are different than will
+ // be used in plugins
+ node.setAttribute(clear, "");
+ node.removeAttribute(clear);
+ }
+
+ if(typeof value == "function"){
+ value = value.toString().replace(this._re4, "$1");
+ }
+
+ if(!change){
+ // Only do a change request if we need to
+ tokens.push([dd.TOKEN_CHANGE, node]);
+ change = true;
+ }
+
+ // We'll have to resolve attributes during parsing (some ref plugins)
+
+ tokens.push([dd.TOKEN_ATTR, node, key, value]);
+ }
+
+ for(i = 0, child; child = children[i]; i++){
+ if(child.nodeType == 1){
+ var instruction = child.getAttribute("dtlinstruction");
+ if(instruction){
+ child.parentNode.removeChild(child);
+ child = {
+ nodeType: 8,
+ data: instruction
+ };
+ }
+ }
+ this.__tokenize(child, tokens);
+ }
+
+ if(!first && node.parentNode && node.parentNode.tagName){
+ if(change){
+ tokens.push([dd.TOKEN_CHANGE, node, true]);
+ }
+ tokens.push([dd.TOKEN_CHANGE, node.parentNode]);
+ node.parentNode.removeChild(node);
+ }else{
+ // If this node is parentless, it's a base node, so we have to "up" change to itself
+ // and note that it's a top-level to watch for errors
+ tokens.push([dd.TOKEN_CHANGE, node, true, true]);
+ }
+ },
+ __tokenize: function(child, tokens){
+ var data = child.data;
+ switch(child.nodeType){
+ case 1:
+ this._tokenize(child, tokens);
+ return;
+ case 3:
+ if(data.match(/[^\s\n]/) && (data.indexOf("{{") != -1 || data.indexOf("{%") != -1)){
+ var texts = ddt.tokenize(data);
+ for(var j = 0, text; text = texts[j]; j++){
+ if(typeof text == "string"){
+ tokens.push([dd.TOKEN_TEXT, text]);
+ }else{
+ tokens.push(text);
+ }
+ }
+ }else{
+ tokens.push([child.nodeType, child]);
+ }
+ if(child.parentNode) child.parentNode.removeChild(child);
+ return;
+ case 8:
+ if(data.indexOf("{%") == 0){
+ var text = lang.trim(data.slice(2, -2));
+ if(text.substr(0, 5) == "load "){
+ var parts = lang.trim(text).split(/\s+/g);
+ for(var i = 1, part; part = parts[i]; i++){
+ if (/\./.test(part)){
+ part = part.replace(/\./g,"/");
+ }
+ require([part]);
+ }
+ }
+ tokens.push([dd.TOKEN_BLOCK, text]);
+ }
+ if(data.indexOf("{{") == 0){
+ tokens.push([dd.TOKEN_VAR, lang.trim(data.slice(2, -2))]);
+ }
+ if(child.parentNode) child.parentNode.removeChild(child);
+ return;
+ }
+ }
+ };
+
+ dd.DomTemplate = lang.extend(function(/*String|DOMNode|dojo._Url*/ obj){
+ // summary: The template class for DOM templating.
+ if(!obj.nodes){
+ var node = dom.byId(obj);
+ if(node && node.nodeType == 1){
+ array.forEach(["class", "src", "href", "name", "value"], function(item){
+ ddh._attributes[item] = true;
+ });
+ obj = {
+ nodes: [node]
+ };
+ }else{
+ if(typeof obj == "object"){
+ obj = ddt.getTemplateString(obj);
+ }
+ obj = ddh.getTemplate(obj);
+ }
+ }
+
+ var tokens = ddh.tokenize(obj.nodes);
+ if(dd.tests){
+ this.tokens = tokens.slice(0);
+ }
+
+ var parser = new dd._DomParser(tokens);
+ this.nodelist = parser.parse();
+ },
+ {
+ _count: 0,
+ _re: /\bdojo:([a-zA-Z0-9_]+)\b/g,
+ setClass: function(/*String*/str){
+ // summary: Sets the specified class name on the root node.
+ this.getRootNode().className = str;
+ },
+ getRootNode: function(){
+ // summary: Returns the template root node.
+ return this.buffer.rootNode;
+ },
+ getBuffer: function(){
+ // summary: Returns a new buffer.
+ return new dd.DomBuffer();
+ },
+ render: function(/*dojox.dtl.Context?*/context, /*concatenable?*/buffer){
+ // summary: Renders this template.
+ buffer = this.buffer = buffer || this.getBuffer();
+ this.rootNode = null;
+ var output = this.nodelist.render(context || new dd.Context({}), buffer);
+ for(var i = 0, node; node = buffer._cache[i]; i++){
+ if(node._cache){
+ node._cache.length = 0;
+ }
+ }
+ return output;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ }
+ });
+
+ dd.DomBuffer = lang.extend(function(/*Node*/ parent){
+ // summary: Allows the manipulation of DOM
+ // description:
+ // Use this to append a child, change the parent, or
+ // change the attribute of the current node.
+ this._parent = parent;
+ this._cache = [];
+ },
+ {
+ concat: function(/*DOMNode*/ node){
+ var parent = this._parent;
+ if(parent && node.parentNode && node.parentNode === parent && !parent._dirty){
+ return this;
+ }
+
+ if(node.nodeType == 1 && !this.rootNode){
+ this.rootNode = node || true;
+ return this;
+ }
+
+ if(!parent){
+ if(node.nodeType == 3 && lang.trim(node.data)){
+ throw new Error("Text should not exist outside of the root node in template");
+ }
+ return this;
+ }
+ if(this._closed){
+ if(node.nodeType == 3 && !lang.trim(node.data)){
+ return this;
+ }else{
+ throw new Error("Content should not exist outside of the root node in template");
+ }
+ }
+ if(parent._dirty){
+ if(node._drawn && node.parentNode == parent){
+ var caches = parent._cache;
+ if(caches){
+ for(var i = 0, cache; cache = caches[i]; i++){
+ this.onAddNode && this.onAddNode(cache);
+ parent.insertBefore(cache, node);
+ this.onAddNodeComplete && this.onAddNodeComplete(cache);
+ }
+ caches.length = 0;
+ }
+ }
+ parent._dirty = false;
+ }
+ if(!parent._cache){
+ parent._cache = [];
+ this._cache.push(parent);
+ }
+ parent._dirty = true;
+ parent._cache.push(node);
+ return this;
+ },
+ remove: function(/*String|DomNode*/obj){
+ if(typeof obj == "string"){
+ if(this._parent){
+ this._parent.removeAttribute(obj);
+ }
+ }else{
+ if(obj.nodeType == 1 && !this.getRootNode() && !this._removed){
+ this._removed = true;
+ return this;
+ }
+ if(obj.parentNode){
+ this.onRemoveNode && this.onRemoveNode(obj);
+ if(obj.parentNode){
+ obj.parentNode.removeChild(obj);
+ }
+ }
+ }
+ return this;
+ },
+ setAttribute: function(key, value){
+ var old = html.attr(this._parent, key);
+ if(this.onChangeAttribute && old != value){
+ this.onChangeAttribute(this._parent, key, old, value);
+ }
+ if(key == "style"){
+ //console.log(value);
+ this._parent.style.cssText = value;
+ }else{
+ html.attr(this._parent, key, value);
+ //console.log(this._parent, key, value);
+ if(key == "value"){
+ this._parent.setAttribute(key, value);
+ }
+ }
+ return this;
+ },
+ addEvent: function(context, type, fn, /*Array|Function*/ args){
+ if(!context.getThis()){ throw new Error("You must use Context.setObject(instance)"); }
+ this.onAddEvent && this.onAddEvent(this.getParent(), type, fn);
+ var resolved = fn;
+ if(lang.isArray(args)){
+ resolved = function(e){
+ this[fn].apply(this, [e].concat(args));
+ }
+ }
+ return connect.connect(this.getParent(), type, context.getThis(), resolved);
+ },
+ setParent: function(node, /*Boolean?*/ up, /*Boolean?*/ root){
+ if(!this._parent) this._parent = this._first = node;
+
+ if(up && root && node === this._first){
+ this._closed = true;
+ }
+
+ if(up){
+ var parent = this._parent;
+ var script = "";
+ var ie = has("ie") && parent.tagName == "SCRIPT";
+ if(ie){
+ parent.text = "";
+ }
+ if(parent._dirty){
+ var caches = parent._cache;
+ var select = (parent.tagName == "SELECT" && !parent.options.length);
+ for(var i = 0, cache; cache = caches[i]; i++){
+ if(cache !== parent){
+ this.onAddNode && this.onAddNode(cache);
+ if(ie){
+ script += cache.data;
+ }else{
+ parent.appendChild(cache);
+ if(select && cache.defaultSelected && i){
+ select = i;
+ }
+ }
+ this.onAddNodeComplete && this.onAddNodeComplete(cache);
+ }
+ }
+ if(select){
+ parent.options.selectedIndex = (typeof select == "number") ? select : 0;
+ }
+ caches.length = 0;
+ parent._dirty = false;
+ }
+ if(ie){
+ parent.text = script;
+ }
+ }
+
+ this._parent = node;
+ this.onSetParent && this.onSetParent(node, up, root);
+ return this;
+ },
+ getParent: function(){
+ return this._parent;
+ },
+ getRootNode: function(){
+ return this.rootNode;
+ }
+ /*=====
+ ,
+ onSetParent: function(node, up){
+ // summary: Stub called when setParent is used.
+ },
+ onAddNode: function(node){
+ // summary: Stub called before new nodes are added
+ },
+ onAddNodeComplete: function(node){
+ // summary: Stub called after new nodes are added
+ },
+ onRemoveNode: function(node){
+ // summary: Stub called when nodes are removed
+ },
+ onChangeAttribute: function(node, attribute, old, updated){
+ // summary: Stub called when an attribute is changed
+ },
+ onChangeData: function(node, old, updated){
+ // summary: Stub called when a data in a node is changed
+ },
+ onClone: function(from, to){
+ // summary: Stub called when a node is duplicated
+ // from: DOMNode
+ // to: DOMNode
+ },
+ onAddEvent: function(node, type, description){
+ // summary: Stub to call when you're adding an event
+ // node: DOMNode
+ // type: String
+ // description: String
+ }
+ =====*/
+ });
+
+ dd._DomNode = lang.extend(function(node){
+ // summary: Places a node into DOM
+ this.contents = node;
+ },
+ {
+ render: function(context, buffer){
+ this._rendered = true;
+ return buffer.concat(this.contents);
+ },
+ unrender: function(context, buffer){
+ if(!this._rendered){
+ return buffer;
+ }
+ this._rendered = false;
+ return buffer.remove(this.contents);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.contents);
+ }
+ });
+
+ dd._DomNodeList = lang.extend(function(/*Node[]*/ nodes){
+ // summary: A list of any DOM-specific node objects
+ // description:
+ // Any object that's used in the constructor or added
+ // through the push function much implement the
+ // render, unrender, and clone functions.
+ this.contents = nodes || [];
+ },
+ {
+ push: function(node){
+ this.contents.push(node);
+ },
+ unshift: function(node){
+ this.contents.unshift(node);
+ },
+ render: function(context, buffer, /*Node*/ instance){
+ buffer = buffer || dd.DomTemplate.prototype.getBuffer();
+
+ if(instance){
+ var parent = buffer.getParent();
+ }
+ for(var i = 0; i < this.contents.length; i++){
+ buffer = this.contents[i].render(context, buffer);
+ if(!buffer) throw new Error("Template node render functions must return their buffer");
+ }
+ if(parent){
+ buffer.setParent(parent);
+ }
+ return buffer;
+ },
+ dummyRender: function(context, buffer, asNode){
+ // summary: A really expensive way of checking to see how a rendering will look.
+ // Used in the ifchanged tag
+ var div = document.createElement("div");
+
+ var parent = buffer.getParent();
+ var old = parent._clone;
+ // Tell the clone system to attach itself to our new div
+ parent._clone = div;
+ var nodelist = this.clone(buffer, div);
+ if(old){
+ // Restore state if there was a previous clone
+ parent._clone = old;
+ }else{
+ // Remove if there was no clone
+ parent._clone = null;
+ }
+
+ buffer = dd.DomTemplate.prototype.getBuffer();
+ nodelist.unshift(new dd.ChangeNode(div));
+ nodelist.unshift(new dd._DomNode(div));
+ nodelist.push(new dd.ChangeNode(div, true));
+ nodelist.render(context, buffer);
+
+ if(asNode){
+ return buffer.getRootNode();
+ }
+
+ var html = div.innerHTML;
+ return (has("ie")) ? domconstruct.replace(/\s*_(dirty|clone)="[^"]*"/g, "") : html;
+ },
+ unrender: function(context, buffer, instance){
+ if(instance){
+ var parent = buffer.getParent();
+ }
+ for(var i = 0; i < this.contents.length; i++){
+ buffer = this.contents[i].unrender(context, buffer);
+ if(!buffer) throw new Error("Template node render functions must return their buffer");
+ }
+ if(parent){
+ buffer.setParent(parent);
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ // summary:
+ // Used to create an identical copy of a NodeList, useful for things like the for tag.
+ var parent = buffer.getParent();
+ var contents = this.contents;
+ var nodelist = new dd._DomNodeList();
+ var cloned = [];
+ for(var i = 0; i < contents.length; i++){
+ var clone = contents[i].clone(buffer);
+ if(clone instanceof dd.ChangeNode || clone instanceof dd._DomNode){
+ var item = clone.contents._clone;
+ if(item){
+ clone.contents = item;
+ }else if(parent != clone.contents && clone instanceof dd._DomNode){
+ var node = clone.contents;
+ clone.contents = clone.contents.cloneNode(false);
+ buffer.onClone && buffer.onClone(node, clone.contents);
+ cloned.push(node);
+ node._clone = clone.contents;
+ }
+ }
+ nodelist.push(clone);
+ }
+
+ for(var i = 0, clone; clone = cloned[i]; i++){
+ clone._clone = null;
+ }
+
+ return nodelist;
+ },
+ rtrim: function(){
+ while(1){
+ var i = this.contents.length - 1;
+ if(this.contents[i] instanceof dd._DomTextNode && this.contents[i].isEmpty()){
+ this.contents.pop();
+ }else{
+ break;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ dd._DomVarNode = lang.extend(function(str){
+ // summary: A node to be processed as a variable
+ // description:
+ // Will render an object that supports the render function
+ // and the getRootNode function
+ this.contents = new dd._Filter(str);
+ },
+ {
+ render: function(context, buffer){
+ var str = this.contents.resolve(context);
+
+ // What type of rendering?
+ var type = "text";
+ if(str){
+ if(str.render && str.getRootNode){
+ type = "injection";
+ }else if(str.safe){
+ if(str.nodeType){
+ type = "node";
+ }else if(str.toString){
+ str = str.toString();
+ type = "html";
+ }
+ }
+ }
+
+ // Has the typed changed?
+ if(this._type && type != this._type){
+ this.unrender(context, buffer);
+ }
+ this._type = type;
+
+ // Now render
+ switch(type){
+ case "text":
+ this._rendered = true;
+ this._txt = this._txt || document.createTextNode(str);
+ if(this._txt.data != str){
+ var old = this._txt.data;
+ this._txt.data = str;
+ buffer.onChangeData && buffer.onChangeData(this._txt, old, this._txt.data);
+ }
+ return buffer.concat(this._txt);
+ case "injection":
+ var root = str.getRootNode();
+
+ if(this._rendered && root != this._root){
+ buffer = this.unrender(context, buffer);
+ }
+ this._root = root;
+
+ var injected = this._injected = new dd._DomNodeList();
+ injected.push(new dd.ChangeNode(buffer.getParent()));
+ injected.push(new dd._DomNode(root));
+ injected.push(str);
+ injected.push(new dd.ChangeNode(buffer.getParent()));
+ this._rendered = true;
+
+ return injected.render(context, buffer);
+ case "node":
+ this._rendered = true;
+ if(this._node && this._node != str && this._node.parentNode && this._node.parentNode === buffer.getParent()){
+ this._node.parentNode.removeChild(this._node);
+ }
+ this._node = str;
+ return buffer.concat(str);
+ case "html":
+ if(this._rendered && this._src != str){
+ buffer = this.unrender(context, buffer);
+ }
+ this._src = str;
+
+ // This can get reset in the above tag
+ if(!this._rendered){
+ this._rendered = true;
+ this._html = this._html || [];
+ var div = (this._div = this._div || document.createElement("div"));
+ div.innerHTML = str;
+ var children = div.childNodes;
+ while(children.length){
+ var removed = div.removeChild(children[0]);
+ this._html.push(removed);
+ buffer = buffer.concat(removed);
+ }
+ }
+
+ return buffer;
+ default:
+ return buffer;
+ }
+ },
+ unrender: function(context, buffer){
+ if(!this._rendered){
+ return buffer;
+ }
+ this._rendered = false;
+
+ // Unrender injected nodes
+ switch(this._type){
+ case "text":
+ return buffer.remove(this._txt);
+ case "injection":
+ return this._injection.unrender(context, buffer);
+ case "node":
+ if(this._node.parentNode === buffer.getParent()){
+ return buffer.remove(this._node);
+ }
+ return buffer;
+ case "html":
+ for(var i = 0, l = this._html.length; i < l; i++){
+ buffer = buffer.remove(this._html[i]);
+ }
+ return buffer;
+ default:
+ return buffer;
+ }
+ },
+ clone: function(){
+ return new this.constructor(this.contents.getExpression());
+ }
+ });
+
+ dd.ChangeNode = lang.extend(function(node, /*Boolean?*/ up, /*Bookean*/ root){
+ // summary: Changes the parent during render/unrender
+ this.contents = node;
+ this.up = up;
+ this.root = root;
+ },
+ {
+ render: function(context, buffer){
+ return buffer.setParent(this.contents, this.up, this.root);
+ },
+ unrender: function(context, buffer){
+ if(!buffer.getParent()){
+ return buffer;
+ }
+ return buffer.setParent(this.contents);
+ },
+ clone: function(){
+ return new this.constructor(this.contents, this.up, this.root);
+ }
+ });
+
+ dd.AttributeNode = lang.extend(function(key, value){
+ // summary: Works on attributes
+ this.key = key;
+ this.value = value;
+ this.contents = value;
+ if(this._pool[value]){
+ this.nodelist = this._pool[value];
+ }else{
+ if(!(this.nodelist = dd.quickFilter(value))){
+ this.nodelist = (new dd.Template(value, true)).nodelist;
+ }
+ this._pool[value] = this.nodelist;
+ }
+
+ this.contents = "";
+ },
+ {
+ _pool: {},
+ render: function(context, buffer){
+ var key = this.key;
+ var value = this.nodelist.dummyRender(context);
+ if(dd.BOOLS[key]){
+ value = !(value == "false" || value == "undefined" || !value);
+ }
+ if(value !== this.contents){
+ this.contents = value;
+ return buffer.setAttribute(key, value);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ this.contents = "";
+ return buffer.remove(this.key);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.key, this.value);
+ }
+ });
+
+ dd._DomTextNode = lang.extend(function(str){
+ // summary: Adds a straight text node without any processing
+ this.contents = document.createTextNode(str);
+ this.upcoming = str;
+ },
+ {
+ set: function(data){
+ this.upcoming = data;
+ return this;
+ },
+ render: function(context, buffer){
+ if(this.contents.data != this.upcoming){
+ var old = this.contents.data;
+ this.contents.data = this.upcoming;
+ buffer.onChangeData && buffer.onChangeData(this.contents, old, this.upcoming);
+ }
+ return buffer.concat(this.contents);
+ },
+ unrender: function(context, buffer){
+ return buffer.remove(this.contents);
+ },
+ isEmpty: function(){
+ return !lang.trim(this.contents.data);
+ },
+ clone: function(){
+ return new this.constructor(this.contents.data);
+ }
+ });
+
+ dd._DomParser = lang.extend(function(tokens){
+ // summary: Turn a simple array into a set of objects
+ // description:
+ // This is also used by all tags to move through
+ // the list of nodes.
+ this.contents = tokens;
+ },
+ {
+ i: 0,
+ parse: function(/*Array?*/ stop_at){
+ var terminators = {};
+ var tokens = this.contents;
+ if(!stop_at){
+ stop_at = [];
+ }
+ for(var i = 0; i < stop_at.length; i++){
+ terminators[stop_at[i]] = true;
+ }
+ var nodelist = new dd._DomNodeList();
+ while(this.i < tokens.length){
+ var token = tokens[this.i++];
+ var type = token[0];
+ var value = token[1];
+ if(type == dd.TOKEN_CUSTOM){
+ nodelist.push(value);
+ }else if(type == dd.TOKEN_CHANGE){
+ var changeNode = new dd.ChangeNode(value, token[2], token[3]);
+ value[changeNode.attr] = changeNode;
+ nodelist.push(changeNode);
+ }else if(type == dd.TOKEN_ATTR){
+ var fn = ddt.getTag("attr:" + token[2], true);
+ if(fn && token[3]){
+ if (token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1) {
+ value.setAttribute(token[2], "");
+ }
+ nodelist.push(fn(null, new dd.Token(type, token[2] + " " + token[3])));
+ }else if(lang.isString(token[3])){
+ if(token[2] == "style" || token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1){
+ nodelist.push(new dd.AttributeNode(token[2], token[3]));
+ }else if(lang.trim(token[3])){
+ try{
+ html.attr(value, token[2], token[3]);
+ }catch(e){}
+ }
+ }
+ }else if(type == dd.TOKEN_NODE){
+ var fn = ddt.getTag("node:" + value.tagName.toLowerCase(), true);
+ if(fn){
+ // TODO: We need to move this to tokenization so that it's before the
+ // node and the parser can be passed here instead of null
+ nodelist.push(fn(null, new dd.Token(type, value), value.tagName.toLowerCase()));
+ }
+ nodelist.push(new dd._DomNode(value));
+ }else if(type == dd.TOKEN_VAR){
+ nodelist.push(new dd._DomVarNode(value));
+ }else if(type == dd.TOKEN_TEXT){
+ nodelist.push(new dd._DomTextNode(value.data || value));
+ }else if(type == dd.TOKEN_BLOCK){
+ if(terminators[value]){
+ --this.i;
+ return nodelist;
+ }
+ var cmd = value.split(/\s+/g);
+ if(cmd.length){
+ cmd = cmd[0];
+ var fn = ddt.getTag(cmd);
+ if(typeof fn != "function"){
+ throw new Error("Function not found for " + cmd);
+ }
+ var tpl = fn(this, new dd.Token(type, value));
+ if(tpl){
+ nodelist.push(tpl);
+ }
+ }
+ }
+ }
+
+ if(stop_at.length){
+ throw new Error("Could not find closing tag(s): " + stop_at.toString());
+ }
+
+ return nodelist;
+ },
+ next_token: function(){
+ // summary: Returns the next token in the list.
+ var token = this.contents[this.i++];
+ return new dd.Token(token[0], token[1]);
+ },
+ delete_first_token: function(){
+ this.i++;
+ },
+ skip_past: function(endtag){
+ return dd._Parser.prototype.skip_past.call(this, endtag);
+ },
+ create_variable_node: function(expr){
+ return new dd._DomVarNode(expr);
+ },
+ create_text_node: function(expr){
+ return new dd._DomTextNode(expr || "");
+ },
+ getTemplate: function(/*String*/ loc){
+ return new dd.DomTemplate(ddh.getTemplate(loc));
+ }
+ });
+ return dojox.dtl.dom;
+});
diff --git a/js/libs/dojox/dtl/ext-dojo/NodeList.js b/js/libs/dojox/dtl/ext-dojo/NodeList.js
new file mode 100644
index 0000000..fc96d11
--- /dev/null
+++ b/js/libs/dojox/dtl/ext-dojo/NodeList.js
@@ -0,0 +1,21 @@
+//>>built
+define("dojox/dtl/ext-dojo/NodeList",["dojo/_base/lang","dojo/_base/NodeList","../_base"],function(_1,_2,dd){
+var nl=_1.getObject("dojox.dtl.ext-dojo.NodeList",true);
+_1.extend(_2,{dtl:function(_3,_4){
+var d=dd,_5=this;
+var _6=function(_7,_8){
+var _9=_7.render(new d._Context(_8));
+_5.forEach(function(_a){
+_a.innerHTML=_9;
+});
+};
+d.text._resolveTemplateArg(_3).addCallback(function(_b){
+_3=new d.Template(_b);
+d.text._resolveContextArg(_4).addCallback(function(_c){
+_6(_3,_c);
+});
+});
+return this;
+}});
+return nl;
+});
diff --git a/js/libs/dojox/dtl/ext-dojo/NodeList.js.uncompressed.js b/js/libs/dojox/dtl/ext-dojo/NodeList.js.uncompressed.js
new file mode 100644
index 0000000..d501685
--- /dev/null
+++ b/js/libs/dojox/dtl/ext-dojo/NodeList.js.uncompressed.js
@@ -0,0 +1,41 @@
+//>>built
+define("dojox/dtl/ext-dojo/NodeList", [
+ "dojo/_base/lang",
+ "dojo/_base/NodeList",
+ "../_base"
+], function(lang,Nodelist,dd){
+ /*=====
+ Nodelist = dojo.Nodelist;
+ dd = dojox.dtl;
+ =====*/
+
+ var nl = lang.getObject("dojox.dtl.ext-dojo.NodeList", true);
+
+ lang.extend(Nodelist, {
+ dtl: function(template, context){
+ // summary: Renders the specified template in each of the Nodelist entries.
+ // template: dojox.dtl.__StringArgs|String
+ // The template string or location
+ // context: dojox.dtl.__ObjectArgs|Object
+ // The context object or location
+ var d = dd, self = this;
+
+ var render = function(template, context){
+ var content = template.render(new d._Context(context));
+ self.forEach(function(node){
+ node.innerHTML = content;
+ });
+ }
+
+ d.text._resolveTemplateArg(template).addCallback(function(templateString){
+ template = new d.Template(templateString);
+ d.text._resolveContextArg(context).addCallback(function(context){
+ render(template, context);
+ });
+ });
+
+ return this;
+ }
+ });
+ return nl;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/dates.js b/js/libs/dojox/dtl/filter/dates.js
new file mode 100644
index 0000000..c231609
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/dates.js
@@ -0,0 +1,50 @@
+//>>built
+define("dojox/dtl/filter/dates",["dojo/_base/lang","../_base","../utils/date"],function(_1,dd,_2){
+_1.getObject("dojox.dtl.filter.dates",true);
+var _3=dd.filter.dates;
+_1.mixin(_3,{_toDate:function(_4){
+if(_4 instanceof Date){
+return _4;
+}
+_4=new Date(_4);
+if(_4.getTime()==new Date(0).getTime()){
+return "";
+}
+return _4;
+},date:function(_5,_6){
+_5=_3._toDate(_5);
+if(!_5){
+return "";
+}
+_6=_6||"N j, Y";
+return _2.format(_5,_6);
+},time:function(_7,_8){
+_7=_3._toDate(_7);
+if(!_7){
+return "";
+}
+_8=_8||"P";
+return _2.format(_7,_8);
+},timesince:function(_9,_a){
+_9=_3._toDate(_9);
+if(!_9){
+return "";
+}
+var _b=_2.timesince;
+if(_a){
+return _b(_a,_9);
+}
+return _b(_9);
+},timeuntil:function(_c,_d){
+_c=_3._toDate(_c);
+if(!_c){
+return "";
+}
+var _e=_2.timesince;
+if(_d){
+return _e(_d,_c);
+}
+return _e(new Date(),_c);
+}});
+return dojox.dtl.filter.dates;
+});
diff --git a/js/libs/dojox/dtl/filter/dates.js.uncompressed.js b/js/libs/dojox/dtl/filter/dates.js.uncompressed.js
new file mode 100644
index 0000000..b9714ad
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/dates.js.uncompressed.js
@@ -0,0 +1,68 @@
+//>>built
+define("dojox/dtl/filter/dates", [
+ "dojo/_base/lang",
+ "../_base",
+ "../utils/date"
+], function(lang,dd,ddud){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.dates", true);
+
+ var ddfd = dd.filter.dates;
+ lang.mixin(ddfd, {
+ _toDate: function(value){
+ if(value instanceof Date){
+ return value;
+ }
+ value = new Date(value);
+ if(value.getTime() == new Date(0).getTime()){
+ return "";
+ }
+ return value;
+ },
+ date: function(value, arg){
+ // summary: Formats a date according to the given format
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ arg = arg || "N j, Y";
+ return ddud.format(value, arg);
+ },
+ time: function(value, arg){
+ // summary: Formats a time according to the given format
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ arg = arg || "P";
+ return ddud.format(value, arg);
+ },
+ timesince: function(value, arg){
+ // summary: Formats a date as the time since that date (i.e. "4 days, 6 hours")
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ var timesince = ddud.timesince;
+ if(arg){
+ return timesince(arg, value);
+ }
+ return timesince(value);
+ },
+ timeuntil: function(value, arg){
+ // summary: Formats a date as the time until that date (i.e. "4 days, 6 hours")
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ var timesince = ddud.timesince;
+ if(arg){
+ return timesince(arg, value);
+ }
+ return timesince(new Date(), value);
+ }
+ });
+ return dojox.dtl.filter.dates;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/htmlstrings.js b/js/libs/dojox/dtl/filter/htmlstrings.js
new file mode 100644
index 0000000..8541e78
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/htmlstrings.js
@@ -0,0 +1,30 @@
+//>>built
+define("dojox/dtl/filter/htmlstrings",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.filter.htmlstrings",true);
+_1.mixin(dd.filter.htmlstrings,{_linebreaksrn:/(\r\n|\n\r)/g,_linebreaksn:/\n{2,}/g,_linebreakss:/(^\s+|\s+$)/g,_linebreaksbr:/\n/g,_removetagsfind:/[a-z0-9]+/g,_striptags:/<[^>]*?>/g,linebreaks:function(_2){
+var _3=[];
+var dh=dd.filter.htmlstrings;
+_2=_2.replace(dh._linebreaksrn,"\n");
+var _4=_2.split(dh._linebreaksn);
+for(var i=0;i<_4.length;i++){
+var _5=_4[i].replace(dh._linebreakss,"").replace(dh._linebreaksbr,"
");
+_3.push(""+_5+"
");
+}
+return _3.join("\n\n");
+},linebreaksbr:function(_6){
+var dh=dd.filter.htmlstrings;
+return _6.replace(dh._linebreaksrn,"\n").replace(dh._linebreaksbr,"
");
+},removetags:function(_7,_8){
+var dh=dd.filter.htmlstrings;
+var _9=[];
+var _a;
+while(_a=dh._removetagsfind.exec(_8)){
+_9.push(_a[0]);
+}
+_9="("+_9.join("|")+")";
+return _7.replace(new RegExp("?s*"+_9+"s*[^>]*>","gi"),"");
+},striptags:function(_b){
+return _b.replace(dojox.dtl.filter.htmlstrings._striptags,"");
+}});
+return dojox.dtl.filter.htmlstrings;
+});
diff --git a/js/libs/dojox/dtl/filter/htmlstrings.js.uncompressed.js b/js/libs/dojox/dtl/filter/htmlstrings.js.uncompressed.js
new file mode 100644
index 0000000..a10beef
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/htmlstrings.js.uncompressed.js
@@ -0,0 +1,53 @@
+//>>built
+define("dojox/dtl/filter/htmlstrings", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.htmlstrings", true);
+
+ lang.mixin(dd.filter.htmlstrings, {
+ _linebreaksrn: /(\r\n|\n\r)/g,
+ _linebreaksn: /\n{2,}/g,
+ _linebreakss: /(^\s+|\s+$)/g,
+ _linebreaksbr: /\n/g,
+ _removetagsfind: /[a-z0-9]+/g,
+ _striptags: /<[^>]*?>/g,
+ linebreaks: function(value){
+ // summary: Converts newlines into and
s
+ var output = [];
+ var dh = dd.filter.htmlstrings;
+ value = value.replace(dh._linebreaksrn, "\n");
+ var parts = value.split(dh._linebreaksn);
+ for(var i = 0; i < parts.length; i++){
+ var part = parts[i].replace(dh._linebreakss, "").replace(dh._linebreaksbr, "
");
+ output.push("
" + part + "
");
+ }
+
+ return output.join("\n\n");
+ },
+ linebreaksbr: function(value){
+ // summary: Converts newlines into
s
+ var dh = dd.filter.htmlstrings;
+ return value.replace(dh._linebreaksrn, "\n").replace(dh._linebreaksbr, "
");
+ },
+ removetags: function(value, arg){
+ // summary: Removes a space separated list of [X]HTML tags from the output"
+ var dh = dd.filter.htmlstrings;
+ var tags = [];
+ var group;
+ while(group = dh._removetagsfind.exec(arg)){
+ tags.push(group[0]);
+ }
+ tags = "(" + tags.join("|") + ")";
+ return value.replace(new RegExp("?\s*" + tags + "\s*[^>]*>", "gi"), "");
+ },
+ striptags: function(value){
+ // summary: Strips all [X]HTML tags
+ return value.replace(dojox.dtl.filter.htmlstrings._striptags, "");
+ }
+ });
+ return dojox.dtl.filter.htmlstrings;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/integers.js b/js/libs/dojox/dtl/filter/integers.js
new file mode 100644
index 0000000..72c09ed
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/integers.js
@@ -0,0 +1,22 @@
+//>>built
+define("dojox/dtl/filter/integers",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.filter.integers",true);
+_1.mixin(dd.filter.integers,{add:function(_2,_3){
+_2=parseInt(_2,10);
+_3=parseInt(_3,10);
+return isNaN(_3)?_2:_2+_3;
+},get_digit:function(_4,_5){
+_4=parseInt(_4,10);
+_5=parseInt(_5,10)-1;
+if(_5>=0){
+_4+="";
+if(_5<_4.length){
+_4=parseInt(_4.charAt(_5),10);
+}else{
+_4=0;
+}
+}
+return (isNaN(_4)?0:_4);
+}});
+return dojox.dtl.filter.integers;
+});
diff --git a/js/libs/dojox/dtl/filter/integers.js.uncompressed.js b/js/libs/dojox/dtl/filter/integers.js.uncompressed.js
new file mode 100644
index 0000000..86d0e54
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/integers.js.uncompressed.js
@@ -0,0 +1,38 @@
+//>>built
+define("dojox/dtl/filter/integers", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.integers", true);
+
+ lang.mixin(dd.filter.integers, {
+ add: function(value, arg){
+ value = parseInt(value, 10);
+ arg = parseInt(arg, 10);
+ return isNaN(arg) ? value : value + arg;
+ },
+ get_digit: function(value, arg){
+ // summary:
+ // Given a whole number, returns the 1-based requested digit of it
+ // desciprtion:
+ // 1 is the right-most digit, 2 is the second-right-most digit, etc. Returns the
+ // original value for invalid input (if input or argument is not an integer,
+ // or if argument is less than 1). Otherwise, output is always an integer.
+ value = parseInt(value, 10);
+ arg = parseInt(arg, 10) - 1;
+ if(arg >= 0){
+ value += "";
+ if(arg < value.length){
+ value = parseInt(value.charAt(arg), 10);
+ }else{
+ value = 0;
+ }
+ }
+ return (isNaN(value) ? 0 : value);
+ }
+ });
+ return dojox.dtl.filter.integers;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/lists.js b/js/libs/dojox/dtl/filter/lists.js
new file mode 100644
index 0000000..8f8e1be
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/lists.js
@@ -0,0 +1,88 @@
+//>>built
+define("dojox/dtl/filter/lists",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.filter.lists",true);
+_1.mixin(dd.filter.lists,{_dictsort:function(a,b){
+if(a[0]==b[0]){
+return 0;
+}
+return (a[0]"+_15[0]+"\n"+_17+"\n"+_18.join("\n")+"\n"+_17+"
\n"+_17+"";
+}else{
+return _17+""+_15[0]+"";
+}
+},unordered_list:function(_19){
+return dojox.dtl.filter.lists._unordered_list(_19,1);
+}});
+return dojox.dtl.filter.lists;
+});
diff --git a/js/libs/dojox/dtl/filter/lists.js.uncompressed.js b/js/libs/dojox/dtl/filter/lists.js.uncompressed.js
new file mode 100644
index 0000000..0292244
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/lists.js.uncompressed.js
@@ -0,0 +1,145 @@
+//>>built
+define("dojox/dtl/filter/lists", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.lists", true);
+
+ lang.mixin(dd.filter.lists, {
+ _dictsort: function(a, b){
+ if(a[0] == b[0]){
+ return 0;
+ }
+ return (a[0] < b[0]) ? -1 : 1;
+ },
+ dictsort: function(value, arg){
+ // summary: Takes a list of dicts, returns that list sorted by the property given in the argument.
+ if(!arg){
+ return value;
+ }
+
+ var i, item, items = [];
+ if(!lang.isArray(value)){
+ var obj = value, value = [];
+ for(var key in obj){
+ value.push(obj[key]);
+ }
+ }
+ for(i = 0; i < value.length; i++){
+ items.push([new dojox.dtl._Filter('var.' + arg).resolve(new dojox.dtl._Context({ 'var' : value[i]})), value[i]]);
+ }
+ items.sort(dojox.dtl.filter.lists._dictsort);
+ var output = [];
+ for(i = 0; item = items[i]; i++){
+ output.push(item[1]);
+ }
+ return output;
+ },
+ dictsortreversed: function(value, arg){
+ // summary: Takes a list of dicts, returns that list sorted in reverse order by the property given in the argument.
+ if(!arg) return value;
+
+ var dictsort = dojox.dtl.filter.lists.dictsort(value, arg);
+ return dictsort.reverse();
+ },
+ first: function(value){
+ // summary: Returns the first item in a list
+ return (value.length) ? value[0] : "";
+ },
+ join: function(value, arg){
+ // summary: Joins a list with a string, like Python's ``str.join(list)``
+ // description:
+ // Django throws a compile error, but JS can't do arg checks
+ // so we're left with run time errors, which aren't wise for something
+ // as trivial here as an empty arg.
+ return value.join(arg || ",");
+ },
+ length: function(value){
+ // summary: Returns the length of the value - useful for lists
+ return (isNaN(value.length)) ? (value + "").length : value.length;
+ },
+ length_is: function(value, arg){
+ // summary: Returns a boolean of whether the value's length is the argument
+ return value.length == parseInt(arg);
+ },
+ random: function(value){
+ // summary: Returns a random item from the list
+ return value[Math.floor(Math.random() * value.length)];
+ },
+ slice: function(value, arg){
+ // summary: Returns a slice of the list.
+ // description:
+ // Uses the same syntax as Python's list slicing; see
+ // http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice
+ // for an introduction.
+ // Also uses the optional third value to denote every X item.
+ arg = arg || "";
+ var parts = arg.split(":");
+ var bits = [];
+ for(var i = 0; i < parts.length; i++){
+ if(!parts[i].length){
+ bits.push(null);
+ }else{
+ bits.push(parseInt(parts[i]));
+ }
+ }
+
+ if(bits[0] === null){
+ bits[0] = 0;
+ }
+ if(bits[0] < 0){
+ bits[0] = value.length + bits[0];
+ }
+ if(bits.length < 2 || bits[1] === null){
+ bits[1] = value.length;
+ }
+ if(bits[1] < 0){
+ bits[1] = value.length + bits[1];
+ }
+
+ return value.slice(bits[0], bits[1]);
+ },
+ _unordered_list: function(value, tabs){
+ var ddl = dojox.dtl.filter.lists;
+ var i, indent = "";
+ for(i = 0; i < tabs; i++){
+ indent += "\t";
+ }
+ if(value[1] && value[1].length){
+ var recurse = [];
+ for(i = 0; i < value[1].length; i++){
+ recurse.push(ddl._unordered_list(value[1][i], tabs + 1))
+ }
+ return indent + "" + value[0] + "\n" + indent + "\n" + recurse.join("\n") + "\n" + indent + "
\n" + indent + "";
+ }else{
+ return indent + "" + value[0] + "";
+ }
+ },
+ unordered_list: function(value){
+ // summary:
+ // Recursively takes a self-nested list and returns an HTML unordered list --
+ // WITHOUT opening and closing tags.
+ // description:
+ // The list is assumed to be in the proper format. For example, if ``var`` contains
+ // ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
+ // then ``{{ var|unordered_list }}`` would return::
+ //
+ // | - States
+ // |
+ // | - Kansas
+ // |
+ // | - Lawrence
+ // | - Topeka
+ // |
+ // |
+ // | - Illinois
+ // |
+ // |
+ return dojox.dtl.filter.lists._unordered_list(value, 1);
+ }
+ });
+ return dojox.dtl.filter.lists;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/logic.js b/js/libs/dojox/dtl/filter/logic.js
new file mode 100644
index 0000000..600437b
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/logic.js
@@ -0,0 +1,27 @@
+//>>built
+define("dojox/dtl/filter/logic",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.filter.logic",true);
+_1.mixin(dd.filter.logic,{default_:function(_2,_3){
+return _2||_3||"";
+},default_if_none:function(_4,_5){
+return (_4===null)?_5||"":_4||"";
+},divisibleby:function(_6,_7){
+return (parseInt(_6,10)%parseInt(_7,10))===0;
+},_yesno:/\s*,\s*/g,yesno:function(_8,_9){
+if(!_9){
+_9="yes,no,maybe";
+}
+var _a=_9.split(dojox.dtl.filter.logic._yesno);
+if(_a.length<2){
+return _8;
+}
+if(_8){
+return _a[0];
+}
+if((!_8&&_8!==null)||_a.length<3){
+return _a[1];
+}
+return _a[2];
+}});
+return dojox.dtl.filter.logic;
+});
diff --git a/js/libs/dojox/dtl/filter/logic.js.uncompressed.js b/js/libs/dojox/dtl/filter/logic.js.uncompressed.js
new file mode 100644
index 0000000..9c8bf39
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/logic.js.uncompressed.js
@@ -0,0 +1,46 @@
+//>>built
+define("dojox/dtl/filter/logic", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.logic", true);
+
+ lang.mixin(dd.filter.logic, {
+ default_: function(value, arg){
+ // summary: If value is unavailable, use given default
+ return value || arg || "";
+ },
+ default_if_none: function(value, arg){
+ // summary: If value is null, use given default
+ return (value === null) ? arg || "" : value || "";
+ },
+ divisibleby: function(value, arg){
+ // summary: Returns true if the value is devisible by the argument"
+ return (parseInt(value, 10) % parseInt(arg, 10)) === 0;
+ },
+ _yesno: /\s*,\s*/g,
+ yesno: function(value, arg){
+ // summary:
+ // arg being a comma-delimited string, value of true/false/none
+ // chooses the appropriate item from the string
+ if(!arg){
+ arg = 'yes,no,maybe';
+ }
+ var parts = arg.split(dojox.dtl.filter.logic._yesno);
+ if(parts.length < 2){
+ return value;
+ }
+ if(value){
+ return parts[0];
+ }
+ if((!value && value !== null) || parts.length < 3){
+ return parts[1];
+ }
+ return parts[2];
+ }
+ });
+ return dojox.dtl.filter.logic;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/filter/misc.js b/js/libs/dojox/dtl/filter/misc.js
new file mode 100644
index 0000000..26e48ca
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/misc.js
@@ -0,0 +1,46 @@
+//>>built
+define("dojox/dtl/filter/misc",["dojo/_base/lang","dojo/_base/json","../_base"],function(_1,_2,dd){
+_1.getObject("dojox.dtl.filter.misc",true);
+_1.mixin(dd.filter.misc,{filesizeformat:function(_3){
+_3=parseFloat(_3);
+if(_3<1024){
+return (_3==1)?_3+" byte":_3+" bytes";
+}else{
+if(_3<1024*1024){
+return (_3/1024).toFixed(1)+" KB";
+}else{
+if(_3<1024*1024*1024){
+return (_3/1024/1024).toFixed(1)+" MB";
+}
+}
+}
+return (_3/1024/1024/1024).toFixed(1)+" GB";
+},pluralize:function(_4,_5){
+_5=_5||"s";
+if(_5.indexOf(",")==-1){
+_5=","+_5;
+}
+var _6=_5.split(",");
+if(_6.length>2){
+return "";
+}
+var _7=_6[0];
+var _8=_6[1];
+if(parseInt(_4,10)!=1){
+return _8;
+}
+return _7;
+},_phone2numeric:{a:2,b:2,c:2,d:3,e:3,f:3,g:4,h:4,i:4,j:5,k:5,l:5,m:6,n:6,o:6,p:7,r:7,s:7,t:8,u:8,v:8,w:9,x:9,y:9},phone2numeric:function(_9){
+var dm=dd.filter.misc;
+_9=_9+"";
+var _a="";
+for(var i=0;i<_9.length;i++){
+var _b=_9.charAt(i).toLowerCase();
+(dm._phone2numeric[_b])?_a+=dm._phone2numeric[_b]:_a+=_9.charAt(i);
+}
+return _a;
+},pprint:function(_c){
+return _2.toJson(_c);
+}});
+return dojox.dtl.filter.misc;
+});
diff --git a/js/libs/dojox/dtl/filter/misc.js.uncompressed.js b/js/libs/dojox/dtl/filter/misc.js.uncompressed.js
new file mode 100644
index 0000000..2b88a4a
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/misc.js.uncompressed.js
@@ -0,0 +1,66 @@
+//>>built
+define("dojox/dtl/filter/misc", [
+ "dojo/_base/lang",
+ "dojo/_base/json", // dojo.toJson
+ "../_base"
+], function(lang,json,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.misc", true);
+
+ lang.mixin(dd.filter.misc, {
+ filesizeformat: function(value){
+ // summary: Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102bytes, etc).
+ value = parseFloat(value);
+ if(value < 1024){
+ return (value == 1) ? value + " byte" : value + " bytes";
+ }else if(value < 1024 * 1024){
+ return (value / 1024).toFixed(1) + " KB";
+ }else if(value < 1024 * 1024 * 1024){
+ return (value / 1024 / 1024).toFixed(1) + " MB";
+ }
+ return (value / 1024 / 1024 / 1024).toFixed(1) + " GB";
+ },
+ pluralize: function(value, arg){
+ // summary:
+ // Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
+ // description:
+ // By default, 's' is used as a suffix; if an argument is provided, that string
+ // is used instead. If the provided argument contains a comma, the text before
+ // the comma is used for the singular case.
+ arg = arg || 's';
+ if(arg.indexOf(",") == -1){
+ arg = "," + arg;
+ }
+ var parts = arg.split(",");
+ if(parts.length > 2){
+ return "";
+ }
+ var singular = parts[0];
+ var plural = parts[1];
+
+ if(parseInt(value, 10) != 1){
+ return plural;
+ }
+ return singular;
+ },
+ _phone2numeric: { a: 2, b: 2, c: 2, d: 3, e: 3, f: 3, g: 4, h: 4, i: 4, j: 5, k: 5, l: 5, m: 6, n: 6, o: 6, p: 7, r: 7, s: 7, t: 8, u: 8, v: 8, w: 9, x: 9, y: 9 },
+ phone2numeric: function(value){
+ // summary: Takes a phone number and converts it in to its numerical equivalent
+ var dm = dd.filter.misc;
+ value = value + "";
+ var output = "";
+ for(var i = 0; i < value.length; i++){
+ var chr = value.charAt(i).toLowerCase();
+ (dm._phone2numeric[chr]) ? output += dm._phone2numeric[chr] : output += value.charAt(i);
+ }
+ return output;
+ },
+ pprint: function(value){
+ // summary: A wrapper around toJson unless something better comes along
+ return json.toJson(value);
+ }
+ });
+ return dojox.dtl.filter.misc;
+});
diff --git a/js/libs/dojox/dtl/filter/strings.js b/js/libs/dojox/dtl/filter/strings.js
new file mode 100644
index 0000000..32350d7
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/strings.js
@@ -0,0 +1,261 @@
+//>>built
+define("dojox/dtl/filter/strings",["dojo/_base/lang","dojo/_base/array","dojox/string/tokenize","dojox/string/sprintf","../filter/htmlstrings","../_base"],function(_1,_2,_3,_4,_5,dd){
+_1.getObject("dojox.dtl.filter.strings",true);
+_1.mixin(dd.filter.strings,{_urlquote:function(_6,_7){
+if(!_7){
+_7="/";
+}
+return _3(_6,/([^\w-_.])/g,function(_8){
+if(_7.indexOf(_8)==-1){
+if(_8==" "){
+return "+";
+}else{
+return "%"+_8.charCodeAt(0).toString(16).toUpperCase();
+}
+}
+return _8;
+}).join("");
+},addslashes:function(_9){
+return _9.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/'/g,"\\'");
+},capfirst:function(_a){
+_a=""+_a;
+return _a.charAt(0).toUpperCase()+_a.substring(1);
+},center:function(_b,_c){
+_c=_c||_b.length;
+_b=_b+"";
+var _d=_c-_b.length;
+if(_d%2){
+_b=_b+" ";
+_d-=1;
+}
+for(var i=0;i<_d;i+=2){
+_b=" "+_b+" ";
+}
+return _b;
+},cut:function(_e,_f){
+_f=_f+""||"";
+_e=_e+"";
+return _e.replace(new RegExp(_f,"g"),"");
+},_fix_ampersands:/&(?!(\w+|#\d+);)/g,fix_ampersands:function(_10){
+return _10.replace(dojox.dtl.filter.strings._fix_ampersands,"&");
+},floatformat:function(_11,arg){
+arg=parseInt(arg||-1,10);
+_11=parseFloat(_11);
+var m=_11-_11.toFixed(0);
+if(!m&&arg<0){
+return _11.toFixed();
+}
+_11=_11.toFixed(Math.abs(arg));
+return (arg<0)?parseFloat(_11)+"":_11;
+},iriencode:function(_12){
+return dojox.dtl.filter.strings._urlquote(_12,"/#%[]=:;$&()+,!");
+},linenumbers:function(_13){
+var df=dojox.dtl.filter;
+var _14=_13.split("\n");
+var _15=[];
+var _16=(_14.length+"").length;
+for(var i=0,_17;i<_14.length;i++){
+_17=_14[i];
+_15.push(df.strings.ljust(i+1,_16)+". "+dojox.dtl._base.escape(_17));
+}
+return _15.join("\n");
+},ljust:function(_18,arg){
+_18=_18+"";
+arg=parseInt(arg,10);
+while(_18.length|(\w[\w\-]*))/g,_truncate_tag:/<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,_truncate_singlets:{br:true,col:true,link:true,base:true,img:true,param:true,area:true,hr:true,input:true},truncatewords_html:function(_28,arg){
+arg=parseInt(arg,10);
+if(arg<=0){
+return "";
+}
+var _29=dojox.dtl.filter.strings;
+var _2a=0;
+var _2b=[];
+var _2c=_3(_28,_29._truncate_words,function(all,_2d){
+if(_2d){
+++_2a;
+if(_2a=arg){
+return;
+}
+var _2e=tag[1];
+var _2f=tag[2].toLowerCase();
+var _30=tag[3];
+if(_2e||_29._truncate_singlets[_2f]){
+}else{
+if(_2e){
+var i=_2.indexOf(_2b,_2f);
+if(i!=-1){
+_2b=_2b.slice(i+1);
+}
+}else{
+_2b.unshift(_2f);
+}
+}
+return all;
+}).join("");
+_2c=_2c.replace(/\s+$/g,"");
+for(var i=0,tag;tag=_2b[i];i++){
+_2c+=""+tag+">";
+}
+return _2c;
+},upper:function(_31){
+return _31.toUpperCase();
+},urlencode:function(_32){
+return dojox.dtl.filter.strings._urlquote(_32);
+},_urlize:/^((?:[(>]|<)*)(.*?)((?:[.,)>\n]|>)*)$/,_urlize2:/^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,urlize:function(_33){
+return dojox.dtl.filter.strings.urlizetrunc(_33);
+},urlizetrunc:function(_34,arg){
+arg=parseInt(arg);
+return _3(_34,/(\S+)/g,function(_35){
+var _36=dojox.dtl.filter.strings._urlize.exec(_35);
+if(!_36){
+return _35;
+}
+var _37=_36[1];
+var _38=_36[2];
+var _39=_36[3];
+var _3a=_38.indexOf("www.")==0;
+var _3b=_38.indexOf("@")!=-1;
+var _3c=_38.indexOf(":")!=-1;
+var _3d=_38.indexOf("http://")==0;
+var _3e=_38.indexOf("https://")==0;
+var _3f=/[a-zA-Z0-9]/.test(_38.charAt(0));
+var _40=_38.substring(_38.length-4);
+var _41=_38;
+if(arg>3){
+_41=_41.substring(0,arg-3)+"...";
+}
+if(_3a||(!_3b&&!_3d&&_38.length&&_3f&&(_40==".org"||_40==".net"||_40==".com"))){
+return ""+_41+"";
+}else{
+if(_3d||_3e){
+return ""+_41+"";
+}else{
+if(_3b&&!_3a&&!_3c&&dojox.dtl.filter.strings._urlize2.test(_38)){
+return ""+_38+"";
+}
+}
+}
+return _35;
+}).join("");
+},wordcount:function(_42){
+_42=_1.trim(_42);
+if(!_42){
+return 0;
+}
+return _42.split(/\s+/g).length;
+},wordwrap:function(_43,arg){
+arg=parseInt(arg);
+var _44=[];
+var _45=_43.split(/\s+/g);
+if(_45.length){
+var _46=_45.shift();
+_44.push(_46);
+var pos=_46.length-_46.lastIndexOf("\n")-1;
+for(var i=0;i<_45.length;i++){
+_46=_45[i];
+if(_46.indexOf("\n")!=-1){
+var _47=_46.split(/\n/g);
+}else{
+var _47=[_46];
+}
+pos+=_47[0].length+1;
+if(arg&&pos>arg){
+_44.push("\n");
+pos=_47[_47.length-1].length;
+}else{
+_44.push(" ");
+if(_47.length>1){
+pos=_47[_47.length-1].length;
+}
+}
+_44.push(_46);
+}
+}
+return _44.join("");
+}});
+return dojox.dtl.filter.strings;
+});
diff --git a/js/libs/dojox/dtl/filter/strings.js.uncompressed.js b/js/libs/dojox/dtl/filter/strings.js.uncompressed.js
new file mode 100644
index 0000000..da71c3e
--- /dev/null
+++ b/js/libs/dojox/dtl/filter/strings.js.uncompressed.js
@@ -0,0 +1,337 @@
+//>>built
+define("dojox/dtl/filter/strings", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojox/string/tokenize",
+ "dojox/string/sprintf",
+ "../filter/htmlstrings",
+ "../_base"
+], function(lang,array,Tokenize,Sprintf,htmlstrings,dd){
+ /*=====
+ dd = dojox.dtl;
+ Tokenize = dojox.string.tokenize;
+ Sprintf = dojox.string.sprintf;
+ =====*/
+ lang.getObject("dojox.dtl.filter.strings", true);
+
+ lang.mixin(dd.filter.strings, {
+ _urlquote: function(/*String*/ url, /*String?*/ safe){
+ if(!safe){
+ safe = "/";
+ }
+ return Tokenize(url, /([^\w-_.])/g, function(token){
+ if(safe.indexOf(token) == -1){
+ if(token == " "){
+ return "+";
+ }else{
+ return "%" + token.charCodeAt(0).toString(16).toUpperCase();
+ }
+ }
+ return token;
+ }).join("");
+ },
+ addslashes: function(value){
+ // summary: Adds slashes - useful for passing strings to JavaScript, for example.
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
+ },
+ capfirst: function(value){
+ // summary: Capitalizes the first character of the value
+ value = "" + value;
+ return value.charAt(0).toUpperCase() + value.substring(1);
+ },
+ center: function(value, arg){
+ // summary: Centers the value in a field of a given width
+ arg = arg || value.length;
+ value = value + "";
+ var diff = arg - value.length;
+ if(diff % 2){
+ value = value + " ";
+ diff -= 1;
+ }
+ for(var i = 0; i < diff; i += 2){
+ value = " " + value + " ";
+ }
+ return value;
+ },
+ cut: function(value, arg){
+ // summary: Removes all values of arg from the given string
+ arg = arg + "" || "";
+ value = value + "";
+ return value.replace(new RegExp(arg, "g"), "");
+ },
+ _fix_ampersands: /&(?!(\w+|#\d+);)/g,
+ fix_ampersands: function(value){
+ // summary: Replaces ampersands with ``&`` entities
+ return value.replace(dojox.dtl.filter.strings._fix_ampersands, "&");
+ },
+ floatformat: function(value, arg){
+ // summary: Format a number according to arg
+ // description:
+ // If called without an argument, displays a floating point
+ // number as 34.2 -- but only if there's a point to be displayed.
+ // With a positive numeric argument, it displays that many decimal places
+ // always.
+ // With a negative numeric argument, it will display that many decimal
+ // places -- but only if there's places to be displayed.
+ arg = parseInt(arg || -1, 10);
+ value = parseFloat(value);
+ var m = value - value.toFixed(0);
+ if(!m && arg < 0){
+ return value.toFixed();
+ }
+ value = value.toFixed(Math.abs(arg));
+ return (arg < 0) ? parseFloat(value) + "" : value;
+ },
+ iriencode: function(value){
+ return dojox.dtl.filter.strings._urlquote(value, "/#%[]=:;$&()+,!");
+ },
+ linenumbers: function(value){
+ // summary: Displays text with line numbers
+ var df = dojox.dtl.filter;
+ var lines = value.split("\n");
+ var output = [];
+ var width = (lines.length + "").length;
+ for(var i = 0, line; i < lines.length; i++){
+ line = lines[i];
+ output.push(df.strings.ljust(i + 1, width) + ". " + dojox.dtl._base.escape(line));
+ }
+ return output.join("\n");
+ },
+ ljust: function(value, arg){
+ value = value + "";
+ arg = parseInt(arg, 10);
+ while(value.length < arg){
+ value = value + " ";
+ }
+ return value;
+ },
+ lower: function(value){
+ // summary: Converts a string into all lowercase
+ return (value + "").toLowerCase();
+ },
+ make_list: function(value){
+ // summary:
+ // Returns the value turned into a list. For an integer, it's a list of
+ // digits. For a string, it's a list of characters.
+ var output = [];
+ if(typeof value == "number"){
+ value = value + "";
+ }
+ if(value.charAt){
+ for(var i = 0; i < value.length; i++){
+ output.push(value.charAt(i));
+ }
+ return output;
+ }
+ if(typeof value == "object"){
+ for(var key in value){
+ output.push(value[key]);
+ }
+ return output;
+ }
+ return [];
+ },
+ rjust: function(value, arg){
+ value = value + "";
+ arg = parseInt(arg, 10);
+ while(value.length < arg){
+ value = " " + value;
+ }
+ return value;
+ },
+ slugify: function(value){
+ // summary: Converts to lowercase, removes
+ // non-alpha chars and converts spaces to hyphens
+ value = value.replace(/[^\w\s-]/g, "").toLowerCase();
+ return value.replace(/[\-\s]+/g, "-");
+ },
+ _strings: {},
+ stringformat: function(value, arg){
+ // summary:
+ // Formats the variable according to the argument, a string formatting specifier.
+ // This specifier uses Python string formating syntax, with the exception that
+ // the leading "%" is dropped.
+ arg = "" + arg;
+ var strings = dojox.dtl.filter.strings._strings;
+ if(!strings[arg]){
+ strings[arg] = new Sprintf.Formatter("%" + arg);
+ }
+ return strings[arg].format(value);
+ },
+ title: function(value){
+ // summary: Converts a string into titlecase
+ var last, title = "";
+ for(var i = 0, current; i < value.length; i++){
+ current = value.charAt(i);
+ if(last == " " || last == "\n" || last == "\t" || !last){
+ title += current.toUpperCase();
+ }else{
+ title += current.toLowerCase();
+ }
+ last = current;
+ }
+ return title;
+ },
+ _truncatewords: /[ \n\r\t]/,
+ truncatewords: function(value, arg){
+ // summary: Truncates a string after a certain number of words
+ // arg: Integer
+ // Number of words to truncate after
+ arg = parseInt(arg, 10);
+ if(!arg){
+ return value;
+ }
+
+ for(var i = 0, j = value.length, count = 0, current, last; i < value.length; i++){
+ current = value.charAt(i);
+ if(dojox.dtl.filter.strings._truncatewords.test(last)){
+ if(!dojox.dtl.filter.strings._truncatewords.test(current)){
+ ++count;
+ if(count == arg){
+ return value.substring(0, j + 1);
+ }
+ }
+ }else if(!dojox.dtl.filter.strings._truncatewords.test(current)){
+ j = i;
+ }
+ last = current;
+ }
+ return value;
+ },
+ _truncate_words: /(&.*?;|<.*?>|(\w[\w\-]*))/g,
+ _truncate_tag: /<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,
+ _truncate_singlets: { br: true, col: true, link: true, base: true, img: true, param: true, area: true, hr: true, input: true },
+ truncatewords_html: function(value, arg){
+ arg = parseInt(arg, 10);
+
+ if(arg <= 0){
+ return "";
+ }
+
+ var strings = dojox.dtl.filter.strings;
+ var words = 0;
+ var open = [];
+
+ var output = Tokenize(value, strings._truncate_words, function(all, word){
+ if(word){
+ // It's an actual non-HTML word
+ ++words;
+ if(words < arg){
+ return word;
+ }else if(words == arg){
+ return word + " ...";
+ }
+ }
+ // Check for tag
+ var tag = all.match(strings._truncate_tag);
+ if(!tag || words >= arg){
+ // Don't worry about non tags or tags after our truncate point
+ return;
+ }
+ var closing = tag[1];
+ var tagname = tag[2].toLowerCase();
+ var selfclosing = tag[3];
+ if(closing || strings._truncate_singlets[tagname]){
+ }else if(closing){
+ var i = array.indexOf(open, tagname);
+ if(i != -1){
+ open = open.slice(i + 1);
+ }
+ }else{
+ open.unshift(tagname);
+ }
+ return all;
+ }).join("");
+
+ output = output.replace(/\s+$/g, "");
+
+ for(var i = 0, tag; tag = open[i]; i++){
+ output += "" + tag + ">";
+ }
+
+ return output;
+ },
+ upper: function(value){
+ return value.toUpperCase();
+ },
+ urlencode: function(value){
+ return dojox.dtl.filter.strings._urlquote(value);
+ },
+ _urlize: /^((?:[(>]|<)*)(.*?)((?:[.,)>\n]|>)*)$/,
+ _urlize2: /^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,
+ urlize: function(value){
+ return dojox.dtl.filter.strings.urlizetrunc(value);
+ },
+ urlizetrunc: function(value, arg){
+ arg = parseInt(arg);
+ return Tokenize(value, /(\S+)/g, function(word){
+ var matches = dojox.dtl.filter.strings._urlize.exec(word);
+ if(!matches){
+ return word;
+ }
+ var lead = matches[1];
+ var middle = matches[2];
+ var trail = matches[3];
+
+ var startsWww = middle.indexOf("www.") == 0;
+ var hasAt = middle.indexOf("@") != -1;
+ var hasColon = middle.indexOf(":") != -1;
+ var startsHttp = middle.indexOf("http://") == 0;
+ var startsHttps = middle.indexOf("https://") == 0;
+ var firstAlpha = /[a-zA-Z0-9]/.test(middle.charAt(0));
+ var last4 = middle.substring(middle.length - 4);
+
+ var trimmed = middle;
+ if(arg > 3){
+ trimmed = trimmed.substring(0, arg - 3) + "...";
+ }
+
+ if(startsWww || (!hasAt && !startsHttp && middle.length && firstAlpha && (last4 == ".org" || last4 == ".net" || last4 == ".com"))){
+ return '' + trimmed + '';
+ }else if(startsHttp || startsHttps){
+ return '' + trimmed + '';
+ }else if(hasAt && !startsWww && !hasColon && dojox.dtl.filter.strings._urlize2.test(middle)){
+ return '' + middle + '';
+ }
+ return word;
+ }).join("");
+ },
+ wordcount: function(value){
+ value = lang.trim(value);
+ if(!value){ return 0; }
+ return value.split(/\s+/g).length;
+ },
+ wordwrap: function(value, arg){
+ arg = parseInt(arg);
+ // summary: Wraps words at specified line length
+ var output = [];
+ var parts = value.split(/\s+/g);
+ if(parts.length){
+ var word = parts.shift();
+ output.push(word);
+ var pos = word.length - word.lastIndexOf("\n") - 1;
+ for(var i = 0; i < parts.length; i++){
+ word = parts[i];
+ if(word.indexOf("\n") != -1){
+ var lines = word.split(/\n/g);
+ }else{
+ var lines = [word];
+ }
+ pos += lines[0].length + 1;
+ if(arg && pos > arg){
+ output.push("\n");
+ pos = lines[lines.length - 1].length;
+ }else{
+ output.push(" ");
+ if(lines.length > 1){
+ pos = lines[lines.length - 1].length;
+ }
+ }
+ output.push(word);
+ }
+ }
+ return output.join("");
+ }
+ });
+ return dojox.dtl.filter.strings;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/render/dom.js b/js/libs/dojox/dtl/render/dom.js
new file mode 100644
index 0000000..19c7ef9
--- /dev/null
+++ b/js/libs/dojox/dtl/render/dom.js
@@ -0,0 +1,27 @@
+//>>built
+define("dojox/dtl/render/dom",["dojo/_base/lang","dojo/dom","../Context","../dom","../_base"],function(_1,_2,_3,_4,dd){
+_1.getObject("dojox.dtl.render.dom",true);
+dd.render.dom.Render=function(_5,_6){
+this._tpl=_6;
+this.domNode=_2.byId(_5);
+};
+_1.extend(dd.render.dom.Render,{setAttachPoint:function(_7){
+this.domNode=_7;
+},render:function(_8,_9,_a){
+if(!this.domNode){
+throw new Error("You cannot use the Render object without specifying where you want to render it");
+}
+this._tpl=_9=_9||this._tpl;
+_a=_a||_9.getBuffer();
+_8=_8||new _3();
+var _b=_9.render(_8,_a).getParent();
+if(!_b){
+throw new Error("Rendered template does not have a root node");
+}
+if(this.domNode!==_b){
+this.domNode.parentNode.replaceChild(_b,this.domNode);
+this.domNode=_b;
+}
+}});
+return dojox.dtl.render.dom;
+});
diff --git a/js/libs/dojox/dtl/render/dom.js.uncompressed.js b/js/libs/dojox/dtl/render/dom.js.uncompressed.js
new file mode 100644
index 0000000..07af56a
--- /dev/null
+++ b/js/libs/dojox/dtl/render/dom.js.uncompressed.js
@@ -0,0 +1,43 @@
+//>>built
+define("dojox/dtl/render/dom", [
+ "dojo/_base/lang",
+ "dojo/dom",
+ "../Context",
+ "../dom",
+ "../_base"
+], function(lang,dom,ddc,dddom,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.render.dom", true);
+
+ dd.render.dom.Render = function(/*DOMNode?*/ attachPoint, /*dojox.dtl.DomTemplate?*/ tpl){
+ this._tpl = tpl;
+ this.domNode = dom.byId(attachPoint);
+ }
+ lang.extend(dd.render.dom.Render, {
+ setAttachPoint: function(/*Node*/ node){
+ this.domNode = node;
+ },
+ render: function(/*Object*/ context, /*dojox.dtl.DomTemplate?*/ tpl, /*dojox.dtl.DomBuffer?*/ buffer){
+ if(!this.domNode){
+ throw new Error("You cannot use the Render object without specifying where you want to render it");
+ }
+
+ this._tpl = tpl = tpl || this._tpl;
+ buffer = buffer || tpl.getBuffer();
+ context = context || new ddc();
+
+ var frag = tpl.render(context, buffer).getParent();
+ if(!frag){
+ throw new Error("Rendered template does not have a root node");
+ }
+
+ if(this.domNode !== frag){
+ this.domNode.parentNode.replaceChild(frag, this.domNode);
+ this.domNode = frag;
+ }
+ }
+ });
+ return dojox.dtl.render.dom;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/render/html.js b/js/libs/dojox/dtl/render/html.js
new file mode 100644
index 0000000..99932f4
--- /dev/null
+++ b/js/libs/dojox/dtl/render/html.js
@@ -0,0 +1,6 @@
+//>>built
+define("dojox/dtl/render/html",["dojo/_base/lang","../render/dom","../_base"],function(_1,_2,dd){
+_1.getObject("dojox.dtl.render.html",true);
+dd.render.html.Render=_2.Render;
+return dojox.dtl.render.html;
+});
diff --git a/js/libs/dojox/dtl/render/html.js.uncompressed.js b/js/libs/dojox/dtl/render/html.js.uncompressed.js
new file mode 100644
index 0000000..6b7296f
--- /dev/null
+++ b/js/libs/dojox/dtl/render/html.js.uncompressed.js
@@ -0,0 +1,14 @@
+//>>built
+define("dojox/dtl/render/html", [
+ "dojo/_base/lang",
+ "../render/dom",
+ "../_base"
+], function(lang,ddrd,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.render.html", true);
+
+ dd.render.html.Render = ddrd.Render;
+ return dojox.dtl.render.html;
+});
diff --git a/js/libs/dojox/dtl/tag/date.js b/js/libs/dojox/dtl/tag/date.js
new file mode 100644
index 0000000..c436970
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/date.js
@@ -0,0 +1,25 @@
+//>>built
+define("dojox/dtl/tag/date",["dojo/_base/lang","../_base","../utils/date"],function(_1,dd,_2){
+_1.getObject("dojox.dtl.tag.date",true);
+dojox.dtl.tag.date.NowNode=function(_3,_4){
+this._format=_3;
+this.format=new _2.DateFormat(_3);
+this.contents=_4;
+};
+_1.extend(dd.tag.date.NowNode,{render:function(_5,_6){
+this.contents.set(this.format.format(new Date()));
+return this.contents.render(_5,_6);
+},unrender:function(_7,_8){
+return this.contents.unrender(_7,_8);
+},clone:function(_9){
+return new this.constructor(this._format,this.contents.clone(_9));
+}});
+dojox.dtl.tag.date.now=function(_a,_b){
+var _c=_b.split_contents();
+if(_c.length!=2){
+throw new Error("'now' statement takes one argument");
+}
+return new dojox.dtl.tag.date.NowNode(_c[1].slice(1,-1),_a.create_text_node());
+};
+return dojox.dtl.tag.date;
+});
diff --git a/js/libs/dojox/dtl/tag/date.js.uncompressed.js b/js/libs/dojox/dtl/tag/date.js.uncompressed.js
new file mode 100644
index 0000000..afb8aa3
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/date.js.uncompressed.js
@@ -0,0 +1,39 @@
+//>>built
+define("dojox/dtl/tag/date", [
+ "dojo/_base/lang",
+ "../_base",
+ "../utils/date"
+], function(lang,dd,ddud){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.date", true);
+
+ dojox.dtl.tag.date.NowNode = function(format, node){
+ this._format = format;
+ this.format = new ddud.DateFormat(format);
+ this.contents = node;
+ }
+ lang.extend(dd.tag.date.NowNode, {
+ render: function(context, buffer){
+ this.contents.set(this.format.format(new Date()));
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this._format, this.contents.clone(buffer));
+ }
+ });
+
+ dojox.dtl.tag.date.now = function(parser, token){
+ // Split by either :" or :'
+ var parts = token.split_contents();
+ if(parts.length != 2){
+ throw new Error("'now' statement takes one argument");
+ }
+ return new dojox.dtl.tag.date.NowNode(parts[1].slice(1, -1), parser.create_text_node());
+ };
+ return dojox.dtl.tag.date;
+});
diff --git a/js/libs/dojox/dtl/tag/loader.js b/js/libs/dojox/dtl/tag/loader.js
new file mode 100644
index 0000000..bf6225f
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/loader.js
@@ -0,0 +1,250 @@
+//>>built
+define("dojox/dtl/tag/loader",["dojo/_base/lang","../_base","dojo/_base/array","dojo/_base/connect"],function(_1,dd,_2,_3){
+_1.getObject("dojox.dtl.tag.loader",true);
+var _4=dd.tag.loader;
+_4.BlockNode=_1.extend(function(_5,_6){
+this.name=_5;
+this.nodelist=_6;
+},{"super":function(){
+if(this.parent){
+var _7=this.parent.nodelist.dummyRender(this.context,null,true);
+if(typeof _7=="string"){
+_7=new String(_7);
+}
+_7.safe=true;
+return _7;
+}
+return "";
+},render:function(_8,_9){
+var _a=this.name;
+var _b=this.nodelist;
+var _c;
+if(_9.blocks){
+var _d=_9.blocks[_a];
+if(_d){
+_c=_d.parent;
+_b=_d.nodelist;
+_d.used=true;
+}
+}
+this.rendered=_b;
+_8=_8.push();
+this.context=_8;
+this.parent=null;
+if(_b!=this.nodelist){
+this.parent=this;
+}
+_8.block=this;
+if(_9.getParent){
+var _e=_9.getParent();
+var _f=_3.connect(_9,"onSetParent",function(_10,up,_11){
+if(up&&_11){
+_9.setParent(_e);
+}
+});
+}
+_9=_b.render(_8,_9,this);
+_f&&_3.disconnect(_f);
+_8=_8.pop();
+return _9;
+},unrender:function(_12,_13){
+return this.rendered.unrender(_12,_13);
+},clone:function(_14){
+return new this.constructor(this.name,this.nodelist.clone(_14));
+},toString:function(){
+return "dojox.dtl.tag.loader.BlockNode";
+}});
+_4.ExtendsNode=_1.extend(function(_15,_16,_17,_18,key){
+this.getTemplate=_15;
+this.nodelist=_16;
+this.shared=_17;
+this.parent=_18;
+this.key=key;
+},{parents:{},getParent:function(_19){
+var _1a=this.parent;
+if(!_1a){
+var _1b;
+_1a=this.parent=_19.get(this.key,false);
+if(!_1a){
+throw new Error("extends tag used a variable that did not resolve");
+}
+if(typeof _1a=="object"){
+var url=_1a.url||_1a.templatePath;
+if(_1a.shared){
+this.shared=true;
+}
+if(url){
+_1a=this.parent=url.toString();
+}else{
+if(_1a.templateString){
+_1b=_1a.templateString;
+_1a=this.parent=" ";
+}else{
+_1a=this.parent=this.parent.toString();
+}
+}
+}
+if(_1a&&_1a.indexOf("shared:")===0){
+this.shared=true;
+_1a=this.parent=_1a.substring(7,_1a.length);
+}
+}
+if(!_1a){
+throw new Error("Invalid template name in 'extends' tag.");
+}
+if(_1a.render){
+return _1a;
+}
+if(this.parents[_1a]){
+return this.parents[_1a];
+}
+this.parent=this.getTemplate(_1b||dojox.dtl.text.getTemplateString(_1a));
+if(this.shared){
+this.parents[_1a]=this.parent;
+}
+return this.parent;
+},render:function(_1c,_1d){
+var _1e=this.getParent(_1c);
+_1e.blocks=_1e.blocks||{};
+_1d.blocks=_1d.blocks||{};
+for(var i=0,_1f;_1f=this.nodelist.contents[i];i++){
+if(_1f instanceof dojox.dtl.tag.loader.BlockNode){
+var old=_1e.blocks[_1f.name];
+if(old&&old.nodelist!=_1f.nodelist){
+_1d=old.nodelist.unrender(_1c,_1d);
+}
+_1e.blocks[_1f.name]=_1d.blocks[_1f.name]={shared:this.shared,nodelist:_1f.nodelist,used:false};
+}
+}
+this.rendered=_1e;
+return _1e.nodelist.render(_1c,_1d,this);
+},unrender:function(_20,_21){
+return this.rendered.unrender(_20,_21,this);
+},toString:function(){
+return "dojox.dtl.block.ExtendsNode";
+}});
+_4.IncludeNode=_1.extend(function(_22,_23,_24,_25,_26){
+this._path=_22;
+this.constant=_23;
+this.path=(_23)?_22:new dd._Filter(_22);
+this.getTemplate=_24;
+this.text=_25;
+this.parsed=(arguments.length==5)?_26:true;
+},{_cache:[{},{}],render:function(_27,_28){
+var _29=((this.constant)?this.path:this.path.resolve(_27)).toString();
+var _2a=Number(this.parsed);
+var _2b=false;
+if(_29!=this.last){
+_2b=true;
+if(this.last){
+_28=this.unrender(_27,_28);
+}
+this.last=_29;
+}
+var _2c=this._cache[_2a];
+if(_2a){
+if(!_2c[_29]){
+_2c[_29]=dd.text._resolveTemplateArg(_29,true);
+}
+if(_2b){
+var _2d=this.getTemplate(_2c[_29]);
+this.rendered=_2d.nodelist;
+}
+return this.rendered.render(_27,_28,this);
+}else{
+if(this.text instanceof dd._TextNode){
+if(_2b){
+this.rendered=this.text;
+this.rendered.set(dd.text._resolveTemplateArg(_29,true));
+}
+return this.rendered.render(_27,_28);
+}else{
+if(!_2c[_29]){
+var _2e=[];
+var div=document.createElement("div");
+div.innerHTML=dd.text._resolveTemplateArg(_29,true);
+var _2f=div.childNodes;
+while(_2f.length){
+var _30=div.removeChild(_2f[0]);
+_2e.push(_30);
+}
+_2c[_29]=_2e;
+}
+if(_2b){
+this.nodelist=[];
+var _31=true;
+for(var i=0,_32;_32=_2c[_29][i];i++){
+this.nodelist.push(_32.cloneNode(true));
+}
+}
+for(var i=0,_33;_33=this.nodelist[i];i++){
+_28=_28.concat(_33);
+}
+}
+}
+return _28;
+},unrender:function(_34,_35){
+if(this.rendered){
+_35=this.rendered.unrender(_34,_35);
+}
+if(this.nodelist){
+for(var i=0,_36;_36=this.nodelist[i];i++){
+_35=_35.remove(_36);
+}
+}
+return _35;
+},clone:function(_37){
+return new this.constructor(this._path,this.constant,this.getTemplate,this.text.clone(_37),this.parsed);
+}});
+_1.mixin(_4,{block:function(_38,_39){
+var _3a=_39.contents.split();
+var _3b=_3a[1];
+_38._blocks=_38._blocks||{};
+_38._blocks[_3b]=_38._blocks[_3b]||[];
+_38._blocks[_3b].push(_3b);
+var _3c=_38.parse(["endblock","endblock "+_3b]).rtrim();
+_38.next_token();
+return new dojox.dtl.tag.loader.BlockNode(_3b,_3c);
+},extends_:function(_3d,_3e){
+var _3f=_3e.contents.split();
+var _40=false;
+var _41=null;
+var key=null;
+if(_3f[1].charAt(0)=="\""||_3f[1].charAt(0)=="'"){
+_41=_3f[1].substring(1,_3f[1].length-1);
+}else{
+key=_3f[1];
+}
+if(_41&&_41.indexOf("shared:")==0){
+_40=true;
+_41=_41.substring(7,_41.length);
+}
+var _42=_3d.parse();
+return new dojox.dtl.tag.loader.ExtendsNode(_3d.getTemplate,_42,_40,_41,key);
+},include:function(_43,_44){
+var _45=_44.contents.split();
+if(_45.length!=2){
+throw new Error(_45[0]+" tag takes one argument: the name of the template to be included");
+}
+var _46=_45[1];
+var _47=false;
+if((_46.charAt(0)=="\""||_46.slice(-1)=="'")&&_46.charAt(0)==_46.slice(-1)){
+_46=_46.slice(1,-1);
+_47=true;
+}
+return new _4.IncludeNode(_46,_47,_43.getTemplate,_43.create_text_node());
+},ssi:function(_48,_49){
+var _4a=_49.contents.split();
+var _4b=false;
+if(_4a.length==3){
+_4b=(_4a.pop()=="parsed");
+if(!_4b){
+throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
+}
+}
+var _4c=_4.include(_48,new dd.Token(_49.token_type,_4a.join(" ")));
+_4c.parsed=_4b;
+return _4c;
+}});
+return dojox.dtl.tag.loader;
+});
diff --git a/js/libs/dojox/dtl/tag/loader.js.uncompressed.js b/js/libs/dojox/dtl/tag/loader.js.uncompressed.js
new file mode 100644
index 0000000..6bd68d1
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/loader.js.uncompressed.js
@@ -0,0 +1,304 @@
+//>>built
+define("dojox/dtl/tag/loader", [
+ "dojo/_base/lang",
+ "../_base",
+ "dojo/_base/array",
+ "dojo/_base/connect"
+], function(lang,dd,array,connect){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loader", true);
+
+ var ddtl = dd.tag.loader;
+
+ ddtl.BlockNode = lang.extend(function(name, nodelist){
+ this.name = name;
+ this.nodelist = nodelist; // Can be overridden
+ },
+ {
+ "super": function(){
+ if(this.parent){
+ var html = this.parent.nodelist.dummyRender(this.context, null, true);
+ if(typeof html == "string"){
+ html = new String(html);
+ }
+ html.safe = true;
+ return html;
+ }
+ return '';
+ },
+ render: function(context, buffer){
+ var name = this.name;
+ var nodelist = this.nodelist;
+ var parent;
+ if(buffer.blocks){
+ var block = buffer.blocks[name];
+ if(block){
+ parent = block.parent;
+ nodelist = block.nodelist;
+ block.used = true;
+ }
+ }
+
+ this.rendered = nodelist;
+
+ context = context.push();
+ this.context = context;
+ this.parent = null;
+ if(nodelist != this.nodelist){
+ this.parent = this;
+ }
+ context.block = this;
+
+ if(buffer.getParent){
+ var bufferParent = buffer.getParent();
+ var setParent = connect.connect(buffer, "onSetParent", function(node, up, root){
+ if(up && root){
+ buffer.setParent(bufferParent);
+ }
+ });
+ }
+ buffer = nodelist.render(context, buffer, this);
+ setParent && connect.disconnect(setParent);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.name, this.nodelist.clone(buffer));
+ },
+ toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
+ });
+
+ ddtl.ExtendsNode = lang.extend(function(getTemplate, nodelist, shared, parent, key){
+ this.getTemplate = getTemplate;
+ this.nodelist = nodelist;
+ this.shared = shared;
+ this.parent = parent;
+ this.key = key;
+ },
+ {
+ parents: {},
+ getParent: function(context){
+ var parent = this.parent;
+ if(!parent){
+ var string;
+ parent = this.parent = context.get(this.key, false);
+ if(!parent){
+ throw new Error("extends tag used a variable that did not resolve");
+ }
+ if(typeof parent == "object"){
+ var url = parent.url || parent.templatePath;
+ if(parent.shared){
+ this.shared = true;
+ }
+ if(url){
+ parent = this.parent = url.toString();
+ }else if(parent.templateString){
+ // Allow the builder's string interning to work
+ string = parent.templateString;
+ parent = this.parent = " ";
+ }else{
+ parent = this.parent = this.parent.toString();
+ }
+ }
+ if(parent && parent.indexOf("shared:") === 0){
+ this.shared = true;
+ parent = this.parent = parent.substring(7, parent.length);
+ }
+ }
+ if(!parent){
+ throw new Error("Invalid template name in 'extends' tag.");
+ }
+ if(parent.render){
+ return parent;
+ }
+ if(this.parents[parent]){
+ return this.parents[parent];
+ }
+ this.parent = this.getTemplate(string || dojox.dtl.text.getTemplateString(parent));
+ if(this.shared){
+ this.parents[parent] = this.parent;
+ }
+ return this.parent;
+ },
+ render: function(context, buffer){
+ var parent = this.getParent(context);
+
+ parent.blocks = parent.blocks || {};
+ buffer.blocks = buffer.blocks || {};
+
+ for(var i = 0, node; node = this.nodelist.contents[i]; i++){
+ if(node instanceof dojox.dtl.tag.loader.BlockNode){
+ var old = parent.blocks[node.name];
+ if(old && old.nodelist != node.nodelist){
+ // In a shared template, the individual blocks might change
+ buffer = old.nodelist.unrender(context, buffer);
+ }
+ parent.blocks[node.name] = buffer.blocks[node.name] = {
+ shared: this.shared,
+ nodelist: node.nodelist,
+ used: false
+ }
+ }
+ }
+
+ this.rendered = parent;
+ return parent.nodelist.render(context, buffer, this);
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer, this);
+ },
+ toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
+ });
+
+ ddtl.IncludeNode = lang.extend(function(path, constant, getTemplate, text, parsed){
+ this._path = path;
+ this.constant = constant;
+ this.path = (constant) ? path : new dd._Filter(path);
+ this.getTemplate = getTemplate;
+ this.text = text;
+ this.parsed = (arguments.length == 5) ? parsed : true;
+ },
+ {
+ _cache: [{}, {}],
+ render: function(context, buffer){
+ var location = ((this.constant) ? this.path : this.path.resolve(context)).toString();
+ var parsed = Number(this.parsed);
+ var dirty = false;
+ if(location != this.last){
+ dirty = true;
+ if(this.last){
+ buffer = this.unrender(context, buffer);
+ }
+ this.last = location;
+ }
+
+ var cache = this._cache[parsed];
+
+ if(parsed){
+ if(!cache[location]){
+ cache[location] = dd.text._resolveTemplateArg(location, true);
+ }
+ if(dirty){
+ var template = this.getTemplate(cache[location]);
+ this.rendered = template.nodelist;
+ }
+ return this.rendered.render(context, buffer, this);
+ }else{
+ if(this.text instanceof dd._TextNode){
+ if(dirty){
+ this.rendered = this.text;
+ this.rendered.set(dd.text._resolveTemplateArg(location, true));
+ }
+ return this.rendered.render(context, buffer);
+ }else{
+ if(!cache[location]){
+ var nodelist = [];
+ var div = document.createElement("div");
+ div.innerHTML = dd.text._resolveTemplateArg(location, true);
+ var children = div.childNodes;
+ while(children.length){
+ var removed = div.removeChild(children[0]);
+ nodelist.push(removed);
+ }
+ cache[location] = nodelist;
+ }
+ if(dirty){
+ this.nodelist = [];
+ var exists = true;
+ for(var i = 0, child; child = cache[location][i]; i++){
+ this.nodelist.push(child.cloneNode(true));
+ }
+ }
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.concat(node);
+ }
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ if(this.rendered){
+ buffer = this.rendered.unrender(context, buffer);
+ }
+ if(this.nodelist){
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.remove(node);
+ }
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._path, this.constant, this.getTemplate, this.text.clone(buffer), this.parsed);
+ }
+ });
+
+ lang.mixin(ddtl, {
+ block: function(parser, token){
+ var parts = token.contents.split();
+ var name = parts[1];
+
+ parser._blocks = parser._blocks || {};
+ parser._blocks[name] = parser._blocks[name] || [];
+ parser._blocks[name].push(name);
+
+ var nodelist = parser.parse(["endblock", "endblock " + name]).rtrim();
+ parser.next_token();
+ return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
+ },
+ extends_: function(parser, token){
+ var parts = token.contents.split();
+ var shared = false;
+ var parent = null;
+ var key = null;
+ if(parts[1].charAt(0) == '"' || parts[1].charAt(0) == "'"){
+ parent = parts[1].substring(1, parts[1].length - 1);
+ }else{
+ key = parts[1];
+ }
+ if(parent && parent.indexOf("shared:") == 0){
+ shared = true;
+ parent = parent.substring(7, parent.length);
+ }
+ var nodelist = parser.parse();
+ return new dojox.dtl.tag.loader.ExtendsNode(parser.getTemplate, nodelist, shared, parent, key);
+ },
+ include: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error(parts[0] + " tag takes one argument: the name of the template to be included");
+ }
+ var path = parts[1];
+ var constant = false;
+ if((path.charAt(0) == '"' || path.slice(-1) == "'") && path.charAt(0) == path.slice(-1)){
+ path = path.slice(1, -1);
+ constant = true;
+ }
+ return new ddtl.IncludeNode(path, constant, parser.getTemplate, parser.create_text_node());
+ },
+ ssi: function(parser, token){
+ // We're going to treat things a little differently here.
+ // First of all, this tag is *not* portable, so I'm not
+ // concerned about it being a "drop in" replacement.
+
+ // Instead, we'll just replicate the include tag, but with that
+ // optional "parsed" parameter.
+ var parts = token.contents.split();
+ var parsed = false;
+ if(parts.length == 3){
+ parsed = (parts.pop() == "parsed");
+ if(!parsed){
+ throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
+ }
+ }
+ var node = ddtl.include(parser, new dd.Token(token.token_type, parts.join(" ")));
+ node.parsed = parsed;
+ return node;
+ }
+ });
+ return dojox.dtl.tag.loader;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/tag/logic.js b/js/libs/dojox/dtl/tag/logic.js
new file mode 100644
index 0000000..0c53d4f
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/logic.js
@@ -0,0 +1,237 @@
+//>>built
+define("dojox/dtl/tag/logic",["dojo/_base/lang","../_base"],function(_1,dd){
+_1.getObject("dojox.dtl.tag.logic",true);
+var _2=dd.text;
+var _3=dd.tag.logic;
+_3.IfNode=_1.extend(function(_4,_5,_6,_7){
+this.bools=_4;
+this.trues=_5;
+this.falses=_6;
+this.type=_7;
+},{render:function(_8,_9){
+var i,_a,_b,_c,_d;
+if(this.type=="or"){
+for(i=0;_a=this.bools[i];i++){
+_b=_a[0];
+_c=_a[1];
+_d=_c.resolve(_8);
+if((_d&&!_b)||(_b&&!_d)){
+if(this.falses){
+_9=this.falses.unrender(_8,_9);
+}
+return (this.trues)?this.trues.render(_8,_9,this):_9;
+}
+}
+if(this.trues){
+_9=this.trues.unrender(_8,_9);
+}
+return (this.falses)?this.falses.render(_8,_9,this):_9;
+}else{
+for(i=0;_a=this.bools[i];i++){
+_b=_a[0];
+_c=_a[1];
+_d=_c.resolve(_8);
+if(_d==_b){
+if(this.trues){
+_9=this.trues.unrender(_8,_9);
+}
+return (this.falses)?this.falses.render(_8,_9,this):_9;
+}
+}
+if(this.falses){
+_9=this.falses.unrender(_8,_9);
+}
+return (this.trues)?this.trues.render(_8,_9,this):_9;
+}
+return _9;
+},unrender:function(_e,_f){
+_f=(this.trues)?this.trues.unrender(_e,_f):_f;
+_f=(this.falses)?this.falses.unrender(_e,_f):_f;
+return _f;
+},clone:function(_10){
+var _11=(this.trues)?this.trues.clone(_10):null;
+var _12=(this.falses)?this.falses.clone(_10):null;
+return new this.constructor(this.bools,_11,_12,this.type);
+}});
+_3.IfEqualNode=_1.extend(function(_13,_14,_15,_16,_17){
+this.var1=new dd._Filter(_13);
+this.var2=new dd._Filter(_14);
+this.trues=_15;
+this.falses=_16;
+this.negate=_17;
+},{render:function(_18,_19){
+var _1a=this.var1.resolve(_18);
+var _1b=this.var2.resolve(_18);
+_1a=(typeof _1a!="undefined")?_1a:"";
+_1b=(typeof _1a!="undefined")?_1b:"";
+if((this.negate&&_1a!=_1b)||(!this.negate&&_1a==_1b)){
+if(this.falses){
+_19=this.falses.unrender(_18,_19,this);
+}
+return (this.trues)?this.trues.render(_18,_19,this):_19;
+}
+if(this.trues){
+_19=this.trues.unrender(_18,_19,this);
+}
+return (this.falses)?this.falses.render(_18,_19,this):_19;
+},unrender:function(_1c,_1d){
+return _3.IfNode.prototype.unrender.call(this,_1c,_1d);
+},clone:function(_1e){
+var _1f=this.trues?this.trues.clone(_1e):null;
+var _20=this.falses?this.falses.clone(_1e):null;
+return new this.constructor(this.var1.getExpression(),this.var2.getExpression(),_1f,_20,this.negate);
+}});
+_3.ForNode=_1.extend(function(_21,_22,_23,_24){
+this.assign=_21;
+this.loop=new dd._Filter(_22);
+this.reversed=_23;
+this.nodelist=_24;
+this.pool=[];
+},{render:function(_25,_26){
+var i,j,k;
+var _27=false;
+var _28=this.assign;
+for(k=0;k<_28.length;k++){
+if(typeof _25[_28[k]]!="undefined"){
+_27=true;
+_25=_25.push();
+break;
+}
+}
+if(!_27&&_25.forloop){
+_27=true;
+_25=_25.push();
+}
+var _29=this.loop.resolve(_25)||[];
+for(i=_29.length;i1&&_1.isArrayLike(_2d)){
+if(!_27){
+_27=true;
+_25=_25.push();
+}
+var _2e={};
+for(k=0;k<_2d.length&&k<_28.length;k++){
+_2e[_28[k]]=_2d[k];
+}
+_1.mixin(_25,_2e);
+}else{
+_25[_28[0]]=_2d;
+}
+if(j+1>this.pool.length){
+this.pool.push(this.nodelist.clone(_26));
+}
+_26=this.pool[j++].render(_25,_26,this);
+}
+delete _25.forloop;
+if(_27){
+_25=_25.pop();
+}else{
+for(k=0;k<_28.length;k++){
+delete _25[_28[k]];
+}
+}
+return _26;
+},unrender:function(_2f,_30){
+for(var i=0,_31;_31=this.pool[i];i++){
+_30=_31.unrender(_2f,_30);
+}
+return _30;
+},clone:function(_32){
+return new this.constructor(this.assign,this.loop.getExpression(),this.reversed,this.nodelist.clone(_32));
+}});
+_1.mixin(_3,{if_:function(_33,_34){
+var i,_35,_36,_37=[],_38=_34.contents.split();
+_38.shift();
+_34=_38.join(" ");
+_38=_34.split(" and ");
+if(_38.length==1){
+_36="or";
+_38=_34.split(" or ");
+}else{
+_36="and";
+for(i=0;i<_38.length;i++){
+if(_38[i].indexOf(" or ")!=-1){
+throw new Error("'if' tags can't mix 'and' and 'or'");
+}
+}
+}
+for(i=0;_35=_38[i];i++){
+var not=false;
+if(_35.indexOf("not ")==0){
+_35=_35.slice(4);
+not=true;
+}
+_37.push([not,new dd._Filter(_35)]);
+}
+var _39=_33.parse(["else","endif"]);
+var _3a=false;
+var _34=_33.next_token();
+if(_34.contents=="else"){
+_3a=_33.parse(["endif"]);
+_33.next_token();
+}
+return new _3.IfNode(_37,_39,_3a,_36);
+},_ifequal:function(_3b,_3c,_3d){
+var _3e=_3c.split_contents();
+if(_3e.length!=3){
+throw new Error(_3e[0]+" takes two arguments");
+}
+var end="end"+_3e[0];
+var _3f=_3b.parse(["else",end]);
+var _40=false;
+var _3c=_3b.next_token();
+if(_3c.contents=="else"){
+_40=_3b.parse([end]);
+_3b.next_token();
+}
+return new _3.IfEqualNode(_3e[1],_3e[2],_3f,_40,_3d);
+},ifequal:function(_41,_42){
+return _3._ifequal(_41,_42);
+},ifnotequal:function(_43,_44){
+return _3._ifequal(_43,_44,true);
+},for_:function(_45,_46){
+var _47=_46.contents.split();
+if(_47.length<4){
+throw new Error("'for' statements should have at least four words: "+_46.contents);
+}
+var _48=_47[_47.length-1]=="reversed";
+var _49=(_48)?-3:-2;
+if(_47[_47.length+_49]!="in"){
+throw new Error("'for' tag received an invalid argument: "+_46.contents);
+}
+var _4a=_47.slice(1,_49).join(" ").split(/ *, */);
+for(var i=0;i<_4a.length;i++){
+if(!_4a[i]||_4a[i].indexOf(" ")!=-1){
+throw new Error("'for' tag received an invalid argument: "+_46.contents);
+}
+}
+var _4b=_45.parse(["endfor"]);
+_45.next_token();
+return new _3.ForNode(_4a,_47[_47.length+_49+1],_48,_4b);
+}});
+return dojox.dtl.tag.logic;
+});
diff --git a/js/libs/dojox/dtl/tag/logic.js.uncompressed.js b/js/libs/dojox/dtl/tag/logic.js.uncompressed.js
new file mode 100644
index 0000000..3f84d25
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/logic.js.uncompressed.js
@@ -0,0 +1,281 @@
+//>>built
+define("dojox/dtl/tag/logic", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang, dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.logic", true);
+
+ var ddt = dd.text;
+ var ddtl = dd.tag.logic;
+
+ ddtl.IfNode = lang.extend(function(bools, trues, falses, type){
+ this.bools = bools;
+ this.trues = trues;
+ this.falses = falses;
+ this.type = type;
+ },
+ {
+ render: function(context, buffer){
+ var i, bool, ifnot, filter, value;
+ if(this.type == "or"){
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ if((value && !ifnot) || (ifnot && !value)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }else{
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ // If we ever encounter a false value
+ if(value == ifnot){
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ buffer = (this.trues) ? this.trues.unrender(context, buffer) : buffer;
+ buffer = (this.falses) ? this.falses.unrender(context, buffer) : buffer;
+ return buffer;
+ },
+ clone: function(buffer){
+ var trues = (this.trues) ? this.trues.clone(buffer) : null;
+ var falses = (this.falses) ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.bools, trues, falses, this.type);
+ }
+ });
+
+ ddtl.IfEqualNode = lang.extend(function(var1, var2, trues, falses, negate){
+ this.var1 = new dd._Filter(var1);
+ this.var2 = new dd._Filter(var2);
+ this.trues = trues;
+ this.falses = falses;
+ this.negate = negate;
+ },
+ {
+ render: function(context, buffer){
+ var var1 = this.var1.resolve(context);
+ var var2 = this.var2.resolve(context);
+ var1 = (typeof var1 != "undefined") ? var1 : "";
+ var2 = (typeof var1 != "undefined") ? var2 : "";
+ if((this.negate && var1 != var2) || (!this.negate && var1 == var2)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer, this);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer, this);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ },
+ unrender: function(context, buffer){
+ return ddtl.IfNode.prototype.unrender.call(this, context, buffer);
+ },
+ clone: function(buffer){
+ var trues = this.trues ? this.trues.clone(buffer) : null;
+ var falses = this.falses ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.var1.getExpression(), this.var2.getExpression(), trues, falses, this.negate);
+ }
+ });
+
+ ddtl.ForNode = lang.extend(function(assign, loop, reversed, nodelist){
+ this.assign = assign;
+ this.loop = new dd._Filter(loop);
+ this.reversed = reversed;
+ this.nodelist = nodelist;
+ this.pool = [];
+ },
+ {
+ render: function(context, buffer){
+ var i, j, k;
+ var dirty = false;
+ var assign = this.assign;
+
+ for(k = 0; k < assign.length; k++){
+ if(typeof context[assign[k]] != "undefined"){
+ dirty = true;
+ context = context.push();
+ break;
+ }
+ }
+ if(!dirty && context.forloop){
+ dirty = true;
+ context = context.push();
+ }
+
+ var items = this.loop.resolve(context) || [];
+ for(i = items.length; i < this.pool.length; i++){
+ this.pool[i].unrender(context, buffer, this);
+ }
+ if(this.reversed){
+ items = items.slice(0).reverse();
+ }
+
+ var isObject = lang.isObject(items) && !lang.isArrayLike(items);
+ var arred = [];
+ if(isObject){
+ for(var key in items){
+ arred.push(items[key]);
+ }
+ }else{
+ arred = items;
+ }
+
+ var forloop = context.forloop = {
+ parentloop: context.get("forloop", {})
+ };
+ var j = 0;
+ for(i = 0; i < arred.length; i++){
+ var item = arred[i];
+
+ forloop.counter0 = j;
+ forloop.counter = j + 1;
+ forloop.revcounter0 = arred.length - j - 1;
+ forloop.revcounter = arred.length - j;
+ forloop.first = !j;
+ forloop.last = (j == arred.length - 1);
+
+ if(assign.length > 1 && lang.isArrayLike(item)){
+ if(!dirty){
+ dirty = true;
+ context = context.push();
+ }
+ var zipped = {};
+ for(k = 0; k < item.length && k < assign.length; k++){
+ zipped[assign[k]] = item[k];
+ }
+ lang.mixin(context, zipped);
+ }else{
+ context[assign[0]] = item;
+ }
+
+ if(j + 1 > this.pool.length){
+ this.pool.push(this.nodelist.clone(buffer));
+ }
+ buffer = this.pool[j++].render(context, buffer, this);
+ }
+
+ delete context.forloop;
+ if(dirty){
+ context = context.pop();
+ }else{
+ for(k = 0; k < assign.length; k++){
+ delete context[assign[k]];
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ for(var i = 0, pool; pool = this.pool[i]; i++){
+ buffer = pool.unrender(context, buffer);
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.assign, this.loop.getExpression(), this.reversed, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtl, {
+ if_: function(parser, token){
+ var i, part, type, bools = [], parts = token.contents.split();
+ parts.shift();
+ token = parts.join(" ");
+ parts = token.split(" and ");
+ if(parts.length == 1){
+ type = "or";
+ parts = token.split(" or ");
+ }else{
+ type = "and";
+ for(i = 0; i < parts.length; i++){
+ if(parts[i].indexOf(" or ") != -1){
+ // Note, since we split by and, this is the only place we need to error check
+ throw new Error("'if' tags can't mix 'and' and 'or'");
+ }
+ }
+ }
+ for(i = 0; part = parts[i]; i++){
+ var not = false;
+ if(part.indexOf("not ") == 0){
+ part = part.slice(4);
+ not = true;
+ }
+ bools.push([not, new dd._Filter(part)]);
+ }
+ var trues = parser.parse(["else", "endif"]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse(["endif"]);
+ parser.next_token();
+ }
+ return new ddtl.IfNode(bools, trues, falses, type);
+ },
+ _ifequal: function(parser, token, negate){
+ var parts = token.split_contents();
+ if(parts.length != 3){
+ throw new Error(parts[0] + " takes two arguments");
+ }
+ var end = 'end' + parts[0];
+ var trues = parser.parse(["else", end]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse([end]);
+ parser.next_token();
+ }
+ return new ddtl.IfEqualNode(parts[1], parts[2], trues, falses, negate);
+ },
+ ifequal: function(parser, token){
+ return ddtl._ifequal(parser, token);
+ },
+ ifnotequal: function(parser, token){
+ return ddtl._ifequal(parser, token, true);
+ },
+ for_: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length < 4){
+ throw new Error("'for' statements should have at least four words: " + token.contents);
+ }
+ var reversed = parts[parts.length - 1] == "reversed";
+ var index = (reversed) ? -3 : -2;
+ if(parts[parts.length + index] != "in"){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ var loopvars = parts.slice(1, index).join(" ").split(/ *, */);
+ for(var i = 0; i < loopvars.length; i++){
+ if(!loopvars[i] || loopvars[i].indexOf(" ") != -1){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ }
+ var nodelist = parser.parse(["endfor"]);
+ parser.next_token();
+ return new ddtl.ForNode(loopvars, parts[parts.length + index + 1], reversed, nodelist);
+ }
+ });
+ return dojox.dtl.tag.logic;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/tag/loop.js b/js/libs/dojox/dtl/tag/loop.js
new file mode 100644
index 0000000..29bf688
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/loop.js
@@ -0,0 +1,153 @@
+//>>built
+define("dojox/dtl/tag/loop",["dojo/_base/lang","dojo/_base/array","dojo/_base/json","../_base","dojox/string/tokenize"],function(_1,_2,_3,dd,_4){
+_1.getObject("dojox.dtl.tag.loop",true);
+var _5=dd.tag.loop;
+_5.CycleNode=_1.extend(function(_6,_7,_8,_9){
+this.cyclevars=_6;
+this.name=_7;
+this.contents=_8;
+this.shared=_9||{counter:-1,map:{}};
+},{render:function(_a,_b){
+if(_a.forloop&&!_a.forloop.counter0){
+this.shared.counter=-1;
+}
+++this.shared.counter;
+var _c=this.cyclevars[this.shared.counter%this.cyclevars.length];
+var _d=this.shared.map;
+if(!_d[_c]){
+_d[_c]=new dd._Filter(_c);
+}
+_c=_d[_c].resolve(_a,_b);
+if(this.name){
+_a[this.name]=_c;
+}
+this.contents.set(_c);
+return this.contents.render(_a,_b);
+},unrender:function(_e,_f){
+return this.contents.unrender(_e,_f);
+},clone:function(_10){
+return new this.constructor(this.cyclevars,this.name,this.contents.clone(_10),this.shared);
+}});
+_5.IfChangedNode=_1.extend(function(_11,_12,_13){
+this.nodes=_11;
+this._vars=_12;
+this.shared=_13||{last:null,counter:0};
+this.vars=_2.map(_12,function(_14){
+return new dojox.dtl._Filter(_14);
+});
+},{render:function(_15,_16){
+if(_15.forloop){
+if(_15.forloop.counter<=this.shared.counter){
+this.shared.last=null;
+}
+this.shared.counter=_15.forloop.counter;
+}
+var _17;
+if(this.vars.length){
+_17=_3.toJson(_2.map(this.vars,function(_18){
+return _18.resolve(_15);
+}));
+}else{
+_17=this.nodes.dummyRender(_15,_16);
+}
+if(_17!=this.shared.last){
+var _19=(this.shared.last===null);
+this.shared.last=_17;
+_15=_15.push();
+_15.ifchanged={firstloop:_19};
+_16=this.nodes.render(_15,_16);
+_15=_15.pop();
+}else{
+_16=this.nodes.unrender(_15,_16);
+}
+return _16;
+},unrender:function(_1a,_1b){
+return this.nodes.unrender(_1a,_1b);
+},clone:function(_1c){
+return new this.constructor(this.nodes.clone(_1c),this._vars,this.shared);
+}});
+_5.RegroupNode=_1.extend(function(_1d,key,_1e){
+this._expression=_1d;
+this.expression=new dd._Filter(_1d);
+this.key=key;
+this.alias=_1e;
+},{_push:function(_1f,_20,_21){
+if(_21.length){
+_1f.push({grouper:_20,list:_21});
+}
+},render:function(_22,_23){
+_22[this.alias]=[];
+var _24=this.expression.resolve(_22);
+if(_24){
+var _25=null;
+var _26=[];
+for(var i=0;i<_24.length;i++){
+var id=_24[i][this.key];
+if(_25!==id){
+this._push(_22[this.alias],_25,_26);
+_25=id;
+_26=[_24[i]];
+}else{
+_26.push(_24[i]);
+}
+}
+this._push(_22[this.alias],_25,_26);
+}
+return _23;
+},unrender:function(_27,_28){
+return _28;
+},clone:function(_29,_2a){
+return this;
+}});
+_1.mixin(_5,{cycle:function(_2b,_2c){
+var _2d=_2c.split_contents();
+if(_2d.length<2){
+throw new Error("'cycle' tag requires at least two arguments");
+}
+if(_2d[1].indexOf(",")!=-1){
+var _2e=_2d[1].split(",");
+_2d=[_2d[0]];
+for(var i=0;i<_2e.length;i++){
+_2d.push("\""+_2e[i]+"\"");
+}
+}
+if(_2d.length==2){
+var _2f=_2d[_2d.length-1];
+if(!_2b._namedCycleNodes){
+throw new Error("No named cycles in template: '"+_2f+"' is not defined");
+}
+if(!_2b._namedCycleNodes[_2f]){
+throw new Error("Named cycle '"+_2f+"' does not exist");
+}
+return _2b._namedCycleNodes[_2f];
+}
+if(_2d.length>4&&_2d[_2d.length-2]=="as"){
+var _2f=_2d[_2d.length-1];
+var _30=new _5.CycleNode(_2d.slice(1,_2d.length-2),_2f,_2b.create_text_node());
+if(!_2b._namedCycleNodes){
+_2b._namedCycleNodes={};
+}
+_2b._namedCycleNodes[_2f]=_30;
+}else{
+_30=new _5.CycleNode(_2d.slice(1),null,_2b.create_text_node());
+}
+return _30;
+},ifchanged:function(_31,_32){
+var _33=_32.contents.split();
+var _34=_31.parse(["endifchanged"]);
+_31.delete_first_token();
+return new _5.IfChangedNode(_34,_33.slice(1));
+},regroup:function(_35,_36){
+var _37=_4(_36.contents,/(\s+)/g,function(_38){
+return _38;
+});
+if(_37.length<11||_37[_37.length-3]!="as"||_37[_37.length-7]!="by"){
+throw new Error("Expected the format: regroup list by key as newList");
+}
+var _39=_37.slice(2,-8).join("");
+var key=_37[_37.length-5];
+var _3a=_37[_37.length-1];
+return new _5.RegroupNode(_39,key,_3a);
+}});
+return dojox.dtl.tag.loop;
+});
diff --git a/js/libs/dojox/dtl/tag/loop.js.uncompressed.js b/js/libs/dojox/dtl/tag/loop.js.uncompressed.js
new file mode 100644
index 0000000..b8742ae
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/loop.js.uncompressed.js
@@ -0,0 +1,202 @@
+//>>built
+define("dojox/dtl/tag/loop", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojo/_base/json",
+ "../_base",
+ "dojox/string/tokenize"
+], function(lang,array,json,dd,Tokenize){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loop", true);
+
+ var ddtl = dd.tag.loop;
+
+ ddtl.CycleNode = lang.extend(function(cyclevars, name, text, shared){
+ this.cyclevars = cyclevars;
+ this.name = name;
+ this.contents = text;
+ this.shared = shared || {counter: -1, map: {}};
+ },
+ {
+ render: function(context, buffer){
+ if(context.forloop && !context.forloop.counter0){
+ this.shared.counter = -1;
+ }
+
+ ++this.shared.counter;
+ var value = this.cyclevars[this.shared.counter % this.cyclevars.length];
+
+ var map = this.shared.map;
+ if(!map[value]){
+ map[value] = new dd._Filter(value);
+ }
+ value = map[value].resolve(context, buffer);
+
+ if(this.name){
+ context[this.name] = value;
+ }
+ this.contents.set(value);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.cyclevars, this.name, this.contents.clone(buffer), this.shared);
+ }
+ });
+
+ ddtl.IfChangedNode = lang.extend(function(nodes, vars, shared){
+ this.nodes = nodes;
+ this._vars = vars;
+ this.shared = shared || {last: null, counter: 0};
+ this.vars = array.map(vars, function(item){
+ return new dojox.dtl._Filter(item);
+ });
+ }, {
+ render: function(context, buffer){
+ if(context.forloop){
+ if(context.forloop.counter <= this.shared.counter){
+ this.shared.last = null;
+ }
+ this.shared.counter = context.forloop.counter;
+ }
+
+ var change;
+ if(this.vars.length){
+ change = json.toJson(array.map(this.vars, function(item){
+ return item.resolve(context);
+ }));
+ }else{
+ change = this.nodes.dummyRender(context, buffer);
+ }
+
+ if(change != this.shared.last){
+ var firstloop = (this.shared.last === null);
+ this.shared.last = change;
+ context = context.push();
+ context.ifchanged = {firstloop: firstloop};
+ buffer = this.nodes.render(context, buffer);
+ context = context.pop();
+ }else{
+ buffer = this.nodes.unrender(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodes.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodes.clone(buffer), this._vars, this.shared);
+ }
+ });
+
+ ddtl.RegroupNode = lang.extend(function(expression, key, alias){
+ this._expression = expression;
+ this.expression = new dd._Filter(expression);
+ this.key = key;
+ this.alias = alias;
+ },
+ {
+ _push: function(container, grouper, stack){
+ if(stack.length){
+ container.push({ grouper: grouper, list: stack });
+ }
+ },
+ render: function(context, buffer){
+ context[this.alias] = [];
+ var list = this.expression.resolve(context);
+ if(list){
+ var last = null;
+ var stack = [];
+ for(var i = 0; i < list.length; i++){
+ var id = list[i][this.key];
+ if(last !== id){
+ this._push(context[this.alias], last, stack);
+ last = id;
+ stack = [list[i]];
+ }else{
+ stack.push(list[i]);
+ }
+ }
+ this._push(context[this.alias], last, stack);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(context, buffer){
+ return this;
+ }
+ });
+
+ lang.mixin(ddtl, {
+ cycle: function(parser, token){
+ // summary: Cycle among the given strings each time this tag is encountered
+ var args = token.split_contents();
+
+ if(args.length < 2){
+ throw new Error("'cycle' tag requires at least two arguments");
+ }
+
+ if(args[1].indexOf(",") != -1){
+ var vars = args[1].split(",");
+ args = [args[0]];
+ for(var i = 0; i < vars.length; i++){
+ args.push('"' + vars[i] + '"');
+ }
+ }
+
+ if(args.length == 2){
+ var name = args[args.length - 1];
+
+ if(!parser._namedCycleNodes){
+ throw new Error("No named cycles in template: '" + name + "' is not defined");
+ }
+ if(!parser._namedCycleNodes[name]){
+ throw new Error("Named cycle '" + name + "' does not exist");
+ }
+
+ return parser._namedCycleNodes[name];
+ }
+
+ if(args.length > 4 && args[args.length - 2] == "as"){
+ var name = args[args.length - 1];
+
+ var node = new ddtl.CycleNode(args.slice(1, args.length - 2), name, parser.create_text_node());
+
+ if(!parser._namedCycleNodes){
+ parser._namedCycleNodes = {};
+ }
+ parser._namedCycleNodes[name] = node;
+ }else{
+ node = new ddtl.CycleNode(args.slice(1), null, parser.create_text_node());
+ }
+
+ return node;
+ },
+ ifchanged: function(parser, token){
+ var parts = token.contents.split();
+ var nodes = parser.parse(["endifchanged"]);
+ parser.delete_first_token();
+ return new ddtl.IfChangedNode(nodes, parts.slice(1));
+ },
+ regroup: function(parser, token){
+ var tokens = Tokenize(token.contents, /(\s+)/g, function(spaces){
+ return spaces;
+ });
+ if(tokens.length < 11 || tokens[tokens.length - 3] != "as" || tokens[tokens.length - 7] != "by"){
+ throw new Error("Expected the format: regroup list by key as newList");
+ }
+ var expression = tokens.slice(2, -8).join("");
+ var key = tokens[tokens.length - 5];
+ var alias = tokens[tokens.length - 1];
+ return new ddtl.RegroupNode(expression, key, alias);
+ }
+ });
+ return dojox.dtl.tag.loop;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/tag/misc.js b/js/libs/dojox/dtl/tag/misc.js
new file mode 100644
index 0000000..0914422
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/misc.js
@@ -0,0 +1,212 @@
+//>>built
+define("dojox/dtl/tag/misc",["dojo/_base/lang","dojo/_base/array","dojo/_base/connect","../_base"],function(_1,_2,_3,dd){
+_1.getObject("dojox.dtl.tag.misc",true);
+var _4=dd.tag.misc;
+_4.DebugNode=_1.extend(function(_5){
+this.text=_5;
+},{render:function(_6,_7){
+var _8=_6.getKeys();
+var _9=[];
+var _a={};
+for(var i=0,_b;_b=_8[i];i++){
+_a[_b]=_6[_b];
+_9+="["+_b+": "+typeof _6[_b]+"]\n";
+}
+return this.text.set(_9).render(_6,_7,this);
+},unrender:function(_c,_d){
+return _d;
+},clone:function(_e){
+return new this.constructor(this.text.clone(_e));
+},toString:function(){
+return "ddtm.DebugNode";
+}});
+_4.FilterNode=_1.extend(function(_f,_10){
+this._varnode=_f;
+this._nodelist=_10;
+},{render:function(_11,_12){
+var _13=this._nodelist.render(_11,new dojox.string.Builder());
+_11=_11.update({"var":_13.toString()});
+var _14=this._varnode.render(_11,_12);
+_11=_11.pop();
+return _12;
+},unrender:function(_15,_16){
+return _16;
+},clone:function(_17){
+return new this.constructor(this._expression,this._nodelist.clone(_17));
+}});
+_4.FirstOfNode=_1.extend(function(_18,_19){
+this._vars=_18;
+this.vars=_2.map(_18,function(_1a){
+return new dojox.dtl._Filter(_1a);
+});
+this.contents=_19;
+},{render:function(_1b,_1c){
+for(var i=0,_1d;_1d=this.vars[i];i++){
+var _1e=_1d.resolve(_1b);
+if(typeof _1e!="undefined"){
+if(_1e===null){
+_1e="null";
+}
+this.contents.set(_1e);
+return this.contents.render(_1b,_1c);
+}
+}
+return this.contents.unrender(_1b,_1c);
+},unrender:function(_1f,_20){
+return this.contents.unrender(_1f,_20);
+},clone:function(_21){
+return new this.constructor(this._vars,this.contents.clone(_21));
+}});
+_4.SpacelessNode=_1.extend(function(_22,_23){
+this.nodelist=_22;
+this.contents=_23;
+},{render:function(_24,_25){
+if(_25.getParent){
+var _26=[_3.connect(_25,"onAddNodeComplete",this,"_watch"),_3.connect(_25,"onSetParent",this,"_watchParent")];
+_25=this.nodelist.render(_24,_25);
+_3.disconnect(_26[0]);
+_3.disconnect(_26[1]);
+}else{
+var _27=this.nodelist.dummyRender(_24);
+this.contents.set(_27.replace(/>\s+<"));
+_25=this.contents.render(_24,_25);
+}
+return _25;
+},unrender:function(_28,_29){
+return this.nodelist.unrender(_28,_29);
+},clone:function(_2a){
+return new this.constructor(this.nodelist.clone(_2a),this.contents.clone(_2a));
+},_isEmpty:function(_2b){
+return (_2b.nodeType==3&&!_2b.data.match(/[^\s\n]/));
+},_watch:function(_2c){
+if(this._isEmpty(_2c)){
+var _2d=false;
+if(_2c.parentNode.firstChild==_2c){
+_2c.parentNode.removeChild(_2c);
+}
+}else{
+var _2e=_2c.parentNode.childNodes;
+if(_2c.nodeType==1&&_2e.length>2){
+for(var i=2,_2f;_2f=_2e[i];i++){
+if(_2e[i-2].nodeType==1&&this._isEmpty(_2e[i-1])){
+_2c.parentNode.removeChild(_2e[i-1]);
+return;
+}
+}
+}
+}
+},_watchParent:function(_30){
+var _31=_30.childNodes;
+if(_31.length){
+while(_30.childNodes.length){
+var _32=_30.childNodes[_30.childNodes.length-1];
+if(!this._isEmpty(_32)){
+return;
+}
+_30.removeChild(_32);
+}
+}
+}});
+_4.TemplateTagNode=_1.extend(function(tag,_33){
+this.tag=tag;
+this.contents=_33;
+},{mapping:{openblock:"{%",closeblock:"%}",openvariable:"{{",closevariable:"}}",openbrace:"{",closebrace:"}",opencomment:"{#",closecomment:"#}"},render:function(_34,_35){
+this.contents.set(this.mapping[this.tag]);
+return this.contents.render(_34,_35);
+},unrender:function(_36,_37){
+return this.contents.unrender(_36,_37);
+},clone:function(_38){
+return new this.constructor(this.tag,this.contents.clone(_38));
+}});
+_4.WidthRatioNode=_1.extend(function(_39,max,_3a,_3b){
+this.current=new dd._Filter(_39);
+this.max=new dd._Filter(max);
+this.width=_3a;
+this.contents=_3b;
+},{render:function(_3c,_3d){
+var _3e=+this.current.resolve(_3c);
+var max=+this.max.resolve(_3c);
+if(typeof _3e!="number"||typeof max!="number"||!max){
+this.contents.set("");
+}else{
+this.contents.set(""+Math.round((_3e/max)*this.width));
+}
+return this.contents.render(_3c,_3d);
+},unrender:function(_3f,_40){
+return this.contents.unrender(_3f,_40);
+},clone:function(_41){
+return new this.constructor(this.current.getExpression(),this.max.getExpression(),this.width,this.contents.clone(_41));
+}});
+_4.WithNode=_1.extend(function(_42,_43,_44){
+this.target=new dd._Filter(_42);
+this.alias=_43;
+this.nodelist=_44;
+},{render:function(_45,_46){
+var _47=this.target.resolve(_45);
+_45=_45.push();
+_45[this.alias]=_47;
+_46=this.nodelist.render(_45,_46);
+_45=_45.pop();
+return _46;
+},unrender:function(_48,_49){
+return _49;
+},clone:function(_4a){
+return new this.constructor(this.target.getExpression(),this.alias,this.nodelist.clone(_4a));
+}});
+_1.mixin(_4,{comment:function(_4b,_4c){
+_4b.skip_past("endcomment");
+return dd._noOpNode;
+},debug:function(_4d,_4e){
+return new _4.DebugNode(_4d.create_text_node());
+},filter:function(_4f,_50){
+var _51=_50.contents.split(null,1)[1];
+var _52=_4f.create_variable_node("var|"+_51);
+var _53=_4f.parse(["endfilter"]);
+_4f.next_token();
+return new _4.FilterNode(_52,_53);
+},firstof:function(_54,_55){
+var _56=_55.split_contents().slice(1);
+if(!_56.length){
+throw new Error("'firstof' statement requires at least one argument");
+}
+return new _4.FirstOfNode(_56,_54.create_text_node());
+},spaceless:function(_57,_58){
+var _59=_57.parse(["endspaceless"]);
+_57.delete_first_token();
+return new _4.SpacelessNode(_59,_57.create_text_node());
+},templatetag:function(_5a,_5b){
+var _5c=_5b.contents.split();
+if(_5c.length!=2){
+throw new Error("'templatetag' statement takes one argument");
+}
+var tag=_5c[1];
+var _5d=_4.TemplateTagNode.prototype.mapping;
+if(!_5d[tag]){
+var _5e=[];
+for(var key in _5d){
+_5e.push(key);
+}
+throw new Error("Invalid templatetag argument: '"+tag+"'. Must be one of: "+_5e.join(", "));
+}
+return new _4.TemplateTagNode(tag,_5a.create_text_node());
+},widthratio:function(_5f,_60){
+var _61=_60.contents.split();
+if(_61.length!=4){
+throw new Error("widthratio takes three arguments");
+}
+var _62=+_61[3];
+if(typeof _62!="number"){
+throw new Error("widthratio final argument must be an integer");
+}
+return new _4.WidthRatioNode(_61[1],_61[2],_62,_5f.create_text_node());
+},with_:function(_63,_64){
+var _65=_64.split_contents();
+if(_65.length!=4||_65[2]!="as"){
+throw new Error("do_width expected format as 'with value as name'");
+}
+var _66=_63.parse(["endwith"]);
+_63.next_token();
+return new _4.WithNode(_65[1],_65[3],_66);
+}});
+return dojox.dtl.tag.misc;
+});
diff --git a/js/libs/dojox/dtl/tag/misc.js.uncompressed.js b/js/libs/dojox/dtl/tag/misc.js.uncompressed.js
new file mode 100644
index 0000000..7570a36
--- /dev/null
+++ b/js/libs/dojox/dtl/tag/misc.js.uncompressed.js
@@ -0,0 +1,294 @@
+//>>built
+define("dojox/dtl/tag/misc", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "../_base"
+], function(lang,array,connect,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.misc", true);
+
+ var ddtm = dd.tag.misc;
+
+ ddtm.DebugNode = lang.extend(function(text){
+ this.text = text;
+ },
+ {
+ render: function(context, buffer){
+ var keys = context.getKeys();
+ var debug = [];
+ var only = {};
+ for(var i = 0, key; key = keys[i]; i++){
+ only[key] = context[key];
+ debug += "[" + key + ": " + typeof context[key] + "]\n";
+ }
+ console.debug(only);
+ return this.text.set(debug).render(context, buffer, this);
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.text.clone(buffer));
+ },
+ toString: function(){ return "ddtm.DebugNode"; }
+ });
+
+ ddtm.FilterNode = lang.extend(function(varnode, nodelist){
+ this._varnode = varnode;
+ this._nodelist = nodelist;
+ },
+ {
+ render: function(context, buffer){
+ // Doing this in HTML requires a different buffer with a fake root node
+ var output = this._nodelist.render(context, new dojox.string.Builder());
+ context = context.update({ "var": output.toString() });
+ var filtered = this._varnode.render(context, buffer);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._expression, this._nodelist.clone(buffer));
+ }
+ });
+
+ ddtm.FirstOfNode = lang.extend(function(vars, text){
+ this._vars = vars;
+ this.vars = array.map(vars, function(item){
+ return new dojox.dtl._Filter(item);
+ });
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ for(var i = 0, item; item = this.vars[i]; i++){
+ var resolved = item.resolve(context);
+ if(typeof resolved != "undefined"){
+ if(resolved === null){
+ resolved = "null";
+ }
+ this.contents.set(resolved);
+ return this.contents.render(context, buffer);
+ }
+ }
+ return this.contents.unrender(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this._vars, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.SpacelessNode = lang.extend(function(nodelist, text){
+ this.nodelist = nodelist;
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ if(buffer.getParent){
+ // Unfortunately, we have to branch here
+ var watch = [
+ connect.connect(buffer, "onAddNodeComplete", this, "_watch"),
+ connect.connect(buffer, "onSetParent", this, "_watchParent")
+ ];
+ buffer = this.nodelist.render(context, buffer);
+ connect.disconnect(watch[0]);
+ connect.disconnect(watch[1]);
+ }else{
+ var value = this.nodelist.dummyRender(context);
+ this.contents.set(value.replace(/>\s+<'));
+ buffer = this.contents.render(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodelist.clone(buffer), this.contents.clone(buffer));
+ },
+ _isEmpty: function(node){
+ return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
+ },
+ _watch: function(node){
+ if(this._isEmpty(node)){
+ var remove = false;
+ if(node.parentNode.firstChild == node){
+ node.parentNode.removeChild(node);
+ }
+ }else{
+ var children = node.parentNode.childNodes;
+ if(node.nodeType == 1 && children.length > 2){
+ for(var i = 2, child; child = children[i]; i++){
+ if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
+ node.parentNode.removeChild(children[i - 1]);
+ return;
+ }
+ }
+ }
+ }
+ },
+ _watchParent: function(node){
+ var children = node.childNodes;
+ if(children.length){
+ while(node.childNodes.length){
+ var last = node.childNodes[node.childNodes.length - 1];
+ if(!this._isEmpty(last)){
+ return;
+ }
+ node.removeChild(last);
+ }
+ }
+ }
+ });
+
+ ddtm.TemplateTagNode = lang.extend(function(tag, text){
+ this.tag = tag;
+ this.contents = text;
+ },
+ {
+ mapping: {
+ openblock: "{%",
+ closeblock: "%}",
+ openvariable: "{{",
+ closevariable: "}}",
+ openbrace: "{",
+ closebrace: "}",
+ opencomment: "{#",
+ closecomment: "#}"
+ },
+ render: function(context, buffer){
+ this.contents.set(this.mapping[this.tag]);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.tag, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WidthRatioNode = lang.extend(function(current, max, width, text){
+ this.current = new dd._Filter(current);
+ this.max = new dd._Filter(max);
+ this.width = width;
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ var current = +this.current.resolve(context);
+ var max = +this.max.resolve(context);
+ if(typeof current != "number" || typeof max != "number" || !max){
+ this.contents.set("");
+ }else{
+ this.contents.set("" + Math.round((current / max) * this.width));
+ }
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WithNode = lang.extend(function(target, alias, nodelist){
+ this.target = new dd._Filter(target);
+ this.alias = alias;
+ this.nodelist = nodelist;
+ },
+ {
+ render: function(context, buffer){
+ var target = this.target.resolve(context);
+ context = context.push();
+ context[this.alias] = target;
+ buffer = this.nodelist.render(context, buffer);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtm, {
+ comment: function(parser, token){
+ // summary: Ignore everything between {% comment %} and {% endcomment %}
+ parser.skip_past("endcomment");
+ return dd._noOpNode;
+ },
+ debug: function(parser, token){
+ // summary: Output the current context, maybe add more stuff later.
+ return new ddtm.DebugNode(parser.create_text_node());
+ },
+ filter: function(parser, token){
+ // summary: Filter the contents of the blog through variable filters.
+ var rest = token.contents.split(null, 1)[1];
+ var varnode = parser.create_variable_node("var|" + rest);
+ var nodelist = parser.parse(["endfilter"]);
+ parser.next_token();
+ return new ddtm.FilterNode(varnode, nodelist);
+ },
+ firstof: function(parser, token){
+ var parts = token.split_contents().slice(1);
+ if(!parts.length){
+ throw new Error("'firstof' statement requires at least one argument");
+ }
+ return new ddtm.FirstOfNode(parts, parser.create_text_node());
+ },
+ spaceless: function(parser, token){
+ var nodelist = parser.parse(["endspaceless"]);
+ parser.delete_first_token();
+ return new ddtm.SpacelessNode(nodelist, parser.create_text_node());
+ },
+ templatetag: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error("'templatetag' statement takes one argument");
+ }
+ var tag = parts[1];
+ var mapping = ddtm.TemplateTagNode.prototype.mapping;
+ if(!mapping[tag]){
+ var keys = [];
+ for(var key in mapping){
+ keys.push(key);
+ }
+ throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
+ }
+ return new ddtm.TemplateTagNode(tag, parser.create_text_node());
+ },
+ widthratio: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 4){
+ throw new Error("widthratio takes three arguments");
+ }
+ var width = +parts[3];
+ if(typeof width != "number"){
+ throw new Error("widthratio final argument must be an integer");
+ }
+ return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.create_text_node());
+ },
+ with_: function(parser, token){
+ var parts = token.split_contents();
+ if(parts.length != 4 || parts[2] != "as"){
+ throw new Error("do_width expected format as 'with value as name'");
+ }
+ var nodelist = parser.parse(["endwith"]);
+ parser.next_token();
+ return new ddtm.WithNode(parts[1], parts[3], nodelist);
+ }
+ });
+ return dojox.dtl.tag.misc;
+});
\ No newline at end of file
diff --git a/js/libs/dojox/dtl/utils/date.js b/js/libs/dojox/dtl/utils/date.js
new file mode 100644
index 0000000..52f17bd
--- /dev/null
+++ b/js/libs/dojox/dtl/utils/date.js
@@ -0,0 +1,50 @@
+//>>built
+define("dojox/dtl/utils/date",["dojo/_base/lang","dojox/date/php","../_base"],function(_1,_2,dd){
+_1.getObject("dojox.dtl.utils.date",true);
+dd.utils.date.DateFormat=_2.DateFormat;
+_1.extend(dd.utils.date.DateFormat,_2.DateFormat.prototype,{f:function(){
+return (!this.date.getMinutes())?this.g():this.g()+":"+this.i();
+},N:function(){
+return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
+},P:function(){
+if(!this.date.getMinutes()&&!this.date.getHours()){
+return "midnight";
+}
+if(!this.date.getMinutes()&&this.date.getHours()==12){
+return "noon";
+}
+return this.f()+" "+this.a();
+}});
+_1.mixin(dojox.dtl.utils.date,{format:function(_3,_4){
+var df=new dojox.dtl.utils.date.DateFormat(_4);
+return df.format(_3);
+},timesince:function(d,_5){
+if(!(d instanceof Date)){
+d=new Date(d.year,d.month,d.day);
+}
+if(!_5){
+_5=new Date();
+}
+var _6=Math.abs(_5.getTime()-d.getTime());
+for(var i=0,_7;_7=dojox.dtl.utils.date._chunks[i];i++){
+var _8=Math.floor(_6/_7[0]);
+if(_8){
+break;
+}
+}
+return _8+" "+_7[1](_8);
+},_chunks:[[60*60*24*365*1000,function(n){
+return (n==1)?"year":"years";
+}],[60*60*24*30*1000,function(n){
+return (n==1)?"month":"months";
+}],[60*60*24*7*1000,function(n){
+return (n==1)?"week":"weeks";
+}],[60*60*24*1000,function(n){
+return (n==1)?"day":"days";
+}],[60*60*1000,function(n){
+return (n==1)?"hour":"hours";
+}],[60*1000,function(n){
+return (n==1)?"minute":"minutes";
+}]],_months_ap:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."]});
+return dojox.dtl.utils.date;
+});
diff --git a/js/libs/dojox/dtl/utils/date.js.uncompressed.js b/js/libs/dojox/dtl/utils/date.js.uncompressed.js
new file mode 100644
index 0000000..1d7b3dd
--- /dev/null
+++ b/js/libs/dojox/dtl/utils/date.js.uncompressed.js
@@ -0,0 +1,80 @@
+//>>built
+define("dojox/dtl/utils/date", [
+ "dojo/_base/lang",
+ "dojox/date/php",
+ "../_base"
+], function(lang,ddp,dd){
+ /*=====
+ ddp = dojox.data.php;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.utils.date", true);
+
+ dd.utils.date.DateFormat = ddp.DateFormat;
+ lang.extend(dd.utils.date.DateFormat, ddp.DateFormat.prototype, {
+ f: function(){
+ // summary:
+ // Time, in 12-hour hours and minutes, with minutes left off if they're zero.
+ // description:
+ // Examples: '1', '1:30', '2:05', '2'
+ // Proprietary extension.
+ return (!this.date.getMinutes()) ? this.g() : this.g() + ":" + this.i();
+ },
+ N: function(){
+ // summary: Month abbreviation in Associated Press style. Proprietary extension.
+ return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
+ },
+ P: function(){
+ // summary:
+ // Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
+ // if they're zero and the strings 'midnight' and 'noon' if appropriate.
+ // description:
+ // Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
+ // Proprietary extension.
+ if(!this.date.getMinutes() && !this.date.getHours()){
+ return 'midnight';
+ }
+ if(!this.date.getMinutes() && this.date.getHours() == 12){
+ return 'noon';
+ }
+ return this.f() + " " + this.a();
+ }
+ });
+
+ lang.mixin(dojox.dtl.utils.date, {
+ format: function(/*Date*/ date, /*String*/ format){
+ var df = new dojox.dtl.utils.date.DateFormat(format);
+ return df.format(date);
+ },
+ timesince: function(d, now){
+ // summary:
+ // Takes two datetime objects and returns the time between then and now
+ // as a nicely formatted string, e.g "10 minutes"
+ // description:
+ // Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
+ if(!(d instanceof Date)){
+ d = new Date(d.year, d.month, d.day);
+ }
+ if(!now){
+ now = new Date();
+ }
+
+ var delta = Math.abs(now.getTime() - d.getTime());
+ for(var i = 0, chunk; chunk = dojox.dtl.utils.date._chunks[i]; i++){
+ var count = Math.floor(delta / chunk[0]);
+ if(count) break;
+ }
+ return count + " " + chunk[1](count);
+ },
+ _chunks: [
+ [60 * 60 * 24 * 365 * 1000, function(n){ return (n == 1) ? 'year' : 'years'; }],
+ [60 * 60 * 24 * 30 * 1000, function(n){ return (n == 1) ? 'month' : 'months'; }],
+ [60 * 60 * 24 * 7 * 1000, function(n){ return (n == 1) ? 'week' : 'weeks'; }],
+ [60 * 60 * 24 * 1000, function(n){ return (n == 1) ? 'day' : 'days'; }],
+ [60 * 60 * 1000, function(n){ return (n == 1) ? 'hour' : 'hours'; }],
+ [60 * 1000, function(n){ return (n == 1) ? 'minute' : 'minutes'; }]
+ ],
+ _months_ap: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."]
+ });
+ return dojox.dtl.utils.date;
+});
diff --git a/js/libs/dojox/editor/README b/js/libs/dojox/editor/README
new file mode 100644
index 0000000..251c9ce
--- /dev/null
+++ b/js/libs/dojox/editor/README
@@ -0,0 +1,369 @@
+-------------------------------------------------------------------------------
+dojox.editor
+-------------------------------------------------------------------------------
+Version 0.9
+Release date: 9/14/2009
+-------------------------------------------------------------------------------
+Project state:
+experimental, beta, stable
+-------------------------------------------------------------------------------
+Credits
+ Mike Wilcox - Author
+ Jared Jurkiewicz - Author (PrettyPrint, PageBreak, ShowBlockNodes,
+ Preview, Save, ToolbarLineBreak, InsertEntity,
+ NormalizeIndentOutdent, Breadcrumb, FindReplace,
+ CollapsibleToolbar, Blockquote, PasteFromWord, InsertAnchor,
+ TextColor, NormalizeStyle, StatusBar, SafePaste)
+ Dustin Machi - Technical Assistance
+ David Schwartz and Gu Yi He (IBM) - Contributed enhancements to the
+ look and feel of FindReplace, as well as behavioral
+ improvements.
+ Eldon (IBM, CCLA) - LocalImage, AutoUrlLink, TablePluginsColorCell -
+ dojox.widget.ColorPicker, ResizeTableColumn, AutoSave, SpellCheck
+
+-------------------------------------------------------------------------------
+Project description
+
+Space for extensions and additional plugins for dijit.Editor. The project
+currently contains the following plugins:
+
+dojox.editor.plugins.TablePlugins:
+ Status: Experimental.
+ The Table Plugins provide a mechanism for editing tables withing the
+ dijit.Editor. This plugin is experimental and does not work correctly
+ in all dojo supported browsers.
+
+dojox.editor.plugins.UploadImage:
+ Status: Experimental.
+ The UploadImage plugin makes use of the dojox upload widgets to provide
+ a mechanism to upload images to your server for use in the editor.
+
+dojox.editor.plugins.PrettyPrint:
+ Status: Supported (stable).
+ The PrettyPrint plugin provides a mechanism by which the output from
+ editor.getValue()/editor.attr("value") is nicely formatted. Optional
+ format parameters are how many spaces to indent by (default is tab),
+ the maximum text line length (not including indent), and what
+ characters in text strings should be encoded to their &;
+ representation.
+
+dojox.editor.plugins.PageBreak:
+ Status: Supported (stable).
+ A simple plugin that allows you to insert 'page breaks' into the doc
+ being edited. These page break styles will then cause the document
+ to break to another page when printed.
+
+dojox.editor.plugins.ShowBlockNodes:
+ Status: Supported (stable).
+ A simple plugin that allows you to toggle on and off a CSS 'view' of
+ how the page is laid out in terms of the block nodes used for its
+ formatting.
+
+dojox.editor.plugins.Save:
+ Status: Supported (beta).
+ A simple plugin that allows you to POST the content of the editor back
+ to a URL.
+
+dojox.editor.plugins.Preview:
+ Status: Supported (beta).
+ A simple plugin that allows you to display the content of the editor
+ in a new window and apply a set of styles to it so you can see how
+ content will look with various styles applied. It is likely this
+ plugin will still evolve a bit.
+
+dojox.editor.plugins.ToolbarLineBreak:
+ Status: Supported (stable).
+ An extremely simple plugin that allows you to 'linebreak' the dijit toolbar so that really long
+ toolbars for editor (lots of plugins enabled), can be broken up into multiple rows.
+
+dojox.editor.plugins.InsertEntity:
+ Status: Experimental (unsupported).
+ A plugin that enables the ability to insert HTML/XML entity characters
+ into a page. These are often called 'symbols'. The set it provides are the
+ basic latin (8859) set and a portion of greek symbols common to mathematics.
+ It has been marked experimental as it is likely this plugin will evolve a bit.
+
+dojox.editor.plugins.NormalizeIndentOutdent:
+ Status: Experimental (unsupported).
+ A plugin that normalizes the behavior of indent/outdent to use margin styles instead
+ of tags. Also fixes indent/outdent of lists to work properly. This is new
+ and has been tested, but not extensively. Therefore it is currently classed as experimental.
+
+dojox.editor.plugins.Breadcrumb:
+ Status: Experimental (unsupported).
+ A plugin that adds a breadcrumb toolbar to the bottom of the editor. Useful for seeing
+ where you aren and what operations you can perform. This is new and has been tested, but not
+ extensively. Therefore it is currently classed as experimental.
+
+dojox.editor.plugins.FindReplace:
+ Status: Experimental (unsupported).
+ A plugin that adds a togglable Find/Replace toolbar to the editor. Useful for searching
+ and replacing text strings in the editor content. Only works on FF, IE, and WebKit. No Opera
+ support. This is new and has been tested, but not extensively. Therefore it is currently
+ classed as experimental.
+
+dojox.editor.plugins.CollapsibleToolbar:
+ Status: Supported (Stable).
+ A plugin that modified the header node of the editor so that it is 'collapsible'. Meaning that
+ it can be closed (reduced), and reopened. Useful for increasing editor real-estate.
+
+dojox.editor.plugins.Blockquote:
+ Status: Supported (Stable).
+ A plugin that puts a button on the toolbar that allows users to select text for a semantic
+ 'blockquote' tag-wrap action. It toggles on and off during state changes to determine if
+ the current section is contained within a blockquote.
+
+dojox.editor.plugins.PasteFromWord:
+ Status: Beta (unsupported).
+ A plugin that puts a button that opens a dialog to paste in content from Word and similar
+ programs like wordpad. It will then filter out extraneous and bad html from the content
+ before injecting it into the RTE. Experimental as the filter list may not be complete yet.
+ Feedback is welcome and appreciated. Filters will be updated based on it.
+
+dojox.editor.plugins.InsertAnchor:
+ Status: Stable (supported).
+ A plugin that allows anchor points to be inserted into the document being edited.
+ The anchors are styled in the doc to make them easily visible/editable in the document.
+
+dojox.editor.plugins.TextColor:
+ Status: Experimental (unsupported).
+ A plugin that makes use of the dojox.widget.ColorPicker widget in lieu of the
+ dijit.ColorPalette.
+
+dojox.editor.plugins.NormalizeStyle:
+ Status: Experimental (unsupported).
+ A plugin that tries to normalize the output from the editor as either CSS styled or semantic (, , etc)
+ style.
+
+dojox.editor.plugins.StatusBar:
+ Status: Experimental (unsupported).
+ A plugin that adds a status bar and an optional resize handle to the footer of the editor.
+
+dojox.editor.plugins.LocalImage
+ Status: Beta
+ A plugin that adds local image upload and edit capability to the editor.
+
+dojox.editor.plugins.AutoUrlLink
+ Status: Experimental (Unsupported)
+ A plugin that adds auto url link creation capability as a headless plugin to the editor
+
+dojox.editor.plugins.ResizeColumnPlugin
+ Status: Experimental (Unsupported)
+ A plugin that adds column resize to the editor table plugins.
+
+dojox.editor.plugins.AutoSave
+ Status: Experimental (Unsupported)
+ A plugin that provides 'auto-save' capablity, eg, post back to some url at an interval.
+
+dojox.editor.plugins.SpellCheck
+ Status: Experimental (Unsupported)
+ A plugin that provides server-side spell-check support.
+
+
+dojox.editor.plugins.SafePaste
+ Status: Beta (Supported)
+ A plugin that provides a safer paste function to the editor. It strips out script tags,
+ tries to fix up odd input from Word, Wordpad, etc. Very similar to PasteFromWord except that
+ it takes complete control of paste in dijit.Editor instead of being an alternate paste icon.
+
+-------------------------------------------------------------------------------
+Dependencies:
+
+dijit
+dojox.form
+dojox.html.format
+dojox.widget.ColorPicker
+dojox.layout.ResizeHandle
+
+-------------------------------------------------------------------------------
+Documentation
+
+The plugins directory contains extensions which work with dijit.Editor.
+
+See also:
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/TablePlugins.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/PrettyPrint.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/PageBreak.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/ShowBlockNodes.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/Preview.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/Save.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/ToolbarLineBreak.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/InsertEntity.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/NormalizeIndentOutdent.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/Breadcrumb.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/FindReplace.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/CollapsibleToolbar.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/Blockquote.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/PasteFromWord.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/InsertAnchor.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/TextColor.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/NormalizeStyle.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/StatusBar.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/LocalImage.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/AutoUrlLink.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/ResizeTableColumn.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/AutoSave.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/SpellCheck.html
+ http://dojotoolkit.org/reference-guide/dojox/editor/plugins/SafePaste.html
+.html
+
+-------------------------------------------------------------------------------
+Plugin Installation instructions
+
+Get dojo and dijit from svn. Include the Editor and plugins in your page:
+
+dojo.require("dijit.Editor");
+
+For the TablePlugins:
+ dojo.require("dojox.editor.plugins.TablePlugins");
+ and CSS:
+
+
+For the UploadImage plugin:
+ dojo.require("dojox.editor.plugins.UploadImage");
+ and CSS:
+
+
+
+For the PrettyPrint plugin:
+ dojo.require("dojox.editor.plugins.PrettyPrint");
+ and CSS:
+ No CSS required.
+
+For the PageBreak plugin:
+ dojo.require("dojox.editor.plugins.PageBreak");
+ and CSS:
+
+
+For the ShowBlockNodes plugin:
+ dojo.require("dojox.editor.plugins.ShowBockNodes");
+ and CSS:
+
+
+For the Preview plugin:
+ dojo.require("dojox.editor.plugins.Preview");
+ and CSS:
+
+
+For the Save plugin:
+ dojo.require("dojox.editor.plugins.Save");
+ and CSS:
+
+
+For the ToolbarLineBreak plugin:
+ dojo.require("dojox.editor.plugins.ToolbarLineBreak");
+ and CSS:
+ No CSS required.
+
+For the InsertEntity plugin:
+ dojo.require("dojox.editor.plugins.InsertEntity");
+ and CSS:
+
+
+For the NormalizeIndentOutdent plugin:
+ dojo.require("dojox.editor.plugins.NormalizeIndentOutdent");
+ and CSS:
+ No CSS required.
+
+For the Breadcrumb plugin:
+ dojo.require("dojox.editor.plugins.Breadcrumb");
+ and CSS:
+
+
+For the FindReplace plugin:
+ dojo.require("dojox.editor.plugins.FindReplace");
+ and CSS:
+
+
+For the CollapsibleToolbar plugin:
+ dojo.require("dojox.editor.plugins.CollapsibleToolbar");
+ and CSS:
+
+
+For the Blockquote plugin:
+ dojo.require("dojox.editor.plugins.Blockquote");
+ and CSS:
+
+
+For the PasteFromWord plugin:
+ dojo.require("dojox.editor.plugins.PasteFromWord");
+ and CSS:
+
+
+For the InsertAnchor plugin:
+ dojo.require("dojox.editor.plugins.InsertAnchor");
+ and CSS:
+
+
+For the TextColor plugin:
+ dojo.require("dojox.editor.plugins.TextColor");
+ and CSS:
+
+
+For the NormalizeStyle plugin:
+ dojo.require("dojox.editor.plugins.NormalizeStyle");
+ and CSS:
+ No CSS required.
+
+For the StatusBar plugin:
+ dojo.require("dojox.editor.plugins.StatusBar");
+ and CSS:
+
+
+For the LocalImage plugin:
+ dojo.require("dojox.editor.plugins.LocalImage");
+ and CSS:
+
+
+For the AutoUrlLink plugin:
+ dojo.require("dojox.editor.plugins.AutoUrlLink");
+ and CSS:
+ No CSS required.
+
+For the ResizeTableColumn plugin:
+ dojo.require("dojox.editor.plugins.ResizeTableColumn");
+ and CSS:
+ No CSS required in addition to the table plugins css.
+
+For the AutoSave plugin:
+ dojo.require("dojox.editor.plugins.AutoSave");
+ and CSS:
+
+
+For the SpellCheck plugin:
+ dojo.require("dojox.editor.plugins.SpellCheck");
+ and CSS:
+
+
+For the SafePaste plugin:
+ dojo.require("dojox.editor.plugins.SafePaste");
+ and CSS:
+
+
+See tests for examples:
+ dojox/editor/tests/editorTablePlugs.html
+ dojox/editor/tests/editorUploadPlug.html
+ dojox/editor/tests/editorPrettyPrint.html
+ dojox/editor/tests/editorPageBreak.html
+ dojox/editor/tests/editorShowBlockNodes.html
+ dojox/editor/tests/editorPreview.html
+ dojox/editor/tests/editorSave.html
+ dojox/editor/tests/editorToolbarLineBreak.html
+ dojox/editor/tests/editorInsertEntity.html
+ dojox/editor/tests/editorNormalizeIndentOutdent.html
+ dojox/editor/tests/editorBreadcrumb.html
+ dojox/editor/tests/editorFindReplace.html
+ dojox/editor/tests/editorCollapsibleToolbar.html
+ dojox/editor/tests/editorBlockquote.html
+ dojox/editor/tests/editorPasteFromWord.html
+ dojox/editor/tests/editorInsertAnchor.html
+ dojox/editor/tests/editorTextColor.html
+ dojox/editor/tests/editorNormalizeStyle.html
+ dojox/editor/tests/editorStatusBar.html
+ dojox/editor/tests/editorLocalImage.html
+ dojox/editor/tests/editorAutoUrlLink.html
+ dojox/editor/tests/editorResizeTableColumn.html
+ dojox/editor/tests/editorAutoSave.html
+ dojox/editor/tests/editorSpellCheck.html
+ dojox/editor/tests/editorSafePaste.html
+ dojox/editor/tests/testPluginsAll.html
diff --git a/js/libs/dojox/editor/plugins/AutoSave.js b/js/libs/dojox/editor/plugins/AutoSave.js
new file mode 100644
index 0000000..82c3514
--- /dev/null
+++ b/js/libs/dojox/editor/plugins/AutoSave.js
@@ -0,0 +1,151 @@
+//>>built
+define("dojox/editor/plugins/AutoSave",["dojo","dijit","dojox","dijit/_base/manager","dijit/_base/popup","dijit/_Widget","dijit/_TemplatedMixin","dijit/_WidgetsInTemplateMixin","dijit/Dialog","dijit/MenuItem","dijit/Menu","dijit/form/Button","dijit/form/ComboButton","dijit/form/ComboBox","dijit/form/_TextBoxMixin","dijit/form/TextBox","dijit/TooltipDialog","dijit/_editor/_Plugin","dojo/_base/connect","dojo/_base/declare","dojo/date/locale","dojo/i18n","dojo/string","dojox/editor/plugins/Save","dojo/i18n!dojox/editor/plugins/nls/AutoSave"],function(_1,_2,_3){
+_1.experimental("dojox.editor.plugins.AutoSave");
+_1.declare("dojox.editor.plugins._AutoSaveSettingDialog",[_2._Widget,_2._TemplatedMixin,_2._WidgetsInTemplateMixin],{dialogTitle:"",dialogDescription:"",paramName:"",paramLabel:"",btnOk:"",btnCancel:"",widgetsInTemplate:true,templateString:""+"