You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2006/09/23 01:22:51 UTC
svn commit: r449122 [27/40] - in
/tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/
java/org/apache/tapestry/dojo/ java/org/apache/tapestry/dojo/form/
java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/form/
java/org/...
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,139 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.svg.HslColorPicker");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.HslColorPicker");
+dojo.require("dojo.math");
+dojo.require("dojo.svg");
+dojo.require("dojo.gfx.color");
+dojo.require("dojo.gfx.color.hsl");
+
+dojo.widget.defineWidget(
+ "dojo.widget.svg.HslColorPicker",
+ dojo.widget.HtmlWidget,
+ function(){
+ dojo.debug("warning: the HslColorPicker is not a finished widget, and is not yet ready for general use");
+ this.filterObject = {};
+ },
+{
+ hue: "0",
+ saturation: "0",
+ light: "0",
+ storedColor: "#0054aa",
+
+ // widget props
+ templatePath: dojo.uri.dojoUri("src/widget/templates/HslColorPicker.svg"),
+ fillInTemplate: function() {
+ this.height = "131px";
+ this.svgDoc = this.hueNode.ownerDocument;
+ this.leftGradientColorNode = this.hueNode.ownerDocument.getElementById("leftGradientColor");
+ this.rightGradientColorNode = this.hueNode.ownerDocument.getElementById("rightGradientColor");
+ this.hueNode.setAttributeNS(dojo.dom.xmlns.xlink, "href", dojo.uri.dojoUri("src/widget/templates/images/hue.png"));
+ var hsl = dojo.gfx.color.hex2hsl(this.storedColor);
+ this.hue = hsl[0];
+ this.saturation = hsl[1];
+ this.light = hsl[2];
+ this.setSaturationStopColors();
+ //this.setHueSlider();
+ //this.setSaturationLightSlider();
+ },
+ setSaturationStopColors: function() {
+ //this.leftGradientStopColor = "rgb(" + dojo.gfx.color.hsl2rgb(this.hue, 20, 50).join(", ") + ")";
+ //this.rightGradientStopColor = "rgb(" + dojo.gfx.color.hsl2rgb(this.hue, 100, 50).join(", ") + ")";
+ //this.leftGradientStopColor = dojo.gfx.color.hsl2hex(this.hue, 20, 50);
+ //this.rightGradientStopColor = dojo.gfx.color.hsl2hex(this.hue, 100, 50);
+ this.leftGradientStopColor = dojo.gfx.color.rgb2hex(this.hsl2rgb(this.hue, 0, 50));
+ this.rightGradientStopColor = dojo.gfx.color.rgb2hex(this.hsl2rgb(this.hue, 100, 50));
+ this.leftGradientColorNode.setAttributeNS(null,'stop-color',this.leftGradientStopColor);
+ this.rightGradientColorNode.setAttributeNS(null,'stop-color',this.rightGradientStopColor);
+ },
+ setHue: function(hue) {
+ this.hue = hue;
+ },
+ setHueSlider: function() {
+ // FIXME: need to add some padding around the picker so you can see the slider at the top and bottom of the picker)
+ this.hueSliderNode.setAttribute("y", parseInt((this.hue/360) * parseInt(this.height) - 2) + "px" );
+ },
+ setSaturationLight: function(saturation, light) {
+ this.saturation = saturation;
+ this.light = light;
+ },
+ setSaturationLightSlider: function() {
+ // TODO
+ },
+ onHueClick: function(evt) {
+ // get the position that was clicked on the element
+ // FIXME: handle document scrolling, offset
+ var yPosition = parseInt(evt.clientY) - parseInt(evt.target.getAttribute("y"));
+ this.setHue( 360 - parseInt(yPosition*(360/parseInt(this.height))) );
+ this.setSaturationStopColors();
+ this.setStoredColor(dojo.gfx.color.hsl2hex(this.hue, this.saturation, this.light));
+ },
+ onHueDrag: function(evt) {
+ // TODO
+ },
+ onSaturationLightClick: function(evt) {
+ // get the position that was clicked on the element
+ // FIXME: handle document scrolling, offset
+ var xPosition = parseInt(evt.clientX) - parseInt(evt.target.getAttribute("y"));
+ var yPosition = parseInt(evt.clientY) - parseInt(evt.target.getAttribute("y"));
+ var saturation = parseInt(parseInt(xPosition)*(101/106));
+ var light = parseInt(parseInt(yPosition)*(101/106));
+ this.setSaturationLight(saturation, light);
+ this.setStoredColor(dojo.gfx.color.hsl2hex(this.hue, this.saturation, this.light));
+ },
+ onSaturationLightDrag: function(evt) {
+ // TODO
+ },
+ getStoredColor: function() {
+ return this.storedColor;
+ },
+ setStoredColor: function(rgbHexColor) {
+ this.storedColor = rgbHexColor;
+ dojo.event.topic.publish("/" + this.widgetId + "/setStoredColor", this.filterObject);
+ },
+ hsl2rgb: function(hue, saturation, light)
+ {
+ // hsl2rgb in dojo.gfx.color did not behave hte way I expected, so
+ // I'm using some old code I wrote until I figure out what the issue is
+ // first, check to see if saturation = 0
+ function rgb(q1,q2,hue) {
+ if (hue>360) hue=hue-360;
+ if (hue<0) hue=hue+360;
+ if (hue<60) return (q1+(q2-q1)*hue/60);
+ else if (hue<180) return(q2);
+ else if (hue<240) return(q1+(q2-q1)*(240-hue)/60);
+ else return(q1);
+ }
+ this.rgb = rgb
+
+ if (saturation==0) {
+ return [Math.round(light*255/100), Math.round(light*255/100), Math.round(light*255/100)];
+ } else {
+ light = light/100;
+ saturation = saturation/100;
+ // check to see if light > 0.5
+ if ((light)<0.5) {
+ var temp2 = (light)*(1.0+saturation)
+ } else {
+ var temp2 = (light+saturation-(light*saturation))
+ }
+ var temp1 = 2.0*light - temp2;
+ var rgbcolor = [];
+ rgbcolor[0] = Math.round(rgb(temp1,temp2,parseInt(hue)+120)*255);
+ rgbcolor[1] = Math.round(rgb(temp1,temp2,hue)*255);
+ rgbcolor[2] = Math.round(rgb(temp1,temp2,parseInt(hue)-120)*255);
+ return rgbcolor;
+ }
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,166 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.html.util");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lfx.toggle");
+
+dojo.declare("dojo.widget.HtmlWidget", dojo.widget.DomWidget, {
+ widgetType: "HtmlWidget",
+
+ templateCssPath: null,
+ templatePath: null,
+
+ lang: "",
+ // for displaying/hiding widget
+ toggle: "plain",
+ toggleDuration: 150,
+
+ animationInProgress: false,
+
+ initialize: function(args, frag){
+ },
+
+ postMixInProperties: function(args, frag){
+ if(this.lang === ""){this.lang = null;}
+ // now that we know the setting for toggle, get toggle object
+ // (default to plain toggler if user specified toggler not present)
+ this.toggleObj =
+ dojo.lfx.toggle[this.toggle.toLowerCase()] || dojo.lfx.toggle.plain;
+ },
+
+ getContainerHeight: function(){
+ // NOTE: container height must be returned as the INNER height
+ dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
+ },
+
+ getContainerWidth: function(){
+ return this.parent.domNode.offsetWidth;
+ },
+
+ setNativeHeight: function(height){
+ var ch = this.getContainerHeight();
+ },
+
+ createNodesFromText: function(txt, wrap){
+ return dojo.html.createNodesFromText(txt, wrap);
+ },
+
+ destroyRendering: function(finalize){
+ try{
+ if(!finalize && this.domNode){
+ dojo.event.browser.clean(this.domNode);
+ }
+ this.domNode.parentNode.removeChild(this.domNode);
+ delete this.domNode;
+ }catch(e){ /* squelch! */ }
+ },
+
+ /////////////////////////////////////////////////////////
+ // Displaying/hiding the widget
+ /////////////////////////////////////////////////////////
+ isShowing: function(){
+ return dojo.html.isShowing(this.domNode);
+ },
+
+ toggleShowing: function(){
+ // dojo.html.toggleShowing(this.domNode);
+ if(this.isHidden){
+ this.show();
+ }else{
+ this.hide();
+ }
+ },
+
+ show: function(){
+ this.animationInProgress=true;
+ this.isHidden = false;
+ this.toggleObj.show(this.domNode, this.toggleDuration, null,
+ dojo.lang.hitch(this, this.onShow), this.explodeSrc);
+ },
+
+ // called after the show() animation has completed
+ onShow: function(){
+ this.animationInProgress=false;
+ this.checkSize();
+ },
+
+ hide: function(){
+ this.animationInProgress = true;
+ this.isHidden = true;
+ this.toggleObj.hide(this.domNode, this.toggleDuration, null,
+ dojo.lang.hitch(this, this.onHide), this.explodeSrc);
+ },
+
+ // called after the hide() animation has completed
+ onHide: function(){
+ this.animationInProgress=false;
+ },
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Sizing related methods
+ // If the parent changes size then for each child it should call either
+ // - resizeTo(): size the child explicitly
+ // - or checkSize(): notify the child the the parent has changed size
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Test if my size has changed.
+ // If width & height are specified then that's my new size; otherwise,
+ // query outerWidth/outerHeight of my domNode
+ _isResized: function(w, h){
+ // If I'm not being displayed then disregard (show() must
+ // check if the size has changed)
+ if(!this.isShowing()){ return false; }
+
+ // If my parent has been resized and I have style="height: 100%"
+ // or something similar then my size has changed too.
+ var wh = dojo.html.getMarginBox(this.domNode);
+ var width=w||wh.width;
+ var height=h||wh.height;
+ if(this.width == width && this.height == height){ return false; }
+
+ this.width=width;
+ this.height=height;
+ return true;
+ },
+
+ // Called when my parent has changed size, but my parent won't call resizeTo().
+ // This is useful if my size is height:100% or something similar.
+ // Also called whenever I am shown, because the first time I am shown I may need
+ // to do size calculations.
+ checkSize: function(){
+ if(!this._isResized()){ return; }
+ this.onResized();
+ },
+
+ // Explicitly set this widget's size (in pixels).
+ resizeTo: function(w, h){
+ if(!this._isResized(w,h)){ return; }
+ dojo.html.setMarginBox(this.domNode, { width: w, height: h });
+ this.onResized();
+ },
+
+ resizeSoon: function(){
+ if(this.isShowing()){
+ dojo.lang.setTimeout(this, this.onResized, 0);
+ }
+ },
+
+ // Called when my size has changed.
+ // Must notify children if their size has (possibly) changed
+ onResized: function(){
+ dojo.lang.forEach(this.children, function(child){ if(child.checkSize){child.checkSize();} });
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,208 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.InlineEditBox");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.gfx.color");
+dojo.require("dojo.string");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.layout");
+
+dojo.widget.defineWidget(
+ "dojo.widget.InlineEditBox",
+ dojo.widget.HtmlWidget,
+ function(){
+ // mutable objects need to be in constructor to give each instance its own copy
+ this.history = [];
+ },
+{
+ templatePath: dojo.uri.dojoUri("src/widget/templates/InlineEditBox.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/InlineEditBox.css"),
+
+ form: null,
+ editBox: null,
+ edit: null,
+ text: null,
+ textarea: null,
+ submitButton: null,
+ cancelButton: null,
+ mode: "text",
+
+ minWidth: 100, //px. minimum width of edit box
+ minHeight: 200, //px. minimum width of edit box, if it's a TA
+
+ editing: false,
+ textValue: "",
+ defaultText: "",
+ doFade: false,
+
+ onSave: function(newValue, oldValue){},
+ onUndo: function(value){},
+
+ postCreate: function(args, frag){
+ // put original node back in the document, and attach handlers
+ // which hide it and display the editor
+ this.editable = this.getFragNodeRef(frag);
+ dojo.html.insertAfter(this.editable, this.form);
+ dojo.event.connect(this.editable, "onmouseover", this, "onMouseOver");
+ dojo.event.connect(this.editable, "onmouseout", this, "onMouseOut");
+ dojo.event.connect(this.editable, "onclick", this, "beginEdit");
+
+ this.textValue = dojo.string.trim(this.editable.innerHTML);
+ if(dojo.string.trim(this.textValue).length == 0){
+ this.editable.innerHTML = this.defaultText;
+ }
+ },
+
+ onMouseOver: function(){
+ if(!this.editing){
+ if (!this.isEnabled){
+ dojo.html.addClass(this.editable, "editableRegionDisabled");
+ } else {
+ dojo.html.addClass(this.editable, "editableRegion");
+ if(this.mode == "textarea"){
+ dojo.html.addClass(this.editable, "editableTextareaRegion");
+ }
+ }
+ }
+
+ this.mouseover();
+ },
+
+ mouseover: function(e){
+ // TODO: How do we deprecate a function without going into overkill with debug statements?
+ // dojo.deprecated("onMouseOver should be used instead of mouseover to listen for mouse events");
+ },
+
+ onMouseOut: function(){
+ if(!this.editing){
+ dojo.html.removeClass(this.editable, "editableRegion");
+ dojo.html.removeClass(this.editable, "editableTextareaRegion");
+ dojo.html.removeClass(this.editable, "editableRegionDisabled");
+ }
+
+ this.mouseout();
+ },
+
+ mouseout: function(e){
+ // dojo.deprecated("onMouseOut should be used instead of mouseout to listen for mouse events");
+ },
+
+ // When user clicks the text, then start editing.
+ // Hide the text and display the form instead.
+ beginEdit: function(e){
+ if(this.editing || !this.isEnabled){ return; }
+ this.mouseout();
+ this.editing = true;
+
+ // setup the form's <input> or <textarea> field, as specified by mode
+ var ee = this[this.mode.toLowerCase()];
+ ee.value = dojo.string.trim(this.textValue);
+ ee.style.fontSize = dojo.html.getStyle(this.editable, "font-size");
+ ee.style.fontWeight = dojo.html.getStyle(this.editable, "font-weight");
+ ee.style.fontStyle = dojo.html.getStyle(this.editable, "font-style");
+ var bb = dojo.html.getBorderBox(this.editable);
+ ee.style.width = Math.max(bb.width, this.minWidth) + "px";
+ if(this.mode.toLowerCase()=="textarea"){
+ ee.style.display = "block";
+ ee.style.height = Math.max(bb.height, this.minHeight) + "px";
+ } else {
+ ee.style.display = "";
+ }
+
+ // show the edit form and hide the read only version of the text
+ this.form.style.display = "";
+ this.editable.style.display = "none";
+
+ ee.focus();
+ ee.select();
+ this.submitButton.disabled = true;
+ },
+
+ saveEdit: function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var ee = this[this.mode.toLowerCase()];
+ if((this.textValue != ee.value)&&
+ (dojo.string.trim(ee.value) != "")){
+ this.doFade = true;
+ this.history.push(this.textValue);
+ this.onSave(ee.value, this.textValue);
+ this.textValue = ee.value;
+ this.editable.innerHTML = "";
+ var textNode = document.createTextNode( this.textValue );
+ this.editable.appendChild( textNode );
+ }else{
+ this.doFade = false;
+ }
+ this.finishEdit(e);
+ },
+
+ cancelEdit: function(e){
+ if(!this.editing){ return false; }
+ this.editing = false;
+ this.form.style.display="none";
+ this.editable.style.display = "";
+ return true;
+ },
+
+ finishEdit: function(e){
+ if(!this.cancelEdit(e)){ return; }
+ if(this.doFade) {
+ dojo.lfx.highlight(this.editable, dojo.gfx.color.hex2rgb("#ffc"), 700).play(300);
+ }
+ this.doFade = false;
+ },
+
+ setText: function(txt){
+ // sets the text without informing the server
+ var tt = dojo.string.trim(txt);
+ this.textValue = tt
+ this.editable.innerHTML = tt;
+ },
+
+ undo: function(){
+ if(this.history.length > 0){
+ var value = this.history.pop();
+ this.editable.innerHTML = value;
+ this.textValue = value;
+ this.onUndo(value);
+ }
+ },
+
+ checkForValueChange: function(){
+ var ee = this[this.mode.toLowerCase()];
+ if((this.textValue != ee.value)&&
+ (dojo.string.trim(ee.value) != "")){
+ this.submitButton.disabled = false;
+ }
+ },
+
+ disable: function(){
+ this.submitButton.disabled = true;
+ this.cancelButton.disabled = true;
+ var ee = this[this.mode.toLowerCase()];
+ ee.disabled = true;
+
+ dojo.widget.Widget.prototype.disable.call(this);
+ },
+
+ enable: function(){
+ this.checkForValueChange();
+ this.cancelButton.disabled = false;
+ var ee = this[this.mode.toLowerCase()];
+ ee.disabled = false;
+
+ dojo.widget.Widget.prototype.enable.call(this);
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+//
+// this widget provides Delphi-style panel layout semantics
+//
+
+dojo.provide("dojo.widget.LayoutContainer");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.html.layout");
+
+dojo.widget.defineWidget(
+ "dojo.widget.LayoutContainer",
+ dojo.widget.HtmlWidget,
+{
+ isContainer: true,
+
+ layoutChildPriority: 'top-bottom',
+
+ postCreate: function(){
+ dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+ },
+
+ addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
+ dojo.widget.LayoutContainer.superclass.addChild.call(this, child, overrideContainerNode, pos, ref, insertIndex);
+ dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+ },
+
+ removeChild: function(pane){
+ dojo.widget.LayoutContainer.superclass.removeChild.call(this,pane);
+ dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+ },
+
+ onResized: function(){
+ dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+ },
+
+ show: function(){
+ // If this node was created while display=="none" then it
+ // hasn't been laid out yet. Do that now.
+ this.domNode.style.display="";
+ this.checkSize();
+ this.domNode.style.display="none";
+ this.domNode.style.visibility="";
+
+ dojo.widget.LayoutContainer.superclass.show.call(this);
+ }
+});
+
+// This argument can be specified for the children of a LayoutContainer.
+// Since any widget can be specified as a LayoutContainer child, mix it
+// into the base widget class. (This is a hack, but it's effective.)
+dojo.lang.extend(dojo.widget.Widget, {
+ layoutAlign: 'none'
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,41 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+//
+// a div that loads from a URL. (Similar to an iframe, but
+// it's in the same environment as the main window)
+//
+
+dojo.provide("dojo.widget.LinkPane");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html.style");
+
+dojo.widget.defineWidget(
+ "dojo.widget.LinkPane",
+ dojo.widget.ContentPane,
+{
+ // I'm using a template because the user may specify the input as
+ // <a href="foo.html">label</a>, in which case we need to get rid of the
+ // <a> because we don't want a link.
+ templateString: '<div class="dojoLinkPane"></div>',
+
+ fillInTemplate: function(args, frag){
+ var source = this.getFragNodeRef(frag);
+
+ // If user has specified node contents, they become the label
+ // (the link must be plain text)
+ this.label += source.innerHTML;
+
+ var source = this.getFragNodeRef(frag);
+ dojo.html.copyStyle(this.domNode, source);
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,359 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.Manager");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.event.*");
+
+// Manager class
+dojo.widget.manager = new function(){
+ this.widgets = [];
+ this.widgetIds = [];
+
+ // map of widgetId-->widget for widgets without parents (top level widgets)
+ this.topWidgets = {};
+
+ var widgetTypeCtr = {};
+ var renderPrefixCache = [];
+
+ this.getUniqueId = function (widgetType) {
+ return widgetType + "_" + (widgetTypeCtr[widgetType] != undefined ?
+ ++widgetTypeCtr[widgetType] : widgetTypeCtr[widgetType] = 0);
+ }
+
+ this.add = function(widget){
+ //dojo.profile.start("dojo.widget.manager.add");
+ this.widgets.push(widget);
+ // Opera9 uses ID (caps)
+ if(!widget.extraArgs["id"]){
+ widget.extraArgs["id"] = widget.extraArgs["ID"];
+ }
+ // FIXME: the rest of this method is very slow!
+ if(widget.widgetId == ""){
+ if(widget["id"]){
+ widget.widgetId = widget["id"];
+ }else if(widget.extraArgs["id"]){
+ widget.widgetId = widget.extraArgs["id"];
+ }else{
+ widget.widgetId = this.getUniqueId(widget.widgetType);
+ }
+ }
+ if(this.widgetIds[widget.widgetId]){
+ dojo.debug("widget ID collision on ID: "+widget.widgetId);
+ }
+ this.widgetIds[widget.widgetId] = widget;
+ // Widget.destroy already calls removeById(), so we don't need to
+ // connect() it here
+ //dojo.profile.end("dojo.widget.manager.add");
+ }
+
+ this.destroyAll = function(){
+ for(var x=this.widgets.length-1; x>=0; x--){
+ try{
+ // this.widgets[x].destroyChildren();
+ this.widgets[x].destroy(true);
+ delete this.widgets[x];
+ }catch(e){ }
+ }
+ }
+
+ // FIXME: we should never allow removal of the root widget until all others
+ // are removed!
+ this.remove = function(widgetIndex){
+ if(dojo.lang.isNumber(widgetIndex)){
+ var tw = this.widgets[widgetIndex].widgetId;
+ delete this.widgetIds[tw];
+ this.widgets.splice(widgetIndex, 1);
+ }else{
+ this.removeById(widgetIndex);
+ }
+ }
+
+ // FIXME: suboptimal performance
+ this.removeById = function(id) {
+ if(!dojo.lang.isString(id)){
+ id = id["widgetId"];
+ if(!id){ dojo.debug("invalid widget or id passed to removeById"); return; }
+ }
+ for (var i=0; i<this.widgets.length; i++){
+ if(this.widgets[i].widgetId == id){
+ this.remove(i);
+ break;
+ }
+ }
+ }
+
+ this.getWidgetById = function(id){
+ if(dojo.lang.isString(id)){
+ return this.widgetIds[id];
+ }
+ return id;
+ }
+
+ this.getWidgetsByType = function(type){
+ var lt = type.toLowerCase();
+ var getType = (type.indexOf(":") < 0 ?
+ function(x) { return x.widgetType.toLowerCase(); } :
+ function(x) { return x.getNamespacedType(); }
+ );
+ var ret = [];
+ dojo.lang.forEach(this.widgets, function(x){
+ if(getType(x) == lt){ret.push(x);}
+ });
+ return ret;
+ }
+
+ this.getWidgetsByFilter = function(unaryFunc, onlyOne){
+ var ret = [];
+ dojo.lang.every(this.widgets, function(x){
+ if(unaryFunc(x)){
+ ret.push(x);
+ if(onlyOne){return false;}
+ }
+ return true;
+ });
+ return (onlyOne ? ret[0] : ret);
+ }
+
+ this.getAllWidgets = function() {
+ return this.widgets.concat();
+ }
+
+ // added, trt 2006-01-20
+ this.getWidgetByNode = function(/* DOMNode */ node){
+ var w=this.getAllWidgets();
+ node = dojo.byId(node);
+ for(var i=0; i<w.length; i++){
+ if(w[i].domNode==node){
+ return w[i];
+ }
+ }
+ return null;
+ }
+
+ // shortcuts, baby
+ this.byId = this.getWidgetById;
+ this.byType = this.getWidgetsByType;
+ this.byFilter = this.getWidgetsByFilter;
+ this.byNode = this.getWidgetByNode;
+
+ // map of previousally discovered implementation names to constructors
+ var knownWidgetImplementations = {};
+
+ // support manually registered widget packages
+ var widgetPackages = ["dojo.widget"];
+ for (var i=0; i<widgetPackages.length; i++) {
+ // convenience for checking if a package exists (reverse lookup)
+ widgetPackages[widgetPackages[i]] = true;
+ }
+
+ this.registerWidgetPackage = function(pname) {
+ if(!widgetPackages[pname]){
+ widgetPackages[pname] = true;
+ widgetPackages.push(pname);
+ }
+ }
+
+ this.getWidgetPackageList = function() {
+ return dojo.lang.map(widgetPackages, function(elt) { return(elt!==true ? elt : undefined); });
+ }
+
+ this.getImplementation = function(widgetName, ctorObject, mixins, ns){
+ // try and find a name for the widget
+ var impl = this.getImplementationName(widgetName, ns);
+ if(impl){
+ // var tic = new Date();
+ var ret = ctorObject ? new impl(ctorObject) : new impl();
+ // dojo.debug(new Date() - tic);
+ return ret;
+ }
+ }
+
+ function buildPrefixCache() {
+ for(var renderer in dojo.render){
+ if(dojo.render[renderer]["capable"] === true){
+ var prefixes = dojo.render[renderer].prefixes;
+ for(var i=0; i<prefixes.length; i++){
+ renderPrefixCache.push(prefixes[i].toLowerCase());
+ }
+ }
+ }
+ // make sure we don't HAVE to prefix widget implementation names
+ // with anything to get them to render
+ //renderPrefixCache.push("");
+ // empty prefix is included automatically
+ }
+
+ findImplementationInModule = function(lowerCaseWidgetName, module){
+ if(!module){return null;}
+ for(var i=0, l=renderPrefixCache.length, widgetModule; i<=l; i++){
+ widgetModule = (i<l ? module[renderPrefixCache[i]] : module);
+ if(!widgetModule){continue;}
+ for(var name in widgetModule){
+ if(name.toLowerCase() == lowerCaseWidgetName){
+ return widgetModule[name];
+ }
+ }
+ }
+ return null;
+ }
+
+ findImplementation = function(lowerCaseWidgetName, moduleName){
+ // locate registered widget module
+ var module = dojo.evalObjPath(moduleName, false);
+ // locate a widget implementation in the registered module for our current rendering environment
+ return (module ? findImplementationInModule(lowerCaseWidgetName, module) : null);
+ }
+
+ this.getImplementationName = function(widgetName, ns){
+ /*
+ * Locate an implementation (constructor) for 'widgetName' in namespace 'ns'
+ * widgetNames are case INSENSITIVE
+ *
+ * 1. Return value from implementation cache, if available, for quick turnaround.
+ * 2. Locate a namespace registration for 'ns'
+ * 3. If no namespace found, register the conventional one (ns.widget)
+ * 4. Allow the namespace resolver (if any) to load a module for this widget.
+ * 5. Permute the widget name and capable rendering prefixes to locate, cache, and return
+ * an appropriate widget implementation.
+ * 6. If no implementation is found, attempt to load the namespace manifest,
+ * and then look again for an implementation to cache and return.
+ * 7. Use the deprecated widgetPackages registration system to attempt to locate the widget
+ * 8. Fail
+ */
+ var lowerCaseWidgetName = widgetName.toLowerCase();
+
+ // default to dojo namespace
+ ns=ns||"dojo";
+ // use cache if available
+ var imps = knownWidgetImplementations[ns] || (knownWidgetImplementations[ns]={});
+ //if(!knownWidgetImplementations[ns]){knownWidgetImplementations[ns]={};}
+ var impl = imps[lowerCaseWidgetName];
+ if(impl){
+ return impl;
+ }
+
+ // (one time) store a list of the render prefixes we are capable of rendering
+ if(!renderPrefixCache.length){
+ buildPrefixCache();
+ }
+
+ // lookup namespace
+ var nsObj = dojo["namespace"].get(ns);
+ if(!nsObj){
+ // default to <ns>.widget by convention
+ dojo.namespace.register(ns, ns + '.widget');
+ nsObj = dojo["namespace"].get(ns);
+ }
+
+ // allow the namespace to resolve the widget module
+ if(nsObj){nsObj.resolve(widgetName);}
+
+ // locate a widget implementation in the registered module for our current rendering environment
+ impl = findImplementation(lowerCaseWidgetName, nsObj.module);
+ if(impl){return(imps[lowerCaseWidgetName] = impl)};
+
+ // try to load a manifest to resolve this implemenation
+ nsObj = dojo["namespace"].require(ns);
+ if((nsObj)&&(nsObj.resolver)){
+ nsObj.resolve(widgetName);
+ impl = findImplementation(lowerCaseWidgetName, nsObj.module);
+ if(impl){return(imps[lowerCaseWidgetName] = impl)};
+ }
+
+ // this is an error condition under new rules
+ dojo.deprecated('dojo.widget.Manager.getImplementationName',
+ 'Could not locate widget implementation for "' + widgetName + '" in "' + nsObj.module + '" registered to namespace "' + nsObj.name + '". '
+ + "Developers must specify correct namespaces for all non-Dojo widgets", "0.5");
+
+ // backward compat: if the user has not specified any namespace and their widget is not in dojo.widget.*
+ // search registered widget packages [sic]
+ // note: registerWidgetPackage itself is now deprecated
+ for(var i=0; i<widgetPackages.length; i++){
+ impl = findImplementation(lowerCaseWidgetName, widgetPackages[i]);
+ if(impl){return(imps[lowerCaseWidgetName] = impl)};
+ }
+
+ throw new Error('Could not locate widget implementation for "' + widgetName + '" in "' + nsObj.module + '" registered to namespace "' + nsObj.name + '"');
+ }
+
+ // FIXME: does it even belong in this module?
+ // NOTE: this method is implemented by DomWidget.js since not all
+ // hostenv's would have an implementation.
+ /*this.getWidgetFromPrimitive = function(baseRenderType){
+ dojo.unimplemented("dojo.widget.manager.getWidgetFromPrimitive");
+ }
+
+ this.getWidgetFromEvent = function(nativeEvt){
+ dojo.unimplemented("dojo.widget.manager.getWidgetFromEvent");
+ }*/
+
+ // Catch window resize events and notify top level widgets
+ this.resizing=false;
+ this.onWindowResized = function(){
+ if(this.resizing){
+ return; // duplicate event
+ }
+ try{
+ this.resizing=true;
+ for(var id in this.topWidgets){
+ var child = this.topWidgets[id];
+ if(child.checkSize ){
+ child.checkSize();
+ }
+ }
+ }catch(e){
+ }finally{
+ this.resizing=false;
+ }
+ }
+ if(typeof window != "undefined") {
+ dojo.addOnLoad(this, 'onWindowResized'); // initial sizing
+ dojo.event.connect(window, 'onresize', this, 'onWindowResized'); // window resize
+ }
+
+ // FIXME: what else?
+};
+
+(function(){
+ var dw = dojo.widget;
+ var dwm = dw.manager;
+ var h = dojo.lang.curry(dojo.lang, "hitch", dwm);
+ var g = function(oldName, newName){
+ dw[(newName||oldName)] = h(oldName);
+ }
+ // copy the methods from the default manager (this) to the widget namespace
+ g("add", "addWidget");
+ g("destroyAll", "destroyAllWidgets");
+ g("remove", "removeWidget");
+ g("removeById", "removeWidgetById");
+ g("getWidgetById");
+ g("getWidgetById", "byId");
+ g("getWidgetsByType");
+ g("getWidgetsByFilter");
+ g("getWidgetsByType", "byType");
+ g("getWidgetsByFilter", "byFilter");
+ g("getWidgetByNode", "byNode");
+ dw.all = function(n){
+ var widgets = dwm.getAllWidgets.apply(dwm, arguments);
+ if(arguments.length > 0) {
+ return widgets[n];
+ }
+ return widgets;
+ }
+ g("registerWidgetPackage");
+ g("getImplementation", "getWidgetImplementation");
+ g("getImplementationName", "getWidgetImplementationName");
+
+ dw.widgets = dwm.widgets;
+ dw.widgetIds = dwm.widgetIds;
+ dw.root = dwm.root;
+})();
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Menu2.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Menu2.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Menu2.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Menu2.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,700 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.Menu2");
+
+dojo.require("dojo.widget.PopupContainer");
+
+dojo.widget.defineWidget(
+ "dojo.widget.PopupMenu2",
+ dojo.widget.PopupContainer,
+ function(){
+ this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it becomes context menu for those nodes
+
+ this.eventNames = {
+ open: ""
+ };
+ },
+{
+ templateCssString: "",
+ currentSubmenuTrigger: null,
+ snarfChildDomOutput: true,
+
+ eventNaming: "default",
+
+ templateString: '<table class="dojoPopupMenu2" border=0 cellspacing=0 cellpadding=0 style="display: none;"><tbody dojoAttachPoint="containerNode"></tbody></table>',
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/Menu2.css"),
+
+ submenuDelay: 500,
+ submenuOverlap: 5,
+ contextMenuForWindow: false,
+ openEvent: null,
+
+ _highlighted_option: null,
+
+ initialize: function(args, frag) {
+ if (this.eventNaming == "default") {
+ for (var eventName in this.eventNames) {
+ this.eventNames[eventName] = this.widgetId+"/"+eventName;
+ }
+ }
+ },
+
+ postCreate: function(){
+ if (this.contextMenuForWindow){
+ var doc = dojo.body();
+ this.bindDomNode(doc);
+ } else if ( this.targetNodeIds.length > 0 ){
+ dojo.lang.forEach(this.targetNodeIds, this.bindDomNode, this);
+ }
+
+ this.subscribeSubitemsOnOpen();
+ },
+
+ subscribeSubitemsOnOpen: function() {
+ var subItems = this.getChildrenOfType(dojo.widget.MenuItem2);
+
+ for(var i=0; i<subItems.length; i++) {
+ dojo.event.topic.subscribe(this.eventNames.open, subItems[i], "menuOpen")
+ }
+ },
+
+ // get open event for current menu
+ getTopOpenEvent: function() {
+ var menu = this;
+ while (menu.parentPopup){ menu = menu.parentPopup; }
+ return menu.openEvent;
+ },
+
+ // attach menu to given node
+ bindDomNode: function(node){
+ node = dojo.byId(node);
+
+ var win = dojo.html.getElementWindow(node);
+ if(dojo.html.isTag(node,'iframe') == 'iframe'){
+ win = dojo.html.iframeContentWindow(node);
+ node = dojo.withGlobal(win, dojo.body);
+ }
+ // fixes node so that it supports oncontextmenu if not natively supported, Konqueror, Opera more?
+ dojo.widget.Menu2.OperaAndKonqFixer.fixNode(node);
+
+ dojo.event.kwConnect({
+ srcObj: node,
+ srcFunc: "oncontextmenu",
+ targetObj: this,
+ targetFunc: "onOpen",
+ once: true
+ });
+
+ //normal connect does not work if document.designMode is on in FF, use addListener instead
+ if(dojo.render.html.moz && win.document.designMode.toLowerCase() == 'on'){
+ dojo.event.browser.addListener(node, "contextmenu", dojo.lang.hitch(this, "onOpen"));
+ }
+ dojo.widget.PopupManager.registerWin(win);
+ },
+
+ // detach menu from given node
+ unBindDomNode: function(nodeName){
+ var node = dojo.byId(nodeName);
+ dojo.event.kwDisconnect({
+ srcObj: node,
+ srcFunc: "oncontextmenu",
+ targetObj: this,
+ targetFunc: "onOpen",
+ once: true
+ });
+
+ // cleans a fixed node, konqueror and opera
+ dojo.widget.Menu2.OperaAndKonqFixer.cleanNode(node);
+ },
+
+ moveToNext: function(evt){
+ this.highlightOption(1);
+ return true; //do not pass to parent menu
+ },
+
+ moveToPrevious: function(evt){
+ this.highlightOption(-1);
+ return true; //do not pass to parent menu
+ },
+
+ moveToParentMenu: function(evt){
+ if(this._highlighted_option && this.parentPopup){
+ //only process event in the focused menu
+ //and its immediate parentPopup to support
+ //MenuBar2
+ if(evt._menu2UpKeyProcessed){
+ return true; //do not pass to parent menu
+ }else{
+ this._highlighted_option.onUnhover();
+ this.closeSubpopup();
+ evt._menu2UpKeyProcessed = true;
+ }
+ }
+ return false;
+ },
+
+ moveToChildMenu: function(evt){
+ if(this._highlighted_option && this._highlighted_option.submenuId){
+ this._highlighted_option._onClick(true);
+ return true; //do not pass to parent menu
+ }
+ return false;
+ },
+
+ selectCurrentItem: function(evt){
+ if(this._highlighted_option){
+ this._highlighted_option._onClick();
+ return true;
+ }
+ return false;
+ },
+
+ //return true to stop the event being processed by the
+ //parent popupmenu
+ processKey: function(evt){
+ if(evt.ctrlKey || evt.altKey || !evt.key){ return false; }
+
+ var rval = false;
+ switch(evt.key){
+ case evt.KEY_DOWN_ARROW:
+ rval = this.moveToNext(evt);
+ break;
+ case evt.KEY_UP_ARROW:
+ rval = this.moveToPrevious(evt);
+ break;
+ case evt.KEY_RIGHT_ARROW:
+ rval = this.moveToChildMenu(evt);
+ break;
+ case evt.KEY_LEFT_ARROW:
+ rval = this.moveToParentMenu(evt);
+ break;
+ case " ": //fall through
+ case evt.KEY_ENTER:
+ if(rval = this.selectCurrentItem(evt)){
+ break;
+ }
+ //fall through
+ case evt.KEY_ESCAPE:
+ dojo.widget.PopupManager.currentMenu.close();
+ rval = true;
+ break;
+ }
+
+ return rval;
+ },
+
+ findValidItem: function(dir, curItem){
+ if(curItem){
+ curItem = dir>0 ? curItem.getNextSibling() : curItem.getPreviousSibling();
+ }
+
+ for(var i=0; i < this.children.length; ++i){
+ if(!curItem){
+ curItem = dir>0 ? this.children[0] : this.children[this.children.length-1];
+ }
+ //find next/previous visible menu item, not including separators
+ if(curItem.onHover && curItem.isShowing()){
+ return curItem;
+ }
+ curItem = dir>0 ? curItem.getNextSibling() : curItem.getPreviousSibling();
+ }
+ },
+
+ highlightOption: function(dir){
+ var item;
+ // || !this._highlighted_option.parentNode
+ if((!this._highlighted_option)){
+ item = this.findValidItem(dir);
+ }else{
+ item = this.findValidItem(dir, this._highlighted_option);
+ }
+ if(item){
+ if(this._highlighted_option) {
+ this._highlighted_option.onUnhover();
+ }
+ item.onHover();
+ dojo.html.scrollIntoView(item.domNode);
+ // navigate into the item table and select the first caption tag
+ try {
+ var node = dojo.html.getElementsByClass("dojoMenuItem2Label", item.domNode)[0];
+ node.focus();
+ } catch(e) { }
+ }
+ },
+
+ // User defined function to handle clicks on an item
+ onItemClick: function(item) {},
+
+ close: function(force){
+ if(this.animationInProgress){
+ dojo.widget.PopupMenu2.superclass.close.apply(this, arguments);
+ return;
+ }
+
+ if(this._highlighted_option){
+ this._highlighted_option.onUnhover();
+ }
+
+ dojo.widget.PopupMenu2.superclass.close.apply(this, arguments);
+ },
+
+ //overwrite the default one
+ closeSubpopup: function(force){
+ if (this.currentSubpopup == null){ return; }
+
+ this.currentSubpopup.close(force);
+ this.currentSubpopup = null;
+
+ this.currentSubmenuTrigger.is_open = false;
+ this.currentSubmenuTrigger.closedSubmenu(force);
+ this.currentSubmenuTrigger = null;
+ },
+
+ // open the menu to the right of the current menu item
+ openSubmenu: function(submenu, from_item){
+ var fromPos = dojo.html.getAbsolutePosition(from_item.domNode, true);
+ var our_w = dojo.html.getMarginBox(this.domNode).width;
+ var x = fromPos.x + our_w - this.submenuOverlap;
+ var y = fromPos.y;
+
+ //the following is set in open, so we do not need it
+ //this.currentSubpopup = submenu;
+ submenu.open(x, y, this, from_item.domNode);
+
+ this.currentSubmenuTrigger = from_item;
+ this.currentSubmenuTrigger.is_open = true;
+ },
+
+ onOpen: function(e){
+ this.openEvent = e;
+ if(e["target"]){
+ this.openedForWindow = dojo.html.getElementWindow(e.target);
+ }else{
+ this.openedForWindow = null;
+ }
+ var x = e.pageX, y = e.pageY;
+
+ var win = dojo.html.getElementWindow(e.target);
+ var iframe = win._frameElement || win.frameElement;
+ if(iframe){
+ var cood = dojo.html.abs(iframe, true);
+ x += cood.x - dojo.withGlobal(win, dojo.html.getScroll).left;
+ y += cood.y - dojo.withGlobal(win, dojo.html.getScroll).top;
+ }
+ this.open(x, y, null, [x, y]);
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+});
+
+dojo.widget.defineWidget(
+ "dojo.widget.MenuItem2",
+ dojo.widget.HtmlWidget,
+ function(){
+ this.eventNames = {
+ engage: ""
+ };
+ },
+{
+ // Make 4 columns
+ // icon, label, accelerator-key, and right-arrow indicating sub-menu
+ templateString:
+ '<tr class="dojoMenuItem2" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick: _onClick; onKey:onKey;">'
+ +'<td><div class="${this.iconClass}" style="${this.iconStyle}"></div></td>'
+ +'<td tabIndex="-1" class="dojoMenuItem2Label">${this.caption}</td>'
+ +'<td class="dojoMenuItem2Accel">${this.accelKey}</td>'
+ +'<td><div class="dojoMenuItem2Submenu" style="display:${this.arrowDisplay};"></div></td>'
+ +'</tr>',
+
+ //
+ // internal settings
+ //
+
+ is_hovering: false,
+ hover_timer: null,
+ is_open: false,
+ topPosition: 0,
+
+ //
+ // options
+ //
+
+ caption: 'Untitled',
+ accelKey: '',
+ iconSrc: '',
+ iconClass: 'dojoMenuItem2Icon',
+ submenuId: '',
+ disabled: false,
+ eventNaming: "default",
+ highlightClass: 'dojoMenuItem2Hover',
+
+ postMixInProperties: function(){
+ this.iconStyle="";
+ if (this.iconSrc){
+ if ((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4) == ".png") && (dojo.render.html.ie55 || dojo.render.html.ie60)){
+ this.iconStyle="filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='image')";
+ }else{
+ this.iconStyle="background-image: url("+this.iconSrc+")";
+ }
+ }
+ this.arrowDisplay = this.submenuId ? 'block' : 'none';
+ dojo.widget.MenuItem2.superclass.postMixInProperties.apply(this, arguments);
+ },
+
+ fillInTemplate: function(){
+ dojo.html.disableSelection(this.domNode);
+
+ if (this.disabled){
+ this.setDisabled(true);
+ }
+
+ if (this.eventNaming == "default") {
+ for (var eventName in this.eventNames) {
+ this.eventNames[eventName] = this.widgetId+"/"+eventName;
+ }
+ }
+ },
+
+ onHover: function(){
+ //this is to prevent some annoying behavior when both mouse and keyboard are used
+ this.onUnhover();
+
+ if (this.is_hovering){ return; }
+ if (this.is_open){ return; }
+
+ if(this.parent._highlighted_option){
+ this.parent._highlighted_option.onUnhover();
+ }
+ this.parent.closeSubpopup();
+ this.parent._highlighted_option = this;
+ dojo.widget.PopupManager.setFocusedMenu(this.parent);
+
+ this.highlightItem();
+
+ if (this.is_hovering){ this.stopSubmenuTimer(); }
+ this.is_hovering = true;
+ this.startSubmenuTimer();
+ },
+
+ onUnhover: function(){
+ if(!this.is_open){ this.unhighlightItem(); }
+
+ this.is_hovering = false;
+
+ this.parent._highlighted_option = null;
+
+ if(this.parent.parentPopup){
+ dojo.widget.PopupManager.setFocusedMenu(this.parent.parentPopup);
+ }
+
+ this.stopSubmenuTimer();
+ },
+
+ // Internal function for clicks
+ _onClick: function(focus){
+ var displayingSubMenu = false;
+ if (this.disabled){ return false; }
+
+ if (this.submenuId){
+ if (!this.is_open){
+ this.stopSubmenuTimer();
+ this.openSubmenu();
+ }
+ displayingSubMenu = true;
+ }else{
+ // for some browsers the onMouseOut doesn't get called (?), so call it manually
+ this.onUnhover(); //only onUnhover when no submenu is available
+ this.parent.closeAll(true);
+ }
+
+ // user defined handler for click
+ this.onClick();
+
+ dojo.event.topic.publish(this.eventNames.engage, this);
+
+ if(displayingSubMenu && focus){
+ dojo.widget.getWidgetById(this.submenuId).highlightOption(1);
+ }
+ return;
+ },
+
+ // User defined function to handle clicks
+ // this default function call the parent
+ // menu's onItemClick
+ onClick: function() {
+ this.parent.onItemClick(this);
+ },
+
+ highlightItem: function(){
+ dojo.html.addClass(this.domNode, this.highlightClass);
+ },
+
+ unhighlightItem: function(){
+ dojo.html.removeClass(this.domNode, this.highlightClass);
+ },
+
+ startSubmenuTimer: function(){
+ this.stopSubmenuTimer();
+
+ if (this.disabled){ return; }
+
+ var self = this;
+ var closure = function(){ return function(){ self.openSubmenu(); } }();
+
+ this.hover_timer = dojo.lang.setTimeout(closure, this.parent.submenuDelay);
+ },
+
+ stopSubmenuTimer: function(){
+ if (this.hover_timer){
+ dojo.lang.clearTimeout(this.hover_timer);
+ this.hover_timer = null;
+ }
+ },
+
+ openSubmenu: function(){
+ // first close any other open submenu
+ this.parent.closeSubpopup();
+
+ var submenu = dojo.widget.getWidgetById(this.submenuId);
+ if (submenu){
+ this.parent.openSubmenu(submenu, this);
+ }
+ },
+
+ closedSubmenu: function(){
+ this.onUnhover();
+ },
+
+ setDisabled: function(value){
+ this.disabled = value;
+
+ if (this.disabled){
+ dojo.html.addClass(this.domNode, 'dojoMenuItem2Disabled');
+ }else{
+ dojo.html.removeClass(this.domNode, 'dojoMenuItem2Disabled');
+ }
+ },
+
+ enable: function(){
+ this.setDisabled(false);
+ },
+
+ disable: function(){
+ this.setDisabled(true);
+ },
+
+ menuOpen: function(message) {
+ }
+
+});
+
+dojo.widget.defineWidget(
+ "dojo.widget.MenuSeparator2",
+ dojo.widget.HtmlWidget,
+{
+ templateString: '<tr class="dojoMenuSeparator2"><td colspan=4>'
+ +'<div class="dojoMenuSeparator2Top"></div>'
+ +'<div class="dojoMenuSeparator2Bottom"></div>'
+ +'</td></tr>',
+
+ postCreate: function(){
+ dojo.html.disableSelection(this.domNode);
+ }
+});
+
+dojo.widget.defineWidget(
+ "dojo.widget.MenuBar2",
+ dojo.widget.PopupMenu2,
+{
+ menuOverlap: 2,
+
+ templateString: '<div class="dojoMenuBar2" tabIndex="0"><table class="dojoMenuBar2Client"><tr dojoAttachPoint="containerNode"></tr></table></div>',
+
+ close: function(force){
+ if(this._highlighted_option){
+ this._highlighted_option.onUnhover();
+ }
+
+ this.closeSubpopup(force);
+ },
+
+ processKey: function(evt){
+ if(evt.ctrlKey || evt.altKey){ return false; }
+
+ if (!dojo.html.hasClass(evt.target,"dojoMenuBar2")) { return false; }
+ var rval = false;
+
+ switch(evt.key){
+ case evt.KEY_DOWN_ARROW:
+ rval = this.moveToChildMenu(evt);
+ break;
+ case evt.KEY_UP_ARROW:
+ rval = this.moveToParentMenu(evt);
+ break;
+ case evt.KEY_RIGHT_ARROW:
+ rval = this.moveToNext(evt);
+ break;
+ case evt.KEY_LEFT_ARROW:
+ rval = this.moveToPrevious(evt);
+ break;
+ default:
+ rval = this.inherited("processKey", [evt]);
+ break;
+ }
+
+ return rval;
+ },
+
+ postCreate: function(){
+ this.inherited("postCreate");
+ dojo.widget.PopupManager.opened(this);
+ this.isShowingNow = true;
+ },
+
+ /*
+ * override PopupMenu2 to open the submenu below us rather than to our right
+ */
+ openSubmenu: function(submenu, from_item){
+ var fromPos = dojo.html.getAbsolutePosition(from_item.domNode, true);
+ var ourPos = dojo.html.getAbsolutePosition(this.domNode, true);
+ var our_h = dojo.html.getBorderBox(this.domNode).height;
+ var x = fromPos.x;
+ var y = ourPos.y + our_h - this.menuOverlap;
+
+ submenu.open(x, y, this, from_item.domNode);
+
+ this.currentSubmenuTrigger = from_item;
+ this.currentSubmenuTrigger.is_open = true;
+ }
+});
+
+dojo.widget.defineWidget(
+ "dojo.widget.MenuBarItem2",
+ dojo.widget.MenuItem2,
+{
+ templateString:
+ '<td class="dojoMenuBarItem2" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick: _onClick;">'
+ +'<span><span>${this.caption}</span>${this.caption}</span>'
+ +'</td>',
+
+ highlightClass: 'dojoMenuBarItem2Hover',
+
+ setDisabled: function(value){
+ this.disabled = value;
+ if (this.disabled){
+ dojo.html.addClass(this.domNode, 'dojoMenuBarItem2Disabled');
+ }else{
+ dojo.html.removeClass(this.domNode, 'dojoMenuBarItem2Disabled');
+ }
+ }
+});
+
+
+// ************************** make contextmenu work in konqueror and opera *********************
+dojo.widget.Menu2.OperaAndKonqFixer = new function(){
+ var implement = true;
+ var delfunc = false;
+
+ /** dom event check
+ *
+ * make a event and dispatch it and se if it calls function below,
+ * if it indeed is supported and we dont need to implement our own
+ */
+
+ // gets called if we have support for oncontextmenu
+ if (!dojo.lang.isFunction(dojo.doc().oncontextmenu)){
+ dojo.doc().oncontextmenu = function(){
+ implement = false;
+ delfunc = true;
+ }
+ }
+
+ if (dojo.doc().createEvent){ // moz, safari has contextmenu event, need to do livecheck on this env.
+ try {
+ var e = dojo.doc().createEvent("MouseEvents");
+ e.initMouseEvent("contextmenu", 1, 1, dojo.global(), 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, null);
+ dojo.doc().dispatchEvent(e);
+ } catch (e) {/* assume not supported */}
+ } else {
+ // IE no need to implement custom contextmenu
+ implement = false;
+ }
+
+ // clear this one if it wasn't there before
+ if (delfunc){
+ delete dojo.doc().oncontextmenu;
+ }
+ /***** end dom event check *****/
+
+
+ /**
+ * this fixes a dom node by attaching a custom oncontextmenu function that gets called when apropriate
+ * @param node a dom node
+ *
+ * no returns
+ */
+ this.fixNode = function(node){
+ if (implement){
+ // attach stub oncontextmenu function
+ if (!dojo.lang.isFunction(node.oncontextmenu)){
+ node.oncontextmenu = function(e){/*stub*/}
+ }
+
+ // attach control function for oncontextmenu
+ if (dojo.render.html.opera){
+ // opera
+ // listen to ctrl-click events
+ node._menufixer_opera = function(e){
+ if (e.ctrlKey){
+ this.oncontextmenu(e);
+ }
+ };
+
+ dojo.event.connect(node, "onclick", node, "_menufixer_opera");
+
+ } else {
+ // konqueror
+ // rightclick, listen to mousedown events
+ node._menufixer_konq = function(e){
+ if (e.button==2 ){
+ e.preventDefault(); // need to prevent browsers menu
+ this.oncontextmenu(e);
+ }
+ };
+
+ dojo.event.connect(node, "onmousedown", node, "_menufixer_konq");
+ }
+ }
+ }
+
+ /**
+ * this cleans up a fixed node, prevent memoryleak?
+ * @param node node to clean
+ *
+ * no returns
+ */
+ this.cleanNode = function(node){
+ if (implement){
+ // checks needed if we gets a non fixed node
+ if (node._menufixer_opera){
+ dojo.event.disconnect(node, "onclick", node, "_menufixer_opera");
+ delete node._menufixer_opera;
+ } else if(node._menufixer_konq){
+ dojo.event.disconnect(node, "onmousedown", node, "_menufixer_konq");
+ delete node._menufixer_konq;
+ }
+ if (node.oncontextmenu){
+ delete node.oncontextmenu;
+ }
+ }
+ }
+};
\ No newline at end of file
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Menu2.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/MonthlyCalendar.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/MonthlyCalendar.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/MonthlyCalendar.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/MonthlyCalendar.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,181 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.MonthlyCalendar");
+dojo.require("dojo.date.common");
+dojo.require("dojo.date.format");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.DatePicker");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.*");
+
+dojo.widget.defineWidget(
+ "dojo.widget.MonthlyCalendar",
+ dojo.widget.DatePicker,
+ function(){
+ this.iCalendars = [];
+ },
+{
+ dayWidth: 'wide',
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/MonthlyCalendar.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/MonthlyCalendar.css"),
+
+ cache: function() {
+ },
+
+ addCalendar: function(/* dojo.iCalendar */ cal) {
+ dojo.debug("Adding Calendar");
+ this.iCalendars.push(cal);
+ dojo.debug("Starting init");
+ this.initUI();
+ dojo.debug("done init");
+ },
+
+ createDayContents: function(node,mydate) {
+ dojo.html.removeChildren(node);
+ node.appendChild(document.createTextNode(mydate.getDate()));
+ for(var x=0; x<this.iCalendars.length; x++) {
+ var evts = this.iCalendars[x].getEvents(mydate);
+ if ((dojo.lang.isArray(evts)) && (evts.length>0)) {
+ for(var y=0;y<evts.length;y++) {
+ var el = document.createElement("div");
+ dojo.html.addClass(el, "dojoMonthlyCalendarEvent");
+ el.appendChild(document.createTextNode(evts[y].summary.value));
+ el.width = dojo.html.getContentBox(node).width;
+ node.appendChild(el);
+ }
+ }
+ }
+ },
+
+ initUI: function() {
+ var dayLabels = dojo.date.getNames('days', this.dayWidth, 'standAlone', this.lang);
+ var dayLabelNodes = this.dayLabelsRow.getElementsByTagName("td");
+ for(var i=0; i<7; i++) {
+ dayLabelNodes.item(i).innerHTML = dayLabels[i];
+ }
+
+ this.selectedIsUsed = false;
+ this.currentIsUsed = false;
+ var currentClassName = "";
+ var previousDate = new Date();
+ var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
+ var currentCalendarNode;
+ // set hours of date such that there is no chance of rounding error due to
+ // time change in local time zones
+ previousDate.setHours(8);
+ var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
+ var lastDay = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date + 42, 8);
+
+ if (this.iCalendars.length > 0) {
+ for (var x=0; x<this.iCalendars.length;x++) {
+ this.iCalendars[x].preComputeRecurringEvents(lastDay);
+ }
+ }
+
+ if(this.firstSaturday.date < 7) {
+ // this means there are days to show from the previous month
+ var dayInWeek = 6;
+ for (var i=this.firstSaturday.date; i>0; i--) {
+ currentCalendarNode = calendarNodes.item(dayInWeek);
+ this.createDayContents(currentCalendarNode, nextDate);
+
+ dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
+ dayInWeek--;
+ previousDate = nextDate;
+ nextDate = this.incrementDate(nextDate, false);
+ }
+ for(var i=dayInWeek; i>-1; i--) {
+ currentCalendarNode = calendarNodes.item(i);
+
+ this.createDayContents(currentCalendarNode, nextDate);
+
+ dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
+ previousDate = nextDate;
+ nextDate = this.incrementDate(nextDate, false);
+ }
+ } else {
+ nextDate.setDate(1);
+ for(var i=0; i<7; i++) {
+ currentCalendarNode = calendarNodes.item(i);
+ this.createDayContents(currentCalendarNode, nextDate);
+ dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
+ previousDate = nextDate;
+ nextDate = this.incrementDate(nextDate, true);
+ }
+ }
+ previousDate.setDate(this.firstSaturday.date);
+ previousDate.setMonth(this.firstSaturday.month);
+ previousDate.setFullYear(this.firstSaturday.year);
+ nextDate = this.incrementDate(previousDate, true);
+ var count = 7;
+ currentCalendarNode = calendarNodes.item(count);
+ while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
+ this.createDayContents(currentCalendarNode, nextDate);
+ dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
+ currentCalendarNode = calendarNodes.item(++count);
+ previousDate = nextDate;
+ nextDate = this.incrementDate(nextDate, true);
+ }
+
+ while(count < 42) {
+ this.createDayContents(currentCalendarNode, nextDate);
+ dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
+ currentCalendarNode = calendarNodes.item(++count);
+ previousDate = nextDate;
+ nextDate = this.incrementDate(nextDate, true);
+ }
+ this.setMonthLabel(this.firstSaturday.month);
+ this.setYearLabels(this.firstSaturday.year);
+ }
+});
+
+dojo.widget.MonthlyCalendar.util= new function() {
+
+ this.toRfcDate = function(jsDate) {
+ if(!jsDate) {
+ jsDate = this.today;
+ }
+ var year = jsDate.getFullYear();
+ var month = jsDate.getMonth() + 1;
+ if (month < 10) {
+ month = "0" + month.toString();
+ }
+ var date = jsDate.getDate();
+ if (date < 10) {
+ date = "0" + date.toString();
+ }
+ // because this is a date picker and not a time picker, we treat time
+ // as zero
+ return year + "-" + month + "-" + date + "T00:00:00+00:00";
+ }
+
+ this.fromRfcDate = function(rfcDate) {
+ var tempDate = rfcDate.split("-");
+ if(tempDate.length < 3) {
+ return new Date();
+ }
+ // fullYear, month, date
+ return new Date(parseInt(tempDate[0]), (parseInt(tempDate[1], 10) - 1), parseInt(tempDate[2].substr(0,2), 10));
+ }
+
+//Note: redundant with dojo.widget.DatePicker.util
+ this.initFirstSaturday = function(month, year) {
+ if(!month) {
+ month = this.date.getMonth();
+ }
+ if(!year) {
+ year = this.date.getFullYear();
+ }
+ var firstOfMonth = new Date(year, month, 1);
+ return {year: year, month: month, date: 7 - firstOfMonth.getDay()};
+ }
+}
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/MonthlyCalendar.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/PageContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/PageContainer.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/PageContainer.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/PageContainer.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,182 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.PageContainer");
+
+dojo.require("dojo.lang.func");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.selection");
+
+// A PageContainer is a container that has multiple panes, but shows only
+// one pane at a time.
+//
+// Publishes topics <widgetId>-addPane, <widgetId>-removePane, and <widgetId>-selectPane
+//
+// Can be base class for TabContainer, Wizard, etc.
+dojo.widget.defineWidget("dojo.widget.PageContainer", dojo.widget.HtmlWidget, {
+ isContainer: true,
+
+ // Boolean
+ // if true, change the size of my currently displayed child to match my size
+ doLayout: true,
+
+ templateString: "<div dojoAttachPoint='containerNode'></div>",
+
+ // String
+ // id of the initially shown page
+ selectedPage: "",
+
+ fillInTemplate: function(args, frag) {
+ // Copy style info from input node to output node
+ var source = this.getFragNodeRef(frag);
+ dojo.html.copyStyle(this.domNode, source);
+ dojo.widget.PageContainer.superclass.fillInTemplate.call(this, args, frag);
+ },
+
+ postCreate: function(args, frag) {
+ // Setup each page panel
+ dojo.lang.forEach(this.children, this._setupPage, this);
+
+ // Display the selected page
+ if(this.selectedPageWidget){
+ this.selectPage(this.selectedPageWidget, true);
+ }
+ },
+
+ addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
+ this._setupPage(child);
+ dojo.widget.PageContainer.superclass.addChild.call(this,child, overrideContainerNode, pos, ref, insertIndex);
+
+ // in case the page labels have overflowed from one line to two lines
+ this.onResized();
+ },
+
+ _setupPage: function(page){
+ // Summary: Add the given pane to this page container
+ page.domNode.style.display="none";
+
+ if(!this.selectedPageWidget || this.selectedPage==page.widgetId || page.selected || (this.children.length==0)){
+ // Deselect old page and select new one
+ // We do this instead of calling selectPage in this case, because other wise other widgets
+ // listening for addChild and selectPage can run into a race condition
+ if(this.selectedPageWidget){
+ this._hidePage(this.selectedPageWidget);
+ }
+ this.selectedPageWidget = page;
+ this._showPage(page);
+
+ } else {
+ this._hidePage(page);
+ }
+
+ dojo.html.addClass(page.domNode, "selected");
+
+ // publish the addPane event for panes added via addChild(), and the original panes too
+ dojo.event.topic.publish(this.widgetId+"-addPane", page);
+ },
+
+ removeChild: function(/* Widget */page){
+ dojo.widget.PageContainer.superclass.removeChild.call(this, page);
+
+ // this will notify any tablists to remove a button; do this first because it may affect sizing
+ dojo.event.topic.publish(this.widgetId+"-removePane", page);
+
+ if (this.selectedPageWidget === page) {
+ this.selectedPageWidget = undefined;
+ if (this.children.length > 0) {
+ this.selectPage(this.children[0], true);
+ }
+ }
+ },
+
+ selectPage: function(/* Widget */ page, /* Boolean */ _noRefresh, /* Widget */ callingWidget){
+ // summary
+ // Show the given widget (which must be one of my children)
+ page = dojo.widget.byId(page);
+ this.correspondingPageButton = callingWidget;
+
+ // Deselect old page and select new one
+ if(this.selectedPageWidget){
+ this._hidePage(this.selectedPageWidget);
+ }
+ this.selectedPageWidget = page;
+ this._showPage(page, _noRefresh);
+ page.isFirstPage = (page == this.children[0]);
+ page.isLastPage = (page == this.children[this.children.length-1]);
+ dojo.event.topic.publish(this.widgetId+"-selectPane", page);
+ },
+
+ nextPage: function(){
+ // Summary: advance to next page
+ var index = dojo.lang.find(this.children, this.selectedPageWidget);
+ this.selectPage(this.children[index+1]);
+ },
+
+ previousPage: function(){
+ // Summary: go back to previous page
+ var index = dojo.lang.find(this.children, this.selectedPageWidget);
+ this.selectPage(this.children[index-1]);
+ },
+
+ onResized: function(){
+ // Summary: called when any page is shown, to make it fit the container correctly
+ if(this.doLayout && this.selectedPageWidget){
+ with(this.selectedPageWidget.domNode.style){
+ top = dojo.html.getPixelValue(this.containerNode, "padding-top", true);
+ left = dojo.html.getPixelValue(this.containerNode, "padding-left", true);
+ }
+ var content = dojo.html.getContentBox(this.containerNode);
+ this.selectedPageWidget.resizeTo(content.width, content.height);
+ }
+ },
+
+ _showPage: function(page, _noRefresh) {
+ page.selected=true;
+
+ // size the current page (in case this is the first time it's being shown, or I have been resized)
+ this.onResized();
+
+ // make sure we dont refresh onClose and on postCreate
+ // speeds up things a bit when using refreshOnShow and fixes #646
+ if(_noRefresh && page.refreshOnShow){
+ var tmp = page.refreshOnShow;
+ page.refreshOnShow = false;
+ page.show();
+ page.refreshOnShow = tmp;
+ }else{
+ page.show();
+ }
+ },
+
+ _hidePage: function(page) {
+ page.selected=false;
+ page.hide();
+ },
+
+ closePage: function(page) {
+ // Summary: callback when user tries to remove page from PageContainer
+ var onc = page.extraArgs.onClose || page.extraArgs.onclose;
+ var fcn = dojo.lang.isFunction(onc) ? onc : window[onc];
+ var remove = dojo.lang.isFunction(fcn) ? fcn(this,page) : true;
+ if(remove) {
+ this.removeChild(page);
+ // makes sure we can clean up executeScripts in ContentPane onUnLoad
+ page.destroy();
+ }
+ },
+
+ destroy: function(){
+ dojo.event.topic.destroy(this.widgetId+"-addPane");
+ dojo.event.topic.destroy(this.widgetId+"-removePane");
+ dojo.event.topic.destroy(this.widgetId+"-selectPane");
+ this.inherited("destroy");
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/PageContainer.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Parse.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Parse.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Parse.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Parse.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,333 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.Parse");
+
+dojo.require("dojo.widget.Manager");
+dojo.require("dojo.dom");
+dojo.require("dojo.namespace");
+
+//
+// dojoML parser should be moved out of 'widget', codifying the difference between a 'component'
+// and a 'widget'. A 'component' being anything that can be generated from a tag.
+//
+// a particular dojoML tag would be handled by a registered tagHandler with a hook for a default handler
+// if the widget system is loaded, a widget builder would be attach itself as the default handler
+//
+// widget tags are no longer registered themselves:
+// they are now arbitrarily namespaced, so we cannot register them all, and the non-prefixed portions
+// are no longer guaranteed unique
+//
+// therefore dojo.widget.tags should go with this parser code out of the widget module
+//
+
+dojo.widget.Parse = function(fragment){
+ this.propertySetsList = [];
+ this.fragment = fragment;
+
+ this.createComponents = function(frag, parentComp){
+ var comps = [];
+ var built = false;
+ // if we have items to parse/create at this level, do it!
+ try{
+ if((frag)&&(frag["tagName"])&&(frag!=frag["nodeRef"])){
+
+ // these are in fact, not ever for widgets per-se anymore,
+ // but for other markup elements (aka components)
+ var djTags = dojo.widget.tags;
+
+ // we split so that you can declare multiple
+ // non-destructive components from the same ctor node
+ var tna = String(frag["tagName"]).split(";");
+ for(var x=0; x<tna.length; x++){
+ var ltn = (tna[x].replace(/^\s+|\s+$/g, "")).toLowerCase();
+ // FIXME: unsure what this does
+ frag.tagName = ltn;
+ if(djTags[ltn]){
+ built = true;
+ var ret = djTags[ltn](frag, this, parentComp, frag["index"]);
+ comps.push(ret);
+ } else {
+ // we require a namespace prefix, default to dojo:
+ if (ltn.indexOf(":") == -1){
+ ltn = "dojo:"+ltn;
+ }
+ // FIXME: handling failure condition correctly?
+ //var ret = djTags[ltn](frag, this, parentComp, frag["index"]);
+ var ret = dojo.widget.buildWidgetFromParseTree(ltn, frag, this, parentComp, frag["index"]);
+ if (ret) {
+ built = true;
+ comps.push(ret);
+ }
+ }
+ }
+ }
+ }catch(e){
+ // dojo.debug("dojo.widget.Parse: error:" + e);
+ throw e;
+ // IE is such a bitch sometimes
+ }
+ // if there's a sub-frag, build widgets from that too
+ if(!built){
+ comps = comps.concat(this.createSubComponents(frag, parentComp));
+ }
+ return comps;
+ }
+
+ /* createSubComponents recurses over a raw JavaScript object structure,
+ and calls the corresponding handler for its normalized tagName if it exists
+ */
+ this.createSubComponents = function(fragment, parentComp){
+ var frag, comps = [];
+ for(var item in fragment){
+ frag = fragment[item];
+ if ((frag)&&(typeof frag == "object")&&(frag!=fragment.nodeRef)&&(frag!=fragment["tagName"])){
+ comps = comps.concat(this.createComponents(frag, parentComp));
+ }
+ }
+ return comps;
+ }
+
+ /* parsePropertySets checks the top level of a raw JavaScript object
+ structure for any propertySets. It stores an array of references to
+ propertySets that it finds.
+ */
+ this.parsePropertySets = function(fragment){
+ return [];
+ /*
+ var propertySets = [];
+ for(var item in fragment){
+ if((fragment[item]["tagName"] == "dojo:propertyset")){
+ propertySets.push(fragment[item]);
+ }
+ }
+ // FIXME: should we store these propertySets somewhere for later retrieval
+ this.propertySetsList.push(propertySets);
+ return propertySets;
+ */
+ }
+
+ /* parseProperties checks a raw JavaScript object structure for
+ properties, and returns an array of properties that it finds.
+ */
+ this.parseProperties = function(fragment){
+ var properties = {};
+ for(var item in fragment){
+ // FIXME: need to check for undefined?
+ // case: its a tagName or nodeRef
+ if((fragment[item] == fragment["tagName"])||(fragment[item] == fragment.nodeRef)){
+ // do nothing
+ }else{
+ if((fragment[item]["tagName"])&&
+ (dojo.widget.tags[fragment[item].tagName.toLowerCase()])){
+ // TODO: it isn't a property or property set, it's a fragment,
+ // so do something else
+ // FIXME: needs to be a better/stricter check
+ // TODO: handle xlink:href for external property sets
+ }else if((fragment[item][0])&&(fragment[item][0].value!="")&&(fragment[item][0].value!=null)){
+ try{
+ // FIXME: need to allow more than one provider
+ if(item.toLowerCase() == "dataprovider") {
+ var _this = this;
+ this.getDataProvider(_this, fragment[item][0].value);
+ properties.dataProvider = this.dataProvider;
+ }
+ properties[item] = fragment[item][0].value;
+ var nestedProperties = this.parseProperties(fragment[item]);
+ // FIXME: this kind of copying is expensive and inefficient!
+ for(var property in nestedProperties){
+ properties[property] = nestedProperties[property];
+ }
+ }catch(e){ dojo.debug(e); }
+ }
+ }
+ }
+ return properties;
+ }
+
+ /* getPropertySetById returns the propertySet that matches the provided id
+ */
+
+ this.getDataProvider = function(objRef, dataUrl){
+ // FIXME: this is currently sync. To make this async, we made need to move
+ //this step into the widget ctor, so that it is loaded when it is needed
+ // to populate the widget
+ dojo.io.bind({
+ url: dataUrl,
+ load: function(type, evaldObj){
+ if(type=="load"){
+ objRef.dataProvider = evaldObj;
+ }
+ },
+ mimetype: "text/javascript",
+ sync: true
+ });
+ }
+
+
+ this.getPropertySetById = function(propertySetId){
+ for(var x = 0; x < this.propertySetsList.length; x++){
+ if(propertySetId == this.propertySetsList[x]["id"][0].value){
+ return this.propertySetsList[x];
+ }
+ }
+ return "";
+ }
+
+ /* getPropertySetsByType returns the propertySet(s) that match(es) the
+ * provided componentClass
+ */
+ this.getPropertySetsByType = function(componentType){
+ var propertySets = [];
+ for(var x=0; x < this.propertySetsList.length; x++){
+ var cpl = this.propertySetsList[x];
+ var cpcc = cpl["componentClass"]||cpl["componentType"]||null;
+ var propertySetId = this.propertySetsList[x]["id"][0].value;
+ if((cpcc)&&(propertySetId == cpcc[0].value)){
+ propertySets.push(cpl);
+ }
+ }
+ return propertySets;
+ }
+
+ /* getPropertySets returns the propertySet for a given component fragment
+ */
+ this.getPropertySets = function(fragment){
+ var ppl = "dojo:propertyproviderlist";
+ var propertySets = [];
+ var tagname = fragment["tagName"];
+ if(fragment[ppl]){
+ var propertyProviderIds = fragment[ppl].value.split(" ");
+ // FIXME: should the propertyProviderList attribute contain #
+ // syntax for reference to ids or not?
+ // FIXME: need a better test to see if this is local or external
+ // FIXME: doesn't handle nested propertySets, or propertySets that
+ // just contain information about css documents, etc.
+ for(var propertySetId in propertyProviderIds){
+ if((propertySetId.indexOf("..")==-1)&&(propertySetId.indexOf("://")==-1)){
+ // get a reference to a propertySet within the current parsed structure
+ var propertySet = this.getPropertySetById(propertySetId);
+ if(propertySet != ""){
+ propertySets.push(propertySet);
+ }
+ }else{
+ // FIXME: add code to parse and return a propertySet from
+ // another document
+ // alex: is this even necessaray? Do we care? If so, why?
+ }
+ }
+ }
+ // we put the typed ones first so that the parsed ones override when
+ // iteration happens.
+ return (this.getPropertySetsByType(tagname)).concat(propertySets);
+ }
+
+ /*
+ nodeRef is the node to be replaced... in the future, we might want to add
+ an alternative way to specify an insertion point
+
+ componentName is the expected dojo widget name, i.e. Button of ContextMenu
+
+ properties is an object of name value pairs
+ namespace is the namespace of the widget. Defaults to "dojo"
+ */
+ this.createComponentFromScript = function(nodeRef, componentName, properties, ns){
+ properties.fastMixIn = true;
+ // FIXME: we pulled it apart and now we put it back together ...
+ var ltn = (ns || "dojo") + ":" + componentName.toLowerCase();
+ if(dojo.widget.tags[ltn]){
+ return [dojo.widget.tags[ltn](properties, this, null, null, properties)];
+ }
+ return [dojo.widget.buildWidgetFromParseTree(ltn, properties, this, null, null, properties)];
+ }
+}
+
+dojo.widget._parser_collection = {"dojo": new dojo.widget.Parse() };
+dojo.widget.getParser = function(name){
+ if(!name){ name = "dojo"; }
+ if(!this._parser_collection[name]){
+ this._parser_collection[name] = new dojo.widget.Parse();
+ }
+ return this._parser_collection[name];
+}
+
+/**
+ * Creates widget.
+ *
+ * @param name The name of the widget to create with optional namespace prefix,
+ * e.g."ns:widget", namespace defaults to "dojo".
+ * @param props Key-Value pairs of properties of the widget
+ * @param refNode If the position argument is specified, this node is used as
+ * a reference for inserting this node into a DOM tree; else
+ * the widget becomes the domNode
+ * @param position The position to insert this widget's node relative to the
+ * refNode argument
+ * @return The new Widget object
+ */
+
+dojo.widget.createWidget = function(name, props, refNode, position){
+ var isNode = false;
+ var isNameStr = (typeof name == "string");
+ if(isNameStr){
+ var pos = name.indexOf(":");
+ var ns = (pos > -1) ? name.substring(0,pos) : "dojo";
+ if(pos > -1){ name = name.substring(pos+1); }
+ var lowerCaseName = name.toLowerCase();
+ var namespacedName = ns + ":" + lowerCaseName;
+ isNode = (dojo.byId(name) && (!dojo.widget.tags[namespacedName]));
+ }
+
+ if((arguments.length == 1) && ((isNode)||(!isNameStr))){
+ // we got a DOM node
+ var xp = new dojo.xml.Parse();
+ // FIXME: we should try to find the parent!
+ var tn = (isNode) ? dojo.byId(name) : name;
+ return dojo.widget.getParser().createComponents(xp.parseElement(tn, null, true))[0];
+ }
+
+ function fromScript(placeKeeperNode, name, props, ns){
+ props[namespacedName] = {
+ dojotype: [{value: lowerCaseName}],
+ nodeRef: placeKeeperNode,
+ fastMixIn: true
+ };
+ props["namespace"] = ns;
+ return dojo.widget.getParser().createComponentFromScript(placeKeeperNode, name, props, ns);
+ }
+
+ props = props||{};
+ var notRef = false;
+ var tn = null;
+ var h = dojo.render.html.capable;
+ if(h){
+ tn = document.createElement("span");
+ }
+ if(!refNode){
+ notRef = true;
+ refNode = tn;
+ if(h){
+ dojo.body().appendChild(refNode);
+ }
+ }else if(position){
+ dojo.dom.insertAtPosition(tn, refNode, position);
+ }else{ // otherwise don't replace, but build in-place
+ tn = refNode;
+ }
+ var widgetArray = fromScript(tn, name.toLowerCase(), props, ns);
+ if (!widgetArray || !widgetArray[0] || typeof widgetArray[0].widgetType == "undefined") {
+ throw new Error("createWidget: Creation of \"" + name + "\" widget failed.");
+ }
+ if (notRef) {
+ if (widgetArray[0].domNode.parentNode) {
+ widgetArray[0].domNode.parentNode.removeChild(widgetArray[0].domNode);
+ }
+ }
+ return widgetArray[0]; // just return the widget
+}
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Parse.js
------------------------------------------------------------------------------
svn:eol-style = native