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/02/01 06:41:23 UTC
svn commit: r373998 [16/23] - in
/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo:
./ src/ src/alg/ src/animation/ src/collections/ src/crypto/ src/data/
src/dnd/ src/event/ src/flash/ src/flash/flash6/ src/flash/flash8/ src/fx/...
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Manager.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Manager.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Manager.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Manager.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,292 @@
+/*
+ Copyright (c) 2004-2005, 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.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);
+ // 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){
+ var tw = this.widgets[widgetIndex].widgetId;
+ delete this.widgetIds[tw];
+ this.widgets.splice(widgetIndex, 1);
+ }
+
+ // FIXME: suboptimal performance
+ this.removeById = function(id) {
+ for (var i=0; i<this.widgets.length; i++){
+ if(this.widgets[i].widgetId == id){
+ this.remove(i);
+ break;
+ }
+ }
+ }
+
+ this.getWidgetById = function(id){
+ return this.widgetIds[id];
+ }
+
+ this.getWidgetsByType = function(type){
+ var lt = type.toLowerCase();
+ var ret = [];
+ dojo.lang.forEach(this.widgets, function(x){
+ if(x.widgetType.toLowerCase() == lt){
+ ret.push(x);
+ }
+ });
+ return ret;
+ }
+
+ this.getWidgetsOfType = function (id) {
+ dj_deprecated("getWidgetsOfType is depecrecated, use getWidgetsByType");
+ return dojo.widget.manager.getWidgetsByType(id);
+ }
+
+ this.getWidgetsByFilter = function(unaryFunc){
+ var ret = [];
+ dojo.lang.forEach(this.widgets, function(x){
+ if(unaryFunc(x)){
+ ret.push(x);
+ }
+ });
+ return ret;
+ }
+
+ this.getAllWidgets = function() {
+ return this.widgets.concat();
+ }
+
+ // added, trt 2006-01-20
+ this.getWidgetByNode = function(/* DOMNode */ node){
+ var w=this.getAllWidgets();
+ 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){
+ // try and find a name for the widget
+ var impl = this.getImplementationName(widgetName);
+ if(impl){
+ // var tic = new Date();
+ var ret = new impl(ctorObject);
+ // dojo.debug(new Date() - tic);
+ return ret;
+ }
+ }
+
+ this.getImplementationName = function(widgetName){
+ /*
+ * This is the overly-simplistic implemention of getImplementation (har
+ * har). In the future, we are going to want something that allows more
+ * freedom of expression WRT to specifying different specializations of
+ * a widget.
+ *
+ * Additionally, this implementation treats widget names as case
+ * insensitive, which does not necessarialy mesh with the markup which
+ * can construct a widget.
+ */
+
+ var lowerCaseWidgetName = widgetName.toLowerCase();
+
+ var impl = knownWidgetImplementations[lowerCaseWidgetName];
+ if(impl){
+ return impl;
+ }
+
+ // first store a list of the render prefixes we are capable of rendering
+ if(!renderPrefixCache.length){
+ 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("");
+ }
+
+ // look for a rendering-context specific version of our widget name
+ for(var i = 0; i < widgetPackages.length; i++){
+ var widgetPackage = dojo.evalObjPath(widgetPackages[i]);
+ if(!widgetPackage) { continue; }
+
+ for (var j = 0; j < renderPrefixCache.length; j++) {
+ if (!widgetPackage[renderPrefixCache[j]]) { continue; }
+ for (var widgetClass in widgetPackage[renderPrefixCache[j]]) {
+ if (widgetClass.toLowerCase() != lowerCaseWidgetName) { continue; }
+ knownWidgetImplementations[lowerCaseWidgetName] =
+ widgetPackage[renderPrefixCache[j]][widgetClass];
+ return knownWidgetImplementations[lowerCaseWidgetName];
+ }
+ }
+
+ for (var j = 0; j < renderPrefixCache.length; j++) {
+ for (var widgetClass in widgetPackage) {
+ if (widgetClass.toLowerCase() !=
+ (renderPrefixCache[j] + lowerCaseWidgetName)) { continue; }
+
+ knownWidgetImplementations[lowerCaseWidgetName] =
+ widgetPackage[widgetClass];
+ return knownWidgetImplementations[lowerCaseWidgetName];
+ }
+ }
+ }
+
+ throw new Error('Could not locate "' + widgetName + '" class');
+ }
+
+ // FIXME: does it even belong in this name space?
+ // NOTE: this method is implemented by DomWidget.js since not all
+ // hostenv's would have an implementation.
+ /*this.getWidgetFromPrimitive = function(baseRenderType){
+ dj_unimplemented("dojo.widget.manager.getWidgetFromPrimitive");
+ }
+
+ this.getWidgetFromEvent = function(nativeEvt){
+ dj_unimplemented("dojo.widget.manager.getWidgetFromEvent");
+ }*/
+
+ // Catch window resize events and notify top level widgets
+ this.resizing=false;
+ this.onResized = function() {
+ if(this.resizing){
+ return; // duplicate event
+ }
+ try {
+ this.resizing=true;
+ for(var id in this.topWidgets) {
+ var child = this.topWidgets[id];
+ //dojo.debug("root resizing child " + child.widgetId);
+ if ( child.onResized ) {
+ child.onResized();
+ }
+ }
+ } finally {
+ this.resizing=false;
+ }
+ }
+ if(typeof window != "undefined") {
+ dojo.addOnLoad(this, 'onResized'); // initial sizing
+ dojo.event.connect(window, 'onresize', this, 'onResized'); // window resize
+ }
+
+ // FIXME: what else?
+}
+
+// copy the methods from the default manager (this) to the widget namespace
+dojo.widget.getUniqueId = function () { return dojo.widget.manager.getUniqueId.apply(dojo.widget.manager, arguments); }
+dojo.widget.addWidget = function () { return dojo.widget.manager.add.apply(dojo.widget.manager, arguments); }
+dojo.widget.destroyAllWidgets = function () { return dojo.widget.manager.destroyAll.apply(dojo.widget.manager, arguments); }
+dojo.widget.removeWidget = function () { return dojo.widget.manager.remove.apply(dojo.widget.manager, arguments); }
+dojo.widget.removeWidgetById = function () { return dojo.widget.manager.removeById.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetById = function () { return dojo.widget.manager.getWidgetById.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetsByType = function () { return dojo.widget.manager.getWidgetsByType.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetsByFilter = function () { return dojo.widget.manager.getWidgetsByFilter.apply(dojo.widget.manager, arguments); }
+dojo.widget.byId = function () { return dojo.widget.manager.getWidgetById.apply(dojo.widget.manager, arguments); }
+dojo.widget.byType = function () { return dojo.widget.manager.getWidgetsByType.apply(dojo.widget.manager, arguments); }
+dojo.widget.byFilter = function () { return dojo.widget.manager.getWidgetsByFilter.apply(dojo.widget.manager, arguments); }
+dojo.widget.byNode = function () { return dojo.widget.manager.getWidgetByNode.apply(dojo.widget.manager, arguments); }
+dojo.widget.all = function (n) {
+ var widgets = dojo.widget.manager.getAllWidgets.apply(dojo.widget.manager, arguments);
+ if(arguments.length > 0) {
+ return widgets[n];
+ }
+ return widgets;
+}
+dojo.widget.registerWidgetPackage = function () { return dojo.widget.manager.registerWidgetPackage.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetImplementation = function () { return dojo.widget.manager.getImplementation.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetImplementationName = function () { return dojo.widget.manager.getImplementationName.apply(dojo.widget.manager, arguments); }
+
+dojo.widget.widgets = dojo.widget.manager.widgets;
+dojo.widget.widgetIds = dojo.widget.manager.widgetIds;
+dojo.widget.root = dojo.widget.manager.root;
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,59 @@
+/*
+ Copyright (c) 2004-2005, 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.Menu");
+dojo.provide("dojo.widget.DomMenu");
+
+dojo.deprecated("dojo.widget.Menu, dojo.widget.DomMenu", "use dojo.widget.Menu2", "0.4");
+
+dojo.require("dojo.widget.*");
+
+dojo.widget.tags.addParseTreeHandler("dojo:menu");
+
+/* Menu
+ *******/
+
+dojo.widget.Menu = function () {
+ dojo.widget.Menu.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.Menu, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.Menu, {
+ widgetType: "Menu",
+ isContainer: true,
+
+ items: [],
+ push: function(item){
+ dojo.connect.event(item, "onSelect", this, "onSelect");
+ this.items.push(item);
+ },
+ onSelect: function(){}
+});
+
+
+/* DomMenu
+ **********/
+
+dojo.widget.DomMenu = function(){
+ dojo.widget.DomMenu.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomMenu, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomMenu, {
+ widgetType: "Menu",
+ isContainer: true,
+
+ push: function (item) {
+ dojo.widget.Menu.call(this, item);
+ this.domNode.appendChild(item.domNode);
+ }
+});
+
+dojo.requireAfterIf("html", "dojo.widget.html.Menu");
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu2.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu2.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu2.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Menu2.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,760 @@
+/*
+ Copyright (c) 2004-2005, 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.provide("dojo.widget.html.Menu2");
+dojo.provide("dojo.widget.PopupMenu2");
+dojo.provide("dojo.widget.MenuItem2");
+
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+
+dojo.widget.PopupMenu2 = function(){
+ dojo.widget.HtmlWidget.call(this);
+ this.items = []; // unused???
+ this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it becomes context menu for those nodes
+ this.queueOnAnimationFinish = [];
+
+ this.eventNames = {
+ open: ""
+ };
+
+}
+
+dojo.inherits(dojo.widget.PopupMenu2, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.PopupMenu2, {
+ widgetType: "PopupMenu2",
+ isContainer: true,
+
+ snarfChildDomOutput: true,
+
+ currentSubmenu: null,
+ currentSubmenuTrigger: null,
+ parentMenu: null,
+ isShowing: false,
+ menuX: 0,
+ menuY: 0,
+ menuWidth: 0,
+ menuHeight: 0,
+ menuIndex: 0,
+
+ domNode: null,
+ containerNode: null,
+
+ eventNaming: "default",
+
+
+ templateString: '<div><div dojoAttachPoint="containerNode"></div></div>',
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlMenu2.css"),
+
+ itemHeight: 18,
+ iconGap: 1,
+ accelGap: 10,
+ submenuGap: 2,
+ finalGap: 5,
+ submenuIconSize: 4,
+ separatorHeight: 9,
+ submenuDelay: 500,
+ submenuOverlap: 5,
+ contextMenuForWindow: false,
+ openEvent: null,
+
+ submenuIconSrc: dojo.uri.dojoUri("src/widget/templates/images/submenu_off.gif").toString(),
+ submenuIconOnSrc: dojo.uri.dojoUri("src/widget/templates/images/submenu_on.gif").toString(),
+
+ initialize: function(args, frag) {
+
+ if (this.eventNaming == "default") {
+ for (eventName in this.eventNames) {
+ this.eventNames[eventName] = this.widgetId+"/"+eventName;
+ }
+ }
+
+ },
+
+ postCreate: function(){
+
+ dojo.html.addClass(this.domNode, 'dojoPopupMenu2');
+ dojo.html.addClass(this.containerNode, 'dojoPopupMenu2Client');
+
+ this.domNode.style.left = '-9999px'
+ this.domNode.style.top = '-9999px'
+
+ if (this.contextMenuForWindow){
+ var doc = document.documentElement || document.body;
+ dojo.event.connect(doc, "oncontextmenu", this, "onOpen");
+ } else if ( this.targetNodeIds.length > 0 ){
+ for(var i=0; i<this.targetNodeIds.length; i++){
+ this.bindDomNode(this.targetNodeIds[i]);
+ }
+ }
+
+ this.subscribeSubitemsOnOpen();
+
+ this.layoutMenuSoon();
+ },
+
+ subscribeSubitemsOnOpen: function() {
+ var subItems = this.getChildrenOfType(dojo.widget.MenuItem2);
+
+ //dojo.debug(subItems)
+
+ for(var i=0; i<subItems.length; i++) {
+ //dojo.debug(subItems[i]);
+ dojo.event.topic.subscribe(this.eventNames.open, subItems[i], "menuOpen")
+ }
+ },
+
+ // get open event for current menu
+ getTopOpenEvent: function() {
+ var menu = this;
+ while (menu.parent){ menu = menu.parent; }
+ return menu.openEvent;
+ },
+
+ // attach menu to given node
+ bindDomNode: function(node){
+ dojo.event.connect(dojo.byId(node), "oncontextmenu", this, "onOpen");
+ },
+
+ // detach menu from given node
+ unBindDomNode: function(node){
+ dojo.event.kwDisconnect({
+ srcObj: dojo.byId(node),
+ srcFunc: "oncontextmenu",
+ targetObj: this,
+ targetFunc: "onOpen",
+ once: true
+ });
+ },
+
+ layoutMenuSoon: function(){
+
+ dojo.lang.setTimeout(this, "layoutMenu", 0);
+ },
+
+ layoutMenu: function(){
+
+ // menu must be attached to DOM for size calculations to work
+
+ var parent = this.domNode.parentNode;
+ if (! parent || parent == undefined) {
+ document.body.appendChild(this.domNode);
+ }
+
+ // determine menu width
+
+ var max_label_w = 0;
+ var max_accel_w = 0;
+
+ for(var i=0; i<this.children.length; i++){
+
+ if (this.children[i].getLabelWidth){
+
+ max_label_w = Math.max(max_label_w, this.children[i].getLabelWidth());
+ }
+
+ if (dojo.lang.isFunction(this.children[i].getAccelWidth)){
+
+ max_accel_w = Math.max(max_accel_w, this.children[i].getAccelWidth());
+ }
+ }
+
+ if( isNaN(max_label_w) || isNaN(max_accel_w) ){
+ // Browser needs some more time to calculate sizes
+ this.layoutMenuSoon();
+ return;
+ }
+
+ var clientLeft = dojo.style.getPixelValue(this.domNode, "padding-left", true) + dojo.style.getPixelValue(this.containerNode, "padding-left", true);
+ var clientTop = dojo.style.getPixelValue(this.domNode, "padding-top", true) + dojo.style.getPixelValue(this.containerNode, "padding-top", true);
+
+ if( isNaN(clientLeft) || isNaN(clientTop) ){
+ // Browser needs some more time to calculate sizes
+ this.layoutMenuSoon();
+ return;
+ }
+
+ var y = clientTop;
+ var max_item_width = 0;
+
+ for(var i=0; i<this.children.length; i++){
+
+ var ch = this.children[i];
+
+ ch.layoutItem(max_label_w, max_accel_w);
+
+ ch.topPosition = y;
+
+ y += dojo.style.getOuterHeight(ch.domNode);
+ max_item_width = Math.max(max_item_width, dojo.style.getOuterWidth(ch.domNode));
+ }
+
+ dojo.style.setContentWidth(this.containerNode, max_item_width);
+ dojo.style.setContentHeight(this.containerNode, y-clientTop);
+
+ dojo.style.setContentWidth(this.domNode, dojo.style.getOuterWidth(this.containerNode));
+ dojo.style.setContentHeight(this.domNode, dojo.style.getOuterHeight(this.containerNode));
+
+ this.menuWidth = dojo.style.getOuterWidth(this.domNode);
+ this.menuHeight = dojo.style.getOuterHeight(this.domNode);
+ },
+
+ open: function(x, y, parentMenu, explodeSrc){
+
+ // NOTE: alex:
+ // this couldn't have possibly worked. this.open wound up calling
+ // this.close, which called open...etc..
+ if (this.isShowing){ /* this.close(); */ return; }
+
+ if ( !parentMenu ) {
+ // record whenever a top level menu is opened
+ dojo.widget.html.Menu2Manager.opened(this, explodeSrc);
+ }
+
+ //dojo.debug("open called for animation "+this.animationInProgress)
+
+ // if I click right button and menu is opened, then it gets 2 commands: close -> open
+ // so close enables animation and next "open" is put to queue to occur at new location
+ if(this.animationInProgress){
+ this.queueOnAnimationFinish.push(this.open, arguments);
+ return;
+ }
+
+ var viewport = dojo.html.getViewportSize();
+ var scrolloffset = dojo.html.getScrollOffset();
+
+ var clientRect = {
+ 'left' : scrolloffset[0],
+ 'right' : scrolloffset[0] + viewport[0],
+ 'top' : scrolloffset[1],
+ 'bottom': scrolloffset[1] + viewport[1]
+ };
+
+ if (parentMenu){
+ // submenu is opening
+
+ if (x + this.menuWidth > clientRect.right){ x = x - (this.menuWidth + parentMenu.menuWidth - (2 * this.submenuOverlap)); }
+
+ if (y + this.menuHeight > clientRect.bottom){ y = y -
+ (this.menuHeight - (this.itemHeight + 5)); } // TODO: why 5?
+
+ }else{
+ // top level menu is opening
+ x+=scrolloffset[0];
+ y+=scrolloffset[1];
+ explodeSrc[0] += scrolloffset[0];
+ explodeSrc[1] += scrolloffset[1];
+
+ if (x < clientRect.left){ x = clientRect.left; }
+ if (x + this.menuWidth > clientRect.right){ x = x - this.menuWidth; }
+
+ if (y < clientRect.top){ y = clientRect.top; }
+ if (y + this.menuHeight > clientRect.bottom){ y = y - this.menuHeight; }
+ }
+
+ this.parentMenu = parentMenu;
+ this.explodeSrc = explodeSrc;
+ this.menuIndex = parentMenu ? parentMenu.menuIndex + 1 : 1;
+
+ this.menuX = x;
+ this.menuY = y;
+
+ // move the menu into position but make it invisible
+ // (because when menus are initially constructed they are visible but off-screen)
+ this.domNode.style.zIndex = 10 + this.menuIndex;
+ this.domNode.style.left = x + 'px';
+ this.domNode.style.top = y + 'px';
+ this.domNode.style.display='none';
+ this.domNode.style.position='absolute';
+
+ // then use the user defined method to display it
+ this.show();
+
+ this.isShowing = true;
+ },
+
+ close: function(){
+ // If we are in the process of opening the menu and we are asked to close it,
+ // we should really cancel the current animation, but for simplicity we will
+ // just ignore the request
+ if(this.animationInProgress){
+ this.queueOnAnimationFinish.push(this.close, []);
+ return;
+ }
+
+ this.closeSubmenu();
+ this.hide();
+ this.isShowing = false;
+ dojo.widget.html.Menu2Manager.closed(this);
+ },
+
+ onShow: function() {
+ dojo.widget.HtmlWidget.prototype.onShow.call(this);
+ this.processQueue();
+ },
+
+ // do events from queue
+ processQueue: function() {
+ if (!this.queueOnAnimationFinish.length) return;
+
+ var func = this.queueOnAnimationFinish.shift();
+ var args = this.queueOnAnimationFinish.shift();
+
+ func.apply(this, args);
+ },
+
+ onHide: function() {
+ dojo.widget.HtmlWidget.prototype.onHide.call(this);
+
+ this.processQueue();
+ },
+
+
+ closeAll: function(){
+
+ if (this.parentMenu){
+ this.parentMenu.closeAll();
+ }else{
+ this.close();
+ }
+ },
+
+ closeSubmenu: function(){
+ if (this.currentSubmenu == null){ return; }
+
+ this.currentSubmenu.close();
+ this.currentSubmenu = null;
+
+ this.currentSubmenuTrigger.is_open = false;
+ this.currentSubmenuTrigger.closedSubmenu();
+ this.currentSubmenuTrigger = null;
+ },
+
+ openSubmenu: function(submenu, from_item){
+
+ var our_x = dojo.style.getPixelValue(this.domNode, 'left');
+ var our_y = dojo.style.getPixelValue(this.domNode, 'top');
+ var our_w = dojo.style.getOuterWidth(this.domNode);
+ var item_y = from_item.topPosition;
+
+ var x = our_x + our_w - this.submenuOverlap;
+ var y = our_y + item_y;
+
+ this.currentSubmenu = submenu;
+ this.currentSubmenu.open(x, y, this, from_item.domNode);
+
+ this.currentSubmenuTrigger = from_item;
+ this.currentSubmenuTrigger.is_open = true;
+ },
+
+ onOpen: function(e){
+ this.openEvent = e;
+
+ //dojo.debugShallow(e);
+ this.open(e.clientX, e.clientY, null, [e.clientX, e.clientY]);
+
+ if(e["preventDefault"]){
+ e.preventDefault();
+ }
+ },
+
+ isPointInMenu: function(x, y){
+
+ if (x < this.menuX){ return 0; }
+ if (x > this.menuX + this.menuWidth){ return 0; }
+
+ if (y < this.menuY){ return 0; }
+ if (y > this.menuY + this.menuHeight){ return 0; }
+
+ return 1;
+ }
+});
+
+
+dojo.widget.MenuItem2 = function(){
+ dojo.widget.HtmlWidget.call(this);
+
+ this.eventNames = {
+ engage: ""
+ };
+}
+
+dojo.inherits(dojo.widget.MenuItem2, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.MenuItem2, {
+ widgetType: "MenuItem2",
+ templateString:
+ '<div class="dojoMenuItem2">'
+ +'<div dojoAttachPoint="iconNode" class="dojoMenuItem2Icon"></div>'
+ +'<span dojoAttachPoint="labelNode" class="dojoMenuItem2Label"><span><span></span></span></span>'
+ +'<span dojoAttachPoint="accelNode" class="dojoMenuItem2Accel"><span><span></span></span></span>'
+ +'<div dojoAttachPoint="submenuNode" class="dojoMenuItem2Submenu"></div>'
+ +'<div dojoAttachPoint="targetNode" class="dojoMenuItem2Target" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick;"> </div>'
+ +'</div>',
+
+ //
+ // nodes
+ //
+
+ domNode: null,
+ iconNode: null,
+ labelNode: null,
+ accelNode: null,
+ submenuNode: null,
+ targetNode: null,
+
+ //
+ // internal settings
+ //
+
+ is_hovering: false,
+ hover_timer: null,
+ is_open: false,
+ topPosition: 0,
+ is_disabled: false,
+
+ //
+ // options
+ //
+
+ caption: 'Untitled',
+ accelKey: '',
+ iconSrc: '',
+ submenuId: '',
+ isDisabled: false,
+ eventNaming: "default",
+
+
+ postCreate: function(){
+
+ dojo.html.disableSelection(this.domNode);
+
+ if (this.isDisabled){
+ this.setDisabled(true);
+ }
+
+ this.labelNode.childNodes[0].appendChild(document.createTextNode(this.caption));
+ this.accelNode.childNodes[0].appendChild(document.createTextNode(this.accelKey));
+
+ this.labelShadowNode = this.labelNode.childNodes[0].childNodes[0];
+ this.accelShadowNode = this.accelNode.childNodes[0].childNodes[0];
+
+ this.labelShadowNode.appendChild(document.createTextNode(this.caption));
+ this.accelShadowNode.appendChild(document.createTextNode(this.accelKey));
+
+ if (this.eventNaming == "default") {
+ for (eventName in this.eventNames) {
+ this.eventNames[eventName] = this.widgetId+"/"+eventName;
+ }
+ }
+ },
+
+ layoutItem: function(label_w, accel_w){
+
+ var x_label = this.parent.itemHeight + this.parent.iconGap;
+ var x_accel = x_label + label_w + this.parent.accelGap;
+ var x_submu = x_accel + accel_w + this.parent.submenuGap;
+ var total_w = x_submu + this.parent.submenuIconSize + this.parent.finalGap;
+
+
+ this.iconNode.style.left = '0px';
+ this.iconNode.style.top = '0px';
+
+
+ if (this.iconSrc){
+
+ if ((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4) == ".png") && (dojo.render.html.ie)){
+
+ this.iconNode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='image')";
+ this.iconNode.style.backgroundImage = '';
+ }else{
+ this.iconNode.style.backgroundImage = 'url('+this.iconSrc+')';
+ }
+ }else{
+ this.iconNode.style.backgroundImage = '';
+ }
+
+ dojo.style.setOuterWidth(this.iconNode, this.parent.itemHeight);
+ dojo.style.setOuterHeight(this.iconNode, this.parent.itemHeight);
+
+ dojo.style.setOuterHeight(this.labelNode, this.parent.itemHeight);
+ dojo.style.setOuterHeight(this.accelNode, this.parent.itemHeight);
+
+ dojo.style.setContentWidth(this.domNode, total_w);
+ dojo.style.setContentHeight(this.domNode, this.parent.itemHeight);
+
+ this.labelNode.style.left = x_label + 'px';
+ this.accelNode.style.left = x_accel + 'px';
+ this.submenuNode.style.left = x_submu + 'px';
+
+ dojo.style.setOuterWidth(this.submenuNode, this.parent.submenuIconSize);
+ dojo.style.setOuterHeight(this.submenuNode, this.parent.itemHeight);
+
+ this.submenuNode.style.display = this.submenuId ? 'block' : 'none';
+ this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconSrc+')';
+
+ dojo.style.setOuterWidth(this.targetNode, total_w);
+ dojo.style.setOuterHeight(this.targetNode, this.parent.itemHeight);
+ },
+
+ onHover: function(){
+
+ if (this.is_hovering){ return; }
+ if (this.is_open){ return; }
+
+ this.parent.closeSubmenu();
+ this.highlightItem();
+
+ if (this.is_hovering){ this.stopSubmenuTimer(); }
+ this.is_hovering = 1;
+ this.startSubmenuTimer();
+ },
+
+ onUnhover: function(){
+
+ if (!this.is_open){ this.unhighlightItem(); }
+
+ this.is_hovering = 0;
+ this.stopSubmenuTimer();
+ },
+
+ onClick: function(){
+
+ if (this.is_disabled){ return; }
+
+ if (this.submenuId){
+
+ if (!this.is_open){
+ this.stopSubmenuTimer();
+ this.openSubmenu();
+ }
+
+ }else{
+ this.parent.closeAll();
+ }
+
+ //dojo.debug("GO "+this.eventNames.engage)
+
+ dojo.event.topic.publish(this.eventNames.engage, this);
+
+ },
+
+ highlightItem: function(){
+
+ dojo.html.addClass(this.domNode, 'dojoMenuItem2Hover');
+ this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconOnSrc+')';
+ },
+
+ unhighlightItem: function(){
+
+ dojo.html.removeClass(this.domNode, 'dojoMenuItem2Hover');
+ this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconSrc+')';
+ },
+
+ startSubmenuTimer: function(){
+ this.stopSubmenuTimer();
+
+ if (this.is_disabled){ return; }
+
+ var self = this;
+ var closure = function(){ return function(){ self.openSubmenu(); } }();
+
+ this.hover_timer = window.setTimeout(closure, this.parent.submenuDelay);
+ },
+
+ stopSubmenuTimer: function(){
+ if (this.hover_timer){
+ window.clearTimeout(this.hover_timer);
+ this.hover_timer = null;
+ }
+ },
+
+ openSubmenu: function(){
+ // first close any other open submenu
+ this.parent.closeSubmenu();
+
+ var submenu = dojo.widget.getWidgetById(this.submenuId);
+ if (submenu){
+
+ this.parent.openSubmenu(submenu, this);
+ }
+
+ //dojo.debug('open submenu for item '+this.widgetId);
+ },
+
+ closedSubmenu: function(){
+
+ this.onUnhover();
+ },
+
+ setDisabled: function(value){
+
+ if (value == this.is_disabled){ return; }
+
+ this.is_disabled = value;
+
+ if (this.is_disabled){
+ dojo.html.addClass(this.domNode, 'dojoMenuItem2Disabled');
+ }else{
+ dojo.html.removeClass(this.domNode, 'dojoMenuItem2Disabled');
+ }
+ },
+
+ getLabelWidth: function(){
+
+ var node = this.labelNode.childNodes[0];
+
+ return dojo.style.getOuterWidth(node);
+ },
+
+ getAccelWidth: function(){
+
+ var node = this.accelNode.childNodes[0];
+
+ return dojo.style.getOuterWidth(node);
+ },
+
+ menuOpen: function(message) {
+ }
+
+});
+
+
+dojo.widget.MenuSeparator2 = function(){
+ dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.MenuSeparator2, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.MenuSeparator2, {
+ widgetType: "MenuSeparator2",
+
+ domNode: null,
+ topNode: null,
+ bottomNode: null,
+
+ templateString: '<div>'
+ +'<div dojoAttachPoint="topNode"></div>'
+ +'<div dojoAttachPoint="bottomNode"></div>'
+ +'</div>',
+
+ postCreate: function(){
+
+ dojo.html.addClass(this.domNode, 'dojoMenuSeparator2');
+ dojo.html.addClass(this.topNode, 'dojoMenuSeparator2Top');
+ dojo.html.addClass(this.bottomNode, 'dojoMenuSeparator2Bottom');
+
+ dojo.html.disableSelection(this.domNode);
+
+ this.layoutItem();
+ },
+
+ layoutItem: function(label_w, accel_w){
+
+ var full_width = this.parent.itemHeight
+ + this.parent.iconGap
+ + label_w
+ + this.parent.accelGap
+ + accel_w
+ + this.parent.submenuGap
+ + this.parent.submenuIconSize
+ + this.parent.finalGap;
+
+ if (isNaN(full_width)){ return; }
+
+ dojo.style.setContentHeight(this.domNode, this.parent.separatorHeight);
+ dojo.style.setContentWidth(this.domNode, full_width);
+ }
+});
+
+//
+// the menu manager makes sure we don't have several menus
+// open at once. the root menu in an opening sequence calls
+// opened(). when a root menu closes it calls closed(). then
+// everything works. lovely.
+//
+
+dojo.widget.html.Menu2Manager = new function(){
+
+ this.currentMenu = null;
+ this.currentButton = null; // button that opened current menu (if any)
+ this.focusNode = null;
+
+ dojo.event.connect(document, 'onmousedown', this, 'onClick');
+ dojo.event.connect(window, "onscroll", this, "onClick");
+
+ this.closed = function(menu){
+ if (this.currentMenu == menu){
+ this.currentMenu = null;
+ this.currentButton = null;
+ }
+ };
+
+ this.opened = function(menu, button){
+ if (menu == this.currentMenu){ return; }
+
+ if (this.currentMenu){
+ this.currentMenu.close();
+ }
+
+ this.currentMenu = menu;
+ this.currentButton = button;
+ };
+
+ this.onClick = function(e){
+
+ if (!this.currentMenu){ return; }
+
+ var scrolloffset = dojo.html.getScrollOffset();
+
+ var x = e.clientX + scrolloffset[0];
+ var y = e.clientY + scrolloffset[1];
+
+ var m = this.currentMenu;
+
+ // starting from the base menu, perform a hit test
+ // and exit when one succeeds
+
+ while (m){
+
+ if (m.isPointInMenu(x, y)){
+
+ return;
+ }
+
+ m = m.currentSubmenu;
+ }
+
+ // Also, if user clicked the button that opened this menu, then
+ // that button will send the menu a close() command, so this code
+ // shouldn't try to close the menu. Closing twice messes up animation.
+ if (this.currentButton && dojo.html.overElement(this.currentButton, e)){
+ return;
+ }
+
+ // the click didn't fall within the open menu tree
+ // so close it
+
+ this.currentMenu.close();
+ };
+}
+
+
+// make it a tag
+dojo.widget.tags.addParseTreeHandler("dojo:PopupMenu2");
+dojo.widget.tags.addParseTreeHandler("dojo:MenuItem2");
+dojo.widget.tags.addParseTreeHandler("dojo:MenuSeparator2");
+
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MenuItem.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MenuItem.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MenuItem.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MenuItem.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,47 @@
+/*
+ Copyright (c) 2004-2005, 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.MenuItem");
+dojo.provide("dojo.widget.DomMenuItem");
+
+dojo.deprecated("dojo.widget.MenuItem, dojo.widget.DomMenuItem", "use dojo.widget.Menu2", "0.4");
+
+dojo.require("dojo.string");
+dojo.require("dojo.widget.*");
+
+dojo.widget.tags.addParseTreeHandler("dojo:MenuItem");
+
+/* MenuItem
+ ***********/
+
+dojo.widget.MenuItem = function(){
+ dojo.widget.MenuItem.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.MenuItem, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.MenuItem, {
+ widgetType: "MenuItem",
+ isContainer: true
+});
+
+
+/* DomMenuItem
+ **************/
+dojo.widget.DomMenuItem = function(){
+ dojo.widget.DomMenuItem.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomMenuItem, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomMenuItem, {
+ widgetType: "MenuItem"
+});
+
+dojo.requireAfterIf("html", "dojo.html");
+dojo.requireAfterIf("html", "dojo.widget.html.MenuItem");
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MonthlyCalendar.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MonthlyCalendar.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MonthlyCalendar.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/MonthlyCalendar.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,74 @@
+/*
+ Copyright (c) 2004-2005, 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.provide("dojo.widget.MonthlyCalendar.util");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.date");
+
+dojo.widget.MonthlyCalendar= function(){
+ dojo.widget.Widget.call(this);
+ this.widgetType = "MonthlyCalendar";
+ this.isContainer = false;
+ // the following aliases prevent breaking people using 0.2.x
+ this.months = dojo.date.months;
+ this.weekdays = dojo.date.days;
+ this.toRfcDate = dojo.widget.MonthlyCalendar.util.toRfcDate;
+ this.fromRfcDate = dojo.widget.MonthlyCalendar.util.fromRfcDate;
+ this.initFirstSaturday = dojo.widget.MonthlyCalendar.util.initFirstSaturday;
+}
+
+dojo.inherits(dojo.widget.MonthlyCalendar, dojo.widget.Widget);
+dojo.widget.tags.addParseTreeHandler("dojo:monthlycalendar");
+
+dojo.requireAfterIf("html", "dojo.widget.html.MonthlyCalendar");
+
+dojo.widget.MonthlyCalendar.util= new function() {
+ this.months = dojo.date.months;
+ this.weekdays = dojo.date.days;
+
+ 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));
+ }
+
+ 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()};
+ }
+}
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Parse.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Parse.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Parse.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Parse.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,319 @@
+/*
+ Copyright (c) 2004-2005, 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.widget.Parse = function(fragment) {
+ this.propertySetsList = [];
+ this.fragment = fragment;
+
+ /* createComponents recurses over a raw JavaScript object structure,
+ and calls the corresponding handler for its normalized tagName if it exists
+ */
+ this.createComponents = function(fragment, parentComp){
+ var djTags = dojo.widget.tags;
+ var returnValue = [];
+ // this allows us to parse without having to include the parent
+ // it is commented out as it currently breaks the existing mechanism for
+ // adding widgets programmatically. Once that is fixed, this can be used
+ /*if( (fragment["tagName"])&&
+ (fragment != fragment["nodeRef"])){
+ var tn = new String(fragment["tagName"]);
+ // we split so that you can declare multiple
+ // non-destructive widgets from the same ctor node
+ var tna = tn.split(";");
+ for(var x=0; x<tna.length; x++){
+ var ltn = dojo.text.trim(tna[x]).toLowerCase();
+ if(djTags[ltn]){
+ fragment.tagName = ltn;
+ returnValue.push(djTags[ltn](fragment, this, parentComp, count++));
+ }else{
+ if(ltn.substr(0, 5)=="dojo:"){
+ dj_debug("no tag handler registed for type: ", ltn);
+ }
+ }
+ }
+ }*/
+ for(var item in fragment){
+ var built = false;
+ // if we have items to parse/create at this level, do it!
+ try{
+ if( fragment[item] && (fragment[item]["tagName"])&&
+ (fragment[item] != fragment["nodeRef"])){
+ var tn = new String(fragment[item]["tagName"]);
+ // we split so that you can declare multiple
+ // non-destructive widgets from the same ctor node
+ var tna = tn.split(";");
+ for(var x=0; x<tna.length; x++){
+ var ltn = (tna[x].replace(/^\s+|\s+$/g, "")).toLowerCase();
+ if(djTags[ltn]){
+ built = true;
+ // var tic = new Date();
+ fragment[item].tagName = ltn;
+ var ret = djTags[ltn](fragment[item], this, parentComp, fragment[item]["index"]);
+ returnValue.push(ret);
+ }else{
+ if((dojo.lang.isString(ltn))&&(ltn.substr(0, 5)=="dojo:")){
+ dojo.debug("no tag handler registed for type: ", ltn);
+ }
+ }
+ }
+ }
+ }catch(e){
+ dojo.debug("fragment creation error:", e);
+ // throw(e);
+ // IE is such a bitch sometimes
+ }
+
+ // if there's a sub-frag, build widgets from that too
+ if( (!built) && (typeof fragment[item] == "object")&&
+ (fragment[item] != fragment.nodeRef)&&
+ (fragment[item] != fragment["tagName"])){
+ returnValue.push(this.createComponents(fragment[item], parentComp));
+ }
+ }
+ return returnValue;
+ }
+
+ /* 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!="")){
+ 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;
+ 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(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
+ */
+ this.createComponentFromScript = function(nodeRef, componentName, properties){
+ var ltn = "dojo:" + componentName.toLowerCase();
+ if(dojo.widget.tags[ltn]){
+ properties.fastMixIn = true;
+ return [dojo.widget.tags[ltn](properties, this, null, null, properties)];
+ }else{
+ if(ltn.substr(0, 5)=="dojo:"){
+ dojo.debug("no tag handler registed for type: ", ltn);
+ }
+ }
+ }
+}
+
+
+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
+ * @param props Key-Value pairs of properties of the widget
+ * @param refNode If the last argument is specified this node is used as
+ * a reference for inserting this node into a DOM tree else
+ * it beomces 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) {
+
+ function fromScript (placeKeeperNode, name, props) {
+ var lowerCaseName = name.toLowerCase();
+ var namespacedName = "dojo:" + lowerCaseName;
+ props[namespacedName] = {
+ dojotype: [{value: lowerCaseName}],
+ nodeRef: placeKeeperNode,
+ fastMixIn: true
+ };
+ return dojo.widget.getParser().createComponentFromScript(
+ placeKeeperNode, name, props, true);
+ }
+
+ if (typeof name != "string" && typeof props == "string") {
+ dojo.deprecated("dojo.widget.createWidget",
+ "argument order is now of the form " +
+ "dojo.widget.createWidget(NAME, [PROPERTIES, [REFERENCENODE, [POSITION]]])");
+ return fromScript(name, props, refNode);
+ }
+
+ 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){
+ document.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, props);
+ if (!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
+}
+
+dojo.widget.fromScript = function(name, props, refNode, position){
+ dojo.deprecated("dojo.widget.fromScript", " use " +
+ "dojo.widget.createWidget instead");
+ return dojo.widget.createWidget(name, props, refNode, position);
+}
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/PopUpButton.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/PopUpButton.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/PopUpButton.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/PopUpButton.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,192 @@
+/*
+ Copyright (c) 2004-2005, 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.PopUpButton");
+dojo.provide("dojo.widget.DomPopUpButton");
+dojo.provide("dojo.widget.HtmlPopUpButton");
+
+dojo.deprecated("dojo.widget.PopUpButton, dojo.widget.DomPopUpButton, dojo.widget.HtmlPopUpButton", "use dojo.widget.DropDownButton2", "0.4");
+
+//dojo.require("dojo.widget.Button");
+//dojo.require("dojo.widget.HtmlButton");
+
+dojo.require("dojo.widget.Menu");
+dojo.require("dojo.widget.MenuItem");
+
+dojo.require("dojo.html");
+
+dojo.widget.tags.addParseTreeHandler("dojo:PopUpButton");
+
+/* PopUpButton
+ **************/
+
+dojo.widget.PopUpButton = function () {
+ dojo.widget.PopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.PopUpButton, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.PopUpButton, {
+ widgetType: "PopUpButton",
+
+ label: ""
+});
+
+
+/* DomPopUpButton
+ *****************/
+dojo.widget.DomPopUpButton = function(){
+ dojo.widget.DomPopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomPopUpButton, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomPopUpButton, {
+ widgetType: dojo.widget.PopUpButton.prototype.widgetType
+});
+
+
+/* HtmlPopUpButton
+ ******************/
+
+dojo.widget.HtmlPopUpButton = function () {
+ dojo.widget.HtmlPopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.HtmlPopUpButton, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlPopUpButton, {
+ widgetType: dojo.widget.PopUpButton.prototype.widgetType,
+ templateString: null,
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/PopUpButton.css"),
+
+ buildRendering: function (args, frag) {
+ dojo.style.insertCssFile(this.templateCssPath, null, true);
+
+ this.domNode = document.createElement("a");
+ this.domNode.className = "PopUpButton";
+ dojo.event.connect(this.domNode, "onmousedown", this, "onMouseDown");
+
+ // draw the arrow
+ var arrow = document.createElement("img");
+ arrow.src = dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow.gif");
+ dojo.html.setClass(arrow, "downArrow");
+ this.domNode.appendChild(arrow);
+
+ this.menu = dojo.widget.fromScript("Menu");
+ dojo.html.addClass(this.menu.domNode, "PopUpButtonMenu");
+ dojo.event.connect(this.menu, "onSelect", this, "onSelect");
+
+ if (frag["dojo:" + this.widgetType.toLowerCase()].nodeRef) {
+ var node = frag["dojo:" + this.widgetType.toLowerCase()].nodeRef;
+ var options = node.getElementsByTagName("option");
+ for (var i = 0; i < options.length; i++) {
+ var properties = {
+ title: dojo.dom.textContent(options[i]),
+ value: options[i].value
+ }
+ this.addItem(dojo.widget.fromScript("MenuItem", properties));
+ }
+ }
+ },
+
+ addItem: function (item) {
+ // TODO: should be dojo.widget.MenuItem
+ if (item instanceof dojo.widget.html.MenuItem) {
+ this.menu.push(item);
+ } else {
+ // TODO: create one
+ var menuItem = dojo.widget.fromScript("MenuItem", {title: item});
+ this.menu.push(menuItem);
+ }
+ },
+
+
+/* Enabled utility methods
+ **************************/
+
+ _enabled: true,
+
+ isEnabled: function() { return this._enabled; },
+
+ setEnabled: function(enabled, force, preventEvent) {
+ enabled = Boolean(enabled);
+ if (force || this._enabled != enabled) {
+ this._enabled = enabled;
+ if (!preventEvent) {
+ this._fireEvent(this._enabled ? "onEnable" : "onDisable");
+ this._fireEvent("onChangeEnabled");
+ }
+ }
+
+ dojo.html[(this._enabled ? "add" : "remove")
+ + "Class"](this.domNode, "disabled");
+
+ 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);
+ },
+
+
+/* Select utility methods
+ **************************/
+
+ onSelect: function (item, e) {
+ this.domNode.firstChild.nodeValue = item.title;
+ },
+
+ onMouseDown: function (e) {
+ if (!this._menuVisible) {
+ this._showMenu(e);
+ dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "_hideMenu");
+ }
+ },
+
+
+ _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);
+ }
+ },
+
+
+ _showMenu: function (e) {
+ if (!this._enabled) { return; }
+ this._menuVisible = true;
+ with (dojo.html) {
+ var y = getAbsoluteY(this.domNode) + getInnerHeight(this.domNode);
+ var x = getAbsoluteX(this.domNode);
+ }
+
+ document.body.appendChild(this.menu.domNode);
+ with (this.menu.domNode.style) {
+ top = y + "px";
+ left = x + "px";
+ }
+ },
+
+ _hideMenu: function (e) {
+ this.menu.domNode.parentNode.removeChild(this.menu.domNode);
+ dojo.event.disconnect(document, "onmousedown", this, "_hideMenu");
+ this._menuVisible = false;
+ }
+
+});
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizableTextarea.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizableTextarea.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizableTextarea.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizableTextarea.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,110 @@
+/*
+ Copyright (c) 2004-2005, 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.ResizableTextarea");
+dojo.require("dojo.html");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.LayoutPane");
+dojo.require("dojo.widget.ResizeHandle");
+
+dojo.widget.tags.addParseTreeHandler("dojo:resizabletextarea");
+
+dojo.widget.ResizableTextarea = function(){
+ dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.ResizableTextarea, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.ResizableTextarea, {
+ templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlResizableTextarea.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlResizableTextarea.css"),
+ widgetType: "ResizableTextarea",
+ tagName: "dojo:resizabletextarea",
+ isContainer: false,
+ textAreaNode: null,
+ textAreaContainer: null,
+ textAreaContainerNode: null,
+ statusBar: null,
+ statusBarContainerNode: null,
+ statusLabelNode: null,
+ statusLabel: null,
+ rootLayoutNode: null,
+ resizeHandleNode: null,
+ resizeHandle: null,
+
+ fillInTemplate: function(args, frag){
+ this.textAreaNode = this.getFragNodeRef(frag).cloneNode(true);
+
+ // FIXME: Safari apparently needs this!
+ document.body.appendChild(this.domNode);
+
+ this.rootLayout = dojo.widget.createWidget(
+ "LayoutPane",
+ {
+ minHeight: 50,
+ minWidth: 100
+ },
+ this.rootLayoutNode
+ );
+
+
+ this.textAreaContainer = dojo.widget.createWidget(
+ "LayoutPane",
+ { layoutAlign: "client" },
+ this.textAreaContainerNode
+ );
+ this.rootLayout.addChild(this.textAreaContainer);
+
+ this.textAreaContainer.domNode.appendChild(this.textAreaNode);
+ with(this.textAreaNode.style){
+ width="100%";
+ height="100%";
+ }
+
+ this.statusBar = dojo.widget.createWidget(
+ "LayoutPane",
+ {
+ layoutAlign: "bottom",
+ minHeight: 28
+ },
+ this.statusBarContainerNode
+ );
+ this.rootLayout.addChild(this.statusBar);
+
+ this.statusLabel = dojo.widget.createWidget(
+ "LayoutPane",
+ {
+ layoutAlign: "client",
+ minWidth: 50
+ },
+ this.statusLabelNode
+ );
+ this.statusBar.addChild(this.statusLabel);
+
+ this.resizeHandle = dojo.widget.createWidget(
+ "ResizeHandle",
+ { targetElmId: this.rootLayout.widgetId },
+ this.resizeHandleNode
+ );
+ this.statusBar.addChild(this.resizeHandle);
+ // dojo.debug(this.rootLayout.widgetId);
+
+ // dojo.event.connect(this.resizeHandle, "beginSizing", this, "hideContent");
+ // dojo.event.connect(this.resizeHandle, "endSizing", this, "showContent");
+ },
+
+ hideContent: function(){
+ this.textAreaNode.style.display = "none";
+ },
+
+ showContent: function(){
+ this.textAreaNode.style.display = "";
+ }
+});
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizeHandle.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizeHandle.js?rev=373998&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizeHandle.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/ResizeHandle.js Tue Jan 31 21:39:49 2006
@@ -0,0 +1,101 @@
+/*
+ Copyright (c) 2004-2005, 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.ResizeHandle");
+dojo.provide("dojo.widget.html.ResizeHandle");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.dom");
+dojo.require("dojo.event");
+
+dojo.widget.html.ResizeHandle = function(){
+ dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.html.ResizeHandle, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.ResizeHandle, {
+ widgetType: "ResizeHandle",
+
+ isSizing: false,
+ startPoint: null,
+ startSize: null,
+
+ grabImg: null,
+
+ targetElmId: '',
+ imgSrc: dojo.uri.dojoUri("src/widget/templates/grabCorner.gif"),
+
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlResizeHandle.css"),
+ templateString: '<div dojoAttachPoint="domNode"><img dojoAttachPoint="grabImg" /></div>',
+
+ fillInTemplate: function(){
+
+ dojo.style.insertCssFile(this.templateCssPath);
+
+ dojo.html.addClass(this.domNode, 'dojoHtmlResizeHandle');
+ dojo.html.addClass(this.grabImg, 'dojoHtmlResizeHandleImage');
+
+ this.grabImg.src = this.imgSrc;
+ },
+
+ postCreate: function(){
+ dojo.event.connect(this.domNode, "onmousedown", this, "beginSizing");
+ },
+
+ beginSizing: function(e){
+ if (this.isSizing){ return false; }
+
+ this.targetElm = dojo.widget.byId(this.targetElmId);
+ if (!this.targetElm){ return; }
+
+ var screenX = window.event ? window.event.clientX : e.pageX;
+ var screenY = window.event ? window.event.clientY : e.pageY;
+
+ this.isSizing = true;
+ this.startPoint = {'x':e.clientX, 'y':e.clientY};
+ this.startSize = {'w':dojo.style.getOuterWidth(this.targetElm.domNode), 'h':dojo.style.getOuterHeight(this.targetElm.domNode)};
+
+ dojo.event.kwConnect({
+ srcObj: document.body,
+ srcFunc: "onmousemove",
+ targetObj: this,
+ targetFunc: "changeSizing",
+ rate: 25
+ });
+ dojo.event.connect(document.body, "onmouseup", this, "endSizing");
+
+ e.preventDefault();
+ },
+
+ changeSizing: function(e){
+ // On IE, if you move the mouse above/to the left of the object being resized,
+ // sometimes clientX/Y aren't set, apparently. Just ignore the event.
+ if(!e.clientX || !e.clientY){ return; }
+ var dx = this.startPoint.x - e.clientX;
+ var dy = this.startPoint.y - e.clientY;
+ this.targetElm.resizeTo(this.startSize.w - dx, this.startSize.h - dy);
+
+ e.preventDefault();
+ },
+
+ endSizing: function(e){
+ dojo.event.disconnect(document.body, "onmousemove", this, "changeSizing");
+ dojo.event.disconnect(document.body, "onmouseup", this, "endSizing");
+
+ this.isSizing = false;
+ }
+
+
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:ResizeHandle");
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org