You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by bu...@apache.org on 2017/05/17 15:33:04 UTC

svn commit: r1012387 [4/29] - in /websites/staging/ooo-site/trunk: cgi-bin/ content/ content/scripts/api.simile-widgets.org/ content/scripts/api.simile-widgets.org/ajax/ content/scripts/api.simile-widgets.org/ajax/2.2.1.fake/ content/scripts/api.simile...

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1.fake/simile-ajax-bundle.js
==============================================================================
--- websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1.fake/simile-ajax-bundle.js (added)
+++ websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1.fake/simile-ajax-bundle.js Wed May 17 15:33:02 2017
@@ -0,0 +1 @@
+define("scripts/simile-ajax-base",[],function(){var e={loaded:!1,loadingScriptsCount:0,error:null,params:{bundle:!0},paramTypes:{bundle:Boolean},version:"3.0.0",jQuery:null,urlPrefix:null};return e}),define("scripts/platform",[],function(){var e={};return e.os={isMac:!1,isWin:!1,isWin32:!1,isUnix:!1},e.browser={isIE:!1,isNetscape:!1,isMozilla:!1,isFirefox:!1,isOpera:!1,isSafari:!1,majorVersion:0,minorVersion:0},function(){var t=navigator.appName.toLowerCase(),n=navigator.userAgent.toLowerCase();e.os.isMac=n.indexOf("mac")!=-1,e.os.isWin=n.indexOf("win")!=-1,e.os.isWin32=e.isWin&&(n.indexOf("95")!=-1||n.indexOf("98")!=-1||n.indexOf("nt")!=-1||n.indexOf("win32")!=-1||n.indexOf("32bit")!=-1),e.os.isUnix=n.indexOf("x11")!=-1,e.browser.isIE=t.indexOf("microsoft")!=-1,e.browser.isNetscape=t.indexOf("netscape")!=-1,e.browser.isMozilla=n.indexOf("mozilla")!=-1,e.browser.isFirefox=n.indexOf("firefox")!=-1,e.browser.isOpera=t.indexOf("opera")!=-1,e.browser.isSafari=t.indexOf("safari")!=-1;var
  r=function(t){var n=t.split(".");e.browser.majorVersion=parseInt(n[0]),e.browser.minorVersion=parseInt(n[1])},i=function(e,t,n){var r=e.indexOf(t,n);return r>=0?r:e.length};if(e.browser.isMozilla){var s=n.indexOf("mozilla/");s>=0&&r(n.substring(s+8,i(n," ",s)))}if(e.browser.isIE){var s=n.indexOf("msie ");s>=0&&r(n.substring(s+5,i(n,";",s)))}if(e.browser.isNetscape){var s=n.indexOf("rv:");s>=0&&r(n.substring(s+3,i(n,")",s)))}if(e.browser.isFirefox){var s=n.indexOf("firefox/");s>=0&&r(n.substring(s+8,i(n," ",s)))}"localeCompare"in String.prototype||(String.prototype.localeCompare=function(e){return this<e?-1:this>e?1:0})}(),e.getDefaultLocale=function(){return e.clientLocale},e}),define("scripts/debug",["./simile-ajax-base"],function(e){var t={silent:!1};return t.log=function(e){var n;"console"in window&&"log"in window.console?n=function(e){console.log(e)}:n=function(e){t.silent||alert(e)},t.log=n,n(e)},t.warn=function(e){var n;"console"in window&&"warn"in window.console?n=function(e
 ){console.warn(e)}:n=function(e){t.silent||alert(e)},t.warn=n,n(e)},t.exception=function(n,r){var i,s=e.parseURLParameters();s.errors=="throw"||e.params.errors=="throw"?i=function(e,t){throw e}:"console"in window&&"error"in window.console?i=function(e,t){throw t!=null?console.error(t+" %o",e):console.error(e),e}:i=function(e,n){throw t.silent||alert("Caught exception: "+n+"\n\nDetails: "+("description"in e?e.description:e)),e},t.exception=i,i(n,r)},t.objectToString=function(e){return t._objectToString(e,"")},t._objectToString=function(e,n){var r=n+" ";if(typeof e=="object"){var i="{";for(s in e)i+=r+s+": "+t._objectToString(e[s],r)+"\n";return i+=n+"}",i}if(typeof e=="array"){var i="[";for(var s=0;s<e.length;s++)i+=t._objectToString(e[s],r)+"\n";return i+=n+"]",i}return e},t}),define("scripts/xmlhttp",["./debug","./platform"],function(e,t){var n=new Object;return n._onReadyStateChange=function(t,n,r){switch(t.readyState){case 4:try{t.status==0||t.status==200?r&&r(t):n&&n(t.statusTex
 t,t.status,t)}catch(i){e.exception("XmlHttp: Error handling onReadyStateChange",i)}}},n._createRequest=function(){if(t.browser.isIE){var e=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];for(var r=0;r<e.length;r++)try{var i=e[r],s=function(){return new ActiveXObject(i)},o=s();return n._createRequest=s,o}catch(u){}}try{var s=function(){return new XMLHttpRequest},o=s();return n._createRequest=s,o}catch(u){throw new Error("Failed to create an XMLHttpRequest object")}},n.get=function(e,t,r){var i=n._createRequest();i.open("GET",e,!0),i.onreadystatechange=function(){n._onReadyStateChange(i,t,r)},i.send(null)},n.post=function(e,t,r,i){var s=n._createRequest();s.open("POST",e,!0),s.onreadystatechange=function(){n._onReadyStateChange(s,r,i)},s.send(t)},n._forceXML=function(e){try{e.overrideMimeType("text/xml")}catch(t){e.setrequestheader("Content-Type","text/xml")}},n}),define("scripts/dom",["./platform"],function(e){var t=new Object;return t.registerEventWithObject=function(e,n
 ,r,i){t.registerEvent(e,n,function(e,t,n){return r[i].call(r,e,t,n)})},t.registerEvent=function(t,n,r){var i=function(e){e=e?e:event?event:null;if(e){var n=e.target?e.target:e.srcElement?e.srcElement:null;return n&&(n=n.nodeType==1||n.nodeType==9?n:n.parentNode),r(t,e,n)}return!0};e.browser.isIE?t.attachEvent("on"+n,i):t.addEventListener(n,i,!1)},t.getPageCoordinates=function(e){var t=0,n=0;e.nodeType!=1&&(e=e.parentNode);var r=e;while(r!=null)t+=r.offsetLeft,n+=r.offsetTop,r=r.offsetParent;var i=document.body;while(e!=null&&e!=i)"scrollLeft"in e&&(t-=e.scrollLeft,n-=e.scrollTop),e=e.parentNode;return{left:t,top:n}},t.getSize=function(e){var t=this.getStyle(e,"width"),n=this.getStyle(e,"height");return t.indexOf("px")>-1&&(t=t.replace("px","")),n.indexOf("px")>-1&&(n=n.replace("px","")),{w:t,h:n}},t.getStyle=function(e,t){if(e.currentStyle)var n=e.currentStyle[t];else if(window.getComputedStyle)var n=document.defaultView.getComputedStyle(e,null).getPropertyValue(t);else var n="";ret
 urn n},t.getEventRelativeCoordinates=function(n,r){if(e.browser.isIE){if(n.type=="mousewheel"){var i=t.getPageCoordinates(r);return{x:n.clientX-i.left,y:n.clientY-i.top}}return{x:n.offsetX,y:n.offsetY}}var i=t.getPageCoordinates(r);return n.type=="DOMMouseScroll"&&e.browser.isFirefox&&e.browser.majorVersion==2?{x:n.screenX-i.left,y:n.screenY-i.top}:{x:n.pageX-i.left,y:n.pageY-i.top}},t.getEventPageCoordinates=function(t){if(e.browser.isIE){var n=0,r=0;return document.body&&(document.body.scrollLeft||document.body.scrollTop)?(n=document.body.scrollTop,r=document.body.scrollLeft):document.documentElement&&(document.documentElement.scrollLeft||document.documentElement.scrollTop)&&(n=document.documentElement.scrollTop,r=document.documentElement.scrollLeft),{x:t.clientX+r,y:t.clientY+n}}return{x:t.pageX,y:t.pageY}},t.hittest=function(e,n,r){return t._hittest(document.body,e,n,r)},t._hittest=function(e,n,r,i){var s=e.childNodes;e:for(var o=0;o<s.length;o++){var u=s[o];for(var a=0;a<i.leng
 th;a++)if(u==i[a])continue e;if(u.offsetWidth==0&&u.offsetHeight==0){var f=t._hittest(u,n,r,i);if(f!=u)return f}else{var l=0,c=0,h=u;while(h)l+=h.offsetTop,c+=h.offsetLeft,h=h.offsetParent;if(c<=n&&l<=r&&n-c<u.offsetWidth&&r-l<u.offsetHeight)return t._hittest(u,n,r,i);if(u.nodeType==1&&u.tagName=="TR"){var p=t._hittest(u,n,r,i);if(p!=u)return p}}}return e},t.cancelEvent=function(e){e.returnValue=!1,e.cancelBubble=!0,"preventDefault"in e&&e.preventDefault()},t.appendClassName=function(e,t){var n=e.className.split(" ");for(var r=0;r<n.length;r++)if(n[r]==t)return;n.push(t),e.className=n.join(" ")},t.createInputElement=function(e){var t=document.createElement("div");return t.innerHTML="<input type='"+e+"' />",t.firstChild},t.createDOMFromTemplate=function(e){var n={};return n.elmt=t._createDOMFromTemplate(e,n,null),n},t._createDOMFromTemplate=function(r,i,s){if(r==null)return null;if(typeof r!="object"){var o=document.createTextNode(r);return s!=null&&s.appendChild(o),o}var u=null;if("
 tag"in r){var a=r.tag;s!=null&&(a=="tr"?u=s.insertRow(s.rows.length):a=="td"&&(u=s.insertCell(s.cells.length))),u==null&&(u=a=="input"?t.createInputElement(r.type):document.createElement(a),s!=null&&s.appendChild(u))}else u=r.elmt,s!=null&&s.appendChild(u);for(var f in r){var l=r[f];if(f=="field")i[l]=u;else if(f=="className")u.className=l;else if(f=="id")u.id=l;else if(f=="title")u.title=l;else if(f!="type"||u.tagName!="input")if(f=="style")for(n in l){var c=l[n];n=="float"&&(n=e.browser.isIE?"styleFloat":"cssFloat"),u.style[n]=c}else if(f=="children")for(var h=0;h<l.length;h++)t._createDOMFromTemplate(l[h],i,u);else f!="tag"&&f!="elmt"&&u.setAttribute(f,l)}return u},t._cachedParent=null,t.createElementFromString=function(e){return t._cachedParent==null&&(t._cachedParent=document.createElement("div")),t._cachedParent.innerHTML=e,t._cachedParent.firstChild},t.createDOMFromString=function(e,n,r){var i=typeof e=="string"?document.createElement(e):e;i.innerHTML=n;var s={elmt:i};return 
 t._processDOMChildrenConstructedFromString(s,i,r!=null?r:{}),s},t._processDOMConstructedFromString=function(e,n,r){var i=n.id;if(i!=null&&i.length>0){n.removeAttribute("id");if(i in r){var s=n.parentNode;s.insertBefore(r[i],n),s.removeChild(n),e[i]=r[i];return}e[i]=n}n.hasChildNodes()&&t._processDOMChildrenConstructedFromString(e,n,r)},t._processDOMChildrenConstructedFromString=function(e,n,r){var i=n.firstChild;while(i!=null){var s=i.nextSibling;i.nodeType==1&&t._processDOMConstructedFromString(e,i,r),i=s}},t}),define("scripts/graphics",["./simile-ajax-base","./platform"],function(e,t){var n={pngIsTranslucent:undefined,createTranslucentImage:undefined,createTranslucentImageHTML:undefined};return n._createTranslucentImage1=function(e,t){var n=document.createElement("img");return n.setAttribute("src",e),t!=null&&(n.style.verticalAlign=t),n},n._createTranslucentImage2=function(e,t){var n=document.createElement("img");return n.style.width="1px",n.style.height="1px",n.style.filter="prog
 id:DXImageTransform.Microsoft.AlphaImageLoader(src='"+e+"', sizingMethod='image')",n.style.verticalAlign=t!=null?t:"middle",n},n._createTranslucentImageHTML1=function(e,t){return'<img src="'+e+'"'+(t!=null?' style="vertical-align: '+t+';"':"")+" />"},n._createTranslucentImageHTML2=function(e,t){var n="width: 1px; height: 1px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+e+"', sizingMethod='image');"+(t!=null?" vertical-align: "+t+";":"");return"<img src='"+e+"' style=\""+n+'" />'},n.initialize=function(n){return n.pngIsTranslucent=!t.browser.isIE||t.browser.majorVersion>6,n.pngIsTranslucent||includeCssFile(document,e.urlPrefix+"styles/graphics-ie6.css"),n.createTranslucentImage=n.pngIsTranslucent?n._createTranslucentImage1:n._createTranslucentImage2,n.createTranslucentImageHTML=n.pngIsTranslucent?n._createTranslucentImageHTML1:n._createTranslucentImageHTML2,n},n.setOpacity=function(e,n){if(t.browser.isIE)e.style.filter="progid:DXImageTransform.Microsoft.Alpha(Sty
 le=0,Opacity="+n+")";else{var r=(n/100).toString();e.style.opacity=r,e.style.MozOpacity=r}},n.bubbleConfig={containerCSSClass:"simileAjax-bubble-container",innerContainerCSSClass:"simileAjax-bubble-innerContainer",contentContainerCSSClass:"simileAjax-bubble-contentContainer",borderGraphicSize:50,borderGraphicCSSClassPrefix:"simileAjax-bubble-border-",arrowGraphicTargetOffset:33,arrowGraphicLength:100,arrowGraphicWidth:49,arrowGraphicCSSClassPrefix:"simileAjax-bubble-arrow-",closeGraphicCSSClass:"simileAjax-bubble-close",extraPadding:20},n.getWindowDimensions=function(){if(typeof window.innerHeight=="number")return{w:window.innerWidth,h:window.innerHeight};if(document.documentElement&&document.documentElement.clientHeight)return{w:document.documentElement.clientWidth,h:document.documentElement.clientHeight};if(document.body&&document.body.clientHeight)return{w:document.body.clientWidth,h:document.body.clientHeight}},n.createMessageBubble=function(e){var t=e.createElement("div"),r="si
 mileAjax-messageBubble";if(n.pngIsTranslucent){var i=e.createElement("div");i.className=r+"-top",t.appendChild(i);var s=e.createElement("div");s.className=r+"-top-right",i.appendChild(s);var o=e.createElement("div");o.className=r+"-middle",t.appendChild(o);var u=e.createElement("div");u.className=r+"-middle-right",o.appendChild(u);var a=e.createElement("div");u.appendChild(a);var f=e.createElement("div");f.className=r+"-bottom",t.appendChild(f);var l=e.createElement("div");l.className=r+"-bottom-right",f.appendChild(l)}else{t.style.border="2px solid #7777AA",t.style.padding="20px",t.style.background="white",n.setOpacity(t,90);var a=e.createElement("div");t.appendChild(a)}return{containerDiv:t,contentDiv:a}},n.createAnimation=function(e,t,r,i,s){return new n._Animation(e,t,r,i,s)},n._Animation=function(e,t,n,r,i){this.f=e,this.cont=typeof i=="function"?i:function(){},this.from=t,this.to=n,this.current=t,this.duration=r,this.start=(new Date).getTime(),this.timePassed=0},n._Animation.p
 rototype.run=function(){var e=this;window.setTimeout(function(){e.step()},50)},n._Animation.prototype.step=function(){this.timePassed+=50;var e=this.timePassed/this.duration,t=-Math.cos(e*Math.PI)/2+.5,n=t*(this.to-this.from)+this.from;try{this.f(n,n-this.current)}catch(r){}this.current=n,this.timePassed<this.duration?this.run():(this.f(this.to,0),this.cont())},n.createStructuredDataCopyButton=function(e,r,i,s){var o=document.createElement("div");o.style.position="relative",o.style.display="inline",o.style.width=r+"px",o.style.height=i+"px",o.style.overflow="hidden",o.style.margin="2px",n.pngIsTranslucent?o.style.background="url("+e+") no-repeat":o.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+e+"', sizingMethod='image')";var u;t.browser.isIE?u="filter:alpha(opacity=0)":u="opacity: 0",o.innerHTML="<textarea rows='1' autocomplete='off' value='none' style='"+u+"' />";var a=o.firstChild;return a.style.width=r+"px",a.style.height=i+"px",a.onmousedown=function(e
 ){e=e?e:event?event:null,e.button==2&&(a.value=s(),a.select())},o},n.getWidthHeight=function(e){var t,n;if(e.getBoundingClientRect==null)t=e.offsetWidth,n=e.offsetHeight;else{var r=e.getBoundingClientRect();t=Math.ceil(r.right-r.left),n=Math.ceil(r.bottom-r.top)}return{width:t,height:n}},n.getFontRenderingContext=function(e,t){return new n._FontRenderingContext(e,t)},n._FontRenderingContext=function(e,t){this._elmt=e,this._elmt.style.visibility="hidden",typeof t=="string"?this._elmt.style.width=t:typeof t=="number"&&(this._elmt.style.width=t+"px")},n._FontRenderingContext.prototype.dispose=function(){this._elmt=null},n._FontRenderingContext.prototype.update=function(){this._elmt.innerHTML="A",this._lineHeight=this._elmt.offsetHeight},n._FontRenderingContext.prototype.computeSize=function(e,t){var r=this._elmt;r.innerHTML=e,r.className=t===undefined?"":t;var i=n.getWidthHeight(r);return r.className="",i},n._FontRenderingContext.prototype.getLineHeight=function(){return this._lineHeig
 ht},n}),define("scripts/window-manager",["./dom","./debug","./graphics","./simile-ajax-base"],function(e,t,n,r){var i={_initialized:!1,_listeners:[],_draggedElement:null,_draggedElementCallback:null,_dropTargetHighlightElement:null,_lastCoords:null,_ghostCoords:null,_draggingMode:"",_dragging:!1,_layers:[]};return i.initialize=function(){if(i._initialized)return;e.registerEvent(document.body,"mousedown",i._onBodyMouseDown),e.registerEvent(document.body,"mousemove",i._onBodyMouseMove),e.registerEvent(document.body,"mouseup",i._onBodyMouseUp),e.registerEvent(document,"keydown",i._onBodyKeyDown),e.registerEvent(document,"keyup",i._onBodyKeyUp),i._layers.push({index:0}),i._initialized=!0},i.getBaseLayer=function(){return i._layers[0]},i.getHighestLayer=function(){return i._layers[i._layers.length-1]},i.registerEventWithObject=function(e,t,n,r,s){i.registerEvent(e,t,function(e,t,i){return n[r].call(n,e,t,i)},s)},i.registerEvent=function(n,r,s,o){o==null&&(o=i.getHighestLayer());var u=fun
 ction(n,r,u){if(i._canProcessEventAtLayer(o)){i._popToLayer(o.index);try{s(n,r,u)}catch(a){t.exception(a)}}return e.cancelEvent(r),!1};e.registerEvent(n,r,u)},i.pushLayer=function(e,t,n){var r={onPop:e,index:i._layers.length,ephemeral:t,elmt:n};return i._layers.push(r),r},i.popLayer=function(e){for(var t=1;t<i._layers.length;t++)if(i._layers[t]==e){i._popToLayer(t-1);break}},i.popAllLayers=function(){i._popToLayer(0)},i.registerForDragging=function(e,t,n){i.registerEvent(e,"mousedown",function(e,n,r){i._handleMouseDown(e,n,t)},n)},i._popToLayer=function(e){while(e+1<i._layers.length)try{var t=i._layers.pop();t.onPop!=null&&t.onPop()}catch(n){}},i._canProcessEventAtLayer=function(e){if(e.index==i._layers.length-1)return!0;for(var t=e.index+1;t<i._layers.length;t++)if(!i._layers[t].ephemeral)return!1;return!0},i.cancelPopups=function(t){var n=t?e.getEventPageCoordinates(t):{x:-1,y:-1},r=i._layers.length-1;while(r>0&&i._layers[r].ephemeral){var s=i._layers[r];if(s.elmt!=null){var o=s.e
 lmt,u=e.getPageCoordinates(o);if(n.x>=u.left&&n.x<u.left+o.offsetWidth&&n.y>=u.top&&n.y<u.top+o.offsetHeight)break}r--}i._popToLayer(r)},i._onBodyMouseDown=function(e,t,n){(!("eventPhase"in t)||t.eventPhase==t.BUBBLING_PHASE)&&i.cancelPopups(t)},i._handleMouseDown=function(t,n,r){return i._draggedElement=t,i._draggedElementCallback=r,i._lastCoords={x:n.clientX,y:n.clientY},e.cancelEvent(n),!1},i._onBodyKeyDown=function(e,t,s){if(i._dragging)if(t.keyCode==27)i._cancelDragging();else if((t.keyCode==17||t.keyCode==16)&&i._draggingMode!="copy"){i._draggingMode="copy";var o=n.createTranslucentImage(r.urlPrefix+"images/copy.png");o.style.position="absolute",o.style.left=i._ghostCoords.left-16+"px",o.style.top=i._ghostCoords.top+"px",document.body.appendChild(o),i._draggingModeIndicatorElmt=o}},i._onBodyKeyUp=function(e,t,n){i._dragging&&(t.keyCode==17||t.keyCode==16)&&(i._draggingMode="",i._draggingModeIndicatorElmt!=null&&(document.body.removeChild(i._draggingModeIndicatorElmt),i._draggi
 ngModeIndicatorElmt=null))},i._onBodyMouseMove=function(r,s,o){if(i._draggedElement!=null){var u=i._draggedElementCallback,a=i._lastCoords,f=s.clientX-a.x,l=s.clientY-a.y;if(!i._dragging){if(Math.abs(f)>5||Math.abs(l)>5)try{"onDragStart"in u&&u.onDragStart();if("ghost"in u&&u.ghost){var c=i._draggedElement;i._ghostCoords=e.getPageCoordinates(c),i._ghostCoords.left+=f,i._ghostCoords.top+=l;var h=c.cloneNode(!0);h.style.position="absolute",h.style.left=i._ghostCoords.left+"px",h.style.top=i._ghostCoords.top+"px",h.style.zIndex=1e3,n.setOpacity(h,50),document.body.appendChild(h),u._ghostElmt=h}i._dragging=!0,i._lastCoords={x:s.clientX,y:s.clientY},document.body.focus()}catch(p){t.exception("WindowManager: Error handling mouse down",p),i._cancelDragging()}}else try{i._lastCoords={x:s.clientX,y:s.clientY},"onDragBy"in u&&u.onDragBy(f,l);if("_ghostElmt"in u){var h=u._ghostElmt;i._ghostCoords.left+=f,i._ghostCoords.top+=l,h.style.left=i._ghostCoords.left+"px",h.style.top=i._ghostCoords.top
 +"px";if(i._draggingModeIndicatorElmt!=null){var d=i._draggingModeIndicatorElmt;d.style.left=i._ghostCoords.left-16+"px",d.style.top=i._ghostCoords.top+"px"}if("droppable"in u&&u.droppable){var v=e.getEventPageCoordinates(s),o=e.hittest(v.x,v.y,[i._ghostElmt,i._dropTargetHighlightElement]);o=i._findDropTarget(o);if(o!=i._potentialDropTarget){i._dropTargetHighlightElement!=null&&(document.body.removeChild(i._dropTargetHighlightElement),i._dropTargetHighlightElement=null,i._potentialDropTarget=null);var m=!1;o!=null&&(!("canDropOn"in u)||u.canDropOn(o))&&(!("canDrop"in o)||o.canDrop(i._draggedElement))&&(m=!0);if(m){var g=4,y=e.getPageCoordinates(o),b=document.createElement("div");b.style.border=g+"px solid yellow",b.style.backgroundColor="yellow",b.style.position="absolute",b.style.left=y.left+"px",b.style.top=y.top+"px",b.style.width=o.offsetWidth-g*2+"px",b.style.height=o.offsetHeight-g*2+"px",n.setOpacity(b,30),document.body.appendChild(b),i._potentialDropTarget=o,i._dropTargetHig
 hlightElement=b}}}}}catch(p){t.exception("WindowManager: Error handling mouse move",p),i._cancelDragging()}return e.cancelEvent(s),!1}},i._onBodyMouseUp=function(t,n,r){if(i._draggedElement!=null){try{if(i._dragging){var s=i._draggedElementCallback;"onDragEnd"in s&&s.onDragEnd();if("droppable"in s&&s.droppable){var o=!1,r=i._potentialDropTarget;r!=null&&(!("canDropOn"in s)||s.canDropOn(r))&&(!("canDrop"in r)||r.canDrop(i._draggedElement))&&("onDropOn"in s&&s.onDropOn(r),r.ondrop(i._draggedElement,i._draggingMode),o=!0),!o}}}finally{i._cancelDragging()}return e.cancelEvent(n),!1}},i._cancelDragging=function(){var e=i._draggedElementCallback;if("_ghostElmt"in e){var t=e._ghostElmt;document.body.removeChild(t),delete e._ghostElmt}i._dropTargetHighlightElement!=null&&(document.body.removeChild(i._dropTargetHighlightElement),i._dropTargetHighlightElement=null),i._draggingModeIndicatorElmt!=null&&(document.body.removeChild(i._draggingModeIndicatorElmt),i._draggingModeIndicatorElmt=null),i
 ._draggedElement=null,i._draggedElementCallback=null,i._potentialDropTarget=null,i._dropTargetHighlightElement=null,i._lastCoords=null,i._ghostCoords=null,i._draggingMode="",i._dragging=!1},i._findDropTarget=function(e){while(e!=null){if("ondrop"in e&&typeof e.ondrop=="function")break;e=e.parentNode}return e},i}),define("scripts/bubble",["./graphics","./window-manager"],function(e,t){return e.createBubbleForPoint=function(n,r,i,s,o){i=parseInt(i,10),s=parseInt(s,10);var u=e.bubbleConfig,a=e.pngIsTranslucent?"pngTranslucent":"pngNotTranslucent",f=i+2*u.borderGraphicSize,l=s+2*u.borderGraphicSize,c=function(e){return e+" "+e+"-"+a},h=document.createElement("div");h.className=c(u.containerCSSClass),h.style.width=i+"px",h.style.height=s+"px";var p=document.createElement("div");p.className=c(u.innerContainerCSSClass),h.appendChild(p);var d=function(){v._closed||(document.body.removeChild(v._div),v._doc=null,v._div=null,v._content=null,v._closed=!0)},v={_closed:!1},m=t.pushLayer(d,!0,h);v
 ._div=h,v.close=function(){t.popLayer(m)};var g=function(e){var t=document.createElement("div");t.className=c(u.borderGraphicCSSClassPrefix+e),p.appendChild(t)};g("top-left"),g("top-right"),g("bottom-left"),g("bottom-right"),g("left"),g("right"),g("top"),g("bottom");var y=document.createElement("div");y.className=c(u.contentContainerCSSClass),p.appendChild(y),v.content=y;var b=document.createElement("div");return b.className=c(u.closeGraphicCSSClass),p.appendChild(b),t.registerEventWithObject(b,"click",v,"close"),function(){var t=e.getWindowDimensions(),a=t.w,f=t.h,l=Math.ceil(u.arrowGraphicWidth/2),d=function(e){var t=document.createElement("div");return t.className=c(u.arrowGraphicCSSClassPrefix+"point-"+e),p.appendChild(t),t};if(n-l-u.borderGraphicSize-u.extraPadding>0&&n+l+u.borderGraphicSize+u.extraPadding<a){var v=n-Math.round(i/2);v=n<a/2?Math.max(v,u.extraPadding+u.borderGraphicSize):Math.min(v,a-u.extraPadding-u.borderGraphicSize-i);if(o&&o=="top"||!o&&r-u.arrowGraphicTarge
 tOffset-s-u.borderGraphicSize-u.extraPadding>0){var m=d("down");m.style.left=n-l-v+"px",h.style.left=v+"px",h.style.top=r-u.arrowGraphicTargetOffset-s+"px";return}if(o&&o=="bottom"||!o&&r+u.arrowGraphicTargetOffset+s+u.borderGraphicSize+u.extraPadding<f){var m=d("up");m.style.left=n-l-v+"px",h.style.left=v+"px",h.style.top=r+u.arrowGraphicTargetOffset+"px";return}}var g=r-Math.round(s/2);g=r<f/2?Math.max(g,u.extraPadding+u.borderGraphicSize):Math.min(g,f-u.extraPadding-u.borderGraphicSize-s);if(o&&o=="left"||!o&&n-u.arrowGraphicTargetOffset-i-u.borderGraphicSize-u.extraPadding>0){var m=d("right");m.style.top=r-l-g+"px",h.style.top=g+"px",h.style.left=n-u.arrowGraphicTargetOffset-i+"px"}else{var m=d("left");m.style.top=r-l-g+"px",h.style.top=g+"px",h.style.left=n+u.arrowGraphicTargetOffset+"px"}}(),document.body.appendChild(h),v},e.createBubbleForContentAndPoint=function(t,n,r,i,s,o){typeof i!="number"&&(i=300),typeof o!="number"&&(o=0),t.style.position="absolute",t.style.left="-5000
 px",t.style.top="0px",t.style.width=i+"px",document.body.appendChild(t),window.setTimeout(function(){var i=t.scrollWidth+10,u=t.scrollHeight+10,a=0;o>0&&u>o&&(u=o,a=i-25);var f=e.createBubbleForPoint(n,r,i,u,s);document.body.removeChild(t),t.style.position="static",t.style.left="",t.style.top="";if(a>0){var l=document.createElement("div");t.style.width="",l.style.width=a+"px",l.appendChild(t),f.content.appendChild(l)}else t.style.width=i+"px",f.content.appendChild(t)},200)},e}),define("scripts/date-time",["./debug"],function(e){var t=new Object;return t.MILLISECOND=0,t.SECOND=1,t.MINUTE=2,t.HOUR=3,t.DAY=4,t.WEEK=5,t.MONTH=6,t.YEAR=7,t.DECADE=8,t.CENTURY=9,t.MILLENNIUM=10,t.EPOCH=-1,t.ERA=-2,t.gregorianUnitLengths=[],function(){var e=t,n=e.gregorianUnitLengths;n[e.MILLISECOND]=1,n[e.SECOND]=1e3,n[e.MINUTE]=n[e.SECOND]*60,n[e.HOUR]=n[e.MINUTE]*60,n[e.DAY]=n[e.HOUR]*24,n[e.WEEK]=n[e.DAY]*7,n[e.MONTH]=n[e.DAY]*31,n[e.YEAR]=n[e.DAY]*365,n[e.DECADE]=n[e.YEAR]*10,n[e.CENTURY]=n[e.YEAR]*100
 ,n[e.MILLENNIUM]=n[e.YEAR]*1e3}(),t._dateRegexp=new RegExp("^(-?)([0-9]{4})("+["(-?([0-9]{2})(-?([0-9]{2}))?)","(-?([0-9]{3}))","(-?W([0-9]{2})(-?([1-7]))?)"].join("|")+")?$"),t._timezoneRegexp=new RegExp("Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$"),t._timeRegexp=new RegExp("^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(.([0-9]+))?)?)?$"),t.setIso8601Date=function(e,n){var r=n.match(t._dateRegexp);if(!r)throw new Error("Invalid date string: "+n);var i=r[1]=="-"?-1:1,s=i*r[2],o=r[5],u=r[7],a=r[9],f=r[11],l=r[13]?r[13]:1;e.setUTCFullYear(s);if(a)e.setUTCMonth(0),e.setUTCDate(Number(a));else if(f){e.setUTCMonth(0),e.setUTCDate(1);var c=e.getUTCDay(),h=c?c:7,p=Number(l)+7*Number(f);h<=4?e.setUTCDate(p+1-h):e.setUTCDate(p+8-h)}else o&&(e.setUTCDate(1),e.setUTCMonth(o-1)),u&&e.setUTCDate(u);return e},t.setIso8601Time=function(n,r){var i=r.match(t._timeRegexp);if(!i)return e.warn("Invalid time string: "+r),!1;var s=i[1],o=Number(i[3]?i[3]:0),u=i[5]?i[5]:0,a=i[7]?Number("0."+i[7])*1e3:0;return n.setUTCH
 ours(s),n.setUTCMinutes(o),n.setUTCSeconds(u),n.setUTCMilliseconds(a),n},t.timezoneOffset=(new Date).getTimezoneOffset(),t.setIso8601=function(e,n){var r=null,i=n.indexOf("T")==-1?n.split(" "):n.split("T");t.setIso8601Date(e,i[0]);if(i.length==2){var s=i[1].match(t._timezoneRegexp);s&&(s[0]=="Z"?r=0:(r=Number(s[3])*60+Number(s[5]),r*=s[2]=="-"?1:-1),i[1]=i[1].substr(0,i[1].length-s[0].length)),t.setIso8601Time(e,i[1])}return r==null&&(r=e.getTimezoneOffset()),e.setTime(e.getTime()+r*6e4),e},t.parseIso8601DateTime=function(e){try{return t.setIso8601(new Date(0),e)}catch(n){return null}},t.parseGregorianDateTime=function(e){if(e==null)return null;if(e instanceof Date)return e;var t=e.toString();if(t.length>0&&t.length<8){var n=t.indexOf(" ");if(n>0){var r=parseInt(t.substr(0,n)),i=t.substr(n+1);i.toLowerCase()=="bc"&&(r=1-r)}else var r=parseInt(t);var s=new Date(0);return s.setUTCFullYear(r),s}try{return new Date(Date.parse(t))}catch(o){return null}},t.roundDownToInterval=function(e,n
 ,r,i,s){var o=r*t.gregorianUnitLengths[t.HOUR],u=new Date(e.getTime()+o),a=function(e){e.setUTCMilliseconds(0),e.setUTCSeconds(0),e.setUTCMinutes(0),e.setUTCHours(0)},f=function(e){a(e),e.setUTCDate(1),e.setUTCMonth(0)};switch(n){case t.MILLISECOND:var l=u.getUTCMilliseconds();u.setUTCMilliseconds(l-l%i);break;case t.SECOND:u.setUTCMilliseconds(0);var l=u.getUTCSeconds();u.setUTCSeconds(l-l%i);break;case t.MINUTE:u.setUTCMilliseconds(0),u.setUTCSeconds(0);var l=u.getUTCMinutes();u.setTime(u.getTime()-l%i*t.gregorianUnitLengths[t.MINUTE]);break;case t.HOUR:u.setUTCMilliseconds(0),u.setUTCSeconds(0),u.setUTCMinutes(0);var l=u.getUTCHours();u.setUTCHours(l-l%i);break;case t.DAY:a(u);break;case t.WEEK:a(u);var c=(u.getUTCDay()+7-s)%7;u.setTime(u.getTime()-c*t.gregorianUnitLengths[t.DAY]);break;case t.MONTH:a(u),u.setUTCDate(1);var l=u.getUTCMonth();u.setUTCMonth(l-l%i);break;case t.YEAR:f(u);var l=u.getUTCFullYear();u.setUTCFullYear(l-l%i);break;case t.DECADE:f(u),u.setUTCFullYear(Math.
 floor(u.getUTCFullYear()/10)*10);break;case t.CENTURY:f(u),u.setUTCFullYear(Math.floor(u.getUTCFullYear()/100)*100);break;case t.MILLENNIUM:f(u),u.setUTCFullYear(Math.floor(u.getUTCFullYear()/1e3)*1e3)}e.setTime(u.getTime()-o)},t.roundUpToInterval=function(e,n,r,i,s){var o=e.getTime();t.roundDownToInterval(e,n,r,i,s),e.getTime()<o&&e.setTime(e.getTime()+t.gregorianUnitLengths[n]*i)},t.incrementByInterval=function(e,n,r){r=typeof r=="undefined"?0:r;var i=r*t.gregorianUnitLengths[t.HOUR],s=new Date(e.getTime()+i);switch(n){case t.MILLISECOND:s.setTime(s.getTime()+1);break;case t.SECOND:s.setTime(s.getTime()+1e3);break;case t.MINUTE:s.setTime(s.getTime()+t.gregorianUnitLengths[t.MINUTE]);break;case t.HOUR:s.setTime(s.getTime()+t.gregorianUnitLengths[t.HOUR]);break;case t.DAY:s.setUTCDate(s.getUTCDate()+1);break;case t.WEEK:s.setUTCDate(s.getUTCDate()+7);break;case t.MONTH:s.setUTCMonth(s.getUTCMonth()+1);break;case t.YEAR:s.setUTCFullYear(s.getUTCFullYear()+1);break;case t.DECADE:s.set
 UTCFullYear(s.getUTCFullYear()+10);break;case t.CENTURY:s.setUTCFullYear(s.getUTCFullYear()+100);break;case t.MILLENNIUM:s.setUTCFullYear(s.getUTCFullYear()+1e3)}e.setTime(s.getTime()-i)},t.removeTimeZoneOffset=function(e,n){return new Date(e.getTime()+n*t.gregorianUnitLengths[t.HOUR])},t.getTimezone=function(){var e=(new Date).getTimezoneOffset();return e/-60},t}),define("scripts/string",[],function(){var e={};return e.trim=function(e){return e.replace(/^\s+|\s+$/g,"")},e.startsWith=function(e,t){return e.length>=t.length&&e.substr(0,t.length)===t},e.endsWith=function(e,t){return e.length>=t.length&&e.substr(e.length-t.length)===t},e.substitute=function(e,t){var n,r,i,s;n="",r=0;while(r<e.length-1){i=e.indexOf("%",r);if(i<0||i===e.length-1)break;i>r&&e.charAt(i-1)==="\\"?(n+=e.substring(r,i-1)+"%",r=i+1):(s=parseInt(e.charAt(i+1)),isNaN(s)||s>=t.length?n+=e.substring(r,i+2):n+=e.substring(r,i)+t[s].toString(),r=i+2)}return r<e.length&&(n+=e.substring(r)),n},e}),define("scripts/html
 ",[],function(){var e=new Object;return e._e2uHash={},function(){var t=e._e2uHash;t.nbsp=" ",t.iexcl="¡",t.cent="¢",t.pound="£",t.curren="¤",t.yen="¥",t.brvbar="¦",t.sect="§",t.uml="¨",t.copy="©",t.ordf="ª",t.laquo="«",t.not="¬",t.shy="­",t.reg="®",t.macr="¯",t.deg="°",t.plusmn="±",t.sup2="²",t.sup3="³",t.acute="´",t.micro="µ",t.para="¶",t.middot="·",t.cedil="¸",t.sup1="¹",t.ordm="º",t.raquo="»",t.frac14="¼",t.frac12="½",t.frac34="¾",t.iquest="¿",t.Agrave="À",t.Aacute="Á",t.Acirc="Â",t.Atilde="Ã",t.Auml="Ä",t.Aring="Å",t.AElig="Æ",t.Ccedil="Ç",t.Egrave="È",t.Eacute="É",t.Ecirc="Ê",t.Euml="Ë",t.Igrave="Ì",t.Iacute="Í",t.Icirc="Î",t.Iuml="Ï",t.ETH="Ð",t.Ntilde="Ñ",t.Ograve="Ò",t.Oacute="Ó",t.Ocirc="Ô",t.Otilde="Õ",t.Ouml="Ö",t.times="×",t.Oslash="Ø",t.Ugrave="Ù",t.Uacute="Ú",t.Ucirc="Û",t.Uuml="Ü",t.Yacut
 e="Ý",t.THORN="Þ",t.szlig="ß",t.agrave="à",t.aacute="á",t.acirc="â",t.atilde="ã",t.auml="ä",t.aring="å",t.aelig="æ",t.ccedil="ç",t.egrave="è",t.eacute="é",t.ecirc="ê",t.euml="ë",t.igrave="ì",t.iacute="í",t.icirc="î",t.iuml="ï",t.eth="ð",t.ntilde="ñ",t.ograve="ò",t.oacute="ó",t.ocirc="ô",t.otilde="õ",t.ouml="ö",t.divide="÷",t.oslash="ø",t.ugrave="ù",t.uacute="ú",t.ucirc="û",t.uuml="ü",t.yacute="ý",t.thorn="þ",t.yuml="ÿ",t.quot='"',t.amp="&",t.lt="<",t.gt=">",t.OElig="",t.oelig="œ",t.Scaron="Š",t.scaron="š",t.Yuml="Ÿ",t.circ="ˆ",t.tilde="˜",t.ensp=" ",t.emsp=" ",t.thinsp=" ",t.zwnj="‌",t.zwj="‍",t.lrm="‎",t.rlm="‏",t.ndash="–",t.mdash="—",t.lsquo="‘",t.rsquo="’",t.sbquo="‚",t.ldquo="“",t.rdquo="”",t.bdquo="„",t.dagger="†",t.Dagger="‡",t.permil="‰",t.lsaquo="‹",t.rsaquo="
 ›",t.euro="€",t.fnof="ƒ",t.Alpha="Α",t.Beta="Β",t.Gamma="Γ",t.Delta="Δ",t.Epsilon="Ε",t.Zeta="Ζ",t.Eta="Η",t.Theta="Θ",t.Iota="Ι",t.Kappa="Κ",t.Lambda="Λ",t.Mu="Μ",t.Nu="Ν",t.Xi="Ξ",t.Omicron="Ο",t.Pi="Π",t.Rho="Ρ",t.Sigma="Σ",t.Tau="Τ",t.Upsilon="Î¥",t.Phi="Φ",t.Chi="Χ",t.Psi="Ψ",t.Omega="Ω",t.alpha="α",t.beta="β",t.gamma="γ",t.delta="δ",t.epsilon="ε",t.zeta="ζ",t.eta="η",t.theta="θ",t.iota="ι",t.kappa="κ",t.lambda="λ",t.mu="μ",t.nu="ν",t.xi="ξ",t.omicron="ο",t.pi="π",t.rho="ρ",t.sigmaf="ς",t.sigma="σ",t.tau="τ",t.upsilon="υ",t.phi="φ",t.chi="χ",t.psi="ψ",t.omega="ω",t.thetasym="ϑ",t.upsih="ϒ",t.piv="ϖ",t.bull="•",t.hellip="…",t.prime="′",t.Prime="″",t.oline="‾",t.frasl="⁄",t.weierp="℘",t.image="ℑ",t.real="ℜ",t.trade="™",t.alefsym="ℵ",t.larr="←",t.uarr="â†
 ‘",t.rarr="→",t.darr="↓",t.harr="↔",t.crarr="↵",t.lArr="⇐",t.uArr="⇑",t.rArr="⇒",t.dArr="⇓",t.hArr="⇔",t.forall="∀",t.part="∂",t.exist="∃",t.empty="∅",t.nabla="∇",t.isin="∈",t.notin="∉",t.ni="∋",t.prod="∏",t.sum="∑",t.minus="−",t.lowast="∗",t.radic="√",t.prop="∝",t.infin="∞",t.ang="∠",t.and="∧",t.or="∨",t.cap="∩",t.cup="∪",t["int"]="∫",t.there4="∴",t.sim="∼",t.cong="≅",t.asymp="≈",t.ne="≠",t.equiv="≡",t.le="≤",t.ge="≥",t.sub="⊂",t.sup="⊃",t.nsub="⊄",t.sube="⊆",t.supe="⊇",t.oplus="⊕",t.otimes="⊗",t.perp="⊥",t.sdot="⋅",t.lceil="⌈",t.rceil="⌉",t.lfloor="⌊",t.rfloor="⌋",t.lang="〈",t.rang="〉",t.loz="◊",t.spades="♠",t.clubs="♣",t.hearts="♥",t.diams="♦"}(),e.deEntify=function(t){var n=e._e2uHash,r=/&(\w+
 ?);/;while(r.test(t)){var i=t.match(r);t=t.replace(r,n[i[1]])}return t},e}),define("scripts/set",[],function(){var e=function(t){this._hash={},this._count=0;if(t instanceof Array)for(var n=0;n<t.length;n++)this.add(t[n]);else t instanceof e&&this.addSet(t)};return e.prototype.add=function(e){return e in this._hash?!1:(this._hash[e]=!0,this._count++,!0)},e.prototype.addSet=function(e){for(var t in e._hash)this.add(t)},e.prototype.remove=function(e){return e in this._hash?(delete this._hash[e],this._count--,!0):!1},e.prototype.removeSet=function(e){for(var t in e._hash)this.remove(t)},e.prototype.retainSet=function(e){for(var t in this._hash)e.contains(t)||(delete this._hash[t],this._count--)},e.prototype.contains=function(e){return e in this._hash},e.prototype.size=function(){return this._count},e.prototype.toArray=function(){var e=[];for(var t in this._hash)e.push(t);return e},e.prototype.visit=function(e){for(var t in this._hash)if(e(t)==1)break},e}),define("scripts/sorted-array",[
 ],function(){var e=function(e,t){this._a=t instanceof Array?t:[],this._compare=e};return e.prototype.add=function(e){var t=this,n=this.find(function(n){return t._compare(n,e)});n<this._a.length?this._a.splice(n,0,e):this._a.push(e)},e.prototype.remove=function(e){var t=this,n=this.find(function(n){return t._compare(n,e)});while(n<this._a.length&&this._compare(this._a[n],e)==0){if(this._a[n]==e)return this._a.splice(n,1),!0;n++}return!1},e.prototype.removeAll=function(){this._a=[]},e.prototype.elementAt=function(e){return this._a[e]},e.prototype.length=function(){return this._a.length},e.prototype.find=function(e){var t=0,n=this._a.length;while(t<n){var r=Math.floor((t+n)/2),i=e(this._a[r]);if(r==t)return i<0?t+1:t;i<0?t=r:n=r}return t},e.prototype.getFirst=function(){return this._a.length>0?this._a[0]:null},e.prototype.getLast=function(){return this._a.length>0?this._a[this._a.length-1]:null},e}),define("scripts/units",["./date-time"],function(e){var t=new Object;return t.makeDefaul
 tValue=function(){return new Date},t.cloneValue=function(e){return new Date(e.getTime())},t.getParser=function(t){typeof t=="string"&&(t=t.toLowerCase());var n=t=="iso8601"||t=="iso 8601"?e.parseIso8601DateTime:e.parseGregorianDateTime;return function(e){return typeof e!="undefined"&&e!==null&&typeof e.toUTCString=="function"?e:n(e)}},t.parseFromObject=function(t){return e.parseGregorianDateTime(t)},t.toNumber=function(e){return e.getTime()},t.fromNumber=function(e){return new Date(e)},t.compare=function(e,t){var n,r;return typeof e=="object"?n=e.getTime():n=Number(e),typeof t=="object"?r=t.getTime():r=Number(t),n-r},t.earlier=function(e,n){return t.compare(e,n)<0?e:n},t.later=function(e,n){return t.compare(e,n)>0?e:n},t.change=function(e,t){return new Date(e.getTime()+t)},t}),define("scripts/event-index",["./units","./sorted-array"],function(e,t){var n=function(n){var r=this;this._unit=n!=null?n:e,this._events=new t(function(e,t){return r._unit.compare(e.getStart(),t.getStart())}),
 this._idToEvent={},this._indexed=!0};return n.prototype.getUnit=function(){return this._unit},n.prototype.getEvent=function(e){return this._idToEvent[e]},n.prototype.add=function(e){this._events.add(e),this._idToEvent[e.getID()]=e,this._indexed=!1},n.prototype.removeAll=function(){this._events.removeAll(),this._idToEvent={},this._indexed=!1},n.prototype.getCount=function(){return this._events.length()},n.prototype.getIterator=function(e,t){return this._indexed||this._index(),new n._Iterator(this._events,e,t,this._unit)},n.prototype.getReverseIterator=function(e,t){return this._indexed||this._index(),new n._ReverseIterator(this._events,e,t,this._unit)},n.prototype.getAllIterator=function(){return new n._AllIterator(this._events)},n.prototype.getEarliestDate=function(){var e=this._events.getFirst();return e==null?null:e.getStart()},n.prototype.getLatestDate=function(){var e=this._events.getLast();if(e==null)return null;this._indexed||this._index();var t=e._earliestOverlapIndex,n=this.
 _events.elementAt(t).getEnd();for(var r=t+1;r<this._events.length();r++)n=this._unit.later(n,this._events.elementAt(r).getEnd());return n},n.prototype._index=function(){var e=this._events.length();for(var t=0;t<e;t++){var n=this._events.elementAt(t);n._earliestOverlapIndex=t}var r=1;for(var t=0;t<e;t++){var n=this._events.elementAt(t),i=n.getEnd();r=Math.max(r,t+1);while(r<e){var s=this._events.elementAt(r),o=s.getStart();if(!(this._unit.compare(o,i)<0))break;s._earliestOverlapIndex=t,r++}}this._indexed=!0},n._Iterator=function(e,t,n,r){this._events=e,this._startDate=t,this._endDate=n,this._unit=r,this._currentIndex=e.find(function(e){return r.compare(e.getStart(),t)}),this._currentIndex-1>=0&&(this._currentIndex=this._events.elementAt(this._currentIndex-1)._earliestOverlapIndex),this._currentIndex--,this._maxIndex=e.find(function(e){return r.compare(e.getStart(),n)}),this._hasNext=!1,this._next=null,this._findNext()},n._Iterator.prototype={hasNext:function(){return this._hasNext},n
 ext:function(){if(this._hasNext){var e=this._next;return this._findNext(),e}return null},_findNext:function(){var e=this._unit;while(++this._currentIndex<this._maxIndex){var t=this._events.elementAt(this._currentIndex);if(e.compare(t.getStart(),this._endDate)<0&&e.compare(t.getEnd(),this._startDate)>0){this._next=t,this._hasNext=!0;return}}this._next=null,this._hasNext=!1}},n._ReverseIterator=function(e,t,n,r){this._events=e,this._startDate=t,this._endDate=n,this._unit=r,this._minIndex=e.find(function(e){return r.compare(e.getStart(),t)}),this._minIndex-1>=0&&(this._minIndex=this._events.elementAt(this._minIndex-1)._earliestOverlapIndex),this._maxIndex=e.find(function(e){return r.compare(e.getStart(),n)}),this._currentIndex=this._maxIndex,this._hasNext=!1,this._next=null,this._findNext()},n._ReverseIterator.prototype={hasNext:function(){return this._hasNext},next:function(){if(this._hasNext){var e=this._next;return this._findNext(),e}return null},_findNext:function(){var e=this._uni
 t;while(--this._currentIndex>=this._minIndex){var t=this._events.elementAt(this._currentIndex);if(e.compare(t.getStart(),this._endDate)<0&&e.compare(t.getEnd(),this._startDate)>0){this._next=t,this._hasNext=!0;return}}this._next=null,this._hasNext=!1}},n._AllIterator=function(e){this._events=e,this._index=0},n._AllIterator.prototype={hasNext:function(){return this._index<this._events.length()},next:function(){return this._index<this._events.length()?this._events.elementAt(this._index++):null}},n}),define("scripts/ajax",["./debug"],function(e){var t=function(e){this._listeners=[],this._wildcardHandlerName=e};return t.prototype.add=function(e){this._listeners.push(e)},t.prototype.remove=function(e){var t=this._listeners;for(var n=0;n<t.length;n++)if(t[n]==e){t.splice(n,1);break}},t.prototype.fire=function(t,n){var r=[].concat(this._listeners);for(var i=0;i<r.length;i++){var s=r[i];if(t in s)try{s[t].apply(s,n)}catch(o){e.exception("Error firing event of name "+t,o)}else if(this._wildc
 ardHandlerName!=null&&this._wildcardHandlerName in s)try{s[this._wildcardHandlerName].apply(s,[t])}catch(o){e.exception("Error firing event of name "+t+" to wildcard handler",o)}}},t}),define("scripts/history",["./ajax","./dom","./debug","./window-manager"],function(e,t,n,r){var i={maxHistoryLength:10,historyFile:"__history__.html",enabled:!0,_initialized:!1,_listeners:new e,_actions:[],_baseIndex:0,_currentIndex:0,_plainDocumentTitle:document.title};return i.formatHistoryEntryTitle=function(e){return i._plainDocumentTitle+" {"+e+"}"},i.initialize=function(){if(i._initialized)return;if(i.enabled){var e=document.createElement("iframe");e.id="simile-ajax-history",e.style.position="absolute",e.style.width="10px",e.style.height="10px",e.style.top="0px",e.style.left="0px",e.style.visibility="hidden",e.src=i.historyFile+"?0",document.body.appendChild(e),t.registerEvent(e,"load",i._handleIFrameOnLoad),i._iframe=e}i._initialized=!0},i.addListener=function(e){i._listeners.add(e)},i.removeLis
 tener=function(e){i._listeners.remove(e)},i.addAction=function(e){i._listeners.fire("onBeforePerform",[e]),window.setTimeout(function(){try{e.perform(),i._listeners.fire("onAfterPerform",[e]);if(i.enabled){i._actions=i._actions.slice(0,i._currentIndex-i._baseIndex),i._actions.push(e),i._currentIndex++;var t=i._actions.length-i.maxHistoryLength;t>0&&(i._actions=i._actions.slice(t),i._baseIndex+=t);try{i._iframe.contentWindow.location.search="?"+i._currentIndex}catch(r){var s=i.formatHistoryEntryTitle(e.label);document.title=s}}}catch(r){n.exception(r,"Error adding action {"+e.label+"} to history")}},0)},i.addLengthyAction=function(e,t,n){i.addAction({perform:e,undo:t,label:n,uiLayer:r.getBaseLayer(),lengthy:!0})},i._handleIFrameOnLoad=function(){try{var e=i._iframe.contentWindow.location.search,t=e.length==0?0:Math.max(0,parseInt(e.substr(1))),r=function(){var e=t-i._currentIndex;i._currentIndex+=e,i._baseIndex+=e,i._iframe.contentWindow.location.search="?"+t};if(t<i._currentIndex)i.
 _listeners.fire("onBeforeUndoSeveral",[]),window.setTimeout(function(){while(i._currentIndex>t&&i._currentIndex>i._baseIndex){i._currentIndex--;var e=i._actions[i._currentIndex-i._baseIndex];try{e.undo()}catch(s){n.exception(s,"History: Failed to undo action {"+e.label+"}")}}i._listeners.fire("onAfterUndoSeveral",[]),r()},0);else if(t>i._currentIndex)i._listeners.fire("onBeforeRedoSeveral",[]),window.setTimeout(function(){while(i._currentIndex<t&&i._currentIndex-i._baseIndex<i._actions.length){var e=i._actions[i._currentIndex-i._baseIndex];try{e.perform()}catch(s){n.exception(s,"History: Failed to redo action {"+e.label+"}")}i._currentIndex++}i._listeners.fire("onAfterRedoSeveral",[]),r()},0);else{var s=i._currentIndex-i._baseIndex-1,o=s>=0&&s<i._actions.length?i.formatHistoryEntryTitle(i._actions[s].label):i._plainDocumentTitle;i._iframe.contentWindow.document.title=o,document.title=o}}catch(u){}},i.getNextUndoAction=function(){try{var e=i._currentIndex-i._baseIndex-1;return i._act
 ions[e]}catch(t){return null}},i.getNextRedoAction=function(){try{var e=i._currentIndex-i._baseIndex;return i._actions[e]}catch(t){return null}},i}),define("simile-ajax",["module","./scripts/simile-ajax-base","./scripts/platform","./scripts/debug","./scripts/xmlhttp","./scripts/dom","./scripts/bubble","./scripts/date-time","./scripts/string","./scripts/html","./scripts/set","./scripts/sorted-array","./scripts/event-index","./scripts/units","./scripts/ajax","./scripts/history","./scripts/window-manager"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m){t.Platform=n,t.Debug=r,t.XmlHttp=i,t.DOM=s,t.Graphics=o,t.DateTime=u,t.StringUtils=a,t.HTML=f,t.Set=l,t.SortedArray=c,t.EventIndex=h,t.NativeDateUnit=p,t.ListenerQueue=d,t.History=v,t.WindowManager=m;var g=function(e){return e.getElementsByTagName("head")[0]};return t.findScript=function(e,t){var n,r,i,s;n=e.documentElement.getElementsByTagName("script");for(r=0;r<n.length;r++){i=n[r].src,s=i.indexOf(t);if(s>=0)return i}return null},t.parse
 URLParameters=function(e,t,n){t=t||{},n=n||{},typeof e=="undefined"&&(e=location.href);var r=e.indexOf("?");if(r<0)return t;e=(e+"#").slice(r+1,e.indexOf("#"));var i=e.split("&"),s,o={},u=window.decodeURIComponent||unescape;for(var a=0;s=i[a];a++){var f=s.indexOf("="),l=u(s.slice(0,f)),c=o[l],h=u(s.slice(f+1));typeof c=="undefined"?c=[]:c instanceof Array||(c=[c]),o[l]=c.concat(h)}for(var a in o){if(!o.hasOwnProperty(a))continue;var p=n[a]||String,d=o[a];d instanceof Array||(d=[d]),p===Boolean&&d[0]=="false"?t[a]=!1:t[a]=p.apply(this,d)}return t},t.includeJavascriptFile=function(e,n,r,i,s){t.Debug.warn("Loading scripts is no longer a feature of SimileAjax. Use RequireJS instead.");return},t.includeJavascriptFiles=function(e,n,r){t.Debug.warn("Loading scripts is no longer a feature of SimileAjax. Use RequireJS instead.");return},t.includeCssFile=function(e,t){if(e.body==null)try{e.write("<link rel='stylesheet' href='"+t+"' type='text/css'/>");return}catch(n){}var r=e.createElement("l
 ink");r.setAttribute("rel","stylesheet"),r.setAttribute("type","text/css"),r.setAttribute("href",t),g(e).appendChild(r)},t.includeCssFiles=function(e,n,r){for(var i=0;i<r.length;i++)t.includeCssFile(e,n+r[i])},t.prefixURLs=function(e,t,n){for(var r=0;r<n.length;r++)e.push(t+n[r])},t.setPrefix=function(e){return t.urlPrefix===null&&e!==null?(e.substr(-1)!=="/"&&(e+="/"),t.urlPrefix=e,t.params.prefix=e,t.loadCSS(t.params.bundle),!0):!1},t.loadCSS=function(e){var n=["main.css"],r="simile-ajax-bundle.css";e=e||!0,e?t.includeCssFile(document,t.urlPrefix+"styles/"+r):t.includeCssFiles(document,t.urlPrefix+"styles/",n)},t.loadLegacy=function(){var e,n,r,i,s;e=null;if(typeof SimileAjax_urlPrefix=="string")e=SimileAjax_urlPrefix,t.setPrefix(e);else{n=null,r=["simile-ajax-api.js","simile-ajax-bundle.js"];for(s=0;s<r.length;s++){i=r[s],n=t.findScript(document,i);if(n!=null){e=n.substr(0,n.indexOf(i));break}}n===null?t.error=new Error("Failed to derive URL prefix for SimileAjax"):(t.setPrefix(e
 ),t.params=t.parseURLParameters(n,t.params,t.paramTypes))}t.Graphics=o.initialize(o),t.History.initialize(),t.WindowManager.initialize()},t.loadRequire=function(){var n;n=e.config(),t.params=n,t.setPrefix(t.params.prefix),t.Graphics=o.initialize(o),t.History.initialize(),t.WindowManager.initialize()},t.load=function(){if(t.loaded)return;t.loaded=!0,e.config().hasOwnProperty("prefix")?t.loadRequire():t.loadLegacy()},t});
