You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by he...@apache.org on 2006/11/13 23:55:14 UTC
svn commit: r474551 [32/49] - in
/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo:
./ src/ src/alg/ src/animation/ src/cal/ src/charting/ src/charting/svg/
src/charting/vml/ src/collections/ src/crypto/ src/data/ src/data/cs...
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DomWidget.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DomWidget.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DomWidget.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DomWidget.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -11,64 +11,65 @@
dojo.provide("dojo.widget.DomWidget");
dojo.require("dojo.event.*");
-dojo.require("dojo.string");
+dojo.require("dojo.io.*");
dojo.require("dojo.widget.Widget");
dojo.require("dojo.dom");
+dojo.require("dojo.html.style");
dojo.require("dojo.xml.Parse");
dojo.require("dojo.uri.*");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.extras");
dojo.widget._cssFiles = {};
+dojo.widget._cssStrings = {};
+dojo.widget._templateCache = {};
+// Object: a mapping of strings that are used in template variable replacement
dojo.widget.defaultStrings = {
dojoRoot: dojo.hostenv.getBaseScriptUri(),
baseScriptUri: dojo.hostenv.getBaseScriptUri()
};
+dojo.widget.fillFromTemplateCache = function( /*DomWidget*/ obj,
+ /*String||dojo.uri.Uri*/ templatePath,
+ /*String, optional*/ templateString,
+ /*Boolean, optional*/ avoidCache){
+ // summary:
+ // static method to build from a template w/ or w/o a real widget in
+ // place
+ // obj: an instance of dojo.widget.DomWidget to initialize the template for
+ // templatePath: the URL to get the template from
+ // templateString:
+ // a string to use in lieu of fetching the template from a URL
+ // avoidCache:
+ // should the template system not use whatever is in the cache and
+ // always use the passed templatePath or templateString?
-// static method to build from a template w/ or w/o a real widget in place
-dojo.widget.buildFromTemplate = function(obj, templatePath, templateCssPath, templateString) {
+ // dojo.debug("avoidCache:", avoidCache);
var tpath = templatePath || obj.templatePath;
- var cpath = templateCssPath || obj.templateCssPath;
- if (!cpath && obj.templateCSSPath) {
- obj.templateCssPath = cpath = obj.templateCSSPath;
- obj.templateCSSPath = null;
- dj_deprecated("templateCSSPath is deprecated, use templateCssPath");
- }
-
- // DEPRECATED: use Uri objects, not strings
- if (tpath && !(tpath instanceof dojo.uri.Uri)) {
- tpath = dojo.uri.dojoUri(tpath);
- dj_deprecated("templatePath should be of type dojo.uri.Uri");
- }
- if (cpath && !(cpath instanceof dojo.uri.Uri)) {
- cpath = dojo.uri.dojoUri(cpath);
- dj_deprecated("templateCssPath should be of type dojo.uri.Uri");
- }
-
- var tmplts = dojo.widget.DomWidget.templates;
+ var tmplts = dojo.widget._templateCache;
if(!obj["widgetType"]) { // don't have a real template here
do {
- var dummyName = "__dummyTemplate__" + dojo.widget.buildFromTemplate.dummyCount++;
+ var dummyName = "__dummyTemplate__" + dojo.widget._templateCache.dummyCount++;
} while(tmplts[dummyName]);
obj.widgetType = dummyName;
}
+ var wt = obj.widgetType;
- if((cpath)&&(!dojo.widget._cssFiles[cpath])){
- dojo.html.insertCssFile(cpath);
- obj.templateCssPath = null;
- dojo.widget._cssFiles[cpath] = true;
- }
-
- var ts = tmplts[obj.widgetType];
+ var ts = tmplts[wt];
if(!ts){
- tmplts[obj.widgetType] = {};
- ts = tmplts[obj.widgetType];
+ tmplts[wt] = { "string": null, "node": null };
+ if(avoidCache){
+ ts = {};
+ }else{
+ ts = tmplts[wt];
+ }
}
- if(!obj.templateString){
+ if((!obj.templateString)&&(!avoidCache)){
obj.templateString = templateString || ts["string"];
}
- if(!obj.templateNode){
+ if((!obj.templateNode)&&(!avoidCache)){
obj.templateNode = ts["node"];
}
if((!obj.templateNode)&&(!obj.templateString)&&(tpath)){
@@ -76,6 +77,9 @@
// NOTE: we rely on blocking IO here!
var tstring = dojo.hostenv.getText(tpath);
if(tstring){
+ // strip <?xml ...?> declarations so that external SVG and XML
+ // documents can be added to a document without worry
+ tstring = tstring.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
var matches = tstring.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
if(matches){
tstring = matches[1];
@@ -84,19 +88,102 @@
tstring = "";
}
obj.templateString = tstring;
- ts.string = tstring;
+ if(!avoidCache){
+ tmplts[wt]["string"] = tstring;
+ }
}
- if(!ts["string"]) {
+ if((!ts["string"])&&(!avoidCache)){
ts.string = obj.templateString;
}
}
-dojo.widget.buildFromTemplate.dummyCount = 0;
+dojo.widget._templateCache.dummyCount = 0;
+// Array: list of properties to search for node-to-property mappings
dojo.widget.attachProperties = ["dojoAttachPoint", "id"];
+// String: name of the property to use for mapping DOM events to widget functions
dojo.widget.eventAttachProperty = "dojoAttachEvent";
+// String: property name of code to evaluate when the widget is constructed
dojo.widget.onBuildProperty = "dojoOnBuild";
+// Array: possible accessibility values to set on widget elements - role or state
+dojo.widget.waiNames = ["waiRole", "waiState"];
+// Object: Contains functions to set accessibility roles and states
+// onto widget elements
+dojo.widget.wai = {
+ waiRole: {
+ // String: information for mapping accessibility role
+ name: "waiRole",
+ // String: URI of the namespace for the set of roles
+ "namespace": "http://www.w3.org/TR/xhtml2",
+ // String: alias to assign the namespace
+ alias: "x2",
+ // String: prefix to assign to the role value
+ prefix: "wairole:"
+ },
+ waiState: {
+ // String: informatin for mapping accessibility state
+ name: "waiState",
+ // String: URI of the namespace for the set of states
+ "namespace": "http://www.w3.org/2005/07/aaa",
+ // String: alias to assign the namespace
+ alias: "aaa",
+ // String: empty string - state value does not require prefix
+ prefix: ""
+ },
+ setAttr: function(/*DomNode*/node, /*String*/ ns, /*String*/ attr, /*String|Boolean*/value){
+ // Summary: Use appropriate API to set the role or state attribute onto the element.
+ // Description: In IE use the generic setAttribute() api. Append a namespace
+ // alias to the attribute name and appropriate prefix to the value.
+ // Otherwise, use the setAttribueNS api to set the namespaced attribute. Also
+ // add the appropriate prefix to the attribute value.
+ if(dojo.render.html.ie){
+ node.setAttribute(this[ns].alias+":"+ attr, this[ns].prefix+value);
+ }else{
+ node.setAttributeNS(this[ns]["namespace"], attr, this[ns].prefix+value);
+ }
+ },
+
+ getAttr: function(/*DomNode*/ node, /*String*/ ns, /*String|Boolena*/ attr){
+ // Summary: Use the appropriate API to retrieve the role or state value
+ // Description: In IE use the generic getAttribute() api. An alias value
+ // was added to the attribute name to simulate a namespace when the attribute
+ // was set. Otherwise use the getAttributeNS() api to retrieve the state value
+ if(dojo.render.html.ie){
+ return node.getAttribute(this[ns].alias+":"+attr);
+ }else{
+ return node.getAttributeNS(this[ns]["namespace"], attr);
+ }
+ },
+ removeAttr: function(/*DomNode*/ node, /*String*/ ns, /*String|Boolena*/ attr){
+ // Summary: Use the appropriate API to remove the role or state value
+ // Description: In IE use the generic removeAttribute() api. An alias value
+ // was added to the attribute name to simulate a namespace when the attribute
+ // was set. Otherwise use the removeAttributeNS() api to remove the state value
+ var success = true; //only IE returns a value
+ if(dojo.render.html.ie){
+ success = node.removeAttribute(this[ns].alias+":"+attr);
+ }else{
+ node.removeAttributeNS(this[ns]["namespace"], attr);
+ }
+ return success;
+ }
+};
+
+dojo.widget.attachTemplateNodes = function( /*DomNode*/ rootNode,
+ /*Widget*/ targetObj,
+ /*Array*/ events ){
+ // summary:
+ // map widget properties and functions to the handlers specified in
+ // the dom node and it's descendants. This function iterates over all
+ // nodes and looks for these properties:
+ // * dojoAttachPoint
+ // * dojoAttachEvent
+ // * waiRole
+ // * waiState
+ // * any "dojoOn*" proprties passed in the events array
+ // rootNode:
+ // the node to search for properties. All children will be searched.
+ // events: a list of properties generated from getDojoEventsFromStr.
-dojo.widget.attachTemplateNodes = function(rootNode, targetObj, events){
// FIXME: this method is still taking WAAAY too long. We need ways of optimizing:
// a.) what we are looking for on each node
// b.) the nodes that are subject to interrogation (use xpath instead?)
@@ -104,6 +191,10 @@
// var start = new Date();
var elementNodeType = dojo.dom.ELEMENT_NODE;
+ function trim(str){
+ return str.replace(/^\s+|\s+$/g, "");
+ }
+
if(!rootNode){
rootNode = targetObj.domNode;
}
@@ -113,24 +204,85 @@
}
// alert(events.length);
- var nodes = rootNode.getElementsByTagName("*");
+ var nodes = rootNode.all || rootNode.getElementsByTagName("*");
var _this = targetObj;
for(var x=-1; x<nodes.length; x++){
var baseNode = (x == -1) ? rootNode : nodes[x];
- // FIXME: is this going to have capitalization problems?
+ // FIXME: is this going to have capitalization problems? Could use getAttribute(name, 0); to get attributes case-insensitve
var attachPoint = [];
- for(var y=0; y<this.attachProperties.length; y++){
- var tmpAttachPoint = baseNode.getAttribute(this.attachProperties[y]);
- if(tmpAttachPoint){
- attachPoint = tmpAttachPoint.split(";");
- for(var z=0; z<this.attachProperties.length; z++){
- if((targetObj[attachPoint[z]])&&(dojo.lang.isArray(targetObj[attachPoint[z]]))){
- targetObj[attachPoint[z]].push(baseNode);
- }else{
- targetObj[attachPoint[z]]=baseNode;
+ if(!targetObj.widgetsInTemplate || !baseNode.getAttribute('dojoType')){
+ for(var y=0; y<this.attachProperties.length; y++){
+ var tmpAttachPoint = baseNode.getAttribute(this.attachProperties[y]);
+ if(tmpAttachPoint){
+ attachPoint = tmpAttachPoint.split(";");
+ for(var z=0; z<attachPoint.length; z++){
+ if(dojo.lang.isArray(targetObj[attachPoint[z]])){
+ targetObj[attachPoint[z]].push(baseNode);
+ }else{
+ targetObj[attachPoint[z]]=baseNode;
+ }
+ }
+ break;
+ }
+ }
+
+ var attachEvent = baseNode.getAttribute(this.eventAttachProperty);
+ if(attachEvent){
+ // NOTE: we want to support attributes that have the form
+ // "domEvent: nativeEvent; ..."
+ var evts = attachEvent.split(";");
+ for(var y=0; y<evts.length; y++){
+ if((!evts[y])||(!evts[y].length)){ continue; }
+ var thisFunc = null;
+ var tevt = trim(evts[y]);
+ if(evts[y].indexOf(":") >= 0){
+ // oh, if only JS had tuple assignment
+ var funcNameArr = tevt.split(":");
+ tevt = trim(funcNameArr[0]);
+ thisFunc = trim(funcNameArr[1]);
+ }
+ if(!thisFunc){
+ thisFunc = tevt;
+ }
+
+ var tf = function(){
+ var ntf = new String(thisFunc);
+ return function(evt){
+ if(_this[ntf]){
+ _this[ntf](dojo.event.browser.fixEvent(evt, this));
+ }
+ };
+ }();
+ dojo.event.browser.addListener(baseNode, tevt, tf, false, true);
+ // dojo.event.browser.addListener(baseNode, tevt, dojo.lang.hitch(_this, thisFunc));
+ }
+ }
+
+ for(var y=0; y<events.length; y++){
+ //alert(events[x]);
+ var evtVal = baseNode.getAttribute(events[y]);
+ if((evtVal)&&(evtVal.length)){
+ var thisFunc = null;
+ var domEvt = events[y].substr(4); // clober the "dojo" prefix
+ thisFunc = trim(evtVal);
+ var funcs = [thisFunc];
+ if(thisFunc.indexOf(";")>=0){
+ funcs = dojo.lang.map(thisFunc.split(";"), trim);
+ }
+ for(var z=0; z<funcs.length; z++){
+ if(!funcs[z].length){ continue; }
+ var tf = function(){
+ var ntf = new String(funcs[z]);
+ return function(evt){
+ if(_this[ntf]){
+ _this[ntf](dojo.event.browser.fixEvent(evt, this));
+ }
+ }
+ }();
+ dojo.event.browser.addListener(baseNode, domEvt, tf, false, true);
+ // dojo.event.browser.addListener(baseNode, domEvt, dojo.lang.hitch(_this, funcs[z]));
}
}
- break;
}
}
// continue;
@@ -142,76 +294,41 @@
targetObj[tmpltPoint]=baseNode;
}
- var attachEvent = baseNode.getAttribute(this.eventAttachProperty);
- if(attachEvent){
- // NOTE: we want to support attributes that have the form
- // "domEvent: nativeEvent; ..."
- var evts = attachEvent.split(";");
- for(var y=0; y<evts.length; y++){
- if((!evts[y])||(!evts[y].length)){ continue; }
- var thisFunc = null;
- // var tevt = dojo.string.trim(evts[y]);
- var tevt = dojo.string.trim(evts[y]);
- if(evts[y].indexOf(":") >= 0){
- // oh, if only JS had tuple assignment
- var funcNameArr = tevt.split(":");
- tevt = dojo.string.trim(funcNameArr[0]);
- thisFunc = dojo.string.trim(funcNameArr[1]);
- }
- if(!thisFunc){
- thisFunc = tevt;
- }
-
- var tf = function(){
- var ntf = new String(thisFunc);
- return function(evt){
- if(_this[ntf]){
- _this[ntf](dojo.event.browser.fixEvent(evt));
- }
- };
- }();
- dojo.event.browser.addListener(baseNode, tevt, tf, false, true);
- }
- }
-
- for(var y=0; y<events.length; y++){
- //alert(events[x]);
- var evtVal = baseNode.getAttribute(events[y]);
- if((evtVal)&&(evtVal.length)){
- var thisFunc = null;
- var domEvt = events[y].substr(4); // clober the "dojo" prefix
- thisFunc = dojo.string.trim(evtVal);
- var tf = function(){
- var ntf = new String(thisFunc);
- return function(evt){
- if(_this[ntf]){
- _this[ntf](dojo.event.browser.fixEvent(evt));
- }
- }
- }();
- dojo.event.browser.addListener(baseNode, domEvt, tf, false, true);
+ dojo.lang.forEach(dojo.widget.waiNames, function(name){
+ var wai = dojo.widget.wai[name];
+ var val = baseNode.getAttribute(wai.name);
+ if(val){
+ if(val.indexOf('-') == -1){
+ dojo.widget.wai.setAttr(baseNode, wai.name, "role", val);
+ }else{
+ // this is a state-value pair
+ var statePair = val.split('-');
+ dojo.widget.wai.setAttr(baseNode, wai.name, statePair[0], statePair[1]);
+ }
}
- }
+ }, this);
var onBuild = baseNode.getAttribute(this.onBuildProperty);
if(onBuild){
eval("var node = baseNode; var widget = targetObj; "+onBuild);
}
-
- // strip IDs to prevent dupes
- baseNode.id = "";
}
}
-dojo.widget.getDojoEventsFromStr = function(str){
+dojo.widget.getDojoEventsFromStr = function(/*String*/str){
+ // summary:
+ // generates a list of properties with names that match the form
+ // dojoOn*
+ // str: the template string to search
+
// var lstr = str.toLowerCase();
var re = /(dojoOn([a-z]+)(\s?))=/gi;
var evts = str ? str.match(re)||[] : [];
var ret = [];
var lem = {};
for(var x=0; x<evts.length; x++){
- if(evts[x].legth < 1){ continue; }
+ if(evts[x].length < 1){ continue; }
var cm = evts[x].replace(/\s/, "");
cm = (cm.slice(0, cm.length-1));
if(!lem[cm]){
@@ -219,316 +336,567 @@
ret.push(cm);
}
}
- return ret;
+ return ret; // Array
}
-
+/*
dojo.widget.buildAndAttachTemplate = function(obj, templatePath, templateCssPath, templateString, targetObj) {
this.buildFromTemplate(obj, templatePath, templateCssPath, templateString);
var node = dojo.dom.createNodesFromText(obj.templateString, true)[0];
this.attachTemplateNodes(node, targetObj||obj, dojo.widget.getDojoEventsFromStr(templateString));
return node;
}
+*/
-dojo.widget.DomWidget = function(){
- dojo.widget.Widget.call(this);
- if((arguments.length>0)&&(typeof arguments[0] == "object")){
- this.create(arguments[0]);
- }
-}
-dojo.inherits(dojo.widget.DomWidget, dojo.widget.Widget);
-
-dojo.lang.extend(dojo.widget.DomWidget, {
- templateNode: null,
- templateString: null,
- preventClobber: false,
- domNode: null, // this is our visible representation of the widget!
- containerNode: null, // holds child elements
-
- // Process the given child widget, inserting it's dom node as a child of our dom node
- // FIXME: should we support addition at an index in the children arr and
- // order the display accordingly? Right now we always append.
- addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
- if(!this.isContainer){ // we aren't allowed to contain other widgets, it seems
- dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
- return null;
- }else{
- this.addWidgetAsDirectChild(widget, overrideContainerNode, pos, ref, insertIndex);
- this.registerChild(widget, insertIndex);
- }
- return widget;
- },
-
- addWidgetAsDirectChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
- if((!this.containerNode)&&(!overrideContainerNode)){
- this.containerNode = this.domNode;
- }
- var cn = (overrideContainerNode) ? overrideContainerNode : this.containerNode;
- if(!pos){ pos = "after"; }
- if(!ref){ ref = cn.lastChild; }
- if(!insertIndex) { insertIndex = 0; }
- widget.domNode.setAttribute("dojoinsertionindex", insertIndex);
-
- // insert the child widget domNode directly underneath my domNode, in the
- // specified position (by default, append to end)
- if(!ref){
- cn.appendChild(widget.domNode);
- }else{
- // FIXME: was this meant to be the (ugly hack) way to support insert @ index?
- //dojo.dom[pos](widget.domNode, ref, insertIndex);
- // CAL: this appears to be the intended way to insert a node at a given position...
- if (pos == 'insertAtIndex'){
- // dojo.debug("idx:", insertIndex, "isLast:", ref === cn.lastChild);
- dojo.dom.insertAtIndex(widget.domNode, ref.parentNode, insertIndex);
+// summary:
+// dojo.widget.DomWidget is the superclass that provides behavior for all
+// DOM-based renderers, including HtmlWidget and SvgWidget. DomWidget
+// implements the templating system that most widget authors use to define
+// the UI for their widgets.
+dojo.declare("dojo.widget.DomWidget",
+ dojo.widget.Widget,
+ function(){
+ if((arguments.length>0)&&(typeof arguments[0] == "object")){
+ this.create(arguments[0]);
+ }
+ },
+ {
+ // DomNode: a node that represents the widget template. Pre-empts both templateString and templatePath.
+ templateNode: null,
+
+ // String:
+ // a string that represents the widget template. Pre-empts the
+ // templatePath. In builds that have their strings "interned", the
+ // templatePath is converted to an inline templateString, thereby
+ // preventing a synchronous network call.
+ templateString: null,
+
+ // String:
+ // a string that represents the CSS for the widgettemplate.
+ // Pre-empts the templateCssPath. In builds that have their
+ // strings "interned", the templateCssPath is converted to an
+ // inline templateCssString, thereby preventing a synchronous
+ // network call.
+ templateCssString: null,
+
+ // Boolean:
+ // should the widget not replace the node from which it was
+ // constructed? Widgets that apply behaviors to pre-existing parts
+ // of a page can be implemented easily by setting this to "true".
+ // In these cases, the domNode property will point to the node
+ // which the widget was created from.
+ preventClobber: false,
+
+ // DomNode:
+ // this is our visible representation of the widget! Other DOM
+ // Nodes may by assigned to other properties, usually through the
+ // template system's dojoAttachPonit syntax, but the domNode
+ // property is the canonical "top level" node in widget UI.
+ domNode: null,
+
+ // DomNode:
+ // holds child elements. "containerNode" is generally set via a
+ // dojoAttachPoint assignment and it designates where widgets that
+ // are defined as "children" of the parent will be placed
+ // visually.
+ containerNode: null,
+
+ // Boolean:
+ // should we parse the template to find widgets that might be
+ // declared in markup inside it? false by default.
+ widgetsInTemplate: false,
+
+ addChild: function( /*Widget*/ widget,
+ /*DomNode, optional*/ overrideContainerNode,
+ /*String, optional*/ pos,
+ /*DomNode, optional*/ ref,
+ /*int, optional*/ insertIndex){
+ // summary:
+ // Process the given child widget, inserting it's dom node as
+ // a child of our dom node
+ // overrideContainerNode: a non-default container node for the widget
+ // pos:
+ // can be one of "before", "after", "first", or "last". This
+ // has the same meaning as in dojo.dom.insertAtPosition()
+ // ref: a node to place the widget relative to
+ // insertIndex: DOM index, same meaning as in dojo.dom.insertAtIndex()
+
+ // FIXME: should we support addition at an index in the children arr and
+ // order the display accordingly? Right now we always append.
+ if(!this.isContainer){ // we aren't allowed to contain other widgets, it seems
+ dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
+ return null;
}else{
- // dojo.debug("pos:", pos, "isLast:", ref === cn.lastChild);
- if((pos == "after")&&(ref === cn.lastChild)){
- cn.appendChild(widget.domNode);
- }else{
- dojo.dom.insertAtPosition(widget.domNode, cn, pos);
+ if(insertIndex == undefined){
+ insertIndex = this.children.length;
}
+ this.addWidgetAsDirectChild(widget, overrideContainerNode, pos, ref, insertIndex);
+ this.registerChild(widget, insertIndex);
}
- }
- },
-
- // Record that given widget descends from me
- registerChild: function(widget, insertionIndex){
+ return widget; // Widget: the widget that was inserted
+ },
+
+ addWidgetAsDirectChild: function( /*Widget*/ widget,
+ /*DomNode*/ overrideContainerNode,
+ /*String, optional*/ pos,
+ /*DomNode, optional*/ ref,
+ /*int, optional*/ insertIndex){
+ // summary:
+ // Process the given child widget, inserting it's dom node as
+ // a child of our dom node
+ // overrideContainerNode: a non-default container node for the widget
+ // pos:
+ // can be one of "before", "after", "first", or "last". This
+ // has the same meaning as in dojo.dom.insertAtPosition()
+ // ref: a node to place the widget relative to
+ // insertIndex: DOM index, same meaning as in dojo.dom.insertAtIndex()
+ if((!this.containerNode)&&(!overrideContainerNode)){
+ this.containerNode = this.domNode;
+ }
+ var cn = (overrideContainerNode) ? overrideContainerNode : this.containerNode;
+ if(!pos){ pos = "after"; }
+ if(!ref){
+ if(!cn){ cn = dojo.body(); }
+ ref = cn.lastChild;
+ }
+ if(!insertIndex) { insertIndex = 0; }
+ widget.domNode.setAttribute("dojoinsertionindex", insertIndex);
+
+ // insert the child widget domNode directly underneath my domNode, in the
+ // specified position (by default, append to end)
+ if(!ref){
+ cn.appendChild(widget.domNode);
+ }else{
+ // FIXME: was this meant to be the (ugly hack) way to support insert @ index?
+ //dojo.dom[pos](widget.domNode, ref, insertIndex);
- // we need to insert the child at the right point in the parent's
- // 'children' array, based on the insertionIndex
+ // CAL: this appears to be the intended way to insert a node at a given position...
+ if (pos == 'insertAtIndex'){
+ // dojo.debug("idx:", insertIndex, "isLast:", ref === cn.lastChild);
+ dojo.dom.insertAtIndex(widget.domNode, ref.parentNode, insertIndex);
+ }else{
+ // dojo.debug("pos:", pos, "isLast:", ref === cn.lastChild);
+ if((pos == "after")&&(ref === cn.lastChild)){
+ cn.appendChild(widget.domNode);
+ }else{
+ dojo.dom.insertAtPosition(widget.domNode, cn, pos);
+ }
+ }
+ }
+ },
- widget.dojoInsertionIndex = insertionIndex;
+ registerChild: function(/*Widget*/widget, /*int*/insertionIndex){
+ // summary: record that given widget descends from me
+ // widget: the widget that is now a child
+ // inesrtionIndex: where in the children[] array to place it
+
+ // we need to insert the child at the right point in the parent's
+ // 'children' array, based on the insertionIndex
+
+ widget.dojoInsertionIndex = insertionIndex;
+
+ var idx = -1;
+ for(var i=0; i<this.children.length; i++){
+
+ //This appears to fix an out of order issue in the case of mixed
+ //markup and programmatically added children. Previously, if a child
+ //existed from markup, and another child was addChild()d without specifying
+ //any additional parameters, it would end up first in the list, when in fact
+ //it should be after. I can't see cases where this would break things, but
+ //I could see no other obvious solution. -dustin
- var idx = -1;
- for(var i=0; i<this.children.length; i++){
- if (this.children[i].dojoInsertionIndex < insertionIndex){
- idx = i;
+ if (this.children[i].dojoInsertionIndex <= insertionIndex){
+ idx = i;
+ }
}
- }
- this.children.splice(idx+1, 0, widget);
+ this.children.splice(idx+1, 0, widget);
- widget.parent = this;
- widget.addedTo(this);
+ widget.parent = this;
+ widget.addedTo(this, idx+1);
+
+ // If this widget was created programatically, then it was erroneously added
+ // to dojo.widget.manager.topWidgets. Fix that here.
+ delete dojo.widget.manager.topWidgets[widget.widgetId];
+ },
+
+ removeChild: function(/*Widget*/widget){
+ // summary: detach child domNode from parent domNode
+ dojo.dom.removeNode(widget.domNode);
+
+ // remove child widget from parent widget
+ return dojo.widget.DomWidget.superclass.removeChild.call(this, widget); // Widget
+ },
+
+ getFragNodeRef: function(/*Object*/frag){
+ // summary:
+ // returns the source node, if any, that the widget was
+ // declared from
+ // frag:
+ // an opaque data structure generated by the first-pass parser
+ if(!frag){return null;} // null
+ if(!frag[this.getNamespacedType()]){
+ dojo.raise("Error: no frag for widget type " + this.getNamespacedType()
+ + ", id " + this.widgetId
+ + " (maybe a widget has set it's type incorrectly)");
+ }
+ return frag[this.getNamespacedType()]["nodeRef"]; // DomNode
+ },
- // If this widget was created programatically, then it was erroneously added
- // to dojo.widget.manager.topWidgets. Fix that here.
- delete dojo.widget.manager.topWidgets[widget.widgetId];
- },
-
- // FIXME: we really need to normalize how we do things WRT "destroy" vs. "remove"
- removeChild: function(widget){
- for(var x=0; x<this.children.length; x++){
- if(this.children[x] === widget){
- this.children.splice(x, 1);
- break;
+ postInitialize: function(/*Object*/args, /*Object*/frag, /*Widget*/parentComp){
+ // summary:
+ // Replace the source domNode with the generated dom
+ // structure, and register the widget with its parent.
+ // This is an implementation of the stub function defined in
+ // dojo.widget.Widget.
+
+ //dojo.profile.start(this.widgetType + " postInitialize");
+
+ var sourceNodeRef = this.getFragNodeRef(frag);
+ // Stick my generated dom into the output tree
+ //alert(this.widgetId + ": replacing " + sourceNodeRef + " with " + this.domNode.innerHTML);
+ if (parentComp && (parentComp.snarfChildDomOutput || !sourceNodeRef)){
+ // Add my generated dom as a direct child of my parent widget
+ // This is important for generated widgets, and also cases where I am generating an
+ // <li> node that can't be inserted back into the original DOM tree
+ parentComp.addWidgetAsDirectChild(this, "", "insertAtIndex", "", args["dojoinsertionindex"], sourceNodeRef);
+ } else if (sourceNodeRef){
+ // Do in-place replacement of the my source node with my generated dom
+ if(this.domNode && (this.domNode !== sourceNodeRef)){
+ var oldNode = sourceNodeRef.parentNode.replaceChild(this.domNode, sourceNodeRef);
+ }
}
- }
- return widget;
- },
- getFragNodeRef: function(frag){
- if( !frag["dojo:"+this.widgetType.toLowerCase()] ){
- dojo.raise("Error: no frag for widget type " + this.widgetType +
- ", id " + this.widgetId + " (maybe a widget has set it's type incorrectly)");
- }
- return (frag ? frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"] : null);
- },
+ // Register myself with my parent, or with the widget manager if
+ // I have no parent
+ // TODO: the code below erroneously adds all programatically generated widgets
+ // to topWidgets (since we don't know who the parent is until after creation finishes)
+ if ( parentComp ) {
+ parentComp.registerChild(this, args.dojoinsertionindex);
+ } else {
+ dojo.widget.manager.topWidgets[this.widgetId]=this;
+ }
+
+ if(this.widgetsInTemplate){
+ var parser = new dojo.xml.Parse();
+
+ var subContainerNode;
+ //TODO: use xpath here?
+ var subnodes = this.domNode.getElementsByTagName("*");
+ for(var i=0;i<subnodes.length;i++){
+ if(subnodes[i].getAttribute('dojoAttachPoint') == 'subContainerWidget'){
+ subContainerNode = subnodes[i];
+// break;
+ }
+ if(subnodes[i].getAttribute('dojoType')){
+ subnodes[i].setAttribute('_isSubWidget', true);
+ }
+ }
+ if (this.isContainer && !this.containerNode){
+ //no containerNode is available, which means a widget is used as a container. find it here and move
+ //all dom nodes defined in the main html page as children of this.domNode into the actual container
+ //widget's node (at this point, the subwidgets defined in the template file is not parsed yet)
+ if(subContainerNode){
+ var src = this.getFragNodeRef(frag);
+ if (src){
+ dojo.dom.moveChildren(src, subContainerNode);
+ //do not need to follow children nodes in the main html page, as they
+ //will be dealt with in the subContainerWidget
+ frag['dojoDontFollow'] = true;
+ }
+ }else{
+ dojo.debug("No subContainerWidget node can be found in template file for widget "+this);
+ }
+ }
+
+ var templatefrag = parser.parseElement(this.domNode, null, true);
+ // createSubComponents not createComponents because frag has already been created
+ dojo.widget.getParser().createSubComponents(templatefrag, this);
- // Replace source domNode with generated dom structure, and register
- // widget with parent.
- postInitialize: function(args, frag, parentComp){
- var sourceNodeRef = this.getFragNodeRef(frag);
- // Stick my generated dom into the output tree
- //alert(this.widgetId + ": replacing " + sourceNodeRef + " with " + this.domNode.innerHTML);
- if (parentComp && (parentComp.snarfChildDomOutput || !sourceNodeRef)){
- // Add my generated dom as a direct child of my parent widget
- // This is important for generated widgets, and also cases where I am generating an
- // <li> node that can't be inserted back into the original DOM tree
- parentComp.addWidgetAsDirectChild(this, "", "insertAtIndex", "", args["dojoinsertionindex"], sourceNodeRef);
- } else if (sourceNodeRef){
- // Do in-place replacement of the my source node with my generated dom
- if(this.domNode && (this.domNode !== sourceNodeRef)){
- var oldNode = sourceNodeRef.parentNode.replaceChild(this.domNode, sourceNodeRef);
+ //find all the sub widgets defined in the template file of this widget
+ var subwidgets = [];
+ var stack = [this];
+ var w;
+ while((w = stack.pop())){
+ for(var i = 0; i < w.children.length; i++){
+ var cwidget = w.children[i];
+ if(cwidget._processedSubWidgets || !cwidget.extraArgs['_issubwidget']){ continue; }
+ subwidgets.push(cwidget);
+ if(cwidget.isContainer){
+ stack.push(cwidget);
+ }
+ }
+ }
+
+ //connect event to this widget/attach dom node
+ for(var i = 0; i < subwidgets.length; i++){
+ var widget = subwidgets[i];
+ if(widget._processedSubWidgets){
+ dojo.debug("This should not happen: widget._processedSubWidgets is already true!");
+ return;
+ }
+ widget._processedSubWidgets = true;
+ if(widget.extraArgs['dojoattachevent']){
+ var evts = widget.extraArgs['dojoattachevent'].split(";");
+ for(var j=0; j<evts.length; j++){
+ var thisFunc = null;
+ var tevt = dojo.string.trim(evts[j]);
+ if(tevt.indexOf(":") >= 0){
+ // oh, if only JS had tuple assignment
+ var funcNameArr = tevt.split(":");
+ tevt = dojo.string.trim(funcNameArr[0]);
+ thisFunc = dojo.string.trim(funcNameArr[1]);
+ }
+ if(!thisFunc){
+ thisFunc = tevt;
+ }
+ if(dojo.lang.isFunction(widget[tevt])){
+ dojo.event.kwConnect({
+ srcObj: widget,
+ srcFunc: tevt,
+ targetObj: this,
+ targetFunc: thisFunc
+ });
+ }else{
+ alert(tevt+" is not a function in widget "+widget);
+ }
+ }
+ }
+
+ if(widget.extraArgs['dojoattachpoint']){
+ //don't attach widget.domNode here, as we do not know which
+ //dom node we should connect to (in checkbox widget case,
+ //it is inputNode). So we make the widget itself available
+ this[widget.extraArgs['dojoattachpoint']] = widget;
+ }
+ }
}
- }
- // Register myself with my parent, or with the widget manager if
- // I have no parent
- // TODO: the code below erroneously adds all programatically generated widgets
- // to topWidgets (since we don't know who the parent is until after creation finishes)
- if ( parentComp ) {
- parentComp.registerChild(this, args.dojoinsertionindex);
- } else {
- dojo.widget.manager.topWidgets[this.widgetId]=this;
- }
-
- // Expand my children widgets
- if(this.isContainer){
- //alert("recurse from " + this.widgetId);
- // build any sub-components with us as the parent
- var fragParser = dojo.widget.getParser();
- fragParser.createComponents(frag, this);
- }
- },
-
- startResize: function(coords){
- dj_unimplemented("dojo.widget.DomWidget.startResize");
- },
-
- updateResize: function(coords){
- dj_unimplemented("dojo.widget.DomWidget.updateResize");
- },
-
- endResize: function(coords){
- dj_unimplemented("dojo.widget.DomWidget.endResize");
- },
+ //dojo.profile.end(this.widgetType + " postInitialize");
- // method over-ride
- buildRendering: function(args, frag){
- // DOM widgets construct themselves from a template
- var ts = dojo.widget.DomWidget.templates[this.widgetType];
- if(
- (!this.preventClobber)&&(
- (this.templatePath)||
- (this.templateNode)||
- (
- (this["templateString"])&&(this.templateString.length)
- )||
- (
- (typeof ts != "undefined")&&( (ts["string"])||(ts["node"]) )
+ // Expand my children widgets
+ /* dojoDontFollow is important for a very special case
+ * basically if you have a widget that you instantiate from script
+ * and that widget is a container, and it contains a reference to a parent
+ * instance, the parser will start recursively parsing until the browser
+ * complains. So the solution is to set an initialization property of
+ * dojoDontFollow: true and then it won't recurse where it shouldn't
+ */
+ if(this.isContainer && !frag["dojoDontFollow"]){
+ //alert("recurse from " + this.widgetId);
+ // build any sub-components with us as the parent
+ dojo.widget.getParser().createSubComponents(frag, this);
+ }
+ },
+
+ // method over-ride
+ buildRendering: function(/*Object*/args, /*Object*/frag){
+ // summary:
+ // Construct the UI for this widget, generally from a
+ // template. This can be over-ridden for custom UI creation to
+ // to side-step the template system. This is an
+ // implementation of the stub function defined in
+ // dojo.widget.Widget.
+
+ // DOM widgets construct themselves from a template
+ var ts = dojo.widget._templateCache[this.widgetType];
+
+ // Handle style for this widget here, as even if templatePath
+ // is not set, style specified by templateCssString or templateCssPath
+ // should be applied. templateCssString has higher priority
+ // than templateCssPath
+ if(args["templatecsspath"]){
+ args["templateCssPath"] = args["templatecsspath"];
+ }
+ var cpath = args["templateCssPath"] || this.templateCssPath;
+ if(cpath && !dojo.widget._cssFiles[cpath.toString()]){
+ if((!this.templateCssString)&&(cpath)){
+ this.templateCssString = dojo.hostenv.getText(cpath);
+ this.templateCssPath = null;
+ }
+ dojo.widget._cssFiles[cpath.toString()] = true;
+ }
+
+ if((this["templateCssString"])&&(!this.templateCssString["loaded"])){
+ dojo.html.insertCssText(this.templateCssString, null, cpath);
+ if(!this.templateCssString){ this.templateCssString = ""; }
+ this.templateCssString.loaded = true;
+ }
+ if(
+ (!this.preventClobber)&&(
+ (this.templatePath)||
+ (this.templateNode)||
+ (
+ (this["templateString"])&&(this.templateString.length)
+ )||
+ (
+ (typeof ts != "undefined")&&( (ts["string"])||(ts["node"]) )
+ )
)
- )
- ){
- // if it looks like we can build the thing from a template, do it!
- this.buildFromTemplate(args, frag);
- }else{
- // otherwise, assign the DOM node that was the source of the widget
- // parsing to be the root node
- this.domNode = this.getFragNodeRef(frag);
- }
- this.fillInTemplate(args, frag); // this is where individual widgets
- // will handle population of data
- // from properties, remote data
- // sets, etc.
- },
-
- buildFromTemplate: function(args, frag){
- // var start = new Date();
- // copy template properties if they're already set in the templates object
- var ts = dojo.widget.DomWidget.templates[this.widgetType];
- if(ts){
- if(!this.templateString.length){
- this.templateString = ts["string"];
- }
- if(!this.templateNode){
- this.templateNode = ts["node"];
- }
- }
- var matches = false;
- var node = null;
- var tstr = new String(this.templateString);
- // attempt to clone a template node, if there is one
- if((!this.templateNode)&&(this.templateString)){
- matches = this.templateString.match(/\$\{([^\}]+)\}/g);
- if(matches) {
- // if we do property replacement, don't create a templateNode
- // to clone from.
- var hash = this.strings || {};
- // FIXME: should this hash of default replacements be cached in
- // templateString?
- for(var key in dojo.widget.defaultStrings) {
- if(dojo.lang.isUndefined(hash[key])) {
- hash[key] = dojo.widget.defaultStrings[key];
- }
- }
- // FIXME: this is a lot of string munging. Can we make it faster?
- for(var i = 0; i < matches.length; i++) {
- var key = matches[i];
- key = key.substring(2, key.length-1);
- var kval = (key.substring(0, 5) == "this.") ? this[key.substring(5)] : hash[key];
- var value;
- if((kval)||(dojo.lang.isString(kval))){
- value = (dojo.lang.isFunction(kval)) ? kval.call(this, key, this.templateString) : kval;
- tstr = tstr.replace(matches[i], value);
+ ){
+ // if it looks like we can build the thing from a template, do it!
+ this.buildFromTemplate(args, frag);
+ }else{
+ // otherwise, assign the DOM node that was the source of the widget
+ // parsing to be the root node
+ this.domNode = this.getFragNodeRef(frag);
+ }
+ this.fillInTemplate(args, frag); // this is where individual widgets
+ // will handle population of data
+ // from properties, remote data
+ // sets, etc.
+ },
+
+ buildFromTemplate: function(/*Object*/args, /*Object*/frag){
+ // summary:
+ // Called by buildRendering, creates the actual UI in a DomWidget.
+
+ // var start = new Date();
+ // copy template properties if they're already set in the templates object
+ // dojo.debug("buildFromTemplate:", this);
+ var avoidCache = false;
+ if(args["templatepath"]){
+ avoidCache = true;
+ args["templatePath"] = args["templatepath"];
+ }
+ dojo.widget.fillFromTemplateCache( this,
+ args["templatePath"],
+ null,
+ avoidCache);
+ var ts = dojo.widget._templateCache[this.widgetType];
+ if((ts)&&(!avoidCache)){
+ if(!this.templateString.length){
+ this.templateString = ts["string"];
+ }
+ if(!this.templateNode){
+ this.templateNode = ts["node"];
+ }
+ }
+ var matches = false;
+ var node = null;
+ // var tstr = new String(this.templateString);
+ var tstr = this.templateString;
+ // attempt to clone a template node, if there is one
+ if((!this.templateNode)&&(this.templateString)){
+ matches = this.templateString.match(/\$\{([^\}]+)\}/g);
+ if(matches) {
+ // if we do property replacement, don't create a templateNode
+ // to clone from.
+ var hash = this.strings || {};
+ // FIXME: should this hash of default replacements be cached in
+ // templateString?
+ for(var key in dojo.widget.defaultStrings) {
+ if(dojo.lang.isUndefined(hash[key])) {
+ hash[key] = dojo.widget.defaultStrings[key];
+ }
+ }
+ // FIXME: this is a lot of string munging. Can we make it faster?
+ for(var i = 0; i < matches.length; i++) {
+ var key = matches[i];
+ key = key.substring(2, key.length-1);
+ var kval = (key.substring(0, 5) == "this.") ? dojo.lang.getObjPathValue(key.substring(5), this) : hash[key];
+ var value;
+ if((kval)||(dojo.lang.isString(kval))){
+ value = new String((dojo.lang.isFunction(kval)) ? kval.call(this, key, this.templateString) : kval);
+ // Safer substitution, see heading "Attribute values" in
+ // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+ while (value.indexOf("\"") > -1) {
+ value=value.replace("\"",""");
+ }
+ tstr = tstr.replace(matches[i], value);
+ }
+ }
+ }else{
+ // otherwise, we are required to instantiate a copy of the template
+ // string if one is provided.
+
+ // FIXME: need to be able to distinguish here what should be done
+ // or provide a generic interface across all DOM implementations
+ // FIMXE: this breaks if the template has whitespace as its first
+ // characters
+ // node = this.createNodesFromText(this.templateString, true);
+ // this.templateNode = node[0].cloneNode(true); // we're optimistic here
+ this.templateNode = this.createNodesFromText(this.templateString, true)[0];
+ if(!avoidCache){
+ ts.node = this.templateNode;
}
}
+ }
+ if((!this.templateNode)&&(!matches)){
+ dojo.debug("DomWidget.buildFromTemplate: could not create template");
+ return false;
+ }else if(!matches){
+ node = this.templateNode.cloneNode(true);
+ if(!node){ return false; }
}else{
- // otherwise, we are required to instantiate a copy of the template
- // string if one is provided.
-
- // FIXME: need to be able to distinguish here what should be done
- // or provide a generic interface across all DOM implementations
- // FIMXE: this breaks if the template has whitespace as its first
- // characters
- // node = this.createNodesFromText(this.templateString, true);
- // this.templateNode = node[0].cloneNode(true); // we're optimistic here
- this.templateNode = this.createNodesFromText(this.templateString, true)[0];
- ts.node = this.templateNode;
- }
- }
- if((!this.templateNode)&&(!matches)){
- dojo.debug("weren't able to create template!");
- return false;
- }else if(!matches){
- node = this.templateNode.cloneNode(true);
- if(!node){ return false; }
- }else{
- node = this.createNodesFromText(tstr, true)[0];
- }
+ node = this.createNodesFromText(tstr, true)[0];
+ }
- // recurse through the node, looking for, and attaching to, our
- // attachment points which should be defined on the template node.
+ // recurse through the node, looking for, and attaching to, our
+ // attachment points which should be defined on the template node.
- this.domNode = node;
- // dojo.profile.start("attachTemplateNodes");
- this.attachTemplateNodes(this.domNode, this);
- // dojo.profile.end("attachTemplateNodes");
+ this.domNode = node;
+ // dojo.profile.start("attachTemplateNodes");
+ this.attachTemplateNodes();
+ // dojo.profile.end("attachTemplateNodes");
- // relocate source contents to templated container node
- // this.containerNode must be able to receive children, or exceptions will be thrown
- if (this.isContainer && this.containerNode){
- var src = this.getFragNodeRef(frag);
- if (src){
- dojo.dom.moveChildren(src, this.containerNode);
+ // relocate source contents to templated container node
+ // this.containerNode must be able to receive children, or exceptions will be thrown
+ if (this.isContainer && this.containerNode){
+ var src = this.getFragNodeRef(frag);
+ if (src){
+ dojo.dom.moveChildren(src, this.containerNode);
+ }
}
- }
- },
+ },
- attachTemplateNodes: function(baseNode, targetObj){
- if(!targetObj){ targetObj = this; }
- return dojo.widget.attachTemplateNodes(baseNode, targetObj,
- dojo.widget.getDojoEventsFromStr(this.templateString));
- },
-
- fillInTemplate: function(){
- // dj_unimplemented("dojo.widget.DomWidget.fillInTemplate");
- },
-
- // method over-ride
- destroyRendering: function(){
- try{
- var tempNode = this.domNode.parentNode.removeChild(this.domNode);
- delete tempNode;
- }catch(e){ /* squelch! */ }
- },
-
- // FIXME: method over-ride
- cleanUp: function(){},
-
- getContainerHeight: function(){
- // FIXME: the generic DOM widget shouldn't be using HTML utils!
- return dojo.html.getInnerHeight(this.domNode.parentNode);
- },
-
- getContainerWidth: function(){
- // FIXME: the generic DOM widget shouldn't be using HTML utils!
- return dojo.html.getInnerWidth(this.domNode.parentNode);
- },
+ attachTemplateNodes: function(/*DomNode*/baseNode, /*Widget*/targetObj){
+ // summary:
+ // hooks up event handlers and property/node linkages. Calls
+ // dojo.widget.attachTemplateNodes to do all the hard work.
+ // baseNode: defaults to "this.domNode"
+ // targetObj: defaults to "this"
+ if(!baseNode){ baseNode = this.domNode; }
+ if(!targetObj){ targetObj = this; }
+ return dojo.widget.attachTemplateNodes(baseNode, targetObj,
+ dojo.widget.getDojoEventsFromStr(this.templateString));
+ },
+
+ fillInTemplate: function(){
+ // summary:
+ // stub function! sub-classes may use as a default UI
+ // initializer function. The UI rendering will be available by
+ // the time this is called from buildRendering. If
+ // buildRendering is over-ridden, this function may not be
+ // fired!
+ // dojo.unimplemented("dojo.widget.DomWidget.fillInTemplate");
+ },
+
+ // method over-ride
+ destroyRendering: function(){
+ // summary: UI destructor
+ try{
+ delete this.domNode;
+ }catch(e){ /* squelch! */ }
+ },
- createNodesFromText: function(){
- dj_unimplemented("dojo.widget.DomWidget.createNodesFromText");
+ // FIXME: method over-ride
+ cleanUp: function(){},
+
+ getContainerHeight: function(){
+ // summary: unimplemented!
+ dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
+ },
+
+ getContainerWidth: function(){
+ // summary: unimplemented!
+ dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
+ },
+
+ createNodesFromText: function(){
+ // summary: unimplemented!
+ dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
+ }
}
-});
-dojo.widget.DomWidget.templates = {};
+);
Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,90 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.DropdownContainer");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.PopupContainer");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.iframe");
+dojo.require("dojo.html.util");
+
+// summary:
+// dojo.widget.DropdownContainer provides an input box and a button for a dropdown.
+// In subclass, the dropdown can be specified.
+dojo.widget.defineWidget(
+ "dojo.widget.DropdownContainer",
+ dojo.widget.HtmlWidget,
+ {
+ // String: width of the input box
+ inputWidth: "7em",
+ // String: id of this widget
+ id: "",
+ // String: id of the input box
+ inputId: "",
+ // String: name of the input box
+ inputName: "",
+ // dojo.uri.Uri: icon for the dropdown button
+ iconURL: dojo.uri.dojoUri("src/widget/templates/images/combo_box_arrow.png"),
+ // dojo.uri.Uri: alt text for the dropdown button icon
+ iconAlt: "",
+
+ inputNode: null,
+ buttonNode: null,
+ containerNode: null,
+
+ // String: toggle property of the dropdown
+ containerToggle: "plain",
+ // Int: toggle duration property of the dropdown
+ containerToggleDuration: 150,
+ containerAnimInProgress: false,
+
+ templateString: '<span style="white-space:nowrap"><input type="hidden" name="" value="" dojoAttachPoint="valueNode" /><input name="" type="text" value="" style="vertical-align:middle;" dojoAttachPoint="inputNode" autocomplete="off" /> <img src="${this.iconURL}" alt="${this.iconAlt}" dojoAttachEvent="onclick: onIconClick" dojoAttachPoint="buttonNode" style="vertical-align:middle; cursor:pointer; cursor:hand" /></span>',
+ templateCssPath: "",
+
+ fillInTemplate: function(args, frag){
+ var source = this.getFragNodeRef(frag);
+
+ this.popup = dojo.widget.createWidget("PopupContainer", {toggle: this.containerToggle, toggleDuration: this.containerToggleDuration});
+
+ this.containerNode = this.popup.domNode;
+
+ this.domNode.appendChild(this.popup.domNode);
+ if(this.id) { this.domNode.id = this.id; }
+ if(this.inputId){ this.inputNode.id = this.inputId; }
+ if(this.inputName){ this.inputNode.name = this.inputName; }
+ this.inputNode.style.width = this.inputWidth;
+
+ dojo.event.connect(this.inputNode, "onchange", this, "onInputChange");
+ },
+
+ onIconClick: function(evt){
+ if(!this.isEnabled) return;
+ if(!this.popup.isShowingNow){
+ this.popup.open(this.inputNode, this, this.buttonNode);
+ }else{
+ this.popup.close();
+ }
+ },
+
+ hideContainer: function(){
+ // summary: hide the dropdown
+ if(this.popup.isShowingNow){
+ this.popup.close();
+ }
+ },
+
+ onInputChange: function(){
+ // summary: signal for changes in the input box
+ }
+ }
+);
Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,228 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.DropdownDatePicker");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.DropdownContainer");
+dojo.require("dojo.widget.DatePicker");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.*");
+dojo.require("dojo.date.format");
+dojo.require("dojo.date.serialize");
+dojo.require("dojo.string.common");
+dojo.require("dojo.i18n.common");
+dojo.requireLocalization("dojo.widget", "DropdownDatePicker");
+
+dojo.widget.defineWidget(
+ "dojo.widget.DropdownDatePicker",
+ dojo.widget.DropdownContainer,
+ {
+ /*
+ summary:
+ A form input for entering dates with a pop-up dojo.widget.DatePicker to aid in selection
+
+ description:
+ This is DatePicker in a DropdownContainer, it supports all features of DatePicker.
+
+ The value displayed in the widget is localized according to the default algorithm provided
+ in dojo.date.format and dojo.date.parse. It is possible to customize the user-visible formatting
+ with either the formatLength or displayFormat attributes. The value sent to the server is
+ typically a locale-independent value in a hidden field as defined by the name attribute.
+ RFC3339 representation is used by default, but other options are available with saveFormat.
+
+ usage:
+ var ddp = dojo.widget.createWidget("DropdownDatePicker", {},
+ dojo.byId("DropdownDatePickerNode"));
+
+ <input dojoType="DropdownDatePicker">
+ */
+
+ iconURL: dojo.uri.dojoUri("src/widget/templates/images/dateIcon.gif"),
+ zIndex: "10",
+
+ //String
+ // Type of visible formatting used, appropriate to locale (choice of long, short, medium or full)
+ // See dojo.date.format for details.
+ formatLength: "short",
+ //String
+ // Pattern used to display formatted date. Setting this overrides the locale-specific settings
+ // which are used by default. See dojo.date.format for a reference which defines the formatting patterns.
+ displayFormat: "",
+ dateFormat: "", // deprecated in 0.5
+ //String
+ // Formatting scheme used when submitting the form element. This formatting is used in a hidden
+ // field (name) intended for server use, and is therefore typically locale-independent.
+ // By default, uses rfc3339 style date formatting (rfc)
+ // Use a pattern string like displayFormat or one of the following:
+ // rfc|iso|posix|unix
+ saveFormat: "",
+ //String|Date
+ // form value property if =='today' will default to todays date
+ value: "",
+ //String
+ // name of the form element, used to create a hidden field by this name for form element submission.
+ name: "",
+
+ // Implement various attributes from DatePicker
+
+ //Integer
+ // total weeks to display default
+ displayWeeks: 6,
+ //Boolean
+ // if true, weekly size of calendar changes to accomodate the month if false, 42 day format is used
+ adjustWeeks: false,
+ //String|Date
+ // first available date in the calendar set
+ startDate: "1492-10-12",
+ //String|Date
+ // last available date in the calendar set
+ endDate: "2941-10-12",
+ //Integer
+ // adjusts the first day of the week 0==Sunday..6==Saturday
+ weekStartsOn: "",
+ //Boolean
+ // disable all incremental controls, must pick a date in the current display
+ staticDisplay: false,
+
+ postMixInProperties: function(localProperties, frag){
+ // summary: see dojo.widget.DomWidget
+
+ dojo.widget.DropdownDatePicker.superclass.postMixInProperties.apply(this, arguments);
+ var messages = dojo.i18n.getLocalization("dojo.widget", "DropdownDatePicker", this.lang);
+ this.iconAlt = messages.selectDate;
+
+ if(typeof(this.value)=='string'&&this.value.toLowerCase()=='today'){
+ this.value = new Date();
+ }
+ if(this.value && isNaN(this.value)){
+ var orig = this.value;
+ this.value = dojo.date.fromRfc3339(this.value);
+ if(!this.value){this.value = new Date(orig); dojo.deprecated("dojo.widget.DropdownDatePicker", "date attributes must be passed in Rfc3339 format", "0.5");}
+ }
+ if(this.value && !isNaN(this.value)){
+ this.value = new Date(this.value);
+ }
+ },
+
+ fillInTemplate: function(args, frag){
+ // summary: see dojo.widget.DomWidget
+ dojo.widget.DropdownDatePicker.superclass.fillInTemplate.call(this, args, frag);
+ //attributes to be passed on to DatePicker
+ var dpArgs = {widgetContainerId: this.widgetId, lang: this.lang, value: this.value,
+ startDate: this.startDate, endDate: this.endDate, displayWeeks: this.displayWeeks,
+ weekStartsOn: this.weekStartsOn, adjustWeeks: this.adjustWeeks, staticDisplay: this.staticDisplay};
+
+ //build the args for DatePicker based on the public attributes of DropdownDatePicker
+ this.datePicker = dojo.widget.createWidget("DatePicker", dpArgs, this.containerNode, "child");
+ dojo.event.connect(this.datePicker, "onValueChanged", this, "onSetDate");
+
+ if(this.value){
+ this.onSetDate();
+ }
+ this.containerNode.style.zIndex = this.zIndex;
+ this.containerNode.explodeClassName = "calendarBodyContainer";
+ this.valueNode.name=this.name;
+ },
+
+ getValue: function(){
+ // summary: return current date in RFC 3339 format
+ return this.valueNode.value; /*String*/
+ },
+
+ getDate: function(){
+ // summary: return current date as a Date object
+ return this.datePicker.value; /*Date*/
+ },
+
+ setValue: function(/*Date|String*/rfcDate){
+ //summary: set the current date from RFC 3339 formatted string or a date object, synonymous with setDate
+ this.setDate(rfcDate);
+ },
+
+ setDate: function(/*Date|String*/dateObj){
+ //summary: set the current date and update the UI
+ this.datePicker.setDate(dateObj);
+ this._synchValueNode();
+ },
+
+ onSetDate: function(){
+ if(this.dateFormat){
+ dojo.deprecated("dojo.widget.DropdownDatePicker",
+ "Must use displayFormat attribute instead of dateFormat. See dojo.date.format for specification.", "0.5");
+ this.inputNode.value = dojo.date.strftime(this.datePicker.value, this.dateFormat, this.lang);
+ }else{
+ this.inputNode.value = dojo.date.format(this.datePicker.value,
+ {formatLength:this.formatLength, datePattern:this.displayFormat, selector:'dateOnly', locale:this.lang});
+ }
+ if(this.value < this.datePicker.startDate||this.value>this.datePicker.endDate){
+ this.inputNode.value = "";
+ }
+ this._synchValueNode();
+ this.onValueChanged(this.getDate());
+ this.hideContainer();
+ },
+
+ onValueChanged: function(/*Date*/dateObj){
+ //summary: triggered when this.value is changed
+ },
+
+ onInputChange: function(){
+ if(this.dateFormat){
+ dojo.deprecated("dojo.widget.DropdownDatePicker",
+ "Cannot parse user input. Must use displayFormat attribute instead of dateFormat. See dojo.date.format for specification.", "0.5");
+ }else{
+ var input = dojo.string.trim(this.inputNode.value);
+ if(input){
+ var inputDate = dojo.date.parse(input,
+ {formatLength:this.formatLength, datePattern:this.displayFormat, selector:'dateOnly', locale:this.lang});
+ if(inputDate){
+ this.setDate(inputDate);
+ }
+ } else {
+ this.valueNode.value = input;
+ }
+ }
+ // If the date entered didn't parse, reset to the old date. KISS, for now.
+ //TODO: usability? should we provide more feedback somehow? an error notice?
+ // seems redundant to do this if the parse failed, but at least until we have validation,
+ // this will fix up the display of entries like 01/32/2006
+ if(input){ this.onSetDate(); }
+ },
+
+ _synchValueNode: function(){
+ var date = this.datePicker.value;
+ var value;
+ switch(this.saveFormat.toLowerCase()){
+ case "rfc": case "iso": case "":
+ value = dojo.date.toRfc3339(date, 'dateOnly');
+ break;
+ case "posix": case "unix":
+ value = Number(date);
+ break;
+ default:
+ value = dojo.date.format(date, {datePattern:this.saveFormat, selector:'dateOnly', locale:this.lang});
+ }
+ this.valueNode.value = value;
+ },
+
+ enable: function() {
+ this.inputNode.disabled = false;
+ this.datePicker.enable();
+ dojo.widget.DropdownDatePicker.superclass.enable.apply(this, arguments);
+ },
+
+ disable: function() {
+ this.inputNode.disabled = true;
+ this.datePicker.disable();
+ dojo.widget.DropdownDatePicker.superclass.disable.apply(this, arguments);
+ }
+ }
+);
Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,116 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.DropdownTimePicker");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.DropdownContainer");
+dojo.require("dojo.widget.TimePicker");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.*");
+dojo.require("dojo.date.format");
+dojo.require("dojo.date.serialize");
+dojo.require("dojo.i18n.common");
+dojo.requireLocalization("dojo.widget", "DropdownTimePicker");
+
+// summary
+// input box with a drop-down gui control, for setting the time (hours, minutes, seconds, am/pm) of an event
+dojo.widget.defineWidget(
+ "dojo.widget.DropdownTimePicker",
+ dojo.widget.DropdownContainer,
+ {
+ // URL
+ // path of icon for button to display time picker widget
+ iconURL: dojo.uri.dojoUri("src/widget/templates/images/timeIcon.gif"),
+
+ // Number
+ // z-index of time picker widget
+ zIndex: "10",
+
+ // pattern used in display of formatted time. Uses locale-specific format by default. See dojo.date.format.
+ displayFormat: "",
+
+ // String
+ // Deprecated. format string for how time is displayed in the input box using strftime, see dojo.date.strftime
+ timeFormat: "",
+
+//FIXME: need saveFormat attribute support
+
+ // type of format appropriate to locale. see dojo.date.format
+ formatLength: "short",
+
+ // String
+ // time value in RFC3339 format (http://www.ietf.org/rfc/rfc3339.txt)
+ // ex: 12:00
+ value: "",
+
+ postMixInProperties: function() {
+ dojo.widget.DropdownTimePicker.superclass.postMixInProperties.apply(this, arguments);
+ var messages = dojo.i18n.getLocalization("dojo.widget", "DropdownTimePicker", this.lang);
+ this.iconAlt = messages.selectTime;
+ },
+
+ fillInTemplate: function(){
+ dojo.widget.DropdownTimePicker.superclass.fillInTemplate.apply(this, arguments);
+
+ var timeProps = { widgetContainerId: this.widgetId, lang: this.lang };
+ this.timePicker = dojo.widget.createWidget("TimePicker", timeProps, this.containerNode, "child");
+ dojo.event.connect(this.timePicker, "onSetTime", this, "onSetTime");
+ dojo.event.connect(this.inputNode, "onchange", this, "onInputChange");
+ this.containerNode.style.zIndex = this.zIndex;
+ this.containerNode.explodeClassName = "timeBorder";
+ if(this.value){
+ this.timePicker.selectedTime.anyTime = false;
+ this.timePicker.setDateTime("2005-01-01T" + this.value);
+ this.timePicker.initData();
+ this.timePicker.initUI();
+ this.onSetTime();
+ }
+ },
+
+ onSetTime: function(){
+ // summary: callback when user sets the time via the TimePicker widget
+ if(this.timePicker.selectedTime.anyTime){
+ this.inputNode.value = "";
+ }else if(this.timeFormat){
+ dojo.deprecated("dojo.widget.DropdownTimePicker",
+ "Must use displayFormat attribute instead of timeFormat. See dojo.date.format for specification.", "0.5");
+ this.inputNode.value = dojo.date.strftime(this.timePicker.time, this.timeFormat, this.lang);
+ }else{
+ this.inputNode.value = dojo.date.format(this.timePicker.time,
+ {formatLength:this.formatLength, datePattern:this.displayFormat, selector:'timeOnly', locale:this.lang});
+ }
+
+ this.hideContainer();
+ },
+
+ onInputChange: function(){
+ // summary: callback when the user has typed in a time value manually
+ this.timePicker.time = "2005-01-01T" + this.inputNode.value; //FIXME: i18n
+ this.timePicker.setDateTime(this.timePicker.time);
+ this.timePicker.initData();
+ this.timePicker.initUI();
+ },
+
+ enable: function() {
+ // summary: enable this widget to accept user input
+ this.inputNode.disabled = false;
+ this.timePicker.enable();
+ dojo.widget.DropdownTimePicker.superclass.enable.apply(this, arguments);
+ },
+
+ disable: function() {
+ // summary: lock this widget so that the user can't change the value
+ this.inputNode.disabled = true;
+ this.timePicker.disable();
+ dojo.widget.DropdownTimePicker.superclass.disable.apply(this, arguments);
+ }
+ }
+);
Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js
------------------------------------------------------------------------------
svn:eol-style = native
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -13,60 +13,79 @@
* - test, bug fix, more features :)
*/
dojo.provide("dojo.widget.Editor");
-dojo.provide("dojo.widget.html.Editor");
+dojo.deprecated("dojo.widget.Editor", "is replaced by dojo.widget.Editor2", "0.5");
+
+dojo.require("dojo.io.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Toolbar");
dojo.require("dojo.widget.RichText");
dojo.require("dojo.widget.ColorPalette");
+dojo.require("dojo.string.extras");
dojo.widget.tags.addParseTreeHandler("dojo:Editor");
-dojo.widget.html.Editor = function() {
+dojo.widget.Editor = function() {
dojo.widget.HtmlWidget.call(this);
this.contentFilters = [];
+ this._toolbars = [];
}
-dojo.inherits(dojo.widget.html.Editor, dojo.widget.HtmlWidget);
+dojo.inherits(dojo.widget.Editor, dojo.widget.HtmlWidget);
-dojo.widget.html.Editor.itemGroups = {
+dojo.widget.Editor.itemGroups = {
textGroup: ["bold", "italic", "underline", "strikethrough"],
- blockGroup: ["formatBlock", "fontName"],
+ blockGroup: ["formatBlock", "fontName", "fontSize"],
justifyGroup: ["justifyleft", "justifycenter", "justifyright"],
commandGroup: ["save", "cancel"],
colorGroup: ["forecolor", "hilitecolor"],
listGroup: ["insertorderedlist", "insertunorderedlist"],
indentGroup: ["outdent", "indent"],
- linkGroup: ["createlink", "insertimage"]
+ linkGroup: ["createlink", "insertimage", "inserthorizontalrule"]
};
-dojo.widget.html.Editor.formatBlockValues = {
+dojo.widget.Editor.formatBlockValues = {
"Normal": "p",
"Main heading": "h2",
"Sub heading": "h3",
- "Sub sub headering": "h4",
+ "Sub sub heading": "h4",
"Preformatted": "pre"
};
-dojo.widget.html.Editor.fontNameValues = {
+dojo.widget.Editor.fontNameValues = {
"Arial": "Arial, Helvetica, sans-serif",
"Verdana": "Verdana, sans-serif",
"Times New Roman": "Times New Roman, serif",
"Courier": "Courier New, monospace"
};
-dojo.widget.html.Editor.defaultItems = [
- "commandGroup", "|", "linkGroup", "|", "textGroup", "|", "justifyGroup", "|", "listGroup", "indentGroup", "|", "colorGroup"
+dojo.widget.Editor.fontSizeValues = {
+ "1 (8 pt)" : "1",
+ "2 (10 pt)": "2",
+ "3 (12 pt)": "3",
+ "4 (14 pt)": "4",
+ "5 (18 pt)": "5",
+ "6 (24 pt)": "6",
+ "7 (36 pt)": "7"
+};
+
+dojo.widget.Editor.defaultItems = [
+ "commandGroup", "|", "blockGroup", "|", "textGroup", "|", "colorGroup", "|", "justifyGroup", "|", "listGroup", "indentGroup", "|", "linkGroup"
];
// ones we support by default without asking the RichText component
// NOTE: you shouldn't put buttons like bold, italic, etc in here
-dojo.widget.html.Editor.supportedCommands = ["save", "cancel", "|", "-", "/", " "];
+dojo.widget.Editor.supportedCommands = ["save", "cancel", "|", "-", "/", " "];
-dojo.lang.extend(dojo.widget.html.Editor, {
+dojo.lang.extend(dojo.widget.Editor, {
widgetType: "Editor",
- items: dojo.widget.html.Editor.defaultItems,
- formatBlockItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.formatBlockValues),
- fontNameItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.fontNameValues),
+ saveUrl: "",
+ saveMethod: "post",
+ saveArgName: "editorContent",
+ closeOnSave: false,
+ items: dojo.widget.Editor.defaultItems,
+ formatBlockItems: dojo.lang.shallowCopy(dojo.widget.Editor.formatBlockValues),
+ fontNameItems: dojo.lang.shallowCopy(dojo.widget.Editor.fontNameValues),
+ fontSizeItems: dojo.lang.shallowCopy(dojo.widget.Editor.fontSizeValues),
// used to get the properties of an item if it is given as a string
getItemProperties: function(name) {
@@ -109,6 +128,10 @@
case "fontname":
props.name = "fontName";
props.values = this.fontNameItems;
+
+ case "fontsize":
+ props.name = "fontSize";
+ props.values = this.fontSizeItems;
}
return props;
},
@@ -194,7 +217,7 @@
addToolbar: function(toolbar) {
this.initToolbar();
- if(!(toolbar instanceof dojo.widget.html.Toolbar)) {
+ if(!(toolbar instanceof dojo.widget.Toolbar)) {
toolbar = dojo.widget.createWidget(this._toolbarType);
}
this._toolbarContainer.addChild(toolbar);
@@ -206,7 +229,7 @@
if(!tb) { tb = this._toolbars[0]; }
var cmd = ((item)&&(!dojo.lang.isUndefined(item["getValue"]))) ? cmd = item["getValue"](): item;
- var groups = dojo.widget.html.Editor.itemGroups;
+ var groups = dojo.widget.Editor.itemGroups;
if(item instanceof dojo.widget.ToolbarItem) {
tb.addChild(item);
} else if(groups[cmd]) {
@@ -221,7 +244,15 @@
worked = false;
}
}
- if(btnGroup.length) {
+ if(btnGroup.length){
+ /*
+ // the addChild interface is assinine. Work around it.
+ var tprops = this.getItemProperties(cmd);
+ var tmpGroup = dojo.widget.createWidget("ToolbarButtonGroup", tprops);
+ dojo.debug(btnGroup);
+ dojo.event.connect(tmpGroup, "onClick", this, "_action");
+ dojo.event.connect(tmpGroup, "onChangeSelect", this, "_action");
+ */
var btn = tb.addChild(btnGroup, null, this.getItemProperties(cmd));
dojo.event.connect(btn, "onClick", this, "_action");
dojo.event.connect(btn, "onChangeSelect", this, "_action");
@@ -260,12 +291,23 @@
dojo.event.connect(select, "onSetValue", dojo.lang.hitch(this, function(item, value) {
this.onAction("fontName", value);
}));
+ } else if(cmd == "fontsize") {
+ var select = dojo.widget.createWidget("ToolbarSelect", {
+ name: "fontSize",
+ values: this.fontSizeItems
+ });
+ tb.addChild(select);
+ dojo.event.connect(select, "onSetValue", dojo.lang.hitch(this, function(item, value) {
+ this.onAction("fontSize", value);
+ }));
} else if(dojo.lang.inArray(cmd, ["forecolor", "hilitecolor"])) {
var btn = tb.addChild(dojo.widget.createWidget("ToolbarColorDialog", this.getItemProperties(cmd)));
dojo.event.connect(btn, "onSetValue", this, "_setValue");
} else {
var btn = tb.addChild(this.getCommandImage(cmd), null, this.getItemProperties(cmd));
- if(dojo.lang.inArray(cmd, ["save", "cancel"])) {
+ if(cmd == "save"){
+ dojo.event.connect(btn, "onClick", this, "_save");
+ }else if(cmd == "cancel"){
dojo.event.connect(btn, "onClick", this, "_close");
} else {
dojo.event.connect(btn, "onClick", this, "_action");
@@ -321,7 +363,7 @@
var items = this._toolbarContainer.getItems();
for(var i = 0; i < items.length; i++) {
var item = items[i];
- if(item instanceof dojo.widget.html.ToolbarSeparator) { continue; }
+ if(item instanceof dojo.widget.ToolbarSeparator) { continue; }
var cmd = item._name;
if (cmd == "save" || cmd == "cancel") { continue; }
else if(cmd == "justifyGroup") {
@@ -376,14 +418,14 @@
}
},
- supportedCommands: dojo.widget.html.Editor.supportedCommands.concat(),
+ supportedCommands: dojo.widget.Editor.supportedCommands.concat(),
isSupportedCommand: function(cmd) {
// FIXME: how do we check for ActiveX?
var yes = dojo.lang.inArray(cmd, this.supportedCommands);
if(!yes) {
try {
- var richText = this._richText || dojo.widget.html.RichText.prototype;
+ var richText = this._richText || dojo.widget.HtmlRichText.prototype;
yes = richText.queryCommandAvailable(cmd);
} catch(E) {}
}
@@ -399,9 +441,6 @@
},
_action: function(e) {
- // djConfig.isDebug = true;
- // dojo.debug(e);
- // dojo.debug(e.getValue());
this._fire("onAction", e.getValue());
},
@@ -409,6 +448,26 @@
this._fire("onAction", a.getValue(), b);
},
+ _save: function(e){
+ // FIXME: how should this behave when there's a larger form in play?
+ if(!this._richText.isClosed){
+ if(this.saveUrl.length){
+ var content = {};
+ content[this.saveArgName] = this.getHtml();
+ dojo.io.bind({
+ method: this.saveMethod,
+ url: this.saveUrl,
+ content: content
+ });
+ }else{
+ dojo.debug("please set a saveUrl for the editor");
+ }
+ if(this.closeOnSave){
+ this._richText.close(e.getName().toLowerCase() == "save");
+ }
+ }
+ },
+
_close: function(e) {
if(!this._richText.isClosed) {
this._richText.close(e.getName().toLowerCase() == "save");
@@ -450,7 +509,7 @@
},
getHtml: function(){
- this._richText.contentFilters = this.contentFilters;
+ this._richText.contentFilters = this._richText.contentFilters.concat(this.contentFilters);
return this._richText.getEditorContent();
},
@@ -473,147 +532,3 @@
onCancel: function(){}
});
-/*
-function dontRunMe() {
-function createToolbar() {
- tick("createToolbar");
- tick("ct-init");
- tbCont = dojo.widget.createWidget("toolbarContainer");
- tb = dojo.widget.createWidget("toolbar");
- tbCont.addChild(tb);
-
- var saveBtn = tb.addChild("Save");
- dojo.event.connect(saveBtn, "onClick", function() { editor.close(true); });
- var cancelBtn = tb.addChild("Cancel");
- dojo.event.connect(cancelBtn, "onClick", function() { editor.close(false); });
- tb.addChild("|");
-
- var headings = dojo.widget.createWidget("ToolbarSelect", {
- name: "formatBlock",
- values: {
- "Normal": "p",
- "Main heading": "h2",
- "Sub heading": "h3",
- "Sub sub heading": "h4",
- "Preformatted": "pre"
- }
- });
- dojo.event.connect(headings, "onSetValue", function(item, val) {
- editor.execCommand("formatBlock", val);
- });
- tb.addChild(headings);
- tb.addChild("|");
- tock("ct-init");
-
- // toolbar layout (2 rows):
- // Save Cancel | WikiWord | Link Img | Table
- // Heading FontFace | B I U | Alignment | OL UL < > | FG BG
- var rows = [
- ["save", "cancel", "|", "wikiword", "|", "createlink", "insertimage", "|", "table"],
- ["formatBlock", "font", "|", "bold", "italic", "underline", "|", "justification", "|", "ol", "ul", "forecolor", "hilitecolor"]
- ];
-
- tick("command array");
- var commands = [
- { values: ["bold", "italic", "underline", "strikethrough"], toggleItem: true },
- { values: [
- dojo.widget.createWidget("ToolbarColorDialog", {toggleItem: true, name: "forecolor", icon: cmdImg("forecolor")}),
- dojo.widget.createWidget("ToolbarColorDialog", {toggleItem: true, name: "hilitecolor", icon: cmdImg("hilitecolor")})
- ]},
- { values: ["justifyleft", "justifycenter", "justifyright"], name: "justify", defaultButton: "justifyleft", buttonGroup: true, preventDeselect: true },
- { values: ["createlink", "insertimage"] },
- { values: ["outdent", "indent"] },
- { values: ["insertorderedlist", "insertunorderedlist"], name: "list", buttonGroup: true },
- { values: ["undo", "redo"] },
- { values: ["wikiword"], title: "WikiWord" }
- ];
- tock("command array");
-
- tick("processCommands");
- for(var i = 0; i < commands.length; i++) {
- var set = commands[i];
- var values = set.values;
- var btnGroup = [set.name];
- for(var j = 0; j < values.length; j++) {
- if(typeof values[j] == "string") {
- var cmd = values[j];
- if(cmd == "wikiword") {
- var btn = tb.addChild(cmdImg(cmd), null, {name:cmd, label:"WikiWord"});
- //dojo.event.connect(bt, "onClick", listenWikiWord);
- //dojo.event.connect(bt, "onChangeSelect", listenWikiWord);
- } else if(dojo.widget.html.RichText.prototype.queryCommandAvailable(cmd)) {
- if(set.buttonGroup) {
- btnGroup.push(cmdImg(cmd));
- } else {
- var btn = tb.addChild(cmdImg(cmd), null, {name:cmd, toggleItem:set.toggleItem});
- dojo.event.connect(btn, "onClick", listen);
- dojo.event.connect(btn, "onChangeSelect", listen);
- }
- }
- } else {
- if(dojo.widget.html.RichText.prototype.queryCommandAvailable(values[j].getName())) {
- var btn = tb.addChild(values[j]);
- dojo.event.connect(btn, "onSetValue", colorListen, values[j].getName());
- }
- }
- }
- if(set.buttonGroup && btnGroup.length > 1) {
- var btn = tb.addChild(btnGroup, null, {defaultButton:set.defaultButton});
- dojo.event.connect(btn, "onClick", listen);
- dojo.event.connect(btn, "onChangeSelect", listen);
- }
-
- if(i + 1 != commands.length
- && !(tb.children[tb.children.length-1] instanceof dojo.widget.html.ToolbarSeparator)) {
- tb.addChild("|");
- }
- }
- tock("processCommands");
- tock("createToolbar");
- return tbCont;
-}
-function cmdImg(cmd) {
- return dojo.uri.dojoUri("src/widget/templates/buttons/" + cmd + ".gif");
-}
-function createWysiwyg(node) {
- tick("createWysiwyg");
- tick("editor");
- editor = dojo.widget.createWidget("RichText", {}, node);
- tock("editor");
- dojo.event.connect(editor, "close", function(changed) {
- if(changed) { setTimeout(save, 5); }
- setTimeout(function() {
- dojo.io.bind({
- url: location,
- content: {
- edit: "0",
- cancel: "Cancel"
- },
- handler: function() {
- hideLoad();
- }
- });
- }, 15);
- finishEdit();
- });
- autolinkWikiWords(editor);
- cleanupWord(editor);
- //createToolbar();
- dojo.event.connect(editor, "onDisplayChanged", updateToolbar);
-
- if(editor && tbCont && tb) {
- var top = document.getElementById("jot-topbar");
- dojo.html.addClass(top, "hidden");
- //placeToolbar(tbCont.domNode);
- //top.appendChild(tbCont.domNode);
- //document.getElementById("jot-bottombar").innerHTML = " ";
- } else {
- alert("Something went wrong trying to create the toolbar + editor.");
- }
- tock("createWysiwyg");
-
- return editor;
-}
-
-}
-*/