diff options
author | 2008-11-13 09:49:11 +0000 | |
---|---|---|
committer | 2008-11-13 09:49:11 +0000 | |
commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dijit/Dialog.js | |
parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
download | scuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz scuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.zip |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dijit/Dialog.js')
-rw-r--r-- | includes/js/dijit/Dialog.js | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/includes/js/dijit/Dialog.js b/includes/js/dijit/Dialog.js new file mode 100644 index 0000000..928d0dc --- /dev/null +++ b/includes/js/dijit/Dialog.js @@ -0,0 +1,480 @@ +if(!dojo._hasResource["dijit.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit.Dialog"] = true; +dojo.provide("dijit.Dialog"); + +dojo.require("dojo.dnd.TimedMoveable"); +dojo.require("dojo.fx"); + +dojo.require("dijit._Widget"); +dojo.require("dijit._Templated"); +dojo.require("dijit.layout.ContentPane"); +dojo.require("dijit.form.Form"); +dojo.requireLocalization("dijit", "common", null, "zh,pt,da,tr,ru,de,sv,ja,he,fi,nb,el,ar,ROOT,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu"); + +dojo.declare( + "dijit.DialogUnderlay", + [dijit._Widget, dijit._Templated], + { + // summary: The component that grays out the screen behind the dialog + + // Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe. + // Inner div has opacity specified in CSS file. + templateString: "<div class='dijitDialogUnderlayWrapper' id='${id}_wrapper'><div class='dijitDialogUnderlay ${class}' id='${id}' dojoAttachPoint='node'></div></div>", + + attributeMap: {}, + + postCreate: function(){ + // summary: Append the underlay to the body + dojo.body().appendChild(this.domNode); + this.bgIframe = new dijit.BackgroundIframe(this.domNode); + }, + + layout: function(){ + // summary: Sets the background to the size of the viewport + // + // description: + // Sets the background to the size of the viewport (rather than the size + // of the document) since we need to cover the whole browser window, even + // if the document is only a few lines long. + + var viewport = dijit.getViewport(); + var is = this.node.style, + os = this.domNode.style; + + os.top = viewport.t + "px"; + os.left = viewport.l + "px"; + is.width = viewport.w + "px"; + is.height = viewport.h + "px"; + + // process twice since the scroll bar may have been removed + // by the previous resizing + var viewport2 = dijit.getViewport(); + if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; } + if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; } + }, + + show: function(){ + // summary: Show the dialog underlay + this.domNode.style.display = "block"; + this.layout(); + if(this.bgIframe.iframe){ + this.bgIframe.iframe.style.display = "block"; + } + this._resizeHandler = this.connect(window, "onresize", "layout"); + }, + + hide: function(){ + // summary: hides the dialog underlay + this.domNode.style.display = "none"; + if(this.bgIframe.iframe){ + this.bgIframe.iframe.style.display = "none"; + } + this.disconnect(this._resizeHandler); + }, + + uninitialize: function(){ + if(this.bgIframe){ + this.bgIframe.destroy(); + } + } + } +); + + +dojo.declare("dijit._DialogMixin", null, + { + attributeMap: dijit._Widget.prototype.attributeMap, + + // execute: Function + // User defined function to do stuff when the user hits the submit button + execute: function(/*Object*/ formContents){}, + + // onCancel: Function + // Callback when user has canceled dialog, to notify container + // (user shouldn't override) + onCancel: function(){}, + + // onExecute: Function + // Callback when user is about to execute dialog, to notify container + // (user shouldn't override) + onExecute: function(){}, + + _onSubmit: function(){ + // summary: callback when user hits submit button + this.onExecute(); // notify container that we are about to execute + this.execute(this.getValues()); + }, + + _getFocusItems: function(/*Node*/ dialogNode){ + // find focusable Items each time a dialog is opened + var focusItem = dijit.getFirstInTabbingOrder(dialogNode); + this._firstFocusItem = focusItem ? focusItem : dialogNode; + focusItem = dijit.getLastInTabbingOrder(dialogNode); + this._lastFocusItem = focusItem ? focusItem : this._firstFocusItem; + if(dojo.isMoz && this._firstFocusItem.tagName.toLowerCase() == "input" && dojo.attr(this._firstFocusItem, "type").toLowerCase() == "file"){ + //FF doesn't behave well when first element is input type=file, set first focusable to dialog container + dojo.attr(dialogNode, "tabindex", "0"); + this._firstFocusItem = dialogNode; + } + } + } +); + +dojo.declare( + "dijit.Dialog", + [dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin], + { + // summary: A modal dialog Widget + // + // description: + // Pops up a modal dialog window, blocking access to the screen + // and also graying out the screen Dialog is extended from + // ContentPane so it supports all the same parameters (href, etc.) + // + // example: + // | <div dojoType="dijit.Dialog" href="test.html"></div> + // + // example: + // | <div id="test">test content</div> + // | ... + // | var foo = new dijit.Dialog({ title: "test dialog" },dojo.byId("test")); + // | foo.startup(); + + templateString: null, + templateString:"<div class=\"dijitDialog\" tabindex=\"-1\" waiRole=\"dialog\" waiState=\"labelledby-${id}_title\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span dojoAttachPoint=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\">${title}</span>\n\t<span dojoAttachPoint=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" dojoAttachEvent=\"onclick: onCancel\">\n\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\">x</span>\n\t</span>\n\t</div>\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n", + + // open: Boolean + // is True or False depending on state of dialog + open: false, + + // duration: Integer + // The time in milliseconds it takes the dialog to fade in and out + duration: 400, + + // refocus: Boolean + // A Toggle to modify the default focus behavior of a Dialog, which + // is to re-focus the element which had focus before being opened. + // False will disable refocusing. Default: true + refocus: true, + + // _firstFocusItem: DomNode + // The pointer to the first focusable node in the dialog + _firstFocusItem:null, + + // _lastFocusItem: DomNode + // The pointer to which node has focus prior to our dialog + _lastFocusItem:null, + + // doLayout: Boolean + // Don't change this parameter from the default value. + // This ContentPane parameter doesn't make sense for Dialog, since Dialog + // is never a child of a layout container, nor can you specify the size of + // Dialog in order to control the size of an inner widget. + doLayout: false, + + attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap), + {title: "titleBar"}), + + postCreate: function(){ + dojo.body().appendChild(this.domNode); + this.inherited(arguments); + var _nlsResources = dojo.i18n.getLocalization("dijit", "common"); + if(this.closeButtonNode){ + this.closeButtonNode.setAttribute("title", _nlsResources.buttonCancel); + } + if(this.closeText){ + this.closeText.setAttribute("title", _nlsResources.buttonCancel); + } + var s = this.domNode.style; + s.visibility = "hidden"; + s.position = "absolute"; + s.display = ""; + s.top = "-9999px"; + + this.connect(this, "onExecute", "hide"); + this.connect(this, "onCancel", "hide"); + this._modalconnects = []; + }, + + onLoad: function(){ + // summary: when href is specified we need to reposition the dialog after the data is loaded + this._position(); + this.inherited(arguments); + }, + + _setup: function(){ + // summary: + // stuff we need to do before showing the Dialog for the first + // time (but we defer it until right beforehand, for + // performance reasons) + + if(this.titleBar){ + this._moveable = new dojo.dnd.TimedMoveable(this.domNode, { handle: this.titleBar, timeout: 0 }); + } + + this._underlay = new dijit.DialogUnderlay({ + id: this.id+"_underlay", + "class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ") + }); + + var node = this.domNode; + this._fadeIn = dojo.fx.combine( + [dojo.fadeIn({ + node: node, + duration: this.duration + }), + dojo.fadeIn({ + node: this._underlay.domNode, + duration: this.duration, + onBegin: dojo.hitch(this._underlay, "show") + }) + ] + ); + + this._fadeOut = dojo.fx.combine( + [dojo.fadeOut({ + node: node, + duration: this.duration, + onEnd: function(){ + node.style.visibility="hidden"; + node.style.top = "-9999px"; + } + }), + dojo.fadeOut({ + node: this._underlay.domNode, + duration: this.duration, + onEnd: dojo.hitch(this._underlay, "hide") + }) + ] + ); + }, + + uninitialize: function(){ + if(this._fadeIn && this._fadeIn.status() == "playing"){ + this._fadeIn.stop(); + } + if(this._fadeOut && this._fadeOut.status() == "playing"){ + this._fadeOut.stop(); + } + if(this._underlay){ + this._underlay.destroy(); + } + }, + + _position: function(){ + // summary: position modal dialog in center of screen + + if(dojo.hasClass(dojo.body(),"dojoMove")){ return; } + var viewport = dijit.getViewport(); + var mb = dojo.marginBox(this.domNode); + + var style = this.domNode.style; + style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px"; + style.top = Math.floor((viewport.t + (viewport.h - mb.h)/2)) + "px"; + }, + + _onKey: function(/*Event*/ evt){ + // summary: handles the keyboard events for accessibility reasons + if(evt.keyCode){ + var node = evt.target; + if (evt.keyCode == dojo.keys.TAB){ + this._getFocusItems(this.domNode); + } + var singleFocusItem = (this._firstFocusItem == this._lastFocusItem); + // see if we are shift-tabbing from first focusable item on dialog + if(node == this._firstFocusItem && evt.shiftKey && evt.keyCode == dojo.keys.TAB){ + if(!singleFocusItem){ + dijit.focus(this._lastFocusItem); // send focus to last item in dialog + } + dojo.stopEvent(evt); + }else if(node == this._lastFocusItem && evt.keyCode == dojo.keys.TAB && !evt.shiftKey){ + if (!singleFocusItem){ + dijit.focus(this._firstFocusItem); // send focus to first item in dialog + } + dojo.stopEvent(evt); + }else{ + // see if the key is for the dialog + while(node){ + if(node == this.domNode){ + if(evt.keyCode == dojo.keys.ESCAPE){ + this.hide(); + }else{ + return; // just let it go + } + } + node = node.parentNode; + } + // this key is for the disabled document window + if(evt.keyCode != dojo.keys.TAB){ // allow tabbing into the dialog for a11y + dojo.stopEvent(evt); + // opera won't tab to a div + }else if(!dojo.isOpera){ + try{ + this._firstFocusItem.focus(); + }catch(e){ /*squelch*/ } + } + } + } + }, + + show: function(){ + // summary: display the dialog + + if(this.open){ return; } + + // first time we show the dialog, there's some initialization stuff to do + if(!this._alreadyInitialized){ + this._setup(); + this._alreadyInitialized=true; + } + + if(this._fadeOut.status() == "playing"){ + this._fadeOut.stop(); + } + + this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout")); + this._modalconnects.push(dojo.connect(dojo.doc.documentElement, "onkeypress", this, "_onKey")); + + dojo.style(this.domNode, "opacity", 0); + this.domNode.style.visibility=""; + this.open = true; + this._loadCheck(); // lazy load trigger + + this._position(); + + this._fadeIn.play(); + + this._savedFocus = dijit.getFocus(this); + + // find focusable Items each time dialog is shown since if dialog contains a widget the + // first focusable items can change + this._getFocusItems(this.domNode); + + // set timeout to allow the browser to render dialog + setTimeout(dojo.hitch(this, function(){ + dijit.focus(this._firstFocusItem); + }), 50); + }, + + hide: function(){ + // summary: Hide the dialog + + // if we haven't been initialized yet then we aren't showing and we can just return + if(!this._alreadyInitialized){ + return; + } + + if(this._fadeIn.status() == "playing"){ + this._fadeIn.stop(); + } + this._fadeOut.play(); + + if (this._scrollConnected){ + this._scrollConnected = false; + } + dojo.forEach(this._modalconnects, dojo.disconnect); + this._modalconnects = []; + if(this.refocus){ + this.connect(this._fadeOut,"onEnd",dojo.hitch(dijit,"focus",this._savedFocus)); + } + this.open = false; + }, + + layout: function() { + // summary: position the Dialog and the underlay + if(this.domNode.style.visibility != "hidden"){ + this._underlay.layout(); + this._position(); + } + }, + + destroy: function(){ + dojo.forEach(this._modalconnects, dojo.disconnect); + if(this.refocus && this.open){ + var fo = this._savedFocus; + setTimeout(dojo.hitch(dijit,"focus",fo),25); + } + this.inherited(arguments); + } + } +); + +dojo.declare( + "dijit.TooltipDialog", + [dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin], + { + // summary: + // Pops up a dialog that appears like a Tooltip + // + // title: String + // Description of tooltip dialog (required for a11Y) + title: "", + + // doLayout: Boolean + // Don't change this parameter from the default value. + // This ContentPane parameter doesn't make sense for TooltipDialog, since TooltipDialog + // is never a child of a layout container, nor can you specify the size of + // TooltipDialog in order to control the size of an inner widget. + doLayout: false, + + // _firstFocusItem: DomNode + // The pointer to the first focusable node in the dialog + _firstFocusItem:null, + + // _lastFocusItem: DomNode + // The domNode that had focus before we took it. + _lastFocusItem: null, + + templateString: null, + templateString:"<div class=\"dijitTooltipDialog\" waiRole=\"presentation\">\n\t<div class=\"dijitTooltipContainer\" waiRole=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" tabindex=\"-1\" waiRole=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" waiRole=\"presenation\"></div>\n</div>\n", + + postCreate: function(){ + this.inherited(arguments); + this.connect(this.containerNode, "onkeypress", "_onKey"); + this.containerNode.title = this.title; + }, + + orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ corner){ + // summary: configure widget to be displayed in given position relative to the button + this.domNode.className="dijitTooltipDialog " +" dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above"); + }, + + onOpen: function(/*Object*/ pos){ + // summary: called when dialog is displayed + + this._getFocusItems(this.containerNode); + this.orient(this.domNode,pos.aroundCorner, pos.corner); + this._loadCheck(); // lazy load trigger + dijit.focus(this._firstFocusItem); + }, + + _onKey: function(/*Event*/ evt){ + // summary: keep keyboard focus in dialog; close dialog on escape key + var node = evt.target; + if (evt.keyCode == dojo.keys.TAB){ + this._getFocusItems(this.containerNode); + } + var singleFocusItem = (this._firstFocusItem == this._lastFocusItem); + if(evt.keyCode == dojo.keys.ESCAPE){ + this.onCancel(); + }else if(node == this._firstFocusItem && evt.shiftKey && evt.keyCode == dojo.keys.TAB){ + if(!singleFocusItem){ + dijit.focus(this._lastFocusItem); // send focus to last item in dialog + } + dojo.stopEvent(evt); + }else if(node == this._lastFocusItem && evt.keyCode == dojo.keys.TAB && !evt.shiftKey){ + if(!singleFocusItem){ + dijit.focus(this._firstFocusItem); // send focus to first item in dialog + } + dojo.stopEvent(evt); + }else if(evt.keyCode == dojo.keys.TAB){ + // we want the browser's default tab handling to move focus + // but we don't want the tab to propagate upwards + evt.stopPropagation(); + } + } + } +); + + +} |