diff --git a/feedlist.js b/feedlist.js index 7dfaef952..5ee103747 100644 --- a/feedlist.js +++ b/feedlist.js @@ -441,7 +441,7 @@ function feedlist_init() { } } -function hide_footer_af(effect) { +/* function hide_footer_af(effect) { try { var c = $("content-frame"); @@ -465,12 +465,15 @@ function hide_footer_af(effect) { } catch (e) { exception_error("hide_footer_af", e); } -} +} */ function hide_footer() { try { if (Element.visible("footer")) { - new Effect.Fade("footer", { afterFinish: hide_footer_af }); + + Element.hide("footer"); + + //new Effect.Fade("footer", { afterFinish: hide_footer_af }); } } catch (e) { exception_error("hide_footer", e); diff --git a/lib/dijit/Calendar.js b/lib/dijit/Calendar.js new file mode 100644 index 000000000..fa82770ee --- /dev/null +++ b/lib/dijit/Calendar.js @@ -0,0 +1,265 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.Calendar"]){ +dojo._hasResource["dijit.Calendar"]=true; +dojo.provide("dijit.Calendar"); +dojo.require("dojo.cldr.supplemental"); +dojo.require("dojo.date"); +dojo.require("dojo.date.locale"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.require("dijit._CssStateMixin"); +dojo.declare("dijit.Calendar",[dijit._Widget,dijit._Templated,dijit._CssStateMixin],{templateString:dojo.cache("dijit","templates/Calendar.html","\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n
\n\t\t\t\t\"\"\n\t\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
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t\t\t\"\"\n\t\t\t\t+\n\t\t\t
\n\t\t\t\t

\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t

\n\t\t\t
\n"),value:new Date(),datePackage:"dojo.date",dayWidth:"narrow",tabIndex:"0",baseClass:"dijitCalendar",cssStateNodes:{"decrementMonth":"dijitCalendarArrow","incrementMonth":"dijitCalendarArrow","previousYearLabelNode":"dijitCalendarPreviousYear","nextYearLabelNode":"dijitCalendarNextYear"},attributeMap:dojo.delegate(dijit._Widget.prototype.attributeMap,{tabIndex:"domNode"}),setValue:function(_1){ +dojo.deprecated("dijit.Calendar:setValue() is deprecated. Use set('value', ...) instead.","","2.0"); +this.set("value",_1); +},_getValueAttr:function(){ +var _2=new this.dateClassObj(this.value); +_2.setHours(0,0,0,0); +if(_2.getDate()_7){ +_b-=7; +} +dojo.query(".dijitCalendarDateTemplate",this.domNode).forEach(function(_c,i){ +i+=_b; +var _d=new this.dateClassObj(_6),_e,_f="dijitCalendar",adj=0; +if(i<_7){ +_e=_9-_7+i+1; +adj=-1; +_f+="Previous"; +}else{ +if(i>=(_7+_8)){ +_e=i-_7-_8+1; +adj=1; +_f+="Next"; +}else{ +_e=i-_7+1; +_f+="Current"; +} +} +if(adj){ +_d=this.dateFuncObj.add(_d,"month",adj); +} +_d.setDate(_e); +if(!this.dateFuncObj.compare(_d,_a,"date")){ +_f="dijitCalendarCurrentDate "+_f; +} +if(this._isSelectedDate(_d,this.lang)){ +_f="dijitCalendarSelectedDate "+_f; +} +if(this.isDisabledDate(_d,this.lang)){ +_f="dijitCalendarDisabledDate "+_f; +} +var _10=this.getClassForDate(_d,this.lang); +if(_10){ +_f=_10+" "+_f; +} +_c.className=_f+"Month dijitCalendarDateTemplate"; +_c.dijitDateValue=_d.valueOf(); +var _11=dojo.query(".dijitCalendarDateLabel",_c)[0],_12=_d.getDateLocalized?_d.getDateLocalized(this.lang):_d.getDate(); +this._setText(_11,_12); +},this); +var _13=this.dateLocaleModule.getNames("months","wide","standAlone",this.lang,_6); +this._setText(this.monthLabelNode,_13[_6.getMonth()]); +dojo.query(".dijitCalendarMonthLabelTemplate",this.domNode).forEach(function(_14,i){ +dojo.toggleClass(_14,"dijitHidden",!(i in _13)); +this._setText(_14,_13[i]); +},this); +var y=_6.getFullYear()-1; +var d=new this.dateClassObj(); +dojo.forEach(["previous","current","next"],function(_15){ +d.setFullYear(y++); +this._setText(this[_15+"YearLabelNode"],this.dateLocaleModule.format(d,{selector:"year",locale:this.lang})); +},this); +var _16=this; +var _17=function(_18,_19,adj){ +_16._connects.push(dijit.typematic.addMouseListener(_16[_18],_16,function(_1a){ +if(_1a>=0){ +_16._adjustDisplay(_19,adj); +} +},0.8,500)); +}; +_17("incrementMonth","month",1); +_17("decrementMonth","month",-1); +_17("nextYearLabelNode","year",1); +_17("previousYearLabelNode","year",-1); +},goToToday:function(){ +this.set("value",new this.dateClassObj()); +},constructor:function(_1b){ +var _1c=(_1b.datePackage&&(_1b.datePackage!="dojo.date"))?_1b.datePackage+".Date":"Date"; +this.dateClassObj=dojo.getObject(_1c,false); +this.datePackage=_1b.datePackage||this.datePackage; +this.dateFuncObj=dojo.getObject(this.datePackage,false); +this.dateLocaleModule=dojo.getObject(this.datePackage+".locale",false); +},postMixInProperties:function(){ +if(isNaN(this.value)){ +delete this.value; +} +this.inherited(arguments); +},postCreate:function(){ +this.inherited(arguments); +dojo.setSelectable(this.domNode,false); +var _1d=dojo.hitch(this,function(_1e,n){ +var _1f=dojo.query(_1e,this.domNode)[0]; +for(var i=0;i= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + + +if(!dojo._hasResource["dijit.CheckedMenuItem"]){ +dojo._hasResource["dijit.CheckedMenuItem"]=true; +dojo.provide("dijit.CheckedMenuItem"); +dojo.require("dijit.MenuItem"); +dojo.declare("dijit.CheckedMenuItem",dijit.MenuItem,{templateString:dojo.cache("dijit","templates/CheckedMenuItem.html","\n\t\n\t\t\"\"\n\t\t\n\t\n\t\n\t\n\t \n\n"),checked:false,_setCheckedAttr:function(_1){ +dojo.toggleClass(this.domNode,"dijitCheckedMenuItemChecked",_1); +dijit.setWaiState(this.domNode,"checked",_1); +this.checked=_1; +},onChange:function(_2){ +},_onClick:function(e){ +if(!this.disabled){ +this.set("checked",!this.checked); +this.onChange(this.checked); +} +this.inherited(arguments); +}}); +} diff --git a/lib/dijit/ColorPalette.js b/lib/dijit/ColorPalette.js new file mode 100644 index 000000000..62aae00df --- /dev/null +++ b/lib/dijit/ColorPalette.js @@ -0,0 +1,31 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.ColorPalette"]){ +dojo._hasResource["dijit.ColorPalette"]=true; +dojo.provide("dijit.ColorPalette"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.require("dojo.colors"); +dojo.require("dojo.i18n"); +dojo.require("dijit._PaletteMixin"); +dojo.requireLocalization("dojo","colors",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); +dojo.declare("dijit.ColorPalette",[dijit._Widget,dijit._Templated,dijit._PaletteMixin],{palette:"7x10",_palettes:{"7x10":[["white","seashell","cornsilk","lemonchiffon","lightyellow","palegreen","paleturquoise","lightcyan","lavender","plum"],["lightgray","pink","bisque","moccasin","khaki","lightgreen","lightseagreen","lightskyblue","cornflowerblue","violet"],["silver","lightcoral","sandybrown","orange","palegoldenrod","chartreuse","mediumturquoise","skyblue","mediumslateblue","orchid"],["gray","red","orangered","darkorange","yellow","limegreen","darkseagreen","royalblue","slateblue","mediumorchid"],["dimgray","crimson","chocolate","coral","gold","forestgreen","seagreen","blue","blueviolet","darkorchid"],["darkslategray","firebrick","saddlebrown","sienna","olive","green","darkcyan","mediumblue","darkslateblue","darkmagenta"],["black","darkred","maroon","brown","darkolivegreen","darkgreen","midnightblue","navy","indigo","purple"]],"3x4":[["white","lime","green","blue"],["silver","yellow","fuchsia","navy"],["gray","red","purple","black"]]},_imagePaths:{"7x10":dojo.moduleUrl("dijit.themes","a11y/colors7x10.png"),"3x4":dojo.moduleUrl("dijit.themes","a11y/colors3x4.png"),"7x10-rtl":dojo.moduleUrl("dijit.themes","a11y/colors7x10-rtl.png"),"3x4-rtl":dojo.moduleUrl("dijit.themes","a11y/colors3x4-rtl.png")},templateString:dojo.cache("dijit","templates/ColorPalette.html","
\n\t\"\"/\n\t\n\t\t\n\t
\n
\n"),baseClass:"dijitColorPalette",dyeClass:"dijit._Color",buildRendering:function(){ +this.inherited(arguments); +this.imageNode.setAttribute("src",this._imagePaths[this.palette+(this.isLeftToRight()?"":"-rtl")].toString()); +var _1=dojo.i18n.getLocalization("dojo","colors",this.lang); +this._preparePalette(this._palettes[this.palette],_1); +}}); +dojo.declare("dijit._Color",dojo.Color,{constructor:function(_2){ +this._alias=_2; +this.setColor(dojo.Color.named[_2]); +},getValue:function(){ +return this.toHex(); +},fillCell:function(_3,_4){ +dojo.create("img",{src:_4,"class":"dijitPaletteImg",alt:this._alias},_3); +}}); +} diff --git a/lib/dijit/Declaration.js b/lib/dijit/Declaration.js new file mode 100644 index 000000000..57cbfd031 --- /dev/null +++ b/lib/dijit/Declaration.js @@ -0,0 +1,36 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.Declaration"]){ +dojo._hasResource["dijit.Declaration"]=true; +dojo.provide("dijit.Declaration"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.declare("dijit.Declaration",dijit._Widget,{_noScript:true,widgetClass:"",defaults:null,mixins:[],buildRendering:function(){ +var _1=this.srcNodeRef.parentNode.removeChild(this.srcNodeRef),_2=dojo.query("> script[type^='dojo/method'][event]",_1).orphan(),_3=dojo.query("> script[type^='dojo/method']",_1).orphan(),_4=dojo.query("> script[type^='dojo/connect']",_1).orphan(),_5=_1.nodeName; +var _6=this.defaults||{}; +dojo.forEach(_2,function(s){ +var _7=s.getAttribute("event"),_8=dojo.parser._functionFromScript(s); +_6[_7]=_8; +}); +this.mixins=this.mixins.length?dojo.map(this.mixins,function(_9){ +return dojo.getObject(_9); +}):[dijit._Widget,dijit._Templated]; +_6.widgetsInTemplate=true; +_6._skipNodeCache=true; +_6.templateString="<"+_5+" class='"+_1.className+"' dojoAttachPoint='"+(_1.getAttribute("dojoAttachPoint")||"")+"' dojoAttachEvent='"+(_1.getAttribute("dojoAttachEvent")||"")+"' >"+_1.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+""; +dojo.query("[dojoType]",_1).forEach(function(_a){ +_a.removeAttribute("dojoType"); +}); +var wc=dojo.declare(this.widgetClass,this.mixins,_6); +var _b=_4.concat(_3); +dojo.forEach(_b,function(s){ +var _c=s.getAttribute("event")||"postscript",_d=dojo.parser._functionFromScript(s); +dojo.connect(wc.prototype,_c,_d); +}); +}}); +} diff --git a/lib/dijit/Dialog.js b/lib/dijit/Dialog.js new file mode 100644 index 000000000..a35d523bf --- /dev/null +++ b/lib/dijit/Dialog.js @@ -0,0 +1,256 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.Dialog"]){ +dojo._hasResource["dijit.Dialog"]=true; +dojo.provide("dijit.Dialog"); +dojo.require("dojo.dnd.move"); +dojo.require("dojo.dnd.TimedMoveable"); +dojo.require("dojo.fx"); +dojo.require("dojo.window"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.require("dijit._CssStateMixin"); +dojo.require("dijit.form._FormMixin"); +dojo.require("dijit._DialogMixin"); +dojo.require("dijit.DialogUnderlay"); +dojo.require("dijit.layout.ContentPane"); +dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); +dojo.declare("dijit._DialogBase",[dijit._Templated,dijit.form._FormMixin,dijit._DialogMixin,dijit._CssStateMixin],{templateString:dojo.cache("dijit","templates/Dialog.html","
\n\t
\n\t\n\t\n\t\tx\n\t\n\t
\n\t\t
\n
\n"),baseClass:"dijitDialog",cssStateNodes:{closeButtonNode:"dijitDialogCloseIcon"},attributeMap:dojo.delegate(dijit._Widget.prototype.attributeMap,{title:[{node:"titleNode",type:"innerHTML"},{node:"titleBar",type:"attribute"}],"aria-describedby":""}),open:false,duration:dijit.defaultDuration,refocus:true,autofocus:true,_firstFocusItem:null,_lastFocusItem:null,doLayout:false,draggable:true,"aria-describedby":"",postMixInProperties:function(){ +var _1=dojo.i18n.getLocalization("dijit","common"); +dojo.mixin(this,_1); +this.inherited(arguments); +},postCreate:function(){ +dojo.style(this.domNode,{display:"none",position:"absolute"}); +dojo.body().appendChild(this.domNode); +this.inherited(arguments); +this.connect(this,"onExecute","hide"); +this.connect(this,"onCancel","hide"); +this._modalconnects=[]; +},onLoad:function(){ +this._position(); +if(this.autofocus){ +this._getFocusItems(this.domNode); +dijit.focus(this._firstFocusItem); +} +this.inherited(arguments); +},_endDrag:function(e){ +if(e&&e.node&&e.node===this.domNode){ +this._relativePosition=dojo.position(e.node); +} +},_setup:function(){ +var _2=this.domNode; +if(this.titleBar&&this.draggable){ +this._moveable=(dojo.isIE==6)?new dojo.dnd.TimedMoveable(_2,{handle:this.titleBar}):new dojo.dnd.Moveable(_2,{handle:this.titleBar,timeout:0}); +dojo.subscribe("/dnd/move/stop",this,"_endDrag"); +}else{ +dojo.addClass(_2,"dijitDialogFixed"); +} +this.underlayAttrs={dialogId:this.id,"class":dojo.map(this["class"].split(/\s/),function(s){ +return s+"_underlay"; +}).join(" ")}; +this._fadeIn=dojo.fadeIn({node:_2,duration:this.duration,beforeBegin:dojo.hitch(this,function(){ +var _3=dijit._underlay; +if(!_3){ +_3=dijit._underlay=new dijit.DialogUnderlay(this.underlayAttrs); +}else{ +_3.set(this.underlayAttrs); +} +var ds=dijit._dialogStack,_4=948+ds.length*2; +if(ds.length==1){ +_3.show(); +} +dojo.style(dijit._underlay.domNode,"zIndex",_4); +dojo.style(this.domNode,"zIndex",_4+1); +}),onEnd:dojo.hitch(this,function(){ +if(this.autofocus){ +this._getFocusItems(this.domNode); +dijit.focus(this._firstFocusItem); +} +})}); +this._fadeOut=dojo.fadeOut({node:_2,duration:this.duration,onEnd:dojo.hitch(this,function(){ +_2.style.display="none"; +var ds=dijit._dialogStack; +if(ds.length==0){ +dijit._underlay.hide(); +}else{ +dojo.style(dijit._underlay.domNode,"zIndex",948+ds.length*2); +dijit._underlay.set(ds[ds.length-1].underlayAttrs); +} +if(this.refocus){ +var _5=this._savedFocus; +if(ds.length>0){ +var pd=ds[ds.length-1]; +if(!dojo.isDescendant(_5.node,pd.domNode)){ +pd._getFocusItems(pd.domNode); +_5=pd._firstFocusItem; +} +} +dijit.focus(_5); +} +})}); +},uninitialize:function(){ +var _6=false; +if(this._fadeIn&&this._fadeIn.status()=="playing"){ +_6=true; +this._fadeIn.stop(); +} +if(this._fadeOut&&this._fadeOut.status()=="playing"){ +_6=true; +this._fadeOut.stop(); +} +if((this.open||_6)&&!dijit._underlay._destroyed){ +dijit._underlay.hide(); +} +if(this._moveable){ +this._moveable.destroy(); +} +this.inherited(arguments); +},_size:function(){ +this._checkIfSingleChild(); +if(this._singleChild){ +if(this._singleChildOriginalStyle){ +this._singleChild.domNode.style.cssText=this._singleChildOriginalStyle; +} +delete this._singleChildOriginalStyle; +}else{ +dojo.style(this.containerNode,{width:"auto",height:"auto"}); +} +var mb=dojo.marginBox(this.domNode); +var _7=dojo.window.getBox(); +if(mb.w>=_7.w||mb.h>=_7.h){ +var w=Math.min(mb.w,Math.floor(_7.w*0.75)),h=Math.min(mb.h,Math.floor(_7.h*0.75)); +if(this._singleChild&&this._singleChild.resize){ +this._singleChildOriginalStyle=this._singleChild.domNode.style.cssText; +this._singleChild.resize({w:w,h:h}); +}else{ +dojo.style(this.containerNode,{width:w+"px",height:h+"px",overflow:"auto",position:"relative"}); +} +}else{ +if(this._singleChild&&this._singleChild.resize){ +this._singleChild.resize(); +} +} +},_position:function(){ +if(!dojo.hasClass(dojo.body(),"dojoMove")){ +var _8=this.domNode,_9=dojo.window.getBox(),p=this._relativePosition,bb=p?null:dojo._getBorderBox(_8),l=Math.floor(_9.l+(p?p.x:(_9.w-bb.w)/2)),t=Math.floor(_9.t+(p?p.y:(_9.h-bb.h)/2)); +dojo.style(_8,{left:l+"px",top:t+"px"}); +} +},_onKey:function(_a){ +var ds=dijit._dialogStack; +if(ds[ds.length-1]!=this){ +return; +} +if(_a.charOrCode){ +var dk=dojo.keys; +var _b=_a.target; +if(_a.charOrCode===dk.TAB){ +this._getFocusItems(this.domNode); +} +var _c=(this._firstFocusItem==this._lastFocusItem); +if(_b==this._firstFocusItem&&_a.shiftKey&&_a.charOrCode===dk.TAB){ +if(!_c){ +dijit.focus(this._lastFocusItem); +} +dojo.stopEvent(_a); +}else{ +if(_b==this._lastFocusItem&&_a.charOrCode===dk.TAB&&!_a.shiftKey){ +if(!_c){ +dijit.focus(this._firstFocusItem); +} +dojo.stopEvent(_a); +}else{ +while(_b){ +if(_b==this.domNode||dojo.hasClass(_b,"dijitPopup")){ +if(_a.charOrCode==dk.ESCAPE){ +this.onCancel(); +}else{ +return; +} +} +_b=_b.parentNode; +} +if(_a.charOrCode!==dk.TAB){ +dojo.stopEvent(_a); +}else{ +if(!dojo.isOpera){ +try{ +this._firstFocusItem.focus(); +} +catch(e){ +} +} +} +} +} +} +},show:function(){ +if(this.open){ +return; +} +if(!this._alreadyInitialized){ +this._setup(); +this._alreadyInitialized=true; +} +if(this._fadeOut.status()=="playing"){ +this._fadeOut.stop(); +} +this._modalconnects.push(dojo.connect(window,"onscroll",this,"layout")); +this._modalconnects.push(dojo.connect(window,"onresize",this,function(){ +var _d=dojo.window.getBox(); +if(!this._oldViewport||_d.h!=this._oldViewport.h||_d.w!=this._oldViewport.w){ +this.layout(); +this._oldViewport=_d; +} +})); +this._modalconnects.push(dojo.connect(dojo.doc.documentElement,"onkeypress",this,"_onKey")); +dojo.style(this.domNode,{opacity:0,display:""}); +this.open=true; +this._onShow(); +this._size(); +this._position(); +dijit._dialogStack.push(this); +this._fadeIn.play(); +this._savedFocus=dijit.getFocus(this); +},hide:function(){ +var ds=dijit._dialogStack; +if(!this._alreadyInitialized||this!=ds[ds.length-1]){ +return; +} +if(this._fadeIn.status()=="playing"){ +this._fadeIn.stop(); +} +ds.pop(); +this._fadeOut.play(); +if(this._scrollConnected){ +this._scrollConnected=false; +} +dojo.forEach(this._modalconnects,dojo.disconnect); +this._modalconnects=[]; +if(this._relativePosition){ +delete this._relativePosition; +} +this.open=false; +this.onHide(); +},layout:function(){ +if(this.domNode.style.display!="none"){ +if(dijit._underlay){ +dijit._underlay.layout(); +} +this._position(); +} +},destroy:function(){ +dojo.forEach(this._modalconnects,dojo.disconnect); +if(this.refocus&&this.open){ +setTimeout(dojo.hitch(dijit,"focus",this._savedFocus),25); +} +this.inherited(arguments); +}}); +dojo.declare("dijit.Dialog",[dijit.layout.ContentPane,dijit._DialogBase],{}); +dijit._dialogStack=[]; +dojo.require("dijit.TooltipDialog"); +} diff --git a/lib/dijit/DialogUnderlay.js b/lib/dijit/DialogUnderlay.js new file mode 100644 index 000000000..0056462a5 --- /dev/null +++ b/lib/dijit/DialogUnderlay.js @@ -0,0 +1,42 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.DialogUnderlay"]){ +dojo._hasResource["dijit.DialogUnderlay"]=true; +dojo.provide("dijit.DialogUnderlay"); +dojo.require("dojo.window"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.declare("dijit.DialogUnderlay",[dijit._Widget,dijit._Templated],{templateString:"
",dialogId:"","class":"",attributeMap:{id:"domNode"},_setDialogIdAttr:function(id){ +dojo.attr(this.node,"id",id+"_underlay"); +},_setClassAttr:function(_1){ +this.node.className="dijitDialogUnderlay "+_1; +},postCreate:function(){ +dojo.body().appendChild(this.domNode); +},layout:function(){ +var is=this.node.style,os=this.domNode.style; +os.display="none"; +var _2=dojo.window.getBox(); +os.top=_2.t+"px"; +os.left=_2.l+"px"; +is.width=_2.w+"px"; +is.height=_2.h+"px"; +os.display="block"; +},show:function(){ +this.domNode.style.display="block"; +this.layout(); +this.bgIframe=new dijit.BackgroundIframe(this.domNode); +},hide:function(){ +this.bgIframe.destroy(); +this.domNode.style.display="none"; +},uninitialize:function(){ +if(this.bgIframe){ +this.bgIframe.destroy(); +} +this.inherited(arguments); +}}); +} diff --git a/lib/dijit/Editor.js b/lib/dijit/Editor.js new file mode 100644 index 000000000..69258eade --- /dev/null +++ b/lib/dijit/Editor.js @@ -0,0 +1,473 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.Editor"]){ +dojo._hasResource["dijit.Editor"]=true; +dojo.provide("dijit.Editor"); +dojo.require("dijit._editor.RichText"); +dojo.require("dijit.Toolbar"); +dojo.require("dijit.ToolbarSeparator"); +dojo.require("dijit._editor._Plugin"); +dojo.require("dijit._editor.plugins.EnterKeyHandling"); +dojo.require("dijit._editor.range"); +dojo.require("dijit._Container"); +dojo.require("dojo.i18n"); +dojo.require("dijit.layout._LayoutWidget"); +dojo.require("dijit._editor.range"); +dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); +dojo.declare("dijit.Editor",dijit._editor.RichText,{plugins:null,extraPlugins:null,constructor:function(){ +if(!dojo.isArray(this.plugins)){ +this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|","insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull","dijit._editor.plugins.EnterKeyHandling"]; +} +this._plugins=[]; +this._editInterval=this.editActionInterval*1000; +if(dojo.isIE){ +this.events.push("onBeforeDeactivate"); +this.events.push("onBeforeActivate"); +} +},postCreate:function(){ +this._steps=this._steps.slice(0); +this._undoedSteps=this._undoedSteps.slice(0); +if(dojo.isArray(this.extraPlugins)){ +this.plugins=this.plugins.concat(this.extraPlugins); +} +this.setValueDeferred=new dojo.Deferred(); +this.inherited(arguments); +this.commands=dojo.i18n.getLocalization("dijit._editor","commands",this.lang); +if(!this.toolbar){ +this.toolbar=new dijit.Toolbar({dir:this.dir,lang:this.lang}); +this.header.appendChild(this.toolbar.domNode); +} +dojo.forEach(this.plugins,this.addPlugin,this); +this.setValueDeferred.callback(true); +dojo.addClass(this.iframe.parentNode,"dijitEditorIFrameContainer"); +dojo.addClass(this.iframe,"dijitEditorIFrame"); +dojo.attr(this.iframe,"allowTransparency",true); +if(dojo.isWebKit){ +dojo.style(this.domNode,"KhtmlUserSelect","none"); +} +this.toolbar.startup(); +this.onNormalizedDisplayChanged(); +},destroy:function(){ +dojo.forEach(this._plugins,function(p){ +if(p&&p.destroy){ +p.destroy(); +} +}); +this._plugins=[]; +this.toolbar.destroyRecursive(); +delete this.toolbar; +this.inherited(arguments); +},addPlugin:function(_1,_2){ +var _3=dojo.isString(_1)?{name:_1}:_1; +if(!_3.setEditor){ +var o={"args":_3,"plugin":null,"editor":this}; +dojo.publish(dijit._scopeName+".Editor.getPlugin",[o]); +if(!o.plugin){ +var pc=dojo.getObject(_3.name); +if(pc){ +o.plugin=new pc(_3); +} +} +if(!o.plugin){ +console.warn("Cannot find plugin",_1); +return; +} +_1=o.plugin; +} +if(arguments.length>1){ +this._plugins[_2]=_1; +}else{ +this._plugins.push(_1); +} +_1.setEditor(this); +if(dojo.isFunction(_1.setToolbar)){ +_1.setToolbar(this.toolbar); +} +},startup:function(){ +},resize:function(_4){ +if(_4){ +dijit.layout._LayoutWidget.prototype.resize.apply(this,arguments); +} +},layout:function(){ +var _5=(this._contentBox.h-(this.getHeaderHeight()+this.getFooterHeight()+dojo._getPadBorderExtents(this.iframe.parentNode).h+dojo._getMarginExtents(this.iframe.parentNode).h)); +this.editingArea.style.height=_5+"px"; +if(this.iframe){ +this.iframe.style.height="100%"; +} +this._layoutMode=true; +},_onIEMouseDown:function(e){ +var _6; +var b=this.document.body; +var _7=b.clientWidth; +var _8=b.clientHeight; +var _9=b.clientLeft; +var _a=b.offsetWidth; +var _b=b.offsetHeight; +var _c=b.offsetLeft; +bodyDir=b.dir?b.dir.toLowerCase():""; +if(bodyDir!="rtl"){ +if(_7<_a&&e.x>_7&&e.x<_a){ +_6=true; +} +}else{ +if(e.x<_9&&e.x>_c){ +_6=true; +} +} +if(!_6){ +if(_8<_b&&e.y>_8&&e.y<_b){ +_6=true; +} +} +if(!_6){ +delete this._cursorToStart; +delete this._savedSelection; +if(e.target.tagName=="BODY"){ +setTimeout(dojo.hitch(this,"placeCursorAtEnd"),0); +} +this.inherited(arguments); +} +},onBeforeActivate:function(e){ +this._restoreSelection(); +},onBeforeDeactivate:function(e){ +if(this.customUndo){ +this.endEditing(true); +} +if(e.target.tagName!="BODY"){ +this._saveSelection(); +} +},customUndo:dojo.isIE||dojo.isWebKit,editActionInterval:3,beginEditing:function(_d){ +if(!this._inEditing){ +this._inEditing=true; +this._beginEditing(_d); +} +if(this.editActionInterval>0){ +if(this._editTimer){ +clearTimeout(this._editTimer); +} +this._editTimer=setTimeout(dojo.hitch(this,this.endEditing),this._editInterval); +} +},_steps:[],_undoedSteps:[],execCommand:function(_e){ +if(this.customUndo&&(_e=="undo"||_e=="redo")){ +return this[_e](); +}else{ +if(this.customUndo){ +this.endEditing(); +this._beginEditing(); +} +var r; +try{ +r=this.inherited("execCommand",arguments); +if(dojo.isWebKit&&_e=="paste"&&!r){ +throw {code:1011}; +} +} +catch(e){ +if(e.code==1011&&/copy|cut|paste/.test(_e)){ +var _f=dojo.string.substitute,_10={cut:"X",copy:"C",paste:"V"}; +alert(_f(this.commands.systemShortcut,[this.commands[_e],_f(this.commands[dojo.isMac?"appleKey":"ctrlKey"],[_10[_e]])])); +} +r=false; +} +if(this.customUndo){ +this._endEditing(); +} +return r; +} +},queryCommandEnabled:function(cmd){ +if(this.customUndo&&(cmd=="undo"||cmd=="redo")){ +return cmd=="undo"?(this._steps.length>1):(this._undoedSteps.length>0); +}else{ +return this.inherited("queryCommandEnabled",arguments); +} +},_moveToBookmark:function(b){ +var _11=b.mark; +var _12=b.mark; +var col=b.isCollapsed; +var r,_13,_14,sel; +if(_12){ +if(dojo.isIE){ +if(dojo.isArray(_12)){ +_11=[]; +dojo.forEach(_12,function(n){ +_11.push(dijit.range.getNode(n,this.editNode)); +},this); +dojo.withGlobal(this.window,"moveToBookmark",dijit,[{mark:_11,isCollapsed:col}]); +}else{ +if(_12.startContainer&&_12.endContainer){ +sel=dijit.range.getSelection(this.window); +if(sel&&sel.removeAllRanges){ +sel.removeAllRanges(); +r=dijit.range.create(this.window); +_13=dijit.range.getNode(_12.startContainer,this.editNode); +_14=dijit.range.getNode(_12.endContainer,this.editNode); +if(_13&&_14){ +r.setStart(_13,_12.startOffset); +r.setEnd(_14,_12.endOffset); +sel.addRange(r); +} +} +} +} +}else{ +sel=dijit.range.getSelection(this.window); +if(sel&&sel.removeAllRanges){ +sel.removeAllRanges(); +r=dijit.range.create(this.window); +_13=dijit.range.getNode(_12.startContainer,this.editNode); +_14=dijit.range.getNode(_12.endContainer,this.editNode); +if(_13&&_14){ +r.setStart(_13,_12.startOffset); +r.setEnd(_14,_12.endOffset); +sel.addRange(r); +} +} +} +} +},_changeToStep:function(_15,to){ +this.setValue(to.text); +var b=to.bookmark; +if(!b){ +return; +} +this._moveToBookmark(b); +},undo:function(){ +var ret=false; +if(!this._undoRedoActive){ +this._undoRedoActive=true; +this.endEditing(true); +var s=this._steps.pop(); +if(s&&this._steps.length>0){ +this.focus(); +this._changeToStep(s,this._steps[this._steps.length-1]); +this._undoedSteps.push(s); +this.onDisplayChanged(); +delete this._undoRedoActive; +ret=true; +} +delete this._undoRedoActive; +} +return ret; +},redo:function(){ +var ret=false; +if(!this._undoRedoActive){ +this._undoRedoActive=true; +this.endEditing(true); +var s=this._undoedSteps.pop(); +if(s&&this._steps.length>0){ +this.focus(); +this._changeToStep(this._steps[this._steps.length-1],s); +this._steps.push(s); +this.onDisplayChanged(); +ret=true; +} +delete this._undoRedoActive; +} +return ret; +},endEditing:function(_16){ +if(this._editTimer){ +clearTimeout(this._editTimer); +} +if(this._inEditing){ +this._endEditing(_16); +this._inEditing=false; +} +},_getBookmark:function(){ +var b=dojo.withGlobal(this.window,dijit.getBookmark); +var tmp=[]; +if(b&&b.mark){ +var _17=b.mark; +if(dojo.isIE){ +var sel=dijit.range.getSelection(this.window); +if(!dojo.isArray(_17)){ +if(sel){ +var _18; +if(sel.rangeCount){ +_18=sel.getRangeAt(0); +} +if(_18){ +b.mark=_18.cloneRange(); +}else{ +b.mark=dojo.withGlobal(this.window,dijit.getBookmark); +} +} +}else{ +dojo.forEach(b.mark,function(n){ +tmp.push(dijit.range.getIndex(n,this.editNode).o); +},this); +b.mark=tmp; +} +} +try{ +if(b.mark&&b.mark.startContainer){ +tmp=dijit.range.getIndex(b.mark.startContainer,this.editNode).o; +b.mark={startContainer:tmp,startOffset:b.mark.startOffset,endContainer:b.mark.endContainer===b.mark.startContainer?tmp:dijit.range.getIndex(b.mark.endContainer,this.editNode).o,endOffset:b.mark.endOffset}; +} +} +catch(e){ +b.mark=null; +} +} +return b; +},_beginEditing:function(cmd){ +if(this._steps.length===0){ +this._steps.push({"text":dijit._editor.getChildrenHtml(this.editNode),"bookmark":this._getBookmark()}); +} +},_endEditing:function(_19){ +var v=dijit._editor.getChildrenHtml(this.editNode); +this._undoedSteps=[]; +this._steps.push({text:v,bookmark:this._getBookmark()}); +},onKeyDown:function(e){ +if(!dojo.isIE&&!this.iframe&&e.keyCode==dojo.keys.TAB&&!this.tabIndent){ +this._saveSelection(); +} +if(!this.customUndo){ +this.inherited(arguments); +return; +} +var k=e.keyCode,ks=dojo.keys; +if(e.ctrlKey&&!e.altKey){ +if(k==90||k==122){ +dojo.stopEvent(e); +this.undo(); +return; +}else{ +if(k==89||k==121){ +dojo.stopEvent(e); +this.redo(); +return; +} +} +} +this.inherited(arguments); +switch(k){ +case ks.ENTER: +case ks.BACKSPACE: +case ks.DELETE: +this.beginEditing(); +break; +case 88: +case 86: +if(e.ctrlKey&&!e.altKey&&!e.metaKey){ +this.endEditing(); +if(e.keyCode==88){ +this.beginEditing("cut"); +setTimeout(dojo.hitch(this,this.endEditing),1); +}else{ +this.beginEditing("paste"); +setTimeout(dojo.hitch(this,this.endEditing),1); +} +break; +} +default: +if(!e.ctrlKey&&!e.altKey&&!e.metaKey&&(e.keyCodedojo.keys.F15)){ +this.beginEditing(); +break; +} +case ks.ALT: +this.endEditing(); +break; +case ks.UP_ARROW: +case ks.DOWN_ARROW: +case ks.LEFT_ARROW: +case ks.RIGHT_ARROW: +case ks.HOME: +case ks.END: +case ks.PAGE_UP: +case ks.PAGE_DOWN: +this.endEditing(true); +break; +case ks.CTRL: +case ks.SHIFT: +case ks.TAB: +break; +} +},_onBlur:function(){ +this.inherited("_onBlur",arguments); +this.endEditing(true); +},_saveSelection:function(){ +this._savedSelection=this._getBookmark(); +},_restoreSelection:function(){ +if(this._savedSelection){ +delete this._cursorToStart; +if(dojo.withGlobal(this.window,"isCollapsed",dijit)){ +this._moveToBookmark(this._savedSelection); +} +delete this._savedSelection; +} +},onClick:function(){ +this.endEditing(true); +this.inherited(arguments); +},_setDisabledAttr:function(_1a){ +if(!this.disabled&&_1a){ +this._buttonEnabledPlugins=dojo.filter(this._plugins,function(p){ +if(p&&p.button&&!p.button.get("disabled")){ +p.button.set("disabled",true); +return true; +} +return false; +}); +}else{ +if(this.disabled&&!_1a){ +dojo.forEach(this._buttonEnabledPlugins,function(p){ +p.button.attr("disabled",false); +p.updateState&&p.updateState(); +}); +} +} +this.inherited(arguments); +},_setStateClass:function(){ +this.inherited(arguments); +if(this.document&&this.document.body){ +dojo.style(this.document.body,"color",dojo.style(this.iframe,"color")); +} +}}); +dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ +if(o.plugin){ +return; +} +var _1b=o.args,p; +var _1c=dijit._editor._Plugin; +var _1d=_1b.name; +switch(_1d){ +case "undo": +case "redo": +case "cut": +case "copy": +case "paste": +case "insertOrderedList": +case "insertUnorderedList": +case "indent": +case "outdent": +case "justifyCenter": +case "justifyFull": +case "justifyLeft": +case "justifyRight": +case "delete": +case "selectAll": +case "removeFormat": +case "unlink": +case "insertHorizontalRule": +p=new _1c({command:_1d}); +break; +case "bold": +case "italic": +case "underline": +case "strikethrough": +case "subscript": +case "superscript": +p=new _1c({buttonClass:dijit.form.ToggleButton,command:_1d}); +break; +case "|": +p=new _1c({button:new dijit.ToolbarSeparator(),setEditor:function(_1e){ +this.editor=_1e; +}}); +} +o.plugin=p; +}); +} diff --git a/lib/dijit/InlineEditBox.js b/lib/dijit/InlineEditBox.js new file mode 100644 index 000000000..5d26498a4 --- /dev/null +++ b/lib/dijit/InlineEditBox.js @@ -0,0 +1,231 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dijit.InlineEditBox"]){ +dojo._hasResource["dijit.InlineEditBox"]=true; +dojo.provide("dijit.InlineEditBox"); +dojo.require("dojo.i18n"); +dojo.require("dijit._Widget"); +dojo.require("dijit._Container"); +dojo.require("dijit.form.Button"); +dojo.require("dijit.form.TextBox"); +dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); +dojo.declare("dijit.InlineEditBox",dijit._Widget,{editing:false,autoSave:true,buttonSave:"",buttonCancel:"",renderAsHtml:false,editor:"dijit.form.TextBox",editorWrapper:"dijit._InlineEditor",editorParams:{},onChange:function(_1){ +},onCancel:function(){ +},width:"100%",value:"",noValueIndicator:dojo.isIE<=6?"    ✍    ":"    ✍    ",constructor:function(){ +this.editorParams={}; +},postMixInProperties:function(){ +this.inherited(arguments); +this.displayNode=this.srcNodeRef; +var _2={ondijitclick:"_onClick",onmouseover:"_onMouseOver",onmouseout:"_onMouseOut",onfocus:"_onMouseOver",onblur:"_onMouseOut"}; +for(var _3 in _2){ +this.connect(this.displayNode,_3,_2[_3]); +} +dijit.setWaiRole(this.displayNode,"button"); +if(!this.displayNode.getAttribute("tabIndex")){ +this.displayNode.setAttribute("tabIndex",0); +} +if(!this.value&&!("value" in this.params)){ +this.value=dojo.trim(this.renderAsHtml?this.displayNode.innerHTML:(this.displayNode.innerText||this.displayNode.textContent||"")); +} +if(!this.value){ +this.displayNode.innerHTML=this.noValueIndicator; +} +dojo.addClass(this.displayNode,"dijitInlineEditBoxDisplayMode"); +},setDisabled:function(_4){ +dojo.deprecated("dijit.InlineEditBox.setDisabled() is deprecated. Use set('disabled', bool) instead.","","2.0"); +this.set("disabled",_4); +},_setDisabledAttr:function(_5){ +this.disabled=_5; +dijit.setWaiState(this.domNode,"disabled",_5); +if(_5){ +this.displayNode.removeAttribute("tabIndex"); +}else{ +this.displayNode.setAttribute("tabIndex",0); +} +dojo.toggleClass(this.displayNode,"dijitInlineEditBoxDisplayModeDisabled",_5); +},_onMouseOver:function(){ +if(!this.disabled){ +dojo.addClass(this.displayNode,"dijitInlineEditBoxDisplayModeHover"); +} +},_onMouseOut:function(){ +dojo.removeClass(this.displayNode,"dijitInlineEditBoxDisplayModeHover"); +},_onClick:function(e){ +if(this.disabled){ +return; +} +if(e){ +dojo.stopEvent(e); +} +this._onMouseOut(); +setTimeout(dojo.hitch(this,"edit"),0); +},edit:function(){ +if(this.disabled||this.editing){ +return; +} +this.editing=true; +this._savedPosition=dojo.style(this.displayNode,"position")||"static"; +this._savedOpacity=dojo.style(this.displayNode,"opacity")||"1"; +this._savedTabIndex=dojo.attr(this.displayNode,"tabIndex")||"0"; +if(this.wrapperWidget){ +var ew=this.wrapperWidget.editWidget; +ew.set("displayedValue" in ew?"displayedValue":"value",this.value); +}else{ +var _6=dojo.create("span",null,this.domNode,"before"); +var _7=dojo.getObject(this.editorWrapper); +this.wrapperWidget=new _7({value:this.value,buttonSave:this.buttonSave,buttonCancel:this.buttonCancel,dir:this.dir,lang:this.lang,tabIndex:this._savedTabIndex,editor:this.editor,inlineEditBox:this,sourceStyle:dojo.getComputedStyle(this.displayNode),save:dojo.hitch(this,"save"),cancel:dojo.hitch(this,"cancel")},_6); +} +var ww=this.wrapperWidget; +if(dojo.isIE){ +dijit.focus(dijit.getFocus()); +} +dojo.style(this.displayNode,{position:"absolute",opacity:"0",display:"none"}); +dojo.style(ww.domNode,{position:this._savedPosition,visibility:"visible",opacity:"1"}); +dojo.attr(this.displayNode,"tabIndex","-1"); +setTimeout(dojo.hitch(this,function(){ +ww.focus(); +ww._resetValue=ww.getValue(); +}),0); +},_onBlur:function(){ +this.inherited(arguments); +if(!this.editing){ +} +},destroy:function(){ +if(this.wrapperWidget){ +this.wrapperWidget.destroy(); +delete this.wrapperWidget; +} +this.inherited(arguments); +},_showText:function(_8){ +var ww=this.wrapperWidget; +dojo.style(ww.domNode,{position:"absolute",visibility:"hidden",opacity:"0"}); +dojo.style(this.displayNode,{position:this._savedPosition,opacity:this._savedOpacity,display:""}); +dojo.attr(this.displayNode,"tabIndex",this._savedTabIndex); +if(_8){ +dijit.focus(this.displayNode); +} +},save:function(_9){ +if(this.disabled||!this.editing){ +return; +} +this.editing=false; +var ww=this.wrapperWidget; +var _a=ww.getValue(); +this.set("value",_a); +setTimeout(dojo.hitch(this,"onChange",_a),0); +this._showText(_9); +},setValue:function(_b){ +dojo.deprecated("dijit.InlineEditBox.setValue() is deprecated. Use set('value', ...) instead.","","2.0"); +return this.set("value",_b); +},_setValueAttr:function(_c){ +this.value=_c=dojo.trim(_c); +if(!this.renderAsHtml){ +_c=_c.replace(/&/gm,"&").replace(//gm,">").replace(/"/gm,""").replace(/\n/g,"
"); +} +this.displayNode.innerHTML=_c||this.noValueIndicator; +},getValue:function(){ +dojo.deprecated("dijit.InlineEditBox.getValue() is deprecated. Use get('value') instead.","","2.0"); +return this.get("value"); +},cancel:function(_d){ +if(this.disabled||!this.editing){ +return; +} +this.editing=false; +setTimeout(dojo.hitch(this,"onCancel"),0); +this._showText(_d); +}}); +dojo.declare("dijit._InlineEditor",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit","templates/InlineEditBox.html","', + // parse: true, + // text: "Send" + // }); + content = this._normalize(content, this[0]); + for(var i = 0, node; node = this[i]; i++){ + this._place(content, node, position, i > 0); + } + return this; //dojo.NodeList + }, + + instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){ + // summary: + // Create a new instance of a specified class, using the + // specified properties and each node in the nodeList as a + // srcNodeRef. + // example: + // Grabs all buttons in the page and converts them to diji.form.Buttons. + // | var buttons = dojo.query("button").instantiate("dijit.form.Button", {showLabel: true}); + var c = d.isFunction(declaredClass) ? declaredClass : d.getObject(declaredClass); + properties = properties || {}; + return this.forEach(function(node){ + new c(properties, node); + }); // dojo.NodeList + }, + + at: function(/*===== index =====*/){ + // summary: + // Returns a new NodeList comprised of items in this NodeList + // at the given index or indices. + // + // index: Integer... + // One or more 0-based indices of items in the current + // NodeList. A negative index will start at the end of the + // list and go backwards. + // + // example: + // Shorten the list to the first, second, and third elements + // | dojo.query("a").at(0, 1, 2).forEach(fn); + // + // example: + // Retrieve the first and last elements of a unordered list: + // | dojo.query("ul > li").at(0, -1).forEach(cb); + // + // example: + // Do something for the first element only, but end() out back to + // the original list and continue chaining: + // | dojo.query("a").at(0).onclick(fn).end().forEach(function(n){ + // | console.log(n); // all anchors on the page. + // | }) + // + // returns: + // dojo.NodeList + var t = new this._NodeListCtor(); + d.forEach(arguments, function(i){ + if(i < 0){ i = this.length + i } + if(this[i]){ t.push(this[i]); } + }, this); + return t._stash(this); // dojo.NodeList + } + + }); + + nl.events = [ + // summary: list of all DOM events used in NodeList + "blur", "focus", "change", "click", "error", "keydown", "keypress", + "keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove", + "mouseout", "mouseover", "mouseup", "submit" + ]; + + // FIXME: pseudo-doc the above automatically generated on-event functions + + // syntactic sugar for DOM events + d.forEach(nl.events, function(evt){ + var _oe = "on" + evt; + nlp[_oe] = function(a, b){ + return this.connect(_oe, a, b); + } + // FIXME: should these events trigger publishes? + /* + return (a ? this.connect(_oe, a, b) : + this.forEach(function(n){ + // FIXME: + // listeners get buried by + // addEventListener and can't be dug back + // out to be triggered externally. + // see: + // http://developer.mozilla.org/en/docs/DOM:element + + console.log(n, evt, _oe); + + // FIXME: need synthetic event support! + var _e = { target: n, faux: true, type: evt }; + // dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt }); + try{ n[evt](_e); }catch(e){ console.log(e); } + try{ n[_oe](_e); }catch(e){ console.log(e); } + }) + ); + */ + } + ); + +})(); + +} + +if(!dojo._hasResource["dojo._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base.query"] = true; +if(typeof dojo != "undefined"){ + dojo.provide("dojo._base.query"); + + + +} + +/* + dojo.query() architectural overview: + + dojo.query is a relatively full-featured CSS3 query library. It is + designed to take any valid CSS3 selector and return the nodes matching + the selector. To do this quickly, it processes queries in several + steps, applying caching where profitable. + + The steps (roughly in reverse order of the way they appear in the code): + 1.) check to see if we already have a "query dispatcher" + - if so, use that with the given parameterization. Skip to step 4. + 2.) attempt to determine which branch to dispatch the query to: + - JS (optimized DOM iteration) + - native (FF3.1+, Safari 3.1+, IE 8+) + 3.) tokenize and convert to executable "query dispatcher" + - this is where the lion's share of the complexity in the + system lies. In the DOM version, the query dispatcher is + assembled as a chain of "yes/no" test functions pertaining to + a section of a simple query statement (".blah:nth-child(odd)" + but not "div div", which is 2 simple statements). Individual + statement dispatchers are cached (to prevent re-definition) + as are entire dispatch chains (to make re-execution of the + same query fast) + 4.) the resulting query dispatcher is called in the passed scope + (by default the top-level document) + - for DOM queries, this results in a recursive, top-down + evaluation of nodes based on each simple query section + - for native implementations, this may mean working around spec + bugs. So be it. + 5.) matched nodes are pruned to ensure they are unique (if necessary) +*/ + +;(function(d){ + // define everything in a closure for compressability reasons. "d" is an + // alias to "dojo" (or the toolkit alias object, e.g., "acme"). + + //////////////////////////////////////////////////////////////////////// + // Toolkit aliases + //////////////////////////////////////////////////////////////////////// + + // if you are extracing dojo.query for use in your own system, you will + // need to provide these methods and properties. No other porting should be + // necessary, save for configuring the system to use a class other than + // dojo.NodeList as the return instance instantiator + var trim = d.trim; + var each = d.forEach; + // d.isIE; // float + // d.isSafari; // float + // d.isOpera; // float + // d.isWebKit; // float + // d.doc ; // document element + var qlc = d._NodeListCtor = d.NodeList; + + var getDoc = function(){ return d.doc; }; + // NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo + var cssCaseBug = ((d.isWebKit||d.isMozilla) && ((getDoc().compatMode) == "BackCompat")); + + //////////////////////////////////////////////////////////////////////// + // Global utilities + //////////////////////////////////////////////////////////////////////// + + + // on browsers that support the "children" collection we can avoid a lot of + // iteration on chaff (non-element) nodes. + // why. + var childNodesName = !!getDoc().firstChild["children"] ? "children" : "childNodes"; + + var specials = ">~+"; + + // global thunk to determine whether we should treat the current query as + // case sensitive or not. This switch is flipped by the query evaluator + // based on the document passed as the context to search. + var caseSensitive = false; + + // how high? + var yesman = function(){ return true; }; + + //////////////////////////////////////////////////////////////////////// + // Tokenizer + //////////////////////////////////////////////////////////////////////// + + var getQueryParts = function(query){ + // summary: + // state machine for query tokenization + // description: + // instead of using a brittle and slow regex-based CSS parser, + // dojo.query implements an AST-style query representation. This + // representation is only generated once per query. For example, + // the same query run multiple times or under different root nodes + // does not re-parse the selector expression but instead uses the + // cached data structure. The state machine implemented here + // terminates on the last " " (space) charachter and returns an + // ordered array of query component structures (or "parts"). Each + // part represents an operator or a simple CSS filtering + // expression. The structure for parts is documented in the code + // below. + + + // NOTE: + // this code is designed to run fast and compress well. Sacrifices + // to readibility and maintainability have been made. Your best + // bet when hacking the tokenizer is to put The Donnas on *really* + // loud (may we recommend their "Spend The Night" release?) and + // just assume you're gonna make mistakes. Keep the unit tests + // open and run them frequently. Knowing is half the battle ;-) + if(specials.indexOf(query.slice(-1)) >= 0){ + // if we end with a ">", "+", or "~", that means we're implicitly + // searching all children, so make it explicit + query += " * " + }else{ + // if you have not provided a terminator, one will be provided for + // you... + query += " "; + } + + var ts = function(/*Integer*/ s, /*Integer*/ e){ + // trim and slice. + + // take an index to start a string slice from and an end position + // and return a trimmed copy of that sub-string + return trim(query.slice(s, e)); + } + + // the overall data graph of the full query, as represented by queryPart objects + var queryParts = []; + + + // state keeping vars + var inBrackets = -1, inParens = -1, inMatchFor = -1, + inPseudo = -1, inClass = -1, inId = -1, inTag = -1, + lc = "", cc = "", pStart; + + // iteration vars + var x = 0, // index in the query + ql = query.length, + currentPart = null, // data structure representing the entire clause + _cp = null; // the current pseudo or attr matcher + + // several temporary variables are assigned to this structure durring a + // potential sub-expression match: + // attr: + // a string representing the current full attribute match in a + // bracket expression + // type: + // if there's an operator in a bracket expression, this is + // used to keep track of it + // value: + // the internals of parenthetical expression for a pseudo. for + // :nth-child(2n+1), value might be "2n+1" + + var endTag = function(){ + // called when the tokenizer hits the end of a particular tag name. + // Re-sets state variables for tag matching and sets up the matcher + // to handle the next type of token (tag or operator). + if(inTag >= 0){ + var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase(); + currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv; + inTag = -1; + } + } + + var endId = function(){ + // called when the tokenizer might be at the end of an ID portion of a match + if(inId >= 0){ + currentPart.id = ts(inId, x).replace(/\\/g, ""); + inId = -1; + } + } + + var endClass = function(){ + // called when the tokenizer might be at the end of a class name + // match. CSS allows for multiple classes, so we augment the + // current item with another class in its list + if(inClass >= 0){ + currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, "")); + inClass = -1; + } + } + + var endAll = function(){ + // at the end of a simple fragment, so wall off the matches + endId(); endTag(); endClass(); + } + + var endPart = function(){ + endAll(); + if(inPseudo >= 0){ + currentPart.pseudos.push({ name: ts(inPseudo+1, x) }); + } + // hint to the selector engine to tell it whether or not it + // needs to do any iteration. Many simple selectors don't, and + // we can avoid significant construction-time work by advising + // the system to skip them + currentPart.loops = ( + currentPart.pseudos.length || + currentPart.attrs.length || + currentPart.classes.length ); + + currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string + + + // otag/tag are hints to suggest to the system whether or not + // it's an operator or a tag. We save a copy of otag since the + // tag name is cast to upper-case in regular HTML matches. The + // system has a global switch to figure out if the current + // expression needs to be case sensitive or not and it will use + // otag or tag accordingly + currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*"); + + if(currentPart.tag){ + // if we're in a case-insensitive HTML doc, we likely want + // the toUpperCase when matching on element.tagName. If we + // do it here, we can skip the string op per node + // comparison + currentPart.tag = currentPart.tag.toUpperCase(); + } + + // add the part to the list + if(queryParts.length && (queryParts[queryParts.length-1].oper)){ + // operators are always infix, so we remove them from the + // list and attach them to the next match. The evaluator is + // responsible for sorting out how to handle them. + currentPart.infixOper = queryParts.pop(); + currentPart.query = currentPart.infixOper.query + " " + currentPart.query; + /* + console.debug( "swapping out the infix", + currentPart.infixOper, + "and attaching it to", + currentPart); + */ + } + queryParts.push(currentPart); + + currentPart = null; + } + + // iterate over the query, charachter by charachter, building up a + // list of query part objects + for(; lc=cc, cc=query.charAt(x), x < ql; x++){ + // cc: the current character in the match + // lc: the last charachter (if any) + + // someone is trying to escape something, so don't try to match any + // fragments. We assume we're inside a literal. + if(lc == "\\"){ continue; } + if(!currentPart){ // a part was just ended or none has yet been created + // NOTE: I hate all this alloc, but it's shorter than writing tons of if's + pStart = x; + // rules describe full CSS sub-expressions, like: + // #someId + // .className:first-child + // but not: + // thinger > div.howdy[type=thinger] + // the indidual components of the previous query would be + // split into 3 parts that would be represented a structure + // like: + // [ + // { + // query: "thinger", + // tag: "thinger", + // }, + // { + // query: "div.howdy[type=thinger]", + // classes: ["howdy"], + // infixOper: { + // query: ">", + // oper: ">", + // } + // }, + // ] + currentPart = { + query: null, // the full text of the part's rule + pseudos: [], // CSS supports multiple pseud-class matches in a single rule + attrs: [], // CSS supports multi-attribute match, so we need an array + classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy + tag: null, // only one tag... + oper: null, // ...or operator per component. Note that these wind up being exclusive. + id: null, // the id component of a rule + getTag: function(){ + return (caseSensitive) ? this.otag : this.tag; + } + }; + + // if we don't have a part, we assume we're going to start at + // the beginning of a match, which should be a tag name. This + // might fault a little later on, but we detect that and this + // iteration will still be fine. + inTag = x; + } + + if(inBrackets >= 0){ + // look for a the close first + if(cc == "]"){ // if we're in a [...] clause and we end, do assignment + if(!_cp.attr){ + // no attribute match was previously begun, so we + // assume this is an attribute existance match in the + // form of [someAttributeName] + _cp.attr = ts(inBrackets+1, x); + }else{ + // we had an attribute already, so we know that we're + // matching some sort of value, as in [attrName=howdy] + _cp.matchFor = ts((inMatchFor||inBrackets+1), x); + } + var cmf = _cp.matchFor; + if(cmf){ + // try to strip quotes from the matchFor value. We want + // [attrName=howdy] to match the same + // as [attrName = 'howdy' ] + if( (cmf.charAt(0) == '"') || (cmf.charAt(0) == "'") ){ + _cp.matchFor = cmf.slice(1, -1); + } + } + // end the attribute by adding it to the list of attributes. + currentPart.attrs.push(_cp); + _cp = null; // necessary? + inBrackets = inMatchFor = -1; + }else if(cc == "="){ + // if the last char was an operator prefix, make sure we + // record it along with the "=" operator. + var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : ""; + _cp.type = addToCc+cc; + _cp.attr = ts(inBrackets+1, x-addToCc.length); + inMatchFor = x+1; + } + // now look for other clause parts + }else if(inParens >= 0){ + // if we're in a parenthetical expression, we need to figure + // out if it's attached to a pseduo-selector rule like + // :nth-child(1) + if(cc == ")"){ + if(inPseudo >= 0){ + _cp.value = ts(inParens+1, x); + } + inPseudo = inParens = -1; + } + }else if(cc == "#"){ + // start of an ID match + endAll(); + inId = x+1; + }else if(cc == "."){ + // start of a class match + endAll(); + inClass = x; + }else if(cc == ":"){ + // start of a pseudo-selector match + endAll(); + inPseudo = x; + }else if(cc == "["){ + // start of an attribute match. + endAll(); + inBrackets = x; + // provide a new structure for the attribute match to fill-in + _cp = { + /*===== + attr: null, type: null, matchFor: null + =====*/ + }; + }else if(cc == "("){ + // we really only care if we've entered a parenthetical + // expression if we're already inside a pseudo-selector match + if(inPseudo >= 0){ + // provide a new structure for the pseudo match to fill-in + _cp = { + name: ts(inPseudo+1, x), + value: null + } + currentPart.pseudos.push(_cp); + } + inParens = x; + }else if( + (cc == " ") && + // if it's a space char and the last char is too, consume the + // current one without doing more work + (lc != cc) + ){ + endPart(); + } + } + return queryParts; + }; + + + //////////////////////////////////////////////////////////////////////// + // DOM query infrastructure + //////////////////////////////////////////////////////////////////////// + + var agree = function(first, second){ + // the basic building block of the yes/no chaining system. agree(f1, + // f2) generates a new function which returns the boolean results of + // both of the passed functions to a single logical-anded result. If + // either are not possed, the other is used exclusively. + if(!first){ return second; } + if(!second){ return first; } + + return function(){ + return first.apply(window, arguments) && second.apply(window, arguments); + } + }; + + var getArr = function(i, arr){ + // helps us avoid array alloc when we don't need it + var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ? + if(i){ r.push(i); } + return r; + }; + + var _isElement = function(n){ return (1 == n.nodeType); }; + + // FIXME: need to coalesce _getAttr with defaultGetter + var blank = ""; + var _getAttr = function(elem, attr){ + if(!elem){ return blank; } + if(attr == "class"){ + return elem.className || blank; + } + if(attr == "for"){ + return elem.htmlFor || blank; + } + if(attr == "style"){ + return elem.style.cssText || blank; + } + return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank; + }; + + var attrs = { + "*=": function(attr, value){ + return function(elem){ + // E[foo*="bar"] + // an E element whose "foo" attribute value contains + // the substring "bar" + return (_getAttr(elem, attr).indexOf(value)>=0); + } + }, + "^=": function(attr, value){ + // E[foo^="bar"] + // an E element whose "foo" attribute value begins exactly + // with the string "bar" + return function(elem){ + return (_getAttr(elem, attr).indexOf(value)==0); + } + }, + "$=": function(attr, value){ + // E[foo$="bar"] + // an E element whose "foo" attribute value ends exactly + // with the string "bar" + var tval = " "+value; + return function(elem){ + var ea = " "+_getAttr(elem, attr); + return (ea.lastIndexOf(value)==(ea.length-value.length)); + } + }, + "~=": function(attr, value){ + // E[foo~="bar"] + // an E element whose "foo" attribute value is a list of + // space-separated values, one of which is exactly equal + // to "bar" + + // return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]"; + var tval = " "+value+" "; + return function(elem){ + var ea = " "+_getAttr(elem, attr)+" "; + return (ea.indexOf(tval)>=0); + } + }, + "|=": function(attr, value){ + // E[hreflang|="en"] + // an E element whose "hreflang" attribute has a + // hyphen-separated list of values beginning (from the + // left) with "en" + var valueDash = " "+value+"-"; + return function(elem){ + var ea = " "+_getAttr(elem, attr); + return ( + (ea == value) || + (ea.indexOf(valueDash)==0) + ); + } + }, + "=": function(attr, value){ + return function(elem){ + return (_getAttr(elem, attr) == value); + } + } + }; + + // avoid testing for node type if we can. Defining this in the negative + // here to avoid negation in the fast path. + var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined"); + var _ns = !_noNES ? "nextElementSibling" : "nextSibling"; + var _ps = !_noNES ? "previousElementSibling" : "previousSibling"; + var _simpleNodeTest = (_noNES ? _isElement : yesman); + + var _lookLeft = function(node){ + // look left + while(node = node[_ps]){ + if(_simpleNodeTest(node)){ return false; } + } + return true; + }; + + var _lookRight = function(node){ + // look right + while(node = node[_ns]){ + if(_simpleNodeTest(node)){ return false; } + } + return true; + }; + + var getNodeIndex = function(node){ + var root = node.parentNode; + var i = 0, + tret = root[childNodesName], + ci = (node["_i"]||-1), + cl = (root["_l"]||-1); + + if(!tret){ return -1; } + var l = tret.length; + + // we calcuate the parent length as a cheap way to invalidate the + // cache. It's not 100% accurate, but it's much more honest than what + // other libraries do + if( cl == l && ci >= 0 && cl >= 0 ){ + // if it's legit, tag and release + return ci; + } + + // else re-key things + root["_l"] = l; + ci = -1; + for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){ + if(_simpleNodeTest(te)){ + te["_i"] = ++i; + if(node === te){ + // NOTE: + // shortcuting the return at this step in indexing works + // very well for benchmarking but we avoid it here since + // it leads to potential O(n^2) behavior in sequential + // getNodexIndex operations on a previously un-indexed + // parent. We may revisit this at a later time, but for + // now we just want to get the right answer more often + // than not. + ci = i; + } + } + } + return ci; + }; + + var isEven = function(elem){ + return !((getNodeIndex(elem)) % 2); + }; + + var isOdd = function(elem){ + return ((getNodeIndex(elem)) % 2); + }; + + var pseudos = { + "checked": function(name, condition){ + return function(elem){ + return !!("checked" in elem ? elem.checked : elem.selected); + } + }, + "first-child": function(){ return _lookLeft; }, + "last-child": function(){ return _lookRight; }, + "only-child": function(name, condition){ + return function(node){ + if(!_lookLeft(node)){ return false; } + if(!_lookRight(node)){ return false; } + return true; + }; + }, + "empty": function(name, condition){ + return function(elem){ + // DomQuery and jQuery get this wrong, oddly enough. + // The CSS 3 selectors spec is pretty explicit about it, too. + var cn = elem.childNodes; + var cnl = elem.childNodes.length; + // if(!cnl){ return true; } + for(var x=cnl-1; x >= 0; x--){ + var nt = cn[x].nodeType; + if((nt === 1)||(nt == 3)){ return false; } + } + return true; + } + }, + "contains": function(name, condition){ + var cz = condition.charAt(0); + if( cz == '"' || cz == "'" ){ //remove quote + condition = condition.slice(1, -1); + } + return function(elem){ + return (elem.innerHTML.indexOf(condition) >= 0); + } + }, + "not": function(name, condition){ + var p = getQueryParts(condition)[0]; + var ignores = { el: 1 }; + if(p.tag != "*"){ + ignores.tag = 1; + } + if(!p.classes.length){ + ignores.classes = 1; + } + var ntf = getSimpleFilterFunc(p, ignores); + return function(elem){ + return (!ntf(elem)); + } + }, + "nth-child": function(name, condition){ + var pi = parseInt; + // avoid re-defining function objects if we can + if(condition == "odd"){ + return isOdd; + }else if(condition == "even"){ + return isEven; + } + // FIXME: can we shorten this? + if(condition.indexOf("n") != -1){ + var tparts = condition.split("n", 2); + var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1; + var idx = tparts[1] ? pi(tparts[1]) : 0; + var lb = 0, ub = -1; + if(pred > 0){ + if(idx < 0){ + idx = (idx % pred) && (pred + (idx % pred)); + }else if(idx>0){ + if(idx >= pred){ + lb = idx - idx % pred; + } + idx = idx % pred; + } + }else if(pred<0){ + pred *= -1; + // idx has to be greater than 0 when pred is negative; + // shall we throw an error here? + if(idx > 0){ + ub = idx; + idx = idx % pred; + } + } + if(pred > 0){ + return function(elem){ + var i = getNodeIndex(elem); + return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx); + } + }else{ + condition = idx; + } + } + var ncount = pi(condition); + return function(elem){ + return (getNodeIndex(elem) == ncount); + } + } + }; + + var defaultGetter = (d.isIE) ? function(cond){ + var clc = cond.toLowerCase(); + if(clc == "class"){ cond = "className"; } + return function(elem){ + return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]); + } + } : function(cond){ + return function(elem){ + return (elem && elem.getAttribute && elem.hasAttribute(cond)); + } + }; + + var getSimpleFilterFunc = function(query, ignores){ + // generates a node tester function based on the passed query part. The + // query part is one of the structures generatd by the query parser + // when it creates the query AST. The "ignores" object specifies which + // (if any) tests to skip, allowing the system to avoid duplicating + // work where it may have already been taken into account by other + // factors such as how the nodes to test were fetched in the first + // place + if(!query){ return yesman; } + ignores = ignores||{}; + + var ff = null; + + if(!("el" in ignores)){ + ff = agree(ff, _isElement); + } + + if(!("tag" in ignores)){ + if(query.tag != "*"){ + ff = agree(ff, function(elem){ + return (elem && (elem.tagName == query.getTag())); + }); + } + } + + if(!("classes" in ignores)){ + each(query.classes, function(cname, idx, arr){ + // get the class name + /* + var isWildcard = cname.charAt(cname.length-1) == "*"; + if(isWildcard){ + cname = cname.substr(0, cname.length-1); + } + // I dislike the regex thing, even if memozied in a cache, but it's VERY short + var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)"); + */ + var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)"); + ff = agree(ff, function(elem){ + return re.test(elem.className); + }); + ff.count = idx; + }); + } + + if(!("pseudos" in ignores)){ + each(query.pseudos, function(pseudo){ + var pn = pseudo.name; + if(pseudos[pn]){ + ff = agree(ff, pseudos[pn](pn, pseudo.value)); + } + }); + } + + if(!("attrs" in ignores)){ + each(query.attrs, function(attr){ + var matcher; + var a = attr.attr; + // type, attr, matchFor + if(attr.type && attrs[attr.type]){ + matcher = attrs[attr.type](a, attr.matchFor); + }else if(a.length){ + matcher = defaultGetter(a); + } + if(matcher){ + ff = agree(ff, matcher); + } + }); + } + + if(!("id" in ignores)){ + if(query.id){ + ff = agree(ff, function(elem){ + return (!!elem && (elem.id == query.id)); + }); + } + } + + if(!ff){ + if(!("default" in ignores)){ + ff = yesman; + } + } + return ff; + }; + + var _nextSibling = function(filterFunc){ + return function(node, ret, bag){ + while(node = node[_ns]){ + if(_noNES && (!_isElement(node))){ continue; } + if( + (!bag || _isUnique(node, bag)) && + filterFunc(node) + ){ + ret.push(node); + } + break; + } + return ret; + } + }; + + var _nextSiblings = function(filterFunc){ + return function(root, ret, bag){ + var te = root[_ns]; + while(te){ + if(_simpleNodeTest(te)){ + if(bag && !_isUnique(te, bag)){ + break; + } + if(filterFunc(te)){ + ret.push(te); + } + } + te = te[_ns]; + } + return ret; + } + }; + + // get an array of child *elements*, skipping text and comment nodes + var _childElements = function(filterFunc){ + filterFunc = filterFunc||yesman; + return function(root, ret, bag){ + // get an array of child elements, skipping text and comment nodes + var te, x = 0, tret = root[childNodesName]; + while(te = tret[x++]){ + if( + _simpleNodeTest(te) && + (!bag || _isUnique(te, bag)) && + (filterFunc(te, x)) + ){ + ret.push(te); + } + } + return ret; + }; + }; + + /* + // thanks, Dean! + var itemIsAfterRoot = d.isIE ? function(item, root){ + return (item.sourceIndex > root.sourceIndex); + } : function(item, root){ + return (item.compareDocumentPosition(root) == 2); + }; + */ + + // test to see if node is below root + var _isDescendant = function(node, root){ + var pn = node.parentNode; + while(pn){ + if(pn == root){ + break; + } + pn = pn.parentNode; + } + return !!pn; + }; + + var _getElementsFuncCache = {}; + + var getElementsFunc = function(query){ + var retFunc = _getElementsFuncCache[query.query]; + // if we've got a cached dispatcher, just use that + if(retFunc){ return retFunc; } + // else, generate a new on + + // NOTE: + // this function returns a function that searches for nodes and + // filters them. The search may be specialized by infix operators + // (">", "~", or "+") else it will default to searching all + // descendants (the " " selector). Once a group of children is + // founde, a test function is applied to weed out the ones we + // don't want. Many common cases can be fast-pathed. We spend a + // lot of cycles to create a dispatcher that doesn't do more work + // than necessary at any point since, unlike this function, the + // dispatchers will be called every time. The logic of generating + // efficient dispatchers looks like this in pseudo code: + // + // # if it's a purely descendant query (no ">", "+", or "~" modifiers) + // if infixOperator == " ": + // if only(id): + // return def(root): + // return d.byId(id, root); + // + // elif id: + // return def(root): + // return filter(d.byId(id, root)); + // + // elif cssClass && getElementsByClassName: + // return def(root): + // return filter(root.getElementsByClassName(cssClass)); + // + // elif only(tag): + // return def(root): + // return root.getElementsByTagName(tagName); + // + // else: + // # search by tag name, then filter + // return def(root): + // return filter(root.getElementsByTagName(tagName||"*")); + // + // elif infixOperator == ">": + // # search direct children + // return def(root): + // return filter(root.children); + // + // elif infixOperator == "+": + // # search next sibling + // return def(root): + // return filter(root.nextElementSibling); + // + // elif infixOperator == "~": + // # search rightward siblings + // return def(root): + // return filter(nextSiblings(root)); + + var io = query.infixOper; + var oper = (io ? io.oper : ""); + // the default filter func which tests for all conditions in the query + // part. This is potentially inefficient, so some optimized paths may + // re-define it to test fewer things. + var filterFunc = getSimpleFilterFunc(query, { el: 1 }); + var qt = query.tag; + var wildcardTag = ("*" == qt); + var ecs = getDoc()["getElementsByClassName"]; + + if(!oper){ + // if there's no infix operator, then it's a descendant query. ID + // and "elements by class name" variants can be accelerated so we + // call them out explicitly: + if(query.id){ + // testing shows that the overhead of yesman() is acceptable + // and can save us some bytes vs. re-defining the function + // everywhere. + filterFunc = (!query.loops && wildcardTag) ? + yesman : + getSimpleFilterFunc(query, { el: 1, id: 1 }); + + retFunc = function(root, arr){ + var te = d.byId(query.id, (root.ownerDocument||root)); + if(!te || !filterFunc(te)){ return; } + if(9 == root.nodeType){ // if root's a doc, we just return directly + return getArr(te, arr); + }else{ // otherwise check ancestry + if(_isDescendant(te, root)){ + return getArr(te, arr); + } + } + } + }else if( + ecs && + // isAlien check. Workaround for Prototype.js being totally evil/dumb. + /\{\s*\[native code\]\s*\}/.test(String(ecs)) && + query.classes.length && + !cssCaseBug + ){ + // it's a class-based query and we've got a fast way to run it. + + // ignore class and ID filters since we will have handled both + filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 }); + var classesString = query.classes.join(" "); + retFunc = function(root, arr, bag){ + var ret = getArr(0, arr), te, x=0; + var tret = root.getElementsByClassName(classesString); + while((te = tret[x++])){ + if(filterFunc(te, root) && _isUnique(te, bag)){ + ret.push(te); + } + } + return ret; + }; + + }else if(!wildcardTag && !query.loops){ + // it's tag only. Fast-path it. + retFunc = function(root, arr, bag){ + var ret = getArr(0, arr), te, x=0; + var tret = root.getElementsByTagName(query.getTag()); + while((te = tret[x++])){ + if(_isUnique(te, bag)){ + ret.push(te); + } + } + return ret; + }; + }else{ + // the common case: + // a descendant selector without a fast path. By now it's got + // to have a tag selector, even if it's just "*" so we query + // by that and filter + filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 }); + retFunc = function(root, arr, bag){ + var ret = getArr(0, arr), te, x=0; + // we use getTag() to avoid case sensitivity issues + var tret = root.getElementsByTagName(query.getTag()); + while((te = tret[x++])){ + if(filterFunc(te, root) && _isUnique(te, bag)){ + ret.push(te); + } + } + return ret; + }; + } + }else{ + // the query is scoped in some way. Instead of querying by tag we + // use some other collection to find candidate nodes + var skipFilters = { el: 1 }; + if(wildcardTag){ + skipFilters.tag = 1; + } + filterFunc = getSimpleFilterFunc(query, skipFilters); + if("+" == oper){ + retFunc = _nextSibling(filterFunc); + }else if("~" == oper){ + retFunc = _nextSiblings(filterFunc); + }else if(">" == oper){ + retFunc = _childElements(filterFunc); + } + } + // cache it and return + return _getElementsFuncCache[query.query] = retFunc; + }; + + var filterDown = function(root, queryParts){ + // NOTE: + // this is the guts of the DOM query system. It takes a list of + // parsed query parts and a root and finds children which match + // the selector represented by the parts + var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret; + + for(var i = 0; i < qpl; i++){ + ret = []; + qp = queryParts[i]; + x = candidates.length - 1; + if(x > 0){ + // if we have more than one root at this level, provide a new + // hash to use for checking group membership but tell the + // system not to post-filter us since we will already have been + // gauranteed to be unique + bag = {}; + ret.nozip = true; + } + var gef = getElementsFunc(qp); + for(var j = 0; (te = candidates[j]); j++){ + // for every root, get the elements that match the descendant + // selector, adding them to the "ret" array and filtering them + // via membership in this level's bag. If there are more query + // parts, then this level's return will be used as the next + // level's candidates + gef(te, ret, bag); + } + if(!ret.length){ break; } + candidates = ret; + } + return ret; + }; + + //////////////////////////////////////////////////////////////////////// + // the query runner + //////////////////////////////////////////////////////////////////////// + + // these are the primary caches for full-query results. The query + // dispatcher functions are generated then stored here for hash lookup in + // the future + var _queryFuncCacheDOM = {}, + _queryFuncCacheQSA = {}; + + // this is the second level of spliting, from full-length queries (e.g., + // "div.foo .bar") into simple query expressions (e.g., ["div.foo", + // ".bar"]) + var getStepQueryFunc = function(query){ + var qparts = getQueryParts(trim(query)); + + // if it's trivial, avoid iteration and zipping costs + if(qparts.length == 1){ + // we optimize this case here to prevent dispatch further down the + // chain, potentially slowing things down. We could more elegantly + // handle this in filterDown(), but it's slower for simple things + // that need to be fast (e.g., "#someId"). + var tef = getElementsFunc(qparts[0]); + return function(root){ + var r = tef(root, new qlc()); + if(r){ r.nozip = true; } + return r; + } + } + + // otherwise, break it up and return a runner that iterates over the parts recursively + return function(root){ + return filterDown(root, qparts); + } + }; + + // NOTES: + // * we can't trust QSA for anything but document-rooted queries, so + // caching is split into DOM query evaluators and QSA query evaluators + // * caching query results is dirty and leak-prone (or, at a minimum, + // prone to unbounded growth). Other toolkits may go this route, but + // they totally destroy their own ability to manage their memory + // footprint. If we implement it, it should only ever be with a fixed + // total element reference # limit and an LRU-style algorithm since JS + // has no weakref support. Caching compiled query evaluators is also + // potentially problematic, but even on large documents the size of the + // query evaluators is often < 100 function objects per evaluator (and + // LRU can be applied if it's ever shown to be an issue). + // * since IE's QSA support is currently only for HTML documents and even + // then only in IE 8's "standards mode", we have to detect our dispatch + // route at query time and keep 2 separate caches. Ugg. + + // we need to determine if we think we can run a given query via + // querySelectorAll or if we'll need to fall back on DOM queries to get + // there. We need a lot of information about the environment and the query + // to make the determiniation (e.g. does it support QSA, does the query in + // question work in the native QSA impl, etc.). + var nua = navigator.userAgent; + // some versions of Safari provided QSA, but it was buggy and crash-prone. + // We need te detect the right "internal" webkit version to make this work. + var wk = "WebKit/"; + var is525 = ( + d.isWebKit && + (nua.indexOf(wk) > 0) && + (parseFloat(nua.split(wk)[1]) > 528) + ); + + // IE QSA queries may incorrectly include comment nodes, so we throw the + // zipping function into "remove" comments mode instead of the normal "skip + // it" which every other QSA-clued browser enjoys + var noZip = d.isIE ? "commentStrip" : "nozip"; + + var qsa = "querySelectorAll"; + var qsaAvail = ( + !!getDoc()[qsa] && + // see #5832 + (!d.isSafari || (d.isSafari > 3.1) || is525 ) + ); + + //Don't bother with n+3 type of matches, IE complains if we modify those. + var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g; + var infixSpaceFunc = function(match, pre, ch, post) { + return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match; + }; + + var getQueryFunc = function(query, forceDOM){ + //Normalize query. The CSS3 selectors spec allows for omitting spaces around + //infix operators, >, ~ and + + //Do the work here since detection for spaces is used as a simple "not use QSA" + //test below. + query = query.replace(infixSpaceRe, infixSpaceFunc); + + if(qsaAvail){ + // if we've got a cached variant and we think we can do it, run it! + var qsaCached = _queryFuncCacheQSA[query]; + if(qsaCached && !forceDOM){ return qsaCached; } + } + + // else if we've got a DOM cached variant, assume that we already know + // all we need to and use it + var domCached = _queryFuncCacheDOM[query]; + if(domCached){ return domCached; } + + // TODO: + // today we're caching DOM and QSA branches separately so we + // recalc useQSA every time. If we had a way to tag root+query + // efficiently, we'd be in good shape to do a global cache. + + var qcz = query.charAt(0); + var nospace = (-1 == query.indexOf(" ")); + + // byId searches are wicked fast compared to QSA, even when filtering + // is required + if( (query.indexOf("#") >= 0) && (nospace) ){ + forceDOM = true; + } + + var useQSA = ( + qsaAvail && (!forceDOM) && + // as per CSS 3, we can't currently start w/ combinator: + // http://www.w3.org/TR/css3-selectors/#w3cselgrammar + (specials.indexOf(qcz) == -1) && + // IE's QSA impl sucks on pseudos + (!d.isIE || (query.indexOf(":") == -1)) && + + (!(cssCaseBug && (query.indexOf(".") >= 0))) && + + // FIXME: + // need to tighten up browser rules on ":contains" and "|=" to + // figure out which aren't good + // Latest webkit (around 531.21.8) does not seem to do well with :checked on option + // elements, even though according to spec, selected options should + // match :checked. So go nonQSA for it: + // http://bugs.dojotoolkit.org/ticket/5179 + (query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) && + (query.indexOf("|=") == -1) // some browsers don't grok it + ); + + // TODO: + // if we've got a descendant query (e.g., "> .thinger" instead of + // just ".thinger") in a QSA-able doc, but are passed a child as a + // root, it should be possible to give the item a synthetic ID and + // trivially rewrite the query to the form "#synid > .thinger" to + // use the QSA branch + + + if(useQSA){ + var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ? + (query + " *") : query; + return _queryFuncCacheQSA[query] = function(root){ + try{ + // the QSA system contains an egregious spec bug which + // limits us, effectively, to only running QSA queries over + // entire documents. See: + // http://ejohn.org/blog/thoughts-on-queryselectorall/ + // despite this, we can also handle QSA runs on simple + // selectors, but we don't want detection to be expensive + // so we're just checking for the presence of a space char + // right now. Not elegant, but it's cheaper than running + // the query parser when we might not need to + if(!((9 == root.nodeType) || nospace)){ throw ""; } + var r = root[qsa](tq); + // skip expensive duplication checks and just wrap in a NodeList + r[noZip] = true; + return r; + }catch(e){ + // else run the DOM branch on this query, ensuring that we + // default that way in the future + return getQueryFunc(query, true)(root); + } + } + }else{ + // DOM branch + var parts = query.split(/\s*,\s*/); + return _queryFuncCacheDOM[query] = ((parts.length < 2) ? + // if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher + getStepQueryFunc(query) : + // if it *is* a complex query, break it up into its + // constituent parts and return a dispatcher that will + // merge the parts when run + function(root){ + var pindex = 0, // avoid array alloc for every invocation + ret = [], + tp; + while((tp = parts[pindex++])){ + ret = ret.concat(getStepQueryFunc(tp)(root)); + } + return ret; + } + ); + } + }; + + var _zipIdx = 0; + + // NOTE: + // this function is Moo inspired, but our own impl to deal correctly + // with XML in IE + var _nodeUID = d.isIE ? function(node){ + if(caseSensitive){ + // XML docs don't have uniqueID on their nodes + return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx); + + }else{ + return node.uniqueID; + } + } : + function(node){ + return (node._uid || (node._uid = ++_zipIdx)); + }; + + // determine if a node in is unique in a "bag". In this case we don't want + // to flatten a list of unique items, but rather just tell if the item in + // question is already in the bag. Normally we'd just use hash lookup to do + // this for us but IE's DOM is busted so we can't really count on that. On + // the upside, it gives us a built in unique ID function. + var _isUnique = function(node, bag){ + if(!bag){ return 1; } + var id = _nodeUID(node); + if(!bag[id]){ return bag[id] = 1; } + return 0; + }; + + // attempt to efficiently determine if an item in a list is a dupe, + // returning a list of "uniques", hopefully in doucment order + var _zipIdxName = "_zipIdx"; + var _zip = function(arr){ + if(arr && arr.nozip){ + return (qlc._wrap) ? qlc._wrap(arr) : arr; + } + // var ret = new d._NodeListCtor(); + var ret = new qlc(); + if(!arr || !arr.length){ return ret; } + if(arr[0]){ + ret.push(arr[0]); + } + if(arr.length < 2){ return ret; } + + _zipIdx++; + + // we have to fork here for IE and XML docs because we can't set + // expandos on their nodes (apparently). *sigh* + if(d.isIE && caseSensitive){ + var szidx = _zipIdx+""; + arr[0].setAttribute(_zipIdxName, szidx); + for(var x = 1, te; te = arr[x]; x++){ + if(arr[x].getAttribute(_zipIdxName) != szidx){ + ret.push(te); + } + te.setAttribute(_zipIdxName, szidx); + } + }else if(d.isIE && arr.commentStrip){ + try{ + for(var x = 1, te; te = arr[x]; x++){ + if(_isElement(te)){ + ret.push(te); + } + } + }catch(e){ /* squelch */ } + }else{ + if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; } + for(var x = 1, te; te = arr[x]; x++){ + if(arr[x][_zipIdxName] != _zipIdx){ + ret.push(te); + } + te[_zipIdxName] = _zipIdx; + } + } + return ret; + }; + + // the main executor + d.query = function(/*String*/ query, /*String|DOMNode?*/ root){ + // summary: + // Returns nodes which match the given CSS3 selector, searching the + // entire document by default but optionally taking a node to scope + // the search by. Returns an instance of dojo.NodeList. + // description: + // dojo.query() is the swiss army knife of DOM node manipulation in + // Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's + // "$" function, dojo.query provides robust, high-performance + // CSS-based node selector support with the option of scoping searches + // to a particular sub-tree of a document. + // + // Supported Selectors: + // -------------------- + // + // dojo.query() supports a rich set of CSS3 selectors, including: + // + // * class selectors (e.g., `.foo`) + // * node type selectors like `span` + // * ` ` descendant selectors + // * `>` child element selectors + // * `#foo` style ID selectors + // * `*` universal selector + // * `~`, the immediately preceeded-by sibling selector + // * `+`, the preceeded-by sibling selector + // * attribute queries: + // | * `[foo]` attribute presence selector + // | * `[foo='bar']` attribute value exact match + // | * `[foo~='bar']` attribute value list item match + // | * `[foo^='bar']` attribute start match + // | * `[foo$='bar']` attribute end match + // | * `[foo*='bar']` attribute substring match + // * `:first-child`, `:last-child`, and `:only-child` positional selectors + // * `:empty` content emtpy selector + // * `:checked` pseudo selector + // * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations + // * `:nth-child(even)`, `:nth-child(odd)` positional selectors + // * `:not(...)` negation pseudo selectors + // + // Any legal combination of these selectors will work with + // `dojo.query()`, including compound selectors ("," delimited). + // Very complex and useful searches can be constructed with this + // palette of selectors and when combined with functions for + // manipulation presented by dojo.NodeList, many types of DOM + // manipulation operations become very straightforward. + // + // Unsupported Selectors: + // ---------------------- + // + // While dojo.query handles many CSS3 selectors, some fall outside of + // what's resaonable for a programmatic node querying engine to + // handle. Currently unsupported selectors include: + // + // * namespace-differentiated selectors of any form + // * all `::` pseduo-element selectors + // * certain pseduo-selectors which don't get a lot of day-to-day use: + // | * `:root`, `:lang()`, `:target`, `:focus` + // * all visual and state selectors: + // | * `:root`, `:active`, `:hover`, `:visisted`, `:link`, + // `:enabled`, `:disabled` + // * `:*-of-type` pseudo selectors + // + // dojo.query and XML Documents: + // ----------------------------- + // + // `dojo.query` (as of dojo 1.2) supports searching XML documents + // in a case-sensitive manner. If an HTML document is served with + // a doctype that forces case-sensitivity (e.g., XHTML 1.1 + // Strict), dojo.query() will detect this and "do the right + // thing". Case sensitivity is dependent upon the document being + // searched and not the query used. It is therefore possible to + // use case-sensitive queries on strict sub-documents (iframes, + // etc.) or XML documents while still assuming case-insensitivity + // for a host/root document. + // + // Non-selector Queries: + // --------------------- + // + // If something other than a String is passed for the query, + // `dojo.query` will return a new `dojo.NodeList` instance + // constructed from that parameter alone and all further + // processing will stop. This means that if you have a reference + // to a node or NodeList, you can quickly construct a new NodeList + // from the original by calling `dojo.query(node)` or + // `dojo.query(list)`. + // + // query: + // The CSS3 expression to match against. For details on the syntax of + // CSS3 selectors, see + // root: + // A DOMNode (or node id) to scope the search from. Optional. + // returns: dojo.NodeList + // An instance of `dojo.NodeList`. Many methods are available on + // NodeLists for searching, iterating, manipulating, and handling + // events on the matched nodes in the returned list. + // example: + // search the entire document for elements with the class "foo": + // | dojo.query(".foo"); + // these elements will match: + // | + // | + // |

+ // example: + // search the entire document for elements with the classes "foo" *and* "bar": + // | dojo.query(".foo.bar"); + // these elements will match: + // | + // while these will not: + // | + // |

+ // example: + // find `` elements which are descendants of paragraphs and + // which have a "highlighted" class: + // | dojo.query("p span.highlighted"); + // the innermost span in this fragment matches: + // |

+ // | ... + // | ... + // | + // |

+ // example: + // set an "odd" class on all odd table rows inside of the table + // `#tabular_data`, using the `>` (direct child) selector to avoid + // affecting any nested tables: + // | dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd"); + // example: + // remove all elements with the class "error" from the document + // and store them in a list: + // | var errors = dojo.query(".error").orphan(); + // example: + // add an onclick handler to every submit button in the document + // which causes the form to be sent via Ajax instead: + // | dojo.query("input[type='submit']").onclick(function(e){ + // | dojo.stopEvent(e); // prevent sending the form + // | var btn = e.target; + // | dojo.xhrPost({ + // | form: btn.form, + // | load: function(data){ + // | // replace the form with the response + // | var div = dojo.doc.createElement("div"); + // | dojo.place(div, btn.form, "after"); + // | div.innerHTML = data; + // | dojo.style(btn.form, "display", "none"); + // | } + // | }); + // | }); + + //Set list constructor to desired value. This can change + //between calls, so always re-assign here. + qlc = d._NodeListCtor; + + if(!query){ + return new qlc(); + } + + if(query.constructor == qlc){ + return query; + } + if(typeof query != "string"){ // inline'd type check + return new qlc(query); // dojo.NodeList + } + if(typeof root == "string"){ // inline'd type check + root = d.byId(root); + if(!root){ return new qlc(); } + } + + root = root||getDoc(); + var od = root.ownerDocument||root.documentElement; + + // throw the big case sensitivity switch + + // NOTE: + // Opera in XHTML mode doesn't detect case-sensitivity correctly + // and it's not clear that there's any way to test for it + caseSensitive = (root.contentType && root.contentType=="application/xml") || + (d.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) || + (!!od) && + (d.isIE ? od.xml : (root.xmlVersion||od.xmlVersion)); + + // NOTE: + // adding "true" as the 2nd argument to getQueryFunc is useful for + // testing the DOM branch without worrying about the + // behavior/performance of the QSA branch. + var r = getQueryFunc(query)(root); + + // FIXME: + // need to investigate this branch WRT #8074 and #8075 + if(r && r.nozip && !qlc._wrap){ + return r; + } + return _zip(r); // dojo.NodeList + } + + // FIXME: need to add infrastructure for post-filtering pseudos, ala :last + d.query.pseudos = pseudos; + + // one-off function for filtering a NodeList based on a simple selector + d._filterQueryResult = function(nodeList, simpleFilter){ + var tmpNodeList = new d._NodeListCtor(); + var filterFunc = getSimpleFilterFunc(getQueryParts(simpleFilter)[0]); + for(var x = 0, te; te = nodeList[x]; x++){ + if(filterFunc(te)){ tmpNodeList.push(te); } + } + return tmpNodeList; + } +})(this["queryPortability"]||this["acme"]||dojo); + +/* +*/ + +} + +if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base.xhr"] = true; +dojo.provide("dojo._base.xhr"); + + + + + +(function(){ + var _d = dojo, cfg = _d.config; + + function setValue(/*Object*/obj, /*String*/name, /*String*/value){ + //summary: + // For the named property in object, set the value. If a value + // already exists and it is a string, convert the value to be an + // array of values. + + //Skip it if there is no value + if(value === null){ + return; + } + + var val = obj[name]; + if(typeof val == "string"){ // inline'd type check + obj[name] = [val, value]; + }else if(_d.isArray(val)){ + val.push(value); + }else{ + obj[name] = value; + } + } + + dojo.fieldToObject = function(/*DOMNode||String*/ inputNode){ + // summary: + // Serialize a form field to a JavaScript object. + // + // description: + // Returns the value encoded in a form field as + // as a string or an array of strings. Disabled form elements + // and unchecked radio and checkboxes are skipped. Multi-select + // elements are returned as an array of string values. + var ret = null; + var item = _d.byId(inputNode); + if(item){ + var _in = item.name; + var type = (item.type||"").toLowerCase(); + if(_in && type && !item.disabled){ + if(type == "radio" || type == "checkbox"){ + if(item.checked){ ret = item.value } + }else if(item.multiple){ + ret = []; + _d.query("option", item).forEach(function(opt){ + if(opt.selected){ + ret.push(opt.value); + } + }); + }else{ + ret = item.value; + } + } + } + return ret; // Object + } + + dojo.formToObject = function(/*DOMNode||String*/ formNode){ + // summary: + // Serialize a form node to a JavaScript object. + // description: + // Returns the values encoded in an HTML form as + // string properties in an object which it then returns. Disabled form + // elements, buttons, and other non-value form elements are skipped. + // Multi-select elements are returned as an array of string values. + // + // example: + // This form: + // |
+ // | + // | + // | + // | + // |
+ // + // yields this object structure as the result of a call to + // formToObject(): + // + // | { + // | blah: "blah", + // | multi: [ + // | "thud", + // | "thonk" + // | ] + // | }; + + var ret = {}; + var exclude = "file|submit|image|reset|button|"; + _d.forEach(dojo.byId(formNode).elements, function(item){ + var _in = item.name; + var type = (item.type||"").toLowerCase(); + if(_in && type && exclude.indexOf(type) == -1 && !item.disabled){ + setValue(ret, _in, _d.fieldToObject(item)); + if(type == "image"){ + ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0; + } + } + }); + return ret; // Object + } + + dojo.objectToQuery = function(/*Object*/ map){ + // summary: + // takes a name/value mapping object and returns a string representing + // a URL-encoded version of that object. + // example: + // this object: + // + // | { + // | blah: "blah", + // | multi: [ + // | "thud", + // | "thonk" + // | ] + // | }; + // + // yields the following query string: + // + // | "blah=blah&multi=thud&multi=thonk" + + // FIXME: need to implement encodeAscii!! + var enc = encodeURIComponent; + var pairs = []; + var backstop = {}; + for(var name in map){ + var value = map[name]; + if(value != backstop[name]){ + var assign = enc(name) + "="; + if(_d.isArray(value)){ + for(var i=0; i < value.length; i++){ + pairs.push(assign + enc(value[i])); + } + }else{ + pairs.push(assign + enc(value)); + } + } + } + return pairs.join("&"); // String + } + + dojo.formToQuery = function(/*DOMNode||String*/ formNode){ + // summary: + // Returns a URL-encoded string representing the form passed as either a + // node or string ID identifying the form to serialize + return _d.objectToQuery(_d.formToObject(formNode)); // String + } + + dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){ + // summary: + // Create a serialized JSON string from a form node or string + // ID identifying the form to serialize + return _d.toJson(_d.formToObject(formNode), prettyPrint); // String + } + + dojo.queryToObject = function(/*String*/ str){ + // summary: + // Create an object representing a de-serialized query section of a + // URL. Query keys with multiple values are returned in an array. + // + // example: + // This string: + // + // | "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&" + // + // results in this object structure: + // + // | { + // | foo: [ "bar", "baz" ], + // | thinger: " spaces =blah", + // | zonk: "blarg" + // | } + // + // Note that spaces and other urlencoded entities are correctly + // handled. + + // FIXME: should we grab the URL string if we're not passed one? + var ret = {}; + var qp = str.split("&"); + var dec = decodeURIComponent; + _d.forEach(qp, function(item){ + if(item.length){ + var parts = item.split("="); + var name = dec(parts.shift()); + var val = dec(parts.join("=")); + if(typeof ret[name] == "string"){ // inline'd type check + ret[name] = [ret[name]]; + } + + if(_d.isArray(ret[name])){ + ret[name].push(val); + }else{ + ret[name] = val; + } + } + }); + return ret; // Object + } + + // need to block async callbacks from snatching this thread as the result + // of an async callback might call another sync XHR, this hangs khtml forever + // must checked by watchInFlight() + + dojo._blockAsync = false; + + // MOW: remove dojo._contentHandlers alias in 2.0 + var handlers = _d._contentHandlers = dojo.contentHandlers = { + // summary: + // A map of availble XHR transport handle types. Name matches the + // `handleAs` attribute passed to XHR calls. + // + // description: + // A map of availble XHR transport handle types. Name matches the + // `handleAs` attribute passed to XHR calls. Each contentHandler is + // called, passing the xhr object for manipulation. The return value + // from the contentHandler will be passed to the `load` or `handle` + // functions defined in the original xhr call. + // + // example: + // Creating a custom content-handler: + // | dojo.contentHandlers.makeCaps = function(xhr){ + // | return xhr.responseText.toUpperCase(); + // | } + // | // and later: + // | dojo.xhrGet({ + // | url:"foo.txt", + // | handleAs:"makeCaps", + // | load: function(data){ /* data is a toUpper version of foo.txt */ } + // | }); + + text: function(xhr){ + // summary: A contentHandler which simply returns the plaintext response data + return xhr.responseText; + }, + json: function(xhr){ + // summary: A contentHandler which returns a JavaScript object created from the response data + return _d.fromJson(xhr.responseText || null); + }, + "json-comment-filtered": function(xhr){ + // summary: A contentHandler which expects comment-filtered JSON. + // description: + // A contentHandler which expects comment-filtered JSON. + // the json-comment-filtered option was implemented to prevent + // "JavaScript Hijacking", but it is less secure than standard JSON. Use + // standard JSON instead. JSON prefixing can be used to subvert hijacking. + // + // Will throw a notice suggesting to use application/json mimetype, as + // json-commenting can introduce security issues. To decrease the chances of hijacking, + // use the standard `json` contentHandler, and prefix your "JSON" with: {}&& + // + // use djConfig.useCommentedJson = true to turn off the notice + if(!dojo.config.useCommentedJson){ + console.warn("Consider using the standard mimetype:application/json." + + " json-commenting can introduce security issues. To" + + " decrease the chances of hijacking, use the standard the 'json' handler and" + + " prefix your json with: {}&&\n" + + "Use djConfig.useCommentedJson=true to turn off this message."); + } + + var value = xhr.responseText; + var cStartIdx = value.indexOf("\/*"); + var cEndIdx = value.lastIndexOf("*\/"); + if(cStartIdx == -1 || cEndIdx == -1){ + throw new Error("JSON was not comment filtered"); + } + return _d.fromJson(value.substring(cStartIdx+2, cEndIdx)); + }, + javascript: function(xhr){ + // summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript + + // FIXME: try Moz and IE specific eval variants? + return _d.eval(xhr.responseText); + }, + xml: function(xhr){ + // summary: A contentHandler returning an XML Document parsed from the response data + var result = xhr.responseXML; + if(_d.isIE && (!result || !result.documentElement)){ + //WARNING: this branch used by the xml handling in dojo.io.iframe, + //so be sure to test dojo.io.iframe if making changes below. + var ms = function(n){ return "MSXML" + n + ".DOMDocument"; } + var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)]; + _d.some(dp, function(p){ + try{ + var dom = new ActiveXObject(p); + dom.async = false; + dom.loadXML(xhr.responseText); + result = dom; + }catch(e){ return false; } + return true; + }); + } + return result; // DOMDocument + }, + "json-comment-optional": function(xhr){ + // summary: A contentHandler which checks the presence of comment-filtered JSON and + // alternates between the `json` and `json-comment-filtered` contentHandlers. + if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){ + return handlers["json-comment-filtered"](xhr); + }else{ + return handlers["json"](xhr); + } + } + }; + + /*===== + dojo.__IoArgs = function(){ + // url: String + // URL to server endpoint. + // content: Object? + // Contains properties with string values. These + // properties will be serialized as name1=value2 and + // passed in the request. + // timeout: Integer? + // Milliseconds to wait for the response. If this time + // passes, the then error callbacks are called. + // form: DOMNode? + // DOM node for a form. Used to extract the form values + // and send to the server. + // preventCache: Boolean? + // Default is false. If true, then a + // "dojo.preventCache" parameter is sent in the request + // with a value that changes with each request + // (timestamp). Useful only with GET-type requests. + // handleAs: String? + // Acceptable values depend on the type of IO + // transport (see specific IO calls for more information). + // rawBody: String? + // Sets the raw body for an HTTP request. If this is used, then the content + // property is ignored. This is mostly useful for HTTP methods that have + // a body to their requests, like PUT or POST. This property can be used instead + // of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively. + // ioPublish: Boolean? + // Set this explicitly to false to prevent publishing of topics related to + // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics + // will be published via dojo.publish for different phases of an IO operation. + // See dojo.__IoPublish for a list of topics that are published. + // load: Function? + // This function will be + // called on a successful HTTP response code. + // error: Function? + // This function will + // be called when the request fails due to a network or server error, the url + // is invalid, etc. It will also be called if the load or handle callback throws an + // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications + // to continue to run even when a logic error happens in the callback, while making + // it easier to troubleshoot while in debug mode. + // handle: Function? + // This function will + // be called at the end of every request, whether or not an error occurs. + this.url = url; + this.content = content; + this.timeout = timeout; + this.form = form; + this.preventCache = preventCache; + this.handleAs = handleAs; + this.ioPublish = ioPublish; + this.load = function(response, ioArgs){ + // ioArgs: dojo.__IoCallbackArgs + // Provides additional information about the request. + // response: Object + // The response in the format as defined with handleAs. + } + this.error = function(response, ioArgs){ + // ioArgs: dojo.__IoCallbackArgs + // Provides additional information about the request. + // response: Object + // The response in the format as defined with handleAs. + } + this.handle = function(loadOrError, response, ioArgs){ + // loadOrError: String + // Provides a string that tells you whether this function + // was called because of success (load) or failure (error). + // response: Object + // The response in the format as defined with handleAs. + // ioArgs: dojo.__IoCallbackArgs + // Provides additional information about the request. + } + } + =====*/ + + /*===== + dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){ + // args: Object + // the original object argument to the IO call. + // xhr: XMLHttpRequest + // For XMLHttpRequest calls only, the + // XMLHttpRequest object that was used for the + // request. + // url: String + // The final URL used for the call. Many times it + // will be different than the original args.url + // value. + // query: String + // For non-GET requests, the + // name1=value1&name2=value2 parameters sent up in + // the request. + // handleAs: String + // The final indicator on how the response will be + // handled. + // id: String + // For dojo.io.script calls only, the internal + // script ID used for the request. + // canDelete: Boolean + // For dojo.io.script calls only, indicates + // whether the script tag that represents the + // request can be deleted after callbacks have + // been called. Used internally to know when + // cleanup can happen on JSONP-type requests. + // json: Object + // For dojo.io.script calls only: holds the JSON + // response for JSONP-type requests. Used + // internally to hold on to the JSON responses. + // You should not need to access it directly -- + // the same object should be passed to the success + // callbacks directly. + this.args = args; + this.xhr = xhr; + this.url = url; + this.query = query; + this.handleAs = handleAs; + this.id = id; + this.canDelete = canDelete; + this.json = json; + } + =====*/ + + + /*===== + dojo.__IoPublish = function(){ + // summary: + // This is a list of IO topics that can be published + // if djConfig.ioPublish is set to true. IO topics can be + // published for any Input/Output, network operation. So, + // dojo.xhr, dojo.io.script and dojo.io.iframe can all + // trigger these topics to be published. + // start: String + // "/dojo/io/start" is sent when there are no outstanding IO + // requests, and a new IO request is started. No arguments + // are passed with this topic. + // send: String + // "/dojo/io/send" is sent whenever a new IO request is started. + // It passes the dojo.Deferred for the request with the topic. + // load: String + // "/dojo/io/load" is sent whenever an IO request has loaded + // successfully. It passes the response and the dojo.Deferred + // for the request with the topic. + // error: String + // "/dojo/io/error" is sent whenever an IO request has errored. + // It passes the error and the dojo.Deferred + // for the request with the topic. + // done: String + // "/dojo/io/done" is sent whenever an IO request has completed, + // either by loading or by erroring. It passes the error and + // the dojo.Deferred for the request with the topic. + // stop: String + // "/dojo/io/stop" is sent when all outstanding IO requests have + // finished. No arguments are passed with this topic. + this.start = "/dojo/io/start"; + this.send = "/dojo/io/send"; + this.load = "/dojo/io/load"; + this.error = "/dojo/io/error"; + this.done = "/dojo/io/done"; + this.stop = "/dojo/io/stop"; + } + =====*/ + + + dojo._ioSetArgs = function(/*dojo.__IoArgs*/args, + /*Function*/canceller, + /*Function*/okHandler, + /*Function*/errHandler){ + // summary: + // sets up the Deferred and ioArgs property on the Deferred so it + // can be used in an io call. + // args: + // The args object passed into the public io call. Recognized properties on + // the args object are: + // canceller: + // The canceller function used for the Deferred object. The function + // will receive one argument, the Deferred object that is related to the + // canceller. + // okHandler: + // The first OK callback to be registered with Deferred. It has the opportunity + // to transform the OK response. It will receive one argument -- the Deferred + // object returned from this function. + // errHandler: + // The first error callback to be registered with Deferred. It has the opportunity + // to do cleanup on an error. It will receive two arguments: error (the + // Error object) and dfd, the Deferred object returned from this function. + + var ioArgs = {args: args, url: args.url}; + + //Get values from form if requestd. + var formObject = null; + if(args.form){ + var form = _d.byId(args.form); + //IE requires going through getAttributeNode instead of just getAttribute in some form cases, + //so use it for all. See #2844 + var actnNode = form.getAttributeNode("action"); + ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); + formObject = _d.formToObject(form); + } + + // set up the query params + var miArgs = [{}]; + + if(formObject){ + // potentially over-ride url-provided params w/ form values + miArgs.push(formObject); + } + if(args.content){ + // stuff in content over-rides what's set by form + miArgs.push(args.content); + } + if(args.preventCache){ + miArgs.push({"dojo.preventCache": new Date().valueOf()}); + } + ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs)); + + // .. and the real work of getting the deferred in order, etc. + ioArgs.handleAs = args.handleAs || "text"; + var d = new _d.Deferred(canceller); + d.addCallbacks(okHandler, function(error){ + return errHandler(error, d); + }); + + //Support specifying load, error and handle callback functions from the args. + //For those callbacks, the "this" object will be the args object. + //The callbacks will get the deferred result value as the + //first argument and the ioArgs object as the second argument. + var ld = args.load; + if(ld && _d.isFunction(ld)){ + d.addCallback(function(value){ + return ld.call(args, value, ioArgs); + }); + } + var err = args.error; + if(err && _d.isFunction(err)){ + d.addErrback(function(value){ + return err.call(args, value, ioArgs); + }); + } + var handle = args.handle; + if(handle && _d.isFunction(handle)){ + d.addBoth(function(value){ + return handle.call(args, value, ioArgs); + }); + } + + //Plug in topic publishing, if dojo.publish is loaded. + if(cfg.ioPublish && _d.publish && ioArgs.args.ioPublish !== false){ + d.addCallbacks( + function(res){ + _d.publish("/dojo/io/load", [d, res]); + return res; + }, + function(res){ + _d.publish("/dojo/io/error", [d, res]); + return res; + } + ); + d.addBoth(function(res){ + _d.publish("/dojo/io/done", [d, res]); + return res; + }); + } + + d.ioArgs = ioArgs; + + // FIXME: need to wire up the xhr object's abort method to something + // analagous in the Deferred + return d; + } + + var _deferredCancel = function(/*Deferred*/dfd){ + // summary: canceller function for dojo._ioSetArgs call. + + dfd.canceled = true; + var xhr = dfd.ioArgs.xhr; + var _at = typeof xhr.abort; + if(_at == "function" || _at == "object" || _at == "unknown"){ + xhr.abort(); + } + var err = dfd.ioArgs.error; + if(!err){ + err = new Error("xhr cancelled"); + err.dojoType="cancel"; + } + return err; + } + var _deferredOk = function(/*Deferred*/dfd){ + // summary: okHandler function for dojo._ioSetArgs call. + + var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr); + return ret === undefined ? null : ret; + } + var _deferError = function(/*Error*/error, /*Deferred*/dfd){ + // summary: errHandler function for dojo._ioSetArgs call. + + if(!dfd.ioArgs.args.failOk){ + console.error(error); + } + return error; + } + + // avoid setting a timer per request. It degrades performance on IE + // something fierece if we don't use unified loops. + var _inFlightIntvl = null; + var _inFlight = []; + + + //Use a separate count for knowing if we are starting/stopping io calls. + //Cannot use _inFlight.length since it can change at a different time than + //when we want to do this kind of test. We only want to decrement the count + //after a callback/errback has finished, since the callback/errback should be + //considered as part of finishing a request. + var _pubCount = 0; + var _checkPubCount = function(dfd){ + if(_pubCount <= 0){ + _pubCount = 0; + if(cfg.ioPublish && _d.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){ + _d.publish("/dojo/io/stop"); + } + } + }; + + var _watchInFlight = function(){ + //summary: + // internal method that checks each inflight XMLHttpRequest to see + // if it has completed or if the timeout situation applies. + + var now = (new Date()).getTime(); + // make sure sync calls stay thread safe, if this callback is called + // during a sync call and this results in another sync call before the + // first sync call ends the browser hangs + if(!_d._blockAsync){ + // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating + // note: the second clause is an assigment on purpose, lint may complain + for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){ + var dfd = tif.dfd; + var func = function(){ + if(!dfd || dfd.canceled || !tif.validCheck(dfd)){ + _inFlight.splice(i--, 1); + _pubCount -= 1; + }else if(tif.ioCheck(dfd)){ + _inFlight.splice(i--, 1); + tif.resHandle(dfd); + _pubCount -= 1; + }else if(dfd.startTime){ + //did we timeout? + if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){ + _inFlight.splice(i--, 1); + var err = new Error("timeout exceeded"); + err.dojoType = "timeout"; + dfd.errback(err); + //Cancel the request so the io module can do appropriate cleanup. + dfd.cancel(); + _pubCount -= 1; + } + } + }; + if(dojo.config.debugAtAllCosts){ + func.call(this); + }else{ + try{ + func.call(this); + }catch(e){ + dfd.errback(e); + } + } + } + } + + _checkPubCount(dfd); + + if(!_inFlight.length){ + clearInterval(_inFlightIntvl); + _inFlightIntvl = null; + return; + } + } + + dojo._ioCancelAll = function(){ + //summary: Cancels all pending IO requests, regardless of IO type + //(xhr, script, iframe). + try{ + _d.forEach(_inFlight, function(i){ + try{ + i.dfd.cancel(); + }catch(e){/*squelch*/} + }); + }catch(e){/*squelch*/} + } + + //Automatically call cancel all io calls on unload + //in IE for trac issue #2357. + if(_d.isIE){ + _d.addOnWindowUnload(_d._ioCancelAll); + } + + _d._ioNotifyStart = function(/*Deferred*/dfd){ + // summary: + // If dojo.publish is available, publish topics + // about the start of a request queue and/or the + // the beginning of request. + // description: + // Used by IO transports. An IO transport should + // call this method before making the network connection. + if(cfg.ioPublish && _d.publish && dfd.ioArgs.args.ioPublish !== false){ + if(!_pubCount){ + _d.publish("/dojo/io/start"); + } + _pubCount += 1; + _d.publish("/dojo/io/send", [dfd]); + } + } + + _d._ioWatch = function(dfd, validCheck, ioCheck, resHandle){ + // summary: + // Watches the io request represented by dfd to see if it completes. + // dfd: Deferred + // The Deferred object to watch. + // validCheck: Function + // Function used to check if the IO request is still valid. Gets the dfd + // object as its only argument. + // ioCheck: Function + // Function used to check if basic IO call worked. Gets the dfd + // object as its only argument. + // resHandle: Function + // Function used to process response. Gets the dfd + // object as its only argument. + var args = dfd.ioArgs.args; + if(args.timeout){ + dfd.startTime = (new Date()).getTime(); + } + + _inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle}); + if(!_inFlightIntvl){ + _inFlightIntvl = setInterval(_watchInFlight, 50); + } + // handle sync requests + //A weakness: async calls in flight + //could have their handlers called as part of the + //_watchInFlight call, before the sync's callbacks + // are called. + if(args.sync){ + _watchInFlight(); + } + } + + var _defaultContentType = "application/x-www-form-urlencoded"; + + var _validCheck = function(/*Deferred*/dfd){ + return dfd.ioArgs.xhr.readyState; //boolean + } + var _ioCheck = function(/*Deferred*/dfd){ + return 4 == dfd.ioArgs.xhr.readyState; //boolean + } + var _resHandle = function(/*Deferred*/dfd){ + var xhr = dfd.ioArgs.xhr; + if(_d._isDocumentOk(xhr)){ + dfd.callback(dfd); + }else{ + var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status); + err.status = xhr.status; + err.responseText = xhr.responseText; + dfd.errback(err); + } + } + + dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){ + //summary: Adds query params discovered by the io deferred construction to the URL. + //Only use this for operations which are fundamentally GET-type operations. + if(ioArgs.query.length){ + ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query; + ioArgs.query = null; + } + } + + /*===== + dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, { + constructor: function(){ + // summary: + // In addition to the properties listed for the dojo._IoArgs type, + // the following properties are allowed for dojo.xhr* methods. + // handleAs: String? + // Acceptable values are: text (default), json, json-comment-optional, + // json-comment-filtered, javascript, xml. See `dojo.contentHandlers` + // sync: Boolean? + // false is default. Indicates whether the request should + // be a synchronous (blocking) request. + // headers: Object? + // Additional HTTP headers to send in the request. + // failOk: Boolean? + // false is default. Indicates whether a request should be + // allowed to fail (and therefore no console error message in + // the event of a failure) + this.handleAs = handleAs; + this.sync = sync; + this.headers = headers; + this.failOk = failOk; + } + }); + =====*/ + + dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){ + // summary: + // Sends an HTTP request with the given method. + // description: + // Sends an HTTP request with the given method. + // See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts + // for those HTTP methods. There are also methods for "raw" PUT and POST methods + // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively. + // method: + // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase. + // hasBody: + // If the request has an HTTP body, then pass true for hasBody. + + //Make the Deferred object for this xhr request. + var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError); + var ioArgs = dfd.ioArgs; + + //Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like + //the one used for iframe proxies. + var xhr = ioArgs.xhr = _d._xhrObj(ioArgs.args); + //If XHR factory fails, cancel the deferred. + if(!xhr){ + dfd.cancel(); + return dfd; + } + + //Allow for specifying the HTTP body completely. + if("postData" in args){ + ioArgs.query = args.postData; + }else if("putData" in args){ + ioArgs.query = args.putData; + }else if("rawBody" in args){ + ioArgs.query = args.rawBody; + }else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) == -1){ + //Check for hasBody being passed. If no hasBody, + //then only append query string if not a POST or PUT request. + _d._ioAddQueryToUrl(ioArgs); + } + + // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open). + // workaround for IE6's apply() "issues" + xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined); + if(args.headers){ + for(var hdr in args.headers){ + if(hdr.toLowerCase() === "content-type" && !args.contentType){ + args.contentType = args.headers[hdr]; + }else if(args.headers[hdr]){ + //Only add header if it has a value. This allows for instnace, skipping + //insertion of X-Requested-With by specifying empty value. + xhr.setRequestHeader(hdr, args.headers[hdr]); + } + } + } + // FIXME: is this appropriate for all content types? + xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType); + if(!args.headers || !("X-Requested-With" in args.headers)){ + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + } + // FIXME: set other headers here! + _d._ioNotifyStart(dfd); + if(dojo.config.debugAtAllCosts){ + xhr.send(ioArgs.query); + }else{ + try{ + xhr.send(ioArgs.query); + }catch(e){ + ioArgs.error = e; + dfd.cancel(); + } + } + _d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle); + xhr = null; + return dfd; // dojo.Deferred + } + + dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP GET request to the server. + return _d.xhr("GET", args); // dojo.Deferred + } + + dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP POST request to the server. In addtion to the properties + // listed for the dojo.__XhrArgs type, the following property is allowed: + // postData: + // String. Send raw data in the body of the POST request. + return _d.xhr("POST", args, true); // dojo.Deferred + } + + dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP PUT request to the server. In addtion to the properties + // listed for the dojo.__XhrArgs type, the following property is allowed: + // putData: + // String. Send raw data in the body of the PUT request. + return _d.xhr("PUT", args, true); // dojo.Deferred + } + + dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP DELETE request to the server. + return _d.xhr("DELETE", args); //dojo.Deferred + } + + /* + dojo.wrapForm = function(formNode){ + //summary: + // A replacement for FormBind, but not implemented yet. + + // FIXME: need to think harder about what extensions to this we might + // want. What should we allow folks to do w/ this? What events to + // set/send? + throw new Error("dojo.wrapForm not yet implemented"); + } + */ +})(); + +} + +if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base.fx"] = true; +dojo.provide("dojo._base.fx"); + + + + + +/* + Animation loosely package based on Dan Pupius' work, contributed under CLA: + http://pupius.co.uk/js/Toolkit.Drawing.js +*/ +(function(){ + var d = dojo; + var _mixin = d._mixin; + + dojo._Line = function(/*int*/ start, /*int*/ end){ + // summary: + // dojo._Line is the object used to generate values from a start value + // to an end value + // start: int + // Beginning value for range + // end: int + // Ending value for range + this.start = start; + this.end = end; + }; + + dojo._Line.prototype.getValue = function(/*float*/ n){ + // summary: Returns the point on the line + // n: a floating point number greater than 0 and less than 1 + return ((this.end - this.start) * n) + this.start; // Decimal + }; + + dojo.Animation = function(args){ + // summary: + // A generic animation class that fires callbacks into its handlers + // object at various states. + // description: + // A generic animation class that fires callbacks into its handlers + // object at various states. Nearly all dojo animation functions + // return an instance of this method, usually without calling the + // .play() method beforehand. Therefore, you will likely need to + // call .play() on instances of `dojo.Animation` when one is + // returned. + // args: Object + // The 'magic argument', mixing all the properties into this + // animation instance. + + _mixin(this, args); + if(d.isArray(this.curve)){ + this.curve = new d._Line(this.curve[0], this.curve[1]); + } + + }; + + // Alias to drop come 2.0: + d._Animation = d.Animation; + + d.extend(dojo.Animation, { + // duration: Integer + // The time in milliseonds the animation will take to run + duration: 350, + + /*===== + // curve: dojo._Line|Array + // A two element array of start and end values, or a `dojo._Line` instance to be + // used in the Animation. + curve: null, + + // easing: Function? + // A Function to adjust the acceleration (or deceleration) of the progress + // across a dojo._Line + easing: null, + =====*/ + + // repeat: Integer? + // The number of times to loop the animation + repeat: 0, + + // rate: Integer? + // the time in milliseconds to wait before advancing to next frame + // (used as a fps timer: 1000/rate = fps) + rate: 20 /* 50 fps */, + + /*===== + // delay: Integer? + // The time in milliseconds to wait before starting animation after it + // has been .play()'ed + delay: null, + + // beforeBegin: Event? + // Synthetic event fired before a dojo.Animation begins playing (synchronous) + beforeBegin: null, + + // onBegin: Event? + // Synthetic event fired as a dojo.Animation begins playing (useful?) + onBegin: null, + + // onAnimate: Event? + // Synthetic event fired at each interval of a `dojo.Animation` + onAnimate: null, + + // onEnd: Event? + // Synthetic event fired after the final frame of a `dojo.Animation` + onEnd: null, + + // onPlay: Event? + // Synthetic event fired any time a `dojo.Animation` is play()'ed + onPlay: null, + + // onPause: Event? + // Synthetic event fired when a `dojo.Animation` is paused + onPause: null, + + // onStop: Event + // Synthetic event fires when a `dojo.Animation` is stopped + onStop: null, + + =====*/ + + _percent: 0, + _startRepeatCount: 0, + + _getStep: function(){ + var _p = this._percent, + _e = this.easing + ; + return _e ? _e(_p) : _p; + }, + _fire: function(/*Event*/ evt, /*Array?*/ args){ + // summary: + // Convenience function. Fire event "evt" and pass it the + // arguments specified in "args". + // description: + // Convenience function. Fire event "evt" and pass it the + // arguments specified in "args". + // Fires the callback in the scope of the `dojo.Animation` + // instance. + // evt: + // The event to fire. + // args: + // The arguments to pass to the event. + var a = args||[]; + if(this[evt]){ + if(d.config.debugAtAllCosts){ + this[evt].apply(this, a); + }else{ + try{ + this[evt].apply(this, a); + }catch(e){ + // squelch and log because we shouldn't allow exceptions in + // synthetic event handlers to cause the internal timer to run + // amuck, potentially pegging the CPU. I'm not a fan of this + // squelch, but hopefully logging will make it clear what's + // going on + console.error("exception in animation handler for:", evt); + console.error(e); + } + } + } + return this; // dojo.Animation + }, + + play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ + // summary: + // Start the animation. + // delay: + // How many milliseconds to delay before starting. + // gotoStart: + // If true, starts the animation from the beginning; otherwise, + // starts it from its current position. + // returns: dojo.Animation + // The instance to allow chaining. + + var _t = this; + if(_t._delayTimer){ _t._clearTimer(); } + if(gotoStart){ + _t._stopTimer(); + _t._active = _t._paused = false; + _t._percent = 0; + }else if(_t._active && !_t._paused){ + return _t; + } + + _t._fire("beforeBegin", [_t.node]); + + var de = delay || _t.delay, + _p = dojo.hitch(_t, "_play", gotoStart); + + if(de > 0){ + _t._delayTimer = setTimeout(_p, de); + return _t; + } + _p(); + return _t; + }, + + _play: function(gotoStart){ + var _t = this; + if(_t._delayTimer){ _t._clearTimer(); } + _t._startTime = new Date().valueOf(); + if(_t._paused){ + _t._startTime -= _t.duration * _t._percent; + } + + _t._active = true; + _t._paused = false; + var value = _t.curve.getValue(_t._getStep()); + if(!_t._percent){ + if(!_t._startRepeatCount){ + _t._startRepeatCount = _t.repeat; + } + _t._fire("onBegin", [value]); + } + + _t._fire("onPlay", [value]); + + _t._cycle(); + return _t; // dojo.Animation + }, + + pause: function(){ + // summary: Pauses a running animation. + var _t = this; + if(_t._delayTimer){ _t._clearTimer(); } + _t._stopTimer(); + if(!_t._active){ return _t; /*dojo.Animation*/ } + _t._paused = true; + _t._fire("onPause", [_t.curve.getValue(_t._getStep())]); + return _t; // dojo.Animation + }, + + gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){ + // summary: + // Sets the progress of the animation. + // percent: + // A percentage in decimal notation (between and including 0.0 and 1.0). + // andPlay: + // If true, play the animation after setting the progress. + var _t = this; + _t._stopTimer(); + _t._active = _t._paused = true; + _t._percent = percent; + if(andPlay){ _t.play(); } + return _t; // dojo.Animation + }, + + stop: function(/*boolean?*/ gotoEnd){ + // summary: Stops a running animation. + // gotoEnd: If true, the animation will end. + var _t = this; + if(_t._delayTimer){ _t._clearTimer(); } + if(!_t._timer){ return _t; /* dojo.Animation */ } + _t._stopTimer(); + if(gotoEnd){ + _t._percent = 1; + } + _t._fire("onStop", [_t.curve.getValue(_t._getStep())]); + _t._active = _t._paused = false; + return _t; // dojo.Animation + }, + + status: function(){ + // summary: + // Returns a string token representation of the status of + // the animation, one of: "paused", "playing", "stopped" + if(this._active){ + return this._paused ? "paused" : "playing"; // String + } + return "stopped"; // String + }, + + _cycle: function(){ + var _t = this; + if(_t._active){ + var curr = new Date().valueOf(); + var step = (curr - _t._startTime) / (_t.duration); + + if(step >= 1){ + step = 1; + } + _t._percent = step; + + // Perform easing + if(_t.easing){ + step = _t.easing(step); + } + + _t._fire("onAnimate", [_t.curve.getValue(step)]); + + if(_t._percent < 1){ + _t._startTimer(); + }else{ + _t._active = false; + + if(_t.repeat > 0){ + _t.repeat--; + _t.play(null, true); + }else if(_t.repeat == -1){ + _t.play(null, true); + }else{ + if(_t._startRepeatCount){ + _t.repeat = _t._startRepeatCount; + _t._startRepeatCount = 0; + } + } + _t._percent = 0; + _t._fire("onEnd", [_t.node]); + !_t.repeat && _t._stopTimer(); + } + } + return _t; // dojo.Animation + }, + + _clearTimer: function(){ + // summary: Clear the play delay timer + clearTimeout(this._delayTimer); + delete this._delayTimer; + } + + }); + + // the local timer, stubbed into all Animation instances + var ctr = 0, + timer = null, + runner = { + run: function(){} + }; + + d.extend(d.Animation, { + + _startTimer: function(){ + if(!this._timer){ + this._timer = d.connect(runner, "run", this, "_cycle"); + ctr++; + } + if(!timer){ + timer = setInterval(d.hitch(runner, "run"), this.rate); + } + }, + + _stopTimer: function(){ + if(this._timer){ + d.disconnect(this._timer); + this._timer = null; + ctr--; + } + if(ctr <= 0){ + clearInterval(timer); + timer = null; + ctr = 0; + } + } + + }); + + var _makeFadeable = + d.isIE ? function(node){ + // only set the zoom if the "tickle" value would be the same as the + // default + var ns = node.style; + // don't set the width to auto if it didn't already cascade that way. + // We don't want to f anyones designs + if(!ns.width.length && d.style(node, "width") == "auto"){ + ns.width = "auto"; + } + } : + function(){}; + + dojo._fade = function(/*Object*/ args){ + // summary: + // Returns an animation that will fade the node defined by + // args.node from the start to end values passed (args.start + // args.end) (end is mandatory, start is optional) + + args.node = d.byId(args.node); + var fArgs = _mixin({ properties: {} }, args), + props = (fArgs.properties.opacity = {}); + + props.start = !("start" in fArgs) ? + function(){ + return +d.style(fArgs.node, "opacity")||0; + } : fArgs.start; + props.end = fArgs.end; + + var anim = d.animateProperty(fArgs); + d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node)); + + return anim; // dojo.Animation + }; + + /*===== + dojo.__FadeArgs = function(node, duration, easing){ + // node: DOMNode|String + // The node referenced in the animation + // duration: Integer? + // Duration of the animation in milliseconds. + // easing: Function? + // An easing function. + this.node = node; + this.duration = duration; + this.easing = easing; + } + =====*/ + + dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){ + // summary: + // Returns an animation that will fade node defined in 'args' from + // its current opacity to fully opaque. + return d._fade(_mixin({ end: 1 }, args)); // dojo.Animation + }; + + dojo.fadeOut = function(/*dojo.__FadeArgs*/ args){ + // summary: + // Returns an animation that will fade node defined in 'args' + // from its current opacity to fully transparent. + return d._fade(_mixin({ end: 0 }, args)); // dojo.Animation + }; + + dojo._defaultEasing = function(/*Decimal?*/ n){ + // summary: The default easing function for dojo.Animation(s) + return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2); + }; + + var PropLine = function(properties){ + // PropLine is an internal class which is used to model the values of + // an a group of CSS properties across an animation lifecycle. In + // particular, the "getValue" function handles getting interpolated + // values between start and end for a particular CSS value. + this._properties = properties; + for(var p in properties){ + var prop = properties[p]; + if(prop.start instanceof d.Color){ + // create a reusable temp color object to keep intermediate results + prop.tempColor = new d.Color(); + } + } + }; + + PropLine.prototype.getValue = function(r){ + var ret = {}; + for(var p in this._properties){ + var prop = this._properties[p], + start = prop.start; + if(start instanceof d.Color){ + ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss(); + }else if(!d.isArray(start)){ + ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0); + } + } + return ret; + }; + + /*===== + dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], { + // Properties: Object? + // A hash map of style properties to Objects describing the transition, + // such as the properties of dojo._Line with an additional 'units' property + properties: {} + + //TODOC: add event callbacks + }); + =====*/ + + dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){ + // summary: + // Returns an animation that will transition the properties of + // node defined in `args` depending how they are defined in + // `args.properties` + // + // description: + // `dojo.animateProperty` is the foundation of most `dojo.fx` + // animations. It takes an object of "properties" corresponding to + // style properties, and animates them in parallel over a set + // duration. + // + // example: + // A simple animation that changes the width of the specified node. + // | dojo.animateProperty({ + // | node: "nodeId", + // | properties: { width: 400 }, + // | }).play(); + // Dojo figures out the start value for the width and converts the + // integer specified for the width to the more expressive but + // verbose form `{ width: { end: '400', units: 'px' } }` which you + // can also specify directly. Defaults to 'px' if ommitted. + // + // example: + // Animate width, height, and padding over 2 seconds... the + // pedantic way: + // | dojo.animateProperty({ node: node, duration:2000, + // | properties: { + // | width: { start: '200', end: '400', units:"px" }, + // | height: { start:'200', end: '400', units:"px" }, + // | paddingTop: { start:'5', end:'50', units:"px" } + // | } + // | }).play(); + // Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties + // are written using "mixed case", as the hyphen is illegal as an object key. + // + // example: + // Plug in a different easing function and register a callback for + // when the animation ends. Easing functions accept values between + // zero and one and return a value on that basis. In this case, an + // exponential-in curve. + // | dojo.animateProperty({ + // | node: "nodeId", + // | // dojo figures out the start value + // | properties: { width: { end: 400 } }, + // | easing: function(n){ + // | return (n==0) ? 0 : Math.pow(2, 10 * (n - 1)); + // | }, + // | onEnd: function(node){ + // | // called when the animation finishes. The animation + // | // target is passed to this function + // | } + // | }).play(500); // delay playing half a second + // + // example: + // Like all `dojo.Animation`s, animateProperty returns a handle to the + // Animation instance, which fires the events common to Dojo FX. Use `dojo.connect` + // to access these events outside of the Animation definiton: + // | var anim = dojo.animateProperty({ + // | node:"someId", + // | properties:{ + // | width:400, height:500 + // | } + // | }); + // | dojo.connect(anim,"onEnd", function(){ + // | console.log("animation ended"); + // | }); + // | // play the animation now: + // | anim.play(); + // + // example: + // Each property can be a function whose return value is substituted along. + // Additionally, each measurement (eg: start, end) can be a function. The node + // reference is passed direcly to callbacks. + // | dojo.animateProperty({ + // | node:"mine", + // | properties:{ + // | height:function(node){ + // | // shrink this node by 50% + // | return dojo.position(node).h / 2 + // | }, + // | width:{ + // | start:function(node){ return 100; }, + // | end:function(node){ return 200; } + // | } + // | } + // | }).play(); + // + + var n = args.node = d.byId(args.node); + if(!args.easing){ args.easing = d._defaultEasing; } + + var anim = new d.Animation(args); + d.connect(anim, "beforeBegin", anim, function(){ + var pm = {}; + for(var p in this.properties){ + // Make shallow copy of properties into pm because we overwrite + // some values below. In particular if start/end are functions + // we don't want to overwrite them or the functions won't be + // called if the animation is reused. + if(p == "width" || p == "height"){ + this.node.display = "block"; + } + var prop = this.properties[p]; + if(d.isFunction(prop)){ + prop = prop(n); + } + prop = pm[p] = _mixin({}, (d.isObject(prop) ? prop: { end: prop })); + + if(d.isFunction(prop.start)){ + prop.start = prop.start(n); + } + if(d.isFunction(prop.end)){ + prop.end = prop.end(n); + } + var isColor = (p.toLowerCase().indexOf("color") >= 0); + function getStyle(node, p){ + // dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable: + var v = { height: node.offsetHeight, width: node.offsetWidth }[p]; + if(v !== undefined){ return v; } + v = d.style(node, p); + return (p == "opacity") ? +v : (isColor ? v : parseFloat(v)); + } + if(!("end" in prop)){ + prop.end = getStyle(n, p); + }else if(!("start" in prop)){ + prop.start = getStyle(n, p); + } + + if(isColor){ + prop.start = new d.Color(prop.start); + prop.end = new d.Color(prop.end); + }else{ + prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start); + } + } + this.curve = new PropLine(pm); + }); + d.connect(anim, "onAnimate", d.hitch(d, "style", anim.node)); + return anim; // dojo.Animation + }; + + dojo.anim = function( /*DOMNode|String*/ node, + /*Object*/ properties, + /*Integer?*/ duration, + /*Function?*/ easing, + /*Function?*/ onEnd, + /*Integer?*/ delay){ + // summary: + // A simpler interface to `dojo.animateProperty()`, also returns + // an instance of `dojo.Animation` but begins the animation + // immediately, unlike nearly every other Dojo animation API. + // description: + // `dojo.anim` is a simpler (but somewhat less powerful) version + // of `dojo.animateProperty`. It uses defaults for many basic properties + // and allows for positional parameters to be used in place of the + // packed "property bag" which is used for other Dojo animation + // methods. + // + // The `dojo.Animation` object returned from `dojo.anim` will be + // already playing when it is returned from this function, so + // calling play() on it again is (usually) a no-op. + // node: + // a DOM node or the id of a node to animate CSS properties on + // duration: + // The number of milliseconds over which the animation + // should run. Defaults to the global animation default duration + // (350ms). + // easing: + // An easing function over which to calculate acceleration + // and deceleration of the animation through its duration. + // A default easing algorithm is provided, but you may + // plug in any you wish. A large selection of easing algorithms + // are available in `dojo.fx.easing`. + // onEnd: + // A function to be called when the animation finishes + // running. + // delay: + // The number of milliseconds to delay beginning the + // animation by. The default is 0. + // example: + // Fade out a node + // | dojo.anim("id", { opacity: 0 }); + // example: + // Fade out a node over a full second + // | dojo.anim("id", { opacity: 0 }, 1000); + return d.animateProperty({ // dojo.Animation + node: node, + duration: duration || d.Animation.prototype.duration, + properties: properties, + easing: easing, + onEnd: onEnd + }).play(delay || 0); + }; +})(); + +} + +if(!dojo._hasResource["dojo._base.browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base.browser"] = true; +dojo.provide("dojo._base.browser"); + + + + + + + + + + +//Need this to be the last code segment in base, so do not place any +//dojo.requireIf calls in this file. Otherwise, due to how the build system +//puts all requireIf dependencies after the current file, the require calls +//could be called before all of base is defined. +dojo.forEach(dojo.config.require, function(i){ + dojo["require"](i); +}); + +} + + //INSERT dojo.i18n._preloadLocalizations HERE + + //Check if document already complete, and if so, just trigger page load + //listeners. NOTE: does not work with Firefox before 3.6. To support + //those browsers, set djConfig.afterOnLoad = true when you know Dojo is added + //after page load. Using a timeout so the rest of this + //script gets evaluated properly. This work needs to happen after the + //dojo.config.require work done in dojo._base. + if(dojo.isBrowser && (document.readyState === "complete" || dojo.config.afterOnLoad)){ + window.setTimeout(dojo._loadInit, 100); + } +})(); + diff --git a/lib/dojo/fx.js b/lib/dojo/fx.js new file mode 100644 index 000000000..39ae253fd --- /dev/null +++ b/lib/dojo/fx.js @@ -0,0 +1,252 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.fx"]){ +dojo._hasResource["dojo.fx"]=true; +dojo.provide("dojo.fx"); +dojo.require("dojo.fx.Toggler"); +(function(){ +var d=dojo,_1={_fire:function(_2,_3){ +if(this[_2]){ +this[_2].apply(this,_3||[]); +} +return this; +}}; +var _4=function(_5){ +this._index=-1; +this._animations=_5||[]; +this._current=this._onAnimateCtx=this._onEndCtx=null; +this.duration=0; +d.forEach(this._animations,function(a){ +this.duration+=a.duration; +if(a.delay){ +this.duration+=a.delay; +} +},this); +}; +d.extend(_4,{_onAnimate:function(){ +this._fire("onAnimate",arguments); +},_onEnd:function(){ +d.disconnect(this._onAnimateCtx); +d.disconnect(this._onEndCtx); +this._onAnimateCtx=this._onEndCtx=null; +if(this._index+1==this._animations.length){ +this._fire("onEnd"); +}else{ +this._current=this._animations[++this._index]; +this._onAnimateCtx=d.connect(this._current,"onAnimate",this,"_onAnimate"); +this._onEndCtx=d.connect(this._current,"onEnd",this,"_onEnd"); +this._current.play(0,true); +} +},play:function(_6,_7){ +if(!this._current){ +this._current=this._animations[this._index=0]; +} +if(!_7&&this._current.status()=="playing"){ +return this; +} +var _8=d.connect(this._current,"beforeBegin",this,function(){ +this._fire("beforeBegin"); +}),_9=d.connect(this._current,"onBegin",this,function(_a){ +this._fire("onBegin",arguments); +}),_b=d.connect(this._current,"onPlay",this,function(_c){ +this._fire("onPlay",arguments); +d.disconnect(_8); +d.disconnect(_9); +d.disconnect(_b); +}); +if(this._onAnimateCtx){ +d.disconnect(this._onAnimateCtx); +} +this._onAnimateCtx=d.connect(this._current,"onAnimate",this,"_onAnimate"); +if(this._onEndCtx){ +d.disconnect(this._onEndCtx); +} +this._onEndCtx=d.connect(this._current,"onEnd",this,"_onEnd"); +this._current.play.apply(this._current,arguments); +return this; +},pause:function(){ +if(this._current){ +var e=d.connect(this._current,"onPause",this,function(_d){ +this._fire("onPause",arguments); +d.disconnect(e); +}); +this._current.pause(); +} +return this; +},gotoPercent:function(_e,_f){ +this.pause(); +var _10=this.duration*_e; +this._current=null; +d.some(this._animations,function(a){ +if(a.duration<=_10){ +this._current=a; +return true; +} +_10-=a.duration; +return false; +}); +if(this._current){ +this._current.gotoPercent(_10/this._current.duration,_f); +} +return this; +},stop:function(_11){ +if(this._current){ +if(_11){ +for(;this._index+1this._animations.length){ +this._fire("onEnd"); +} +},_call:function(_19,_1a){ +var t=this._pseudoAnimation; +t[_19].apply(t,_1a); +},play:function(_1b,_1c){ +this._finished=0; +this._doAction("play",arguments); +this._call("play",arguments); +return this; +},pause:function(){ +this._doAction("pause",arguments); +this._call("pause",arguments); +return this; +},gotoPercent:function(_1d,_1e){ +var ms=this.duration*_1d; +d.forEach(this._animations,function(a){ +a.gotoPercent(a.duration= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + + +if(!dojo._hasResource["dojo.fx.Toggler"]){ +dojo._hasResource["dojo.fx.Toggler"]=true; +dojo.provide("dojo.fx.Toggler"); +dojo.declare("dojo.fx.Toggler",null,{node:null,showFunc:dojo.fadeIn,hideFunc:dojo.fadeOut,showDuration:200,hideDuration:200,constructor:function(_1){ +var _2=this; +dojo.mixin(_2,_1); +_2.node=_1.node; +_2._showArgs=dojo.mixin({},_1); +_2._showArgs.node=_2.node; +_2._showArgs.duration=_2.showDuration; +_2.showAnim=_2.showFunc(_2._showArgs); +_2._hideArgs=dojo.mixin({},_1); +_2._hideArgs.node=_2.node; +_2._hideArgs.duration=_2.hideDuration; +_2.hideAnim=_2.hideFunc(_2._hideArgs); +dojo.connect(_2.showAnim,"beforeBegin",dojo.hitch(_2.hideAnim,"stop",true)); +dojo.connect(_2.hideAnim,"beforeBegin",dojo.hitch(_2.showAnim,"stop",true)); +},show:function(_3){ +return this.showAnim.play(_3||0); +},hide:function(_4){ +return this.hideAnim.play(_4||0); +}}); +} diff --git a/lib/dojo/fx/easing.js b/lib/dojo/fx/easing.js new file mode 100644 index 000000000..0de5d5e99 --- /dev/null +++ b/lib/dojo/fx/easing.js @@ -0,0 +1,166 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.fx.easing"]){ +dojo._hasResource["dojo.fx.easing"]=true; +dojo.provide("dojo.fx.easing"); +dojo.fx.easing={linear:function(n){ +return n; +},quadIn:function(n){ +return Math.pow(n,2); +},quadOut:function(n){ +return n*(n-2)*-1; +},quadInOut:function(n){ +n=n*2; +if(n<1){ +return Math.pow(n,2)/2; +} +return -1*((--n)*(n-2)-1)/2; +},cubicIn:function(n){ +return Math.pow(n,3); +},cubicOut:function(n){ +return Math.pow(n-1,3)+1; +},cubicInOut:function(n){ +n=n*2; +if(n<1){ +return Math.pow(n,3)/2; +} +n-=2; +return (Math.pow(n,3)+2)/2; +},quartIn:function(n){ +return Math.pow(n,4); +},quartOut:function(n){ +return -1*(Math.pow(n-1,4)-1); +},quartInOut:function(n){ +n=n*2; +if(n<1){ +return Math.pow(n,4)/2; +} +n-=2; +return -1/2*(Math.pow(n,4)-2); +},quintIn:function(n){ +return Math.pow(n,5); +},quintOut:function(n){ +return Math.pow(n-1,5)+1; +},quintInOut:function(n){ +n=n*2; +if(n<1){ +return Math.pow(n,5)/2; +} +n-=2; +return (Math.pow(n,5)+2)/2; +},sineIn:function(n){ +return -1*Math.cos(n*(Math.PI/2))+1; +},sineOut:function(n){ +return Math.sin(n*(Math.PI/2)); +},sineInOut:function(n){ +return -1*(Math.cos(Math.PI*n)-1)/2; +},expoIn:function(n){ +return (n==0)?0:Math.pow(2,10*(n-1)); +},expoOut:function(n){ +return (n==1)?1:(-1*Math.pow(2,-10*n)+1); +},expoInOut:function(n){ +if(n==0){ +return 0; +} +if(n==1){ +return 1; +} +n=n*2; +if(n<1){ +return Math.pow(2,10*(n-1))/2; +} +--n; +return (-1*Math.pow(2,-10*n)+2)/2; +},circIn:function(n){ +return -1*(Math.sqrt(1-Math.pow(n,2))-1); +},circOut:function(n){ +n=n-1; +return Math.sqrt(1-Math.pow(n,2)); +},circInOut:function(n){ +n=n*2; +if(n<1){ +return -1/2*(Math.sqrt(1-Math.pow(n,2))-1); +} +n-=2; +return 1/2*(Math.sqrt(1-Math.pow(n,2))+1); +},backIn:function(n){ +var s=1.70158; +return Math.pow(n,2)*((s+1)*n-s); +},backOut:function(n){ +n=n-1; +var s=1.70158; +return Math.pow(n,2)*((s+1)*n+s)+1; +},backInOut:function(n){ +var s=1.70158*1.525; +n=n*2; +if(n<1){ +return (Math.pow(n,2)*((s+1)*n-s))/2; +} +n-=2; +return (Math.pow(n,2)*((s+1)*n+s)+2)/2; +},elasticIn:function(n){ +if(n==0||n==1){ +return n; +} +var p=0.3; +var s=p/4; +n=n-1; +return -1*Math.pow(2,10*n)*Math.sin((n-s)*(2*Math.PI)/p); +},elasticOut:function(n){ +if(n==0||n==1){ +return n; +} +var p=0.3; +var s=p/4; +return Math.pow(2,-10*n)*Math.sin((n-s)*(2*Math.PI)/p)+1; +},elasticInOut:function(n){ +if(n==0){ +return 0; +} +n=n*2; +if(n==2){ +return 1; +} +var p=0.3*1.5; +var s=p/4; +if(n<1){ +n-=1; +return -0.5*(Math.pow(2,10*n)*Math.sin((n-s)*(2*Math.PI)/p)); +} +n-=1; +return 0.5*(Math.pow(2,-10*n)*Math.sin((n-s)*(2*Math.PI)/p))+1; +},bounceIn:function(n){ +return (1-dojo.fx.easing.bounceOut(1-n)); +},bounceOut:function(n){ +var s=7.5625; +var p=2.75; +var l; +if(n<(1/p)){ +l=s*Math.pow(n,2); +}else{ +if(n<(2/p)){ +n-=(1.5/p); +l=s*Math.pow(n,2)+0.75; +}else{ +if(n<(2.5/p)){ +n-=(2.25/p); +l=s*Math.pow(n,2)+0.9375; +}else{ +n-=(2.625/p); +l=s*Math.pow(n,2)+0.984375; +} +} +} +return l; +},bounceInOut:function(n){ +if(n<0.5){ +return dojo.fx.easing.bounceIn(n*2)/2; +} +return (dojo.fx.easing.bounceOut(n*2-1)/2)+0.5; +}}; +} diff --git a/lib/dojo/gears.js b/lib/dojo/gears.js new file mode 100644 index 000000000..4b70c14da --- /dev/null +++ b/lib/dojo/gears.js @@ -0,0 +1,45 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.gears"]){ +dojo._hasResource["dojo.gears"]=true; +dojo.provide("dojo.gears"); +dojo.gears._gearsObject=function(){ +var _1; +var _2; +var _3=dojo.getObject("google.gears"); +if(_3){ +return _3; +} +if(typeof GearsFactory!="undefined"){ +_1=new GearsFactory(); +}else{ +if(dojo.isIE){ +try{ +_1=new ActiveXObject("Gears.Factory"); +} +catch(e){ +} +}else{ +if(navigator.mimeTypes["application/x-googlegears"]){ +_1=document.createElement("object"); +_1.setAttribute("type","application/x-googlegears"); +_1.setAttribute("width",0); +_1.setAttribute("height",0); +_1.style.display="none"; +document.documentElement.appendChild(_1); +} +} +} +if(!_1){ +return null; +} +dojo.setObject("google.gears.factory",_1); +return dojo.getObject("google.gears"); +}; +dojo.gears.available=(!!dojo.gears._gearsObject())||0; +} diff --git a/lib/dojo/hash.js b/lib/dojo/hash.js new file mode 100644 index 000000000..b73d37058 --- /dev/null +++ b/lib/dojo/hash.js @@ -0,0 +1,137 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.hash"]){ +dojo._hasResource["dojo.hash"]=true; +dojo.provide("dojo.hash"); +(function(){ +dojo.hash=function(_1,_2){ +if(!arguments.length){ +return _3(); +} +if(_1.charAt(0)=="#"){ +_1=_1.substring(1); +} +if(_2){ +_4(_1); +}else{ +location.href="#"+_1; +} +return _1; +}; +var _5=null,_6=null,_7=dojo.config.hashPollFrequency||100; +function _8(_9,_a){ +var i=_9.indexOf(_a); +return (i>=0)?_9.substring(i+1):""; +}; +function _3(){ +return _8(location.href,"#"); +}; +function _b(){ +dojo.publish("/dojo/hashchange",[_3()]); +}; +function _c(){ +if(_3()===_5){ +return; +} +_5=_3(); +_b(); +}; +function _4(_d){ +if(_6){ +if(_6.isTransitioning()){ +setTimeout(dojo.hitch(null,_4,_d),_7); +return; +} +var _e=_6.iframe.location.href; +var _f=_e.indexOf("?"); +_6.iframe.location.replace(_e.substring(0,_f)+"?"+_d); +return; +} +location.replace("#"+_d); +_c(); +}; +function _10(){ +var ifr=document.createElement("iframe"),_11="dojo-hash-iframe",_12=dojo.config.dojoBlankHtmlUrl||dojo.moduleUrl("dojo","resources/blank.html"); +ifr.id=_11; +ifr.src=_12+"?"+_3(); +ifr.style.display="none"; +document.body.appendChild(ifr); +this.iframe=dojo.global[_11]; +var _13,_14,_15,_16,_17,_18=this.iframe.location; +function _19(){ +_5=_3(); +_13=_17?_5:_8(_18.href,"?"); +_14=false; +_15=null; +}; +this.isTransitioning=function(){ +return _14; +}; +this.pollLocation=function(){ +if(!_17){ +try{ +var _1a=_8(_18.href,"?"); +if(document.title!=_16){ +_16=this.iframe.document.title=document.title; +} +} +catch(e){ +_17=true; +console.error("dojo.hash: Error adding history entry. Server unreachable."); +} +} +var _1b=_3(); +if(_14&&_5===_1b){ +if(_17||_1a===_15){ +_19(); +_b(); +}else{ +setTimeout(dojo.hitch(this,this.pollLocation),0); +return; +} +}else{ +if(_5===_1b&&(_17||_13===_1a)){ +}else{ +if(_5!==_1b){ +_5=_1b; +_14=true; +_15=_1b; +ifr.src=_12+"?"+_15; +_17=false; +setTimeout(dojo.hitch(this,this.pollLocation),0); +return; +}else{ +if(!_17){ +location.href="#"+_18.search.substring(1); +_19(); +_b(); +} +} +} +} +setTimeout(dojo.hitch(this,this.pollLocation),_7); +}; +_19(); +setTimeout(dojo.hitch(this,this.pollLocation),_7); +}; +dojo.addOnLoad(function(){ +if("onhashchange" in dojo.global&&(!dojo.isIE||(dojo.isIE>=8&&document.compatMode!="BackCompat"))){ +dojo.connect(dojo.global,"onhashchange",_b); +}else{ +if(document.addEventListener){ +_5=_3(); +setInterval(_c,_7); +}else{ +if(document.attachEvent){ +_6=new _10(); +} +} +} +}); +})(); +} diff --git a/lib/dojo/html.js b/lib/dojo/html.js new file mode 100644 index 000000000..7c15e5812 --- /dev/null +++ b/lib/dojo/html.js @@ -0,0 +1,145 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.html"]){ +dojo._hasResource["dojo.html"]=true; +dojo.provide("dojo.html"); +dojo.require("dojo.parser"); +(function(){ +var _1=0,d=dojo; +dojo.html._secureForInnerHtml=function(_2){ +return _2.replace(/(?:\s*]+>|]*>[\s\S]*?<\/title>)/ig,""); +}; +dojo.html._emptyNode=dojo.empty; +dojo.html._setNodeContent=function(_3,_4){ +d.empty(_3); +if(_4){ +if(typeof _4=="string"){ +_4=d._toDom(_4,_3.ownerDocument); +} +if(!_4.nodeType&&d.isArrayLike(_4)){ +for(var _5=_4.length,i=0;i<_4.length;i=_5==_4.length?i+1:0){ +d.place(_4[i],_3,"last"); +} +}else{ +d.place(_4,_3,"last"); +} +} +return _3; +}; +dojo.declare("dojo.html._ContentSetter",null,{node:"",content:"",id:"",cleanContent:false,extractContent:false,parseContent:false,constructor:function(_6,_7){ +dojo.mixin(this,_6||{}); +_7=this.node=dojo.byId(this.node||_7); +if(!this.id){ +this.id=["Setter",(_7)?_7.id||_7.tagName:"",_1++].join("_"); +} +},set:function(_8,_9){ +if(undefined!==_8){ +this.content=_8; +} +if(_9){ +this._mixin(_9); +} +this.onBegin(); +this.setContent(); +this.onEnd(); +return this.node; +},setContent:function(){ +var _a=this.node; +if(!_a){ +throw new Error(this.declaredClass+": setContent given no node"); +} +try{ +_a=dojo.html._setNodeContent(_a,this.content); +} +catch(e){ +var _b=this.onContentError(e); +try{ +_a.innerHTML=_b; +} +catch(e){ +console.error("Fatal "+this.declaredClass+".setContent could not change content due to "+e.message,e); +} +} +this.node=_a; +},empty:function(){ +if(this.parseResults&&this.parseResults.length){ +dojo.forEach(this.parseResults,function(w){ +if(w.destroy){ +w.destroy(); +} +}); +delete this.parseResults; +} +dojo.html._emptyNode(this.node); +},onBegin:function(){ +var _c=this.content; +if(dojo.isString(_c)){ +if(this.cleanContent){ +_c=dojo.html._secureForInnerHtml(_c); +} +if(this.extractContent){ +var _d=_c.match(/]*>\s*([\s\S]+)\s*<\/body>/im); +if(_d){ +_c=_d[1]; +} +} +} +this.empty(); +this.content=_c; +return this.node; +},onEnd:function(){ +if(this.parseContent){ +this._parse(); +} +return this.node; +},tearDown:function(){ +delete this.parseResults; +delete this.node; +delete this.content; +},onContentError:function(_e){ +return "Error occured setting content: "+_e; +},_mixin:function(_f){ +var _10={},key; +for(key in _f){ +if(key in _10){ +continue; +} +this[key]=_f[key]; +} +},_parse:function(){ +var _11=this.node; +try{ +this.parseResults=dojo.parser.parse({rootNode:_11,dir:this.dir,lang:this.lang}); +} +catch(e){ +this._onError("Content",e,"Error parsing in _ContentSetter#"+this.id); +} +},_onError:function(_12,err,_13){ +var _14=this["on"+_12+"Error"].call(this,err); +if(_13){ +console.error(_13,err); +}else{ +if(_14){ +dojo.html._setNodeContent(this.node,_14,true); +} +} +}}); +dojo.html.set=function(_15,_16,_17){ +if(undefined==_16){ +console.warn("dojo.html.set: no cont argument provided, using empty string"); +_16=""; +} +if(!_17){ +return dojo.html._setNodeContent(_15,_16,true); +}else{ +var op=new dojo.html._ContentSetter(dojo.mixin(_17,{content:_16,node:_15})); +return op.set(); +} +}; +})(); +} diff --git a/lib/dojo/i18n.js b/lib/dojo/i18n.js new file mode 100644 index 000000000..e914392a1 --- /dev/null +++ b/lib/dojo/i18n.js @@ -0,0 +1,171 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.i18n"]){ +dojo._hasResource["dojo.i18n"]=true; +dojo.provide("dojo.i18n"); +dojo.i18n.getLocalization=function(_1,_2,_3){ +_3=dojo.i18n.normalizeLocale(_3); +var _4=_3.split("-"); +var _5=[_1,"nls",_2].join("."); +var _6=dojo._loadedModules[_5]; +if(_6){ +var _7; +for(var i=_4.length;i>0;i--){ +var _8=_4.slice(0,i).join("_"); +if(_6[_8]){ +_7=_6[_8]; +break; +} +} +if(!_7){ +_7=_6.ROOT; +} +if(_7){ +var _9=function(){ +}; +_9.prototype=_7; +return new _9(); +} +} +throw new Error("Bundle not found: "+_2+" in "+_1+" , locale="+_3); +}; +dojo.i18n.normalizeLocale=function(_a){ +var _b=_a?_a.toLowerCase():dojo.locale; +if(_b=="root"){ +_b="ROOT"; +} +return _b; +}; +dojo.i18n._requireLocalization=function(_c,_d,_e,_f){ +var _10=dojo.i18n.normalizeLocale(_e); +var _11=[_c,"nls",_d].join("."); +var _12=""; +if(_f){ +var _13=_f.split(","); +for(var i=0;i<_13.length;i++){ +if(_10["indexOf"](_13[i])==0){ +if(_13[i].length>_12.length){ +_12=_13[i]; +} +} +} +if(!_12){ +_12="ROOT"; +} +} +var _14=_f?_12:_10; +var _15=dojo._loadedModules[_11]; +var _16=null; +if(_15){ +if(dojo.config.localizationComplete&&_15._built){ +return; +} +var _17=_14.replace(/-/g,"_"); +var _18=_11+"."+_17; +_16=dojo._loadedModules[_18]; +} +if(!_16){ +_15=dojo["provide"](_11); +var _19=dojo._getModuleSymbols(_c); +var _1a=_19.concat("nls").join("/"); +var _1b; +dojo.i18n._searchLocalePath(_14,_f,function(loc){ +var _1c=loc.replace(/-/g,"_"); +var _1d=_11+"."+_1c; +var _1e=false; +if(!dojo._loadedModules[_1d]){ +dojo["provide"](_1d); +var _1f=[_1a]; +if(loc!="ROOT"){ +_1f.push(loc); +} +_1f.push(_d); +var _20=_1f.join("/")+".js"; +_1e=dojo._loadPath(_20,null,function(_21){ +var _22=function(){ +}; +_22.prototype=_1b; +_15[_1c]=new _22(); +for(var j in _21){ +_15[_1c][j]=_21[j]; +} +}); +}else{ +_1e=true; +} +if(_1e&&_15[_1c]){ +_1b=_15[_1c]; +}else{ +_15[_1c]=_1b; +} +if(_f){ +return true; +} +}); +} +if(_f&&_10!=_12){ +_15[_10.replace(/-/g,"_")]=_15[_12.replace(/-/g,"_")]; +} +}; +(function(){ +var _23=dojo.config.extraLocale; +if(_23){ +if(!_23 instanceof Array){ +_23=[_23]; +} +var req=dojo.i18n._requireLocalization; +dojo.i18n._requireLocalization=function(m,b,_24,_25){ +req(m,b,_24,_25); +if(_24){ +return; +} +for(var i=0;i<_23.length;i++){ +req(m,b,_23[i],_25); +} +}; +} +})(); +dojo.i18n._searchLocalePath=function(_26,_27,_28){ +_26=dojo.i18n.normalizeLocale(_26); +var _29=_26.split("-"); +var _2a=[]; +for(var i=_29.length;i>0;i--){ +_2a.push(_29.slice(0,i).join("-")); +} +_2a.push(false); +if(_27){ +_2a.reverse(); +} +for(var j=_2a.length-1;j>=0;j--){ +var loc=_2a[j]||"ROOT"; +var _2b=_28(loc); +if(_2b){ +break; +} +} +}; +dojo.i18n._preloadLocalizations=function(_2c,_2d){ +function _2e(_2f){ +_2f=dojo.i18n.normalizeLocale(_2f); +dojo.i18n._searchLocalePath(_2f,true,function(loc){ +for(var i=0;i<_2d.length;i++){ +if(_2d[i]==loc){ +dojo["require"](_2c+"_"+loc); +return true; +} +} +return false; +}); +}; +_2e(); +var _30=dojo.config.extraLocale||[]; +for(var i=0;i<_30.length;i++){ +_2e(_30[i]); +} +}; +} diff --git a/lib/dojo/io/iframe.js b/lib/dojo/io/iframe.js new file mode 100644 index 000000000..105af1697 --- /dev/null +++ b/lib/dojo/io/iframe.js @@ -0,0 +1,265 @@ +/* + Copyright (c) 2004-2010, 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 +*/ + + +if(!dojo._hasResource["dojo.io.iframe"]){ +dojo._hasResource["dojo.io.iframe"]=true; +dojo.provide("dojo.io.iframe"); +dojo.io.iframe={create:function(_1,_2,_3){ +if(window[_1]){ +return window[_1]; +} +if(window.frames[_1]){ +return window.frames[_1]; +} +var _4=null; +var _5=_3; +if(!_5){ +if(dojo.config["useXDomain"]&&!dojo.config["dojoBlankHtmlUrl"]){ +console.warn("dojo.io.iframe.create: When using cross-domain Dojo builds,"+" please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"+" to the path on your domain to blank.html"); +} +_5=(dojo.config["dojoBlankHtmlUrl"]||dojo.moduleUrl("dojo","resources/blank.html")); +} +var _6=dojo.isIE?"