\ No newline at end of file

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/content/history.html
==============================================================================
--- websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/content/history.html (added)
+++ websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/content/history.html Wed May 17 15:33:02 2017
@@ -0,0 +1,28 @@
+<!--#include virtual="/doctype.html" -->
+<html>
+<head>
+<link href="/css/ooo.css" rel="stylesheet" type="text/css">
+
+    <title>Dummy Page for Keeping Track of History</title>
+
+<!--#include virtual="/google-analytics.js" --> 
+<!--#include virtual="/scripts/entourage.js" -->
+</head>
+<body>
+<!--#include virtual="/brand.html" -->
+  <div id="topbara">
+    <!--#include virtual="/topnav.html" -->
+    <div id="breadcrumbsa"><a href="/">home</a>&nbsp;&raquo;&nbsp;<a href="/scripts/">scripts</a>&nbsp;&raquo;&nbsp;<a href="/scripts/api.simile-widgets.org/">api.simile-widgets.org</a>&nbsp;&raquo;&nbsp;<a href="/scripts/api.simile-widgets.org/ajax/">ajax</a>&nbsp;&raquo;&nbsp;<a href="/scripts/api.simile-widgets.org/ajax/2.2.1/">2.2.1</a>&nbsp;&raquo;&nbsp;<a href="/scripts/api.simile-widgets.org/ajax/2.2.1/content/">content</a></div>
+  </div>
+  <div id="clear"></div>
+  
+  
+  <div id="content">
+    
+    
+    
+
+  </div>
+<!--#include virtual="/footer.html" -->
+</body>
+</html>

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-down.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-down.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-up.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-arrow-point-up.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-bottom.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/bubble-top.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/close-button.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/close-button.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/copy.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/copy.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-bottom-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-bottom-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-bottom-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-bottom-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-top-left.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-top-left.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-top-right.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/images/message-top-right.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/ajax.js
==============================================================================
--- websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/ajax.js (added)
+++ websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/ajax.js Wed May 17 15:33:02 2017
@@ -0,0 +1,45 @@
+/*==================================================
+ *  General, miscellaneous SimileAjax stuff
+ *==================================================
+ */
+
+SimileAjax.ListenerQueue = function(wildcardHandlerName) {
+    this._listeners = [];
+    this._wildcardHandlerName = wildcardHandlerName;
+};
+
+SimileAjax.ListenerQueue.prototype.add = function(listener) {
+    this._listeners.push(listener);
+};
+
+SimileAjax.ListenerQueue.prototype.remove = function(listener) {
+    var listeners = this._listeners;
+    for (var i = 0; i < listeners.length; i++) {
+        if (listeners[i] == listener) {
+            listeners.splice(i, 1);
+            break;
+        }
+    }
+};
+
+SimileAjax.ListenerQueue.prototype.fire = function(handlerName, args) {
+    var listeners = [].concat(this._listeners);
+    for (var i = 0; i < listeners.length; i++) {
+        var listener = listeners[i];
+        if (handlerName in listener) {
+            try {
+                listener[handlerName].apply(listener, args);
+            } catch (e) {
+                SimileAjax.Debug.exception("Error firing event of name " + handlerName, e);
+            }
+        } else if (this._wildcardHandlerName != null &&
+            this._wildcardHandlerName in listener) {
+            try {
+                listener[this._wildcardHandlerName].apply(listener, [ handlerName ]);
+            } catch (e) {
+                SimileAjax.Debug.exception("Error firing event of name " + handlerName + " to wildcard handler", e);
+            }
+        }
+    }
+};
+

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/data-structure.js
==============================================================================
--- websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/data-structure.js (added)
+++ websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/data-structure.js Wed May 17 15:33:02 2017
@@ -0,0 +1,447 @@
+/**
+ * A basic set (in the mathematical sense) data structure
+ *
+ * @constructor
+ * @param {Array or SimileAjax.Set} [a] an initial collection
+ */
+SimileAjax.Set = function(a) {
+    this._hash = {};
+    this._count = 0;
+    
+    if (a instanceof Array) {
+        for (var i = 0; i < a.length; i++) {
+            this.add(a[i]);
+        }
+    } else if (a instanceof SimileAjax.Set) {
+        this.addSet(a);
+    }
+}
+
+/**
+ * Adds the given object to this set, assuming there it does not already exist
+ *
+ * @param {Object} o the object to add
+ * @return {Boolean} true if the object was added, false if not
+ */
+SimileAjax.Set.prototype.add = function(o) {
+    if (!(o in this._hash)) {
+        this._hash[o] = true;
+        this._count++;
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Adds each element in the given set to this set
+ *
+ * @param {SimileAjax.Set} set the set of elements to add
+ */
+SimileAjax.Set.prototype.addSet = function(set) {
+    for (var o in set._hash) {
+        this.add(o);
+    }
+}
+
+/**
+ * Removes the given element from this set
+ *
+ * @param {Object} o the object to remove
+ * @return {Boolean} true if the object was successfully removed,
+ *   false otherwise
+ */
+SimileAjax.Set.prototype.remove = function(o) {
+    if (o in this._hash) {
+        delete this._hash[o];
+        this._count--;
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Removes the elements in this set that correspond to the elements in the
+ * given set
+ *
+ * @param {SimileAjax.Set} set the set of elements to remove
+ */
+SimileAjax.Set.prototype.removeSet = function(set) {
+    for (var o in set._hash) {
+        this.remove(o);
+    }
+}
+
+/**
+ * Removes all elements in this set that are not present in the given set, i.e.
+ * modifies this set to the intersection of the two sets
+ *
+ * @param {SimileAjax.Set} set the set to intersect
+ */
+SimileAjax.Set.prototype.retainSet = function(set) {
+    for (var o in this._hash) {
+        if (!set.contains(o)) {
+            delete this._hash[o];
+            this._count--;
+        }
+    }
+}
+
+/**
+ * Returns whether or not the given element exists in this set
+ *
+ * @param {SimileAjax.Set} o the object to test for
+ * @return {Boolean} true if the object is present, false otherwise
+ */
+SimileAjax.Set.prototype.contains = function(o) {
+    return (o in this._hash);
+}
+
+/**
+ * Returns the number of elements in this set
+ *
+ * @return {Number} the number of elements in this set
+ */
+SimileAjax.Set.prototype.size = function() {
+    return this._count;
+}
+
+/**
+ * Returns the elements of this set as an array
+ *
+ * @return {Array} a new array containing the elements of this set
+ */
+SimileAjax.Set.prototype.toArray = function() {
+    var a = [];
+    for (var o in this._hash) {
+        a.push(o);
+    }
+    return a;
+}
+
+/**
+ * Iterates through the elements of this set, order unspecified, executing the
+ * given function on each element until the function returns true
+ *
+ * @param {Function} f a function of form f(element)
+ */
+SimileAjax.Set.prototype.visit = function(f) {
+    for (var o in this._hash) {
+        if (f(o) == true) {
+            break;
+        }
+    }
+}
+
+/**
+ * A sorted array data structure
+ *
+ * @constructor
+ */
+SimileAjax.SortedArray = function(compare, initialArray) {
+    this._a = (initialArray instanceof Array) ? initialArray : [];
+    this._compare = compare;
+};
+
+SimileAjax.SortedArray.prototype.add = function(elmt) {
+    var sa = this;
+    var index = this.find(function(elmt2) {
+        return sa._compare(elmt2, elmt);
+    });
+    
+    if (index < this._a.length) {
+        this._a.splice(index, 0, elmt);
+    } else {
+        this._a.push(elmt);
+    }
+};
+
+SimileAjax.SortedArray.prototype.remove = function(elmt) {
+    var sa = this;
+    var index = this.find(function(elmt2) {
+        return sa._compare(elmt2, elmt);
+    });
+    
+    while (index < this._a.length && this._compare(this._a[index], elmt) == 0) {
+        if (this._a[index] == elmt) {
+            this._a.splice(index, 1);
+            return true;
+        } else {
+            index++;
+        }
+    }
+    return false;
+};
+
+SimileAjax.SortedArray.prototype.removeAll = function() {
+    this._a = [];
+};
+
+SimileAjax.SortedArray.prototype.elementAt = function(index) {
+    return this._a[index];
+};
+
+SimileAjax.SortedArray.prototype.length = function() {
+    return this._a.length;
+};
+
+SimileAjax.SortedArray.prototype.find = function(compare) {
+    var a = 0;
+    var b = this._a.length;
+    
+    while (a < b) {
+        var mid = Math.floor((a + b) / 2);
+        var c = compare(this._a[mid]);
+        if (mid == a) {
+            return c < 0 ? a+1 : a;
+        } else if (c < 0) {
+            a = mid;
+        } else {
+            b = mid;
+        }
+    }
+    return a;
+};
+
+SimileAjax.SortedArray.prototype.getFirst = function() {
+    return (this._a.length > 0) ? this._a[0] : null;
+};
+
+SimileAjax.SortedArray.prototype.getLast = function() {
+    return (this._a.length > 0) ? this._a[this._a.length - 1] : null;
+};
+
+/*==================================================
+ *  Event Index
+ *==================================================
+ */
+
+SimileAjax.EventIndex = function(unit) {
+    var eventIndex = this;
+    
+    this._unit = (unit != null) ? unit : SimileAjax.NativeDateUnit;
+    this._events = new SimileAjax.SortedArray(
+        function(event1, event2) {
+            return eventIndex._unit.compare(event1.getStart(), event2.getStart());
+        }
+    );
+    this._idToEvent = {};
+    this._indexed = true;
+};
+
+SimileAjax.EventIndex.prototype.getUnit = function() {
+    return this._unit;
+};
+
+SimileAjax.EventIndex.prototype.getEvent = function(id) {
+    return this._idToEvent[id];
+};
+
+SimileAjax.EventIndex.prototype.add = function(evt) {
+    this._events.add(evt);
+    this._idToEvent[evt.getID()] = evt;
+    this._indexed = false;
+};
+
+SimileAjax.EventIndex.prototype.removeAll = function() {
+    this._events.removeAll();
+    this._idToEvent = {};
+    this._indexed = false;
+};
+
+SimileAjax.EventIndex.prototype.getCount = function() {
+    return this._events.length();
+};
+
+SimileAjax.EventIndex.prototype.getIterator = function(startDate, endDate) {
+    if (!this._indexed) {
+        this._index();
+    }
+    return new SimileAjax.EventIndex._Iterator(this._events, startDate, endDate, this._unit);
+};
+
+SimileAjax.EventIndex.prototype.getReverseIterator = function(startDate, endDate) {
+    if (!this._indexed) {
+        this._index();
+    }
+    return new SimileAjax.EventIndex._ReverseIterator(this._events, startDate, endDate, this._unit);
+};
+
+SimileAjax.EventIndex.prototype.getAllIterator = function() {
+    return new SimileAjax.EventIndex._AllIterator(this._events);
+};
+
+SimileAjax.EventIndex.prototype.getEarliestDate = function() {
+    var evt = this._events.getFirst();
+    return (evt == null) ? null : evt.getStart();
+};
+
+SimileAjax.EventIndex.prototype.getLatestDate = function() {
+    var evt = this._events.getLast();
+    if (evt == null) {
+        return null;
+    }
+    
+    if (!this._indexed) {
+        this._index();
+    }
+    
+    var index = evt._earliestOverlapIndex;
+    var date = this._events.elementAt(index).getEnd();
+    for (var i = index + 1; i < this._events.length(); i++) {
+        date = this._unit.later(date, this._events.elementAt(i).getEnd());
+    }
+    
+    return date;
+};
+
+SimileAjax.EventIndex.prototype._index = function() {
+    /*
+     *  For each event, we want to find the earliest preceding
+     *  event that overlaps with it, if any.
+     */
+    
+    var l = this._events.length();
+    for (var i = 0; i < l; i++) {
+        var evt = this._events.elementAt(i);
+        evt._earliestOverlapIndex = i;
+    }
+    
+    var toIndex = 1;
+    for (var i = 0; i < l; i++) {
+        var evt = this._events.elementAt(i);
+        var end = evt.getEnd();
+        
+        toIndex = Math.max(toIndex, i + 1);
+        while (toIndex < l) {
+            var evt2 = this._events.elementAt(toIndex);
+            var start2 = evt2.getStart();
+            
+            if (this._unit.compare(start2, end) < 0) {
+                evt2._earliestOverlapIndex = i;
+                toIndex++;
+            } else {
+                break;
+            }
+        }
+    }
+    this._indexed = true;
+};
+
+SimileAjax.EventIndex._Iterator = function(events, startDate, endDate, unit) {
+    this._events = events;
+    this._startDate = startDate;
+    this._endDate = endDate;
+    this._unit = unit;
+    
+    this._currentIndex = events.find(function(evt) {
+        return unit.compare(evt.getStart(), startDate);
+    });
+    if (this._currentIndex - 1 >= 0) {
+        this._currentIndex = this._events.elementAt(this._currentIndex - 1)._earliestOverlapIndex;
+    }
+    this._currentIndex--;
+    
+    this._maxIndex = events.find(function(evt) {
+        return unit.compare(evt.getStart(), endDate);
+    });
+    
+    this._hasNext = false;
+    this._next = null;
+    this._findNext();
+};
+
+SimileAjax.EventIndex._Iterator.prototype = {
+    hasNext: function() { return this._hasNext; },
+    next: function() {
+        if (this._hasNext) {
+            var next = this._next;
+            this._findNext();
+            
+            return next;
+        } else {
+            return null;
+        }
+    },
+    _findNext: function() {
+        var unit = this._unit;
+        while ((++this._currentIndex) < this._maxIndex) {
+            var evt = this._events.elementAt(this._currentIndex);
+            if (unit.compare(evt.getStart(), this._endDate) < 0 &&
+                unit.compare(evt.getEnd(), this._startDate) > 0) {
+                
+                this._next = evt;
+                this._hasNext = true;
+                return;
+            }
+        }
+        this._next = null;
+        this._hasNext = false;
+    }
+};
+
+SimileAjax.EventIndex._ReverseIterator = function(events, startDate, endDate, unit) {
+    this._events = events;
+    this._startDate = startDate;
+    this._endDate = endDate;
+    this._unit = unit;
+    
+    this._minIndex = events.find(function(evt) {
+        return unit.compare(evt.getStart(), startDate);
+    });
+    if (this._minIndex - 1 >= 0) {
+        this._minIndex = this._events.elementAt(this._minIndex - 1)._earliestOverlapIndex;
+    }
+    
+    this._maxIndex = events.find(function(evt) {
+        return unit.compare(evt.getStart(), endDate);
+    });
+    
+    this._currentIndex = this._maxIndex;
+    this._hasNext = false;
+    this._next = null;
+    this._findNext();
+};
+
+SimileAjax.EventIndex._ReverseIterator.prototype = {
+    hasNext: function() { return this._hasNext; },
+    next: function() {
+        if (this._hasNext) {
+            var next = this._next;
+            this._findNext();
+            
+            return next;
+        } else {
+            return null;
+        }
+    },
+    _findNext: function() {
+        var unit = this._unit;
+        while ((--this._currentIndex) >= this._minIndex) {
+            var evt = this._events.elementAt(this._currentIndex);
+            if (unit.compare(evt.getStart(), this._endDate) < 0 &&
+                unit.compare(evt.getEnd(), this._startDate) > 0) {
+                
+                this._next = evt;
+                this._hasNext = true;
+                return;
+            }
+        }
+        this._next = null;
+        this._hasNext = false;
+    }
+};
+
+SimileAjax.EventIndex._AllIterator = function(events) {
+    this._events = events;
+    this._index = 0;
+};
+
+SimileAjax.EventIndex._AllIterator.prototype = {
+    hasNext: function() {
+        return this._index < this._events.length();
+    },
+    next: function() {
+        return this._index < this._events.length() ?
+            this._events.elementAt(this._index++) : null;
+    }
+};
\ No newline at end of file

Added: websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/date-time.js
==============================================================================
--- websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/date-time.js (added)
+++ websites/staging/ooo-site/trunk/content/scripts/api.simile-widgets.org/ajax/2.2.1/scripts/date-time.js Wed May 17 15:33:02 2017
@@ -0,0 +1,452 @@
+/**
+ * @fileOverview A collection of date/time utility functions
+ * @name SimileAjax.DateTime
+ */
+
+SimileAjax.DateTime = new Object();
+
+SimileAjax.DateTime.MILLISECOND    = 0;
+SimileAjax.DateTime.SECOND         = 1;
+SimileAjax.DateTime.MINUTE         = 2;
+SimileAjax.DateTime.HOUR           = 3;
+SimileAjax.DateTime.DAY            = 4;
+SimileAjax.DateTime.WEEK           = 5;
+SimileAjax.DateTime.MONTH          = 6;
+SimileAjax.DateTime.YEAR           = 7;
+SimileAjax.DateTime.DECADE         = 8;
+SimileAjax.DateTime.CENTURY        = 9;
+SimileAjax.DateTime.MILLENNIUM     = 10;
+
+SimileAjax.DateTime.EPOCH          = -1;
+SimileAjax.DateTime.ERA            = -2;
+
+/**
+ * An array of unit lengths, expressed in milliseconds, of various lengths of
+ * time.  The array indices are predefined and stored as properties of the
+ * SimileAjax.DateTime object, e.g. SimileAjax.DateTime.YEAR.
+ * @type Array
+ */
+SimileAjax.DateTime.gregorianUnitLengths = [];
+    (function() {
+        var d = SimileAjax.DateTime;
+        var a = d.gregorianUnitLengths;
+        
+        a[d.MILLISECOND] = 1;
+        a[d.SECOND]      = 1000;
+        a[d.MINUTE]      = a[d.SECOND] * 60;
+        a[d.HOUR]        = a[d.MINUTE] * 60;
+        a[d.DAY]         = a[d.HOUR] * 24;
+        a[d.WEEK]        = a[d.DAY] * 7;
+        a[d.MONTH]       = a[d.DAY] * 31;
+        a[d.YEAR]        = a[d.DAY] * 365;
+        a[d.DECADE]      = a[d.YEAR] * 10;
+        a[d.CENTURY]     = a[d.YEAR] * 100;
+        a[d.MILLENNIUM]  = a[d.YEAR] * 1000;
+    })();
+    
+SimileAjax.DateTime._dateRegexp = new RegExp(
+    "^(-?)([0-9]{4})(" + [
+        "(-?([0-9]{2})(-?([0-9]{2}))?)", // -month-dayOfMonth
+        "(-?([0-9]{3}))",                // -dayOfYear
+        "(-?W([0-9]{2})(-?([1-7]))?)"    // -Wweek-dayOfWeek
+    ].join("|") + ")?$"
+);
+SimileAjax.DateTime._timezoneRegexp = new RegExp(
+    "Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$"
+);
+SimileAjax.DateTime._timeRegexp = new RegExp(
+    "^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(\.([0-9]+))?)?)?$"
+);
+
+/**
+ * Takes a date object and a string containing an ISO 8601 date and sets the
+ * the date using information parsed from the string.  Note that this method
+ * does not parse any time information.
+ *
+ * @param {Date} dateObject the date object to modify
+ * @param {String} string an ISO 8601 string to parse
+ * @return {Date} the modified date object
+ */
+SimileAjax.DateTime.setIso8601Date = function(dateObject, string) {
+    /*
+     *  This function has been adapted from dojo.date, v.0.3.0
+     *  http://dojotoolkit.org/.
+     */
+     
+    var d = string.match(SimileAjax.DateTime._dateRegexp);
+    if(!d) {
+        throw new Error("Invalid date string: " + string);
+    }
+    
+    var sign = (d[1] == "-") ? -1 : 1; // BC or AD
+    var year = sign * d[2];
+    var month = d[5];
+    var date = d[7];
+    var dayofyear = d[9];
+    var week = d[11];
+    var dayofweek = (d[13]) ? d[13] : 1;
+
+    dateObject.setUTCFullYear(year);
+    if (dayofyear) { 
+        dateObject.setUTCMonth(0);
+        dateObject.setUTCDate(Number(dayofyear));
+    } else if (week) {
+        dateObject.setUTCMonth(0);
+        dateObject.setUTCDate(1);
+        var gd = dateObject.getUTCDay();
+        var day =  (gd) ? gd : 7;
+        var offset = Number(dayofweek) + (7 * Number(week));
+        
+        if (day <= 4) { 
+            dateObject.setUTCDate(offset + 1 - day); 
+        } else { 
+            dateObject.setUTCDate(offset + 8 - day); 
+        }
+    } else {
+        if (month) { 
+            dateObject.setUTCDate(1);
+            dateObject.setUTCMonth(month - 1); 
+        }
+        if (date) { 
+            dateObject.setUTCDate(date); 
+        }
+    }
+    
+    return dateObject;
+};
+
+/**
+ * Takes a date object and a string containing an ISO 8601 time and sets the
+ * the time using information parsed from the string.  Note that this method
+ * does not parse any date information.
+ *
+ * @param {Date} dateObject the date object to modify
+ * @param {String} string an ISO 8601 string to parse
+ * @return {Date} the modified date object
+ */
+SimileAjax.DateTime.setIso8601Time = function (dateObject, string) {
+    /*
+     *  This function has been adapted from dojo.date, v.0.3.0
+     *  http://dojotoolkit.org/.
+     */
+    
+    var d = string.match(SimileAjax.DateTime._timeRegexp);
+    if(!d) {
+        SimileAjax.Debug.warn("Invalid time string: " + string);
+        return false;
+    }
+    var hours = d[1];
+    var mins = Number((d[3]) ? d[3] : 0);
+    var secs = (d[5]) ? d[5] : 0;
+    var ms = d[7] ? (Number("0." + d[7]) * 1000) : 0;
+
+    dateObject.setUTCHours(hours);
+    dateObject.setUTCMinutes(mins);
+    dateObject.setUTCSeconds(secs);
+    dateObject.setUTCMilliseconds(ms);
+    
+    return dateObject;
+};
+
+/**
+ * The timezone offset in minutes in the user's browser.
+ * @type Number
+ */
+SimileAjax.DateTime.timezoneOffset = new Date().getTimezoneOffset();
+
+/**
+ * Takes a date object and a string containing an ISO 8601 date and time and 
+ * sets the date object using information parsed from the string.
+ *
+ * @param {Date} dateObject the date object to modify
+ * @param {String} string an ISO 8601 string to parse
+ * @return {Date} the modified date object
+ */
+SimileAjax.DateTime.setIso8601 = function (dateObject, string){
+    /*
+     *  This function has been adapted from dojo.date, v.0.3.0
+     *  http://dojotoolkit.org/.
+     */
+     
+    var offset = null;
+    var comps = (string.indexOf("T") == -1) ? string.split(" ") : string.split("T");
+    
+    SimileAjax.DateTime.setIso8601Date(dateObject, comps[0]);
+    if (comps.length == 2) { 
+        // first strip timezone info from the end
+        var d = comps[1].match(SimileAjax.DateTime._timezoneRegexp);
+        if (d) {
+            if (d[0] == 'Z') {
+                offset = 0;
+            } else {
+                offset = (Number(d[3]) * 60) + Number(d[5]);
+                offset *= ((d[2] == '-') ? 1 : -1);
+            }
+            comps[1] = comps[1].substr(0, comps[1].length - d[0].length);
+        }
+
+        SimileAjax.DateTime.setIso8601Time(dateObject, comps[1]); 
+    }
+    if (offset == null) {
+        offset = dateObject.getTimezoneOffset(); // local time zone if no tz info
+    }
+    dateObject.setTime(dateObject.getTime() + offset * 60000);
+    
+    return dateObject;
+};
+
+/**
+ * Takes a string containing an ISO 8601 date and returns a newly instantiated
+ * date object with the parsed date and time information from the string.
+ *
+ * @param {String} string an ISO 8601 string to parse
+ * @return {Date} a new date object created from the string
+ */
+SimileAjax.DateTime.parseIso8601DateTime = function (string) {
+    try {
+        return SimileAjax.DateTime.setIso8601(new Date(0), string);
+    } catch (e) {
+        return null;
+    }
+};
+
+/**
+ * Takes a string containing a Gregorian date and time and returns a newly
+ * instantiated date object with the parsed date and time information from the
+ * string.  If the param is actually an instance of Date instead of a string, 
+ * simply returns the given date instead.
+ *
+ * @param {Object} o an object, to either return or parse as a string
+ * @return {Date} the date object
+ */
+SimileAjax.DateTime.parseGregorianDateTime = function(o) {
+    if (o == null) {
+        return null;
+    } else if (o instanceof Date) {
+        return o;
+    }
+    
+    var s = o.toString();
+    if (s.length > 0 && s.length < 8) {
+        var space = s.indexOf(" ");
+        if (space > 0) {
+            var year = parseInt(s.substr(0, space));
+            var suffix = s.substr(space + 1);
+            if (suffix.toLowerCase() == "bc") {
+                year = 1 - year;
+            }
+        } else {
+            var year = parseInt(s);
+        }
+            
+        var d = new Date(0);
+        d.setUTCFullYear(year);
+        
+        return d;
+    }
+    
+    try {
+        return new Date(Date.parse(s));
+    } catch (e) {
+        return null;
+    }
+};
+
+/**
+ * Rounds date objects down to the nearest interval or multiple of an interval.
+ * This method modifies the given date object, converting it to the given
+ * timezone if specified.
+ * 
+ * @param {Date} date the date object to round
+ * @param {Number} intervalUnit a constant, integer index specifying an 
+ *   interval, e.g. SimileAjax.DateTime.HOUR
+ * @param {Number} timeZone a timezone shift, given in hours
+ * @param {Number} multiple a multiple of the interval to round by
+ * @param {Number} firstDayOfWeek an integer specifying the first day of the
+ *   week, 0 corresponds to Sunday, 1 to Monday, etc.
+ */
+SimileAjax.DateTime.roundDownToInterval = function(date, intervalUnit, timeZone, multiple, firstDayOfWeek) {
+    var timeShift = timeZone * 
+        SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.HOUR];
+        
+    var date2 = new Date(date.getTime() + timeShift);
+    var clearInDay = function(d) {
+        d.setUTCMilliseconds(0);
+        d.setUTCSeconds(0);
+        d.setUTCMinutes(0);
+        d.setUTCHours(0);
+    };
+    var clearInYear = function(d) {
+        clearInDay(d);
+        d.setUTCDate(1);
+        d.setUTCMonth(0);
+    };
+    
+    switch(intervalUnit) {
+    case SimileAjax.DateTime.MILLISECOND:
+        var x = date2.getUTCMilliseconds();
+        date2.setUTCMilliseconds(x - (x % multiple));
+        break;
+    case SimileAjax.DateTime.SECOND:
+        date2.setUTCMilliseconds(0);
+        
+        var x = date2.getUTCSeconds();
+        date2.setUTCSeconds(x - (x % multiple));
+        break;
+    case SimileAjax.DateTime.MINUTE:
+        date2.setUTCMilliseconds(0);
+        date2.setUTCSeconds(0);
+        
+        var x = date2.getUTCMinutes();
+        date2.setTime(date2.getTime() - 
+            (x % multiple) * SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.MINUTE]);
+        break;
+    case SimileAjax.DateTime.HOUR:
+        date2.setUTCMilliseconds(0);
+        date2.setUTCSeconds(0);
+        date2.setUTCMinutes(0);
+        
+        var x = date2.getUTCHours();
+        date2.setUTCHours(x - (x % multiple));
+        break;
+    case SimileAjax.DateTime.DAY:
+        clearInDay(date2);
+        break;
+    case SimileAjax.DateTime.WEEK:
+        clearInDay(date2);
+        var d = (date2.getUTCDay() + 7 - firstDayOfWeek) % 7;
+        date2.setTime(date2.getTime() - 
+            d * SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.DAY]);
+        break;
+    case SimileAjax.DateTime.MONTH:
+        clearInDay(date2);
+        date2.setUTCDate(1);
+        
+        var x = date2.getUTCMonth();
+        date2.setUTCMonth(x - (x % multiple));
+        break;
+    case SimileAjax.DateTime.YEAR:
+        clearInYear(date2);
+        
+        var x = date2.getUTCFullYear();
+        date2.setUTCFullYear(x - (x % multiple));
+        break;
+    case SimileAjax.DateTime.DECADE:
+        clearInYear(date2);
+        date2.setUTCFullYear(Math.floor(date2.getUTCFullYear() / 10) * 10);
+        break;
+    case SimileAjax.DateTime.CENTURY:
+        clearInYear(date2);
+        date2.setUTCFullYear(Math.floor(date2.getUTCFullYear() / 100) * 100);
+        break;
+    case SimileAjax.DateTime.MILLENNIUM:
+        clearInYear(date2);
+        date2.setUTCFullYear(Math.floor(date2.getUTCFullYear() / 1000) * 1000);
+        break;
+    }
+    
+    date.setTime(date2.getTime() - timeShift);
+};
+
+/**
+ * Rounds date objects up to the nearest interval or multiple of an interval.
+ * This method modifies the given date object, converting it to the given
+ * timezone if specified.
+ * 
+ * @param {Date} date the date object to round
+ * @param {Number} intervalUnit a constant, integer index specifying an 
+ *   interval, e.g. SimileAjax.DateTime.HOUR
+ * @param {Number} timeZone a timezone shift, given in hours
+ * @param {Number} multiple a multiple of the interval to round by
+ * @param {Number} firstDayOfWeek an integer specifying the first day of the
+ *   week, 0 corresponds to Sunday, 1 to Monday, etc.
+ * @see SimileAjax.DateTime.roundDownToInterval
+ */
+SimileAjax.DateTime.roundUpToInterval = function(date, intervalUnit, timeZone, multiple, firstDayOfWeek) {
+    var originalTime = date.getTime();
+    SimileAjax.DateTime.roundDownToInterval(date, intervalUnit, timeZone, multiple, firstDayOfWeek);
+    if (date.getTime() < originalTime) {
+        date.setTime(date.getTime() + 
+            SimileAjax.DateTime.gregorianUnitLengths[intervalUnit] * multiple);
+    }
+};
+
+/**
+ * Increments a date object by a specified interval, taking into
+ * consideration the timezone.
+ *
+ * @param {Date} date the date object to increment
+ * @param {Number} intervalUnit a constant, integer index specifying an 
+ *   interval, e.g. SimileAjax.DateTime.HOUR
+ * @param {Number} timeZone the timezone offset in hours
+ */
+SimileAjax.DateTime.incrementByInterval = function(date, intervalUnit, timeZone) {
+    timeZone = (typeof timeZone == 'undefined') ? 0 : timeZone;
+
+    var timeShift = timeZone * 
+        SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.HOUR];
+        
+    var date2 = new Date(date.getTime() + timeShift);
+
+    switch(intervalUnit) {
+    case SimileAjax.DateTime.MILLISECOND:
+        date2.setTime(date2.getTime() + 1)
+        break;
+    case SimileAjax.DateTime.SECOND:
+        date2.setTime(date2.getTime() + 1000);
+        break;
+    case SimileAjax.DateTime.MINUTE:
+        date2.setTime(date2.getTime() + 
+            SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.MINUTE]);
+        break;
+    case SimileAjax.DateTime.HOUR:
+        date2.setTime(date2.getTime() + 
+            SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.HOUR]);
+        break;
+    case SimileAjax.DateTime.DAY:
+        date2.setUTCDate(date2.getUTCDate() + 1);
+        break;
+    case SimileAjax.DateTime.WEEK:
+        date2.setUTCDate(date2.getUTCDate() + 7);
+        break;
+    case SimileAjax.DateTime.MONTH:
+        date2.setUTCMonth(date2.getUTCMonth() + 1);
+        break;
+    case SimileAjax.DateTime.YEAR:
+        date2.setUTCFullYear(date2.getUTCFullYear() + 1);
+        break;
+    case SimileAjax.DateTime.DECADE:
+        date2.setUTCFullYear(date2.getUTCFullYear() + 10);
+        break;
+    case SimileAjax.DateTime.CENTURY:
+        date2.setUTCFullYear(date2.getUTCFullYear() + 100);
+        break;
+    case SimileAjax.DateTime.MILLENNIUM:
+        date2.setUTCFullYear(date2.getUTCFullYear() + 1000);
+        break;
+    }
+
+    date.setTime(date2.getTime() - timeShift);
+};
+
+/**
+ * Returns a new date object with the given time offset removed.
+ *
+ * @param {Date} date the starting date
+ * @param {Number} timeZone a timezone specified in an hour offset to remove
+ * @return {Date} a new date object with the offset removed
+ */
+SimileAjax.DateTime.removeTimeZoneOffset = function(date, timeZone) {
+    return new Date(date.getTime() + 
+        timeZone * SimileAjax.DateTime.gregorianUnitLengths[SimileAjax.DateTime.HOUR]);
+};
+
+/**
+ * Returns the timezone of the user's browser.
+ *
+ * @return {Number} the timezone in the user's locale in hours
+ */
+SimileAjax.DateTime.getTimezone = function() {
+    var d = new Date().getTimezoneOffset();
+    return d / -60;
+};