You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2006/06/27 22:49:06 UTC
svn commit: r417618 [9/19] - in /incubator/xap/trunk/src/dojo/src: ./ lfx/
logging/ rpc/ selection/ storage/ string/ text/ undo/ uri/ uuid/ widget/
widget/html/ widget/svg/ widget/templates/ widget/templates/buttons/
widget/templates/images/ widget/tem...
Added: incubator/xap/trunk/src/dojo/src/widget/Dialog.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/Dialog.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/Dialog.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/Dialog.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,269 @@
+/*
+ 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.Dialog");
+dojo.provide("dojo.widget.html.Dialog");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.event.*");
+dojo.require("dojo.graphics.color");
+dojo.require("dojo.html");
+
+dojo.widget.defineWidget(
+ "dojo.widget.html.Dialog",
+ dojo.widget.html.ContentPane,
+ {
+ templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDialog.html"),
+ isContainer: true,
+ _scrollConnected: false,
+
+ // provide a focusable element or element id if you need to
+ // work around FF's tendency to send focus into outer space on hide
+ focusElement: "",
+
+ bg: null,
+ bgColor: "black",
+ bgOpacity: 0.4,
+ followScroll: true,
+ _fromTrap: false,
+ anim: null,
+ blockDuration: 0,
+ lifetime: 0,
+
+ trapTabs: function(e){
+ if(e.target == this.tabStart) {
+ if(this._fromTrap) {
+ this._fromTrap = false;
+ } else {
+ this._fromTrap = true;
+ this.tabEnd.focus();
+ }
+ } else if(e.target == this.tabEnd) {
+ if(this._fromTrap) {
+ this._fromTrap = false;
+ } else {
+ this._fromTrap = true;
+ this.tabStart.focus();
+ }
+ }
+ },
+
+ clearTrap: function(e) {
+ var _this = this;
+ setTimeout(function() {
+ _this._fromTrap = false;
+ }, 100);
+ },
+
+ postCreate: function(args, frag, parentComp) {
+ with(this.domNode.style) {
+ position = "absolute";
+ zIndex = 999;
+ display = "none";
+ overflow = "visible";
+ }
+ var b = document.body;
+ b.appendChild(this.domNode);
+
+ this.bg = document.createElement("div");
+ this.bg.className = "dialogUnderlay";
+ with(this.bg.style) {
+ position = "absolute";
+ left = top = "0px";
+ zIndex = 998;
+ display = "none";
+ }
+ this.setBackgroundColor(this.bgColor);
+ b.appendChild(this.bg);
+
+ this.bgIframe = new dojo.html.BackgroundIframe(this.bg);
+ },
+
+ setBackgroundColor: function(color) {
+ if(arguments.length >= 3) {
+ color = new dojo.graphics.color.Color(arguments[0], arguments[1], arguments[2]);
+ } else {
+ color = new dojo.graphics.color.Color(color);
+ }
+ this.bg.style.backgroundColor = color.toString();
+ return this.bgColor = color;
+ },
+
+ setBackgroundOpacity: function(op) {
+ if(arguments.length == 0) { op = this.bgOpacity; }
+ dojo.style.setOpacity(this.bg, op);
+ try {
+ this.bgOpacity = dojo.style.getOpacity(this.bg);
+ } catch (e) {
+ this.bgOpacity = op;
+ }
+ return this.bgOpacity;
+ },
+
+ sizeBackground: function() {
+ if(this.bgOpacity > 0) {
+ var h = Math.max(
+ document.documentElement.scrollHeight || document.body.scrollHeight,
+ dojo.html.getViewportHeight());
+ var w = dojo.html.getViewportWidth();
+ this.bg.style.width = w + "px";
+ this.bg.style.height = h + "px";
+ }
+ this.bgIframe.onResized();
+ },
+
+ showBackground: function() {
+ this.sizeBackground();
+ if(this.bgOpacity > 0) {
+ this.bg.style.display = "block";
+ }
+ },
+
+ placeDialog: function() {
+ var scroll_offset = dojo.html.getScrollOffset();
+ var viewport_size = dojo.html.getViewportSize();
+
+ // find the size of the dialog
+ var w = dojo.style.getOuterWidth(this.containerNode);
+ var h = dojo.style.getOuterHeight(this.containerNode);
+
+ var x = scroll_offset[0] + (viewport_size[0] - w)/2;
+ var y = scroll_offset[1] + (viewport_size[1] - h)/2;
+
+ with(this.domNode.style) {
+ left = x + "px";
+ top = y + "px";
+ }
+ },
+
+ show: function() {
+ this.setBackgroundOpacity();
+ this.showBackground();
+
+ dojo.widget.html.Dialog.superclass.show.call(this);
+
+ // FIXME: moz doesn't generate onscroll events for mouse or key scrolling (wtf)
+ // we should create a fake event by polling the scrolltop/scrollleft every X ms.
+ // this smells like it should be a dojo feature rather than just for this widget.
+
+ if (this.followScroll && !this._scrollConnected){
+ this._scrollConnected = true;
+ dojo.event.connect(window, "onscroll", this, "onScroll");
+ }
+
+ if(this.lifetime){
+ this.timeRemaining = this.lifetime;
+ if(!this.blockDuration){
+ dojo.event.connect(this.bg, "onclick", this, "hide");
+ }else{
+ dojo.event.disconnect(this.bg, "onclick", this, "hide");
+ }
+ if(this.timerNode){
+ this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
+ }
+ if(this.blockDuration && this.closeNode){
+ if(this.lifetime > this.blockDuration){
+ this.closeNode.style.visibility = "hidden";
+ }else{
+ this.closeNode.style.display = "none";
+ }
+ }
+ this.timer = setInterval(dojo.lang.hitch(this, "onTick"), 100);
+ }
+
+ this.onParentResized();
+ },
+
+ onLoad: function(){
+ // when href is specified we need to reposition
+ // the dialog after the data is loaded
+ this.placeDialog();
+ },
+
+ fillInTemplate: function(){
+ // dojo.event.connect(this.domNode, "onclick", this, "killEvent");
+ },
+
+ hide: function(){
+ // workaround for FF focus going into outer space
+ if (this.focusElement) {
+ dojo.byId(this.focusElement).focus();
+ dojo.byId(this.focusElement).blur();
+ }
+
+ if(this.timer){
+ clearInterval(this.timer);
+ }
+
+ this.bg.style.display = "none";
+ this.bg.style.width = this.bg.style.height = "1px";
+
+ dojo.widget.html.Dialog.superclass.hide.call(this);
+
+ if (this._scrollConnected){
+ this._scrollConnected = false;
+ dojo.event.disconnect(window, "onscroll", this, "onScroll");
+ }
+ },
+
+ setTimerNode: function(node){
+ this.timerNode = node;
+ },
+
+ setCloseControl: function(node) {
+ this.closeNode = node;
+ dojo.event.connect(node, "onclick", this, "hide");
+ },
+
+ setShowControl: function(node) {
+ dojo.event.connect(node, "onclick", this, "show");
+ },
+
+ onTick: function(){
+ if(this.timer){
+ this.timeRemaining -= 100;
+ if(this.lifetime - this.timeRemaining >= this.blockDuration){
+ dojo.event.connect(this.bg, "onclick", this, "hide");
+ if(this.closeNode){
+ this.closeNode.style.visibility = "visible";
+ }
+ }
+ if(!this.timeRemaining){
+ clearInterval(this.timer);
+ this.hide();
+ }else if(this.timerNode){
+ this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
+ }
+ }
+ },
+
+ onScroll: function(){
+ this.placeDialog();
+ this.domNode.style.display = "block";
+ },
+
+ // Called when the browser window's size is changed
+ onParentResized: function() {
+ if(this.isShowing()){
+ this.sizeBackground();
+ this.placeDialog();
+ this.domNode.style.display="block";
+ this.onResized();
+ }
+ },
+
+ killEvent: function(evt){
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+
+ }
+);
Propchange: incubator/xap/trunk/src/dojo/src/widget/Dialog.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/widget/DocPane.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/DocPane.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/DocPane.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/DocPane.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,12 @@
+/*
+ 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.DocPane");
+dojo.requireAfterIf("html", "dojo.widget.html.DocPane");
Added: incubator/xap/trunk/src/dojo/src/widget/DomWidget.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/DomWidget.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/DomWidget.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/DomWidget.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,555 @@
+/*
+ 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.DomWidget");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.Widget");
+dojo.require("dojo.dom");
+dojo.require("dojo.xml.Parse");
+dojo.require("dojo.uri.*");
+dojo.require("dojo.lang.func");
+
+dojo.widget._cssFiles = {};
+dojo.widget._cssStrings = {};
+dojo.widget._templateCache = {};
+
+dojo.widget.defaultStrings = {
+ dojoRoot: dojo.hostenv.getBaseScriptUri(),
+ baseScriptUri: dojo.hostenv.getBaseScriptUri()
+};
+
+dojo.widget.buildFromTemplate = function() {
+ dojo.lang.forward("fillFromTemplateCache");
+}
+
+// static method to build from a template w/ or w/o a real widget in place
+dojo.widget.fillFromTemplateCache = function(obj, templatePath, templateCssPath, templateString, avoidCache){
+ // dojo.debug("avoidCache:", avoidCache);
+ var tpath = templatePath || obj.templatePath;
+ var cpath = templateCssPath || obj.templateCssPath;
+
+ // DEPRECATED: use Uri objects, not strings
+ if (tpath && !(tpath instanceof dojo.uri.Uri)) {
+ tpath = dojo.uri.dojoUri(tpath);
+ dojo.deprecated("templatePath should be of type dojo.uri.Uri");
+ }
+ if (cpath && !(cpath instanceof dojo.uri.Uri)) {
+ cpath = dojo.uri.dojoUri(cpath);
+ dojo.deprecated("templateCssPath should be of type dojo.uri.Uri");
+ }
+
+ var tmplts = dojo.widget._templateCache;
+ if(!obj["widgetType"]) { // don't have a real template here
+ do {
+ var dummyName = "__dummyTemplate__" + dojo.widget._templateCache.dummyCount++;
+ } while(tmplts[dummyName]);
+ obj.widgetType = dummyName;
+ }
+ var wt = obj.widgetType;
+
+ if((!obj.templateCssString)&&(cpath)&&(!dojo.widget._cssFiles[cpath])){
+ obj.templateCssString = dojo.hostenv.getText(cpath);
+ obj.templateCssPath = null;
+ dojo.widget._cssFiles[cpath] = true;
+ }
+ if((obj["templateCssString"])&&(!obj.templateCssString["loaded"])){
+ dojo.style.insertCssText(obj.templateCssString, null, cpath);
+ if(!obj.templateCssString){ obj.templateCssString = ""; }
+ obj.templateCssString.loaded = true;
+ }
+
+ var ts = tmplts[wt];
+ if(!ts){
+ tmplts[wt] = { "string": null, "node": null };
+ if(avoidCache){
+ ts = {};
+ }else{
+ ts = tmplts[wt];
+ }
+ }
+ if(!obj.templateString){
+ obj.templateString = templateString || ts["string"];
+ }
+ if(!obj.templateNode){
+ obj.templateNode = ts["node"];
+ }
+ if((!obj.templateNode)&&(!obj.templateString)&&(tpath)){
+ // fetch a text fragment and assign it to templateString
+ // NOTE: we rely on blocking IO here!
+ var tstring = dojo.hostenv.getText(tpath);
+ if(tstring){
+ var matches = tstring.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+ if(matches){
+ tstring = matches[1];
+ }
+ }else{
+ tstring = "";
+ }
+ obj.templateString = tstring;
+ if(!avoidCache){
+ tmplts[wt]["string"] = tstring;
+ }
+ }
+ if((!ts["string"])&&(!avoidCache)){
+ ts.string = obj.templateString;
+ }
+}
+dojo.widget._templateCache.dummyCount = 0;
+
+dojo.widget.attachProperties = ["dojoAttachPoint", "id"];
+dojo.widget.eventAttachProperty = "dojoAttachEvent";
+dojo.widget.onBuildProperty = "dojoOnBuild";
+
+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?)
+ // c.) how expensive event assignment is (less eval(), more connect())
+ // var start = new Date();
+ var elementNodeType = dojo.dom.ELEMENT_NODE;
+
+ function trim(str){
+ return str.replace(/^\s+|\s+$/g, "");
+ }
+
+ if(!rootNode){
+ rootNode = targetObj.domNode;
+ }
+
+ if(rootNode.nodeType != elementNodeType){
+ return;
+ }
+ // alert(events.length);
+
+ 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? 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<attachPoint.length; z++){
+ if(dojo.lang.isArray(targetObj[attachPoint[z]])){
+ targetObj[attachPoint[z]].push(baseNode);
+ }else{
+ targetObj[attachPoint[z]]=baseNode;
+ }
+ }
+ break;
+ }
+ }
+ // continue;
+
+ // FIXME: we need to put this into some kind of lookup structure
+ // instead of direct assignment
+ var tmpltPoint = baseNode.getAttribute(this.templateProperty);
+ if(tmpltPoint){
+ 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 = 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]));
+ }
+ }
+ }
+
+ var onBuild = baseNode.getAttribute(this.onBuildProperty);
+ if(onBuild){
+ eval("var node = baseNode; var widget = targetObj; "+onBuild);
+ }
+ }
+
+}
+
+dojo.widget.getDojoEventsFromStr = function(str){
+ // 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; }
+ var cm = evts[x].replace(/\s/, "");
+ cm = (cm.slice(0, cm.length-1));
+ if(!lem[cm]){
+ lem[cm] = true;
+ ret.push(cm);
+ }
+ }
+ return ret;
+}
+
+/*
+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.declare("dojo.widget.DomWidget", dojo.widget.Widget, {
+ initializer: function() {
+ if((arguments.length>0)&&(typeof arguments[0] == "object")){
+ this.create(arguments[0]);
+ }
+ },
+
+ templateNode: null,
+ templateString: null,
+ templateCssString: 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){
+ // if(!cn){ cn = document.body; }
+ if(!cn){ cn = document.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);
+
+ // 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);
+ }
+ }
+ }
+ },
+
+ // Record that given widget descends from me
+ registerChild: function(widget, insertionIndex){
+
+ // 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++){
+ if (this.children[i].dojoInsertionIndex < insertionIndex){
+ idx = i;
+ }
+ }
+
+ this.children.splice(idx+1, 0, widget);
+
+ widget.parent = this;
+ widget.addedTo(this);
+
+ // 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){
+ // 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);
+ },
+
+ getFragNodeRef: function(frag){
+ if( !frag || !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);
+ },
+
+ // 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);
+ }
+ }
+
+ // 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.createSubComponents(frag, this);
+ }
+ },
+
+ // method over-ride
+ buildRendering: function(args, frag){
+ // DOM widgets construct themselves from a template
+ var ts = dojo.widget._templateCache[this.widgetType];
+ 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
+ // dojo.debug("buildFromTemplate:", this);
+ var avoidCache = false;
+ if(args["templatecsspath"]){
+ args["templateCssPath"] = args["templatecsspath"];
+ }
+ if(args["templatepath"]){
+ avoidCache = true;
+ args["templatePath"] = args["templatepath"];
+ }
+ dojo.widget.fillFromTemplateCache( this,
+ args["templatePath"],
+ args["templateCssPath"],
+ 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.") ? 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);
+ }
+ }
+ }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];
+ }
+
+ // 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");
+
+ // 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(){
+ // dojo.unimplemented("dojo.widget.DomWidget.fillInTemplate");
+ },
+
+ // method over-ride
+ destroyRendering: function(){
+ try{
+ delete this.domNode;
+ }catch(e){ /* squelch! */ }
+ },
+
+ // FIXME: method over-ride
+ cleanUp: function(){},
+
+ getContainerHeight: function(){
+ dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
+ },
+
+ getContainerWidth: function(){
+ dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
+ },
+
+ createNodesFromText: function(){
+ dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
+ }
+});
Propchange: incubator/xap/trunk/src/dojo/src/widget/DomWidget.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/widget/DropdownButton.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/DropdownButton.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/DropdownButton.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/DropdownButton.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,29 @@
+/*
+ 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.DropdownButton");
+
+dojo.deprecated("dojo.widget.DropdownButton", "use dojo.widget.ComboButton", "0.4");
+
+// Draws a button with a down arrow;
+// when you press the down arrow something appears (usually a menu)
+
+dojo.require("dojo.widget.*");
+
+dojo.widget.tags.addParseTreeHandler("dojo:dropdownbutton");
+
+dojo.widget.DropdownButton = function(){
+ dojo.widget.Widget.call(this);
+
+ this.widgetType = "DropdownButton";
+}
+dojo.inherits(dojo.widget.DropdownButton, dojo.widget.Widget);
+
+dojo.requireAfterIf("html", "dojo.widget.html.DropdownButton");
Added: incubator/xap/trunk/src/dojo/src/widget/DropdownContainer.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/DropdownContainer.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/DropdownContainer.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/DropdownContainer.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,104 @@
+/*
+ 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.event.*");
+dojo.require("dojo.html");
+
+dojo.widget.defineWidget(
+ "dojo.widget.DropdownContainer",
+ dojo.widget.HtmlWidget,
+ {
+ initializer: function(){
+ },
+
+ isContainer: true,
+ snarfChildDomOutput: true,
+
+ inputWidth: "7em",
+ inputId: "",
+ inputName: "",
+ iconURL: null,
+ iconAlt: null,
+
+ inputNode: null,
+ buttonNode: null,
+ containerNode: null,
+ subWidgetNode: null,
+
+ templateString: '<div><span style="white-space:nowrap"><input type="text" value="" style="vertical-align:middle;" dojoAttachPoint="inputNode" autocomplete="off" /> <img src="" alt="" dojoAttachPoint="buttonNode" dojoAttachEvent="onclick: onIconClick;" style="vertical-align:middle; cursor:pointer; cursor:hand;" /></span><br /><div dojoAttachPoint="containerNode" style="display:none;position:absolute;width:12em;background-color:#fff;"></div></div>',
+ templateCssPath: "",
+
+ fillInTemplate: function(args, frag){
+ var source = this.getFragNodeRef(frag);
+
+ if(args.inputId){ this.inputId = args.inputId; }
+ if(args.inputName){ this.inputName = args.inputName; }
+ if(args.iconURL){ this.iconURL = args.iconURL; }
+ if(args.iconAlt){ this.iconAlt = args.iconAlt; }
+
+ this.containerNode.style.left = "";
+ this.containerNode.style.top = "";
+
+ if(this.inputId){ this.inputNode.id = this.inputId; }
+ if(this.inputName){ this.inputNode.name = this.inputName; }
+ this.inputNode.style.width = this.inputWidth;
+
+ if(this.iconURL){ this.buttonNode.src = this.iconURL; }
+ if(this.iconAlt){ this.buttonNode.alt = this.iconAlt; }
+
+ dojo.event.connect(this.inputNode, "onchange", this, "onInputChange");
+
+ this.containerIframe = new dojo.html.BackgroundIframe(this.containerNode);
+ this.containerIframe.size([0,0,0,0]);
+ },
+
+ onIconClick: function(evt){
+ this.toggleContainerShow();
+ },
+
+ toggleContainerShow: function(){
+ if(dojo.html.isShowing(this.containerNode)){
+ dojo.html.hide(this.containerNode);
+ }else{
+ this.showContainer();
+ }
+ },
+
+ showContainer: function(){
+ dojo.html.show(this.containerNode);
+ this.sizeBackgroundIframe();
+ },
+
+ onHide: function(evt){
+ dojo.html.hide(this.containerNode);
+ },
+
+ sizeBackgroundIframe: function(){
+ var w = dojo.style.getOuterWidth(this.containerNode);
+ var h = dojo.style.getOuterHeight(this.containerNode);
+ if(w==0||h==0){
+ // need more time to calculate size
+ dojo.lang.setTimeout(this, "sizeBackgroundIframe", 100);
+ return;
+ }
+ if(dojo.html.isShowing(this.containerNode)){
+ this.containerIframe.size([0,0,w,h]);
+ }
+ },
+
+ onInputChange: function(){}
+ },
+ "html"
+);
+
+dojo.widget.tags.addParseTreeHandler("dojo:dropdowncontainer");
\ No newline at end of file
Added: incubator/xap/trunk/src/dojo/src/widget/DropdownDatePicker.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/DropdownDatePicker.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/DropdownDatePicker.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/DropdownDatePicker.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,67 @@
+/*
+ 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.widget.defineWidget(
+ "dojo.widget.DropdownDatePicker",
+ dojo.widget.DropdownContainer,
+ {
+ iconURL: dojo.uri.dojoUri("src/widget/templates/images/dateIcon.gif"),
+ iconAlt: "Select a Date",
+ iconTitle: "Select a Date",
+
+ datePicker: null,
+
+ dateFormat: "%m/%d/%Y",
+ date: null,
+
+ fillInTemplate: function(args, frag){
+ dojo.widget.DropdownDatePicker.superclass.fillInTemplate.call(this, args, frag);
+ var source = this.getFragNodeRef(frag);
+
+ if(args.dateFormat){ this.dateFormat = args.dateFormat; }
+ if(args.date){ this.date = new Date(args.date); }
+
+ var dpNode = document.createElement("div");
+ this.containerNode.appendChild(dpNode);
+
+ var dateProps = { widgetContainerId: this.widgetId };
+ if(this.date){
+ dateProps["date"] = this.date;
+ dateProps["storedDate"] = dojo.widget.DatePicker.util.toRfcDate(this.date);
+ this.inputNode.value = dojo.date.format(this.date, this.dateFormat);
+ }
+ this.datePicker = dojo.widget.createWidget("DatePicker", dateProps, dpNode);
+ dojo.event.connect(this.datePicker, "onSetDate", this, "onSetDate");
+ },
+
+ onSetDate: function(){
+ this.inputNode.value = dojo.date.format(this.datePicker.date, this.dateFormat);
+ this.onHide();
+ },
+
+ onInputChange: function(){
+ var tmp = new Date(this.inputNode.value);
+ this.datePicker.date = tmp;
+ this.datePicker.setDate(dojo.widget.DatePicker.util.toRfcDate(tmp));
+ this.datePicker.initData();
+ this.datePicker.initUI();
+ }
+ },
+ "html"
+);
+
+dojo.widget.tags.addParseTreeHandler("dojo:dropdowndatepicker");
\ No newline at end of file
Propchange: incubator/xap/trunk/src/dojo/src/widget/DropdownDatePicker.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/widget/Editor.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/Editor.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/Editor.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/Editor.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,533 @@
+/*
+ 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
+*/
+
+/* TODO:
+ * - font selector
+ * - test, bug fix, more features :)
+*/
+dojo.provide("dojo.widget.Editor");
+dojo.provide("dojo.widget.html.Editor");
+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.HtmlWidget.call(this);
+ this.contentFilters = [];
+ this._toolbars = [];
+}
+dojo.inherits(dojo.widget.html.Editor, dojo.widget.HtmlWidget);
+
+dojo.widget.html.Editor.itemGroups = {
+ textGroup: ["bold", "italic", "underline", "strikethrough"],
+ blockGroup: ["formatBlock", "fontName", "fontSize"],
+ justifyGroup: ["justifyleft", "justifycenter", "justifyright"],
+ commandGroup: ["save", "cancel"],
+ colorGroup: ["forecolor", "hilitecolor"],
+ listGroup: ["insertorderedlist", "insertunorderedlist"],
+ indentGroup: ["outdent", "indent"],
+ linkGroup: ["createlink", "insertimage", "inserthorizontalrule"]
+};
+
+dojo.widget.html.Editor.formatBlockValues = {
+ "Normal": "p",
+ "Main heading": "h2",
+ "Sub heading": "h3",
+ "Sub sub heading": "h4",
+ "Preformatted": "pre"
+};
+
+dojo.widget.html.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.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.html.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.lang.extend(dojo.widget.html.Editor, {
+ widgetType: "Editor",
+
+ saveUrl: "",
+ saveMethod: "post",
+ saveArgName: "editorContent",
+ closeOnSave: false,
+ items: dojo.widget.html.Editor.defaultItems,
+ formatBlockItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.formatBlockValues),
+ fontNameItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.fontNameValues),
+ fontSizeItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.fontSizeValues),
+
+ // used to get the properties of an item if it is given as a string
+ getItemProperties: function(name) {
+ var props = {};
+ switch(name.toLowerCase()) {
+ case "bold":
+ case "italic":
+ case "underline":
+ case "strikethrough":
+ props.toggleItem = true;
+ break;
+
+ case "justifygroup":
+ props.defaultButton = "justifyleft";
+ props.preventDeselect = true;
+ props.buttonGroup = true;
+ break;
+
+ case "listgroup":
+ props.buttonGroup = true;
+ break;
+
+ case "save":
+ case "cancel":
+ props.label = dojo.string.capitalize(name);
+ break;
+
+ case "forecolor":
+ case "hilitecolor":
+ props.name = name;
+ props.toggleItem = true; // FIXME: they aren't exactly toggle items
+ props.icon = this.getCommandImage(name);
+ break;
+
+ case "formatblock":
+ props.name = "formatBlock";
+ props.values = this.formatBlockItems;
+ break;
+
+ case "fontname":
+ props.name = "fontName";
+ props.values = this.fontNameItems;
+
+ case "fontsize":
+ props.name = "fontSize";
+ props.values = this.fontSizeItems;
+ }
+ return props;
+ },
+
+ validateItems: true, // set to false to add items, regardless of support
+ focusOnLoad: true,
+ minHeight: "1em",
+
+ _richText: null, // RichText widget
+ _richTextType: "RichText",
+
+ _toolbarContainer: null, // ToolbarContainer widget
+ _toolbarContainerType: "ToolbarContainer",
+
+ _toolbars: [],
+ _toolbarType: "Toolbar",
+
+ _toolbarItemType: "ToolbarItem",
+
+ buildRendering: function(args, frag) {
+ // get the node from args/frag
+ var node = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+ var trt = dojo.widget.createWidget(this._richTextType, {
+ focusOnLoad: this.focusOnLoad,
+ minHeight: this.minHeight
+ }, node)
+ var _this = this;
+ // this appears to fix a weird timing bug on Safari
+ setTimeout(function(){
+ _this.setRichText(trt);
+
+ _this.initToolbar();
+
+ _this.fillInTemplate(args, frag);
+ }, 0);
+ },
+
+ setRichText: function(richText) {
+ if(this._richText && this._richText == richText) {
+ dojo.debug("Already set the richText to this richText!");
+ return;
+ }
+
+ if(this._richText && !this._richText.isClosed) {
+ dojo.debug("You are switching richTexts yet you haven't closed the current one. Losing reference!");
+ }
+ this._richText = richText;
+ dojo.event.connect(this._richText, "close", this, "onClose");
+ dojo.event.connect(this._richText, "onLoad", this, "onLoad");
+ dojo.event.connect(this._richText, "onDisplayChanged", this, "updateToolbar");
+ if(this._toolbarContainer) {
+ this._toolbarContainer.enable();
+ this.updateToolbar(true);
+ }
+ },
+
+ initToolbar: function() {
+ // var tic = new Date();
+ if(this._toolbarContainer) { return; } // only create it once
+ this._toolbarContainer = dojo.widget.createWidget(this._toolbarContainerType);
+ var tb = this.addToolbar();
+ var last = true;
+ for(var i = 0; i < this.items.length; i++) {
+ if(this.items[i] == "\n") { // new row
+ tb = this.addToolbar();
+ } else {
+ if((this.items[i] == "|")&&(!last)){
+ last = true;
+ }else{
+ last = this.addItem(this.items[i], tb);
+ }
+ }
+ }
+ this.insertToolbar(this._toolbarContainer.domNode, this._richText.domNode);
+ // alert(new Date - tic);
+ },
+
+ // allow people to override this so they can make their own placement logic
+ insertToolbar: function(tbNode, richTextNode) {
+ dojo.html.insertBefore(tbNode, richTextNode);
+ //dojo.html.insertBefore(this._toolbarContainer.domNode, this._richText.domNode);
+ },
+
+ addToolbar: function(toolbar) {
+ this.initToolbar();
+ if(!(toolbar instanceof dojo.widget.html.Toolbar)) {
+ toolbar = dojo.widget.createWidget(this._toolbarType);
+ }
+ this._toolbarContainer.addChild(toolbar);
+ this._toolbars.push(toolbar);
+ return toolbar;
+ },
+
+ addItem: function(item, tb, dontValidate) {
+ 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;
+ if(item instanceof dojo.widget.ToolbarItem) {
+ tb.addChild(item);
+ } else if(groups[cmd]) {
+ var group = groups[cmd];
+ var worked = true;
+ if(cmd == "justifyGroup" || cmd == "listGroup") {
+ var btnGroup = [cmd];
+ for(var i = 0 ; i < group.length; i++) {
+ if(dontValidate || this.isSupportedCommand(group[i])) {
+ btnGroup.push(this.getCommandImage(group[i]));
+ }else{
+ worked = false;
+ }
+ }
+ 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");
+ }
+ return worked;
+ } else {
+ for(var i = 0; i < group.length; i++) {
+ if(!this.addItem(group[i], tb)){
+ worked = false;
+ }
+ }
+ return worked;
+ }
+ } else {
+ if((!dontValidate)&&(!this.isSupportedCommand(cmd))){
+ return false;
+ }
+ if(dontValidate || this.isSupportedCommand(cmd)) {
+ cmd = cmd.toLowerCase();
+ if(cmd == "formatblock") {
+ var select = dojo.widget.createWidget("ToolbarSelect", {
+ name: "formatBlock",
+ values: this.formatBlockItems
+ });
+ tb.addChild(select);
+ var _this = this;
+ dojo.event.connect(select, "onSetValue", function(item, value) {
+ _this.onAction("formatBlock", value);
+ });
+ } else if(cmd == "fontname") {
+ var select = dojo.widget.createWidget("ToolbarSelect", {
+ name: "fontName",
+ values: this.fontNameItems
+ });
+ tb.addChild(select);
+ 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(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");
+ dojo.event.connect(btn, "onChangeSelect", this, "_action");
+ }
+ }
+ }
+ }
+ return true;
+ },
+
+ enableToolbar: function() {
+ if(this._toolbarContainer) {
+ this._toolbarContainer.domNode.style.display = "";
+ this._toolbarContainer.enable();
+ }
+ },
+
+ disableToolbar: function(hide){
+ if(hide){
+ if(this._toolbarContainer){
+ this._toolbarContainer.domNode.style.display = "none";
+ }
+ }else{
+ if(this._toolbarContainer){
+ this._toolbarContainer.disable();
+ }
+ }
+ },
+
+ _updateToolbarLastRan: null,
+ _updateToolbarTimer: null,
+ _updateToolbarFrequency: 500,
+
+ updateToolbar: function(force) {
+ if(!this._toolbarContainer) { return; }
+
+ // keeps the toolbar from updating too frequently
+ // TODO: generalize this functionality?
+ var diff = new Date() - this._updateToolbarLastRan;
+ if(!force && this._updateToolbarLastRan && (diff < this._updateToolbarFrequency)) {
+ clearTimeout(this._updateToolbarTimer);
+ var _this = this;
+ this._updateToolbarTimer = setTimeout(function() {
+ _this.updateToolbar();
+ }, this._updateToolbarFrequency/2);
+ return;
+ } else {
+ this._updateToolbarLastRan = new Date();
+ }
+ // end frequency checker
+
+ 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; }
+ var cmd = item._name;
+ if (cmd == "save" || cmd == "cancel") { continue; }
+ else if(cmd == "justifyGroup") {
+ try {
+ if(!this._richText.queryCommandEnabled("justifyleft")) {
+ item.disable(false, true);
+ } else {
+ item.enable(false, true);
+ var jitems = item.getItems();
+ for(var j = 0; j < jitems.length; j++) {
+ var name = jitems[j]._name;
+ var value = this._richText.queryCommandValue(name);
+ if(typeof value == "boolean" && value) {
+ value = name;
+ break;
+ } else if(typeof value == "string") {
+ value = "justify"+value;
+ } else {
+ value = null;
+ }
+ }
+ if(!value) { value = "justifyleft"; } // TODO: query actual style
+ item.setValue(value, false, true);
+ }
+ } catch(err) {}
+ } else if(cmd == "listGroup") {
+ var litems = item.getItems();
+ for(var j = 0; j < litems.length; j++) {
+ this.updateItem(litems[j]);
+ }
+ } else {
+ this.updateItem(item);
+ }
+ }
+ },
+
+ updateItem: function(item) {
+ try {
+ var cmd = item._name;
+ var enabled = this._richText.queryCommandEnabled(cmd);
+ item.setEnabled(enabled, false, true);
+
+ var active = this._richText.queryCommandState(cmd);
+ if(active && cmd == "underline") {
+ // don't activate underlining if we are on a link
+ active = !this._richText.queryCommandEnabled("unlink");
+ }
+ item.setSelected(active, false, true);
+ return true;
+ } catch(err) {
+ return false;
+ }
+ },
+
+ supportedCommands: dojo.widget.html.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.HtmlRichText.prototype;
+ yes = richText.queryCommandAvailable(cmd);
+ } catch(E) {}
+ }
+ return yes;
+ },
+
+ getCommandImage: function(cmd) {
+ if(cmd == "|") {
+ return cmd;
+ } else {
+ return dojo.uri.dojoUri("src/widget/templates/buttons/" + cmd + ".gif");
+ }
+ },
+
+ _action: function(e) {
+ this._fire("onAction", e.getValue());
+ },
+
+ _setValue: function(a, b) {
+ 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");
+ }
+ },
+
+ onAction: function(cmd, value) {
+ switch(cmd) {
+ case "createlink":
+ if(!(value = prompt("Please enter the URL of the link:", "http://"))) {
+ return;
+ }
+ break;
+ case "insertimage":
+ if(!(value = prompt("Please enter the URL of the image:", "http://"))) {
+ return;
+ }
+ break;
+ }
+ this._richText.execCommand(cmd, value);
+ },
+
+ fillInTemplate: function(args, frag) {
+ // dojo.event.connect(this, "onResized", this._richText, "onResized");
+ },
+
+ _fire: function(eventName) {
+ if(dojo.lang.isFunction(this[eventName])) {
+ var args = [];
+ if(arguments.length == 1) {
+ args.push(this);
+ } else {
+ for(var i = 1; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ }
+ this[eventName].apply(this, args);
+ }
+ },
+
+ getHtml: function(){
+ this._richText.contentFilters = this._richText.contentFilters.concat(this.contentFilters);
+ return this._richText.getEditorContent();
+ },
+
+ getEditorContent: function(){
+ return this.getHtml();
+ },
+
+ onClose: function(save, hide){
+ this.disableToolbar(hide);
+ if(save) {
+ this._fire("onSave");
+ } else {
+ this._fire("onCancel");
+ }
+ },
+
+ // events baby!
+ onLoad: function(){},
+ onSave: function(){},
+ onCancel: function(){}
+});
+
Propchange: incubator/xap/trunk/src/dojo/src/widget/Editor.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/widget/Editor2.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/Editor2.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/Editor2.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/Editor2.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,378 @@
+/*
+ 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
+*/
+
+/* TODO:
+ * - font selector
+ * - test, bug fix, more features :)
+*/
+dojo.provide("dojo.widget.Editor2");
+dojo.provide("dojo.widget.html.Editor2");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.RichText");
+dojo.require("dojo.widget.Editor2Toolbar");
+// dojo.require("dojo.widget.ColorPalette");
+// dojo.require("dojo.string.extras");
+
+dojo.widget.defineWidget(
+ "dojo.widget.html.Editor2",
+ dojo.widget.html.RichText,
+ {
+ saveUrl: "",
+ saveMethod: "post",
+ saveArgName: "editorContent",
+ closeOnSave: false,
+ shareToolbar: false,
+ toolbarAlwaysVisible: false,
+ htmlEditing: false,
+ _inHtmlMode: false,
+ _htmlEditNode: null,
+
+ commandList: dojo.widget.html.Editor2Toolbar.prototype.commandList,
+ toolbarWidget: null,
+ scrollInterval: null,
+
+
+ editorOnLoad: function(){
+ var toolbars = dojo.widget.byType("Editor2Toolbar");
+ if((!toolbars.length)||(!this.shareToolbar)){
+ var tbOpts = {};
+ tbOpts.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbarOneline.html");
+ this.toolbarWidget = dojo.widget.createWidget("Editor2Toolbar",
+ tbOpts, this.domNode, "before");
+ dojo.event.connect(this, "destroy", this.toolbarWidget, "destroy");
+ this.toolbarWidget.hideUnusableButtons(this);
+
+ if(this.object){
+ this.tbBgIframe = new dojo.html.BackgroundIframe(this.toolbarWidget.domNode);
+ this.tbBgIframe.iframe.style.height = "30px";
+ }
+
+ // need to set position fixed to wherever this thing has landed
+ if(this.toolbarAlwaysVisible){
+ var src = document["documentElement"]||window;
+ this.scrollInterval = setInterval(dojo.lang.hitch(this, "globalOnScrollHandler"), 100);
+ // dojo.event.connect(src, "onscroll", this, "globalOnScrollHandler");
+ dojo.event.connect("before", this, "destroyRendering", this, "unhookScroller");
+ }
+ }else{
+ // FIXME: should we try harder to explicitly manage focus in
+ // order to prevent too many editors from all querying
+ // for button status concurrently?
+ // FIXME: selecting in one shared toolbar doesn't clobber
+ // selection in the others. This is problematic.
+ this.toolbarWidget = toolbars[0];
+ }
+ dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onfocus");
+ // dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onclick");
+ dojo.event.topic.subscribe("Editor2.clobberFocus", this, "setBlur");
+ dojo.event.connect(this.editNode, "onfocus", this, "setFocus");
+ dojo.event.connect(this.toolbarWidget.linkButton, "onclick",
+ dojo.lang.hitch(this, function(){
+ var range;
+ if(this.document.selection){
+ range = this.document.selection.createRange().text;
+ }else if(dojo.render.html.mozilla){
+ range = this.window.getSelection().toString();
+ }
+ if(range.length){
+ this.toolbarWidget.exec("createlink",
+ prompt("Please enter the URL of the link:", "http://"));
+ }else{
+ alert("Please select text to link");
+ }
+ })
+ );
+
+ var focusFunc = dojo.lang.hitch(this, function(){
+ if(dojo.render.html.ie){
+ this.editNode.focus();
+ }else{
+ this.window.focus();
+ }
+ });
+
+ dojo.event.connect(this.toolbarWidget, "formatSelectClick", focusFunc);
+ dojo.event.connect(this, "execCommand", focusFunc);
+
+ if(this.htmlEditing){
+ var tb = this.toolbarWidget.htmltoggleButton;
+ if(tb){
+ tb.style.display = "";
+ dojo.event.connect(this.toolbarWidget, "htmltoggleClick",
+ this, "toggleHtmlEditing");
+ }
+ }
+ },
+
+ toggleHtmlEditing: function(){
+ if(!this._inHtmlMode){
+ this._inHtmlMode = true;
+ this.toolbarWidget.highlightButton("htmltoggle");
+ if(!this._htmlEditNode){
+ this._htmlEditNode = document.createElement("textarea");
+ dojo.html.insertBefore(this._htmlEditNode, this.domNode);
+ }
+ this._htmlEditNode.style.display = "";
+ this._htmlEditNode.style.width = "100%";
+ this._htmlEditNode.style.height = dojo.style.getInnerHeight(this.editNode)+"px";
+ this._htmlEditNode.value = this.editNode.innerHTML;
+ this.domNode.style.display = "none";
+ }else{
+ this._inHtmlMode = false;
+ this.domNode.style.display = "";
+ this.toolbarWidget.unhighlightButton("htmltoggle");
+ dojo.lang.setTimeout(this, "replaceEditorContent", 1, this._htmlEditNode.value);
+ this._htmlEditNode.style.display = "none";
+ this.editNode.focus();
+ }
+ },
+
+ setFocus: function(){
+ // dojo.debug("setFocus:", this);
+ dojo.event.connect(this.toolbarWidget, "exec", this, "execCommand");
+ },
+
+ setBlur: function(){
+ // dojo.debug("setBlur:", this);
+ dojo.event.disconnect(this.toolbarWidget, "exec", this, "execCommand");
+ },
+
+ _scrollSetUp: false,
+ _fixEnabled: false,
+ _scrollThreshold: false,
+ _handleScroll: true,
+ globalOnScrollHandler: function(){
+ var isIE = dojo.render.html.ie;
+ if(!this._handleScroll){ return; }
+ var ds = dojo.style;
+ var tdn = this.toolbarWidget.domNode;
+ var db = document["body"];
+ var totalHeight = ds.getOuterHeight(tdn);
+ if(!this._scrollSetUp){
+ this._scrollSetUp = true;
+ var editorWidth = ds.getOuterWidth(this.domNode);
+ this._scrollThreshold = ds.abs(tdn, false).y;
+ // dojo.debug("threshold:", this._scrollThreshold);
+ if((isIE)&&(db)&&(ds.getStyle(db, "background-image")=="none")){
+ with(db.style){
+ backgroundImage = "url(" + dojo.uri.dojoUri("src/widget/templates/images/blank.gif") + ")";
+ backgroundAttachment = "fixed";
+ }
+ }
+ }
+
+ var scrollPos = (window["pageYOffset"]) ? window["pageYOffset"] : (document["documentElement"]||document["body"]).scrollTop;
+
+ // FIXME: need to have top and bottom thresholds so toolbar doesn't keep scrolling past the bottom
+ if(scrollPos > this._scrollThreshold){
+ // dojo.debug(scrollPos);
+ if(!this._fixEnabled){
+ this.domNode.style.marginTop = totalHeight+"px";
+ if(isIE){
+ // FIXME: should we just use setBehvior() here instead?
+ var cl = dojo.style.abs(tdn).x;
+ document.body.appendChild(tdn);
+ tdn.style.left = cl+dojo.style.getPixelValue(document.body, "margin-left")+"px";
+ dojo.html.addClass(tdn, "IEFixedToolbar");
+ if(this.object){
+ dojo.html.addClass(this.tbBgIframe, "IEFixedToolbar");
+ }
+
+ }else{
+ with(tdn.style){
+ position = "fixed";
+ top = "0px";
+ }
+ }
+ tdn.style.zIndex = 1000;
+ this._fixEnabled = true;
+ }
+ }else if(this._fixEnabled){
+ this.domNode.style.marginTop = null;
+ with(tdn.style){
+ position = "";
+ top = "";
+ zIndex = "";
+ if(isIE){
+ marginTop = "";
+ }
+ }
+ if(isIE){
+ dojo.html.removeClass(tdn, "IEFixedToolbar");
+ dojo.html.insertBefore(tdn, this._htmlEditNode||this.domNode);
+ }
+ this._fixEnabled = false;
+ }
+ },
+
+ unhookScroller: function(){
+ this._handleScroll = false;
+ clearInterval(this.scrollInterval);
+ // var src = document["documentElement"]||window;
+ // dojo.event.disconnect(src, "onscroll", this, "globalOnScrollHandler");
+ if(dojo.render.html.ie){
+ dojo.html.removeClass(this.toolbarWidget.domNode, "IEFixedToolbar");
+ }
+ },
+
+ _updateToolbarLastRan: null,
+ _updateToolbarTimer: null,
+ _updateToolbarFrequency: 500,
+
+ updateToolbar: function(force){
+ if((!this.isLoaded)||(!this.toolbarWidget)){ return; }
+
+ // keeps the toolbar from updating too frequently
+ // TODO: generalize this functionality?
+ var diff = new Date() - this._updateToolbarLastRan;
+ if( (!force)&&(this._updateToolbarLastRan)&&
+ ((diff < this._updateToolbarFrequency)) ){
+
+ clearTimeout(this._updateToolbarTimer);
+ var _this = this;
+ this._updateToolbarTimer = setTimeout(function() {
+ _this.updateToolbar();
+ }, this._updateToolbarFrequency/2);
+ return;
+
+ }else{
+ this._updateToolbarLastRan = new Date();
+ }
+ // end frequency checker
+
+ dojo.lang.forEach(this.commandList, function(cmd){
+ if(cmd == "inserthtml"){ return; }
+ try{
+ if(this.queryCommandEnabled(cmd)){
+ if(this.queryCommandState(cmd)){
+ this.toolbarWidget.highlightButton(cmd);
+ }else{
+ this.toolbarWidget.unhighlightButton(cmd);
+ }
+ }
+ }catch(e){
+ // alert(cmd+":"+e);
+ }
+ }, this);
+
+ var h = dojo.render.html;
+
+ // safari f's us for selection primitives
+ if(h.safari){ return; }
+
+ var selectedNode = (h.ie) ? this.document.selection.createRange().parentElement() : this.window.getSelection().anchorNode;
+ // make sure we actuall have an element
+ while((selectedNode)&&(selectedNode.nodeType != 1)){
+ selectedNode = selectedNode.parentNode;
+ }
+ if(!selectedNode){ return; }
+
+ var formats = ["p", "pre", "h1", "h2", "h3", "h4"];
+ // gotta run some specialized updates for the various
+ // formatting options
+ var type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
+ while((selectedNode)&&(selectedNode!=this.editNode)&&(!type)){
+ selectedNode = selectedNode.parentNode;
+ type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
+ }
+ if(!type){
+ type = "";
+ }else{
+ if(type.charAt(0)=="h"){
+ this.toolbarWidget.unhighlightButton("bold");
+ }
+ }
+ this.toolbarWidget.selectFormat(type);
+ },
+
+ updateItem: function(item) {
+ try {
+ var cmd = item._name;
+ var enabled = this._richText.queryCommandEnabled(cmd);
+ item.setEnabled(enabled, false, true);
+
+ var active = this._richText.queryCommandState(cmd);
+ if(active && cmd == "underline") {
+ // don't activate underlining if we are on a link
+ active = !this._richText.queryCommandEnabled("unlink");
+ }
+ item.setSelected(active, false, true);
+ return true;
+ } catch(err) {
+ return false;
+ }
+ },
+
+
+ _save: function(e){
+ // FIXME: how should this behave when there's a larger form in play?
+ if(!this.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.close(e.getName().toLowerCase() == "save");
+ }
+ }
+ },
+
+ wireUpOnLoad: function(){
+ if(!dojo.render.html.ie){
+ /*
+ dojo.event.kwConnect({
+ srcObj: this.document,
+ srcFunc: "click",
+ targetObj: this.toolbarWidget,
+ targetFunc: "hideAllDropDowns",
+ once: true
+ });
+ */
+ }
+ }
+ },
+ "html",
+ function(){
+ var cp = dojo.widget.html.Editor2.prototype;
+ if(!cp._wrappersSet){
+ cp._wrappersSet = true;
+ cp.fillInTemplate = (function(fit){
+ return function(){
+ fit.call(this);
+ this.editorOnLoad();
+ };
+ })(cp.fillInTemplate);
+
+ cp.onDisplayChanged = (function(odc){
+ return function(){
+ try{
+ odc.call(this);
+ this.updateToolbar();
+ }catch(e){}
+ };
+ })(cp.onDisplayChanged);
+
+ cp.onLoad = (function(ol){
+ return function(){
+ ol.call(this);
+ this.wireUpOnLoad();
+ };
+ })(cp.onLoad);
+ }
+ }
+);
Propchange: incubator/xap/trunk/src/dojo/src/widget/Editor2.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/widget/Editor2Toolbar.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/widget/Editor2Toolbar.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/widget/Editor2Toolbar.js (added)
+++ incubator/xap/trunk/src/dojo/src/widget/Editor2Toolbar.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,316 @@
+/*
+ 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.Editor2Toolbar");
+dojo.provide("dojo.widget.html.Editor2Toolbar");
+
+dojo.require("dojo.lang.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.RichText");
+dojo.require("dojo.widget.ColorPalette");
+
+dojo.widget.defineWidget(
+ "dojo.widget.html.Editor2Toolbar",
+ dojo.widget.HtmlWidget,
+ {
+ commandList: [ "bold", "italic", "underline", "subscript", "superscript",
+ "fontname", "fontsize", "forecolor", "hilitecolor", "justifycenter",
+ "justifyfull", "justifyleft", "justifyright", "cut", "copy", "paste",
+ "delete", "undo", "redo", "createlink", "unlink", "removeformat",
+ "inserthorizontalrule", "insertimage", "insertorderedlist",
+ "insertunorderedlist", "indent", "outdent", "formatblock", "strikethrough",
+ "inserthtml", "blockdirltr", "blockdirrtl", "dirltr", "dirrtl",
+ "inlinedirltr", "inlinedirrtl", "inserttable", "insertcell",
+ "insertcol", "insertrow", "deletecells", "deletecols", "deleterows",
+ "mergecells", "splitcell"
+ ],
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbar.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbar.css"),
+
+ forecolorPalette: null,
+ hilitecolorPalette: null,
+
+ // DOM Nodes
+ wikiwordButton: null,
+ htmltoggleButton: null,
+ insertimageButton: null,
+ styleDropdownButton: null,
+ styleDropdownContainer: null,
+ copyButton: null,
+ boldButton: null,
+ italicButton: null,
+ underlineButton: null,
+ justifycenterButton: null,
+ justifyleftButton: null,
+ justifyfullButton: null,
+ justifyrightButton: null,
+ pasteButton: null,
+ undoButton: null,
+ redoButton: null,
+ linkButton: null,
+ insertunorderedlistButton: null,
+ insertorderedlistButton: null,
+ forecolorButton: null,
+ forecolorDropDown: null,
+ hilitecolorButton: null,
+ hilitecolorDropDown: null,
+ formatSelectBox: null,
+ inserthorizontalruleButton: null,
+ strikethroughButton: null,
+ clickInterceptDiv: null,
+ oneLineTr: null,
+
+ buttonClick: function(e){ e.preventDefault(); /* dojo.debug("buttonClick"); */ },
+
+ buttonMouseOver: function(e){ },
+ buttonMouseOut: function(e){ },
+
+
+ // event signals
+ preventSelect: function(e){ if(dojo.render.html.safari){ e.preventDefault(); } },
+ wikiwordClick: function(){ },
+ insertimageClick: function(){ },
+ htmltoggleClick: function(){ },
+
+ styleDropdownClick: function(){
+ dojo.debug("styleDropdownClick:", this.styleDropdownContainer);
+ dojo.style.toggleShowing(this.styleDropdownContainer);
+ },
+
+
+ copyClick: function(){ this.exec("copy"); },
+ boldClick: function(){ this.exec("bold"); },
+ italicClick: function(){ this.exec("italic"); },
+ underlineClick: function(){ this.exec("underline"); },
+ justifyleftClick: function(){ this.exec("justifyleft"); },
+ justifycenterClick: function(){ this.exec("justifycenter"); },
+ justifyfullClick: function(){ this.exec("justifyfull"); },
+ justifyrightClick: function(){ this.exec("justifyright"); },
+ pasteClick: function(){ this.exec("paste"); },
+ undoClick: function(){ this.exec("undo"); },
+ redoClick: function(){ this.exec("redo"); },
+ linkClick: function(){
+ // FIXME: we need to alert the user if they haven't selected any text
+ // this.exec( "createlink",
+ // prompt("Please enter the URL of the link:", "http://"));
+ },
+ insertunorderedlistClick: function(){ this.exec("insertunorderedlist"); },
+ insertorderedlistClick: function(){ this.exec("insertorderedlist"); },
+ inserthorizontalruleClick: function(){ this.exec("inserthorizontalrule"); },
+ strikethroughClick: function(){ this.exec("strikethrough"); },
+
+ formatSelectClick: function(){
+ var sv = this.formatSelectBox.value.toLowerCase();
+ this.exec("formatblock", sv);
+ },
+
+ normalTextClick: function(){ this.exec("formatblock", "p"); },
+ h1TextClick: function(){ this.exec("formatblock", "h1"); },
+ h2TextClick: function(){ this.exec("formatblock", "h2"); },
+ h3TextClick: function(){ this.exec("formatblock", "h3"); },
+ h4TextClick: function(){ this.exec("formatblock", "h4"); },
+ indentClick: function(){ this.exec("indent"); },
+ outdentClick: function(){ this.exec("outdent"); },
+
+
+ hideAllDropDowns: function(){
+ this.domNode.style.height = "";
+ dojo.lang.forEach(dojo.widget.byType("Editor2Toolbar"), function(tb){
+ try{
+ dojo.style.hide(tb.forecolorDropDown);
+ dojo.style.hide(tb.hilitecolorDropDown);
+ dojo.style.hide(tb.styleDropdownContainer);
+ if(tb.clickInterceptDiv){
+ dojo.style.hide(tb.clickInterceptDiv);
+ }
+ }catch(e){}
+ if(dojo.render.html.ie){
+ try{
+ dojo.style.hide(tb.forecolorPalette.bgIframe);
+ }catch(e){}
+ try{
+ dojo.style.hide(tb.hilitecolorPalette.bgIframe);
+ }catch(e){}
+ }
+ });
+ },
+
+ selectFormat: function(format){
+ dojo.lang.forEach(this.formatSelectBox.options, function(item){
+ if(item.value.toLowerCase() == format.toLowerCase()){
+ item.selected = true;
+ }
+ });
+ },
+
+ forecolorClick: function(e){
+ this.colorClick(e, "forecolor");
+ },
+
+ hilitecolorClick: function(e){
+ this.colorClick(e, "hilitecolor");
+ },
+
+ // FIXME: these methods aren't currently dealing with clicking in the
+ // general document to hide the menu
+ colorClick: function(e, type){
+ var h = dojo.render.html;
+ this.hideAllDropDowns();
+ // FIXME: if we've been "popped out", we need to set the height of the toolbar.
+ e.stopPropagation();
+ var dd = this[type+"DropDown"];
+ var pal = this[type+"Palette"];
+ dojo.style.toggleShowing(dd);
+ if(!pal){
+ pal = this[type+"Palette"] = dojo.widget.createWidget("ColorPalette", {}, dd, "first");
+ var fcp = pal.domNode;
+ with(dd.style){
+ width = dojo.html.getOuterWidth(fcp) + "px";
+ height = dojo.html.getOuterHeight(fcp) + "px";
+ zIndex = 1002;
+ position = "absolute";
+ }
+
+ dojo.event.connect( "after",
+ pal, "onColorSelect",
+ this, "exec",
+ function(mi){ mi.args.unshift(type); return mi.proceed(); }
+ );
+
+ dojo.event.connect( "after",
+ pal, "onColorSelect",
+ dojo.style, "toggleShowing",
+ this, function(mi){ mi.args.unshift(dd); return mi.proceed(); }
+ );
+
+ var cid = this.clickInterceptDiv;
+ if(!cid){
+ cid = this.clickInterceptDiv = document.createElement("div");
+ document.body.appendChild(cid);
+ with(cid.style){
+ backgroundColor = "transparent";
+ top = left = "0px";
+ height = width = "100%";
+ position = "absolute";
+ border = "none";
+ display = "none";
+ zIndex = 1001;
+ }
+ dojo.event.connect(cid, "onclick", function(){ cid.style.display = "none"; });
+ }
+ dojo.event.connect(pal, "onColorSelect", function(){ cid.style.display = "none"; });
+
+ dojo.event.kwConnect({
+ srcObj: document.body,
+ srcFunc: "onclick",
+ targetObj: this,
+ targetFunc: "hideAllDropDowns",
+ once: true
+ });
+ document.body.appendChild(dd);
+ }
+ dojo.style.toggleShowing(this.clickInterceptDiv);
+ var pos = dojo.style.abs(this[type+"Button"]);
+ dojo.html.placeOnScreenPoint(dd, pos.x, pos.y, 0, false);
+ if(pal.bgIframe){
+ with(pal.bgIframe.style){
+ display = "block";
+ left = dd.style.left;
+ top = dd.style.top;
+ width = dojo.style.getOuterWidth(dd)+"px";
+ height = dojo.style.getOuterHeight(dd)+"px";
+ }
+ }
+ },
+
+ uninitialize: function(){
+ dojo.event.kwDisconnect({
+ srcObj: document.body,
+ srcFunc: "onclick",
+ targetObj: this,
+ targetFunc: "hideAllDropDowns",
+ once: true
+ });
+ },
+
+ // stub for observers
+ exec: function(what, arg){ /* dojo.debug(what, new Date()); */ },
+
+ hideUnusableButtons: function(obj){
+ var op = obj||dojo.widget.html.RichText.prototype;
+ dojo.lang.forEach(this.commandList,
+ function(cmd){
+ if(this[cmd+"Button"]){
+ var cb = this[cmd+"Button"];
+ if(!op.queryCommandAvailable(cmd)){
+ cb.style.display = "none";
+ cb.parentNode.style.display = "none";
+ }
+ }
+ },
+ this);
+ if(this.oneLineTr){
+ var lastVisibleIsSpacer = false;
+ var lastVisible = false;
+ var tds = this.oneLineTr.getElementsByTagName("td");
+ dojo.lang.forEach(tds, function(td){
+ if(td.getAttribute("isSpacer")){
+ if(td.style.display != "none"){
+ if(lastVisibleIsSpacer){
+ td.style.display = "none";
+ }
+ lastVisibleIsSpacer = true;
+ }else{
+ lastVisible = td;
+ lastVisibleIsSpacer = true;
+ }
+ }else{
+ if(td.style.display != "none"){
+ lastVisible = td;
+ lastVisibleIsSpacer = false;
+ }
+ }
+ });
+ }
+ },
+
+ highlightButton: function(name){
+ var bn = name+"Button";
+ if(this[bn]){
+ with(this[bn].style){
+ backgroundColor = "White";
+ border = "1px solid #aeaeab";
+ }
+ }
+ },
+
+ unhighlightButton: function(name){
+ var bn = name+"Button";
+ if(this[bn]){
+ // dojo.debug("unhighlighting:", name);
+ with(this[bn].style){
+ backgroundColor = "";
+ border = "";
+ }
+ }
+ }
+ },
+ "html",
+ function(){
+ // dojo.event.connect(this, "fillInTemplate", this, "hideUnusableButtons");
+ dojo.event.connect(this, "fillInTemplate", dojo.lang.hitch(this, function(){
+ if(dojo.render.html.ie){
+ this.domNode.style.zoom = 1.0;
+ }
+ }));
+ }
+);
Propchange: incubator/xap/trunk/src/dojo/src/widget/Editor2Toolbar.js
------------------------------------------------------------------------------
svn:eol-style = native