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/03/11 22:19:18 UTC
svn commit: r385171 [17/24] - in
/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo:
./ src/ src/animation/ src/collections/ src/crypto/ src/data/ src/dnd/
src/event/ src/flash/ src/flash/flash6/ src/flash/flash8/ src/fx/ src/grap...
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=385171&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 Sat Mar 11 13:18:41 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!="")&&(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;
+ 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=385171&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 Sat Mar 11 13:18:41 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=385171&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 Sat Mar 11 13:18:41 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=385171&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 Sat Mar 11 13:18:41 2006
@@ -0,0 +1,93 @@
+/*
+ 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,
+
+ targetElmId: '',
+
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlResizeHandle.css"),
+ templateString: '<div class="dojoHtmlResizeHandle"><div></div></div>',
+
+ 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.
+ try{
+ if(!e.clientX || !e.clientY){ return; }
+ }catch(e){
+ // sometimes you get an exception accessing above fields...
+ 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");
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/RichText.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/RichText.js?rev=385171&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/RichText.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/RichText.js Sat Mar 11 13:18:41 2006
@@ -0,0 +1,1058 @@
+/*
+ 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.RichText");
+dojo.provide("dojo.widget.HtmlRichText");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.dom");
+dojo.require("dojo.html");
+dojo.require("dojo.event.*");
+dojo.require("dojo.style");
+dojo.require("dojo.string");
+
+// used to save content
+try {
+ document.write('<textarea id="dojo.widget.RichText.savedContent" ' +
+ 'style="display:none;position:absolute;top:-100px;left:-100px;"></textarea>');
+}catch(e){ }
+
+dojo.widget.tags.addParseTreeHandler("dojo:richtext");
+
+dojo.widget.HtmlRichText = function () {
+ dojo.widget.HtmlWidget.call(this);
+ this.contentFilters = [];
+}
+dojo.inherits(dojo.widget.HtmlRichText, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlRichText, {
+
+ widgetType: "richtext",
+
+ /** whether to inherit the parent's width or simply use 100% */
+ inheritWidth: false,
+ focusOnLoad: true,
+
+ /**
+ * If a save name is specified the content is saved and restored if the
+ * editor is not properly closed after editing has started.
+ */
+ saveName: "",
+ _content: "",
+
+ /** The minimum height that the editor should have */
+ minHeight: "1em",
+
+ isClosed: true,
+ isLoaded: false,
+
+ /** whether to use the active-x object in IE */
+ useActiveX: false,
+
+ _SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",
+
+ // contentFilters: [],
+
+/* Init
+ *******/
+
+ fillInTemplate: function(){
+ this.open();
+
+ // add the formatting functions
+ var funcs = ["queryCommandEnabled", "queryCommandState",
+ "queryCommandValue", "execCommand"];
+ for (var i = 0; i < funcs.length; i++) {
+ dojo.event.connect("around", this, funcs[i], this, "_normalizeCommand");
+ }
+
+ // backwards compatibility, needs to be removed
+ dojo.event.connect(this, "onKeyPressed", this, "afterKeyPress");
+ dojo.event.connect(this, "onKeyPress", this, "keyPress");
+ dojo.event.connect(this, "onKeyDown", this, "keyDown");
+ dojo.event.connect(this, "onKeyUp", this, "keyUp");
+ },
+
+ /**
+ * Transforms the node referenced in this.domNode into a rich text editing
+ * node. This can result in the creation and replacement with an <iframe> if
+ * designMode is used, an <object> and active-x component if inside of IE or
+ * a reguler element if contentEditable is available.
+ */
+ open: function (element) {
+ dojo.event.topic.publish("dojo.widget.RichText::open", this);
+
+ if (!this.isClosed) { this.close(); }
+ this._content = "";
+ if (arguments.length == 1) { this.domNode = element; } // else unchanged
+
+ if(this.domNode.nodeName.toLowerCase() == "textarea"){
+ this.textarea = this.domNode;
+ var html = dojo.string.trim(this.textarea.value);
+ if(html == ""){ html = " "; }
+ this.domNode = document.createElement("div");
+ with(this.textarea.style){
+ display = "block";
+ position = "absolute";
+ width = "1px";
+ height = "1px";
+ border = margin = padding = "0px";
+ visiblity = "hidden";
+ }
+ dojo.dom.insertBefore(this.domNode, this.textarea);
+ // this.domNode.innerHTML = html;
+
+ if(this.textarea.form){
+ dojo.event.connect(this.textarea.form, "onsubmit",
+ // FIXME: should we be calling close() here instead?
+ dojo.lang.hitch(this, function(){
+ this.textarea.value = this.getEditorContent();
+ })
+ );
+ }
+
+ // dojo plucks our original domNode from the document so we need
+ // to go back and put ourselves back in
+ var editor = this;
+ dojo.event.connect(this, "postCreate", function (){
+ dojo.dom.insertAfter(editor.textarea, editor.domNode);
+ });
+ } else {
+ var html = dojo.string.trim(this.domNode.innerHTML);
+ if(html == ""){ html = " "; }
+ }
+
+ this._oldHeight = dojo.style.getContentHeight(this.domNode);
+ this._oldWidth = dojo.style.getContentWidth(this.domNode);
+
+ this.savedContent = document.createElement("div");
+ while (this.domNode.hasChildNodes()) {
+ this.savedContent.appendChild(this.domNode.firstChild);
+ }
+
+ // If we're a list item we have to put in a blank line to force the
+ // bullet to nicely align at the top of text
+ if (this.domNode.nodeName == "LI") { this.domNode.innerHTML = " <br>"; }
+
+ if (this.saveName != "") {
+ var saveTextarea = document.getElementById("dojo.widget.RichText.savedContent");
+ if (saveTextarea.value != "") {
+ var datas = saveTextarea.value.split(this._SEPARATOR);
+ for (var i = 0; i < datas.length; i++) {
+ var data = datas[i].split(":");
+ if (data[0] == this.saveName) {
+ html = data[1];
+ datas.splice(i, 1);
+ break;
+ }
+ }
+ }
+ this.connect(window, "onunload", "_saveContent");
+ }
+
+ // Safari's selections go all out of whack if we do it inline,
+ // so for now IE is our only hero
+ //if (typeof document.body.contentEditable != "undefined") {
+ if (this.useActiveX && dojo.render.html.ie) { // active-x
+ this._drawObject(html);
+ } else if (dojo.render.html.ie) { // contentEditable, easy
+ this.editNode = document.createElement("div");
+ with (this.editNode) {
+ contentEditable = true;
+ innerHTML = html;
+ style.height = this.minHeight;
+ }
+ this.domNode.appendChild(this.editNode);
+
+ var events = ["onBlur", "onFocus", "onKeyPress",
+ "onKeyDown", "onKeyUp", "onClick"];
+ for (var i = 0; i < events.length; i++) {
+ this.connect(this.editNode, events[i].toLowerCase(), events[i]);
+ }
+
+ this.window = window;
+ this.document = document;
+
+ this.onLoad();
+ } else { // designMode in iframe
+ this._drawIframe(html);
+ }
+
+ // TODO: this is a guess at the default line-height, kinda works
+ if (this.domNode.nodeName == "LI") { this.domNode.lastChild.style.marginTop = "-1.2em"; }
+ dojo.html.addClass(this.domNode, "RichTextEditable");
+
+ this.isClosed = false;
+ },
+
+ /** Draws an iFrame using the existing one if one exists. Used by Mozilla and Safari */
+ _drawIframe: function (html) {
+ if (!this.iframe) {
+ this.iframe = document.createElement("iframe");
+ with (this.iframe) {
+ scrolling = "no";
+ style.border = "none";
+ style.lineHeight = "0"; // squash line height
+ style.verticalAlign = "bottom";
+ }
+ }
+
+ with (this.iframe) {
+ width = this.inheritWidth ? this._oldWidth : "100%";
+ height = this._oldHeight;
+ }
+ this.domNode.appendChild(this.iframe);
+
+ var _iframeInitialized = false;
+
+ // now we wait for onload. Janky hack!
+ var ifrFunc = dojo.lang.hitch(this, function(){
+ if(!_iframeInitialized){
+ _iframeInitialized = true;
+ }else{ return; }
+ if(!this.editNode){
+ this.window = this.iframe.contentWindow;
+ this.document = this.iframe.contentDocument;
+
+ // curry the getStyle function
+ var getStyle = (function (domNode) { return function (style) {
+ return dojo.style.getStyle(domNode, style);
+ }; })(this.domNode);
+ var font = getStyle('font-size') + " " + getStyle('font-family');
+
+ var contentEditable = Boolean(document.body.contentEditable);
+ var currentDomain = (new dojo.uri.Uri(document.location)).host;
+ // alert(currentDomain);
+ with(this.document){
+ if(!contentEditable){ designMode = "on"; }
+ open();
+ write(
+ //'<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' +
+ '<html><title></title>\n' +
+ '<script type="text/javascript">\n' +
+ ' function init(){\n' +
+ // ' var pwidget = window.parent.dojo.widget.byId("'+this.widgetId+'");\n' +
+ // ' // pwidget.window = window\n' +
+ // ' pwidget.document = document\n' +
+ // ' alert(document.body.innerHTML);\n' +
+ // ' pwidget.onLoad();\n' +
+ // FIXME: this might not work on high ports!!!
+ ' document.domain = "'+currentDomain+'";\n' +
+ ' }\n' +
+ '</script>\n' +
+ '<style type="text/css">\n' +
+ ' body,html { padding: 0; margin: 0; font: ' + font + '; }\n' +
+ // TODO: left positioning will case contents to disappear out of view
+ // if it gets too wide for the visible area
+ ' body { position: fixed; top: 0; left: 0; right: 0;' +
+ ' min-height: ' + this.minHeight + '; }\n' +
+ ' p { margin: 1em 0 !important; }\n' +
+ ' body > *:first-child { padding-top: 0 !important; margin-top: 0 !important; }\n' +
+ ' body > *:last-child { padding-bottom: 0 !important; margin-bottom: 0 !important; }\n' +
+ ' li > ul:-moz-first-node, li > ol:-moz-first-node { padding-top: 1.2em; }\n' +
+ ' li { min-height: 1.2em; }\n' +
+ //' p,ul,li { padding-top: 0; padding-bottom: 0; margin-top:0; margin-bottom: 0; }\n' +
+ '</style>\n' +
+ //'<base href="' + window.location + '">' +
+ '<body' + (contentEditable ? ' contentEditable="true"' : '') + ' onload="init();">' +
+ html + '</body></html>');
+ close();
+ }
+
+ this.onLoad();
+ }else{
+ this.editNode.innerHTML = html;
+ this.onDisplayChanged(e);
+ }
+ });
+ if(dojo.render.html.moz){
+ this.iframe.onload = ifrFunc;
+ }else{
+ ifrFunc();
+ }
+ },
+
+ /** Draws an active x object, used by IE */
+ _drawObject: function (html) {
+ this.object = document.createElement("object");
+
+ with (this.object) {
+ classid = "clsid:2D360201-FFF5-11D1-8D03-00A0C959BC0A";
+ width = this.inheritWidth ? this._oldWidth : "100%";
+ height = this._oldHeight;
+ Scrollbars = false;
+ Appearance = this._activeX.appearance.flat;
+ }
+ this.domNode.appendChild(this.object);
+
+ this.object.attachEvent("DocumentComplete", dojo.lang.hitch(this, "onLoad"));
+ this.object.attachEvent("DisplayChanged", dojo.lang.hitch(this, "_updateHeight"));
+ this.object.attachEvent("DisplayChanged", dojo.lang.hitch(this, "onDisplayChanged"));
+
+ this.object.DocumentHTML = '<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' +
+ '<title></title>' +
+ '<style type="text/css">' +
+ ' body,html { padding: 0; margin: 0; }' + //font: ' + font + '; }' +
+ ' body { overflow: hidden; }' +
+ //' #bodywrapper { }' +
+ '</style>' +
+ //'<base href="' + window.location + '">' +
+ '<body><div id="bodywrapper">' + html + '</div></body>';
+ },
+
+/* Event handlers
+ *****************/
+
+ onLoad: function(e){
+ this.isLoaded = true;
+ if (this.object){
+ this.document = this.object.DOM;
+ this.editNode = this.document.body.firstChild;
+ }else if (this.iframe){
+ this.editNode = this.document.body;
+ this.connect(this, "onDisplayChanged", "_updateHeight");
+
+ try { // sanity check for Mozilla
+ this.document.execCommand("useCSS", false, true); // old moz call
+ this.document.execCommand("styleWithCSS", false, false); // new moz call
+ //this.document.execCommand("insertBrOnReturn", false, false); // new moz call
+ }catch(e2){ }
+
+ if (dojo.render.html.safari) {
+ /*
+ this.iframe.style.visiblity = "visible";
+ this.iframe.style.border = "1px solid black";
+ this.editNode.style.visiblity = "visible";
+ this.editNode.style.border = "1px solid black";
+ */
+ // this.onDisplayChanged();
+ this.connect(this.editNode, "onblur", "onBlur");
+ this.connect(this.editNode, "onfocus", "onFocus");
+
+ this.interval = setInterval(dojo.lang.hitch(this, "onDisplayChanged"), 750);
+ // dojo.raise("onload");
+ // dojo.debug(this.editNode.parentNode.parentNode.parentNode.nodeName);
+ } else if (dojo.render.html.mozilla) {
+
+ // We need to unhook the blur event listener on close as we
+ // can encounter a garunteed crash in FF if another event is
+ // also fired
+ var doc = this.document;
+ var blurfp = dojo.event.browser.addListener(this.document, "blur", dojo.lang.hitch(this, "onBlur"));
+ var unBlur = { unBlur: function(e){
+ dojo.event.browser.removeListener(doc, "blur", blurfp);
+ } };
+ dojo.event.connect("before", this, "close", unBlur, "unBlur");
+ dojo.event.browser.addListener(this.document, "focus", dojo.lang.hitch(this, "onFocus"));
+
+ // safari can't handle key listeners, it kills the speed
+ var addListener = dojo.event.browser.addListener;
+ addListener(this.document, "keypress", dojo.lang.hitch(this, "onKeyPress"));
+ addListener(this.document, "keydown", dojo.lang.hitch(this, "onKeyDown"));
+ addListener(this.document, "keyup", dojo.lang.hitch(this, "onKeyUp"));
+ addListener(this.document, "click", dojo.lang.hitch(this, "onClick"));
+ }
+
+ // FIXME: when scrollbars appear/disappear this needs to be fired
+ }
+
+ if(this.focusOnLoad){
+ this.focus();
+ }
+ this.onDisplayChanged(e);
+ },
+
+ /** Fired on keydown */
+ onKeyDown: function (e) {
+ // we need this event at the moment to get the events from control keys
+ // such as the backspace. It might be possible to add this to Dojo, so that
+ // keyPress events can be emulated by the keyDown and keyUp detection.
+ },
+
+ /** Fired on keyup */
+ onKeyUp: function (e) {
+ },
+
+ /** Fired on keypress. */
+ onKeyPress: function (e) {
+ // handle the various key events
+
+ var character = e.charCode > 0 ? String.fromCharCode(e.charCode) : null;
+ var code = e.keyCode;
+
+ var preventDefault = true; // by default assume we cancel;
+
+ // define some key combos
+ if (e.ctrlKey || e.metaKey) { // modifier pressed
+ switch (character) {
+ case "b": this.execCommand("bold"); break;
+ case "i": this.execCommand("italic"); break;
+ case "u": this.execCommand("underline"); break;
+ //case "a": this.execCommand("selectall"); break;
+ //case "k": this.execCommand("createlink", ""); break;
+ case "Z": this.execCommand("redo"); break;
+ case "s": this.close(true); break; // saves
+ default: switch (code) {
+ case e.KEY_LEFT_ARROW:
+ case e.KEY_RIGHT_ARROW:
+ //break; // preventDefault stops the browser
+ // going through its history
+ default:
+ preventDefault = false; break; // didn't handle here
+ }
+ }
+ } else {
+ switch (code) {
+ case e.KEY_TAB:
+ // commenting out bcs it's crashing FF
+ // this.execCommand(e.shiftKey ? "unindent" : "indent");
+ // break;
+ default:
+ preventDefault = false; break; // didn't handle here
+ }
+ }
+
+ if (preventDefault) { e.preventDefault(); }
+
+ // function call after the character has been inserted
+ dojo.lang.setTimeout(this, this.onKeyPressed, 1, e);
+ },
+
+ /**
+ * Fired after a keypress event has occured and it's action taken. This
+ * is useful if action needs to be taken after text operations have
+ * finished
+ */
+ onKeyPressed: function (e) {
+ // Mozilla adds a single <p> with an embedded <br> when you hit enter once:
+ // <p><br>\n</p>
+ // when you hit enter again it adds another <br> inside your enter
+ // <p><br>\n<br>\n</p>
+ // and if you hit enter again it splits the <br>s over 2 <p>s
+ // <p><br>\n</p>\n<p><br>\n</p>
+ // now this assumes that <p>s have double the line-height of <br>s to work
+ // and so we need to remove the <p>s to ensure the position of the cursor
+ // changes from the users perspective when they hit enter, as the second two
+ // html snippets render the same when margins are set to 0.
+
+ // TODO: doesn't really work; is this really needed?
+ //if (dojo.render.html.moz) {
+ // for (var i = 0; i < this.document.getElementsByTagName("p").length; i++) {
+ // var p = this.document.getElementsByTagName("p")[i];
+ // if (p.innerHTML.match(/^<br>\s$/m)) {
+ // while (p.hasChildNodes()) { p.parentNode.insertBefore(p.firstChild, p); }
+ // p.parentNode.removeChild(p);
+ // }
+ // }
+ //}
+ this.onDisplayChanged(/*e*/); // can't pass in e
+ },
+
+ onClick: function(e){ this.onDisplayChanged(e); },
+ onBlur: function(e){ },
+ _initialFocus: true,
+ onFocus: function(e){
+ if( (dojo.render.html.mozilla)&&(this._initialFocus) ){
+ this._initialFocus = false;
+ if(dojo.string.trim(this.editNode.innerHTML) == " "){
+ this.execCommand("selectall");
+ this.window.getSelection().collapseToStart();
+ }
+ }
+ },
+
+ blur: function () {
+ if (this.iframe) { this.window.blur(); }
+ else if (this.editNode) { this.editNode.blur(); }
+ },
+
+ focus: function () {
+ if(this.iframe){
+ this.window.focus();
+ }else if(this.editNode){
+ this.editNode.focus();
+ }
+ },
+
+ /** this event will be fired everytime the display context changes and the
+ result needs to be reflected in the UI */
+ onDisplayChanged: function (e){ },
+
+
+/* Formatting commands
+ **********************/
+
+ /** IE's Active X codes */
+ _activeX: {
+ command: {
+ bold: 5000,
+ italic: 5023,
+ underline: 5048,
+
+ justifycenter: 5024,
+ justifyleft: 5025,
+ justifyright: 5026,
+
+ cut: 5003,
+ copy: 5002,
+ paste: 5032,
+ "delete": 5004,
+
+ undo: 5049,
+ redo: 5033,
+
+ removeformat: 5034,
+ selectall: 5035,
+ unlink: 5050,
+
+ indent: 5018,
+ outdent: 5031,
+
+ insertorderedlist: 5030,
+ insertunorderedlist: 5051,
+
+ // table commands
+ inserttable: 5022,
+ insertcell: 5019,
+ insertcol: 5020,
+ insertrow: 5021,
+ deletecells: 5005,
+ deletecols: 5006,
+ deleterows: 5007,
+ mergecells: 5029,
+ splitcell: 5047,
+
+ // the command need mapping, they don't translate directly
+ // to the contentEditable commands
+ setblockformat: 5043,
+ getblockformat: 5011,
+ getblockformatnames: 5012,
+ setfontname: 5044,
+ getfontname: 5013,
+ setfontsize: 5045,
+ getfontsize: 5014,
+ setbackcolor: 5042,
+ getbackcolor: 5010,
+ setforecolor: 5046,
+ getforecolor: 5015,
+
+ findtext: 5008,
+ font: 5009,
+ hyperlink: 5016,
+ image: 5017,
+
+ lockelement: 5027,
+ makeabsolute: 5028,
+ sendbackward: 5036,
+ bringforward: 5037,
+ sendbelowtext: 5038,
+ bringabovetext: 5039,
+ sendtoback: 5040,
+ bringtofront: 5041,
+
+ properties: 5052
+ },
+
+ ui: {
+ "default": 0,
+ prompt: 1,
+ noprompt: 2
+ },
+
+ status: {
+ notsupported: 0,
+ disabled: 1,
+ enabled: 3,
+ latched: 7,
+ ninched: 11
+ },
+
+ appearance: {
+ flat: 0,
+ inset: 1
+ },
+
+ state: {
+ unchecked: 0,
+ checked: 1,
+ gray: 2
+ }
+ },
+
+ /**
+ * Used as the advice function by dojo.event.connect to map our
+ * normalized set of commands to those supported by the target
+ * browser
+ *
+ * @param arugments The arguments Array, containing at least one
+ * item, the command and an optional second item,
+ * an argument.
+ */
+ _normalizeCommand: function (joinObject){
+ var drh = dojo.render.html;
+
+ var command = joinObject.args[0].toLowerCase();
+ if(command == "formatblock"){
+ if(drh.safari){ command = "heading"; }
+ if(drh.ie){ joinObject.args[1] = "<"+joinObject.args[1]+">"; }
+ }
+ if (command == "hilitecolor" && !drh.mozilla) { command = "backcolor"; }
+ joinObject.args[0] = command;
+
+ if (joinObject.args.length > 1) { // a command was specified
+ var argument = joinObject.args[1];
+ if (command == "heading") { throw new Error("unimplemented"); }
+ joinObject.args[1] = argument;
+ }
+
+ return joinObject.proceed();
+ },
+
+ /**
+ * Tests whether a command is supported by the host. Clients SHOULD check
+ * whether a command is supported before attempting to use it, behaviour
+ * for unsupported commands is undefined.
+ *
+ * @param command The command to test for
+ * @return true if the command is supported, false otherwise
+ */
+ queryCommandAvailable: function (command) {
+ var ie = 1;
+ var mozilla = 1 << 1;
+ var safari = 1 << 2;
+ var opera = 1 << 3;
+ function isSupportedBy (browsers) {
+ return {
+ ie: Boolean(browsers & ie),
+ mozilla: Boolean(browsers & mozilla),
+ safari: Boolean(browsers & safari),
+ opera: Boolean(browsers & opera)
+ }
+ }
+
+ var supportedBy = null;
+
+ switch (command.toLowerCase()) {
+ case "bold": case "italic": case "underline":
+ case "subscript": case "superscript":
+ case "fontname": case "fontsize":
+ case "forecolor": case "hilitecolor":
+ case "justifycenter": case "justifyfull": case "justifyleft": case "justifyright":
+ case "cut": case "copy": case "paste": case "delete":
+ case "undo": case "redo":
+ supportedBy = isSupportedBy(mozilla | ie | safari | opera);
+ break;
+
+ case "createlink": case "unlink": case "removeformat":
+ case "inserthorizontalrule": case "insertimage":
+ case "insertorderedlist": case "insertunorderedlist":
+ case "indent": case "outdent": case "formatblock": case "strikethrough":
+ supportedBy = isSupportedBy(mozilla | ie | opera);
+ break;
+
+ case "blockdirltr": case "blockdirrtl":
+ case "dirltr": case "dirrtl":
+ case "inlinedirltr": case "inlinedirrtl":
+ supportedBy = isSupportedBy(ie);
+ break;
+
+ case "inserttable":
+ supportedBy = isSupportedBy(mozilla | (this.object ? ie : 0));
+ break;
+
+ case "insertcell": case "insertcol": case "insertrow":
+ case "deletecells": case "deletecols": case "deleterows":
+ case "mergecells": case "splitcell":
+ supportedBy = isSupportedBy(this.object ? ie : 0);
+ break;
+
+ default: return false;
+ }
+
+ return (dojo.render.html.ie && supportedBy.ie) ||
+ (dojo.render.html.mozilla && supportedBy.mozilla) ||
+ (dojo.render.html.safari && supportedBy.safari) ||
+ (dojo.render.html.opera && supportedBy.opera);
+ },
+
+ /**
+ * Executes a command in the Rich Text area
+ *
+ * @param command The command to execute
+ * @param argument An optional argument to the command
+ */
+ execCommand: function (command, argument) {
+ if (this.object) {
+ if (command == "forecolor") { command = "setforecolor"; }
+ else if (command == "backcolor") { command = "setbackcolor"; }
+
+ //if (typeof this._activeX.command[command] == "undefined") { return null; }
+
+ if (command == "inserttable") {
+ var tableInfo = this.constructor._tableInfo;
+ if (!tableInfo) {
+ tableInfo = document.createElement("object");
+ tableInfo.classid = "clsid:47B0DFC7-B7A3-11D1-ADC5-006008A5848C";
+ document.body.appendChild(tableInfo);
+ this.constructor._table = tableInfo;
+ }
+
+ tableInfo.NumRows = argument.rows;
+ tableInfo.NumCols = argument.cols;
+ tableInfo.TableAttrs = argument["TableAttrs"];
+ tableInfo.CellAttrs = arr["CellAttrs"];
+ tableInfo.Caption = arr["Caption"];
+ }
+
+ if (arguments.length == 1) {
+ return this.object.ExecCommand(this._activeX.command[command],
+ this._activeX.ui.noprompt);
+ } else {
+ return this.object.ExecCommand(this._activeX.command[command],
+ this._activeX.ui.noprompt, argument);
+ }
+
+ // fix up unlink in Mozilla to unlink the link and not just the selection
+ } else if (command == "unlink" &&
+ this.queryCommandEnabled("unlink") && dojo.render.html.mozilla) {
+ // grab selection
+ // Mozilla gets upset if we just store the range so we have to
+ // get the basic properties and recreate to save the selection
+ var selection = this.window.getSelection();
+ var selectionRange = selection.getRangeAt(0);
+ var selectionStartContainer = selectionRange.startContainer;
+ var selectionStartOffset = selectionRange.startOffset;
+ var selectionEndContainer = selectionRange.endContainer;
+ var selectionEndOffset = selectionRange.endOffset;
+
+ // select our link and unlink
+ var range = document.createRange();
+ var a = this.getSelectedNode();
+ while (a.nodeName != "A") { a = a.parentNode; }
+ range.selectNode(a);
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var returnValue = this.document.execCommand("unlink", false, null);
+
+ // restore original selection
+ var selectionRange = document.createRange();
+ selectionRange.setStart(selectionStartContainer, selectionStartOffset);
+ selectionRange.setEnd(selectionEndContainer, selectionEndOffset);
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+
+ return returnValue;
+ } else if (command == "inserttable" && dojo.render.html.mozilla) {
+
+ var cols = "<tr>";
+ for (var i = 0; i < argument.cols; i++) { cols += "<td></td>"; }
+ cols += "</tr>";
+
+ var table = "<table><tbody>";
+ for (var i = 0; i < argument.rows; i++) { table += cols; }
+ table += "</tbody></table>";
+ var returnValue = this.document.execCommand("inserthtml", false, table);
+
+ } else if (command == "hilitecolor" && dojo.render.html.mozilla) {
+ // mozilla doesn't support hilitecolor properly when useCSS is
+ // set to false (bugzilla #279330)
+
+ this.document.execCommand("useCSS", false, false);
+ var returnValue = this.document.execCommand(command, false, argument);
+ this.document.execCommand("useCSS", false, true);
+
+ } else {
+ argument = arguments.length > 1 ? argument : null;
+ var returnValue = this.document.execCommand(command, false, argument);
+ }
+
+ this.onDisplayChanged();
+ return returnValue;
+ },
+
+ queryCommandEnabled: function (command, argument) {
+ if (this.object) {
+ if (command == "forecolor") { command = "setforecolor"; }
+ else if (command == "backcolor") { command = "setbackcolor"; }
+
+ if (typeof this._activeX.command[command] == "undefined") { return false; }
+ var status = this.object.QueryStatus(this._activeX.command[command]);
+ return (status != this.activeX.status.notsupported &&
+ status != this.activeX.status.diabled);
+ } else {
+ // mozilla returns true always
+ if (command == "unlink" && dojo.render.html.mozilla) {
+ var node = this.getSelectedNode();
+ while (node.parentNode && node.nodeName != "A") { node = node.parentNode; }
+ return node.nodeName == "A";
+ } else if (command == "inserttable" && dojo.render.html.mozilla) {
+ return true;
+ }
+ return this.document.queryCommandEnabled(command);
+ }
+ },
+
+ queryCommandState: function (command, argument) {
+ if (this.object) {
+ if (command == "forecolor") { command = "setforecolor"; }
+ else if (command == "backcolor") { command = "setbackcolor"; }
+
+ if (typeof this._activeX.command[command] == "undefined") { return null; }
+ var status = this.object.QueryStatus(this._activeX.command[command]);
+ return (status == this._activeX.status.enabled ||
+ status == this._activeX.status.ninched);
+ } else {
+ return this.document.queryCommandState(command);
+ }
+ },
+
+ queryCommandValue: function (command, argument) {
+ if (this.object) {
+ switch (command) {
+ case "forecolor":
+ case "backcolor":
+ case "fontsize":
+ case "fontname":
+ case "blockformat":
+ command = "get" + command;
+ return this.object.execCommand(
+ this._activeX.command[command],
+ this._activeX.ui.noprompt);
+ }
+
+ //var status = this.object.QueryStatus(this._activeX.command[command]);
+ } else {
+ return this.document.queryCommandValue(command);
+ }
+ },
+
+
+/* Misc.
+ ********/
+
+ getSelectedNode: function () {
+ if(!this.isLoaded){ return; }
+ if (this.document.selection) {
+ return this.document.selection.createRange().parentElement();
+ } else if (dojo.render.html.mozilla) {
+ return this.window.getSelection().getRangeAt(0).commonAncestorContainer;
+ }
+ return this.editNode;
+ },
+
+ placeCursorAtStart: function () {
+ if(!this.isLoaded){
+ dojo.event.connect(this, "onLoad", this, "placeCursorAtEnd");
+ return;
+ }
+ dojo.event.disconnect(this, "onLoad", this, "placeCursorAtEnd");
+ if (this.window.getSelection) {
+ var selection = this.window.getSelection;
+ if (selection.removeAllRanges) { // Mozilla
+ var range = this.document.createRange();
+ range.selectNode(this.editNode.firstChild);
+ range.collapse(true);
+ var selection = this.window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+ } else { // Safari
+ // not a great deal we can do
+ }
+ } else if (this.document.selection) { // IE
+ var range = this.document.body.createTextRange();
+ range.moveToElementText(this.editNode);
+ range.collapse(true);
+ range.select();
+ }
+ },
+
+ placeCursorAtEnd: function () {
+ if(!this.isLoaded){
+ dojo.event.connect(this, "onLoad", this, "placeCursorAtEnd");
+ return;
+ }
+ dojo.event.disconnect(this, "onLoad", this, "placeCursorAtEnd");
+ if (this.window.getSelection) {
+ var selection = this.window.getSelection;
+ if (selection.removeAllRanges) { // Mozilla
+ var range = this.document.createRange();
+ range.selectNode(this.editNode.lastChild);
+ range.collapse(false);
+ var selection = this.window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+ } else { // Safari
+ // not a great deal we can do
+ }
+ } else if (this.document.selection) { // IE
+ var range = this.document.body.createTextRange();
+ range.moveToElementText(this.editNode);
+ range.collapse(true);
+ range.select();
+ }
+ },
+
+ _lastHeight: 0,
+
+ /** Updates the height of the iframe to fit the contents. */
+ _updateHeight: function () {
+ if (this.iframe) {
+ /*
+ if(!this.document.body["offsetHeight"]){
+ return;
+ }
+ */
+ // The height includes the padding, borders and margins so these
+ // need to be added on
+ var heights = ["margin-top", "margin-bottom",
+ "padding-bottom", "padding-top",
+ "border-width-bottom", "border-width-top"];
+ for (var i = 0, chromeheight = 0; i < heights.length; i++) {
+ var height = dojo.style.getStyle(this.iframe, heights[i]);
+ // Safari doesn't have all the heights so we have to test
+ if (height) {
+ chromeheight += Number(height.replace(/[^0-9]/g, ""));
+ }
+ }
+ // dojo.debug(this.document.body.offsetHeight);
+ // dojo.debug(chromeheight);
+ if(this.document.body["offsetHeight"]){
+ this._lastHeight = this.document.body.offsetHeight + chromeheight;
+ this.iframe.height = this._lastHeight + "px";
+ this.window.scrollTo(0, 0);
+ }
+ // this.iframe.height = this._lastHeight + "px";
+ // dojo.debug(this.iframe.height);
+ } else if (this.object) {
+ this.object.height = dojo.style.getInnerHeight(this.editNode);
+ }
+ },
+
+ /**
+ * Saves the content in an onunload event if the editor has not been closed
+ */
+ _saveContent: function(e){
+ var saveTextarea = document.getElementById("dojo.widget.RichText.savedContent");
+ saveTextarea.value += this._SEPARATOR + this.saveName + ":" + this.getEditorContent();
+ },
+
+ getEditorContent: function(){
+ var ec = "";
+ try{
+ ec = (this._content.length > 0) ? this._content : this.editNode.innerHTML;
+ if(dojo.string.trim(ec) == " "){ ec = ""; }
+ }catch(e){ /* squelch */ }
+
+ dojo.lang.forEach(this.contentFilters, function(ef){
+ ec = ef(ec);
+ });
+ return ec;
+ },
+
+ /**
+ * Kills the editor and optionally writes back the modified contents to the
+ * element from which it originated.
+ *
+ * @param save Whether or not to save the changes. If false, the changes are
+ * discarded.
+ * @return true if the contents has been modified, false otherwise
+ */
+ close: function(save, force){
+ if(this.isClosed){return false; }
+
+ if (arguments.length == 0) { save = true; }
+ this._content = this.editNode.innerHTML;
+ var changed = (this.savedContent.innerHTML != this._content);
+
+ // line height is squashed for iframes
+ if (this.iframe){ this.domNode.style.lineHeight = null; }
+
+ if(this.interval){ clearInterval(this.interval); }
+
+ if(dojo.render.html.ie && !this.object){
+ dojo.event.browser.clean(this.editNode);
+ }
+ if(dojo.render.html.moz){
+ var ifr = this.domNode.firstChild;
+ ifr.style.display = "none";
+ /*
+ setTimeout(function(){
+ ifr.parentNode.removeChild(ifr);
+ }, 0);
+ */
+ }else{
+ this.domNode.innerHTML = "";
+ }
+ // dojo.dom.removeChildren(this.domNode);
+ if(save){
+ // kill listeners on the saved content
+ dojo.event.browser.clean(this.savedContent);
+ if(dojo.render.html.moz){
+ var nc = document.createElement("span");
+ this.domNode.appendChild(nc);
+ nc.innerHTML = this.editNode.innerHTML;
+ }else{
+ this.domNode.innerHTML = this._content;
+ }
+ } else {
+ while (this.savedContent.hasChildNodes()) {
+ this.domNode.appendChild(this.savedContent.firstChild);
+ }
+ }
+ delete this.savedContent;
+
+ dojo.html.removeClass(this.domNode, "RichTextEditable");
+ this.isClosed = true;
+ this.isLoaded = false;
+
+ return changed;
+ },
+
+ destroy: function () {
+ if (!this.isClosed) { this.close(false); }
+
+ // disconnect those listeners.
+ while (this._connected.length) {
+ this.disconnect(this._connected[0],
+ this._connected[1], this._connected[2]);
+ }
+ },
+
+ _connected: [],
+ connect: function (targetObj, targetFunc, thisFunc) {
+ dojo.event.connect(targetObj, targetFunc, this, thisFunc);
+ // this._connected.push([targetObj, targetFunc, thisFunc]);
+ },
+
+ // FIXME: below two functions do not work with the above line commented out
+ disconnect: function (targetObj, targetFunc, thisFunc) {
+ for (var i = 0; i < this._connected.length; i++) {
+ if (this._connected[0] == targetObj &&
+ this._connected[1] == targetFunc &&
+ this._connected[2] == thisFunc) {
+ dojo.event.disconnect(targetObj, targetFunc, this, thisFunc);
+ this._connected.splice(i, 1);
+ break;
+ }
+ }
+ },
+
+ disconnectAllWithRoot: function (targetObj) {
+ for (var i = 0; i < this._connected.length; i++) {
+ if (this._connected[0] == targetObj) {
+ dojo.event.disconnect(targetObj,
+ this._connected[1], this, this._connected[2]);
+ this._connected.splice(i, 1);
+ }
+ }
+ }
+
+});
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SimpleDropdownButtons.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SimpleDropdownButtons.js?rev=385171&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SimpleDropdownButtons.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SimpleDropdownButtons.js Sat Mar 11 13:18:41 2006
@@ -0,0 +1,158 @@
+/*
+ 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
+*/
+
+/* TODO:
+ * - make the dropdowns "smart" so they can't get cutoff on bottom of page, sides of page, etc.
+ * - unify menus with the MenuItem and Menu classes so we can add stuff to all menus at once
+ * - allow buttons to be enabled/disabled at runtime
+ * - this probably means creating all menus upfront and then triggering a disable action
+ * for disabled buttons in the constructor loop. we'll need a disable and enable action anyway
+ * - should each button with menu be a widget object of it's own?
+ */
+dojo.provide("dojo.widget.SimpleDropdownButtons");
+dojo.provide("dojo.widget.HtmlSimpleDropdownButtons");
+
+dojo.deprecated("dojo.widget.SimpleDropdownButtons", "use dojo.widget.DropDownButton2", "0.4");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.dom");
+dojo.require("dojo.style");
+dojo.require("dojo.html");
+
+dojo.widget.tags.addParseTreeHandler("dojo:simpledropdownbuttons");
+
+dojo.widget.HtmlSimpleDropdownButtons = function() {
+ dojo.widget.HtmlWidget.call(this);
+
+ this.widgetType = "SimpleDropdownButtons";
+ this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlSimpleDropdownButtons.css");
+
+ this.menuTriggerClass = "dojoSimpleDropdownButtons";
+ this.menuClass = "dojoSimpleDropdownButtonsMenu";
+
+ // overwrite buildRendering so we don't clobber our list
+ this.buildRendering = function(args, frag) {
+ if(this.templateCssPath) {
+ dojo.style.insertCssFile(this.templateCssPath, null, true);
+ }
+ this.domNode = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+
+ var menu = this.domNode;
+ if( !dojo.html.hasClass(menu, this.menuTriggerClass) ) {
+ dojo.html.addClass(menu, this.menuTriggerClass);
+ }
+ var li = dojo.dom.getFirstChildElement(menu);
+ var menuIDs = [];
+ var arrowIDs = [];
+
+ while(li) {
+ if(li.getElementsByTagName("ul").length > 0) {
+ var a = dojo.dom.getFirstChildElement(li);
+ var arrow = document.createElement("a");
+ arrow.href = "javascript:;";
+ arrow.innerHTML = " ";
+ dojo.html.setClass(arrow, "downArrow");
+ if(!arrow.id) {
+ arrow.id = dojo.dom.getUniqueId();
+ }
+ arrowIDs.push(arrow.id);
+ var submenu = dojo.dom.getNextSiblingElement(a);
+ if(!submenu.id) {
+ submenu.id = dojo.dom.getUniqueId();
+ }
+ menuIDs.push(submenu.id);
+
+ if( dojo.html.hasClass(a, "disabled") ) {
+ dojo.html.addClass(arrow, "disabled");
+ dojo.html.disableSelection(li);
+ arrow.onfocus = function(){ this.blur(); }
+ } else {
+ dojo.html.addClass(submenu, this.menuClass);
+ document.body.appendChild(submenu);
+ dojo.event.connect(arrow, "onmousedown", (function() {
+ var ar = arrow;
+ return function(e) {
+ dojo.html.addClass(ar, "pressed");
+ }
+ })());
+ dojo.event.connect(arrow, "onclick", (function() {
+ var aa = a;
+ var ar = arrow;
+ var sm = submenu;
+ var setWidth = false;
+
+ return function(e) {
+ hideAll(sm, ar);
+ sm.style.left = (dojo.html.getScrollLeft()
+ + e.clientX - e.layerX + aa.offsetLeft) + "px";
+ sm.style.top = (dojo.html.getScrollTop() + e.clientY
+ - e.layerY + aa.offsetTop + aa.offsetHeight) + "px";
+ sm.style.display = sm.style.display == "block" ? "none" : "block";
+ if(sm.style.display == "none") {
+ dojo.html.removeClass(ar, "pressed");
+ e.target.blur()
+ }
+ if(!setWidth && sm.style.display == "block"
+ && sm.offsetWidth < aa.offsetWidth + ar.offsetWidth) {
+ sm.style.width = aa.offsetWidth + ar.offsetWidth + "px";
+ setWidth = true;
+ }
+ e.preventDefault();
+ }
+ })());
+ }
+
+ dojo.event.connect(a, "onclick", function(e) {
+ if(e && e.target && e.target.blur) {
+ e.target.blur();
+ }
+ });
+
+ if(a.nextSibling) {
+ li.insertBefore(arrow, a.nextSibling);
+ } else {
+ li.appendChild(arrow);
+ }
+
+ }
+ li = dojo.dom.getNextSiblingElement(li);
+ }
+
+ function hideAll(excludeMenu, excludeArrow) {
+ // hide menus
+ for(var i = 0; i < menuIDs.length; i++) {
+ var m = document.getElementById(menuIDs[i]);
+ if(!excludeMenu || m != excludeMenu) {
+ document.getElementById(menuIDs[i]).style.display = "none";
+ }
+ }
+ // restore arrows to non-pressed state
+ for(var i = 0; i < arrowIDs.length; i++) {
+ var m = document.getElementById(arrowIDs[i]);
+ if(!excludeArrow || m != excludeArrow) {
+ dojo.html.removeClass(m, "pressed");
+ }
+ }
+ }
+
+ dojo.event.connect(document.documentElement, "onmousedown", function(e) {
+ if( dojo.html.hasClass(e.target, "downArrow") ) { return };
+ for(var i = 0; i < menuIDs.length; i++) {
+ if( dojo.dom.isDescendantOf(e.target, document.getElementById(menuIDs[i])) ) {
+ return;
+ }
+ }
+ hideAll();
+ });
+ }
+}
+dojo.inherits(dojo.widget.HtmlSimpleDropdownButtons, dojo.widget.HtmlWidget);
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SlideShow.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SlideShow.js?rev=385171&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SlideShow.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SlideShow.js Sat Mar 11 13:18:41 2006
@@ -0,0 +1,133 @@
+/*
+ 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.SlideShow");
+dojo.provide("dojo.widget.html.SlideShow");
+
+dojo.require("dojo.event");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.fx.html");
+dojo.require("dojo.style");
+
+dojo.widget.html.SlideShow = function(){
+ dojo.widget.HtmlWidget.call(this);
+
+ this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlSlideShow.html");
+ this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlSlideShow.css");
+
+ // over-ride some defaults
+ this.isContainer = false;
+ this.widgetType = "SlideShow";
+
+ // useful properties
+ this.imgUrls = []; // the images we'll go through
+ this.imgUrlBase = "";
+ this.urlsIdx = 0; // where in the images we are
+ this.delay = 4000; // give it 4 seconds
+ this.transitionInterval = 2000; // 2 seconds
+ this.imgWidth = 800; // img width
+ this.imgHeight = 600; // img height
+ this.background = "img2"; // what's in the bg
+ this.foreground = "img1"; // what's in the fg
+ this.stopped = false; // should I stay or should I go?
+ this.fadeAnim = null; // references our animation
+
+ // our DOM nodes:
+ this.imagesContainer = null;
+ this.startStopButton = null;
+ this.controlsContainer = null;
+ this.img1 = null;
+ this.img2 = null;
+
+ this.fillInTemplate = function(){
+ dojo.style.setOpacity(this.img1, 0.9999);
+ dojo.style.setOpacity(this.img2, 0.9999);
+ with(this.imagesContainer.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ with(this.img1.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ with(this.img2.style){
+ width = this.imgWidth+"px";
+ height = this.imgHeight+"px";
+ }
+ if(this.imgUrls.length>1){
+ this.img2.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
+ this.endTransition();
+ }else{
+ this.img1.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
+ }
+ }
+
+ this.togglePaused = function(){
+ if(this.stopped){
+ this.stopped = false;
+ this.endTransition();
+ this.startStopButton.value= "pause";
+ }else{
+ this.stopped = true;
+ this.startStopButton.value= "play";
+ }
+ }
+
+ this.backgroundImageLoaded = function(){
+ // start fading out the foreground image
+ if(this.stopped){ return; }
+ // closure magic for callback
+ var _this = this;
+ var callback = function(){ _this.endTransition(); };
+
+ // actually start the fadeOut effect
+ // NOTE: if we wanted to use other transition types, we'd set them up
+ // here as well
+ if(this.fadeAnim) {
+ this.fadeAnim.stop();
+ }
+ this.fadeAnim = dojo.fx.html.fadeOut(this[this.foreground],
+ this.transitionInterval, callback);
+ }
+
+ this.endTransition = function(){
+ // move the foreground image to the background
+ with(this[this.background].style){ zIndex = parseInt(zIndex)+1; }
+ with(this[this.foreground].style){ zIndex = parseInt(zIndex)-1; }
+
+ // fg/bg book-keeping
+ var tmp = this.foreground;
+ this.foreground = this.background;
+ this.background = tmp;
+
+ // keep on truckin
+ this.loadNextImage();
+ }
+
+ this.loadNextImage = function(){
+ // load a new image in that container, and make sure it informs
+ // us when it finishes loading
+ dojo.event.kwConnect({
+ srcObj: this[this.background],
+ srcFunc: "onload",
+ adviceObj: this,
+ adviceFunc: "backgroundImageLoaded",
+ once: true, // make sure we only ever hear about it once
+ delay: this.delay
+ });
+ dojo.style.setOpacity(this[this.background], 1.0);
+ this[this.background].src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
+ if(this.urlsIdx>(this.imgUrls.length-1)){
+ this.urlsIdx = 0;
+ }
+ }
+}
+dojo.inherits(dojo.widget.html.SlideShow, dojo.widget.HtmlWidget);
+dojo.widget.tags.addParseTreeHandler("dojo:slideshow");
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SortableTable.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SortableTable.js?rev=385171&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SortableTable.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SortableTable.js Sat Mar 11 13:18:41 2006
@@ -0,0 +1,38 @@
+/*
+ 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.SortableTable");
+dojo.require("dojo.widget.*");
+dojo.requireAfterIf("html", "dojo.widget.html.SortableTable");
+dojo.widget.tags.addParseTreeHandler("dojo:sortableTable");
+
+// set up the general widget
+dojo.widget.SortableTable=function(){
+ // summary
+ // base class for the SortableTable
+ dojo.widget.Widget.call(this);
+ this.widgetType="SortableTable";
+ this.isContainer=false;
+
+ // custom properties
+ this.enableMultipleSelect=false;
+ this.maximumNumberOfSelections=0; // 0 for unlimited, is the default.
+ this.enableAlternateRows=false;
+ this.minRows=0; // 0 means ignore.
+ this.defaultDateFormat="%D";
+ this.data=[];
+ this.selected=[]; // always an array to handle multiple selections.
+ this.columns=[];
+ this.sortIndex=0; // index of the column sorted on, first is the default.
+ this.sortDirection=0; // 0==asc, 1==desc
+ this.valueField="Id"; // if a JSON structure is parsed and there is a field of this name,
+ // a value attribute will be added to the row (tr value="{Id}")
+};
+dojo.inherits(dojo.widget.SortableTable, dojo.widget.Widget);
Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SplitPane.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SplitPane.js?rev=385171&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SplitPane.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/SplitPane.js Sat Mar 11 13:18:41 2006
@@ -0,0 +1,549 @@
+/*
+ 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.SplitPane");
+dojo.provide("dojo.widget.SplitPanePanel");
+dojo.provide("dojo.widget.html.SplitPane");
+dojo.provide("dojo.widget.html.SplitPanePanel");
+
+//
+// TODO
+// make it prettier
+// active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
+//
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.LayoutPane");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.dom");
+
+dojo.widget.html.SplitPane = function(){
+
+ dojo.widget.HtmlWidget.call(this);
+
+ this.sizers = [];
+}
+
+dojo.inherits(dojo.widget.html.SplitPane, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.SplitPane, {
+ widgetType: "SplitPane",
+ isContainer: true,
+
+ virtualSizer: null,
+ isHorizontal: 0,
+ paneBefore: null,
+ paneAfter: null,
+ isSizing: false,
+ dragOffset: null,
+ startPoint: null,
+ lastPoint: null,
+ sizingSplitter: null,
+ isActiveResize: 0,
+ offsetX: 0,
+ offsetY: 0,
+ isDraggingLeft: 0,
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSplitPane.css"),
+ originPos: null,
+
+ activeSizing: '',
+ sizerWidth: 15,
+ orientation: 'horizontal',
+
+ debugName: '',
+
+ fillInTemplate: function(){
+
+ dojo.style.insertCssFile(this.templateCssPath, null, true);
+ dojo.html.addClass(this.domNode, "dojoHtmlSplitPane");
+ this.domNode.style.overflow='hidden'; // workaround firefox bug
+
+ this.paneWidth = dojo.style.getContentWidth(this.domNode);
+ this.paneHeight = dojo.style.getContentHeight(this.domNode);
+
+ this.isHorizontal = (this.orientation == 'horizontal') ? 1 : 0;
+ this.isActiveResize = (this.activeSizing == '1') ? 1 : 0;
+
+ //dojo.debug("fillInTemplate for "+this.debugName);
+ },
+
+ onResized: function(e){
+ this.paneWidth = dojo.style.getContentWidth(this.domNode);
+ this.paneHeight = dojo.style.getContentHeight(this.domNode);
+ this.layoutPanels();
+ this.notifyChildrenOfResize(); // notify children they've been moved/resized
+ },
+
+ postCreate: function(args, fragment, parentComp){
+
+ // dojo.debug("post create for "+this.debugName);
+
+ // attach the children and create the draggers
+ for(var i=0; i<this.children.length; i++){
+ with(this.children[i].domNode.style){
+ position = "absolute";
+ }
+ dojo.html.addClass(this.children[i].domNode,
+ "dojoHtmlSplitterPanePanel");
+
+ if(i == this.children.length-1){
+ break;
+ }
+
+ this._addSizer();
+ }
+
+ // create the fake dragger
+ this.virtualSizer = document.createElement('div');
+ this.virtualSizer.style.position = 'absolute';
+ this.virtualSizer.style.display = 'none';
+ //this.virtualSizer.style.backgroundColor = 'lime';
+ this.virtualSizer.style.zIndex = 10;
+ this.virtualSizer.className = this.isHorizontal ? 'dojoHtmlSplitPaneVirtualSizerH' : 'dojoHtmlSplitPaneVirtualSizerV';
+ this.domNode.appendChild(this.virtualSizer);
+
+ dojo.html.disableSelection(this.virtualSizer);
+
+ // size the panels once the browser has caught up
+ this.resizeSoon();
+ },
+
+ _injectChild: function(child) {
+ with(child.domNode.style){
+ position = "absolute";
+ }
+ dojo.html.addClass(child.domNode,
+ "dojoHtmlSplitterPanePanel");
+ },
+
+ _addSizer: function() {
+ var i = this.sizers.length;
+
+ this.sizers[i] = document.createElement('div');
+ this.sizers[i].style.position = 'absolute';
+ this.sizers[i].className = this.isHorizontal ? 'dojoHtmlSplitPaneSizerH' : 'dojoHtmlSplitPaneSizerV';
+
+ var self = this;
+ var handler = (function(){ var sizer_i = i; return function(e){ self.beginSizing(e, sizer_i); } })();
+ dojo.event.connect(this.sizers[i], "onmousedown", handler);
+
+ this.domNode.appendChild(this.sizers[i]);
+ dojo.html.disableSelection(this.sizers[i]);
+ },
+
+ removeChild: function(widget){
+ // Remove sizer, but only if widget is really our child and
+ // we have at least one sizer to throw away
+ if (this.sizers.length > 0) {
+ for(var x=0; x<this.children.length; x++){
+ if(this.children[x] === widget){
+ var i = this.sizers.length - 1;
+ this.domNode.removeChild(this.sizers[i]);
+ this.sizers.length = i;
+ break;
+ }
+ }
+ }
+
+ // Remove widget and repaint
+ dojo.widget.html.SplitPane.superclass.removeChild.call(this, widget, arguments);
+ this.onResized();
+ },
+
+ addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
+ dojo.widget.html.SplitPane.superclass.addChild.call(this, widget, overrideContainerNode, pos, ref, insertIndex);
+ this._injectChild(widget);
+
+ if (this.children.length > 1) {
+ this._addSizer();
+ }
+
+ this.layoutPanels();
+ },
+
+ layoutPanels: function(){
+ if (this.children.length == 0){ return; }
+
+ //
+ // calculate space
+ //
+
+ var space = this.isHorizontal ? this.paneWidth : this.paneHeight;
+
+ if (this.children.length > 1){
+
+ space -= this.sizerWidth * (this.children.length - 1);
+ }
+
+
+ //
+ // calculate total of SizeShare values
+ //
+
+ var out_of = 0;
+
+ for(var i=0; i<this.children.length; i++){
+
+ out_of += this.children[i].sizeShare;
+ }
+
+
+ //
+ // work out actual pixels per sizeshare unit
+ //
+
+ var pix_per_unit = space / out_of;
+
+
+ //
+ // set the SizeActual member of each pane
+ //
+
+ var total_size = 0;
+
+ for(var i=0; i<this.children.length-1; i++){
+
+ var size = Math.round(pix_per_unit * this.children[i].sizeShare);
+ this.children[i].sizeActual = size;
+ total_size += size;
+ }
+ this.children[this.children.length-1].sizeActual = space - total_size;
+
+ //
+ // make sure the sizes are ok
+ //
+
+ this.checkSizes();
+
+
+ //
+ // now loop, positioning each pane and letting children resize themselves
+ //
+
+ var pos = 0;
+ var size = this.children[0].sizeActual;
+ this.movePanel(this.children[0].domNode, pos, size);
+ this.children[0].position = pos;
+ this.children[0].onResized();
+ pos += size;
+
+ for(var i=1; i<this.children.length; i++){
+
+ // first we position the sizing handle before this pane
+ this.movePanel(this.sizers[i-1], pos, this.sizerWidth);
+ this.sizers[i-1].position = pos;
+ pos += this.sizerWidth;
+
+ size = this.children[i].sizeActual;
+ this.movePanel(this.children[i].domNode, pos, size);
+ this.children[i].position = pos;
+ this.children[i].onResized();
+ pos += size;
+ }
+ },
+
+ movePanel: function(panel, pos, size){
+ if (this.isHorizontal){
+ panel.style.left = pos + 'px';
+ panel.style.top = 0;
+
+ dojo.style.setOuterWidth(panel, size);
+ dojo.style.setOuterHeight(panel, this.paneHeight);
+ }else{
+ panel.style.left = 0;
+ panel.style.top = pos + 'px';
+
+ dojo.style.setOuterWidth(panel, this.paneWidth);
+ dojo.style.setOuterHeight(panel, size);
+ }
+ },
+
+ growPane: function(growth, pane){
+
+ if (growth > 0){
+ if (pane.sizeActual > pane.sizeMin){
+ if ((pane.sizeActual - pane.sizeMin) > growth){
+
+ // stick all the growth in this pane
+ pane.sizeActual = pane.sizeActual - growth;
+ growth = 0;
+ }else{
+ // put as much growth in here as we can
+ growth -= pane.sizeActual - pane.sizeMin;
+ pane.sizeActual = pane.sizeMin;
+ }
+ }
+ }
+ return growth;
+ },
+
+ checkSizes: function(){
+
+ var total_min_size = 0;
+ var total_size = 0;
+
+ for(var i=0; i<this.children.length; i++){
+
+ total_size += this.children[i].sizeActual;
+ total_min_size += this.children[i].sizeMin;
+ }
+
+ // only make adjustments if we have enough space for all the minimums
+
+ if (total_min_size <= total_size){
+
+ var growth = 0;
+
+ for(var i=0; i<this.children.length; i++){
+
+ if (this.children[i].sizeActual < this.children[i].sizeMin){
+
+ growth += this.children[i].sizeMin - this.children[i].sizeActual;
+ this.children[i].sizeActual = this.children[i].sizeMin;
+ }
+ }
+
+ if (growth > 0){
+ if (this.isDraggingLeft){
+ for(var i=this.children.length-1; i>=0; i--){
+ growth = this.growPane(growth, this.children[i]);
+ }
+ }else{
+ for(var i=0; i<this.children.length; i++){
+ growth = this.growPane(growth, this.children[i]);
+ }
+ }
+ }
+ }else{
+
+ for(var i=0; i<this.children.length; i++){
+ this.children[i].sizeActual = Math.round(total_size * (this.children[i].sizeMin / total_min_size));
+ }
+ }
+ },
+
+ beginSizing: function(e, i){
+ var clientX = window.event ? window.event.offsetX : e.layerX;
+ var clientY = window.event ? window.event.offsetY : e.layerY;
+ var screenX = window.event ? window.event.clientX : e.pageX;
+ var screenY = window.event ? window.event.clientY : e.pageY;
+
+ this.paneBefore = this.children[i];
+ this.paneAfter = this.children[i+1];
+
+ this.isSizing = true;
+ this.sizingSplitter = this.sizers[i];
+ this.originPos = dojo.style.getAbsolutePosition(this.domNode, true);
+ this.dragOffset = {'x':clientX, 'y':clientY};
+ this.startPoint = {'x':screenX, 'y':screenY};
+ this.lastPoint = {'x':screenX, 'y':screenY};
+
+ this.offsetX = screenX - clientX;
+ this.offsetY = screenY - clientY;
+
+ if (!this.isActiveResize){
+ this.showSizingLine();
+ }
+
+ //
+ // attach mouse events
+ //
+
+ dojo.event.connect(document.documentElement, "onmousemove", this, "changeSizing");
+ dojo.event.connect(document.documentElement, "onmouseup", this, "endSizing");
+ },
+
+ changeSizing: function(e){
+
+ // FIXME: is this fixed in connect()?
+ var screenX = window.event ? window.event.clientX : e.pageX;
+ var screenY = window.event ? window.event.clientY : e.pageY;
+
+ if (this.isActiveResize){
+ this.lastPoint = {'x':screenX, 'y':screenY};
+ this.movePoint();
+ this.updateSize();
+ }else{
+ this.lastPoint = {'x':screenX, 'y':screenY};
+ this.movePoint();
+ this.moveSizingLine();
+ }
+ },
+
+ endSizing: function(e){
+
+ if (!this.isActiveResize){
+ this.hideSizingLine();
+ }
+
+ this.updateSize();
+
+ this.isSizing = false;
+
+ dojo.event.disconnect(document.documentElement, "onmousemove", this, "changeSizing");
+ dojo.event.disconnect(document.documentElement, "onmouseup", this, "endSizing");
+ },
+
+ movePoint: function(){
+
+ // make sure FLastPoint is a legal point to drag to
+ p = this.screenToMainClient(this.lastPoint);
+
+ if (this.isHorizontal){
+
+ var a = p.x - this.dragOffset.x;
+ a = this.legaliseSplitPoint(a);
+ p.x = a + this.dragOffset.x;
+ }else{
+ var a = p.y - this.dragOffset.y;
+ a = this.legaliseSplitPoint(a);
+ p.y = a + this.dragOffset.y;
+ }
+
+ this.lastPoint = this.mainClientToScreen(p);
+ },
+
+ screenToClient: function(pt){
+
+ pt.x -= (this.offsetX + this.sizingSplitter.position);
+ pt.y -= (this.offsetY + this.sizingSplitter.position);
+
+ return pt;
+ },
+
+ clientToScreen: function(pt){
+
+ pt.x += (this.offsetX + this.sizingSplitter.position);
+ pt.y += (this.offsetY + this.sizingSplitter.position);
+
+ return pt;
+ },
+
+ screenToMainClient: function(pt){
+
+ pt.x -= this.offsetX;
+ pt.y -= this.offsetY;
+
+ return pt;
+ },
+
+ mainClientToScreen: function(pt){
+
+ pt.x += this.offsetX;
+ pt.y += this.offsetY;
+
+ return pt;
+ },
+
+ legaliseSplitPoint: function(a){
+
+ a += this.sizingSplitter.position;
+
+ this.isDraggingLeft = (a > 0) ? 1 : 0;
+
+ if (!this.isActiveResize){
+
+ if (a < this.paneBefore.position + this.paneBefore.sizeMin){
+
+ a = this.paneBefore.position + this.paneBefore.sizeMin;
+ }
+
+ if (a > this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin))){
+
+ a = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
+ }
+ }
+
+ a -= this.sizingSplitter.position;
+
+ this.checkSizes();
+
+ return a;
+ },
+
+ updateSize: function(){
+
+ var p = this.clientToScreen(this.lastPoint);
+ var p = this.screenToClient(this.lastPoint);
+
+ var pos = this.isHorizontal ? p.x - (this.dragOffset.x + this.originPos.x) : p.y - (this.dragOffset.y + this.originPos.y);
+
+ var start_region = this.paneBefore.position;
+ var end_region = this.paneAfter.position + this.paneAfter.sizeActual;
+
+ this.paneBefore.sizeActual = pos - start_region;
+ this.paneAfter.position = pos + this.sizerWidth;
+ this.paneAfter.sizeActual = end_region - this.paneAfter.position;
+
+ for(var i=0; i<this.children.length; i++){
+
+ this.children[i].sizeShare = this.children[i].sizeActual;
+ }
+
+ this.layoutPanels();
+ },
+
+ showSizingLine: function(){
+
+ this.moveSizingLine();
+
+ if (this.isHorizontal){
+ dojo.style.setOuterWidth(this.virtualSizer, this.sizerWidth);
+ dojo.style.setOuterHeight(this.virtualSizer, this.paneHeight);
+ }else{
+ dojo.style.setOuterWidth(this.virtualSizer, this.paneWidth);
+ dojo.style.setOuterHeight(this.virtualSizer, this.sizerWidth);
+ }
+
+ this.virtualSizer.style.display = 'block';
+ },
+
+ hideSizingLine: function(){
+
+ this.virtualSizer.style.display = 'none';
+ },
+
+ moveSizingLine: function(){
+
+ var origin = {'x':0, 'y':0};
+
+ if (this.isHorizontal){
+ origin.x += (this.lastPoint.x - this.startPoint.x) + this.sizingSplitter.position;
+ }else{
+ origin.y += (this.lastPoint.y - this.startPoint.y) + this.sizingSplitter.position;
+ }
+
+ this.virtualSizer.style.left = origin.x + 'px';
+ this.virtualSizer.style.top = origin.y + 'px';
+ }
+});
+
+// These arguments can be specified for the children of a SplitPane.
+// Since any widget can be specified as a SplitPane child, mix them
+// into the base widget class. (This is a hack, but it's effective.)
+dojo.lang.extend(dojo.widget.Widget, {
+ sizeMin: 10,
+ sizeShare: 10
+});
+
+// Deprecated class for split pane children.
+// Actually any widget can be the child of a split pane
+dojo.widget.html.SplitPanePanel = function(){
+ dojo.widget.html.LayoutPane.call(this);
+}
+dojo.inherits(dojo.widget.html.SplitPanePanel, dojo.widget.html.LayoutPane);
+dojo.lang.extend(dojo.widget.html.SplitPanePanel, {
+ widgetType: "SplitPanePanel"
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:SplitPane");
+dojo.widget.tags.addParseTreeHandler("dojo:SplitPanePanel");
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org