You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ed...@apache.org on 2006/11/11 17:44:48 UTC
svn commit: r473755 [34/43] - in /jackrabbit/trunk/contrib/jcr-browser: ./
src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/jackrabbit/
src/main/java/org/apache/jackrabbit/browser/ src/main/resources/ ...
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Select.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Show.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Show.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Show.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Show.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,244 @@
+dojo.provide("dojo.widget.Show");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.event.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.math.curves");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.func");
+
+dojo.widget.defineWidget(
+ "dojo.widget.Show",
+ dojo.widget.HtmlWidget,
+ function(){
+ this._slides=[];
+ },
+ {
+ isContainer: true,
+ _slide: -1,
+
+ body: null,
+ nav: null,
+ hider: null,
+ select: null,
+ option: null,
+ inNav: false,
+ debugPane: null,
+ noClick: false,
+ templatePath: dojo.uri.dojoUri("src/widget/templates/Show.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/Show.css"),
+ fillInTemplate: function(args, frag){
+ if(args.debugPane){
+ var dp = this.debugPane = dojo.widget.byId(args.debugPane);
+ dp.hide();
+ dojo.event.connect(dp, "closeWindow", dojo.lang.hitch(this, function(){ this.debugPane = false; }));
+ }
+ var source = this.getFragNodeRef(frag);
+ this.sourceNode = dojo.body().appendChild(source.cloneNode(true));
+ for(var i = 0, child; child = this.sourceNode.childNodes[i]; i++){
+ if(child.tagName && child.getAttribute("dojotype").toLowerCase() == "showslide"){
+ child.className = "dojoShowPrintSlide";
+ child.innerHTML = "<h1>" + child.title + "</h1>" + child.innerHTML;
+ }
+ }
+ this.sourceNode.className = "dojoShowPrint";
+ this.sourceNode.style.display = "none";
+
+ dojo.event.connect(document, "onclick", this, "gotoSlideByEvent");
+ if(dojo.render.html.ie) {
+ dojo.event.connect(document,"onkeydown",this, "gotoSlideByEvent");
+ } else {
+ // while keydown works, keypress allows rapid successive key presses
+ // to be handled correctly
+ dojo.event.connect(document,"onkeypress",this, "gotoSlideByEvent");
+ }
+ dojo.event.connect(window, "onresize", this, "resizeWindow");
+ dojo.event.connect(this.nav, "onmousemove", this, "popUpNav");
+ },
+ postCreate: function(){
+ this._slides = [];
+ for(var i = 0, child; child = this.children[i]; i++){
+ if(child.widgetType == "ShowSlide"){
+ this._slides.push(child);
+ this.option.text = child.title+" ("+(i+1)+")";
+ this.option.parentNode.insertBefore(this.option.cloneNode(true), this.option);
+ }
+ }
+ this.option.parentNode.removeChild(this.option);
+ this.domNode.style.display = "block";
+ this.resizeWindow();
+
+ this.gotoSlide(0, true);
+
+ // check to see if we're initialized from a particular slide
+ dojo.addOnLoad(dojo.lang.hitch(this,
+ function(){
+ var th = window.location.hash;
+ if(th.length){
+ var parts = (""+window.location).split(this.widgetId+"_SlideNo_");
+ if(parts.length > 1){
+ setTimeout(dojo.lang.hitch(this, function(){
+ this.gotoSlide(parseInt(parts[1]), true);
+ }), 300);
+ }
+ }
+ })
+ );
+ },
+ gotoSlide: function(/*int*/ slide, /*Boolean*/preventSetHash){
+ if(slide == this._slide){
+ return;
+ }
+
+ if(!this._slides[slide]){
+ // slide: string
+ for(var i = 0, child; child = this._slides[i]; i++){
+ if(child.title == slide){
+ slide = i;
+ break;
+ }
+ }
+ }
+
+ if(!this._slides[slide]){
+ return;
+ }
+
+ if(this.debugPane){
+ if(this._slides[slide].debug){
+ this.debugPane.show();
+ }else{
+ this.debugPane.hide();
+ }
+ }
+
+ if(this._slide != -1){
+ while(this._slides[this._slide].previousAction()){}
+ }
+
+ if(!preventSetHash){
+ window.location.href = "#"+this.widgetId+"_SlideNo_"+slide;
+ }
+ if(this._slides[this._slide]){
+ this._slides[this._slide].hide();
+ }
+
+ this._slide = slide;
+ this.select.selectedIndex = slide;
+ var cn = this.contentNode;
+ while(cn.firstChild){ cn.removeChild(cn.firstChild); }
+ cn.appendChild(this._slides[slide].domNode);
+ this._slides[slide].show();
+ },
+ gotoSlideByEvent: function(/*Event*/ event){
+ var node = event.target;
+ var type = event.type;
+ if(type == "click"){
+ if(node.tagName == "OPTION" && node.parentNode == this.select){
+ this.gotoSlide(node.index);
+ }else if(node == this.select){
+ this.gotoSlide(node.selectedIndex);
+ }else{
+ this.nextSlide(event);
+ }
+ }else if (type=="keydown" || type=="keypress") {
+ var key = event.keyCode;
+ var ch = event.charCode;
+ if(key == 63234 || key == 37){
+ this.previousSlide(event);
+ }else if(key == 63235 || key == 39 || ch == 32){
+ this.nextSlide(event);
+ }
+ }
+ },
+ nextSlide: function(/*Event?*/ event){
+ if(!this.stopEvent(event)){
+ return false;
+ }
+ if(!this._slides[this._slide].nextAction(event)){
+ if((this._slide + 1) != this._slides.length){
+ this.gotoSlide(this._slide + 1);
+ return true; // boolean
+ }
+ return false; // boolean
+ }
+ },
+ previousSlide: function(/*Event?*/ event){
+ if(!this.stopEvent(event)){
+ return false;
+ }
+ if(!this._slides[this._slide].previousAction(event)){
+ if((this._slide - 1) != -1){
+ this.gotoSlide(this._slide - 1);
+ return true; // boolean
+ }
+ return false; // boolean
+ }
+ },
+
+ stopEvent: function(/*Event*/ ev){
+ if(!ev){
+ return true;
+ }
+
+ if (ev.type == "click" && (this._slides[this._slide].noClick || this.noClick)) {
+ return false;
+ }
+ var target = ev.target;
+ // Check to see if the target is below the show domNode
+ while(target != null){
+ if(target == this.domNode){
+ target = ev.target;
+ break;
+ }
+ target = target.parentNode;
+ }
+ // Now that we know it's below this widget's domNode, we bubble up until we get to our domNode
+ while(target && target != this.domNode){
+ if(target.tagName == "A" || target.tagName == "INPUT" || target.tagName == "TEXTAREA" || target.tagName == "SELECT"){
+ return false;
+ }
+ if(typeof target.onclick == "function" || typeof target.onkeypress == "function"){
+ return false;
+ }
+ target = target.parentNode;
+ }
+
+ if(window.event){
+ ev.returnValue = false;
+ ev.cancelBubble = true;
+ }else{
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+
+ return true;
+ },
+ popUpNav: function(){
+ if(!this.inNav){
+ // dojo.widget.Show.node = this.nav;
+ dojo.lfx.propertyAnimation(this.nav, {
+ "height": { start: 5, end: 30 }
+ }, 250).play();
+ }
+ clearTimeout(this.inNav);
+ this.inNav = setTimeout(dojo.lang.hitch(this, "hideNav"), 2000);
+ },
+ hideNav: function(){
+ clearTimeout(this.inNav);
+ this.inNav = false;
+ // dojo.widget.Show.node = this.nav;
+ dojo.lfx.propertyAnimation(this.nav, {
+ "height": { start: 30, end: 5 }
+ }, 250).play();
+ },
+ resizeWindow: function(/*Event*/ ev){
+ dojo.body().style.height = "auto";
+ var h = Math.max(
+ document.documentElement.scrollHeight || dojo.body().scrollHeight,
+ dojo.html.getViewport().height);
+ dojo.body().style.height = h + "px";
+ }
+});
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Show.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowAction.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowAction.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowAction.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowAction.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,14 @@
+dojo.provide("dojo.widget.ShowAction");
+dojo.require("dojo.widget.*");
+
+dojo.widget.defineWidget(
+ "dojo.widget.ShowAction",
+ dojo.widget.HtmlWidget,
+{
+ on: "",
+ action: "fade",
+ duration: 350,
+ from: "",
+ to: "",
+ auto: "false"
+});
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowAction.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowSlide.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowSlide.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowSlide.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowSlide.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,219 @@
+dojo.provide("dojo.widget.ShowSlide");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.lfx.html");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.animation.Animation");
+dojo.require("dojo.gfx.color");
+
+dojo.widget.defineWidget(
+ "dojo.widget.ShowSlide",
+ dojo.widget.HtmlWidget,
+{
+ title: "",
+ _action: -1,
+ isContainer: true,
+ _components: {},
+ _actions: [],
+
+ gotoAction: function(/*int*/ action){
+ this._action = action;
+ },
+ _nextAction: function(/*Event?*/ event){
+ if((this._action + 1) != this._actions.length){
+ ++this._action;
+ return true; // boolean
+ }
+ return false; // boolean
+ },
+ _previousAction: function(/*Event?*/ event){
+ if((this._action - 1) != -1){
+ --this._action;
+ return true; // boolean
+ }
+ return false; // boolean
+ },
+
+ htmlTitle: null,
+ debug: false,
+ noClick: false,
+ templatePath: dojo.uri.dojoUri("src/widget/templates/ShowSlide.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/ShowSlide.css"),
+ postCreate: function(){
+ this.htmlTitle.innerHTML = this.title;
+
+ var actions = this.getChildrenOfType("ShowAction", false);
+ var atypes = {};
+ dojo.lang.forEach(actions, function(act){ atypes[act.on] = true; });
+
+ this._components = {};
+ var cn = this.containerNode;
+ var nodes = dojo.render.html.ie ? cn.all : cn.getElementsByTagName('*');
+ dojo.lang.forEach(nodes, function(node){
+ var as = node.getAttribute("as");
+ if(as){
+ if(!this._components[as]){
+ this._components[as] = [];
+ }
+ this._components[as].push(node);
+ if(!atypes[as]){
+ var tmpAction = dojo.widget.createWidget("ShowAction", { on: as });
+ this.addChild(tmpAction);
+ atypes[as] = true;
+ }
+ }
+ }, this);
+
+ this._actions = [];
+ actions = this.getChildrenOfType("ShowAction", false);
+ dojo.lang.forEach(actions, function(child){
+ this._actions.push(child);
+ var components = this._components[child.on];
+ for(var j = 0, component; component = components[j]; j++){
+ if(child["action"] && (
+ (child.action != "remove")&&
+ (child.action != "fadeout")&&
+ (child.action != "wipeout")
+ ) ){
+ this.hideComponent(component);
+ }
+ }
+ }, this);
+ },
+
+ previousAction: function(/*Event?*/ event){
+ if(!this.parent.stopEvent(event)){
+ return false;
+ }
+
+ var action = this._actions[this._action];
+ if(!action){
+ return false;
+ }
+
+ var on = action.on;
+ while(action.on == on){
+ var components = this._components[on];
+ for(var i = 0, component; component = components[i]; i++){
+ if(
+ (action.action == "remove")||
+ (action.action == "fadeout")||
+ (action.action == "wipeout")
+ ){
+ if(component.style.display == "none"){
+ component.style.display = "";
+ component.style.visibility = "visible";
+ var exits = true;
+ }
+ dojo.html.setOpacity(component, 1);
+ }else if(action.action){
+ this.hideComponent(component);
+ }
+ }
+
+ --this._action;
+
+ if(exits){
+ return true;
+ }
+
+ if(action.auto == "true"){
+ on = this._actions[this._action].on;
+ }
+
+ action = this._actions[this._action];
+ if(!action){
+ return false;
+ }
+ }
+ return true;
+ },
+ hideComponent: function(/*Node*/ component){
+ component.style.visibility = "hidden";
+ component.style.backgroundColor = "transparent";
+ var parent = component.parentNode;
+ if((parent)&&(parent.tagName.toLowerCase() == "li")){
+ parent.oldType = parent.style.listStyleType;
+ parent.style.listStyleType = "none";
+ }
+ },
+ nextAction: function(/*Event?*/ event){
+ if(!this.parent.stopEvent(event)){
+ return false;
+ }
+
+ if(!this._nextAction(this)){
+ return false;
+ }
+
+ var action = this._actions[this._action];
+ if(!action){
+ return false;
+ }
+ var tmpAction = action["action"];
+
+ var components = this._components[action.on];
+ for(var i = 0, component; component = components[i]; i++){
+ if(tmpAction){
+ var duration = action.duration || 1000;
+ if((tmpAction == "fade")||(tmpAction == "fadeIn")){
+ dojo.html.setOpacity(component, 0);
+ dojo.lfx.html.fadeShow(component, duration).play(true);
+ }else if(tmpAction == "fadeout"){
+ dojo.lfx.html.fadeHide(component, duration).play(true);
+ }else if(tmpAction == "fly"){
+ var width = dojo.html.getMarginBox(component).width;
+ var position = dojo.html.getAbsolutePosition(component);
+ // alert(position);
+ component.style.position = "relative";
+ component.style.left = -(width + position.x) + "px";
+ dojo.lfx.html.slideBy(component, { top: 0, left: (width + position.x)}, duration, -1, this.callWith).play(true);
+ }else if((tmpAction == "wipe")||(tmpAction == "wipein")){
+ dojo.lfx.html.wipeIn(component, duration).play();
+ }else if(tmpAction == "wipeout"){
+ dojo.lfx.html.wipeOut(component, duration).play();
+ }else if(tmpAction == "color"){
+ var from = new dojo.gfx.color.Color(action.from).toRgb();
+ var to = new dojo.gfx.color.Color(action.to).toRgb();
+ var anim = new dojo.animation.Animation(new dojo.math.curves.Line(from, to), duration, 0);
+ var node = component;
+ dojo.event.connect(anim, "onAnimate", function(e) {
+ node.style.color = "rgb(" + e.coordsAsInts().join(",") + ")";
+ });
+ anim.play(true);
+ }else if(tmpAction == "bgcolor"){
+ dojo.lfx.html.unhighlight(component, action.to, duration).play();
+ }else if(tmpAction == "remove"){
+ component.style.display = "none";
+ }
+
+ if(tmpAction == "hide"){
+ component.style.visibility = "hidden";
+ }else{
+ component.style.visibility = "visible";
+ }
+ }
+ }
+
+ action = this._actions[this._action + 1];
+ if(action && action.auto == "true"){
+ this.nextAction();
+ }
+
+ return true;
+ },
+ callWith: function(/*Node*/ node){
+ if(!node){ return; }
+ if(dojo.lang.isArray(node)){
+ dojo.lang.forEach(node, arguments.callee);
+ return;
+ }
+ var parent = node.parentNode;
+ if((parent)&&(parent.tagName.toLowerCase() == "li")){
+ parent.style.listStyleType = parent.oldType;
+ }
+ }
+});
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/ShowSlide.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SlideShow.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SlideShow.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SlideShow.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SlideShow.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,131 @@
+dojo.provide("dojo.widget.SlideShow");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.html.display");
+
+dojo.widget.defineWidget(
+ "dojo.widget.SlideShow",
+ dojo.widget.HtmlWidget,
+ {
+ templatePath: dojo.uri.dojoUri("src/widget/templates/SlideShow.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/SlideShow.css"),
+
+ // useful properties
+ imgUrls: [], // the images we'll go through
+ imgUrlBase: "",
+ urlsIdx: 0, // where in the images we are
+ delay: 4000, // give it 4 seconds
+ transitionInterval: 2000, // 2 seconds
+ imgWidth: 800, // img width
+ imgHeight: 600, // img height
+ background: "img2", // what's in the bg
+ foreground: "img1", // what's in the fg
+ stopped: false, // should I stay or should I go?
+ fadeAnim: null, // references our animation
+
+ // our DOM nodes:
+ imagesContainer: null,
+ startStopButton: null,
+ controlsContainer: null,
+ img1: null,
+ img2: null,
+ preventCache: false,
+
+ fillInTemplate: function(){
+ // safari will cache the images and not fire an image onload event if
+ // there are only two images in the slideshow
+ if(dojo.render.html.safari && this.imgUrls.length == 2) {
+ this.preventCache = true;
+ }
+ dojo.html.setOpacity(this.img1, 0.9999);
+ dojo.html.setOpacity(this.img2, 0.9999);
+ with(this.imagesContainer.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ with(this.img1.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ with(this.img2.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ if(this.imgUrls.length>1){
+ this.img2.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++] + this.getUrlSuffix();
+ this.endTransition();
+ }else{
+ this.img1.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++] + this.getUrlSuffix();
+ }
+ },
+
+ getUrlSuffix: function() {
+ if(this.preventCache) {
+ return "?ts=" + (new Date()).getTime();
+ } else {
+ return "";
+ }
+ },
+
+ togglePaused: function(){
+ dojo.debug("pause");
+ if(this.stopped){
+ this.stopped = false;
+ this.backgroundImageLoaded();
+ this.startStopButton.value= "pause";
+ }else{
+ this.stopped = true;
+ this.startStopButton.value= "play";
+ }
+ },
+
+ backgroundImageLoaded: function(){
+ // start fading out the foreground image
+ if(this.stopped){ return; }
+
+ // actually start the fadeOut effect
+ // NOTE: if we wanted to use other transition types, we'd set them up
+ // here as well
+ if(this.fadeAnim) {
+ this.fadeAnim.stop();
+ }
+ this.fadeAnim = dojo.lfx.fadeOut(this[this.foreground],
+ this.transitionInterval, null);
+ dojo.event.connect(this.fadeAnim,"onEnd",this,"endTransition");
+ this.fadeAnim.play();
+ },
+
+ endTransition: function(){
+ // move the foreground image to the background
+ with(this[this.background].style){ zIndex = parseInt(zIndex)+1; }
+ with(this[this.foreground].style){ zIndex = parseInt(zIndex)-1; }
+
+ // fg/bg book-keeping
+ var tmp = this.foreground;
+ this.foreground = this.background;
+ this.background = tmp;
+ // keep on truckin
+ this.loadNextImage();
+ },
+
+ loadNextImage: function(){
+ // load a new image in that container, and make sure it informs
+ // us when it finishes loading
+ dojo.event.kwConnect({
+ srcObj: this[this.background],
+ srcFunc: "onload",
+ adviceObj: this,
+ adviceFunc: "backgroundImageLoaded",
+ once: true, // make sure we only ever hear about it once
+ delay: this.delay
+ });
+ dojo.html.setOpacity(this[this.background], 1.0);
+ this[this.background].src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
+ if(this.urlsIdx>(this.imgUrls.length-1)){
+ this.urlsIdx = 0;
+ }
+ }
+ }
+);
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SlideShow.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Slider.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Slider.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Slider.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Slider.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,878 @@
+dojo.provide("dojo.widget.Slider");
+
+// load dependencies
+dojo.require("dojo.event.*");
+dojo.require("dojo.dnd.*");
+// dojo.dnd.* doesn't include this package, because it's not in __package__.js
+dojo.require("dojo.dnd.HtmlDragMove");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.html.layout");
+
+
+// summary
+// Slider Widget.
+//
+// The slider widget comes in three forms:
+// 1. Base Slider widget which supports movement in x and y dimensions
+// 2. Vertical Slider (SliderVertical) widget which supports movement
+// only in the y dimension.
+// 3. Horizontal Slider (SliderHorizontal) widget which supports movement
+// only in the x dimension.
+//
+// The key objects in the widget are:
+// - a container div which displays a bar in the background (Slider object)
+// - a handle inside the container div, which represents the value
+// (sliderHandle DOM node)
+// - the object which moves the handle (_handleMove is of type
+// SliderDragMoveSource)
+//
+// The values for the slider are calculated by grouping pixels together,
+// based on the number of values to be represented by the slider.
+// The number of pixels in a group is called the _valueSize
+// e.g. if slider is 150 pixels long, and is representing the values
+// 0,1,...10 then pixels are grouped into lots of 15 (_valueSize), where:
+// value 0 maps to pixels 0 - 7
+// 1 8 - 22
+// 2 23 - 37 etc.
+// The accuracy of the slider is limited to the number of pixels
+// (i.e tiles > pixels will result in the slider not being able to
+// represent some values).
+dojo.widget.defineWidget (
+ "dojo.widget.Slider",
+ dojo.widget.HtmlWidget,
+ {
+ // Number
+ // minimum value to be represented by slider in the horizontal direction
+ minimumX: 0,
+ // Number
+ // minimum value to be represented by slider in the vertical direction
+ minimumY: 0,
+ // Number
+ // maximum value to be represented by slider in the horizontal direction
+ maximumX: 10,
+ // Number
+ // maximum value to be represented by slider in the vertical direction
+ maximumY: 10,
+ // Number
+ // number of values to be represented by slider in the horizontal direction
+ // =0 means no snapping
+ snapValuesX: 0,
+ // Number
+ // number of values to be represented by slider in the vertical direction
+ // =0 means no snapping
+ snapValuesY: 0,
+ // should the handle snap to the grid or remain where it was dragged to?
+ // FIXME: snapToGrid=false is logically in conflict with setting snapValuesX and snapValuesY
+ _snapToGrid: true,
+ // Boolean
+ // enables (disables) sliding in the horizontal direction
+ isEnableX: true,
+ // Boolean
+ // enables (disables) sliding in the vertical direction
+ isEnableY: true,
+ // value size (pixels) in the x dimension
+ _valueSizeX: 0.0,
+ // value size (pixels) in the y dimension
+ _valueSizeY: 0.0,
+ // left most edge of constraining container (pixels) in the X dimension
+ _minX: 0,
+ // top most edge of constraining container (pixels) in the Y dimension
+ _minY: 0,
+ // constrained slider size (pixels) in the x dimension
+ _constraintWidth: 0,
+ // constrained slider size (pixels) in the y dimension
+ _constraintHeight: 0,
+ // progress image right clip value (pixels) in the X dimension
+ _clipLeft: 0,
+ // progress image left clip value (pixels) in the X dimension
+ _clipRight: 0,
+ // progress image top clip value (pixels) in the Y dimension
+ _clipTop: 0,
+ // progress image bottom clip value (pixels) in the Y dimension
+ _clipBottom: 0,
+ // half the size of the slider handle (pixels) in the X dimension
+ _clipXdelta: 0,
+ // half the size of the slider handle (pixels) in the Y dimension
+ _clipYdelta: 0,
+ // Number
+ // initial value in the x dimension
+ initialValueX: 0,
+ // Number
+ // initial value in the y dimension
+ initialValueY: 0,
+ // Boolean
+ // values decrease in the X dimension
+ flipX: false,
+ // Boolean
+ // values decrease in the Y dimension
+ flipY: false,
+ // Boolean
+ // enables (disables) the user to click on the slider to set the position
+ clickSelect: true,
+ // Boolean
+ // disables (enables) the value to change while you are dragging, or just after drag finishes
+ activeDrag: false,
+
+ templateCssPath: dojo.uri.dojoUri ("src/widget/templates/Slider.css"),
+ templatePath: dojo.uri.dojoUri ("src/widget/templates/Slider.html"),
+
+ // This is set to true when a drag is started, so that it is not confused
+ // with a click
+ _isDragInProgress: false,
+
+ // default user style attributes
+ // String
+ // down arrow graphic URL
+ bottomButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_down_arrow.png"),
+ // String
+ // up arrow graphic URL
+ topButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_up_arrow.png"),
+ // String
+ // left arrow graphic URL
+ leftButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_left_arrow.png"),
+ // String
+ // right arrow graphic URL
+ rightButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_right_arrow.png"),
+ // String
+ // slider background graphic URL
+ backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),
+ // String
+ // slider background graphic URL to overlay the normal background to show progress
+ progressBackgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),
+ // String
+ // sizing style attributes for the background image
+ backgroundSize: "width:200px;height:200px;",
+ // String
+ // style attributes (other than sizing) for the background image
+ backgroundStyle: "",
+ // String
+ // style attributes for the left and right arrow images
+ buttonStyleX: "",
+ // String
+ // style attributes for the up and down arrow images
+ buttonStyleY: "",
+ // String
+ // style attributes for the moveable slider image
+ handleStyle: "",
+ // String
+ // moveable slider graphic URL
+ handleSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-button.png"),
+ // Boolean
+ // show (don't show) the arrow buttons
+ showButtons: true,
+ _eventCount: 0,
+ _typamaticTimer: null,
+ _typamaticFunction: null,
+ // Number
+ // number of milliseconds before a held key or button becomes typematic
+ defaultTimeout: 500,
+ // Number
+ // fraction of time used to change the typematic timer between events
+ // 1.0 means that each typematic event fires at defaultTimeout intervals
+ // < 1.0 means that each typematic event fires at an increasing faster rate
+ timeoutChangeRate: 0.90,
+ _currentTimeout: this.defaultTimeout,
+
+ // does the keyboard related stuff
+ _handleKeyEvents: function(/*Event*/ evt){
+ if(!evt.key){ return; }
+
+ if(!evt.ctrlKey && !evt.altKey){
+ switch(evt.key){
+ case evt.KEY_LEFT_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._leftButtonPressed(evt);
+ return;
+ case evt.KEY_RIGHT_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._rightButtonPressed(evt);
+ return;
+ case evt.KEY_DOWN_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._bottomButtonPressed(evt);
+ return;
+ case evt.KEY_UP_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._topButtonPressed(evt);
+ return;
+ }
+ }
+ this._eventCount++;
+
+ },
+
+ _pressButton: function(/*DomNode*/ buttonNode){
+ buttonNode.className = buttonNode.className.replace("Outset","Inset");
+ },
+
+ _releaseButton: function(/*DomNode*/ buttonNode){
+ buttonNode.className = buttonNode.className.replace("Inset","Outset");
+ },
+
+ _buttonPressed: function(/*Event*/ evt, /*DomNode*/ buttonNode){
+ this._setFocus();
+ if(typeof evt == "object"){
+ if(this._typamaticTimer != null){
+ if(this._typamaticNode == buttonNode){
+ return;
+ }
+ clearTimeout(this._typamaticTimer);
+ }
+ this._buttonReleased(null);
+ this._eventCount++;
+ this._typamaticTimer = null;
+ this._currentTimeout = this.defaultTimeout;
+ dojo.event.browser.stopEvent(evt);
+ }else if (evt != this._eventCount){
+ this._buttonReleased(null);
+ return false;
+ }
+ if (buttonNode == this.leftButtonNode && this.isEnableX){
+ this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") - this._valueSizeX);
+ }
+ else if (buttonNode == this.rightButtonNode && this.isEnableX){
+ this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") + this._valueSizeX);
+ }
+ else if (buttonNode == this.topButtonNode && this.isEnableY){
+ this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") - this._valueSizeY);
+ }
+ else if (buttonNode == this.bottomButtonNode && this.isEnableY){
+ this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") + this._valueSizeY);
+ }
+ else {
+ return false;
+ }
+ this._pressButton(buttonNode);
+ this.notifyListeners();
+ this._typamaticNode = buttonNode;
+ this._typamaticTimer = dojo.lang.setTimeout(this, "_buttonPressed", this._currentTimeout, this._eventCount, buttonNode);
+ this._currentTimeout = Math.round(this._currentTimeout * this.timeoutChangeRate);
+ return false;
+ },
+
+ _bottomButtonPressed: function(/*Event*/ evt){
+ return this._buttonPressed(evt,this.bottomButtonNode);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _bottomButtonDoubleClicked: function(/*Event*/ evt){
+ var rc = this._bottomButtonPressed(evt);
+ dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+ return rc;
+ },
+
+ _topButtonPressed: function(/*Event*/ evt){
+ return this._buttonPressed(evt,this.topButtonNode);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _topButtonDoubleClicked: function(/*Event*/ evt){
+ var rc = this._topButtonPressed(evt);
+ dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+ return rc;
+ },
+
+ _leftButtonPressed: function(/*Event*/ evt){
+ return this._buttonPressed(evt,this.leftButtonNode);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _leftButtonDoubleClicked: function(/*Event*/ evt){
+ var rc = this._leftButtonPressed(evt);
+ dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+ return rc;
+ },
+
+ _rightButtonPressed: function(/*Event*/ evt){
+ return this._buttonPressed(evt,this.rightButtonNode);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _rightButtonDoubleClicked: function(/*Event*/ evt){
+ var rc = this._rightButtonPressed(evt);
+ dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+ return rc;
+ },
+
+ _buttonReleased: function(/*Event*/ evt){
+ if(typeof evt == "object" && evt != null && typeof evt.keyCode != "undefined" && evt.keyCode != null){
+ var keyCode = evt.keyCode;
+
+ switch(keyCode){
+ case evt.KEY_LEFT_ARROW:
+ case evt.KEY_RIGHT_ARROW:
+ case evt.KEY_DOWN_ARROW:
+ case evt.KEY_UP_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ break;
+ }
+ }
+ this._releaseButton(this.topButtonNode);
+ this._releaseButton(this.bottomButtonNode);
+ this._releaseButton(this.leftButtonNode);
+ this._releaseButton(this.rightButtonNode);
+ this._eventCount++;
+ if(this._typamaticTimer != null){
+ clearTimeout(this._typamaticTimer);
+ }
+ this._typamaticTimer = null;
+ this._currentTimeout = this.defaultTimeout;
+ },
+
+ _mouseWheeled: function(/*Event*/ evt){
+ var scrollAmount = 0;
+ if(typeof evt.wheelDelta == 'number'){ // IE
+ scrollAmount = evt.wheelDelta;
+ }else if (typeof evt.detail == 'number'){ // Mozilla+Firefox
+ scrollAmount = -evt.detail;
+ }
+ if (this.isEnableY){
+ if(scrollAmount > 0){
+ this._topButtonPressed(evt);
+ this._buttonReleased(evt);
+ }else if (scrollAmount < 0){
+ this._bottomButtonPressed(evt);
+ this._buttonReleased(evt);
+ }
+ } else if (this.isEnableX){
+ if(scrollAmount > 0){
+ this._rightButtonPressed(evt);
+ this._buttonReleased(evt);
+ }else if (scrollAmount < 0){
+ this._leftButtonPressed(evt);
+ this._buttonReleased(evt);
+ }
+ }
+ },
+
+ _discardEvent: function(/*Event*/ evt){
+ dojo.event.browser.stopEvent(evt);
+ },
+
+ _setFocus: function(){
+ if (this.focusNode.focus){
+ this.focusNode.focus();
+ }
+ },
+
+ // This function is called when the template is loaded
+ fillInTemplate: function (/*Object*/ args, /*Object*/ frag)
+ {
+ var source = this.getFragNodeRef(frag);
+ dojo.html.copyStyle(this.domNode, source);
+ // the user's style for the widget might include border and padding
+ // unfortunately, border isn't supported for inline elements
+ // so I get to fake everyone out by setting the border and padding
+ // of the outer table cells
+ var padding = this.domNode.style.padding;
+ if (dojo.lang.isString(padding) && padding != "" && padding != "0px" && padding != "0px 0px 0px 0px"){
+ this.topBorderNode.style.padding =
+ this.bottomBorderNode.style.padding = padding;
+ this.topBorderNode.style.paddingBottom = "0px";
+ this.bottomBorderNode.style.paddingTop = "0px";
+ this.rightBorderNode.style.paddingRight = this.domNode.style.paddingRight;
+ this.leftBorderNode.style.paddingLeft= this.domNode.style.paddingLeft;
+ this.domNode.style.padding = "0px 0px 0px 0px";
+ }
+ var borderWidth = this.domNode.style.borderWidth;
+ if (dojo.lang.isString(borderWidth) && borderWidth != "" && borderWidth != "0px" && borderWidth != "0px 0px 0px 0px"){
+ this.topBorderNode.style.borderStyle =
+ this.rightBorderNode.style.borderStyle =
+ this.bottomBorderNode.style.borderStyle =
+ this.leftBorderNode.style.borderStyle =
+ this.domNode.style.borderStyle;
+ this.topBorderNode.style.borderColor =
+ this.rightBorderNode.style.borderColor =
+ this.bottomBorderNode.style.borderColor =
+ this.leftBorderNode.style.borderColor =
+ this.domNode.style.borderColor;
+ this.topBorderNode.style.borderWidth =
+ this.bottomBorderNode.style.borderWidth = borderWidth;
+ this.topBorderNode.style.borderBottomWidth = "0px";
+ this.bottomBorderNode.style.borderTopWidth = "0px";
+ this.rightBorderNode.style.borderRightWidth = this.domNode.style.borderRightWidth;
+ this.leftBorderNode.style.borderLeftWidth = this.domNode.style.borderLeftWidth;
+ this.domNode.style.borderWidth = "0px 0px 0px 0px";
+ }
+
+ // dojo.debug ("fillInTemplate - className = " + this.domNode.className);
+
+ // setup drag-n-drop for the sliderHandle
+ this._handleMove = new dojo.widget._SliderDragMoveSource (this.sliderHandleNode);
+ this._handleMove.setParent (this);
+
+ if (this.clickSelect){
+ dojo.event.connect (this.constrainingContainerNode, "onmousedown", this, "_onClick");
+ }
+
+ if (this.isEnableX){
+ this.setValueX (!isNaN(this.initialValueX) ? this.initialValueX : (!isNaN(this.minimumX) ? this.minimumX : 0));
+ }
+ if (!this.isEnableX || !this.showButtons){
+ this.rightButtonNode.style.width = "1px"; // allow the border to show
+ this.rightButtonNode.style.visibility = "hidden";
+ this.leftButtonNode.style.width = "1px"; // allow the border to show
+ this.leftButtonNode.style.visibility = "hidden";
+ }
+ if (this.isEnableY){
+ this.setValueY (!isNaN(this.initialValueY) ? this.initialValueY : (!isNaN(this.minimumY) ? this.minimumY : 0));
+ }
+ if (!this.isEnableY || !this.showButtons){
+ this.bottomButtonNode.style.width = "1px"; // allow the border to show
+ this.bottomButtonNode.style.visibility = "hidden";
+ this.topButtonNode.style.width = "1px"; // allow the border to show
+ this.topButtonNode.style.visibility = "hidden";
+ }
+ if(this.focusNode.addEventListener){
+ // dojo.event.connect() doesn't seem to work with DOMMouseScroll
+ this.focusNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "_mouseWheeled"), false); // Mozilla + Firefox + Netscape
+ }
+ },
+
+ // move the X value to the closest allowable value
+ _snapX: function(/*Number*/ x){
+ if (x < 0){ x = 0; }
+ else if (x > this._constraintWidth){ x = this._constraintWidth; }
+ else {
+ var selectedValue = Math.round (x / this._valueSizeX);
+ x = Math.round (selectedValue * this._valueSizeX);
+ }
+ this.sliderHandleNode.style.left = x + "px";
+ if (this.flipX){
+ this._clipLeft = x + this._clipXdelta;
+ } else {
+ this._clipRight = x + this._clipXdelta;
+ }
+ this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)";
+ },
+
+ // compute _valueSizeX & _constraintWidth & default snapValuesX
+ _calc_valueSizeX: function (){
+ var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode);
+ var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode);
+ if (isNaN(constrainingCtrBox.width) || isNaN(sliderHandleBox.width) || constrainingCtrBox.width <= 0 || sliderHandleBox.width <= 0){
+ return false;
+ }
+
+ this._constraintWidth = constrainingCtrBox.width
+ + dojo.html.getPadding(this.constrainingContainerNode).width
+ - sliderHandleBox.width;
+
+ if (this.flipX){
+ this._clipLeft = this._clipRight = constrainingCtrBox.width;
+ } else {
+ this._clipLeft = this._clipRight = 0;
+ }
+ this._clipXdelta = sliderHandleBox.width >> 1;
+ if (!this.isEnableY){
+ this._clipTop = 0;
+ this._clipBottom = constrainingCtrBox.height;
+ }
+
+ if (this._constraintWidth <= 0){ return false; }
+ if (this.snapValuesX == 0){
+ this.snapValuesX = this._constraintWidth + 1;
+ }
+
+ this._valueSizeX = this._constraintWidth / (this.snapValuesX - 1);
+ return true;
+ },
+
+ // summary
+ // move the handle horizontally to the specified value
+ setValueX: function (/*Number*/ value){
+ if (0.0 == this._valueSizeX){
+ if (this._calc_valueSizeX () == false){
+ dojo.lang.setTimeout(this, "setValueX", 100, value);
+ return;
+ }
+ }
+ if (isNaN(value)){
+ value = 0;
+ }
+ if (value > this.maximumX){
+ value = this.maximumX;
+ }
+ else if (value < this.minimumX){
+ value = this.minimumX;
+ }
+ var pixelPercent = (value-this.minimumX) / (this.maximumX-this.minimumX);
+ if (this.flipX){
+ pixelPercent = 1.0 - pixelPercent;
+ }
+ this._snapX (pixelPercent * this._constraintWidth);
+ this.notifyListeners();
+ },
+
+
+ // summary
+ // return the X value that the matches the position of the handle
+ getValueX: function (){
+ var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"left") / this._constraintWidth;
+ if (this.flipX){
+ pixelPercent = 1.0 - pixelPercent;
+ }
+ return Math.round (pixelPercent * (this.snapValuesX-1)) * ((this.maximumX-this.minimumX) / (this.snapValuesX-1)) + this.minimumX;
+ },
+
+ // move the Y value to the closest allowable value
+ _snapY: function (/*Number*/ y){
+ if (y < 0){ y = 0; }
+ else if (y > this._constraintHeight){ y = this._constraintHeight; }
+ else {
+ var selectedValue = Math.round (y / this._valueSizeY);
+ y = Math.round (selectedValue * this._valueSizeY);
+ }
+ this.sliderHandleNode.style.top = y + "px";
+ if (this.flipY){
+ this._clipTop = y + this._clipYdelta;
+ } else {
+ this._clipBottom = y + this._clipYdelta;
+ }
+ this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)";
+ },
+ // compute _valueSizeY & _constraintHeight & default snapValuesY
+ _calc_valueSizeY: function (){
+ var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode);
+ var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode);
+ if (isNaN(constrainingCtrBox.height) || isNaN(sliderHandleBox.height) || constrainingCtrBox.height <= 0 || sliderHandleBox.height <= 0){
+ return false;
+ }
+
+ this._constraintHeight = constrainingCtrBox.height
+ + dojo.html.getPadding(this.constrainingContainerNode).height
+ - sliderHandleBox.height;
+
+ if (this.flipY){
+ this._clipTop = this._clipBottom = constrainingCtrBox.height;
+ } else {
+ this._clipTop = this._clipBottom = 0;
+ }
+ this._clipYdelta = sliderHandleBox.height >> 1;
+ if (!this.isEnableX){
+ this._clipLeft = 0;
+ this._clipRight = constrainingCtrBox.width;
+ }
+
+ if (this._constraintHeight <= 0){ return false; }
+ if (this.snapValuesY == 0){
+ this.snapValuesY = this._constraintHeight + 1;
+ }
+
+ this._valueSizeY = this._constraintHeight / (this.snapValuesY - 1);
+ return true;
+ },
+
+ // summary
+ // move the handle vertically to the specified value
+ setValueY: function (/*Number*/ value){
+ if (0.0 == this._valueSizeY){
+ if (this._calc_valueSizeY () == false){
+ dojo.lang.setTimeout(this, "setValueY", 100, value);
+ return;
+ }
+ }
+ if (isNaN(value)){
+ value = 0;
+ }
+ if (value > this.maximumY){
+ value = this.maximumY;
+ }
+ else if (value < this.minimumY){
+ value = this.minimumY;
+ }
+ var pixelPercent = (value-this.minimumY) / (this.maximumY-this.minimumY);
+ if (this.flipY){
+ pixelPercent = 1.0 - pixelPercent;
+ }
+ this._snapY (pixelPercent * this._constraintHeight);
+ this.notifyListeners();
+ },
+
+ // summary
+ // return the Y value that the matches the position of the handle
+ getValueY: function (){
+ var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"top") / this._constraintHeight;
+ if (this.flipY){
+ pixelPercent = 1.0 - pixelPercent;
+ }
+ return Math.round (pixelPercent * (this.snapValuesY-1)) * ((this.maximumY-this.minimumY) / (this.snapValuesY-1)) + this.minimumY;
+ },
+
+ // set the position of the handle
+ _onClick: function(/*Event*/ evt){
+ if (this._isDragInProgress){
+ return;
+ }
+
+ var parent = dojo.html.getAbsolutePosition(this.constrainingContainerNode, true, dojo.html.boxSizing.MARGIN_BOX);
+ var content = dojo.html.getContentBox(this._handleMove.domNode);
+ if (this.isEnableX){
+ var x = evt.pageX - parent.x - (content.width >> 1);
+ this._snapX(x);
+ }
+ if (this.isEnableY){
+ var y = evt.pageY - parent.y - (content.height >> 1);
+ this._snapY(y);
+ }
+ this.notifyListeners();
+ },
+
+ // summary
+ // method to invoke user's onValueChanged method
+ notifyListeners: function(){
+ this.onValueChanged(this.getValueX(), this.getValueY());
+ },
+
+ // summary
+ // empty method to be overridden by user
+ onValueChanged: function(/*Number*/ x, /*Number*/ y){
+ }
+ }
+);
+
+
+
+// summary
+// the horizontal slider widget subclass
+dojo.widget.defineWidget (
+ "dojo.widget.SliderHorizontal",
+ dojo.widget.Slider,
+ {
+ widgetType: "SliderHorizontal",
+
+ isEnableX: true,
+ isEnableY: false,
+ // Number
+ // sets initialValueX
+ initialValue: "",
+ // Number
+ // sets snapValuesX
+ snapValues: "",
+ // Number
+ // sets minimumX
+ minimum: "",
+ // Number
+ // sets maximumX
+ maximum: "",
+ // String
+ // sets buttonStyleX
+ buttonStyle: "",
+ backgroundSize: "height:10px;width:200px;",
+ backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg.gif"),
+ // Boolean
+ // sets flipX
+ flip: false,
+
+ postMixInProperties: function(){
+ dojo.widget.SliderHorizontal.superclass.postMixInProperties.apply(this, arguments);
+ if (!isNaN(parseFloat(this.initialValue))){
+ this.initialValueX = parseFloat(this.initialValue);
+ }
+ if (!isNaN(parseFloat(this.minimum))){
+ this.minimumX = parseFloat(this.minimum);
+ }
+ if (!isNaN(parseFloat(this.maximum))){
+ this.maximumX = parseFloat(this.maximum);
+ }
+ if (!isNaN(parseInt(this.snapValues))){
+ this.snapValuesX = parseInt(this.snapValues);
+ }
+ if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != ""){
+ this.buttonStyleX = this.buttonStyle;
+ }
+ if (dojo.lang.isBoolean(this.flip)){
+ this.flipX = this.flip;
+ }
+ },
+
+ notifyListeners: function(){
+ this.onValueChanged(this.getValueX());
+ },
+
+ // summary
+ // wrapper for getValueX()
+ getValue: function (){
+ return this.getValueX ();
+ },
+
+ // summary
+ // wrapper for setValueX()
+ setValue: function (/*Number*/ value){
+ this.setValueX (value);
+ },
+
+ onValueChanged: function(/*Number*/ value){
+ }
+ }
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+// summary
+// the vertical slider widget subclass
+dojo.widget.defineWidget (
+ "dojo.widget.SliderVertical",
+ dojo.widget.Slider,
+ {
+ widgetType: "SliderVertical",
+
+ isEnableX: false,
+ isEnableY: true,
+ // Number
+ // sets initialValueY
+ initialValue: "",
+ // Number
+ // sets snapValuesY
+ snapValues: "",
+ // Number
+ // sets minimumY
+ minimum: "",
+ // Number
+ // sets maximumY
+ maximum: "",
+ // String
+ // sets buttonStyleY
+ buttonStyle: "",
+ backgroundSize: "width:10px;height:200px;",
+ backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg-vert.gif"),
+ // Boolean
+ // sets flipY
+ flip: false,
+
+ postMixInProperties: function(){
+ dojo.widget.SliderVertical.superclass.postMixInProperties.apply(this, arguments);
+ if (!isNaN(parseFloat(this.initialValue))){
+ this.initialValueY = parseFloat(this.initialValue);
+ }
+ if (!isNaN(parseFloat(this.minimum))){
+ this.minimumY = parseFloat(this.minimum);
+ }
+ if (!isNaN(parseFloat(this.maximum))){
+ this.maximumY = parseFloat(this.maximum);
+ }
+ if (!isNaN(parseInt(this.snapValues))){
+ this.snapValuesY = parseInt(this.snapValues);
+ }
+ if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != ""){
+ this.buttonStyleY = this.buttonStyle;
+ }
+ if (dojo.lang.isBoolean(this.flip)){
+ this.flipY = this.flip;
+ }
+ },
+
+ notifyListeners: function(){
+ this.onValueChanged(this.getValueY());
+ },
+
+ // summary
+ // wrapper for getValueY()
+ getValue: function (){
+ return this.getValueY ();
+ },
+
+ // summary
+ // wrapper for setValueY()
+ setValue: function (/*Number*/ value){
+ this.setValueY (value);
+ },
+
+ onValueChanged: function(/*Number*/ value){
+ }
+ }
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveSource class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+ "dojo.widget._SliderDragMoveSource",
+ dojo.dnd.HtmlDragMoveSource,
+{
+ slider: null,
+
+ /** Setup the handle for drag
+ * Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */
+ onDragStart: function(/*Event*/ evt){
+ this.slider._isDragInProgress = true;
+ var pos = dojo.html.getAbsolutePosition(this.slider.constrainingContainerNode, true, dojo.html.boxSizing.MARGIN_BOX);
+ if (this.slider.isEnableX){
+ this.slider._minX = pos.x;
+ }
+ if (this.slider.isEnableY){
+ this.slider._minY = pos.y;
+ }
+
+ var dragObj = this.createDragMoveObject ();
+
+ this.slider.notifyListeners();
+ return dragObj;
+ },
+
+ onDragEnd: function(/*Event*/ evt){
+ this.slider._isDragInProgress = false;
+ this.slider.notifyListeners();
+ },
+
+ createDragMoveObject: function (){
+ //dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider);
+ var dragObj = new dojo.widget._SliderDragMoveObject (this.dragObject, this.type);
+ dragObj.slider = this.slider;
+
+ // this code copied from dojo.dnd.HtmlDragSource#onDragStart
+ if (this.dragClass){
+ dragObj.dragClass = this.dragClass;
+ }
+
+ return dragObj;
+ },
+
+
+ setParent: function (/*Widget*/ slider){
+ this.slider = slider;
+ }
+});
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveObject class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+ "dojo.widget._SliderDragMoveObject",
+ dojo.dnd.HtmlDragMoveObject,
+{
+ // reference to dojo.widget.Slider
+ slider: null,
+
+ /** Moves the node to follow the mouse.
+ * Extends functon HtmlDragObject by adding functionality to snap handle
+ * to a discrete value */
+ onDragMove: function(/*Event*/ evt){
+ this.updateDragOffset ();
+
+ if (this.slider.isEnableX){
+ var x = this.dragOffset.x + evt.pageX - this.slider._minX;
+ this.slider._snapX(x);
+ }
+
+ if (this.slider.isEnableY){
+ var y = this.dragOffset.y + evt.pageY - this.slider._minY;
+ this.slider._snapY(y);
+ }
+ if(this.slider.activeDrag){
+ this.slider.notifyListeners();
+ }
+ }
+});
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Slider.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SortableTable.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SortableTable.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SortableTable.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SortableTable.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,605 @@
+dojo.provide("dojo.widget.SortableTable");
+
+dojo.deprecated("SortableTable will be removed in favor of FilteringTable.", "0.5");
+
+dojo.require("dojo.lang.common");
+dojo.require("dojo.date.format");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.selection");
+dojo.require("dojo.html.util");
+dojo.require("dojo.html.style");
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget(
+ "dojo.widget.SortableTable",
+ dojo.widget.HtmlWidget,
+ function(){
+ this.data=[];
+ this.selected=[]; // always an array to handle multiple selections.
+ this.columns=[];
+ },
+ {
+ // custom properties
+ enableMultipleSelect: false,
+ maximumNumberOfSelections: 0, // 0 for unlimited, is the default.
+ enableAlternateRows: false,
+ minRows: 0, // 0 means ignore.
+ defaultDateFormat: "%D",
+ sortIndex: 0, // index of the column sorted on, first is the default.
+ sortDirection: 0, // 0==asc, 1==desc
+ valueField: "Id", // if a JSON structure is parsed and there is a field of this name,
+ // a value attribute will be added to the row (tr value="{Id}")
+
+ headClass: "",
+ tbodyClass: "",
+ headerClass: "",
+ headerSortUpClass: "selected",
+ headerSortDownClass: "selected",
+ rowClass: "",
+ rowAlternateClass: "alt",
+ rowSelectedClass: "selected",
+ columnSelected: "sorted-column",
+
+ isContainer: false,
+ templatePath:null,
+ templateCssPath:null,
+
+ getTypeFromString:function(/* string */ s){
+ // summary
+ // Find the constructor that matches param s by searching through the entire object tree.
+ var parts=s.split("."),i=0,obj=dj_global;
+ do{obj=obj[parts[i++]];}while(i<parts.length&&obj);
+ return(obj!=dj_global)?obj:null; // function
+ },
+ compare:function(/* object */ o1, /* object */ o2){
+ // summary
+ // Compare two objects using a shallow property compare
+ for(var p in o1){
+ if(!(p in o2)) return false; // boolean
+ if(o1[p].valueOf()!=o2[p].valueOf()) return false; // boolean
+ }
+ return true; // boolean
+ },
+ isSelected:function(/* object */ o){
+ // summary
+ // checked to see if the passed object is in the current selection.
+ for(var i=0;i<this.selected.length;i++){
+ if(this.compare(this.selected[i],o)){
+ return true; // boolean
+ }
+ }
+ return false; // boolean
+ },
+ removeFromSelected:function(/* object */ o){
+ // summary
+ // remove the passed object from the current selection.
+ var idx=-1;
+ for(var i=0;i<this.selected.length;i++){
+ if(this.compare(this.selected[i],o)){
+ idx=i;
+ break;
+ }
+ }
+ if(idx>=0){
+ this.selected.splice(idx,1);
+ }
+ },
+ getSelection:function(){
+ // summary
+ // return the array of currently selected objects (JSON format)
+ return this.selected; // array
+ },
+ getValue:function(){
+ // summary
+ // return a comma-delimited list of selected valueFields.
+ var a=[];
+ for(var i=0;i<this.selected.length;i++){
+ if (this.selected[i][this.valueField]){
+ a.push(this.selected[i][this.valueField]);
+ }
+ }
+ return a.join(); // string
+ },
+ reset:function(){
+ // summary
+ // completely resets the internal representations.
+ this.columns=[];
+ this.data=[];
+ this.resetSelections(this.domNode.getElementsByTagName("tbody")[0]);
+ },
+ resetSelections:function(/* HTMLTableBodyElement */ body){
+ this.selected=[];
+ var idx=0;
+ var rows=body.getElementsByTagName("tr");
+ for(var i=0; i<rows.length; i++){
+ if(rows[i].parentNode==body){
+ rows[i].removeAttribute("selected");
+ if(this.enableAlternateRows&&idx%2==1){
+ rows[i].className=this.rowAlternateClass;
+ }else{
+ rows[i].className="";
+ }
+ idx++;
+ }
+ }
+ },
+
+ getObjectFromRow:function(/* HTMLTableRowElement */ row){
+ // summary
+ // creates a JSON object based on the passed row
+ var cells=row.getElementsByTagName("td");
+ var o={};
+ for(var i=0; i<this.columns.length;i++){
+ if(this.columns[i].sortType=="__markup__"){
+ // FIXME: should we parse this instead? Because if the user may not get back the markup they put in...
+ o[this.columns[i].getField()]=cells[i].innerHTML;
+ }else{
+ var text=dojo.html.renderedTextContent(cells[i]);
+ var val=text;
+ if (this.columns[i].getType() != String){
+ var val=new (this.columns[i].getType())(text);
+ }
+ o[this.columns[i].getField()]=val;
+ }
+ }
+ if(dojo.html.hasAttribute(row,"value")){
+ o[this.valueField]=dojo.html.getAttribute(row,"value");
+ }
+ return o; // object
+ },
+ setSelectionByRow:function(/* HTMLTableElementRow */ row){
+ // summary
+ // create the selection object based on the passed row, makes sure it's unique.
+ // note that you need to call render manually (because of multi-select operations)
+ var o=this.getObjectFromRow(row);
+ var b=false;
+ for(var i=0;i<this.selected.length;i++){
+ if(this.compare(this.selected[i], o)){
+ b=true;
+ break;
+ }
+ }
+ if(!b){
+ this.selected.push(o);
+ }
+ },
+
+ parseColumns:function(/* HTMLTableHeadElement */ node){
+ // summary
+ // parses the passed element to create column objects
+ this.reset();
+ var row=node.getElementsByTagName("tr")[0];
+ var cells=row.getElementsByTagName("td");
+ if (cells.length==0) cells=row.getElementsByTagName("th");
+ for(var i=0; i<cells.length; i++){
+ var o={
+ field:null,
+ format:null,
+ noSort:false,
+ sortType:"String",
+ dataType:String,
+ sortFunction:null,
+ label:null,
+ align:"left",
+ valign:"middle",
+ getField:function(){ return this.field||this.label; },
+ getType:function(){ return this.dataType; }
+ };
+ // presentation attributes
+ if(dojo.html.hasAttribute(cells[i], "align")){
+ o.align=dojo.html.getAttribute(cells[i],"align");
+ }
+ if(dojo.html.hasAttribute(cells[i], "valign")){
+ o.valign=dojo.html.getAttribute(cells[i],"valign");
+ }
+
+ // sorting features.
+ if(dojo.html.hasAttribute(cells[i], "nosort")){
+ o.noSort=dojo.html.getAttribute(cells[i],"nosort")=="true";
+ }
+ if(dojo.html.hasAttribute(cells[i], "sortusing")){
+ var trans=dojo.html.getAttribute(cells[i],"sortusing");
+ var f=this.getTypeFromString(trans);
+ if (f!=null && f!=window && typeof(f)=="function")
+ o.sortFunction=f;
+ }
+
+ if(dojo.html.hasAttribute(cells[i], "field")){
+ o.field=dojo.html.getAttribute(cells[i],"field");
+ }
+ if(dojo.html.hasAttribute(cells[i], "format")){
+ o.format=dojo.html.getAttribute(cells[i],"format");
+ }
+ if(dojo.html.hasAttribute(cells[i], "dataType")){
+ var sortType=dojo.html.getAttribute(cells[i],"dataType");
+ if(sortType.toLowerCase()=="html"||sortType.toLowerCase()=="markup"){
+ o.sortType="__markup__"; // always convert to "__markup__"
+ o.noSort=true;
+ }else{
+ var type=this.getTypeFromString(sortType);
+ if(type){
+ o.sortType=sortType;
+ o.dataType=type;
+ }
+ }
+ }
+ o.label=dojo.html.renderedTextContent(cells[i]);
+ this.columns.push(o);
+
+ // check to see if there's a default sort, and set the properties necessary
+ if(dojo.html.hasAttribute(cells[i], "sort")){
+ this.sortIndex=i;
+ var dir=dojo.html.getAttribute(cells[i], "sort");
+ if(!isNaN(parseInt(dir))){
+ dir=parseInt(dir);
+ this.sortDirection=(dir!=0)?1:0;
+ }else{
+ this.sortDirection=(dir.toLowerCase()=="desc")?1:0;
+ }
+ }
+ }
+ },
+
+ parseData:function(/* array */ data){
+ // summary
+ // Parse the passed JSON data structure, and cast based on columns.
+ this.data=[];
+ this.selected=[];
+ for(var i=0; i<data.length; i++){
+ var o={}; // new data object.
+ for(var j=0; j<this.columns.length; j++){
+ var field=this.columns[j].getField();
+ if(this.columns[j].sortType=="__markup__"){
+ o[field]=String(data[i][field]);
+ }else{
+ var type=this.columns[j].getType();
+ var val=data[i][field];
+ var t=this.columns[j].sortType.toLowerCase();
+ if(type == String) {
+ o[field]=val;
+ } else {
+ if(val!=null){
+ o[field]=new type(val);
+ }else{
+ o[field]=new type(); // let it use the default.
+ }
+ }
+ }
+ }
+ // check for the valueField if not already parsed.
+ if(data[i][this.valueField]&&!o[this.valueField]){
+ o[this.valueField]=data[i][this.valueField];
+ }
+ this.data.push(o);
+ }
+ },
+
+ parseDataFromTable:function(/* HTMLTableBodyElement */ tbody){
+ // summary
+ // parses the data in the tbody of a table to create a set of objects.
+ // Will add objects to this.selected if an attribute 'selected="true"' is present on the row.
+ this.data=[];
+ this.selected=[];
+ var rows=tbody.getElementsByTagName("tr");
+ for(var i=0; i<rows.length; i++){
+ if(dojo.html.getAttribute(rows[i],"ignoreIfParsed")=="true"){
+ continue;
+ }
+ var o={}; // new data object.
+ var cells=rows[i].getElementsByTagName("td");
+ for(var j=0; j<this.columns.length; j++){
+ var field=this.columns[j].getField();
+ if(this.columns[j].sortType=="__markup__"){
+ // FIXME: parse this?
+ o[field]=cells[j].innerHTML;
+ }else{
+ var type=this.columns[j].getType();
+ var val=dojo.html.renderedTextContent(cells[j]); // should be the same index as the column.
+ if(type == String){
+ o[field]=val;
+ } else {
+ if (val!=null){
+ o[field]=new type(val);
+ } else {
+ o[field]=new type(); // let it use the default.
+ }
+ }
+ }
+ }
+ if(dojo.html.hasAttribute(rows[i],"value")&&!o[this.valueField]){
+ o[this.valueField]=dojo.html.getAttribute(rows[i],"value");
+ }
+ // FIXME: add code to preserve row attributes in __metadata__ field?
+ this.data.push(o);
+
+ // add it to the selections if selected="true" is present.
+ if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+ this.selected.push(o);
+ }
+ }
+ },
+
+ showSelections:function(){
+ var body=this.domNode.getElementsByTagName("tbody")[0];
+ var rows=body.getElementsByTagName("tr");
+ var idx=0;
+ for(var i=0; i<rows.length; i++){
+ if(rows[i].parentNode==body){
+ if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+ rows[i].className=this.rowSelectedClass;
+ } else {
+ if(this.enableAlternateRows&&idx%2==1){
+ rows[i].className=this.rowAlternateClass;
+ }else{
+ rows[i].className="";
+ }
+ }
+ idx++;
+ }
+ }
+ },
+ render:function(bDontPreserve){
+ // summary
+ // renders the table to the browser
+ var data=[];
+ var body=this.domNode.getElementsByTagName("tbody")[0];
+
+ if(!bDontPreserve){
+ // rebuild data and selection
+ this.parseDataFromTable(body);
+ }
+
+ // clone this.data for sorting purposes.
+ for(var i=0; i<this.data.length; i++){
+ data.push(this.data[i]);
+ }
+
+ var col=this.columns[this.sortIndex];
+ if(!col.noSort){
+ var field=col.getField();
+ if(col.sortFunction){
+ var sort=col.sortFunction;
+ }else{
+ var sort=function(a,b){
+ if (a[field]>b[field]) return 1;
+ if (a[field]<b[field]) return -1;
+ return 0;
+ }
+ }
+ data.sort(sort);
+ if(this.sortDirection!=0) data.reverse();
+ }
+
+ // build the table and pop it in.
+ while(body.childNodes.length>0) body.removeChild(body.childNodes[0]);
+ for(var i=0; i<data.length;i++){
+ var row=document.createElement("tr");
+ dojo.html.disableSelection(row);
+ if (data[i][this.valueField]){
+ row.setAttribute("value",data[i][this.valueField]);
+ }
+ if(this.isSelected(data[i])){
+ row.className=this.rowSelectedClass;
+ row.setAttribute("selected","true");
+ } else {
+ if(this.enableAlternateRows&&i%2==1){
+ row.className=this.rowAlternateClass;
+ }
+ }
+ for(var j=0;j<this.columns.length;j++){
+ var cell=document.createElement("td");
+ cell.setAttribute("align", this.columns[j].align);
+ cell.setAttribute("valign", this.columns[j].valign);
+ dojo.html.disableSelection(cell);
+ if(this.sortIndex==j){
+ cell.className=this.columnSelected;
+ }
+ if(this.columns[j].sortType=="__markup__"){
+ cell.innerHTML=data[i][this.columns[j].getField()];
+ for(var k=0; k<cell.childNodes.length; k++){
+ var node=cell.childNodes[k];
+ if(node&&node.nodeType==dojo.html.ELEMENT_NODE){
+ dojo.html.disableSelection(node);
+ }
+ }
+ }else{
+ if(this.columns[j].getType()==Date){
+ var format=this.defaultDateFormat;
+ if(this.columns[j].format) format=this.columns[j].format;
+ cell.appendChild(document.createTextNode(dojo.date.strftime(data[i][this.columns[j].getField()], format)));
+ }else{
+ cell.appendChild(document.createTextNode(data[i][this.columns[j].getField()]));
+ }
+ }
+ row.appendChild(cell);
+ }
+ body.appendChild(row);
+ dojo.event.connect(row, "onclick", this, "onUISelect");
+ }
+
+ // if minRows exist.
+ var minRows=parseInt(this.minRows);
+ if (!isNaN(minRows) && minRows>0 && data.length<minRows){
+ var mod=0;
+ if(data.length%2==0) mod=1;
+ var nRows=minRows-data.length;
+ for(var i=0; i<nRows; i++){
+ var row=document.createElement("tr");
+ row.setAttribute("ignoreIfParsed","true");
+ if(this.enableAlternateRows&&i%2==mod){
+ row.className=this.rowAlternateClass;
+ }
+ for(var j=0;j<this.columns.length;j++){
+ var cell=document.createElement("td");
+ cell.appendChild(document.createTextNode("\u00A0"));
+ row.appendChild(cell);
+ }
+ body.appendChild(row);
+ }
+ }
+ },
+
+ // the following the user can override.
+ onSelect:function(/* DomEvent */ e){
+ // summary
+ // empty function for the user to attach code to, fired by onUISelect
+ },
+ onUISelect:function(/* DomEvent */ e){
+ // summary
+ // fired when a user selects a row
+ var row=dojo.html.getParentByType(e.target,"tr");
+ var body=dojo.html.getParentByType(row,"tbody");
+ if(this.enableMultipleSelect){
+ if(e.metaKey||e.ctrlKey){
+ if(this.isSelected(this.getObjectFromRow(row))){
+ this.removeFromSelected(this.getObjectFromRow(row));
+ row.removeAttribute("selected");
+ }else{
+ // push onto the selection stack.
+ this.setSelectionByRow(row);
+ row.setAttribute("selected","true");
+ }
+ }else if(e.shiftKey){
+ // the tricky one. We need to figure out the *last* selected row above,
+ // and select all the rows in between.
+ var startRow;
+ var rows=body.getElementsByTagName("tr");
+ // if there's a selection above, we go with that first.
+ for(var i=0;i<rows.length;i++){
+ if(rows[i].parentNode==body){
+ if(rows[i]==row) break;
+ if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+ startRow=rows[i];
+ }
+ }
+ }
+ // if there isn't a selection above, we continue with a selection below.
+ if(!startRow){
+ startRow=row;
+ for(;i<rows.length;i++){
+ if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+ row=rows[i];
+ break;
+ }
+ }
+ }
+ this.resetSelections(body);
+ if(startRow==row){
+ // this is the only selection
+ row.setAttribute("selected","true");
+ this.setSelectionByRow(row);
+ }else{
+ var doSelect=false;
+ for(var i=0; i<rows.length; i++){
+ if(rows[i].parentNode==body){
+ rows[i].removeAttribute("selected");
+ if(rows[i]==startRow){
+ doSelect=true;
+ }
+ if(doSelect){
+ this.setSelectionByRow(rows[i]);
+ rows[i].setAttribute("selected","true");
+ }
+ if(rows[i]==row){
+ doSelect=false;
+ }
+ }
+ }
+ }
+ }else{
+ // reset the selection
+ this.resetSelections(body);
+ row.setAttribute("selected","true");
+ this.setSelectionByRow(row);
+ }
+ }else{
+ // reset the data selection and go.
+ this.resetSelections(body);
+ row.setAttribute("selected","true");
+ this.setSelectionByRow(row);
+ }
+ this.showSelections();
+ this.onSelect(e);
+ e.stopPropagation();
+ e.preventDefault();
+ },
+ onHeaderClick:function(/* DomEvent */ e){
+ // summary
+ // Main handler function for each header column click.
+ var oldIndex=this.sortIndex;
+ var oldDirection=this.sortDirection;
+ var source=e.target;
+ var row=dojo.html.getParentByType(source,"tr");
+ var cellTag="td";
+ if(row.getElementsByTagName(cellTag).length==0) cellTag="th";
+
+ var headers=row.getElementsByTagName(cellTag);
+ var header=dojo.html.getParentByType(source,cellTag);
+
+ for(var i=0; i<headers.length; i++){
+ if(headers[i]==header){
+ if(i!=oldIndex){
+ // new col.
+ this.sortIndex=i;
+ this.sortDirection=0;
+ headers[i].className=this.headerSortDownClass
+ }else{
+ this.sortDirection=(oldDirection==0)?1:0;
+ if(this.sortDirection==0){
+ headers[i].className=this.headerSortDownClass;
+ }else{
+ headers[i].className=this.headerSortUpClass;
+ }
+ }
+ }else{
+ // reset the header class.
+ headers[i].className=this.headerClass;
+ }
+ }
+ this.render();
+ },
+
+ postCreate:function(){
+ // summary
+ // overridden from HtmlWidget, initializes and renders the widget.
+ var thead=this.domNode.getElementsByTagName("thead")[0];
+ if(this.headClass.length>0){
+ thead.className=this.headClass;
+ }
+
+ // disable selections
+ dojo.html.disableSelection(this.domNode);
+
+ // parse the columns.
+ this.parseColumns(thead);
+
+ // attach header handlers.
+ var header="td";
+ if(thead.getElementsByTagName(header).length==0) header="th";
+ var headers=thead.getElementsByTagName(header);
+ for(var i=0; i<headers.length; i++){
+ if(!this.columns[i].noSort){
+ dojo.event.connect(headers[i], "onclick", this, "onHeaderClick");
+ }
+ if(this.sortIndex==i){
+ if(this.sortDirection==0){
+ headers[i].className=this.headerSortDownClass;
+ }else{
+ headers[i].className=this.headerSortUpClass;
+ }
+ }
+ }
+
+ // parse the tbody element and re-render it.
+ var tbody=this.domNode.getElementsByTagName("tbody")[0];
+ if (this.tbodyClass.length>0) {
+ tbody.className=this.tbodyClass;
+ }
+
+ this.parseDataFromTable(tbody);
+ this.render(true);
+ }
+ }
+);
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SortableTable.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Spinner.js
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Spinner.js?view=auto&rev=473755
==============================================================================
--- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Spinner.js (added)
+++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Spinner.js Sat Nov 11 08:44:22 2006
@@ -0,0 +1,612 @@
+dojo.provide("dojo.widget.Spinner");
+
+dojo.require("dojo.io.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.string");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.IntegerTextbox");
+dojo.require("dojo.widget.RealNumberTextbox");
+dojo.require("dojo.widget.DateTextbox");
+
+dojo.require("dojo.experimental");
+
+// summary: Mixin for validation widgets with a spinner
+// description: This class basically (conceptually) extends dojo.widget.ValidationTextbox.
+// It modifies the template to have up/down arrows, and provides related handling code.
+dojo.declare(
+ "dojo.widget.Spinner",
+ null,
+ {
+ _typamaticTimer: null,
+ _typamaticFunction: null,
+ _currentTimeout: this.defaultTimeout,
+ _eventCount: 0,
+ // Number
+ // number of milliseconds before a held key or button becomes typematic
+ defaultTimeout: 500,
+ // Number
+ // fraction of time used to change the typematic timer between events
+ // 1.0 means that each typematic event fires at defaultTimeout intervals
+ // < 1.0 means that each typematic event fires at an increasing faster rate
+ timeoutChangeRate: 0.90,
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/Spinner.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/Spinner.css"),
+ // String
+ // up arrow graphic URL
+ incrementSrc: dojo.uri.dojoUri("src/widget/templates/images/spinnerIncrement.gif"),
+ // String
+ // down arrow graphic URL
+ decrementSrc: dojo.uri.dojoUri("src/widget/templates/images/spinnerDecrement.gif"),
+
+ // does the keyboard related stuff
+ _handleKeyEvents: function(/*Event*/ evt){
+ if(!evt.key){ return; }
+
+ if(!evt.ctrlKey && !evt.altKey){
+ switch(evt.key){
+ case evt.KEY_DOWN_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._downArrowPressed(evt);
+ return;
+ case evt.KEY_UP_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ this._upArrowPressed(evt);
+ return;
+ }
+ }
+ this._eventCount++;
+ },
+
+ _onSpinnerKeyUp: function(/*Event*/ evt){
+ this._arrowReleased(evt);
+ this.onkeyup(evt);
+ },
+
+ // reset button size; this function is called when the input area has changed size
+ _resize: function(){
+ var inputSize = dojo.html.getBorderBox(this.textbox);
+ this.buttonSize = { width: inputSize.height / 2, height: inputSize.height / 2 };
+ if(this.upArrowNode){
+ dojo.html.setMarginBox(this.upArrowNode, this.buttonSize);
+ dojo.html.setMarginBox(this.downArrowNode, this.buttonSize);
+ }
+ },
+
+ _pressButton: function(/*DomNode*/ node){
+ node.style.borderWidth = "1px 0px 0px 1px";
+ node.style.borderStyle = "inset";
+ },
+
+ _releaseButton: function(/*DomNode*/ node){
+ node.style.borderWidth = "0px 1px 1px 0px";
+ node.style.borderStyle = "outset";
+ },
+
+ _arrowPressed: function(/*Event*/ evt, /*Number*/ direction){
+ var nodePressed = (direction == -1) ? this.downArrowNode : this.upArrowNode;
+ var nodeReleased = (direction == +1) ? this.downArrowNode : this.upArrowNode;
+ if(typeof evt != "number"){
+ if(this._typamaticTimer != null){
+ if(this._typamaticNode == nodePressed){
+ return;
+ }
+ dojo.lang.clearTimeout(this._typamaticTimer);
+ }
+ this._releaseButton(nodeReleased);
+ this._eventCount++;
+ this._typamaticTimer = null;
+ this._currentTimeout = this.defaultTimeout;
+
+ }else if (evt != this._eventCount){
+ this._releaseButton(nodePressed);
+ return;
+ }
+ this._pressButton(nodePressed);
+ this._setCursorX(this.adjustValue(direction,this._getCursorX()));
+ this._typamaticNode = nodePressed;
+ this._typamaticTimer = dojo.lang.setTimeout(this, "_arrowPressed", this._currentTimeout, this._eventCount, direction);
+ this._currentTimeout = Math.round(this._currentTimeout * this.timeoutChangeRate);
+ },
+
+ _downArrowPressed: function(/*Event*/ evt){
+ return this._arrowPressed(evt,-1);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _downArrowDoubleClicked: function(/*Event*/ evt){
+ var rc = this._downArrowPressed(evt);
+ dojo.lang.setTimeout(this, "_arrowReleased", 50, null);
+ return rc;
+ },
+
+ _upArrowPressed: function(/*Event*/ evt){
+ return this._arrowPressed(evt,+1);
+ },
+
+ // IE sends these events when rapid clicking, mimic an extra single click
+ _upArrowDoubleClicked: function(/*Event*/ evt){
+ var rc = this._upArrowPressed(evt);
+ dojo.lang.setTimeout(this, "_arrowReleased", 50, null);
+ return rc;
+ },
+
+ _arrowReleased: function(/*Event*/ evt){
+ this.textbox.focus();
+ if(evt != null && typeof evt == "object" && evt.keyCode && evt.keyCode != null){
+ var keyCode = evt.keyCode;
+ var k = dojo.event.browser.keys;
+
+ switch(keyCode){
+ case k.KEY_DOWN_ARROW:
+ case k.KEY_UP_ARROW:
+ dojo.event.browser.stopEvent(evt);
+ break;
+ }
+ }
+ this._releaseButton(this.upArrowNode);
+ this._releaseButton(this.downArrowNode);
+ this._eventCount++;
+ if(this._typamaticTimer != null){
+ dojo.lang.clearTimeout(this._typamaticTimer);
+ }
+ this._typamaticTimer = null;
+ this._currentTimeout = this.defaultTimeout;
+ },
+
+ _mouseWheeled: function(/*Event*/ evt){
+ var scrollAmount = 0;
+ if(typeof evt.wheelDelta == 'number'){ // IE
+ scrollAmount = evt.wheelDelta;
+ }else if (typeof evt.detail == 'number'){ // Mozilla+Firefox
+ scrollAmount = -evt.detail;
+ }
+ if(scrollAmount > 0){
+ this._upArrowPressed(evt);
+ this._arrowReleased(evt);
+ }else if (scrollAmount < 0){
+ this._downArrowPressed(evt);
+ this._arrowReleased(evt);
+ }
+ },
+
+ _discardEvent: function(/*Event*/ evt){
+ dojo.event.browser.stopEvent(evt);
+ },
+
+ _getCursorX: function(){
+ var x = -1;
+ try{
+ this.textbox.focus();
+ if (typeof this.textbox.selectionEnd == "number"){
+ x = this.textbox.selectionEnd;
+ }else if (document.selection && document.selection.createRange){
+ var range = document.selection.createRange().duplicate();
+ if(range.parentElement() == this.textbox){
+ range.moveStart('textedit', -1);
+ x = range.text.length;
+ }
+ }
+ }catch(e){ /* squelch! */ }
+ return x;
+ },
+
+ _setCursorX: function(/*Number*/ x){
+ try{
+ this.textbox.focus();
+ if(!x){ x = 0; }
+ if(typeof this.textbox.selectionEnd == "number"){
+ this.textbox.selectionEnd = x;
+ }else if(this.textbox.createTextRange){
+ var range = this.textbox.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', x);
+ range.moveStart('character', x);
+ range.select();
+ }
+ }catch(e){ /* squelch! */ }
+ },
+
+ _spinnerPostMixInProperties: function(/*Object*/ args, /*Object*/ frag){
+ // summary: the widget's postMixInProperties() method should call this method
+
+ // set image size before instantiating template;
+ // changing it aftwards doesn't work on FF
+ var inputNode = this.getFragNodeRef(frag);
+ var inputSize = dojo.html.getBorderBox(inputNode);
+ this.buttonSize = { width: inputSize.height / 2 - 1, height: inputSize.height / 2 - 1};
+ },
+
+ _spinnerPostCreate: function(/*Object*/ args, /*Object*/ frag){
+ // summary: the widget's postCreate() method should call this method
+
+ // extra listeners
+ if(this.textbox.addEventListener){
+ // dojo.event.connect() doesn't seem to work with DOMMouseScroll
+ this.textbox.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "_mouseWheeled"), false); // Mozilla + Firefox + Netscape
+ }else{
+ dojo.event.connect(this.textbox, "onmousewheel", this, "_mouseWheeled"); // IE + Safari
+ }
+ //dojo.event.connect(window, "onchange", this, "_resize");
+ }
+ }
+);
+
+// summary
+// create spinable, single integer, input field
+dojo.widget.defineWidget(
+ "dojo.widget.IntegerSpinner",
+ [dojo.widget.IntegerTextbox, dojo.widget.Spinner],
+{
+ // summary: an IntegerSpinner with +/- buttons
+
+ // Number
+ // increment amount
+ delta: "1",
+
+ postMixInProperties: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.IntegerSpinner.superclass.postMixInProperties.apply(this, arguments);
+ this._spinnerPostMixInProperties(args, frag);
+ },
+
+ postCreate: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.IntegerSpinner.superclass.postCreate.apply(this, arguments);
+ this._spinnerPostCreate(args, frag);
+ },
+
+ // sumary
+ // spin the input field
+ // direction < 0: spin down
+ // direction > 0: spin up
+ // direction = 0: revalidate existing value
+ adjustValue: function(/*Number*/ direction, /*Number*/ x){
+ var val = this.getValue().replace(/[^\-+\d]/g, "");
+ if(val.length == 0){ return; }
+
+ var num = Math.min(Math.max((parseInt(val)+(parseInt(this.delta) * direction)), (this.flags.min?this.flags.min:-Infinity)), (this.flags.max?this.flags.max:+Infinity));
+ val = num.toString();
+
+ if(num >= 0){
+ val = ((this.flags.signed == true)?'+':' ')+val; // make sure first char is a nondigit
+ }
+
+ if(this.flags.separator.length > 0){
+ for (var i=val.length-3; i > 1; i-=3){
+ val = val.substr(0,i)+this.flags.separator+val.substr(i);
+ }
+ }
+
+ if(val.substr(0,1) == ' '){ val = val.substr(1); } // remove space
+
+ this.setValue(val);
+
+ return val.length;
+ }
+});
+
+/*
+ ****** RealNumberSpinner ******
+
+ A subclass of RealNumberTextbox.
+ @attr places The exact number of decimal places. If omitted, it's unlimited and optional.
+ @attr exponent Can be true or false. If omitted the exponential part is optional.
+ @attr eSigned Is the exponent signed? Can be true or false, if omitted the sign is optional.
+*/
+dojo.widget.defineWidget(
+ "dojo.widget.RealNumberSpinner",
+ [dojo.widget.RealNumberTextbox, dojo.widget.Spinner],
+ function(){ dojo.experimental("dojo.widget.RealNumberSpinner"); },
+{
+ // new subclass properties
+ delta: "1e1",
+
+ postMixInProperties: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.RealNumberSpinner.superclass.postMixInProperties.apply(this, arguments);
+ this._spinnerPostMixInProperties(args, frag);
+ },
+
+ postCreate: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.RealNumberSpinner.superclass.postCreate.apply(this, arguments);
+ this._spinnerPostCreate(args, frag);
+ },
+
+ adjustValue: function(/*Number*/ direction, /*Number*/ x){
+ var val = this.getValue().replace(/[^\-+\.eE\d]/g, "");
+ if(!val.length){ return; }
+
+ var num = parseFloat(val);
+ if(isNaN(num)){ return; }
+ var delta = this.delta.split(/[eE]/);
+ if(!delta.length){
+ delta = [1, 1];
+ }else{
+ delta[0] = parseFloat(delta[0].replace(/[^\-+\.\d]/g, ""));
+ if(isNaN(delta[0])){ delta[0] = 1; }
+ if(delta.length > 1){
+ delta[1] = parseInt(delta[1]);
+ }
+ if(isNaN(delta[1])){ delta[1] = 1; }
+ }
+ val = this.getValue().split(/[eE]/);
+ if(!val.length){ return; }
+ var numBase = parseFloat(val[0].replace(/[^\-+\.\d]/g, ""));
+ if(val.length == 1){
+ var numExp = 0;
+ }else{
+ var numExp = parseInt(val[1].replace(/[^\-+\d]/g, ""));
+ }
+ if(x <= val[0].length){
+ x = 0;
+ numBase += delta[0] * direction;
+ }else{
+ x = Number.MAX_VALUE;
+ numExp += delta[1] * direction;
+ if(this.flags.eSigned == false && numExp < 0){
+ numExp = 0;
+ }
+ }
+ num = Math.min(Math.max((numBase * Math.pow(10,numExp)), (this.flags.min?this.flags.min:-Infinity)), (this.flags.max?this.flags.max:+Infinity));
+ if((this.flags.exponent == true || (this.flags.exponent != false && x != 0)) && num.toExponential){
+ if (isNaN(this.flags.places) || this.flags.places == Infinity){
+ val = num.toExponential();
+ }else{
+ val = num.toExponential(this.flags.places);
+ }
+ }else if(num.toFixed && num.toPrecision){
+ if(isNaN(this.flags.places) || this.flags.places == Infinity){
+ val = num.toPrecision((1/3).toString().length-1);
+ }else{
+ val = num.toFixed(this.flags.places);
+ }
+ }else{
+ val = num.toString();
+ }
+
+ if(num >= 0){
+ if(this.flags.signed == true){
+ val = '+' + val;
+ }
+ }
+ val = val.split(/[eE]/);
+ if(this.flags.separator.length > 0){
+ if(num >= 0 && val[0].substr(0,1) != '+'){
+ val[0] = ' ' + val[0]; // make sure first char is nondigit for easy algorithm
+ }
+ var i = val[0].lastIndexOf('.');
+ if(i >= 0){
+ i -= 3;
+ }else{
+ i = val[0].length-3;
+ }
+ for (; i > 1; i-=3){
+ val[0] = val[0].substr(0,i)+this.flags.separator+val[0].substr(i);
+ }
+ if(val[0].substr(0,1) == ' '){ val[0] = val[0].substr(1); } // remove space
+ }
+ if(val.length > 1){
+ if((this.flags.eSigned == true)&&(val[1].substr(0,1) != '+')){
+ val[1] = '+' + val[1];
+ }else if((!this.flags.eSigned)&&(val[1].substr(0,1) == '+')){
+ val[1] = val[1].substr(1);
+ }else if((!this.flags.eSigned)&&(val[1].substr(0,1) == '-')&&(num.toFixed && num.toPrecision)){
+ if(isNaN(this.flags.places)){
+ val[0] = num.toPrecision((1/3).toString().length-1);
+ }else{
+ val[0] = num.toFixed(this.flags.places).toString();
+ }
+ val[1] = "0";
+ }
+ val[0] += 'e' + val[1];
+ }
+ this.setValue(val[0]);
+ if(x > val[0].length){ x = val[0].length; }
+ return x;
+ }
+});
+
+dojo.widget.defineWidget(
+ "dojo.widget.TimeSpinner",
+ [dojo.widget.TimeTextbox, dojo.widget.Spinner],
+ function(){ dojo.experimental("dojo.widget.TimeSpinner"); },
+{
+ postMixInProperties: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.TimeSpinner.superclass.postMixInProperties.apply(this, arguments);
+ this._spinnerPostMixInProperties(args, frag);
+ },
+
+ postCreate: function(/*Object*/ args, /*Object*/ frag){
+ dojo.widget.TimeSpinner.superclass.postCreate.apply(this, arguments);
+ this._spinnerPostCreate(args, frag);
+ },
+
+ adjustValue: function(/*Number*/ direction, /*Number*/ x){
+ //FIXME: formatting should make use of dojo.date.format?
+ var val = this.getValue();
+ var format = (this.flags.format && this.flags.format.search(/[Hhmst]/) >= 0) ? this.flags.format : "hh:mm:ss t";
+ if(direction == 0 || !val.length || !this.isValid()){ return; }
+ if (!this.flags.amSymbol){
+ this.flags.amSymbol = "AM";
+ }
+ if (!this.flags.pmSymbol){
+ this.flags.pmSymbol = "PM";
+ }
+ var re = dojo.regexp.time(this.flags);
+ var qualifiers = format.replace(/H/g,"h").replace(/[^hmst]/g,"").replace(/([hmst])\1/g,"$1");
+ var hourPos = qualifiers.indexOf('h') + 1;
+ var minPos = qualifiers.indexOf('m') + 1;
+ var secPos = qualifiers.indexOf('s') + 1;
+ var ampmPos = qualifiers.indexOf('t') + 1;
+ // tweak format to match the incoming data exactly to help find where the cursor is
+ var cursorFormat = format;
+ var ampm = "";
+ if (ampmPos > 0){
+ ampm = val.replace(new RegExp(re),"$"+ampmPos);
+ cursorFormat = cursorFormat.replace(/t+/, ampm.replace(/./g,"t"));
+ }
+ var hour = 0;
+ var deltaHour = 1;
+ if (hourPos > 0){
+ hour = val.replace(new RegExp(re),"$"+hourPos);
+ if (dojo.lang.isString(this.delta)){
+ deltaHour = this.delta.replace(new RegExp(re),"$"+hourPos);
+ }
+ if (isNaN(deltaHour)){
+ deltaHour = 1;
+ } else {
+ deltaHour = parseInt(deltaHour);
+ }
+ if (hour.length == 2){
+ cursorFormat = cursorFormat.replace(/([Hh])+/, "$1$1");
+ } else {
+ cursorFormat = cursorFormat.replace(/([Hh])+/, "$1");
+ }
+ if (isNaN(hour)){
+ hour = 0;
+ } else {
+ hour = parseInt(hour.replace(/^0(\d)/,"$1"));
+ }
+ }
+ var min = 0;
+ var deltaMin = 1;
+ if (minPos > 0){
+ min = val.replace(new RegExp(re),"$"+minPos);
+ if (dojo.lang.isString(this.delta)){
+ deltaMin = this.delta.replace(new RegExp(re),"$"+minPos);
+ }
+ if (isNaN(deltaMin)){
+ deltaMin = 1;
+ } else {
+ deltaMin = parseInt(deltaMin);
+ }
+ cursorFormat = cursorFormat.replace(/m+/, min.replace(/./g,"m"));
+ if (isNaN(min)){
+ min = 0;
+ } else {
+ min = parseInt(min.replace(/^0(\d)/,"$1"));
+ }
+ }
+ var sec = 0;
+ var deltaSec = 1;
+ if (secPos > 0){
+ sec = val.replace(new RegExp(re),"$"+secPos);
+ if (dojo.lang.isString(this.delta)){
+ deltaSec = this.delta.replace(new RegExp(re),"$"+secPos);
+ }
+ if (isNaN(deltaSec)){
+ deltaSec = 1;
+ } else {
+ deltaSec = parseInt(deltaSec);
+ }
+ cursorFormat = cursorFormat.replace(/s+/, sec.replace(/./g,"s"));
+ if (isNaN(sec)){
+ sec = 0;
+ } else {
+ sec = parseInt(sec.replace(/^0(\d)/,"$1"));
+ }
+ }
+ if (isNaN(x) || x >= cursorFormat.length){
+ x = cursorFormat.length-1;
+ }
+ var cursorToken = cursorFormat.charAt(x);
+
+ switch(cursorToken){
+ case 't':
+ if (ampm == this.flags.amSymbol){
+ ampm = this.flags.pmSymbol;
+ }
+ else if (ampm == this.flags.pmSymbol){
+ ampm = this.flags.amSymbol;
+ }
+ break;
+ default:
+ if (hour >= 1 && hour < 12 && ampm == this.flags.pmSymbol){
+ hour += 12;
+ }
+ if (hour == 12 && ampm == this.flags.amSymbol){
+ hour = 0;
+ }
+ switch(cursorToken){
+ case 's':
+ sec += deltaSec * direction;
+ while (sec < 0){
+ min--;
+ sec += 60;
+ }
+ while (sec >= 60){
+ min++;
+ sec -= 60;
+ }
+ case 'm':
+ if (cursorToken == 'm'){
+ min += deltaMin * direction;
+ }
+ while (min < 0){
+ hour--;
+ min += 60;
+ }
+ while (min >= 60){
+ hour++;
+ min -= 60;
+ }
+ case 'h':
+ case 'H':
+ if (cursorToken == 'h' || cursorToken == 'H'){
+ hour += deltaHour * direction;
+ }
+ while (hour < 0){
+ hour += 24;
+ }
+ while (hour >= 24){
+ hour -= 24;
+ }
+ break;
+ default: // should never get here
+ return;
+ }
+ if (hour >= 12){
+ ampm = this.flags.pmSymbol;
+ if (format.indexOf('h') >= 0 && hour >= 13){
+ hour -= 12;
+ }
+ } else {
+ ampm = this.flags.amSymbol;
+ if (format.indexOf('h') >= 0 && hour == 0){
+ hour = 12;
+ }
+ }
+ }
+
+ cursorFormat = format;
+ if (hour >= 0 && hour < 10 && format.search(/[hH]{2}/) >= 0){
+ hour = "0" + hour.toString();
+ }
+ if (hour >= 10 && cursorFormat.search(/[hH]{2}/) < 0 ){
+ cursorFormat = cursorFormat.replace(/(h|H)/, "$1$1");
+ }
+ if (min >= 0 && min < 10 && cursorFormat.search(/mm/) >= 0){
+ min = "0" + min.toString();
+ }
+ if (min >= 10 && cursorFormat.search(/mm/) < 0 ){
+ cursorFormat = cursorFormat.replace(/m/, "$1$1");
+ }
+ if (sec >= 0 && sec < 10 && cursorFormat.search(/ss/) >= 0){
+ sec = "0" + sec.toString();
+ }
+ if (sec >= 10 && cursorFormat.search(/ss/) < 0 ){
+ cursorFormat = cursorFormat.replace(/s/, "$1$1");
+ }
+ x = cursorFormat.indexOf(cursorToken);
+ if (x == -1){
+ x = format.length;
+ }
+ format = format.replace(/[hH]+/, hour);
+ format = format.replace(/m+/, min);
+ format = format.replace(/s+/, sec);
+ format = format.replace(/t/, ampm);
+ this.setValue(format);
+ if(x > format.length){ x = format.length; }
+ return x;
+ }
+});
Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Spinner.js
------------------------------------------------------------------------------
svn:eol-style = native