Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SplitContainer.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SplitContainer.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SplitContainer.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SplitContainer.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,517 @@ +dojo.provide("dojo.widget.SplitContainer"); + +// +// TODO +// make it prettier +// active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case) +// + +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.ContentPane"); +dojo.require("dojo.widget.HtmlWidget"); +dojo.require("dojo.html.style"); +dojo.require("dojo.html.layout"); +dojo.require("dojo.html.selection"); +dojo.require("dojo.io.cookie"); + +dojo.widget.defineWidget( + "dojo.widget.SplitContainer", + dojo.widget.HtmlWidget, + function(){ + this.sizers = []; + }, +{ + isContainer: true, + + // variables + virtualSizer: null, + isHorizontal: null, + paneBefore: null, + paneAfter: null, + isSizing: false, + dragOffset: 0, + startPoint: 0, + lastPoint: 0, + sizingSplitter: null, + screenToClientOffset: 0, + isDraggingLeft: 0, + templateCssPath: dojo.uri.dojoUri("src/widget/templates/SplitContainer.css"), + originPos: 0, + + // parameters (user settable) + activeSizing: false, + sizerWidth: 15, + orientation: 'horizontal', + persist: true, // save splitter positions in a cookie + + debugName: '', + + fillInTemplate: function(){ + + dojo.html.insertCssFile(this.templateCssPath, null, true); + dojo.html.addClass(this.domNode, "dojoSplitContainer"); + // overflow has to be explicitly hidden for splitContainers using gekko (trac #1435) + // to keep other combined css classes from inadvertantly making the overflow visible + if (dojo.render.html.moz) { + this.domNode.style.overflow = '-moz-scrollbars-none'; // hidden doesn't work + } + + var content = dojo.html.getContentBox(this.domNode); + this.paneWidth = content.width; + this.paneHeight = content.height; + + this.isHorizontal = (this.orientation == 'horizontal'); + + //dojo.debug("fillInTemplate for "+this.debugName); + }, + + onResized: function(e){ + var content = dojo.html.getContentBox(this.domNode); + this.paneWidth = content.width; + this.paneHeight = content.height; + this.layoutPanels(); + }, + + postCreate: function(args, fragment, parentComp){ + + // dojo.debug("post create for "+this.debugName); + + // attach the children and create the draggers + for(var i=0; i 0) { + for(var x=0; x 1) { + this._addSizer(); + } + + this.layoutPanels(); + }, + + layoutPanels: function(){ + if (this.children.length == 0){ return; } + + // + // calculate space + // + + var space = this.isHorizontal ? this.paneWidth : this.paneHeight; + + if (this.children.length > 1){ + + space -= this.sizerWidth * (this.children.length - 1); + } + + + // + // calculate total of SizeShare values + // + + var out_of = 0; + + for(var i=0; i 0){ + if (pane.sizeActual > pane.sizeMin){ + if ((pane.sizeActual - pane.sizeMin) > growth){ + + // stick all the growth in this pane + pane.sizeActual = pane.sizeActual - growth; + growth = 0; + }else{ + // put as much growth in here as we can + growth -= pane.sizeActual - pane.sizeMin; + pane.sizeActual = pane.sizeMin; + } + } + } + return growth; + }, + + checkSizes: function(){ + + var total_min_size = 0; + var total_size = 0; + + for(var i=0; i 0){ + if (this.isDraggingLeft){ + for(var i=this.children.length-1; i>=0; i--){ + growth = this.growPane(growth, this.children[i]); + } + }else{ + for(var i=0; i 0) ? 1 : 0; + + if (!this.activeSizing){ + + if (a < this.paneBefore.position + this.paneBefore.sizeMin){ + + a = this.paneBefore.position + this.paneBefore.sizeMin; + } + + if (a > this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin))){ + + a = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin)); + } + } + + a -= this.sizingSplitter.position; + + this.checkSizes(); + + return a; + }, + + updateSize: function(){ + var pos = this.lastPoint - this.dragOffset - this.originPos; + + var start_region = this.paneBefore.position; + var end_region = this.paneAfter.position + this.paneAfter.sizeActual; + + this.paneBefore.sizeActual = pos - start_region; + this.paneAfter.position = pos + this.sizerWidth; + this.paneAfter.sizeActual = end_region - this.paneAfter.position; + + for(var i=0; i"+ label + ""; + //textNode.setAttribute("x", coords[6]); + //textNode.setAttribute("y", coords[7]); + break; + case "rectangle": + //FIXME: implement + textString = ""; + //textNode.setAttribute("x", coords[6]); + //textNode.setAttribute("y", coords[7]); + break; + case "circle": + //FIXME: implement + textString = ""; + //textNode.setAttribute("x", coords[6]); + //textNode.setAttribute("y", coords[7]); + break; + } + //textNode.appendChild(labelNode); + //this.domNode.appendChild(textNode); + return textString; + //alert(textNode.getComputedTextLength()); + } + + this.fillInTemplate = function(x, y, textSize, label, shape){ + // the idea is to set the text to the appropriate place given its length + // and the template shape + + // FIXME: For now, assuming text sizes are integers in SVG units + this.textSize = textSize || 12; + this.label = label; + // FIXEME: for now, I'm going to fake this... need to come up with a real way to + // determine the actual width of the text, such as computedStyle + var textWidth = this.label.length*this.textSize ; + //this.setLabel(); + } +} + +dojo.inherits(dojo.widget.SvgButton, dojo.widget.DomButton); + +// FIXME +dojo.widget.SvgButton.prototype.shapeString = function(x, y, textSize, label, shape) { + switch(shape) { + case "ellipse": + var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape) + return ""; + break; + case "rect": + //FIXME: implement + return ""; + //return ""; + break; + case "circle": + //FIXME: implement + return ""; + //return ""; + break; + } +} + +dojo.widget.SvgButton.prototype.coordinates = function(x, y, textSize, label, shape) { + switch(shape) { + case "ellipse": + var buttonWidth = label.length*textSize; + var buttonHeight = textSize*2.5 + var rx = buttonWidth/2; + var ry = buttonHeight/2; + var cx = rx + x; + var cy = ry + y; + var textX = cx - rx*textSize/25; + var textY = cy*1.1; + return [buttonWidth, buttonHeight, rx, ry, cx, cy, textX, textY]; + break; + case "rectangle": + //FIXME: implement + return ""; + break; + case "circle": + //FIXME: implement + return ""; + break; + } +} + +dojo.widget.SvgButton.prototype.labelString = function(x, y, textSize, label, shape){ + var textString = ""; + var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape); + switch(shape) { + case "ellipse": + textString = ""+ label + ""; + break; + case "rectangle": + //FIXME: implement + textString = ""; + break; + case "circle": + //FIXME: implement + textString = ""; + break; + } + return textString; +} + +dojo.widget.SvgButton.prototype.templateString = function(x, y, textSize, label, shape) { + return ""+ dojo.widgets.SVGButton.prototype.shapeString(x, y, textSize, label, shape) + dojo.widget.SVGButton.prototype.labelString(x, y, textSize, label, shape) + ""; +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgButton.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgWidget.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgWidget.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgWidget.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgWidget.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,79 @@ +dojo.require("dojo.widget.DomWidget"); +dojo.provide("dojo.widget.SvgWidget"); +dojo.provide("dojo.widget.SVGWidget"); // back compat + +dojo.require("dojo.dom"); + +// SVGWidget is a mixin ONLY +dojo.widget.declare( + "dojo.widget.SvgWidget", + dojo.widget.DomWidget, +{ + getContainerHeight: function(){ + // NOTE: container height must be returned as the INNER height + dojo.unimplemented("dojo.widget.SvgWidget.getContainerHeight"); + }, + + getContainerWidth: function(){ + // return this.parent.domNode.offsetWidth; + dojo.unimplemented("dojo.widget.SvgWidget.getContainerWidth"); + }, + + setNativeHeight: function(height){ + // var ch = this.getContainerHeight(); + dojo.unimplemented("dojo.widget.SVGWidget.setNativeHeight"); + }, + + createNodesFromText: function(txt, wrap){ + return dojo.dom.createNodesFromText(txt, wrap); + } +}); + +dojo.widget.SVGWidget = dojo.widget.SvgWidget; + +try{ +(function(){ + var tf = function(){ + // FIXME: fill this in!!! + var rw = new function(){ + dojo.widget.SvgWidget.call(this); + this.buildRendering = function(){ return; } + this.destroyRendering = function(){ return; } + this.postInitialize = function(){ return; } + this.cleanUp = function(){ return; } + this.widgetType = "SVGRootWidget"; + this.domNode = document.documentElement; + } + var wm = dojo.widget.manager; + wm.root = rw; + wm.add(rw); + + // extend the widgetManager with a getWidgetFromNode method + wm.getWidgetFromNode = function(node){ + var filter = function(x){ + if(x.domNode == node){ + return true; + } + } + var widgets = []; + while((node)&&(widgets.length < 1)){ + widgets = this.getWidgetsByFilter(filter); + node = node.parentNode; + } + if(widgets.length > 0){ + return widgets[0]; + }else{ + return null; + } + } + + wm.getWidgetFromEvent = function(domEvt){ + return this.getWidgetFromNode(domEvt.target); + } + + wm.getWidgetFromPrimitive = wm.getWidgetFromNode; + } + // make sure we get called when the time is right + dojo.event.connect(dojo.hostenv, "loaded", tf); +})(); +}catch(e){ alert(e); } Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SvgWidget.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SwtWidget.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SwtWidget.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SwtWidget.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SwtWidget.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,54 @@ +dojo.provide("dojo.widget.SwtWidget"); + +dojo.require("dojo.event.*"); +dojo.require("dojo.widget.Widget"); +dojo.require("dojo.uri.*"); +dojo.require("dojo.lang.func"); +dojo.require("dojo.lang.extras"); + +try{ + importPackage(Packages.org.eclipse.swt.widgets); + + dojo.declare("dojo.widget.SwtWidget", dojo.widget.Widget, + function() { + if((arguments.length>0)&&(typeof arguments[0] == "object")){ + this.create(arguments[0]); + } + }, + { + display: null, + shell: null, + + show: function(){ }, + hide: function(){ }, + + addChild: function(){ }, + registerChild: function(){ }, + addWidgetAsDirectChild: function(){ }, + removeChild: function(){ }, + cleanUp: function(){ }, + destroyRendering: function(){ }, + postInitialize: function(){ }, + }); + + // initialize SWT runtime + + dojo.widget.SwtWidget.prototype.display = new Display(); + dojo.widget.SwtWidget.prototype.shell = new Shell(dojo.widget.SwtWidget.prototype.display); + + dojo.widget.manager.startShell = function(){ + var sh = dojo.widget.SwtWidget.prototype.shell; + var d = dojo.widget.SwtWidget.prototype.display; + sh.open(); + while(!sh.isDisposed()){ + dojo.widget.manager.doNext(); + if(!d.readAndDispatch()){ + d.sleep(); + } + } + d.dispose(); + }; +}catch(e){ + // seems we didn't have the SWT classes in the environment. Log it. + dojo.debug("dojo.widget.SwtWidget not loaded. SWT classes not available"); +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/SwtWidget.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TabContainer.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TabContainer.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TabContainer.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TabContainer.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,205 @@ +dojo.provide("dojo.widget.TabContainer"); + +dojo.require("dojo.lang.func"); +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.PageContainer"); +dojo.require("dojo.event.*"); +dojo.require("dojo.html.selection"); +dojo.require("dojo.widget.html.layout"); + +// summary +// A TabContainer is a container that has multiple panes, but shows only +// one pane at a time. There are a set of tabs corresponding to each pane, +// where each tab has the title (aka label) of the pane, and optionally a close button. +// +// Publishes topics -addChild, -removeChild, and -selectChild +// (where is the id of the TabContainer itself. +dojo.widget.defineWidget("dojo.widget.TabContainer", dojo.widget.PageContainer, { + + // String + // Defines where tab labels go relative to tab content. + // "top", "bottom", "left-h", "right-h" + labelPosition: "top", + + // String + // If closebutton=="tab", then every tab gets a close button. + // DEPRECATED: Should just say closable=true on each + // pane you want to be closable. + closeButton: "none", + + templateString: null, // override setting in PageContainer + templatePath: dojo.uri.dojoUri("src/widget/templates/TabContainer.html"), + templateCssPath: dojo.uri.dojoUri("src/widget/templates/TabContainer.css"), + + // String + // initially selected tab (widgetId) + // DEPRECATED: use selectedChild instead. + selectedTab: "", + + postMixInProperties: function() { + if(this.selectedTab){ + dojo.deprecated("selectedTab deprecated, use selectedChild instead, will be removed in", "0.5"); + this.selectedChild=this.selectedTab; + } + if(this.closeButton!="none"){ + dojo.deprecated("closeButton deprecated, use closable='true' on each child instead, will be removed in", "0.5"); + } + dojo.widget.TabContainer.superclass.postMixInProperties.apply(this, arguments); + }, + + fillInTemplate: function() { + // create the tab list that will have a tab (a.k.a. tab button) for each tab panel + this.tablist = dojo.widget.createWidget("TabController", + { + id: this.widgetId + "_tablist", + labelPosition: this.labelPosition, + doLayout: this.doLayout, + containerId: this.widgetId + }, this.tablistNode); + dojo.widget.TabContainer.superclass.fillInTemplate.apply(this, arguments); + }, + + postCreate: function(args, frag) { + dojo.widget.TabContainer.superclass.postCreate.apply(this, arguments); + + // size the container pane to take up the space not used by the tabs themselves + this.onResized(); + }, + + _setupChild: function(tab){ + if(this.closeButton=="tab" || this.closeButton=="pane"){ + // TODO: remove in 0.5 + tab.closable=true; + } + dojo.html.addClass(tab.domNode, "dojoTabPane"); + dojo.widget.TabContainer.superclass._setupChild.apply(this, arguments); + }, + + onResized: function(){ + // Summary: Configure the content pane to take up all the space except for where the tabs are + if(!this.doLayout){ return; } + + // position the labels and the container node + var labelAlign=this.labelPosition.replace(/-h/,""); + var children = [ + {domNode: this.tablist.domNode, layoutAlign: labelAlign}, + {domNode: this.containerNode, layoutAlign: "client"} + ]; + dojo.widget.html.layout(this.domNode, children); + + if(this.selectedChildWidget){ + var containerSize = dojo.html.getContentBox(this.containerNode); + this.selectedChildWidget.resizeTo(containerSize.width, containerSize.height); + } + }, + + selectTab: function(tab, callingWidget){ + dojo.deprecated("use selectChild() rather than selectTab(), selectTab() will be removed in", "0.5"); + this.selectChild(tab, callingWidget); + }, + + onKey: function(e){ + // summary + // Keystroke handling for keystrokes on the tab panel itself (that were bubbled up to me) + // Ctrl-up: focus is returned from the pane to the tab button + // Alt-del: close tab + if(e.keyCode == e.KEY_UP_ARROW && e.ctrlKey){ + // set focus to current tab + var button = this.correspondingTabButton || this.selectedTabWidget.tabButton; + button.focus(); + dojo.event.browser.stopEvent(e); + }else if(e.keyCode == e.KEY_DELETE && e.altKey){ + if (this.selectedChildWidget.closable){ + this.closeChild(this.selectedChildWidget); + dojo.event.browser.stopEvent(e); + } + } + }, + + destroy: function(){ + this.tablist.destroy(); + dojo.widget.TabContainer.superclass.destroy.apply(this, arguments); + } +}); + +// summary +// Set of tabs (the things with labels and a close button, that you click to show a tab panel). +// Lets the user select the currently shown pane in a TabContainer or PageContainer. +// TabController also monitors the TabContainer, and whenever a pane is +// added or deleted updates itself accordingly. +dojo.widget.defineWidget( + "dojo.widget.TabController", + dojo.widget.PageController, + { + templateString: "
", + + // String + // Defines where tab labels go relative to tab content. + // "top", "bottom", "left-h", "right-h" + labelPosition: "top", + + doLayout: true, + + // String + // Class name to apply to the top dom node + "class": "", + + // String + // the name of the tab widget to create to correspond to each page + buttonWidget: "TabButton", + + postMixInProperties: function() { + if(!this["class"]){ + this["class"] = "dojoTabLabels-" + this.labelPosition + (this.doLayout ? "" : " dojoTabNoLayout"); + } + dojo.widget.TabController.superclass.postMixInProperties.apply(this, arguments); + } + } +); + +// summary +// A tab (the thing you click to select a pane). +// Contains the title (aka label) of the pane, and optionally a close-button to destroy the pane. +// This is an internal widget and should not be instantiated directly. +dojo.widget.defineWidget("dojo.widget.TabButton", dojo.widget.PageButton, +{ + templateString: "
" + +"
" + +"${this.label}" + +"" + +"
" + +"
", + + postMixInProperties: function(){ + this.closeButtonStyle = this.closeButton ? "" : "display: none"; + dojo.widget.TabButton.superclass.postMixInProperties.apply(this, arguments); + }, + + fillInTemplate: function(){ + dojo.html.disableSelection(this.titleNode); + dojo.widget.TabButton.superclass.fillInTemplate.apply(this, arguments); + } +}); + + +// summary +// Tab for display in high-contrast mode (where background images don't show up). +// This is an internal widget and shouldn't be instantiated directly. +dojo.widget.defineWidget( + "dojo.widget.a11y.TabButton", + dojo.widget.TabButton, + { + imgPath: dojo.uri.dojoUri("src/widget/templates/images/tab_close.gif"), + + templateString: "
" + +"
" + +"${this.label}" + +"[x]" + +"
" + +"
" + } +); + + Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TabContainer.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TaskBar.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TaskBar.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TaskBar.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TaskBar.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,83 @@ +dojo.provide("dojo.widget.TaskBar"); + +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.FloatingPane"); +dojo.require("dojo.widget.HtmlWidget"); +dojo.require("dojo.event.*"); +dojo.require("dojo.html.selection"); + +// summary +// Widget used internally by the TaskBar; +// shows an icon associated w/a floating pane +dojo.widget.defineWidget( + "dojo.widget.TaskBarItem", + dojo.widget.HtmlWidget, +{ + // String + // path of icon for associated floating pane + iconSrc: '', + + // String + // name of associated floating pane + caption: 'Untitled', + + // String + // widget id of associated floating pane + widgetId: "", + + templatePath: dojo.uri.dojoUri("src/widget/templates/TaskBarItemTemplate.html"), + templateCssPath: dojo.uri.dojoUri("src/widget/templates/TaskBar.css"), + + fillInTemplate: function() { + if (this.iconSrc) { + var img = document.createElement("img"); + img.src = this.iconSrc; + this.domNode.appendChild(img); + } + this.domNode.appendChild(document.createTextNode(this.caption)); + dojo.html.disableSelection(this.domNode); + }, + + postCreate: function() { + this.window=dojo.widget.getWidgetById(this.windowId); + this.window.explodeSrc = this.domNode; + dojo.event.connect(this.window, "destroy", this, "destroy") + }, + + onClick: function() { + this.window.toggleDisplay(); + } +}); + +// summary: +// Displays an icon for each associated floating pane, like Windows task bar +dojo.widget.defineWidget( + "dojo.widget.TaskBar", + dojo.widget.FloatingPane, + function(){ + this._addChildStack = []; + }, +{ + // TODO: this class extends floating pane merely to get the shadow; + // it should extend HtmlWidget and then just call the shadow code directly + resizable: false, + titleBarDisplay: "none", + + addChild: function(/*Widget*/ child) { + // summary: add taskbar item for specified FloatingPane + // TODO: this should not be called addChild(), as that has another meaning. + if(!this.containerNode){ + this._addChildStack.push(child); + }else if(this._addChildStack.length > 0){ + var oarr = this._addChildStack; + this._addChildStack = []; + dojo.lang.forEach(oarr, this.addChild, this); + } + var tbi = dojo.widget.createWidget("TaskBarItem", + { windowId: child.widgetId, + caption: child.title, + iconSrc: child.iconSrc + }); + dojo.widget.TaskBar.superclass.addChild.call(this,tbi); + } +}); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TaskBar.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Textbox.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Textbox.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Textbox.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Textbox.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,84 @@ +dojo.provide("dojo.widget.Textbox"); + +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.HtmlWidget"); +dojo.require("dojo.widget.Manager"); +dojo.require("dojo.widget.Parse"); +dojo.require("dojo.xml.Parse"); +dojo.require("dojo.lang.array"); +dojo.require("dojo.lang.common"); + +dojo.require("dojo.i18n.common"); +dojo.requireLocalization("dojo.widget", "validate"); + +/* + ****** Textbox ****** + + This widget is a generic textbox field. + Serves as a base class to derive more specialized functionality in subclasses. + Has the following properties that can be specified as attributes in the markup. + + @attr id The textbox id attribute. + @attr className The textbox class attribute. + @attr name The textbox name attribute. + @attr value The textbox value attribute. + @attr trim Removes leading and trailing whitespace if true. Default is false. + @attr uppercase Converts all characters to uppercase if true. Default is false. + @attr lowercase Converts all characters to lowercase if true. Default is false. + @attr ucFirst Converts the first character of each word to uppercase if true. + @attr lowercase Removes all characters that are not digits if true. Default is false. +*/ +dojo.widget.defineWidget( + "dojo.widget.Textbox", + dojo.widget.HtmlWidget, + { + // default values for new subclass properties + className: "", + name: "", + value: "", + type: "", + trim: false, + uppercase: false, + lowercase: false, + ucFirst: false, + digit: false, + htmlfloat: "none", + + templatePath: dojo.uri.dojoUri("src/widget/templates/Textbox.html"), + + // our DOM nodes + textbox: null, + + // Apply various filters to textbox value + filter: function() { + if (this.trim) { + this.textbox.value = this.textbox.value.replace(/(^\s*|\s*$)/g, ""); + } + if (this.uppercase) { + this.textbox.value = this.textbox.value.toUpperCase(); + } + if (this.lowercase) { + this.textbox.value = this.textbox.value.toLowerCase(); + } + if (this.ucFirst) { + this.textbox.value = this.textbox.value.replace(/\b\w+\b/g, + function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); }); + } + if (this.digit) { + this.textbox.value = this.textbox.value.replace(/\D/g, ""); + } + }, + + // event handlers, you can over-ride these in your own subclasses + onfocus: function() {}, + onblur: function() { this.filter(); }, + + // All functions below are called by create from dojo.widget.Widget + mixInProperties: function(localProperties, frag) { + dojo.widget.Textbox.superclass.mixInProperties.apply(this, arguments); + if ( localProperties["class"] ) { + this.className = localProperties["class"]; + } + } + } +); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Textbox.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TimePicker.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TimePicker.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TimePicker.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TimePicker.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,332 @@ +dojo.provide("dojo.widget.TimePicker"); +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.HtmlWidget"); +dojo.require("dojo.event.*"); +dojo.require("dojo.date.serialize"); +dojo.require("dojo.date.format"); +dojo.require("dojo.dom"); +dojo.require("dojo.html.style"); + +dojo.requireLocalization("dojo.i18n.calendar", "gregorian"); +dojo.requireLocalization("dojo.widget", "TimePicker"); + +dojo.widget.defineWidget( + "dojo.widget.TimePicker", + dojo.widget.HtmlWidget, + function(){ + // selected time, JS Date object + this.time = ""; + // set following flag to true if a default time should be set + this.useDefaultTime = false; + // set the following to true to set default minutes to current time, false to // use zero + this.useDefaultMinutes = false; + // rfc 3339 date + this.storedTime = ""; + // time currently selected in the UI, stored in hours, minutes, seconds in the format that will be actually displayed + this.currentTime = {}; + this.classNames = { + selectedTime: "selectedItem" + }; + this.any = "any"; //FIXME: never used? + // dom node indecies for selected hour, minute, amPm, and "any time option" + this.selectedTime = { + hour: "", + minute: "", + amPm: "", + anyTime: false + }; + + // minutes are ordered as follows: ["12", "6", "1", "7", "2", "8", "3", "9", "4", "10", "5", "11"] + this.hourIndexMap = ["", 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11, 0]; + // minutes are ordered as follows: ["00", "30", "05", "35", "10", "40", "15", "45", "20", "50", "25", "55"] + this.minuteIndexMap = [0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11]; + }, +{ + isContainer: false, + templatePath: dojo.uri.dojoUri("src/widget/templates/TimePicker.html"), + templateCssPath: dojo.uri.dojoUri("src/widget/templates/TimePicker.css"), + + fillInTemplate: function(args, frag){ + // Copy style info from input node to output node + var source = this.getFragNodeRef(frag); + dojo.html.copyStyle(this.domNode, source); + + this.initData(); + this.initUI(); + }, + + postMixInProperties: function(localProperties, frag) { + dojo.widget.TimePicker.superclass.postMixInProperties.apply(this, arguments); + this.calendar = dojo.i18n.getLocalization("dojo.i18n.calendar", "gregorian", this.lang); // "am","pm" + this.widgetStrings = dojo.i18n.getLocalization("dojo.widget", "TimePicker", this.lang); // "any" + }, + + initData: function() { + // FIXME: doesn't currently validate the time before trying to set it + // Determine the date/time from stored info, or by default don't + // have a set time + // FIXME: should normalize against whitespace on storedTime... for now + // just a lame hack + if(this.storedTime.indexOf("T")!=-1 && this.storedTime.split("T")[1] && this.storedTime!=" " && this.storedTime.split("T")[1]!="any") { + this.time = dojo.widget.TimePicker.util.fromRfcDateTime(this.storedTime, this.useDefaultMinutes, this.selectedTime.anyTime); + } else if (this.useDefaultTime) { + this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes, this.selectedTime.anyTime); + } else { + this.selectedTime.anyTime = true; + this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", 0, 1); + } + }, + + initUI: function() { + // set UI to match the currently selected time + if(!this.selectedTime.anyTime && this.time) { + var amPmHour = dojo.widget.TimePicker.util.toAmPmHour(this.time.getHours()); + var hour = amPmHour[0]; + var isAm = amPmHour[1]; + var minute = this.time.getMinutes(); + var minuteIndex = parseInt(minute/5); + this.onSetSelectedHour(this.hourIndexMap[hour]); + this.onSetSelectedMinute(this.minuteIndexMap[minuteIndex]); + this.onSetSelectedAmPm(isAm); + } else { + this.onSetSelectedAnyTime(); + } + }, + + setTime: function(date) { + if(date) { + this.selectedTime.anyTime = false; + this.setDateTime(dojo.date.toRfc3339(date)); + } else { + this.selectedTime.anyTime = true; + } + this.initData(); + this.initUI(); + }, + + setDateTime: function(rfcDate) { + this.storedTime = rfcDate; + }, + + onClearSelectedHour: function(evt) { + this.clearSelectedHour(); + }, + + onClearSelectedMinute: function(evt) { + this.clearSelectedMinute(); + }, + + onClearSelectedAmPm: function(evt) { + this.clearSelectedAmPm(); + }, + + onClearSelectedAnyTime: function(evt) { + this.clearSelectedAnyTime(); + if(this.selectedTime.anyTime) { + this.selectedTime.anyTime = false; + this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes); + this.initUI(); + } + }, + + clearSelectedHour: function() { + var hourNodes = this.hourContainerNode.getElementsByTagName("td"); + for (var i=0; i12) { + amPmHour = amPmHour - 12; + isAm = false; + } else if (amPmHour == 12) { + isAm = false; + } + return [amPmHour, isAm]; + } + + this.fromAmPmHour = function(amPmHour, isAm) { + var hour = parseInt(amPmHour, 10); + if(isAm && hour == 12) { + hour = 0; + } else if (!isAm && hour<12) { + hour = hour + 12; + } + return hour; + } +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TimePicker.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TitlePane.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TitlePane.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TitlePane.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TitlePane.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,51 @@ +dojo.provide("dojo.widget.TitlePane"); +dojo.require("dojo.widget.*"); +dojo.require("dojo.widget.ContentPane"); +dojo.require("dojo.html.style"); +dojo.require("dojo.lfx.*"); + +dojo.widget.defineWidget( + "dojo.widget.TitlePane", + dojo.widget.ContentPane, +{ + labelNode: "", + labelNodeClass: "", + containerNodeClass: "", + label: "", + + open: true, + templatePath: dojo.uri.dojoUri("src/widget/templates/TitlePane.html"), + + postCreate: function() { + if (this.label) { + this.labelNode.appendChild(document.createTextNode(this.label)); + } + + if (this.labelNodeClass) { + dojo.html.addClass(this.labelNode, this.labelNodeClass); + } + + if (this.containerNodeClass) { + dojo.html.addClass(this.containerNode, this.containerNodeClass); + } + + if (!this.open) { + dojo.html.hide(this.containerNode); + } + dojo.widget.TitlePane.superclass.postCreate.apply(this, arguments); + }, + + onLabelClick: function() { + if (this.open) { + dojo.lfx.wipeOut(this.containerNode, 250).play(); + this.open=false; + } else { + dojo.lfx.wipeIn(this.containerNode, 250).play(); + this.open=true; + } + }, + + setLabel: function(label) { + this.labelNode.innerHTML=label; + } +}); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/TitlePane.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toaster.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toaster.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toaster.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toaster.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,235 @@ +dojo.provide("dojo.widget.Toaster"); + +dojo.require("dojo.widget.*"); +dojo.require("dojo.lfx.*"); +dojo.require("dojo.html.iframe"); + +// This is mostly taken from Jesse Kuhnert's MessageNotifier. +// Modified by Bryan Forbes to support topics and a variable delay. + +dojo.widget.defineWidget( + "dojo.widget.Toaster", + dojo.widget.HtmlWidget, + { + templateString: '
', + templateCssPath: dojo.uri.dojoUri("src/widget/templates/Toaster.css"), + + clipNode: null, + + messageTopic: "", + contentNode: null, + + _scrollConnected: false, + + // possible message types + messageTypes: { + MESSAGE: "MESSAGE", + WARNING: "WARNING", + ERROR: "ERROR", + FATAL: "FATAL" + }, + defaultType: "MESSAGE", + + // css classes + clipCssClass: "dojoToasterClip", + containerCssClass: "dojoToasterContainer", + contentCssClass: "dojoToasterContent", + messageCssClass: "dojoToasterMessage", + warningCssClass: "dojoToasterWarning", + errorCssClass: "dojoToasterError", + fatalCssClass: "dojoToasterFatal", + + positionDirection: "br-up", + positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"], + showDelay: 2000, + + slideAnim: null, + fadeAnim: null, + + bgIframe: null, + + postCreate: function(){ + this.hide(); + dojo.html.setClass(this.clipNode, this.clipCssClass); + dojo.html.addClass(this.containerNode, this.containerCssClass); + dojo.html.setClass(this.contentNode, this.contentCssClass); + if(this.messageTopic){ + dojo.event.topic.subscribe(this.messageTopic, this, "handleMessage"); + } + if(!this.positionDirection || !dojo.lang.inArray(this.positionDirectionTypes, this.positionDirection)){ + this.positionDirection = this.positionDirectionTypes.BRU; + } + }, + + handleMessage: function(msg){ + if(dojo.lang.isString(msg)){ + this.setContent(msg); + }else{ + this.setContent(msg["message"], msg["type"], msg["delay"]); + } + }, + + setContent: function(msg, messageType, delay){ + var delay = delay||this.showDelay; + // sync animations so there are no ghosted fades and such + if(this.slideAnim && this.slideAnim.status() == "playing"){ + dojo.lang.setTimeout(50, dojo.lang.hitch(this, function(){ + this.setContent(msg, messageType); + })); + return; + }else if(this.slideAnim){ + this.slideAnim.stop(); + if(this.fadeAnim) this.fadeAnim.stop(); + } + if(!msg){ + dojo.debug(this.widgetId + ".setContent() incoming content was null, ignoring."); + return; + } + if(!this.positionDirection || !dojo.lang.inArray(this.positionDirectionTypes, this.positionDirection)){ + dojo.raise(this.widgetId + ".positionDirection is an invalid value: " + this.positionDirection); + } + + // determine type of content and apply appropriately + dojo.html.removeClass(this.containerNode, this.messageCssClass); + dojo.html.removeClass(this.containerNode, this.warningCssClass); + dojo.html.removeClass(this.containerNode, this.errorCssClass); + dojo.html.removeClass(this.containerNode, this.fatalCssClass); + + dojo.html.clearOpacity(this.containerNode); + + if(msg instanceof String || typeof msg == "string"){ + this.contentNode.innerHTML = msg; + }else if(dojo.html.isNode(msg)){ + this.contentNode.innerHTML = dojo.html.getContentAsString(msg); + }else{ + dojo.raise("Toaster.setContent(): msg is of unknown type:" + msg); + } + + switch(messageType){ + case this.messageTypes.WARNING: + dojo.html.addClass(this.containerNode, this.warningCssClass); + break; + case this.messageTypes.ERROR: + dojo.html.addClass(this.containerNode, this.errorCssClass); + break + case this.messageTypes.FATAL: + dojo.html.addClass(this.containerNode, this.fatalCssClass); + break; + case this.messageTypes.MESSAGE: + default: + dojo.html.addClass(this.containerNode, this.messageCssClass); + break; + } + + // now do funky animation of widget appearing from + // bottom right of page and up + this.show(); + + var nodeSize = dojo.html.getMarginBox(this.containerNode); + + // sets up initial position of container node and slide-out direction + if(this.positionDirection.indexOf("-up") >= 0){ + this.containerNode.style.left=0+"px"; + this.containerNode.style.top=nodeSize.height + 10 + "px"; + }else if(this.positionDirection.indexOf("-left") >= 0){ + this.containerNode.style.left=nodeSize.width + 10 +"px"; + this.containerNode.style.top=0+"px"; + }else if(this.positionDirection.indexOf("-right") >= 0){ + this.containerNode.style.left = 0 - nodeSize.width - 10 + "px"; + this.containerNode.style.top = 0+"px"; + }else if(this.positionDirection.indexOf("-down") >= 0){ + this.containerNode.style.left = 0+"px"; + this.containerNode.style.top = 0 - nodeSize.height - 10 + "px"; + }else{ + dojo.raise(this.widgetId + ".positionDirection is an invalid value: " + this.positionDirection); + } + + this.slideAnim = dojo.lfx.html.slideTo( + this.containerNode, + { top: 0, left: 0 }, + 450, + null, + dojo.lang.hitch(this, function(nodes, anim){ + dojo.lang.setTimeout(dojo.lang.hitch(this, function(evt){ + // we must hide the iframe in order to fade + // TODO: figure out how to fade with a BackgroundIframe + if(this.bgIframe){ + this.bgIframe.hide(); + } + // can't do a fadeHide because we're fading the + // inner node rather than the clipping node + this.fadeAnim = dojo.lfx.html.fadeOut( + this.containerNode, + 1000, + null, + dojo.lang.hitch(this, function(evt){ + this.hide(); + })).play(); + }), delay); + })).play(); + }, + + placeClip: function(){ + var scroll = dojo.html.getScroll(); + var view = dojo.html.getViewport(); + + var nodeSize = dojo.html.getMarginBox(this.containerNode); + + // sets up the size of the clipping node + this.clipNode.style.height = nodeSize.height+"px"; + this.clipNode.style.width = nodeSize.width+"px"; + + // sets up the position of the clipping node + if(this.positionDirection.match(/^t/)){ + this.clipNode.style.top = scroll.top+"px"; + }else if(this.positionDirection.match(/^b/)){ + this.clipNode.style.top = (view.height - nodeSize.height - 2 + scroll.top)+"px"; + } + if(this.positionDirection.match(/^[tb]r-/)){ + this.clipNode.style.left = (view.width - nodeSize.width - 1 - scroll.left)+"px"; + }else if(this.positionDirection.match(/^[tb]l-/)){ + this.clipNode.style.left = 0 + "px"; + } + + this.clipNode.style.clip = "rect(0px, " + nodeSize.width + "px, " + nodeSize.height + "px, 0px)"; + + if(dojo.render.html.ie){ + if(!this.bgIframe){ + this.bgIframe = new dojo.html.BackgroundIframe(this.containerNode); + this.bgIframe.setZIndex(this.containerNode); + } + this.bgIframe.onResized(); + this.bgIframe.show(); + } + }, + + onSelect: function(e) { }, + + onScroll: function(){ + this.placeClip(); + }, + + show: function(){ + dojo.widget.Toaster.superclass.show.call(this); + + this.placeClip(); + + if(!this._scrollConnected){ + this._scrollConnected = true; + dojo.event.connect(window, "onscroll", this, "onScroll"); + } + }, + + hide: function(){ + dojo.widget.Toaster.superclass.hide.call(this); + + if(this._scrollConnected){ + this._scrollConnected = false; + dojo.event.disconnect(window, "onscroll", this, "onScroll"); + } + + dojo.html.setOpacity(this.containerNode, 1.0); + } + }, + "html" +); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toaster.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toggler.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toggler.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toggler.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toggler.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,24 @@ +dojo.provide("dojo.widget.Toggler"); +dojo.require("dojo.widget.*"); +dojo.require("dojo.event.*"); + +// clicking on this node shows/hides another widget + +dojo.widget.defineWidget( + "dojo.widget.Toggler", + dojo.widget.HtmlWidget, +{ + // Associated widget + targetId: '', + + fillInTemplate: function() { + dojo.event.connect(this.domNode, "onclick", this, "onClick"); + }, + + onClick: function() { + var pane = dojo.widget.byId(this.targetId); + if(!pane){ return; } + pane.explodeSrc = this.domNode; + pane.toggleShowing(); + } +}); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toggler.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toolbar.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toolbar.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toolbar.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toolbar.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,936 @@ +dojo.provide("dojo.widget.Toolbar"); + +dojo.require("dojo.widget.*"); +dojo.require("dojo.html.style"); + +/* ToolbarContainer + *******************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarContainer", + dojo.widget.HtmlWidget, +{ + isContainer: true, + + templateString: '
', + templateCssPath: dojo.uri.dojoUri("src/widget/templates/Toolbar.css"), + + getItem: function(name) { + if(name instanceof dojo.widget.ToolbarItem) { return name; } + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + var item = child.getItem(name); + if(item) { return item; } + } + } + return null; + }, + + getItems: function() { + var items = []; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + items = items.concat(child.getItems()); + } + } + return items; + }, + + enable: function() { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + child.enable.apply(child, arguments); + } + } + }, + + disable: function() { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + child.disable.apply(child, arguments); + } + } + }, + + select: function(name) { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + child.select(arguments); + } + } + }, + + deselect: function(name) { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + child.deselect(arguments); + } + } + }, + + getItemsState: function() { + var values = {}; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + dojo.lang.mixin(values, child.getItemsState()); + } + } + return values; + }, + + getItemsActiveState: function() { + var values = {}; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + dojo.lang.mixin(values, child.getItemsActiveState()); + } + } + return values; + }, + + getItemsSelectedState: function() { + var values = {}; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.Toolbar) { + dojo.lang.mixin(values, child.getItemsSelectedState()); + } + } + return values; + } +}); + +/* Toolbar + **********/ + +dojo.widget.defineWidget( + "dojo.widget.Toolbar", + dojo.widget.HtmlWidget, +{ + isContainer: true, + + templateString: '
', + + // given a node, tries to find it's toolbar item + _getItem: function(node) { + var start = new Date(); + var widget = null; + while(node && node != this.domNode) { + if(dojo.html.hasClass(node, "toolbarItem")) { + var widgets = dojo.widget.manager.getWidgetsByFilter(function(w) { return w.domNode == node; }); + if(widgets.length == 1) { + widget = widgets[0]; + break; + } else if(widgets.length > 1) { + dojo.raise("Toolbar._getItem: More than one widget matches the node"); + } + } + node = node.parentNode; + } + return widget; + }, + + _onmouseover: function(e) { + var widget = this._getItem(e.target); + if(widget && widget._onmouseover) { widget._onmouseover(e); } + }, + + _onmouseout: function(e) { + var widget = this._getItem(e.target); + if(widget && widget._onmouseout) { widget._onmouseout(e); } + }, + + _onclick: function(e) { + var widget = this._getItem(e.target); + if(widget && widget._onclick){ + widget._onclick(e); + } + }, + + _onmousedown: function(e) { + var widget = this._getItem(e.target); + if(widget && widget._onmousedown) { widget._onmousedown(e); } + }, + + _onmouseup: function(e) { + var widget = this._getItem(e.target); + if(widget && widget._onmouseup) { widget._onmouseup(e); } + }, + + addChild: function(item, pos, props) { + var widget = dojo.widget.ToolbarItem.make(item, null, props); + var ret = dojo.widget.Toolbar.superclass.addChild.call(this, widget, null, pos, null); + return ret; + }, + + push: function() { + for(var i = 0; i < arguments.length; i++) { + this.addChild(arguments[i]); + } + }, + + getItem: function(name) { + if(name instanceof dojo.widget.ToolbarItem) { return name; } + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem + && child._name == name) { return child; } + } + return null; + }, + + getItems: function() { + var items = []; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + items.push(child); + } + } + return items; + }, + + getItemsState: function() { + var values = {}; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + values[child._name] = { + selected: child._selected, + enabled: child._enabled + }; + } + } + return values; + }, + + getItemsActiveState: function() { + var values = this.getItemsState(); + for(var item in values) { + values[item] = values[item].enabled; + } + return values; + }, + + getItemsSelectedState: function() { + var values = this.getItemsState(); + for(var item in values) { + values[item] = values[item].selected; + } + return values; + }, + + enable: function() { + var items = arguments.length ? arguments : this.children; + for(var i = 0; i < items.length; i++) { + var child = this.getItem(items[i]); + if(child instanceof dojo.widget.ToolbarItem) { + child.enable(false, true); + } + } + }, + + disable: function() { + var items = arguments.length ? arguments : this.children; + for(var i = 0; i < items.length; i++) { + var child = this.getItem(items[i]); + if(child instanceof dojo.widget.ToolbarItem) { + child.disable(); + } + } + }, + + select: function() { + for(var i = 0; i < arguments.length; i++) { + var name = arguments[i]; + var item = this.getItem(name); + if(item) { item.select(); } + } + }, + + deselect: function() { + for(var i = 0; i < arguments.length; i++) { + var name = arguments[i]; + var item = this.getItem(name); + if(item) { item.disable(); } + } + }, + + setValue: function() { + for(var i = 0; i < arguments.length; i += 2) { + var name = arguments[i], value = arguments[i+1]; + var item = this.getItem(name); + if(item) { + if(item instanceof dojo.widget.ToolbarItem) { + item.setValue(value); + } + } + } + } +}); + +/* ToolbarItem hierarchy: + - ToolbarItem + - ToolbarButton + - ToolbarDialog + - ToolbarMenu + - ToolbarSeparator + - ToolbarSpace + - ToolbarFlexibleSpace +*/ + + +/* ToolbarItem + **************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarItem", + dojo.widget.HtmlWidget, +{ + templateString: '', + + _name: null, + getName: function() { return this._name; }, + setName: function(value) { return (this._name = value); }, + getValue: function() { return this.getName(); }, + setValue: function(value) { return this.setName(value); }, + + _selected: false, + isSelected: function() { return this._selected; }, + setSelected: function(is, force, preventEvent) { + if(!this._toggleItem && !force) { return; } + is = Boolean(is); + if(force || this._enabled && this._selected != is) { + this._selected = is; + this.update(); + if(!preventEvent) { + this._fireEvent(is ? "onSelect" : "onDeselect"); + this._fireEvent("onChangeSelect"); + } + } + }, + select: function(force, preventEvent) { + return this.setSelected(true, force, preventEvent); + }, + deselect: function(force, preventEvent) { + return this.setSelected(false, force, preventEvent); + }, + + _toggleItem: false, + isToggleItem: function() { return this._toggleItem; }, + setToggleItem: function(value) { this._toggleItem = Boolean(value); }, + + toggleSelected: function(force) { + return this.setSelected(!this._selected, force); + }, + + _enabled: true, + isEnabled: function() { return this._enabled; }, + setEnabled: function(is, force, preventEvent) { + is = Boolean(is); + if(force || this._enabled != is) { + this._enabled = is; + this.update(); + if(!preventEvent) { + this._fireEvent(this._enabled ? "onEnable" : "onDisable"); + this._fireEvent("onChangeEnabled"); + } + } + return this._enabled; + }, + enable: function(force, preventEvent) { + return this.setEnabled(true, force, preventEvent); + }, + disable: function(force, preventEvent) { + return this.setEnabled(false, force, preventEvent); + }, + toggleEnabled: function(force, preventEvent) { + return this.setEnabled(!this._enabled, force, preventEvent); + }, + + _icon: null, + getIcon: function() { return this._icon; }, + setIcon: function(value) { + var icon = dojo.widget.Icon.make(value); + if(this._icon) { + this._icon.setIcon(icon); + } else { + this._icon = icon; + } + var iconNode = this._icon.getNode(); + if(iconNode.parentNode != this.domNode) { + if(this.domNode.hasChildNodes()) { + this.domNode.insertBefore(iconNode, this.domNode.firstChild); + } else { + this.domNode.appendChild(iconNode); + } + } + return this._icon; + }, + + // TODO: update the label node (this.labelNode?) + _label: "", + getLabel: function() { return this._label; }, + setLabel: function(value) { + var ret = (this._label = value); + if(!this.labelNode) { + this.labelNode = document.createElement("span"); + this.domNode.appendChild(this.labelNode); + } + this.labelNode.innerHTML = ""; + this.labelNode.appendChild(document.createTextNode(this._label)); + this.update(); + return ret; + }, + + // fired from: setSelected, setEnabled, setLabel + update: function() { + if(this._enabled) { + dojo.html.removeClass(this.domNode, "disabled"); + if(this._selected) { + dojo.html.addClass(this.domNode, "selected"); + } else { + dojo.html.removeClass(this.domNode, "selected"); + } + } else { + this._selected = false; + dojo.html.addClass(this.domNode, "disabled"); + dojo.html.removeClass(this.domNode, "down"); + dojo.html.removeClass(this.domNode, "hover"); + } + this._updateIcon(); + }, + + _updateIcon: function() { + if(this._icon) { + if(this._enabled) { + if(this._cssHover) { + this._icon.hover(); + } else if(this._selected) { + this._icon.select(); + } else { + this._icon.enable(); + } + } else { + this._icon.disable(); + } + } + }, + + _fireEvent: function(evt) { + if(typeof this[evt] == "function") { + var args = [this]; + for(var i = 1; i < arguments.length; i++) { + args.push(arguments[i]); + } + this[evt].apply(this, args); + } + }, + + _onmouseover: function(e) { + if(!this._enabled) { return; } + dojo.html.addClass(this.domNode, "hover"); + this._fireEvent("onMouseOver"); + }, + + _onmouseout: function(e) { + dojo.html.removeClass(this.domNode, "hover"); + dojo.html.removeClass(this.domNode, "down"); + if(!this._selected) { + dojo.html.removeClass(this.domNode, "selected"); + } + this._fireEvent("onMouseOut"); + }, + + _onclick: function(e) { + // FIXME: buttons never seem to have this._enabled set to true on Opera 9 + // dojo.debug("widget:", this.widgetType, ":", this.getName(), ", enabled:", this._enabled); + if(this._enabled && !this._toggleItem) { + this._fireEvent("onClick"); + } + }, + + _onmousedown: function(e) { + if(e.preventDefault) { e.preventDefault(); } + if(!this._enabled) { return; } + dojo.html.addClass(this.domNode, "down"); + if(this._toggleItem) { + if(this.parent.preventDeselect && this._selected) { + return; + } + this.toggleSelected(); + } + this._fireEvent("onMouseDown"); + }, + + _onmouseup: function(e) { + dojo.html.removeClass(this.domNode, "down"); + this._fireEvent("onMouseUp"); + }, + + onClick: function() { }, + onMouseOver: function() { }, + onMouseOut: function() { }, + onMouseDown: function() { }, + onMouseUp: function() { }, + + fillInTemplate: function(args, frag) { + if(args.name) { this._name = args.name; } + if(args.selected) { this.select(); } + if(args.disabled) { this.disable(); } + if(args.label) { this.setLabel(args.label); } + if(args.icon) { this.setIcon(args.icon); } + if(args.toggleitem||args.toggleItem) { this.setToggleItem(true); } + } +}); + +dojo.widget.ToolbarItem.make = function(wh, whIsType, props) { + var item = null; + + if(wh instanceof Array) { + item = dojo.widget.createWidget("ToolbarButtonGroup", props); + item.setName(wh[0]); + for(var i = 1; i < wh.length; i++) { + item.addChild(wh[i]); + } + } else if(wh instanceof dojo.widget.ToolbarItem) { + item = wh; + } else if(wh instanceof dojo.uri.Uri) { + item = dojo.widget.createWidget("ToolbarButton", + dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())})); + } else if(whIsType) { + item = dojo.widget.createWidget(wh, props); + } else if(typeof wh == "string" || wh instanceof String) { + switch(wh.charAt(0)) { + case "|": + case "-": + case "/": + item = dojo.widget.createWidget("ToolbarSeparator", props); + break; + case " ": + if(wh.length == 1) { + item = dojo.widget.createWidget("ToolbarSpace", props); + } else { + item = dojo.widget.createWidget("ToolbarFlexibleSpace", props); + } + break; + default: + if(/\.(gif|jpg|jpeg|png)$/i.test(wh)) { + item = dojo.widget.createWidget("ToolbarButton", + dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())})); + } else { + item = dojo.widget.createWidget("ToolbarButton", + dojo.lang.mixin(props||{}, {label: wh.toString()})); + } + } + } else if(wh && wh.tagName && /^img$/i.test(wh.tagName)) { + item = dojo.widget.createWidget("ToolbarButton", + dojo.lang.mixin(props||{}, {icon: wh})); + } else { + item = dojo.widget.createWidget("ToolbarButton", + dojo.lang.mixin(props||{}, {label: wh.toString()})); + } + return item; +} + +/* ToolbarButtonGroup + *********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarButtonGroup", + dojo.widget.ToolbarItem, +{ + isContainer: true, + + templateString: '', + + // if a button has the same name, it will be selected + // if this is set to a number, the button at that index will be selected + defaultButton: "", + + postCreate: function() { + for (var i = 0; i < this.children.length; i++) { + this._injectChild(this.children[i]); + } + }, + + addChild: function(item, pos, props) { + var widget = dojo.widget.ToolbarItem.make(item, null, dojo.lang.mixin(props||{}, {toggleItem:true})); + var ret = dojo.widget.ToolbarButtonGroup.superclass.addChild.call(this, widget, null, pos, null); + this._injectChild(widget); + return ret; + }, + + _injectChild: function(widget) { + dojo.event.connect(widget, "onSelect", this, "onChildSelected"); + dojo.event.connect(widget, "onDeselect", this, "onChildDeSelected"); + if(widget._name == this.defaultButton + || (typeof this.defaultButton == "number" + && this.children.length-1 == this.defaultButton)) { + widget.select(false, true); + } + }, + + getItem: function(name) { + if(name instanceof dojo.widget.ToolbarItem) { return name; } + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem + && child._name == name) { return child; } + } + return null; + }, + + getItems: function() { + var items = []; + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + items.push(child); + } + } + return items; + }, + + onChildSelected: function(e) { + this.select(e._name); + }, + + onChildDeSelected: function(e) { + this._fireEvent("onChangeSelect", this._value); + }, + + enable: function(force, preventEvent) { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + child.enable(force, preventEvent); + if(child._name == this._value) { + child.select(force, preventEvent); + } + } + } + }, + + disable: function(force, preventEvent) { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + child.disable(force, preventEvent); + } + } + }, + + _value: "", + getValue: function() { return this._value; }, + + select: function(name, force, preventEvent) { + for(var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if(child instanceof dojo.widget.ToolbarItem) { + if(child._name == name) { + child.select(force, preventEvent); + this._value = name; + } else { + child.deselect(true, true); + } + } + } + if(!preventEvent) { + this._fireEvent("onSelect", this._value); + this._fireEvent("onChangeSelect", this._value); + } + }, + setValue: this.select, + + preventDeselect: false // if true, once you select one, you can't have none selected +}); + +/* ToolbarButton + ***********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarButton", + dojo.widget.ToolbarItem, +{ + fillInTemplate: function(args, frag) { + dojo.widget.ToolbarButton.superclass.fillInTemplate.call(this, args, frag); + dojo.html.addClass(this.domNode, "toolbarButton"); + if(this._icon) { + this.setIcon(this._icon); + } + if(this._label) { + this.setLabel(this._label); + } + + if(!this._name) { + if(this._label) { + this.setName(this._label); + } else if(this._icon) { + var src = this._icon.getSrc("enabled").match(/[\/^]([^\.\/]+)\.(gif|jpg|jpeg|png)$/i); + if(src) { this.setName(src[1]); } + } else { + this._name = this._widgetId; + } + } + } +}); + +/* ToolbarDialog + **********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarDialog", + dojo.widget.ToolbarButton, +{ + fillInTemplate: function (args, frag) { + dojo.widget.ToolbarDialog.superclass.fillInTemplate.call(this, args, frag); + dojo.event.connect(this, "onSelect", this, "showDialog"); + dojo.event.connect(this, "onDeselect", this, "hideDialog"); + }, + + showDialog: function (e) { + dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "deselect"); + }, + + hideDialog: function (e) { + dojo.event.disconnect(document, "onmousedown", this, "deselect"); + } + +}); + +/* ToolbarMenu + **********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarMenu", + dojo.widget.ToolbarDialog, + {} +); + +/* ToolbarMenuItem + ******************/ +dojo.widget.ToolbarMenuItem = function() { +} + +/* ToolbarSeparator + **********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarSeparator", + dojo.widget.ToolbarItem, +{ + templateString: '', + + defaultIconPath: new dojo.uri.dojoUri("src/widget/templates/buttons/sep.gif"), + + fillInTemplate: function(args, frag, skip) { + dojo.widget.ToolbarSeparator.superclass.fillInTemplate.call(this, args, frag); + this._name = this.widgetId; + if(!skip) { + if(!this._icon) { + this.setIcon(this.defaultIconPath); + } + this.domNode.appendChild(this._icon.getNode()); + } + }, + + // don't want events! + _onmouseover: null, + _onmouseout: null, + _onclick: null, + _onmousedown: null, + _onmouseup: null +}); + +/* ToolbarSpace + **********************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarSpace", + dojo.widget.ToolbarSeparator, +{ + fillInTemplate: function(args, frag, skip) { + dojo.widget.ToolbarSpace.superclass.fillInTemplate.call(this, args, frag, true); + if(!skip) { + dojo.html.addClass(this.domNode, "toolbarSpace"); + } + } +}); + +/* ToolbarSelect + ******************/ + +dojo.widget.defineWidget( + "dojo.widget.ToolbarSelect", + dojo.widget.ToolbarItem, +{ + templateString: '', + + fillInTemplate: function(args, frag) { + dojo.widget.ToolbarSelect.superclass.fillInTemplate.call(this, args, frag, true); + var keys = args.values; + var i = 0; + for(var val in keys) { + var opt = document.createElement("option"); + opt.setAttribute("value", keys[val]); + opt.innerHTML = val; + this.selectBox.appendChild(opt); + } + }, + + changed: function(e) { + this._fireEvent("onSetValue", this.selectBox.value); + }, + + setEnabled: function(is, force, preventEvent) { + var ret = dojo.widget.ToolbarSelect.superclass.setEnabled.call(this, is, force, preventEvent); + this.selectBox.disabled = !this._enabled; + return ret; + }, + + // don't want events! + _onmouseover: null, + _onmouseout: null, + _onclick: null, + _onmousedown: null, + _onmouseup: null +}); + +/* Icon + *********/ +// arguments can be IMG nodes, Image() instances or URLs -- enabled is the only one required +dojo.widget.Icon = function(enabled, disabled, hovered, selected){ + if(!arguments.length){ + // FIXME: should this be dojo.raise? + throw new Error("Icon must have at least an enabled state"); + } + var states = ["enabled", "disabled", "hovered", "selected"]; + var currentState = "enabled"; + var domNode = document.createElement("img"); + + this.getState = function(){ return currentState; } + this.setState = function(value){ + if(dojo.lang.inArray(states, value)){ + if(this[value]){ + currentState = value; + var img = this[currentState]; + if ((dojo.render.html.ie55 || dojo.render.html.ie60) && img.src && img.src.match(/[.]png$/i) ) { + domNode.width = img.width||img.offsetWidth; + domNode.height = img.height||img.offsetHeight; + domNode.setAttribute("src", dojo.uri.dojoUri("src/widget/templates/images/blank.gif").uri); + domNode.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+img.src+"',sizingMethod='image')"; + } else { + domNode.setAttribute("src", img.src); + } + } + }else{ + throw new Error("Invalid state set on Icon (state: " + value + ")"); + } + } + + this.setSrc = function(state, value){ + if(/^img$/i.test(value.tagName)){ + this[state] = value; + }else if(typeof value == "string" || value instanceof String + || value instanceof dojo.uri.Uri){ + this[state] = new Image(); + this[state].src = value.toString(); + } + return this[state]; + } + + this.setIcon = function(icon){ + for(var i = 0; i < states.length; i++){ + if(icon[states[i]]){ + this.setSrc(states[i], icon[states[i]]); + } + } + this.update(); + } + + this.enable = function(){ this.setState("enabled"); } + this.disable = function(){ this.setState("disabled"); } + this.hover = function(){ this.setState("hovered"); } + this.select = function(){ this.setState("selected"); } + + this.getSize = function(){ + return { + width: domNode.width||domNode.offsetWidth, + height: domNode.height||domNode.offsetHeight + }; + } + + this.setSize = function(w, h){ + domNode.width = w; + domNode.height = h; + return { width: w, height: h }; + } + + this.getNode = function(){ + return domNode; + } + + this.getSrc = function(state){ + if(state){ return this[state].src; } + return domNode.src||""; + } + + this.update = function(){ + this.setState(currentState); + } + + for(var i = 0; i < states.length; i++){ + var arg = arguments[i]; + var state = states[i]; + this[state] = null; + if(!arg){ continue; } + this.setSrc(state, arg); + } + + this.enable(); +} + +dojo.widget.Icon.make = function(a,b,c,d){ + for(var i = 0; i < arguments.length; i++){ + if(arguments[i] instanceof dojo.widget.Icon){ + return arguments[i]; + } + } + + return new dojo.widget.Icon(a,b,c,d); +} + +/* ToolbarColorDialog + ******************/ +dojo.widget.defineWidget( + "dojo.widget.ToolbarColorDialog", + dojo.widget.ToolbarDialog, +{ + palette: "7x10", + + fillInTemplate: function (args, frag) { + dojo.widget.ToolbarColorDialog.superclass.fillInTemplate.call(this, args, frag); + this.dialog = dojo.widget.createWidget("ColorPalette", {palette: this.palette}); + this.dialog.domNode.style.position = "absolute"; + + dojo.event.connect(this.dialog, "onColorSelect", this, "_setValue"); + }, + + _setValue: function(color) { + this._value = color; + this._fireEvent("onSetValue", color); + }, + + showDialog: function (e) { + dojo.widget.ToolbarColorDialog.superclass.showDialog.call(this, e); + var abs = dojo.html.getAbsolutePosition(this.domNode, true); + var y = abs.y + dojo.html.getBorderBox(this.domNode).height; + this.dialog.showAt(abs.x, y); + }, + + hideDialog: function (e) { + dojo.widget.ToolbarColorDialog.superclass.hideDialog.call(this, e); + this.dialog.hide(); + } +}); \ No newline at end of file Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/widget/Toolbar.js ------------------------------------------------------------------------------ svn:eol-style = native