Improve output: distinguish between failed assertions (failures) and unexpected exceptions (errors), and print a filtered stack trace for any exception.

This commit is contained in:
jeb228 2010-01-29 22:13:57 +00:00
commit 4f2e303079
1839 changed files with 235630 additions and 0 deletions

View file

@ -0,0 +1,98 @@
/*
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.html.AccordionPane");
dojo.require("dojo.widget.TitlePane");
dojo.widget.html.AccordionPane = function(){
dojo.widget.html.TitlePane.call(this);
this.widgetType = "AccordionPane";
this.open=false;
this.allowCollapse=true;
this.label="";
this.open=false;
this.labelNodeClass="";
this.containerNodeClass="";
}
dojo.inherits(dojo.widget.html.AccordionPane, dojo.widget.html.TitlePane);
dojo.lang.extend(dojo.widget.html.AccordionPane, {
postCreate: function() {
dojo.widget.html.AccordionPane.superclass.postCreate.call(this);
this.domNode.widgetType=this.widgetType;
this.setSizes();
dojo.html.addClass(this.labelNode, this.labelNodeClass);
dojo.html.disableSelection(this.labelNode);
dojo.html.addClass(this.containerNode, this.containerNodeClass);
},
collapse: function() {
//dojo.fx.html.wipeOut(this.containerNode,250);
//var anim = dojo.fx.html.wipe(this.containerNode, 1000, this.containerNode.offsetHeight, 0, null, true);
this.containerNode.style.display="none";
this.open=false;
},
expand: function() {
//dojo.fx.html.wipeIn(this.containerNode,250);
this.containerNode.style.display="block";
//var anim = dojo.fx.html.wipe(this.containerNode, 1000, 0, this.containerNode.scrollHeight, null, true);
this.open=true;
},
getCollapsedHeight: function() {
return dojo.style.getOuterHeight(this.labelNode)+1;
},
setSizes: function() {
var siblings = this.domNode.parentNode.childNodes;
var height=dojo.style.getInnerHeight(this.domNode.parentNode)-this.getCollapsedHeight();
this.siblingWidgets = [];
for (var x=0; x<siblings.length; x++) {
if (siblings[x].widgetType==this.widgetType) {
if (this.domNode != siblings[x]) {
var ap = dojo.widget.byNode(siblings[x]);
this.siblingWidgets.push(ap);
height -= ap.getCollapsedHeight();
}
}
}
for (var x=0; x<this.siblingWidgets.length; x++) {
dojo.style.setOuterHeight(this.siblingWidgets[x].containerNode,height);
}
dojo.style.setOuterHeight(this.containerNode,height);
},
onLabelClick: function() {
this.setSizes();
if (!this.open) {
for (var x=0; x<this.siblingWidgets.length;x++) {
if (this.siblingWidgets[x].open) {
this.siblingWidgets[x].collapse();
}
}
this.expand();
} else {
if (this.allowCollapse) {
this.collapse();
}
}
}
});
dojo.widget.tags.addParseTreeHandler("dojo:AccordionPane");

View file

@ -0,0 +1,25 @@
/*
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
*/
// this is a stub that will be removed in 0.4, see ../Button2.html for details
dojo.provide("dojo.widget.html.Button2");
dojo.widget.html.Button2 = function(){}
dojo.inherits(dojo.widget.html.Button2, dojo.widget.html.Button);
dojo.lang.extend(dojo.widget.html.Button2, { widgetType: "Button2" });
dojo.widget.html.DropDownButton2 = function(){}
dojo.inherits(dojo.widget.html.DropDownButton2, dojo.widget.html.DropDownButton);
dojo.lang.extend(dojo.widget.html.DropDownButton2, { widgetType: "DropDownButton2" });
dojo.widget.html.ComboButton2 = function(){}
dojo.inherits(dojo.widget.html.ComboButton2, dojo.widget.html.ComboButton);
dojo.lang.extend(dojo.widget.html.ComboButton2, { widgetType: "ComboButton2" });

View file

@ -0,0 +1,82 @@
/*
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.html.Checkbox");
dojo.require("dojo.widget.*");
dojo.require("dojo.event");
dojo.require("dojo.html");
dojo.widget.defineWidget(
"dojo.widget.html.Checkbox",
dojo.widget.HtmlWidget,
{
widgetType: "Checkbox",
templatePath: dojo.uri.dojoUri('src/widget/templates/HtmlCheckBox.html'),
srcOn: dojo.uri.dojoUri('src/widget/templates/check_on.gif'),
srcOff: dojo.uri.dojoUri('src/widget/templates/check_off.gif'),
srcDisabledOn: dojo.uri.dojoUri('src/widget/templates/check_disabled_on.gif'),
srcDisabledOff: dojo.uri.dojoUri('src/widget/templates/check_disabled_off.gif'),
srcHoverOn: dojo.uri.dojoUri('src/widget/templates/check_hover_on.gif'),
srcHoverOff: dojo.uri.dojoUri('src/widget/templates/check_hover_off.gif'),
imgSrc: null,
// parameters
disabled: "enabled",
name: "",
checked: false,
tabIndex: -1,
imgNode: null,
inputNode: null,
postMixInProperties: function(){
// set correct source for image before instantiating template
this._updateImgSrc();
},
onMouseUp: function(){
if(this.disabled == "enabled"){
this.checked = !this.checked;
this.inputNode.checked = this.checked;
this._updateImgSrc();
}
},
onMouseOver: function(){
this.hover=true;
this._updateImgSrc();
},
onMouseOut: function(){
this.hover=false;
this._updateImgSrc();
},
_updateImgSrc: function(){
if(this.disabled == "enabled"){
if(this.hover){
this.imgSrc = this.checked ? this.srcHoverOn : this.srcHoverOff;
}else{
this.imgSrc = this.checked ? this.srcOn : this.srcOff;
}
}else{
this.imgSrc = this.checked ? this.srcDisabledOn : this.srcDisabledOff;
}
if(this.imgNode){
this.imgNode.src = this.imgSrc;
}
}
}
);

View file

@ -0,0 +1,611 @@
/*
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.html.ComboBox");
dojo.require("dojo.widget.ComboBox");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.string");
dojo.require("dojo.widget.html.stabile");
dojo.widget.defineWidget(
"dojo.widget.html.ComboBox",
[dojo.widget.HtmlWidget, dojo.widget.ComboBox],
{
autoComplete: true,
formInputName: "",
name: "", // clone in the name from the DOM node
textInputNode: null,
comboBoxValue: null,
comboBoxSelectionValue: null,
optionsListWrapper: null,
optionsListNode: null,
downArrowNode: null,
cbTableNode: null,
searchTimer: null,
searchDelay: 100,
dataUrl: "",
fadeTime: 200,
// maxListLength limits list to X visible rows, scroll on rest
maxListLength: 8,
// mode can also be "remote" for JSON-returning live search or "html" for
// dumber live search
mode: "local",
selectedResult: null,
_highlighted_option: null,
_prev_key_backspace: false,
_prev_key_esc: false,
_result_list_open: false,
_gotFocus: false,
_mouseover_list: false,
dataProviderClass: "dojo.widget.ComboBoxDataProvider",
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlComboBox.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlComboBox.css"),
setValue: function(value) {
this.comboBoxValue.value = value;
if (this.textInputNode.value != value) { // prevent mucking up of selection
this.textInputNode.value = value;
}
dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
},
getValue: function() {
return this.comboBoxValue.value;
},
getState: function() {
return {value: this.getValue()};
},
setState: function(state) {
this.setValue(state.value);
},
getCaretPos: function(element){
// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
if(dojo.lang.isNumber(element.selectionStart)){
// FIXME: this is totally borked on Moz < 1.3. Any recourse?
return element.selectionStart;
}else if(dojo.render.html.ie){
// in the case of a mouse click in a popup being handled,
// then the document.selection is not the textarea, but the popup
// var r = document.selection.createRange();
// hack to get IE 6 to play nice. What a POS browser.
var tr = document.selection.createRange().duplicate();
var ntr = element.createTextRange();
tr.move("character",0);
ntr.move("character",0);
try {
// If control doesnt have focus, you get an exception.
// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
// There appears to be no workaround for this - googled for quite a while.
ntr.setEndPoint("EndToEnd", tr);
return String(ntr.text).replace(/\r/g,"").length;
} catch (e) {
return 0; // If focus has shifted, 0 is fine for caret pos.
}
}
},
setCaretPos: function(element, location){
location = parseInt(location);
this.setSelectedRange(element, location, location);
},
setSelectedRange: function(element, start, end){
if(!end){ end = element.value.length; } // NOTE: Strange - should be able to put caret at start of text?
// Mozilla
// parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130
if(element.setSelectionRange){
element.focus();
element.setSelectionRange(start, end);
}else if(element.createTextRange){ // IE
var range = element.createTextRange();
with(range){
collapse(true);
moveEnd('character', end);
moveStart('character', start);
select();
}
}else{ //otherwise try the event-creation hack (our own invention)
// do we need these?
element.value = element.value;
element.blur();
element.focus();
// figure out how far back to go
var dist = parseInt(element.value.length)-end;
var tchar = String.fromCharCode(37);
var tcc = tchar.charCodeAt(0);
for(var x = 0; x < dist; x++){
var te = document.createEvent("KeyEvents");
te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);
element.dispatchEvent(te);
}
}
},
// does the keyboard related stuff
_handleKeyEvents: function(evt){
if(evt.ctrlKey || evt.altKey){ return; }
// reset these
this._prev_key_backspace = false;
this._prev_key_esc = false;
var k = dojo.event.browser.keys;
var doSearch = true;
// mozilla quirk
// space has no keyCode in mozilla
var keyCode = evt.keyCode;
if(keyCode==0 && evt.charCode==k.KEY_SPACE){
keyCode = k.KEY_SPACE;
}
switch(keyCode){
case k.KEY_DOWN_ARROW:
if(!this._result_list_open){
this.startSearchFromInput();
}
this.highlightNextOption();
dojo.event.browser.stopEvent(evt);
return;
case k.KEY_UP_ARROW:
this.highlightPrevOption();
dojo.event.browser.stopEvent(evt);
return;
case k.KEY_ENTER:
// prevent submitting form if we press enter with list open
if(this._result_list_open){
dojo.event.browser.stopEvent(evt);
}
// fallthrough
case k.KEY_TAB:
// using linux alike tab for autocomplete
if(!this.autoComplete && this._result_list_open && this._highlighted_option){
dojo.event.browser.stopEvent(evt);
this.selectOption({ 'target': this._highlighted_option, 'noHide': true });
// put caret last
this.setSelectedRange(this.textInputNode, this.textInputNode.value.length, null);
}else{
this.selectOption();
return;
}
break;
case k.KEY_SPACE:
if(this._result_list_open && this._highlighted_option){
dojo.event.browser.stopEvent(evt);
this.selectOption();
this.hideResultList();
return;
}
break;
case k.KEY_ESCAPE:
this.hideResultList();
this._prev_key_esc = true;
return;
case k.KEY_BACKSPACE:
this._prev_key_backspace = true;
if(!this.textInputNode.value.length){
this.setAllValues("", "");
this.hideResultList();
doSearch = false;
}
break;
case k.KEY_RIGHT_ARROW: // fall through
case k.KEY_LEFT_ARROW: // fall through
case k.KEY_SHIFT:
doSearch = false;
break;
default:// non char keys (F1-F12 etc..) shouldn't open list
if(evt.charCode==0){
doSearch = false;
}
}
if(this.searchTimer){
clearTimeout(this.searchTimer);
}
if(doSearch){
// if we have gotten this far we dont want to keep our highlight
this.blurOptionNode();
// need to wait a tad before start search so that the event bubbles through DOM and we have value visible
this.searchTimer = setTimeout(dojo.lang.hitch(this, this.startSearchFromInput), this.searchDelay);
}
},
onKeyDown: function(evt){
// IE needs to stop keyDown others need to stop keyPress
if(!document.createEvent){ // only IE
this._handleKeyEvents(evt);
}
// FIXME: What about ESC ??
},
onKeyPress: function(evt){
if(document.createEvent){ // never IE
this._handleKeyEvents(evt);
}
},
onKeyUp: function(evt){
this.setValue(this.textInputNode.value);
},
setSelectedValue: function(value){
// FIXME, not sure what to do here!
this.comboBoxSelectionValue.value = value;
},
setAllValues: function(value1, value2){
this.setValue(value1);
this.setSelectedValue(value2);
},
// opera, khtml, safari doesnt support node.scrollIntoView(), workaround
scrollIntoView: function(){
var node = this._highlighted_option;
var parent = this.optionsListNode;
// don't rely on that node.scrollIntoView works just because the function is there
// it doesnt work in Konqueror or Opera even though the function is there and probably
// not safari either
// dont like browser sniffs implementations but sometimes you have to use it
if(dojo.render.html.ie || dojo.render.html.mozilla){
// IE, mozilla
node.scrollIntoView(false);
}else{
var parentBottom = parent.scrollTop + dojo.style.getInnerHeight(parent);
var nodeBottom = node.offsetTop + dojo.style.getOuterHeight(node);
if(parentBottom < nodeBottom){
parent.scrollTop += (nodeBottom - parentBottom);
}else if(parent.scrollTop > node.offsetTop){
parent.scrollTop -= (parent.scrollTop - node.offsetTop);
}
}
},
// does the actual highlight
focusOptionNode: function(node){
if(this._highlighted_option != node){
this.blurOptionNode();
this._highlighted_option = node;
dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
}
},
// removes highlight on highlighted
blurOptionNode: function(){
if(this._highlighted_option){
dojo.html.removeClass(this._highlighted_option, "dojoComboBoxItemHighlight");
this._highlighted_option = null;
}
},
highlightNextOption: function(){
if((!this._highlighted_option) || !this._highlighted_option.parentNode){
this.focusOptionNode(this.optionsListNode.firstChild);
}else if(this._highlighted_option.nextSibling){
this.focusOptionNode(this._highlighted_option.nextSibling);
}
this.scrollIntoView();
},
highlightPrevOption: function(){
if(this._highlighted_option && this._highlighted_option.previousSibling){
this.focusOptionNode(this._highlighted_option.previousSibling);
}else{
this._highlighted_option = null;
this.hideResultList();
return;
}
this.scrollIntoView();
},
itemMouseOver: function(evt){
this.focusOptionNode(evt.target);
dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
},
itemMouseOut: function(evt){
this.blurOptionNode();
},
fillInTemplate: function(args, frag){
// FIXME: need to get/assign DOM node names for form participation here.
this.comboBoxValue.name = this.name;
this.comboBoxSelectionValue.name = this.name+"_selected";
var source = this.getFragNodeRef(frag);
dojo.html.copyStyle(this.domNode, source);
var dpClass;
if(this.mode == "remote"){
dpClass = dojo.widget.incrementalComboBoxDataProvider;
}else if(typeof this.dataProviderClass == "string"){
dpClass = dojo.evalObjPath(this.dataProviderClass)
}else{
dpClass = this.dataProviderClass;
}
this.dataProvider = new dpClass();
this.dataProvider.init(this, this.getFragNodeRef(frag));
// Prevent IE bleed-through problem
this.optionsIframe = new dojo.html.BackgroundIframe(this.optionsListWrapper);
this.optionsIframe.size([0,0,0,0]);
},
focus: function(){
// summary
// set focus to input node from code
this.tryFocus();
},
openResultList: function(results){
this.clearResultList();
if(!results.length){
this.hideResultList();
}
if( (this.autoComplete)&&
(results.length)&&
(!this._prev_key_backspace)&&
(this.textInputNode.value.length > 0)){
var cpos = this.getCaretPos(this.textInputNode);
// only try to extend if we added the last character at the end of the input
if((cpos+1) > this.textInputNode.value.length){
// only add to input node as we would overwrite Capitalisation of chars
this.textInputNode.value += results[0][0].substr(cpos);
// build a new range that has the distance from the earlier
// caret position to the end of the first string selected
this.setSelectedRange(this.textInputNode, cpos, this.textInputNode.value.length);
}
}
var even = true;
while(results.length){
var tr = results.shift();
if(tr){
var td = document.createElement("div");
td.appendChild(document.createTextNode(tr[0]));
td.setAttribute("resultName", tr[0]);
td.setAttribute("resultValue", tr[1]);
td.className = "dojoComboBoxItem "+((even) ? "dojoComboBoxItemEven" : "dojoComboBoxItemOdd");
even = (!even);
this.optionsListNode.appendChild(td);
dojo.event.connect(td, "onmouseover", this, "itemMouseOver");
dojo.event.connect(td, "onmouseout", this, "itemMouseOut");
}
}
// show our list (only if we have content, else nothing)
this.showResultList();
},
onFocusInput: function(){
this._hasFocus = true;
},
onBlurInput: function(){
this._hasFocus = false;
this._handleBlurTimer(true, 500);
},
// collect all blur timers issues here
_handleBlurTimer: function(/*Boolean*/clear, /*Number*/ millisec){
if(this.blurTimer && (clear || millisec)){
clearTimeout(this.blurTimer);
}
if(millisec){ // we ignore that zero is false and never sets as that never happens in this widget
this.blurTimer = dojo.lang.setTimeout(this, "checkBlurred", millisec);
}
},
// these 2 are needed in IE and Safari as inputTextNode loses focus when scrolling optionslist
_onMouseOver: function(evt){
if(!this._mouseover_list){
this._handleBlurTimer(true, 0);
this._mouseover_list = true;
}
},
_onMouseOut:function(evt){
var relTarget = evt.relatedTarget;
if(!relTarget || relTarget.parentNode!=this.optionsListNode){
this._mouseover_list = false;
this._handleBlurTimer(true, 100);
this.tryFocus();
}
},
_isInputEqualToResult: function(result){
input = this.textInputNode.value;
if(!this.dataProvider.caseSensitive){
input = input.toLowerCase();
result = result.toLowerCase();
}
return (input == result);
},
_isValidOption: function(){
tgt = dojo.dom.firstElement(this.optionsListNode);
isValidOption = false;
while(!isValidOption && tgt){
if(this._isInputEqualToResult(tgt.getAttribute("resultName"))){
isValidOption = true;
}else{
tgt = dojo.dom.nextElement(tgt);
}
}
return isValidOption;
},
checkBlurred: function(){
if(!this._hasFocus && !this._mouseover_list){
this.hideResultList();
// clear the list if the user empties field and moves away.
if(!this.textInputNode.value.length){
this.setAllValues("", "");
return;
}
isValidOption = this._isValidOption();
// enforce selection from option list
if(this.forceValidOption && !isValidOption){
this.setAllValues("", "");
return;
}
if(!isValidOption){// clear
this.setSelectedValue("");
}
}
},
sizeBackgroundIframe: function(){
var w = dojo.style.getOuterWidth(this.optionsListNode);
var h = dojo.style.getOuterHeight(this.optionsListNode);
if( w==0 || h==0 ){
// need more time to calculate size
dojo.lang.setTimeout(this, "sizeBackgroundIframe", 100);
return;
}
if(this._result_list_open){
this.optionsIframe.size([0,0,w,h]);
}
},
selectOption: function(evt){
var tgt = null;
if(!evt){
evt = { target: this._highlighted_option };
}
if(!dojo.dom.isDescendantOf(evt.target, this.optionsListNode)){
// handle autocompletion where the the user has hit ENTER or TAB
// if the input is empty do nothing
if(!this.textInputNode.value.length){
return;
}
tgt = dojo.dom.firstElement(this.optionsListNode);
// user has input value not in option list
if(!tgt || !this._isInputEqualToResult(tgt.getAttribute("resultName"))){
return;
}
// otherwise the user has accepted the autocompleted value
}else{
tgt = evt.target;
}
while((tgt.nodeType!=1)||(!tgt.getAttribute("resultName"))){
tgt = tgt.parentNode;
if(tgt === document.body){
return false;
}
}
this.textInputNode.value = tgt.getAttribute("resultName");
this.selectedResult = [tgt.getAttribute("resultName"), tgt.getAttribute("resultValue")];
this.setAllValues(tgt.getAttribute("resultName"), tgt.getAttribute("resultValue"));
if(!evt.noHide){
this.hideResultList();
this.setSelectedRange(this.textInputNode, 0, null);
}
this.tryFocus();
},
clearResultList: function(){
var oln = this.optionsListNode;
while(oln.firstChild){
dojo.event.disconnect(oln.firstChild, "onmouseover", this, "itemMouseOver");
dojo.event.disconnect(oln.firstChild, "onmouseout", this, "itemMouseOut");
oln.removeChild(oln.firstChild);
}
},
hideResultList: function(){
if(this._result_list_open){
this._result_list_open = false;
this.optionsIframe.size([0,0,0,0]);
dojo.lfx.fadeHide(this.optionsListNode, this.fadeTime).play();
}
},
showResultList: function(){
// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time
var childs = this.optionsListNode.childNodes;
if(childs.length){
var visibleCount = this.maxListLength;
if(childs.length < visibleCount){
visibleCount = childs.length;
}
with(this.optionsListNode.style){
display = "";
height = ((visibleCount) ? (dojo.style.getOuterHeight(childs[0]) * visibleCount) : 0)+"px";
width = dojo.html.getOuterWidth(this.cbTableNode)-2+"px";
}
// only fadein once (flicker)
if(!this._result_list_open){
dojo.html.setOpacity(this.optionsListNode, 0);
dojo.lfx.fadeIn(this.optionsListNode, this.fadeTime).play();
}
// prevent IE bleed through
this._iframeTimer = dojo.lang.setTimeout(this, "sizeBackgroundIframe", 200);
this._result_list_open = true;
}else{
this.hideResultList();
}
},
handleArrowClick: function(){
this._handleBlurTimer(true, 0);
this.tryFocus();
if(this._result_list_open){
this.hideResultList();
}else{
this.startSearchFromInput();
}
},
tryFocus: function(){
try {
this.textInputNode.focus();
} catch (e) {
// element isn't focusable if disabled, or not visible etc - not easy to test for.
};
},
startSearchFromInput: function(){
this.startSearch(this.textInputNode.value);
},
postCreate: function(){
dojo.event.connect(this, "startSearch", this.dataProvider, "startSearch");
dojo.event.connect(this.dataProvider, "provideSearchResults", this, "openResultList");
dojo.event.connect(this.textInputNode, "onblur", this, "onBlurInput");
dojo.event.connect(this.textInputNode, "onfocus", this, "onFocusInput");
var s = dojo.widget.html.stabile.getState(this.widgetId);
if (s) {
this.setState(s);
}
}
}
);

View file

@ -0,0 +1,566 @@
/*
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.html.ContentPane");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.string");
dojo.require("dojo.string.extras");
dojo.require("dojo.style");
dojo.widget.html.ContentPane = function(){
this._onLoadStack = [];
this._onUnLoadStack = [];
dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.ContentPane, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.ContentPane, {
widgetType: "ContentPane",
isContainer: true,
// remote loading options
adjustPaths: true,
href: "",
extractContent: true,
parseContent: true,
cacheContent: true,
preload: false, // force load of data even if pane is hidden
refreshOnShow: false,
handler: "", // generate pane content from a java function
executeScripts: false, // if true scripts in content will be evaled after content is set and parsed
scriptScope: null, // scopeContainer for downloaded scripts
// If the user want a global in the remote script he/she just omitts the var
// examples:
//--------------------------
// these gets collected by scriptScope and is reached by dojo.widget.byId('..').scriptScope.myCustomproperty
// this.myString = "dojo is a great javascript toolkit!";
//
// this.alertMyString = function(){
// alert(myString);
// }
// -------------------------
// these go into the global namespace (window) notice lack of var, equiv to window.myString
// myString = "dojo is a javascript toolkit!";
//
// alertMyString = function(){
// alert(myString);
// }
// private
_remoteStyles: null, // array of stylenodes inserted to document head
// by remote content, used when we clean up for new content
_callOnUnLoad: false, // used by setContent and _handleDefults, makes sure onUnLoad is only called once
postCreate: function(args, frag, parentComp){
if ( this.handler != "" ){
this.setHandler(this.handler);
}
if(this.isShowing()||this.preload){ this.loadContents(); }
},
show: function(){
// if refreshOnShow is true, reload the contents every time; otherwise, load only the first time
if(this.refreshOnShow){
this.refresh();
}else{
this.loadContents();
}
dojo.widget.html.ContentPane.superclass.show.call(this);
},
refresh: function(){
this.isLoaded=false;
this.loadContents();
},
loadContents: function() {
if ( this.isLoaded ){
return;
}
this.isLoaded=true;
if ( dojo.lang.isFunction(this.handler)) {
this._runHandler();
} else if ( this.href != "" ) {
this._downloadExternalContent(this.href, this.cacheContent);
}
},
setUrl: function(/*String*/ url) {
// summary:
// Reset the (external defined) content of this pane and replace with new url
this.href = url;
this.isLoaded = false;
if ( this.preload || this.isShowing() ){
this.loadContents();
}
},
_downloadExternalContent: function(url, useCache) {
this._handleDefaults("Loading...", "onDownloadStart");
var self = this;
dojo.io.bind({
url: url,
useCache: useCache,
preventCache: !useCache,
mimetype: "text/html",
handler: function(type, data, e) {
if(type == "load") {
self.onDownloadEnd.call(self, url, data);
} else {
// works best when from a live server instead of from file system
self._handleDefaults.call(self, "Error loading '" + url + "' (" + e.status + " "+ e.statusText + ")", "onDownloadError");
self.onLoad();
}
}
});
},
// called when setContent is finished
onLoad: function(e){
this._runStack("_onLoadStack");
},
// called before old content is cleared
onUnLoad: function(e){
this._runStack("_onUnLoadStack");
this.scriptScope = null;
},
_runStack: function(stName){
var st = this[stName]; var err = "";
for(var i = 0;i < st.length; i++){
try{
st[i].call(this.scriptScope);
}catch(e){
err += "\n"+st[i]+" failed: "+e.description;
}
}
this[stName] = [];
if(err.length){
var name = (stName== "_onLoadStack") ? "addOnLoad" : "addOnUnLoad";
this._handleDefaults(name+" failure\n "+err, "onExecError", true);
}
},
addOnLoad: function(obj, func){
// summary
// same as to dojo.addOnLoad but does not take "function_name" as a string
this._pushOnStack(this._onLoadStack, obj, func);
},
addOnUnLoad: function(obj, func){
// summary
// same as to dojo.addUnOnLoad but does not take "function_name" as a string
this._pushOnStack(this._onUnLoadStack, obj, func);
},
_pushOnStack: function(stack, obj, func){
if(typeof func == 'undefined') {
stack.push(obj);
}else{
stack.push(function(){ obj[func](); });
}
},
destroy: function(){
// make sure we call onUnLoad
this.onUnLoad();
dojo.widget.html.ContentPane.superclass.destroy.call(this);
},
// called when content script eval error or Java error occurs, preventDefault-able
onExecError: function(e){ /*stub*/ },
// called on DOM faults, require fault etc in content, preventDefault-able
onContentError: function(e){ /*stub*/ },
// called when download error occurs, preventDefault-able
onDownloadError: function(e){ /*stub*/ },
// called before download starts, preventDefault-able
onDownloadStart: function(e){ /*stub*/ },
// called when download is finished
onDownloadEnd: function(url, data){
data = this.splitAndFixPaths(data, url);
this.setContent(data);
},
// usefull if user wants to prevent default behaviour ie: _setContent("Error...")
_handleDefaults: function(e, handler, useAlert){
if(!handler){ handler = "onContentError"; }
if(dojo.lang.isString(e)){
e = {
"text": e,
"toString": function(){ return this.text; }
}
}
if(typeof e.returnValue != "boolean"){
e.returnValue = true;
}
if(typeof e.preventDefault != "function"){
e.preventDefault = function(){
this.returnValue = false;
}
}
// call our handler
this[handler](e);
if(e.returnValue){
if(useAlert){
alert(e.toString());
}else{
if(this._callOnUnLoad){
this.onUnLoad(); // makes sure scripts can clean up after themselves, before we setContent
}
this._callOnUnLoad = false; // makes sure we dont try to call onUnLoad again on this event,
// ie onUnLoad before 'Loading...' but not before clearing 'Loading...'
this._setContent(e.toString());
}
}
},
splitAndFixPaths: function(/*String*/s, /*dojo.uri.Uri?*/url){
// summary:
// fixes all remote paths in (hopefully) all cases for example images, remote scripts, links etc.
// splits up content in different pieces, scripts, title, style, link and whats left becomes .xml
if(!url) { url = "./"; } // point to this page if not set
if(!s) { return ""; }
// fix up paths in data
var titles = []; var scripts = []; var linkStyles = [];
var styles = []; var remoteScripts = []; var requires = [];
// khtml is much more picky about dom faults, you can't for example attach a style node under body of document
// must go into head, as does a title node, so we need to cut out those tags
// cut out title tags
var match = [];
while(match){
match = s.match(/<title[^>]*>([\s\S]*?)<\/title>/i); // can't match with dot as that
if(!match){ break;} //doesnt match newline in js
titles.push(match[1]);
s = s.replace(/<title[^>]*>[\s\S]*?<\/title>/i, "");
}
// cut out <style> url(...) </style>, as that bails out in khtml
var match = [];
while(match){
match = s.match(/<style[^>]*>([\s\S]*?)<\/style>/i);
if(!match){ break; }
styles.push(dojo.style.fixPathsInCssText(match[1], url));
s = s.replace(/<style[^>]*?>[\s\S]*?<\/style>/i, "");
}
// attributepaths one tag can have multiple paths example:
// <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
// strip out the tag and run fix on that.
// this guarantees that we won't run replace another tag's attribute + it was easier do
var pos = 0; var pos2 = 0; var stop = 0 ;var str = ""; var fixedPath = "";
var attr = []; var fix = ""; var tagFix = ""; var tag = ""; var regex = "";
while(pos>-1){
pos = s.search(/<[a-z][a-z0-9]*[^>]*\s(?:(?:src|href|style)=[^>])+[^>]*>/i);
if(pos==-1){ break; }
str += s.substring(0, pos);
s = s.substring(pos, s.length);
tag = s.match(/^<[a-z][a-z0-9]*[^>]*>/i)[0];
s = s.substring(tag.length, s.length);
// loop through attributes
pos2 = 0; tagFix = ""; fix = ""; regex = ""; var regexlen = 0;
while(pos2!=-1){
// slices up before next attribute check, values from previous loop
tagFix += tag.substring(0, pos2) + fix;
tag = tag.substring(pos2+regexlen, tag.length);
// fix next attribute or bail out when done
// hopefully this charclass covers most urls
attr = tag.match(/ (src|href|style)=(['"]?)([\w()\[\]\/.,\\'"-:;#=&?\s@]+?)\2/i);
if(!attr){ break; }
switch(attr[1].toLowerCase()){
case "src":// falltrough
case "href":
// this hopefully covers most common protocols
if(attr[3].search(/^(?:[#]|(?:(?:https?|ftps?|file|javascript|mailto|news):))/)==-1){
fixedPath = (new dojo.uri.Uri(url, attr[3]).toString());
} else {
pos2 = pos2 + attr[3].length;
continue;
}
break;
case "style":// style
fixedPath = dojo.style.fixPathsInCssText(attr[3], url);
break;
default:
pos2 = pos2 + attr[3].length;
continue;
}
regex = " " + attr[1] + "=" + attr[2] + attr[3] + attr[2];
regexlen = regex.length;
fix = " " + attr[1] + "=" + attr[2] + fixedPath + attr[2];
pos2 = tag.search(new RegExp(dojo.string.escapeRegExp(regex)));
}
str += tagFix + tag;
pos = 0; // reset for next mainloop
}
s = str+s;
// cut out all script tags, push them into scripts array
match = []; var tmp = [];
while(match){
match = s.match(/<script([^>]*)>([\s\S]*?)<\/script>/i);
if(!match){ break; }
if(match[1]){
attr = match[1].match(/src=(['"]?)([^"']*)\1/i);
if(attr){
// remove a dojo.js or dojo.js.uncompressed.js from remoteScripts
// we declare all files with dojo.js as bad, regardless of folder
var tmp = attr[2].search(/.*(\bdojo\b(?:\.uncompressed)?\.js)$/);
if(tmp > -1){
dojo.debug("Security note! inhibit:"+attr[2]+" from beeing loaded again.");
}else{
remoteScripts.push(attr[2]);
}
}
}
if(match[2]){
// strip out all djConfig variables from script tags nodeValue
// this is ABSOLUTLY needed as reinitialize djConfig after dojo is initialised
// makes a dissaster greater than Titanic, update remove writeIncludes() to
var sc = match[2].replace(/(?:var )?\bdjConfig\b(?:[\s]*=[\s]*\{[^}]+\}|\.[\w]*[\s]*=[\s]*[^;\n]*)?;?|dojo\.hostenv\.writeIncludes\(\s*\);?/g, "");
if(!sc){ continue; }
// cut out all dojo.require (...) calls, if we have execute
// scripts false widgets dont get there require calls
// does suck out possible widgetpackage registration as well
tmp = [];
while(tmp && requires.length<100){
tmp = sc.match(/dojo\.(?:(?:require(?:After)?(?:If)?)|(?:widget\.(?:manager\.)?registerWidgetPackage)|(?:(?:hostenv\.)?setModulePrefix))\((['"]).*?\1\)\s*;?/);
if(!tmp){ break;}
requires.push(tmp[0]);
sc = sc.replace(tmp[0], "");
}
scripts.push(sc);
}
s = s.replace(/<script[^>]*>[\s\S]*?<\/script>/i, "");
}
// scan for scriptScope in html eventHandlers and replace with link to this pane
if(this.executeScripts){
var regex = /(<[a-zA-Z][a-zA-Z0-9]*\s[^>]*\S=(['"])[^>]*[^\.\]])scriptScope([^>]*>)/;
var pos = 0;var str = "";match = [];var cit = "";
while(pos > -1){
pos = s.search(regex);
if(pos > -1){
cit = ((RegExp.$2=="'") ? '"': "'");
str += s.substring(0, pos);
s = s.substr(pos).replace(regex, "$1dojo.widget.byId("+ cit + this.widgetId + cit + ").scriptScope$3");
}
}
s = str + s;
}
// cut out all <link rel="stylesheet" href="..">
match = [];
while(match){
match = s.match(/<link ([^>]*rel=['"]?stylesheet['"]?[^>]*)>/i);
if(!match){ break; }
attr = match[1].match(/href=(['"]?)([^'">]*)\1/i);
if(attr){
linkStyles.push(attr[2]);
}
s = s.replace(new RegExp(match[0]), "");
}
return {"xml": s, // Object
"styles": styles,
"linkStyles": linkStyles,
"titles": titles,
"requires": requires,
"scripts": scripts,
"remoteScripts": remoteScripts,
"url": url};
},
_setContent: function(/*String*/ xml){
// summary:
// private internal function without path regExpCheck and no onLoad calls aftervards
// remove old children from current content
this.destroyChildren();
// remove old stylenodes from HEAD
if(this._remoteStyles){
for(var i = 0; i < this._remoteStyles.length; i++){
if(this._remoteStyles[i] && this._remoteStyles.parentNode){
this._remoteStyles[i].parentNode.removeChild(this._remoteStyles[i]);
}
}
this._remoteStyles = null;
}
var node = this.containerNode || this.domNode;
try{
if(typeof xml != "string"){
node.innerHTML = "";
node.appendChild(xml);
}else{
node.innerHTML = xml;
}
} catch(e){
e = "Could'nt load content:"+e;
this._handleDefaults(e, "onContentError");
}
},
setContent: function(/*String*/ data){
// summary:
// Destroys old content and setting new content, and possibly initialize any widgets within 'data'
if(this._callOnUnLoad){ // this tells a remote script clean up after itself
this.onUnLoad();
}
this._callOnUnLoad = true;
if(!data || dojo.dom.isNode(data)){
// if we do a clean using setContent(""); or setContent(#node) bypass all parseing, extractContent etc
this._setContent(data);
this.onResized();
this.onLoad();
}else{
// need to run splitAndFixPaths? ie. manually setting content
if((!data.xml)&&(this.adjustPaths)){
data = this.splitAndFixPaths(data);
}
if(this.extractContent) {
var matches = data.xml.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
if(matches) { data.xml = matches[1]; }
}
// insert styleNodes, from <style>....
for(var i = 0; i < data.styles.length; i++){
if(i==0){
this._remoteStyles = [];
}
this._remoteStyles.push(dojo.style.insertCssText(data.styles[i]));
}
// insert styleNodes, from <link href="...">
for(var i = 0; i < data.linkStyles.length; i++){
if(i==0){
this._remoteStyles = [];
}
this._remoteStyles.push(dojo.style.insertCssFile(data.linkStyles[i]));
}
this._setContent(data.xml);
if(this.parseContent){
for(var i = 0; i < data.requires.length; i++){
try{
eval(data.requires[i]);
} catch(e){
this._handleDefaults(e, "onContentError", true);
}
}
}
// need to allow async load, Xdomain uses it
// is inline function because we cant send args to addOnLoad function
var _self = this;
function asyncParse(){
if(_self.executeScripts){
_self._executeScripts(data);
}
if(_self.parseContent){
var node = _self.containerNode || _self.domNode;
var parser = new dojo.xml.Parse();
var frag = parser.parseElement(node, null, true);
// createSubComponents not createComponents because frag has already been created
dojo.widget.getParser().createSubComponents(frag, _self);
}
_self.onResized();
_self.onLoad();
}
// try as long as possible to make setContent sync call
if(dojo.hostenv.isXDomain && data.requires.length){
dojo.addOnLoad(asyncParse);
}else{
asyncParse();
}
}
},
// Generate pane content from given java function
setHandler: function(handler) {
var fcn = dojo.lang.isFunction(handler) ? handler : window[handler];
if(!dojo.lang.isFunction(fcn)) {
// FIXME: needs testing! somebody with java knowledge needs to try this
this._handleDefaults("Unable to set handler, '" + handler + "' not a function.", "onExecError", true);
return;
}
this.handler = function() {
return fcn.apply(this, arguments);
}
},
_runHandler: function() {
if(dojo.lang.isFunction(this.handler)) {
this.handler(this, this.domNode);
return false;
}
return true;
},
_executeScripts: function(data) {
// do remoteScripts first
var self = this;
for(var i = 0; i < data.remoteScripts.length; i++){
dojo.io.bind({
"url": data.remoteScripts[i],
"useCash": this.cacheContent,
"load": function(type, scriptStr){
dojo.lang.hitch(self, data.scripts.push(scriptStr));
},
"error": function(type, error){
self._handleDefaults.call(self, type + " downloading remote script", "onExecError", true);
},
"mimetype": "text/plain",
"sync": true
});
}
var scripts = "";
for(var i = 0; i < data.scripts.length; i++){
scripts += data.scripts[i];
}
try{
// initialize a new anonymous container for our script, dont make it part of this widgets scope chain
// instead send in a variable that points to this widget, usefull to connect events to onLoad, onUnLoad etc..
this.scriptScope = null;
this.scriptScope = new (new Function('_container_', scripts+'; return this;'))(self);
}catch(e){
this._handleDefaults("Error running scripts from content:\n"+e, "onExecError", true);
}
}
});
dojo.widget.tags.addParseTreeHandler("dojo:ContentPane");

View file

@ -0,0 +1,166 @@
/*
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.html.ContextMenu");
dojo.require("dojo.html");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.ContextMenu");
dojo.require("dojo.lang");
dojo.widget.html.ContextMenu = function(){
dojo.widget.ContextMenu.call(this);
dojo.widget.HtmlWidget.call(this);
this.isShowing = 0;
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlContextMenuTemplate.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/Menu.css");
this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it only responds to those nodes
// default event detection method
var eventType = "oncontextmenu";
var doc = document.documentElement || document.body;
var _blockHide = false;
this.fillInTemplate = function(args, frag){
var func = "onOpen";
var attached = false;
// connect with rightclick if oncontextmenu is not around
// NOTE: It would be very nice to have a dojo.event.browser.supportsEvent here
// NOTE: Opera does not have rightclick events, it is listed here only because
// it bails out when connecting with oncontextmenu event
if((dojo.render.html.khtml && !dojo.render.html.safari) || (dojo.render.html.opera)){
eventType = "onmousedown";
func = "_checkRightClick";
}
// attach event listeners to our selected nodes
for(var i=0; i<this.targetNodeIds.length; i++){
var node = document.getElementById(this.targetNodeIds[i]);
if(node){
dojo.event.connect(node, eventType, this, func);
attached = true;
}else{
// remove this nodeId
dojo.debug("Couldent find "+this.targetNodeIds[i]+", cant do ContextMenu on this node");
this.targetNodeIds.splice(i,1);
}
}
// if we got attached to a node, hide on all non node contextevents
if(attached){ func = "_canHide"; }
dojo.event.connect(doc, eventType, this, func);
}
this.onOpen = function(evt){
// if (this.isShowing){ this.onHide(evt); } // propably not needed
this.isShowing = 1;
// if I do this, I cant preventDefault in khtml
//evt = dojo.event.browser.fixEvent(evt);
// stop default contextmenu, needed in khtml
if (evt.preventDefault){ evt.preventDefault(); }
// need to light up this one before we check width and height
this.domNode.style.left = "-9999px";
this.domNode.style.top = "-9999px";
this.domNode.style.display = "block";
// calculate if menu is going to apear within window
// or if its partially out of visable area
with(dojo.html){
var menuW = getInnerWidth(this.domNode);
var menuH = getInnerHeight(this.domNode);
var viewport = getViewportSize();
var scrolloffset = getScrollOffset();
}
var minX = viewport[0];
var minY = viewport[1];
var maxX = (viewport[0] + scrolloffset[0]) - menuW;
var maxY = (viewport[1] + scrolloffset[1]) - menuH;
var posX = evt.clientX + scrolloffset[0];
var posY = evt.clientY + scrolloffset[1];
if (posX > maxX){ posX = posX - menuW; }
if (posY > maxY){ posY = posY - menuH; }
this.domNode.style.left = posX + "px";
this.domNode.style.top = posY + "px";
// block the onclick that follows this particular right click
// not if the eventtrigger is documentElement and always when
// we use onmousedown hack
_blockHide = (evt.currentTarget!=doc || eventType=='onmousedown');
//return false; // we propably doesnt need to return false as we dont stop the event as we did before
}
/*
* _canHide is meant to block the onHide call that follows the event that triggered
* onOpen. This is (hopefully) faster that event.connect and event.disconnect every
* time the code executes and it makes connecting with onmousedown event possible
* and we dont have to stop the event from bubbling further.
*
* this code is moved into a separete function because it makes it possible for the
* user to connect to a onHide event, if anyone would like that.
*/
this._canHide = function(evt){
// block the onclick that follows the same event that turn on contextmenu
if(_blockHide){
// the onclick check is needed to prevent displaying multiple
// menus when we have 2 or more contextmenus loaded and are using
// the onmousedown hack
if(evt.type=='click' || eventType=='oncontextmenu'){
_blockHide = false;
return;
}else{
return;
}
}
this.onHide(evt);
}
this.onHide = function(evt){
// FIXME: use whatever we use to do more general style setting?
this.domNode.style.display = "none";
//dojo.event.disconnect(doc, "onclick", this, "onHide");
this.isShowing = 0;
}
// callback for rightclicks, needed for browsers that doesnt implement oncontextmenu, konqueror and more?
this._checkRightClick = function(evt){
// for some reason konq comes here even when we are not clicking on the attached nodes
// added check for targetnode
if (evt.button==2 && (this.targetNodeIds.length==0 || (evt.currentTarget.id!="" && dojo.lang.inArray(this.targetNodeIds, evt.currentTarget.id)))){
return this.onOpen(evt);
}
}
dojo.event.connect(doc, "onclick", this, "_canHide");
}
dojo.inherits(dojo.widget.html.ContextMenu, dojo.widget.HtmlWidget);

View file

@ -0,0 +1,346 @@
/*
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.html.DatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.DatePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.date");
/*
Some assumptions:
- I'm planning on always showing 42 days at a time, and we can scroll by week,
not just by month or year
- To get a sense of what month to highlight, I basically initialize on the
first Saturday of each month, since that will be either the first of two or
the second of three months being partially displayed, and then I work forwards
and backwards from that point.
Currently, I assume that dates are stored in the RFC 3339 format,
because I find it to be most human readable and easy to parse
http://www.faqs.org/rfcs/rfc3339.html: 2005-06-30T08:05:00-07:00
*/
dojo.widget.defineWidget(
"dojo.widget.html.DatePicker",
dojo.widget.HtmlWidget,
{
classConstructor: function() {
// mixin dojo.widget.DatePicker non-demoninational code
dojo.widget.DatePicker.call(this);
// today's date, JS Date object
this.today = "";
// selected date, JS Date object
this.date = "";
// rfc 3339 date
this.storedDate = "";
// date currently selected in the UI, stored in year, month, date in the format that will be actually displayed
this.currentDate = {};
// stored in year, month, date in the format that will be actually displayed
this.firstSaturday = {};
},
classNames: {
previous: "previousMonth",
current: "currentMonth",
next: "nextMonth",
currentDate: "currentDate",
selectedDate: "selectedItem"
},
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.css"),
fillInTemplate: function(){
dojo.widget.DatePicker.call(this);
this.initData();
this.initUI();
},
initData: function() {
this.today = new Date();
if(this.storedDate && (this.storedDate.split("-").length > 2)) {
this.date = dojo.widget.DatePicker.util.fromRfcDate(this.storedDate);
} else {
this.date = this.today;
}
// calendar math is simplified if time is set to 0
this.today.setHours(0);
this.date.setHours(0);
var month = this.date.getMonth();
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.date.getMonth().toString(), this.date.getFullYear());
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
},
setDate: function(rfcDate) {
this.storedDate = rfcDate;
},
initUI: function() {
this.selectedIsUsed = false;
this.currentIsUsed = false;
var currentClassName = "";
var previousDate = new Date();
var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
var currentCalendarNode;
// set hours of date such that there is no chance of rounding error due to
// time change in local time zones
previousDate.setHours(8);
var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
if(this.firstSaturday.date < 7) {
// this means there are days to show from the previous month
var dayInWeek = 6;
for (var i=this.firstSaturday.date; i>0; i--) {
currentCalendarNode = calendarNodes.item(dayInWeek);
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
dayInWeek--;
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
for(var i=dayInWeek; i>-1; i--) {
currentCalendarNode = calendarNodes.item(i);
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
} else {
nextDate.setDate(this.firstSaturday.date-6);
for(var i=0; i<7; i++) {
currentCalendarNode = calendarNodes.item(i);
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
}
previousDate.setDate(this.firstSaturday.date);
previousDate.setMonth(this.firstSaturday.month);
previousDate.setFullYear(this.firstSaturday.year);
nextDate = this.incrementDate(previousDate, true);
var count = 7;
currentCalendarNode = calendarNodes.item(count);
while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
while(count < 42) {
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
this.setMonthLabel(this.firstSaturday.month);
this.setYearLabels(this.firstSaturday.year);
},
incrementDate: function(date, bool) {
// bool: true to increase, false to decrease
var time = date.getTime();
var increment = 1000 * 60 * 60 * 24;
time = (bool) ? (time + increment) : (time - increment);
var returnDate = new Date();
returnDate.setTime(time);
return returnDate;
},
incrementWeek: function(evt) {
var date = this.firstSaturday.date;
var month = this.firstSaturday.month;
var year = this.firstSaturday.year;
switch(evt.target) {
case this.increaseWeekNode.getElementsByTagName("img").item(0):
case this.increaseWeekNode:
date = date + 7;
if (date>this._daysIn(month,year)) {
date = date - this._daysIn(month,year);
if (month < 11) {
month++;
} else {
month=0;
year++;
}
}
break;
case this.decreaseWeekNode.getElementsByTagName("img").item(0):
case this.decreaseWeekNode:
if (date > 7) {
date = date - 7;
} else {
var diff = 7 - date;
if (month > 0) {
month--;
date = this._daysIn(month,year) - diff;
}else {
year--;
month=11;
date = 31 - diff;
}
}
break;
}
this.firstSaturday.date=date;
this.firstSaturday.month=month;
this.firstSaturday.year=year;
this.initUI();
},
incrementMonth: function(evt) {
var month = this.firstSaturday.month;
var year = this.firstSaturday.year;
switch(evt.currentTarget) {
case this.increaseMonthNode:
if(month < 11) {
month++;
} else {
month = 0;
year++;
this.setYearLabels(year);
}
break;
case this.decreaseMonthNode:
if(month > 0) {
month--;
} else {
month = 11;
year--;
this.setYearLabels(year);
}
break;
case this.increaseMonthNode.getElementsByTagName("img").item(0):
if(month < 11) {
month++;
} else {
month = 0;
year++;
this.setYearLabels(year);
}
break;
case this.decreaseMonthNode.getElementsByTagName("img").item(0):
if(month > 0) {
month--;
} else {
month = 11;
year--;
this.setYearLabels(year);
}
break;
}
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(month.toString(), year);
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
this.initUI();
},
incrementYear: function(evt) {
var year = this.firstSaturday.year;
switch(evt.target) {
case this.nextYearLabelNode:
year++;
break;
case this.previousYearLabelNode:
year--;
break;
}
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.firstSaturday.month.toString(), year);
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
this.initUI();
},
_daysIn: function(month,year) {
var daysIn = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (month==1) {
return (year%400 == 0) ? 29: (year%100 == 0) ? 28: (year%4 == 0) ? 29: 28;
} else {
return daysIn[month];
}
},
onIncrementDate: function(evt) {
dojo.unimplemented('dojo.widget.html.DatePicker.onIncrementDate');
},
onIncrementWeek: function(evt) {
evt.stopPropagation();
this.incrementWeek(evt);
},
onIncrementMonth: function(evt) {
evt.stopPropagation();
this.incrementMonth(evt);
},
onIncrementYear: function(evt) {
evt.stopPropagation();
this.incrementYear(evt);
},
setMonthLabel: function(monthIndex) {
this.monthLabelNode.innerHTML = dojo.date.months[monthIndex];
},
setYearLabels: function(year) {
this.previousYearLabelNode.innerHTML = year - 1;
this.currentYearLabelNode.innerHTML = year;
this.nextYearLabelNode.innerHTML = year + 1;
},
getDateClassName: function(date, monthState) {
var currentClassName = this.classNames[monthState];
if ((!this.selectedIsUsed) && (date.getDate() == this.date.getDate()) && (date.getMonth() == this.date.getMonth()) && (date.getFullYear() == this.date.getFullYear())) {
currentClassName = this.classNames.selectedDate + " " + currentClassName;
this.selectedIsUsed = 1;
}
if((!this.currentIsUsed) && (date.getDate() == this.today.getDate()) && (date.getMonth() == this.today.getMonth()) && (date.getFullYear() == this.today.getFullYear())) {
currentClassName = currentClassName + " " + this.classNames.currentDate;
this.currentIsUsed = 1;
}
return currentClassName;
},
onClick: function(evt) {
dojo.event.browser.stopEvent(evt)
},
onSetDate: function(evt) {
dojo.event.browser.stopEvent(evt);
this.selectedIsUsed = 0;
this.todayIsUsed = 0;
var month = this.firstSaturday.month;
var year = this.firstSaturday.year;
if (dojo.html.hasClass(evt.target, this.classNames["next"])) {
month = ++month % 12;
// if month is now == 0, add a year
year = (month==0) ? ++year : year;
} else if (dojo.html.hasClass(evt.target, this.classNames["previous"])) {
month = --month % 12;
// if month is now == 0, add a year
year = (month==11) ? --year : year;
}
this.date = new Date(year, month, evt.target.innerHTML);
this.setDate(dojo.widget.DatePicker.util.toRfcDate(this.date));
this.initUI();
}
}
);

View file

@ -0,0 +1,31 @@
/*
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.html.DebugConsole");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.FloatingPane");
dojo.widget.html.DebugConsole= function(){
dojo.widget.html.FloatingPane.call(this);
dojo.widget.DebugConsole.call(this);
}
dojo.inherits(dojo.widget.html.DebugConsole, dojo.widget.html.FloatingPane);
dojo.lang.extend(dojo.widget.html.DebugConsole, {
fillInTemplate: function() {
dojo.widget.html.DebugConsole.superclass.fillInTemplate.apply(this, arguments);
this.containerNode.id = "debugConsoleClientPane";
djConfig.isDebug = true;
djConfig.debugContainerId = this.containerNode.id;
}
});

View file

@ -0,0 +1,210 @@
/*
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.html.DocPane");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.widget.html.DocPane = function(){
dojo.widget.HtmlWidget.call(this);
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlDocPane.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlDocPane.css");
this.widgetType = "DocPane";
this.isContainer = true;
this.select;
this.result;
this.fn;
this.fnLink;
this.count;
this.row;
this.summary;
this.description;
this.variables;
this.vRow;
this.vLink;
this.vDesc;
this.parameters;
this.pRow;
this.pLink;
this.pDesc;
this.pOpt;
this.pType;
this.source;
this.sType;
this.sName;
this.sParams;
this.sPType;
this.sPTypeSave;
this.sPName;
this.sPNameSave;
dojo.event.topic.subscribe("/doc/results", this, "onDocResults");
dojo.event.topic.subscribe("/doc/functionDetail", this, "onDocSelectFunction");
}
dojo.inherits(dojo.widget.html.DocPane, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.DocPane, {
fillInTemplate: function(){
this.homeSave = this.containerNode.cloneNode(true);
this.selectSave = dojo.dom.removeNode(this.select);
this.resultSave = dojo.dom.removeNode(this.result);
this.rowParent = this.row.parentNode;
this.rowSave = dojo.dom.removeNode(this.row);
this.vParent = this.vRow.parentNode;
this.vSave = dojo.dom.removeNode(this.vRow);
this.pParent = this.pRow.parentNode;
this.pSave = dojo.dom.removeNode(this.pRow);
this.sPTypeSave = dojo.dom.removeNode(this.sPType);
this.sPNameSave = dojo.dom.removeNode(this.sPName);
},
onDocSelectFunction: function(message){
var meta = message.meta;
if(meta){
var variables = meta.variables;
var this_variables = meta.this_variables;
var child_variables = meta.child_variables;
var parameters = meta.parameters;
}
var doc = message.doc;
var appends = [];
dojo.dom.removeChildren(this.domNode);
this.fn.innerHTML = message.name;
this.description.innerHTML = doc.description;
this.variables.style.display = "block";
var all = [];
if(variables){
all = variables;
}
if(this_variables){
all = all.concat(this_variables);
}
if(child_variables){
all = all.concat(child_variables);
}
if(!all.length){
this.variables.style.display = "none";
}else{
for(var i = 0, one; one = all[i]; i++){
this.vLink.innerHTML = one;
this.vDesc.parentNode.style.display = "none";
appends.push(this.vParent.appendChild(this.vSave.cloneNode(true)));
}
}
this.sParams.innerHTML = "";
for(var param in parameters){
var paramType = parameters[param][0];
var paramName = parameters[param][1];
this.parameters.style.display = "block";
this.pLink.innerHTML = paramName;
this.pOpt.style.display = "none";
if(parameters[param].opt){
this.pOpt.style.display = "inline";
}
this.pType.parentNode.style.display = "none";
if(parameters[param][0]){
this.pType.parentNode.style.display = "inline";
this.pType.innerHTML = paramType;
}
this.pDesc.parentNode.style.display = "none";
if(doc.parameters[paramName] && doc.parameters[paramName].description){
this.pDesc.parentNode.style.display = "inline";
this.pDesc.innerHTML = doc.parameters[paramName].description;
}
appends.push(this.pParent.appendChild(this.pSave.cloneNode(true)));
if(param > 0) {
this.sParams.appendChild(document.createTextNode(", "));
}
if(paramType){
dojo.debug(this.sPTypeSave);
this.sPTypeSave.innerHTML = paramType;
this.sParams.appendChild(this.sPTypeSave.cloneNode(true));
this.sParams.appendChild(document.createTextNode(" "));
}
dojo.debug(this.sPNameSave);
this.sPNameSave.innerHTML = paramName;
this.sParams.appendChild(this.sPNameSave.cloneNode(true))
}
if(message.returns){
this.sType.innerHTML = message.returns;
}else{
this.sType.innerHTML = "void";
}
this.sName.innerHTML = message.name;
dojo.dom.removeChildren(this.source);
this.source.appendChild(document.createTextNode("\n\r"));
this.source.appendChild(document.createTextNode(message.src.replace(/\n/g, "\r\n\t")));
this.source.appendChild(document.createTextNode("\n\r"));
this.domNode.appendChild(this.selectSave.cloneNode(true));
for(var i = 0, append; append = appends[i]; i++){
dojo.dom.removeNode(append);
}
},
onDocResults: function(message){
var results = message.docResults;
if(results.length == 1){
dojo.event.topic.publish("/doc/selectFunction", results[0]);
return;
}
dojo.dom.removeChildren(this.domNode);
this.count.innerHTML = results.length;
var appends = [];
for(var i = 0, row; row = results[i]; i++){
this.fnLink.innerHTML = row.name;
this.fnLink.href = "#" + row.name;
if(row.id){
this.fnLink.href = this.fnLink.href + "," + row.id;
}
this.summary.parentNode.style.display = "none";
if(row.summary){
this.summary.parentNode.style.display = "inline";
this.summary.innerHTML = row.summary;
}
appends.push(this.rowParent.appendChild(this.rowSave.cloneNode(true)));
}
function makeSelect(x){
return function(e) {
dojo.event.topic.publish("/doc/selectFunction", x);
}
}
this.domNode.appendChild(this.resultSave.cloneNode(true));
var as = this.domNode.getElementsByTagName("a");
for(var i = 0, a; a = as[i]; i++){
dojo.event.connect(a, "onclick", makeSelect(results[i]));
}
for(var i = 0, append; append = appends[i]; i++){
this.rowParent.removeChild(append);
}
}
});
dojo.widget.tags.addParseTreeHandler("dojo:DocPane");

View file

@ -0,0 +1,188 @@
/*
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:
* - make the dropdown "smart" so it can't get cutoff on bottom of page, sides of page, etc.
*/
dojo.provide("dojo.widget.html.DropdownButton");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.html");
dojo.widget.html.DropdownButton = function() {
// mix in the button properties
dojo.widget.DropdownButton.call(this);
dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.DropdownButton, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.DropdownButton, {
// In IE, event handlers on objects inside buttons don't work correctly, so
// we just set onClick on the button itself.
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDropDownButtonTemplate.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),
// attach points
button: null,
table: null,
labelCell: null,
borderCell: null,
arrowCell: null,
arrow: null,
fillInTemplate: function(args, frag) {
// input data (containing the anchor for the button itself, plus the
// thing to display when you push the down arrow)
var input = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
// Recursively expand widgets inside of the <dojo:dropdownButton>
var parser = new dojo.xml.Parse();
var frag = parser.parseElement(input, null, true);
var ary = dojo.widget.getParser().createComponents(frag);
this.a = dojo.dom.getFirstChildElement(input); // the button contents
this.menu = dojo.dom.getNextSiblingElement(this.a); // the menu under the button
this.disabled = dojo.html.hasClass(this.a, "disabled");
if( this.disabled ) {
dojo.html.addClass(this.button, "dojoDisabled");
this.domNode.setAttribute("disabled", "true");
}
dojo.html.disableSelection(this.a);
this.a.style["text-decoration"]="none";
this.labelCell.appendChild(this.a);
this.arrow.src =
dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow" +
(this.disabled ? "-disabled" : "") + ".gif");
// Attach menu to body so that it appears above other buttons
this.menu.style.position="absolute";
this.menu.style.display="none";
this.menu.style["z-index"] = 99;
document.body.appendChild(this.menu);
},
postCreate: function() {
if ( dojo.render.html.ie ) {
// Compensate for IE's weird padding of button content, which seems to be relative
// to the length of the content
var contentWidth = dojo.style.getOuterWidth(this.table);
this.labelCell.style["left"] = "-" + (contentWidth / 10) + "px";
this.arrowCell.style["left"] = (contentWidth / 10) + "px";
}
// Make menu at least as wide as the button
var buttonWidth = dojo.style.getOuterWidth(this.button);
var menuWidth = dojo.style.getOuterWidth(this.menu);
if ( buttonWidth > menuWidth ) {
dojo.style.setOuterWidth(this.menu, buttonWidth);
}
},
// If someone clicks anywhere else on the screen (including another menu),
// then close this menu.
onCanvasMouseDown: function(e) {
if( !dojo.dom.isDescendantOf(e.target, this.button) &&
!dojo.dom.isDescendantOf(e.target, this.menu) ) {
this.hideMenu();
}
},
eventWasOverArrow: function(e) {
// want to use dojo.html.overElement() but also need to detect clicks
// on the area between the arrow and the edge of the button
var eventX = e.clientX;
var borderX = dojo.style.totalOffsetLeft(this.borderCell);
return (eventX > borderX );
},
onMouseOver: function(e) {
dojo.html.addClass(this.button, "dojoButtonHover");
dojo.html.removeClass(this.button, "dojoButtonNoHover");
},
onMouseOut: function(e) {
dojo.html.removeClass(this.button, "dojoButtonHover");
dojo.html.addClass(this.button, "dojoButtonNoHover");
},
onClick: function(e) {
if ( this.eventWasOverArrow(e) ) {
this._onClickArrow();
} else {
this._onClickButton();
}
},
// Action when the user presses the button
_onClickButton: function(e) {
if ( this.a ) {
if ( this.a.click ) {
this.a.click();
} else if ( this.a.href ) {
location.href = this.a.href;
}
}
},
// Action when user presses the arrow
_onClickArrow: function() {
if ( this.menu.style.display == "none" ) {
this.showMenu();
} else {
this.hideMenu();
}
},
showMenu: function() {
if ( this.disabled )
return;
// Position it accordingly, relative to screen root (since
// it's attached to document.body)
this.menu.style.left = dojo.style.totalOffsetLeft(this.button) + "px";
this.menu.style.top = dojo.style.totalOffsetTop(this.button) + dojo.style.getOuterHeight(this.button) + "px";
// Display the menu; do this funky code below to stop the menu from extending
// all the way to the right edge of the screen.
// TODO: retest simple display="" to confirm that it doesn't work.
try {
this.menu.style.display="table"; // mozilla
} catch(e) {
this.menu.style.display="block"; // IE
}
// If someone clicks somewhere else on the screen then close the menu
dojo.event.connect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
// When someone clicks the menu, after the menu handles the event,
// close the menu (be careful not to close the menu too early or else
// the menu will never receive the event.)
dojo.event.connect(this.menu, "onclick", this, "hideMenu");
},
hideMenu: function() {
this.menu.style.display = "none";
dojo.event.disconnect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
dojo.event.disconnect(this.menu, "onclick", this, "hideMenu");
}
});

View file

@ -0,0 +1,198 @@
/*
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.html.GoogleMap");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.math");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.GoogleMap");
(function(){
var gkey = djConfig["gMapKey"]||djConfig["googleMapKey"];
// the Google API key mechanism sucks. We're hardcoding here for love and affection but I don't like it.
var uri=new dojo.uri.Uri(window.location.href);
if(uri.host=="www.dojotoolkit.org"){
gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hRqjp7ri2mNiOEYqetD3xnFHpt5rBSjszDd1sdufPyQKUTyCf_YxoIxvw";
}
else if(uri.host=="blog.dojotoolkit.org"){
gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSkep6Av1xaMhVn3yCLkorJeXeLARQ6fammI_P3qSGleTJhoI5_1JmP_Q";
}
else if(uri.host=="archive.dojotoolkit.org"){
gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hTaQpDt0dyGLIHbXMPTzg1kWeAfwRTwZNyrUfbfxYE9yIvRivEjcXoDTg";
}
else if(uri.host=="dojotoolkit.org"){
gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSaOaO_TgJ5c3mtQFnk5JO2zD5dZBRZk-ieqVs7BORREYNzAERmcJoEjQ";
}
if(!dojo.hostenv.post_load_){
var tag = "<scr"+"ipt src='http://maps.google.com/maps?file=api&amp;v=2&amp;key="+gkey+"'></scri"+"pt>";
if(!dj_global["GMap2"]){ // prevent multi-inclusion
document.write(tag);
}
}else{
dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Google in your page or require() the GoogleMap widget before onload has fired");
}
})();
dojo.widget.html.GoogleMap=function(){
dojo.widget.HtmlWidget.call(this);
dojo.widget.GoogleMap.call(this);
var gm=dojo.widget.GoogleMap;
this.map=null;
this.data=[];
this.datasrc="";
// FIXME: this is pehraps the stupidest way to specify this enum I can think of
this.controls=[gm.Controls.LargeMap,gm.Controls.Scale,gm.Controls.MapType];
};
dojo.inherits(dojo.widget.html.GoogleMap, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.GoogleMap, {
templatePath:null,
templateCssPath:null,
setControls:function(){
var c=dojo.widget.GoogleMap.Controls;
for(var i=0; i<this.controls.length; i++){
var type=this.controls[i];
switch(type){
case c.LargeMap:{
this.map.addControl(new GLargeMapControl());
break;
}
case c.SmallMap:{
this.map.addControl(new GSmallMapControl());
break;
}
case c.SmallZoom:{
this.map.addControl(new GSmallZoomControl());
break;
}
case c.Scale:{
this.map.addControl(new GScaleControl());
break;
}
case c.MapType:{
this.map.addControl(new GMapTypeControl());
break;
}
case c.Overview:{
this.map.addControl(new GOverviewMapControl());
break;
}
default:{
break;
}
}
}
},
findCenter:function(bounds){
var clat=(bounds.getNorthEast().lat()+bounds.getSouthWest().lat())/2;
var clng=(bounds.getNorthEast().lng()+bounds.getSouthWest().lng())/2;
return (new GLatLng(clat,clng));
},
createPinpoint:function(pt,overlay){
var m=new GMarker(pt);
if(overlay){
GEvent.addListener(m,"click",function(){
m.openInfoWindowHtml("<div>"+overlay+"</div>");
});
}
return m;
},
parse:function(table){
this.data=[];
// get the column indices
var h=table.getElementsByTagName("thead")[0];
if(!h){
return;
}
var a=[];
var cols=h.getElementsByTagName("td");
if(cols.length==0){
cols=h.getElementsByTagName("th");
}
for(var i=0; i<cols.length; i++){
var c=cols[i].innerHTML.toLowerCase();
if(c=="long") c="lng";
a.push(c);
}
// parse the data
var b=table.getElementsByTagName("tbody")[0];
if(!b){
return;
}
for(var i=0; i<b.childNodes.length; i++){
if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
continue;
}
var cells=b.childNodes[i].getElementsByTagName("td");
var o={};
for(var j=0; j<a.length; j++){
var col=a[j];
if(col=="lat"||col=="lng"){
o[col]=parseFloat(cells[j].innerHTML);
}else{
o[col]=cells[j].innerHTML;
}
}
this.data.push(o);
}
},
render:function(){
var bounds=new GLatLngBounds();
var d=this.data;
var pts=[];
for(var i=0; i<d.length; i++){
bounds.extend(new GLatLng(d[i].lat,d[i].lng));
}
this.map.setCenter(this.findCenter(bounds), this.map.getBoundsZoomLevel(bounds));
for(var i=0; i<this.data.length; i++){
var p=new GLatLng(this.data[i].lat,this.data[i].lng);
var d=this.data[i].description||null;
var m=this.createPinpoint(p,d);
this.map.addOverlay(m);
}
},
initialize:function(args, frag){
if(!GMap2){
dojo.raise("dojo.widget.GoogleMap: The Google Map script must be included (with a proper API key) in order to use this widget.");
}
if(this.datasrc){
this.parse(dojo.byId(this.datasrc));
}
else if(this.domNode.getElementsByTagName("table")[0]){
this.parse(this.domNode.getElementsByTagName("table")[0]);
}
},
postCreate:function(){
// clean the domNode before creating the map.
while(this.domNode.childNodes.length>0){
this.domNode.removeChild(this.domNode.childNodes[0]);
}
this.map=new GMap2(this.domNode);
this.render();
this.setControls();
}
});

View file

@ -0,0 +1,54 @@
/*
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.LinkPane");
dojo.provide("dojo.widget.html.LinkPane");
//
// a div that loads from a URL. (Similar to an iframe, but
// it's in the same environment as the main window)
//
dojo.require("dojo.widget.LinkPane");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.require("dojo.string");
dojo.widget.html.LinkPane = function(){
dojo.widget.html.ContentPane.call(this);
}
dojo.inherits(dojo.widget.html.LinkPane, dojo.widget.html.ContentPane);
dojo.lang.extend(dojo.widget.html.LinkPane, {
widgetType: "LinkPane",
// I'm using a template because the user may specify the input as
// <a href="foo.html">label</a>, in which case we need to get rid of the
// <a> because we don't want a link.
templateString: '<div class="dojoLinkPane"></div>',
fillInTemplate: function(args, frag){
var source = this.getFragNodeRef(frag);
// If user has specified node contents, they become the label
// (the link must be plain text)
this.label += source.innerHTML;
var source = this.getFragNodeRef(frag);
dojo.html.copyStyle(this.domNode, source);
}
});

View file

@ -0,0 +1,51 @@
/*
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.require("dojo.widget.Menu");
dojo.provide("dojo.widget.html.Menu");
/* HtmlMenu
***********/
dojo.widget.html.Menu = function(){
dojo.widget.html.Menu.superclass.constructor.call(this);
this.items = [];
}
dojo.inherits(dojo.widget.html.Menu, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.Menu, {
widgetType: "Menu",
isContainer: true,
// copy children widgets output directly to parent (this node), to avoid
// errors trying to insert an <li> under a <div>
snarfChildDomOutput: true,
templateString: '<ul></ul>',
templateCssPath: dojo.uri.dojoUri("src/widget/templates/Menu.css"),
fillInTemplate: function (args, frag){
//dojo.widget.HtmlMenu.superclass.fillInTemplate.apply(this, arguments);
this.domNode.className = "dojoMenu";
},
_register: function (item ) {
dojo.event.connect(item, "onSelect", this, "onSelect");
this.items.push(item);
},
push: function (item) {
this.domNode.appendChild(item.domNode);
this._register(item);
}
});

View file

@ -0,0 +1,60 @@
/*
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.html.MenuItem");
/* HtmlMenuItem
***************/
dojo.widget.html.MenuItem = function(){
dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.MenuItem, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.MenuItem, {
widgetType: "MenuItem",
templateString: '<li class="dojoMenuItem" dojoAttachEvent="onMouseOver; onMouseOut; onMouseDown; onMouseUp; onClick;"></li>',
title: "",
fillInTemplate: function(args, frag){
dojo.html.disableSelection(this.domNode);
if(!dojo.string.isBlank(this.title)){
this.domNode.appendChild(document.createTextNode(this.title));
}else{
this.domNode.appendChild(frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"]);
}
},
onMouseOver: function(e){
dojo.html.addClass(this.domNode, "dojoMenuItemHover");
},
onMouseOut: function(e){
dojo.html.removeClass(this.domNode, "dojoMenuItemHover");
},
onClick: function(e){ this.onSelect(this, e); },
onMouseDown: function(e){},
onMouseUp: function(e){},
// By default, when I am clicked, click the item inside of me
onSelect: function (item, e) {
var child = dojo.dom.getFirstChildElement(this.domNode);
if(child){
if(child.click){
child.click();
}else if(child.href){
location.href = child.href;
}
}
}
});

View file

@ -0,0 +1,134 @@
/*
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.html.MonthlyCalendar");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.html.DatePicker");
dojo.require("dojo.widget.MonthlyCalendar");
//dojo.require("dojo.widget.MonthlyCalendar.util");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.widget.html.MonthlyCalendar= function(){
dojo.widget.MonthlyCalendar.call(this);
//dojo.widget.html.DatePicker.call(this);
this.widgetType = "MonthlyCalendar";
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlMonthlyCalendar.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlMonthlyCalendar.css");
this.iCalendars = [];
}
dojo.inherits(dojo.widget.html.MonthlyCalendar, dojo.widget.html.DatePicker);
dojo.lang.extend(dojo.widget.html.MonthlyCalendar, {
cache: function() {
},
addCalendar: function(/* dojo.iCalendar */ cal) {
dojo.debug("Adding Calendar");
this.iCalendars.push(cal);
dojo.debug("Starting init");
this.initUI()
dojo.debug("done init");
},
createDayContents: function(node,mydate) {
dojo.dom.removeChildren(node);
node.appendChild(document.createTextNode(mydate.getDate()));
for(var x=0; x<this.iCalendars.length; x++) {
var evts = this.iCalendars[x].getEvents(mydate);
if ((dojo.lang.isArray(evts)) && (evts.length>0)) {
for(var y=0;y<evts.length;y++) {
var el = document.createElement("div");
dojo.html.addClass(el, "dojoMonthlyCalendarEvent");
el.appendChild(document.createTextNode(evts[y].summary.value));
el.width = dojo.style.getContentWidth(node);
node.appendChild(el);
}
}
}
},
initUI: function() {
this.selectedIsUsed = false;
this.currentIsUsed = false;
var currentClassName = "";
var previousDate = new Date();
var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
var currentCalendarNode;
// set hours of date such that there is no chance of rounding error due to
// time change in local time zones
previousDate.setHours(8);
var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
var lastDay = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date + 42, 8);
if (this.iCalendars.length > 0) {
for (var x=0; x<this.iCalendars.length;x++) {
this.iCalendars[x].preComputeRecurringEvents(lastDay);
}
}
if(this.firstSaturday.date < 7) {
// this means there are days to show from the previous month
var dayInWeek = 6;
for (var i=this.firstSaturday.date; i>0; i--) {
currentCalendarNode = calendarNodes.item(dayInWeek);
this.createDayContents(currentCalendarNode, nextDate);
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
dayInWeek--;
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
for(var i=dayInWeek; i>-1; i--) {
currentCalendarNode = calendarNodes.item(i);
this.createDayContents(currentCalendarNode, nextDate);
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
} else {
nextDate.setDate(1);
for(var i=0; i<7; i++) {
currentCalendarNode = calendarNodes.item(i);
this.createDayContents(currentCalendarNode, nextDate);
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
}
previousDate.setDate(this.firstSaturday.date);
previousDate.setMonth(this.firstSaturday.month);
previousDate.setFullYear(this.firstSaturday.year);
nextDate = this.incrementDate(previousDate, true);
var count = 7;
currentCalendarNode = calendarNodes.item(count);
while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
this.createDayContents(currentCalendarNode, nextDate);
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
while(count < 42) {
this.createDayContents(currentCalendarNode, nextDate);
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
this.setMonthLabel(this.firstSaturday.month);
this.setYearLabels(this.firstSaturday.year);
}
});

View file

@ -0,0 +1,177 @@
/*
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.html.Show");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Show");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.event");
dojo.require("dojo.animation.Animation");
dojo.require("dojo.math.curves");
dojo.require("dojo.html");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.func");
dojo.widget.defineWidget(
"dojo.widget.html.Show",
dojo.widget.HtmlWidget,
null,
"html",
function(){
dojo.widget.Show.call(this);
}
);
dojo.lang.extend(dojo.widget.html.Show, dojo.widget.Show.prototype);
dojo.lang.extend(dojo.widget.html.Show, {
body: null,
nav: null,
hider: null,
select: null,
option: null,
inNav: false,
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlShow.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlShow.css"),
fillInTemplate: function(args, frag){
var source = this.getFragNodeRef(frag);
this.sourceNode = document.body.appendChild(source.cloneNode(true));
for(var i = 0, child; child = this.sourceNode.childNodes[i]; i++){
if(child.tagName && child.getAttribute("dojotype").toLowerCase() == "showslide"){
child.className = "dojoShowPrintSlide";
child.innerHTML = "<h1>" + child.title + "</h1>" + child.innerHTML;
}
}
this.sourceNode.className = "dojoShowPrint";
this.sourceNode.style.display = "none";
dojo.event.connect(document, "onclick", this, "gotoSlideByEvent");
dojo.event.connect(document, "onkeypress", this, "gotoSlideByEvent");
dojo.event.connect(window, "onresize", this, "resizeWindow");
dojo.event.connect(this.nav, "onmousemove", this, "popUpNav");
},
postCreate: function(){
this._slides = [];
for(var i = 0, child; child = this.children[i]; i++){
if(child.widgetType == "ShowSlide"){
this._slides.push(child);
this.option.text = child.title;
this.option.parentNode.insertBefore(this.option.cloneNode(true), this.option);
}
}
this.option.parentNode.removeChild(this.option);
document.body.style.display = "block";
this.resizeWindow();
this.gotoSlide(0);
},
gotoSlide: function(/*int*/ slide){
if(slide == this._slide){
return;
}
if(!this._slides[slide]){
// slide: string
for(var i = 0, child; child = this._slides[i]; i++){
if(child.title == slide){
slide = i;
break;
}
}
}
if(!this._slides[slide]){
return;
}
if(this._slide != -1){
while(this._slides[this._slide].previousAction()){}
}
this._slide = slide;
this.select.selectedIndex = slide;
while(this.contentNode.hasChildNodes()){ this.contentNode.removeChild(this.contentNode.firstChild); }
this.contentNode.appendChild(this._slides[slide].domNode);
},
gotoSlideByEvent: function(/*Event*/ event){
var node = event.target;
var type = event.type;
if(type == "click"){
if(node.tagName == "OPTION"){
this.gotoSlide(node.index);
}else if(node.tagName == "SELECT"){
this.gotoSlide(node.selectedIndex);
}else if(node.tagName != "A"){
this.nextSlide(event);
}
}else if(type == "keypress"){
var key = event.keyCode;
var ch = event.charCode;
if(key == 63234 || key == 37){
this.previousSlide(event);
}else if(key == 63235 || key == 39 || ch == 32){
this.nextSlide(event);
}
}
},
nextSlide: function(/*Event?*/ event){
this.stopEvent(event);
return dojo.widget.Show.prototype.nextSlide.call(this, event);
},
previousSlide: function(/*Event?*/ event){
this.stopEvent(event);
return dojo.widget.Show.prototype.previousSlide.call(this, event);
},
stopEvent: function(/*Event*/ ev){
if(window.event){
ev.returnValue = false;
ev.cancelBubble = true;
}else{
ev.preventDefault();
ev.stopPropagation();
}
},
popUpNav: function(){
if(!this.inNav){
dojo.widget.Show.node = this.nav;
var anim = new dojo.animation.Animation(new dojo.math.curves.Line([5], [30]), 250, -1);
dojo.event.connect(anim, "onAnimate", function(e) {
dojo.widget.Show.node.style.height = e.x + "px";
});
dojo.event.connect(anim, "onEnd", function(e) {
dojo.widget.Show.node.style.height = e.x + "px";
});
anim.play(true);
}
clearTimeout(this.inNav);
this.inNav = setTimeout(dojo.lang.hitch(this, "hideNav"), 2000);
},
hideNav: function(){
clearTimeout(this.inNav);
this.inNav = false;
dojo.widget.Show.node = this.nav;
var anim = new dojo.animation.Animation(new dojo.math.curves.Line([30], [5]), 250, 1);
dojo.event.connect(anim, "onAnimate", function(e) {
dojo.widget.Show.node.style.height = e.x + "px";
});
dojo.event.connect(anim, "onEnd", function(e) {
dojo.widget.Show.node.style.height = e.x + "px";
});
anim.play(true);
},
resizeWindow: function(/*Event*/ ev){
document.body.style.height = "auto";
var h = Math.max(
document.documentElement.scrollHeight || document.body.scrollHeight,
dojo.html.getViewportHeight());
document.body.style.height = h + "px";
}
});

View file

@ -0,0 +1,28 @@
/*
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.html.ShowAction");
dojo.require("dojo.widget.ShowAction");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lang.common");
dojo.widget.defineWidget(
"dojo.widget.html.ShowAction",
dojo.widget.HtmlWidget,
null,
"html",
function(){
dojo.widget.ShowAction.call(this);
}
);
dojo.lang.extend(dojo.widget.html.ShowAction, dojo.widget.ShowAction.prototype);
dojo.lang.extend(dojo.widget.html.ShowAction, {
});

View file

@ -0,0 +1,189 @@
/*
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.html.ShowSlide");
dojo.require("dojo.widget.*");
dojo.require("dojo.lang.common");
dojo.require("dojo.widget.ShowSlide");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lfx.html");
dojo.require("dojo.animation.Animation");
dojo.require("dojo.graphics.color");
dojo.widget.defineWidget(
"dojo.widget.html.ShowSlide",
dojo.widget.HtmlWidget,
null,
"html",
function(){
dojo.widget.ShowSlide.call(this);
}
);
dojo.lang.extend(dojo.widget.html.ShowSlide, dojo.widget.ShowSlide.prototype);
dojo.lang.extend(dojo.widget.html.ShowSlide, {
htmlTitle: null,
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlShowSlide.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlShowSlide.css"),
fillInTemplate: function(){
this.htmlTitle.innerHTML = this.title;
this._components = {};
var nodes = this.containerNode.all ? this.containerNode.all : this.containerNode.getElementsByTagName('*');
for(var i = 0, node; node = nodes[i]; i++){
var as = node.getAttribute("as");
if(as){
if(!this._components[as]){
this._components[as] = [];
}
this._components[as].push(node);
}
}
},
postCreate: function(){
this._actions = [];
for(var i = 0, child; child = this.children[i]; i++){
if(child.widgetType == "ShowAction"){
this._actions.push(child);
var components = this._components[child.on];
for(var j = 0, component; component = components[j]; j++){
if(child.action && child.action != "remove"){
this.hideComponent(component);
}
}
}
}
},
previousAction: function(/*Event?*/ event){
this.stopEvent(event);
var action = this._actions[this._action];
if(!action){
return false;
}
var on = action.on;
while(action.on == on){
var components = this._components[on];
for(var i = 0, component; component = components[i]; i++){
if(action.action == "remove"){
if(component.style.display == "none"){
component.style.display = "";
component.style.visibility = "visible";
var exits = true;
}
}else if(action.action){
this.hideComponent(component);
}
}
--this._action;
if(exits){
return true;
}
if(action.auto == "true"){
on = this._actions[this._action].on;
}
action = this._actions[this._action];
if(!action){
return false;
}
}
return true;
},
hideComponent: function(/*Node*/ component){
component.style.visibility = "hidden";
component.style.backgroundColor = "transparent";
var parent = component.parentNode;
if((parent)&&(parent.tagName == "LI")){
parent.oldType = parent.style.listStyleType;
parent.style.listStyleType = "none";
}
},
nextAction: function(/*Event?*/ event){
this.stopEvent(event);
if(!dojo.widget.ShowSlide.prototype.nextAction.call(this, event)){
return false;
}
var action = this._actions[this._action];
if(!action){
return false;
}
var components = this._components[action.on];
for(var i = 0, component; component = components[i]; i++){
if(action.action){
var duration = action.duration || 1000;
if(action.action == "fade"){
dojo.style.setOpacity(component, 0);
dojo.lfx.html.fadeIn(component, duration).play(true);
}else if(action.action == "fly"){
var width = dojo.style.getMarginBoxWidth(component);
var position = dojo.style.getAbsolutePosition(component);
// alert(position);
component.style.position = "relative";
component.style.left = -(width + position.x) + "px";
dojo.lfx.html.slideBy(component, [0, (width + position.x)], duration, -1, this.callWith).play(true);
}else if(action.action == "wipe"){
dojo.lfx.html.wipeIn(component, duration).play();
}else if(action.action == "color"){
var from = new dojo.graphics.color.Color(action.from).toRgb();
var to = new dojo.graphics.color.Color(action.to).toRgb();
var anim = new dojo.animation.Animation(new dojo.math.curves.Line(from, to), duration, 0);
node = component;
dojo.event.connect(anim, "onAnimate", function(e) {
node.style.color = "rgb(" + e.coordsAsInts().join(",") + ")";
});
anim.play(true);
}else if(action.action == "bgcolor"){
dojo.lfx.html.unhighlight(component, action.to, duration).play();
}else if(action.action == "remove"){
component.style.display = "none";
}
component.style.visibility = "visible";
}
}
action = this._actions[this._action + 1];
if(action && action.auto == "true"){
this.nextAction();
}
return true;
},
callWith: function(/*Node*/ node){
if(!node){ return; }
if(dojo.lang.isArray(node)){
dojo.lang.forEach(node, arguments.callee);
return;
}
var parent = node.parentNode;
if((parent)&&(parent.tagName.toLowerCase() == "li")){
parent.style.listStyleType = parent.oldType;
}
},
stopEvent: function(/*Event*/ ev){
if(!ev){
return;
}
if(window.event){
ev.returnValue = false;
ev.cancelBubble = true;
}else{
ev.preventDefault();
ev.stopPropagation();
}
}
});

View file

@ -0,0 +1,500 @@
/*
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
*/
/**
* Slider Widget.
*
* The slider widget comes in three forms:
* 1. Base Slider widget which supports movement in x and y dimensions
* 2. Vertical Slider (SliderVertical) widget which supports movement
* only in the y dimension.
* 3. Horizontal Slider (SliderHorizontal) widget which supports movement
* only in the x dimension.
*
* The key objects in the widget are:
* - a container div which displays a bar in the background (Slider object)
* - a handle inside the container div, which represents the value
* (sliderHandle DOM node)
* - the object which moves the handle (handleMove is of type
* SliderDragMoveSource)
*
* The values for the slider are calculated by grouping pixels together,
* based on the number of values to be represented by the slider.
* The number of pixels in a group is called the valueSize
* e.g. if slider is 150 pixels long, and is representing the values
* 0,1,...10 then pixels are grouped into lots of 15 (valueSize), where:
* value 0 maps to pixels 0 - 7
* 1 8 - 22
* 2 23 - 37 etc.
* The accuracy of the slider is limited to the number of pixels
* (i.e tiles > pixels will result in the slider not being able to
* represent some values).
*
* Technical Notes:
* - 3 widgets exist because the framework caches the template in
* dojo.widget.fillFromTemplateCache (which ignores the changed URI)
*
* Todo:
* - Setting of initial value currently doesn't work, because the one or
* more of the offsets, constraints or containing block are not set and
* are required to set the valueSize is not set before fillInTemplate
* is called.
* - Issues with dragging handle when page has been scrolled
* -
*
* References (aka sources of inspiration):
* - http://dojotoolkit.org/docs/fast_widget_authoring.html
* - http://dojotoolkit.org/docs/dojo_event_system.html
*
* @author Marcel Linnenfelser (m.linnen@synflag.de)
* @author Mathew Pole (mathew.pole@ebor.com)
*
* $Id: $
*/
// tell the package system what functionality is provided in this module (file)
// (note that the package system works on modules, not the classes)
dojo.provide("dojo.widget.html.Slider");
// load dependencies
dojo.require("dojo.event.*");
dojo.require("dojo.dnd.*");
// dojo.dnd.* doesn't include this package, because it's not in __package__.js
dojo.require("dojo.dnd.HtmlDragMove");
dojo.require("dojo.widget.*");
dojo.require("dojo.style");
/**
* Define the two dimensional slider widget class.
*/
dojo.widget.defineWidget (
"dojo.widget.html.Slider",
dojo.widget.HtmlWidget,
{
// over-ride some defaults
isContainer: false,
widgetType: "Slider",
// useful properties (specified as attributes in the html tag)
// number of values to be represented by slider in the horizontal direction
valuesX: 10,
// number of values to be represented by slider in the vertical direction
valuesY: 10,
// can values be changed on the x (horizontal) axis?
isEnableX: true,
// can values be changed on the y (vertical) axis?
isEnableY: true,
// value size (pixels) in the x dimension
valueSizeX: 0.0,
// value size (pixels) in the y dimension
valueSizeY: 0.0,
// initial value in the x dimension
initialValueX: 0,
// initial value in the y dimension
initialValueY: 0,
// do we allow the user to click on the slider to set the position?
// (note: dojo's infrastructor will convert attribute to a boolean)
clickSelect: true,
// should the handle snap to the grid or remain where it was dragged to?
// (note: dojo's infrastructor will convert attribute to a boolean)
snapToGrid: false,
// should the value change while you are dragging, or just after drag finishes?
activeDrag: false,
templateCssPath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.css"),
templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.html"),
// our DOM nodes
sliderHandle: null,
// private attributes
// This is set to true when a drag is started, so that it is not confused
// with a click
isDragInProgress: false,
// This function is called when the template is loaded
fillInTemplate: function ()
{
// dojo.debug ("fillInTemplate - className = " + this.domNode.className);
// setup drag-n-drop for the sliderHandle
this.handleMove = new dojo.widget.html.SliderDragMoveSource (this.sliderHandle);
this.handleMove.setParent (this);
dojo.event.connect(this.handleMove, "onDragMove", this, "onDragMove");
dojo.event.connect(this.handleMove, "onDragEnd", this, "onDragEnd");
dojo.event.connect(this.handleMove, "onClick", this, "onClick");
// keep the slider handle inside it's parent container
this.handleMove.constrainToContainer = true;
if (this.clickSelect) {
dojo.event.connect (this.domNode, "onclick", this, "setPosition");
}
if (this.isEnableX && this.initialValueX > 0) {
alert("setting x to " + this.initialValueX);
this.setValueX (this.initialValueX);
}
if (this.isEnableY && this.initialValueY > 0) {
this.setValueY (this.initialValueY);
}
},
// Move the handle (in the x dimension) to the specified value
setValueX: function (value) {
if (0.0 == this.valueSizeX) {
this.valueSizeX = this.handleMove.calcValueSizeX ();
}
if (value > this.valuesX) {
value = this.valuesX;
}
else if (value < 0) {
value = 0;
}
//dojo.debug ("value = " + value, ", valueSizeX = " + this.valueSizeX);
this.handleMove.domNode.style.left = (value * this.valueSizeX) + "px";
},
// Get the number of the value that matches the position of the handle
getValueX: function () {
if (0.0 == this.valueSizeX) {
this.valueSizeX = this.handleMove.calcValueSizeX ();
}
return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "left") / this.valueSizeX);
},
// set the slider to a particular value
setValueY: function (value) {
if (0.0 == this.valueSizeY) {
this.valueSizeY = this.handleMove.calcValueSizeY ();
}
if (value > this.valuesY) {
value = this.valuesY;
}
else if (value < 0) {
value = 0;
}
this.handleMove.domNode.style.top = (value * this.valueSizeY) + "px";
},
// Get the number of the value that the matches the position of the handle
getValueY: function () {
if (0.0 == this.valueSizeY) {
this.valueSizeY = this.handleMove.calcValueSizeY ();
}
return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "top") / this.valueSizeY);
},
// set the position of the handle
setPosition: function (e) {
//dojo.debug ("Slider#setPosition - e.clientX = " + e.clientX
// + ", e.clientY = " + e.clientY);
if (this.isDragInProgress) {
this.isDragInProgress = false;
}
var offset = dojo.html.getScrollOffset();
var parent = dojo.style.getAbsolutePosition(this.domNode, true);
if (this.isEnableX) {
var x = offset.x + e.clientX - parent.x;
if (x > this.domNode.offsetWidth) {
x = this.domNode.offsetWidth;
}
if (this.snapToGrid && x > 0) {
if (0.0 == this.valueSizeX) {
this.valueSizeX = this.handleMove.calcValueSizeX ();
}
x = this.valueSizeX * (Math.round (x / this.valueSizeX));
}
this.handleMove.domNode.style.left = x + "px";
}
if (this.isEnableY) {
var y = offset.y + e.clientY - parent.y;
if (y > this.domNode.offsetHeight) {
y = this.domNode.offsetHeight;
}
if (this.snapToGrid && y > 0) {
if (0.0 == this.valueSizeY) {
this.valueSizeY = this.handleMove.calcValueSizeY ();
}
y = this.valueSizeY * (Math.round (y / this.valueSizeY));
}
this.handleMove.domNode.style.top = y + "px";
}
},
onDragMove: function(){
this.onValueChanged(this.getValueX(), this.getValueY());
},
onClick: function(){
this.onValueChanged(this.getValueX(), this.getValueY());
},
onValueChanged: function(x, y){
}
}
);
/* ------------------------------------------------------------------------- */
/**
* Define the horizontal slider widget class.
*/
dojo.widget.defineWidget (
"dojo.widget.html.SliderHorizontal",
dojo.widget.html.Slider,
{
widgetType: "SliderHorizontal",
value: 0,
isEnableY: false,
templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderHorizontal.html"),
postMixInProperties: function(){
this.initialValue = this.value;
},
// wrapper for getValueX
getValue: function () {
return this.getValueX ();
},
// wrapper for setValueX
setValue: function (value) {
this.setValueX (value);
this.onValueChanged(value);
},
onDragMove: function(){
if(this.activeDrag){
this.onValueChanged(this.getValue());
}
},
onDragEnd: function(){
if(!this.activeDrag){
this.onValueChanged(this.getValue());
}
},
onClick: function(){
this.onValueChanged(this.getValue());
},
onValueChanged: function(value){
this.value=value;
}
}
);
/* ------------------------------------------------------------------------- */
/**
* Define the vertical slider widget class.
*/
dojo.widget.defineWidget (
"dojo.widget.html.SliderVertical",
dojo.widget.html.Slider,
{
widgetType: "SliderVertical",
value: 0,
isEnableX: false,
templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderVertical.html"),
postMixInProperties: function(){
this.initialValueY = this.value;
},
// wrapper for getValueY
getValue: function () {
return this.getValueY ();
},
// wrapper for setValueY
setValue: function (value) {
this.setValueY (value);
},
onDragMove: function(){
if(this.activeDrag){
this.onValueChanged(this.getValue());
}
},
onDragEnd: function(){
if(!this.activeDrag){
this.onValueChanged(this.getValue());
}
},
onClick: function(){
this.onValueChanged(this.getValue());
},
onValueChanged: function(value){
this.value=value;
}
}
);
/* ------------------------------------------------------------------------- */
/**
* This class extends the HtmlDragMoveSource class to provide
* features for the slider handle.
*/
dojo.declare (
"dojo.widget.html.SliderDragMoveSource",
dojo.dnd.HtmlDragMoveSource,
{
isDragInProgress: false,
slider: null,
/** Setup the handle for drag
* Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */
onDragStart: function (e) {
this.isDragInProgress = true;
this.constrainToContainer = true;
var dragObj = this.createDragMoveObject ();
var constraints = null;
dojo.event.connect (dragObj, "onDragMove", this, "onDragMove");
return dragObj;
},
onDragMove: function (e) {
// placeholder to enable event connection
},
createDragMoveObject: function () {
//dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider);
var dragObj = new dojo.widget.html.SliderDragMoveObject (this.dragObject, this.type);
dragObj.slider = this.slider;
// this code copied from dojo.dnd.HtmlDragSource#onDragStart
if (this.dragClass) {
dragObj.dragClass = this.dragClass;
}
if (this.constrainToContainer) {
dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
}
return dragObj;
},
setParent: function (slider) {
this.slider = slider;
},
calcValueSizeX: function () {
var dragObj = this.createDragMoveObject ();
dragObj.containingBlockPosition = dragObj.domNode.offsetParent ?
dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
var constraints = dragObj.getConstraints ();
return (constraints.maxX - constraints.minX) / this.slider.valuesX;
},
calcValueSizeY: function () {
var dragObj = this.createDragMoveObject ();
dragObj.containingBlockPosition = dragObj.domNode.offsetParent ?
dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
var constraints = dragObj.getConstraints ();
return (constraints.maxY - constraints.minY) / this.slider.valuesY;
}
});
/* ------------------------------------------------------------------------- */
/**
* This class extends the HtmlDragMoveObject class to provide
* features for the slider handle.
*/
dojo.declare (
"dojo.widget.html.SliderDragMoveObject",
dojo.dnd.HtmlDragMoveObject,
{
// reference to dojo.widget.html.Slider
slider: null,
/** Moves the node to follow the mouse.
* Extends functon HtmlDragObject by adding functionality to snap handle
* to a discrete value */
onDragMove: function (e) {
if (this.slider.isEnableX && 0.0 == this.slider.valueSizeX) {
this.slider.valueSizeX = (this.constraints.maxX - this.constraints.minX) / this.slider.valuesX;
}
if (this.slider.isEnableY && 0.0 == this.slider.valueSizeY) {
this.slider.valueSizeY = (this.constraints.maxY - this.constraints.minY) / this.slider.valuesY;
}
this.updateDragOffset ();
var x = this.dragOffset.x + e.pageX;
var y = this.dragOffset.y + e.pageY;
if (this.constrainToContainer) {
if (x < this.constraints.minX) { x = this.constraints.minX; }
if (y < this.constraints.minY) { y = this.constraints.minY; }
if (x > this.constraints.maxX) { x = this.constraints.maxX; }
if (y > this.constraints.maxY) { y = this.constraints.maxY; }
}
if (this.slider.isEnableX) {
var selectedValue = 0;
if (x > 0) {
selectedValue = Math.round (x / this.slider.valueSizeX);
}
// dojo.debug ("x = " + x + ", valueSize = " + valueSize
// + ", selectedValue = " + selectedValue);
x = (selectedValue * this.slider.valueSizeX);
}
if (this.slider.isEnableY) {
var selectedValue = 0;
if (y > 0) {
selectedValue = Math.round (y / this.slider.valueSizeY);
}
y = (selectedValue * this.slider.valueSizeY);
}
this.setAbsolutePosition (x, y);
}
});

View file

@ -0,0 +1,582 @@
/*
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.html.SortableTable");
dojo.require("dojo.lang");
dojo.require("dojo.date");
dojo.require("dojo.html");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.SortableTable");
dojo.widget.html.SortableTable=function(){
// summary
// Constructor for the SortableTable widget
dojo.widget.SortableTable.call(this);
dojo.widget.HtmlWidget.call(this);
this.headClass="";
this.tbodyClass="";
this.headerClass="";
this.headerSortUpClass="selected";
this.headerSortDownClass="selected";
this.rowClass="";
this.rowAlternateClass="alt";
this.rowSelectedClass="selected";
this.columnSelected="sorted-column";
};
dojo.inherits(dojo.widget.html.SortableTable, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.SortableTable, {
templatePath:null,
templateCssPath:null,
getTypeFromString:function(/* string */ s){
// summary
// Find the constructor that matches param s by searching through the entire object tree.
var parts=s.split("."),i=0,obj=dj_global;
do{obj=obj[parts[i++]];}while(i<parts.length&&obj);
return(obj!=dj_global)?obj:null; // function
},
compare:function(/* object */ o1, /* object */ o2){
// summary
// Compare two objects using a shallow property compare
for(var p in o1){
if(!(p in o2)) return false; // boolean
if(o1[p].valueOf()!=o2[p].valueOf()) return false; // boolean
}
return true; // boolean
},
isSelected:function(/* object */ o){
// summary
// checked to see if the passed object is in the current selection.
for(var i=0;i<this.selected.length;i++){
if(this.compare(this.selected[i],o)){
return true; // boolean
}
}
return false; // boolean
},
removeFromSelected:function(/* object */ o){
// summary
// remove the passed object from the current selection.
var idx=-1;
for(var i=0;i<this.selected.length;i++){
if(this.compare(this.selected[i],o)){
idx=i;
break;
}
}
if(idx>=0){
this.selected.splice(idx,1);
}
},
getSelection:function(){
// summary
// return the array of currently selected objects (JSON format)
return this.selected; // array
},
getValue:function(){
// summary
// return a comma-delimited list of selected valueFields.
var a=[];
for(var i=0;i<this.selected.length;i++){
if (this.selected[i][this.valueField]){
a.push(this.selected[i][this.valueField]);
}
}
return a.join(); // string
},
reset:function(){
// summary
// completely resets the internal representations.
this.columns=[];
this.data=[];
this.resetSelections(this.domNode.getElementsByTagName("tbody")[0]);
},
resetSelections:function(/* HTMLTableBodyElement */ body){
this.selected=[];
var idx=0;
var rows=body.getElementsByTagName("tr");
for(var i=0; i<rows.length; i++){
if(rows[i].parentNode==body){
rows[i].removeAttribute("selected");
if(this.enableAlternateRows&&idx%2==1){
rows[i].className=this.rowAlternateClass;
}else{
rows[i].className="";
}
idx++;
}
}
},
getObjectFromRow:function(/* HTMLTableRowElement */ row){
// summary
// creates a JSON object based on the passed row
var cells=row.getElementsByTagName("td");
var o={};
for(var i=0; i<this.columns.length;i++){
if(this.columns[i].sortType=="__markup__"){
// FIXME: should we parse this instead? Because if the user may not get back the markup they put in...
o[this.columns[i].getField()]=cells[i].innerHTML;
}else{
var text=dojo.html.renderedTextContent(cells[i]);
var val=new (this.columns[i].getType())(text);
o[this.columns[i].getField()]=val;
}
}
if(dojo.html.hasAttribute(row,"value")){
o[this.valueField]=dojo.html.getAttribute(row,"value");
}
return o; // object
},
setSelectionByRow:function(/* HTMLTableElementRow */ row){
// summary
// create the selection object based on the passed row, makes sure it's unique.
// note that you need to call render manually (because of multi-select operations)
var o=this.getObjectFromRow(row);
var b=false;
for(var i=0;i<this.selected.length;i++){
if(this.compare(this.selected[i], o)){
b=true;
break;
}
}
if(!b){
this.selected.push(o);
}
},
parseColumns:function(/* HTMLTableHeadElement */ node){
// summary
// parses the passed element to create column objects
this.reset();
var row=node.getElementsByTagName("tr")[0];
var cells=row.getElementsByTagName("td");
if (cells.length==0) cells=row.getElementsByTagName("th");
for(var i=0; i<cells.length; i++){
var o={
field:null,
format:null,
noSort:false,
sortType:"String",
dataType:String,
sortFunction:null,
label:null,
align:"left",
valign:"middle",
getField:function(){ return this.field||this.label; },
getType:function(){ return this.dataType; }
};
// presentation attributes
if(dojo.html.hasAttribute(cells[i], "align")){
o.align=dojo.html.getAttribute(cells[i],"align");
}
if(dojo.html.hasAttribute(cells[i], "valign")){
o.valign=dojo.html.getAttribute(cells[i],"valign");
}
// sorting features.
if(dojo.html.hasAttribute(cells[i], "nosort")){
o.noSort=dojo.html.getAttribute(cells[i],"nosort")=="true";
}
if(dojo.html.hasAttribute(cells[i], "sortusing")){
var trans=dojo.html.getAttribute(cells[i],"sortusing");
var f=this.getTypeFromString(trans);
if (f!=null && f!=window && typeof(f)=="function")
o.sortFunction=f;
}
if(dojo.html.hasAttribute(cells[i], "field")){
o.field=dojo.html.getAttribute(cells[i],"field");
}
if(dojo.html.hasAttribute(cells[i], "format")){
o.format=dojo.html.getAttribute(cells[i],"format");
}
if(dojo.html.hasAttribute(cells[i], "dataType")){
var sortType=dojo.html.getAttribute(cells[i],"dataType");
if(sortType.toLowerCase()=="html"||sortType.toLowerCase()=="markup"){
o.sortType="__markup__"; // always convert to "__markup__"
o.noSort=true;
}else{
var type=this.getTypeFromString(sortType);
if(type){
o.sortType=sortType;
o.dataType=type;
}
}
}
o.label=dojo.html.renderedTextContent(cells[i]);
this.columns.push(o);
// check to see if there's a default sort, and set the properties necessary
if(dojo.html.hasAttribute(cells[i], "sort")){
this.sortIndex=i;
var dir=dojo.html.getAttribute(cells[i], "sort");
if(!isNaN(parseInt(dir))){
dir=parseInt(dir);
this.sortDirection=(dir!=0)?1:0;
}else{
this.sortDirection=(dir.toLowerCase()=="desc")?1:0;
}
}
}
},
parseData:function(/* array */ data){
// summary
// Parse the passed JSON data structure, and cast based on columns.
this.data=[];
this.selected=[];
for(var i=0; i<data.length; i++){
var o={}; // new data object.
for(var j=0; j<this.columns.length; j++){
var field=this.columns[j].getField();
if(this.columns[j].sortType=="__markup__"){
o[field]=String(data[i][field]);
}else{
var type=this.columns[j].getType();
var val=data[i][field];
var t=this.columns[j].sortType.toLowerCase();
if(val){
o[field]=new type(val);
}else{
o[field]=new type(); // let it use the default.
}
}
}
// check for the valueField if not already parsed.
if(data[i][this.valueField]&&!o[this.valueField]){
o[this.valueField]=data[i][this.valueField];
}
this.data.push(o);
}
},
parseDataFromTable:function(/* HTMLTableBodyElement */ tbody){
// summary
// parses the data in the tbody of a table to create a set of objects.
// Will add objects to this.selected if an attribute 'selected="true"' is present on the row.
this.data=[];
this.selected=[];
var rows=tbody.getElementsByTagName("tr");
for(var i=0; i<rows.length; i++){
if(dojo.html.getAttribute(rows[i],"ignoreIfParsed")=="true"){
continue;
}
var o={}; // new data object.
var cells=rows[i].getElementsByTagName("td");
for(var j=0; j<this.columns.length; j++){
var field=this.columns[j].getField();
if(this.columns[j].sortType=="__markup__"){
// FIXME: parse this?
o[field]=cells[j].innerHTML;
}else{
var type=this.columns[j].getType();
var val=dojo.html.renderedTextContent(cells[j]); // should be the same index as the column.
if (val) o[field]=new type(val);
else o[field]=new type(); // let it use the default.
}
}
if(dojo.html.hasAttribute(rows[i],"value")&&!o[this.valueField]){
o[this.valueField]=dojo.html.getAttribute(rows[i],"value");
}
// FIXME: add code to preserve row attributes in __metadata__ field?
this.data.push(o);
// add it to the selections if selected="true" is present.
if(dojo.html.getAttribute(rows[i],"selected")=="true"){
this.selected.push(o);
}
}
},
showSelections:function(){
var body=this.domNode.getElementsByTagName("tbody")[0];
var rows=body.getElementsByTagName("tr");
var idx=0;
for(var i=0; i<rows.length; i++){
if(rows[i].parentNode==body){
if(dojo.html.getAttribute(rows[i],"selected")=="true"){
rows[i].className=this.rowSelectedClass;
} else {
if(this.enableAlternateRows&&idx%2==1){
rows[i].className=this.rowAlternateClass;
}else{
rows[i].className="";
}
}
idx++;
}
}
},
render:function(bDontPreserve){
// summary
// renders the table to the browser
var data=[];
var body=this.domNode.getElementsByTagName("tbody")[0];
if(!bDontPreserve){
// rebuild data and selection
this.parseDataFromTable(body);
}
// clone this.data for sorting purposes.
for(var i=0; i<this.data.length; i++){
data.push(this.data[i]);
}
var col=this.columns[this.sortIndex];
if(!col.noSort){
var field=col.getField();
if(col.sortFunction){
var sort=col.sortFunction;
}else{
var sort=function(a,b){
if (a[field]>b[field]) return 1;
if (a[field]<b[field]) return -1;
return 0;
}
}
data.sort(sort);
if(this.sortDirection!=0) data.reverse();
}
// build the table and pop it in.
while(body.childNodes.length>0) body.removeChild(body.childNodes[0]);
for(var i=0; i<data.length;i++){
var row=document.createElement("tr");
dojo.html.disableSelection(row);
if (data[i][this.valueField]){
row.setAttribute("value",data[i][this.valueField]);
}
if(this.isSelected(data[i])){
row.className=this.rowSelectedClass;
row.setAttribute("selected","true");
} else {
if(this.enableAlternateRows&&i%2==1){
row.className=this.rowAlternateClass;
}
}
for(var j=0;j<this.columns.length;j++){
var cell=document.createElement("td");
cell.setAttribute("align", this.columns[j].align);
cell.setAttribute("valign", this.columns[j].valign);
dojo.html.disableSelection(cell);
if(this.sortIndex==j){
cell.className=this.columnSelected;
}
if(this.columns[j].sortType=="__markup__"){
cell.innerHTML=data[i][this.columns[j].getField()];
for(var k=0; k<cell.childNodes.length; k++){
var node=cell.childNodes[k];
if(node&&node.nodeType==dojo.html.ELEMENT_NODE){
dojo.html.disableSelection(node);
}
}
}else{
if(this.columns[j].getType()==Date){
var format=this.defaultDateFormat;
if(this.columns[j].format) format=this.columns[j].format;
cell.appendChild(document.createTextNode(dojo.date.format(data[i][this.columns[j].getField()], format)));
}else{
cell.appendChild(document.createTextNode(data[i][this.columns[j].getField()]));
}
}
row.appendChild(cell);
}
body.appendChild(row);
dojo.event.connect(row, "onclick", this, "onUISelect");
}
// if minRows exist.
var minRows=parseInt(this.minRows);
if (!isNaN(minRows) && minRows>0 && data.length<minRows){
var mod=0;
if(data.length%2==0) mod=1;
var nRows=minRows-data.length;
for(var i=0; i<nRows; i++){
var row=document.createElement("tr");
row.setAttribute("ignoreIfParsed","true");
if(this.enableAlternateRows&&i%2==mod){
row.className=this.rowAlternateClass;
}
for(var j=0;j<this.columns.length;j++){
var cell=document.createElement("td");
cell.appendChild(document.createTextNode("\u00A0"));
row.appendChild(cell);
}
body.appendChild(row);
}
}
},
// the following the user can override.
onSelect:function(/* DomEvent */ e){
// summary
// empty function for the user to attach code to, fired by onUISelect
},
onUISelect:function(/* DomEvent */ e){
// summary
// fired when a user selects a row
var row=dojo.html.getParentByType(e.target,"tr");
var body=dojo.html.getParentByType(row,"tbody");
if(this.enableMultipleSelect){
if(e.metaKey||e.ctrlKey){
if(this.isSelected(this.getObjectFromRow(row))){
this.removeFromSelected(this.getObjectFromRow(row));
row.removeAttribute("selected");
}else{
// push onto the selection stack.
this.setSelectionByRow(row);
row.setAttribute("selected","true");
}
}else if(e.shiftKey){
// the tricky one. We need to figure out the *last* selected row above,
// and select all the rows in between.
var startRow;
var rows=body.getElementsByTagName("tr");
// if there's a selection above, we go with that first.
for(var i=0;i<rows.length;i++){
if(rows[i].parentNode==body){
if(rows[i]==row) break;
if(dojo.html.getAttribute(rows[i],"selected")=="true"){
startRow=rows[i];
}
}
}
// if there isn't a selection above, we continue with a selection below.
if(!startRow){
startRow=row;
for(;i<rows.length;i++){
if(dojo.html.getAttribute(rows[i],"selected")=="true"){
row=rows[i];
break;
}
}
}
this.resetSelections(body);
if(startRow==row){
// this is the only selection
row.setAttribute("selected","true");
this.setSelectionByRow(row);
}else{
var doSelect=false;
for(var i=0; i<rows.length; i++){
if(rows[i].parentNode==body){
rows[i].removeAttribute("selected");
if(rows[i]==startRow){
doSelect=true;
}
if(doSelect){
this.setSelectionByRow(rows[i]);
rows[i].setAttribute("selected","true");
}
if(rows[i]==row){
doSelect=false;
}
}
}
}
}else{
// reset the selection
this.resetSelections(body);
row.setAttribute("selected","true");
this.setSelectionByRow(row);
}
}else{
// reset the data selection and go.
this.resetSelections(body);
row.setAttribute("selected","true");
this.setSelectionByRow(row);
}
this.showSelections();
this.onSelect(e);
e.stopPropagation();
e.preventDefault();
},
onHeaderClick:function(/* DomEvent */ e){
// summary
// Main handler function for each header column click.
var oldIndex=this.sortIndex;
var oldDirection=this.sortDirection;
var source=e.target;
var row=dojo.html.getParentByType(source,"tr");
var cellTag="td";
if(row.getElementsByTagName(cellTag).length==0) cellTag="th";
var headers=row.getElementsByTagName(cellTag);
var header=dojo.html.getParentByType(source,cellTag);
for(var i=0; i<headers.length; i++){
if(headers[i]==header){
if(i!=oldIndex){
// new col.
this.sortIndex=i;
this.sortDirection=0;
headers[i].className=this.headerSortDownClass
}else{
this.sortDirection=(oldDirection==0)?1:0;
if(this.sortDirection==0){
headers[i].className=this.headerSortDownClass;
}else{
headers[i].className=this.headerSortUpClass;
}
}
}else{
// reset the header class.
headers[i].className=this.headerClass;
}
}
this.render();
},
postCreate:function(){
// summary
// overridden from HtmlWidget, initializes and renders the widget.
var thead=this.domNode.getElementsByTagName("thead")[0];
if(this.headClass.length>0){
thead.className=this.headClass;
}
// disable selections
dojo.html.disableSelection(this.domNode);
// parse the columns.
this.parseColumns(thead);
// attach header handlers.
var header="td";
if(thead.getElementsByTagName(header).length==0) header="th";
var headers=thead.getElementsByTagName(header);
for(var i=0; i<headers.length; i++){
if(!this.columns[i].noSort){
dojo.event.connect(headers[i], "onclick", this, "onHeaderClick");
}
if(this.sortIndex==i){
if(this.sortDirection==0){
headers[i].className=this.headerSortDownClass;
}else{
headers[i].className=this.headerSortUpClass;
}
}
}
// parse the tbody element and re-render it.
var tbody=this.domNode.getElementsByTagName("tbody")[0];
if (this.tbodyClass.length>0) {
tbody.className=this.tbodyClass;
}
this.parseDataFromTable(tbody);
this.render(true);
}
});

View file

@ -0,0 +1,383 @@
/*
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.html.Spinner");
dojo.require("dojo.widget.Spinner");
dojo.require("dojo.widget.Manager.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.string");
dojo.require("dojo.widget.html.stabile");
dojo.widget.html.Spinner = function(){
dojo.widget.Spinner.call(this);
dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.Spinner, dojo.widget.HtmlWidget);
// copied from superclass since we can't really over-ride via prototype
dojo.lang.extend(dojo.widget.html.Spinner, dojo.widget.Spinner.defaults);
dojo.lang.extend(dojo.widget.html.Spinner, {
name: "", // clone in the name from the DOM node
inputNode: null,
upArrowNode: null,
downArrowNode: null,
absNode: null,
relNode: null,
innerRelNode: null,
spacerNode: null,
inputWidgetId: "",
inputWidget: null,
typamaticTimer: null,
typamaticFunction: null,
defaultTimeout: 500,
currentTimeout: this.defaultTimeout,
eventCount: 0,
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.css"),
setValue: function(value){
this.inputWidget.setValue(value);
this.inputWidget.adjustValue(0);
dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
},
getValue: function(){
return this.inputWidget.getValue();
},
getState: function(){
return {value: this.getValue()};
},
setState: function(state){
this.setValue(state.value);
},
// does the keyboard related stuff
_handleKeyEvents: function(evt){
var k = dojo.event.browser.keys;
var keyCode = evt.keyCode;
switch(keyCode){
case k.KEY_DOWN_ARROW:
dojo.event.browser.stopEvent(evt);
this.downArrowPressed(evt);
return;
case k.KEY_UP_ARROW:
dojo.event.browser.stopEvent(evt);
this.upArrowPressed(evt);
return;
}
this.eventCount++;
},
onKeyDown: function(evt){
// IE needs to stop keyDown others need to stop keyPress
if(!document.createEvent){ // only IE
this._handleKeyEvents(evt);
}
},
onKeyPress: function(evt){
if(document.createEvent){ // never IE
this._handleKeyEvents(evt);
}
},
fillInTemplate: function(args, frag){
var source = this.getFragNodeRef(frag);
dojo.html.copyStyle(this.domNode, source);
},
resizeUpArrow: function(){
var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
if(newh==0){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeUpArrow", 100);
return;
}
var oldh = this.upArrowNode.height;
if(oldh==0){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeUpArrow", 100);
return;
}
var ratio = newh / oldh;
this.upArrowNode.width=Math.floor(this.upArrowNode.width * ratio);
this.upArrowNode.height=newh;
},
resizeDownArrow: function(){
var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
if(newh==0){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeDownArrow", 100);
return;
}
var oldh = this.downArrowNode.height;
if(oldh==0){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeDownArrow", 100);
return;
}
var ratio = newh / oldh;
this.downArrowNode.width=Math.floor(this.downArrowNode.width * ratio);
this.downArrowNode.height=newh;
},
resizeSpacer: function(){
var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
if( newh==0 ){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeSpacer", 100);
return;
}
var oldh = this.downArrowNode.height;
if( oldh==0 ){
// need more time to calculate size
dojo.lang.setTimeout(this, "resizeSpacer", 100);
return;
}
var ratio = newh / oldh;
this.spacerNode.width=Math.floor(this.spacerNode.width * ratio);
this.spacerNode.height=newh;
},
_pressButton: function(node){
with(node.style){
borderRight = "0px";
borderBottom = "0px";
borderLeft = "1px solid black";
borderTop = "1px solid black";
}
},
_releaseButton: function(node){
with(node.style){
borderLeft = "0px";
borderTop = "0px";
borderRight = "1px solid gray";
borderBottom = "1px solid gray";
}
},
downArrowPressed: function(evt){
if(typeof evt != "number"){
if(this.typamaticTimer != null){
if(this.typamaticFunction == this.downArrowPressed){
return;
}
clearTimeout(this.typamaticTimer);
}
this._releaseButton(this.upArrowNode);
this.eventCount++;
this.typamaticTimer = null;
this.currentTimeout = this.defaultTimeout;
}else if (evt != this.eventCount){
this._releaseButton(this.downArrowNode);
return;
}
this._pressButton(this.downArrowNode);
this.setCursorX(this.inputWidget.adjustValue(-1,this.getCursorX()));
this.typamaticFunction = this.downArrowPressed;
this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.downArrowPressed(this.eventCount);}), this.currentTimeout);
this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
},
upArrowPressed: function(evt){
if(typeof evt != "number"){
if(this.typamaticTimer != null){
if(this.typamaticFunction == this.upArrowPressed){
return;
}
clearTimeout(this.typamaticTimer);
}
this._releaseButton(this.downArrowNode);
this.eventCount++;
this.typamaticTimer = null;
this.currentTimeout = this.defaultTimeout;
}else if(evt != this.eventCount) {
this._releaseButton(this.upArrowNode);
return;
}
this._pressButton(this.upArrowNode);
this.setCursorX(this.inputWidget.adjustValue(+1,this.getCursorX()));
this.typamaticFunction = this.upArrowPressed;
this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.upArrowPressed(this.eventCount);}), this.currentTimeout);
this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
},
arrowReleased: function(evt){
this.inputNode.focus();
if(evt.keyCode && evt.keyCode != null){
var keyCode = evt.keyCode;
var k = dojo.event.browser.keys;
switch(keyCode){
case k.KEY_DOWN_ARROW:
case k.KEY_UP_ARROW:
dojo.event.browser.stopEvent(evt);
break;
}
}
this._releaseButton(this.upArrowNode);
this._releaseButton(this.downArrowNode);
this.eventCount++;
if(this.typamaticTimer != null){
clearTimeout(this.typamaticTimer);
}
this.typamaticTimer = null;
this.currentTimeout = this.defaultTimeout;
},
mouseWheeled: function(evt) {
var scrollAmount = 0;
if(typeof evt.wheelDelta == 'number'){ // IE
scrollAmount = evt.wheelDelta;
}else if (typeof evt.detail == 'number'){ // Mozilla+Firefox
scrollAmount = -evt.detail;
}
if(scrollAmount > 0){
this.upArrowPressed(evt);
this.arrowReleased(evt);
}else if (scrollAmount < 0){
this.downArrowPressed(evt);
this.arrowReleased(evt);
}
},
getCursorX: function(){
var x = -1;
try{
this.inputNode.focus();
if (typeof this.inputNode.selectionEnd == "number"){
x = this.inputNode.selectionEnd;
}else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange().duplicate();
if(range.parentElement() == this.inputNode){
range.moveStart('textedit', -1);
x = range.text.length;
}
}
}catch(e){ /* squelch! */ }
return x;
},
setCursorX: function(x){
try{
this.inputNode.focus();
if(!x){ x = 0 }
if(typeof this.inputNode.selectionEnd == "number"){
this.inputNode.selectionEnd = x;
}else if(this.inputNode.createTextRange){
var range = this.inputNode.createTextRange();
range.collapse(true);
range.moveEnd('character', x);
range.moveStart('character', x);
range.select();
}
}catch(e){ /* squelch! */ }
},
postCreate: function(){
this.domNode.style.display="none";
if((typeof this.inputWidgetId != 'string')||(this.inputWidgetId.length == 0)){
var w=dojo.widget.manager.getAllWidgets();
for(var i=w.length-1; i>=0; i--){
if(w[i].adjustValue){
this.inputWidget = w[i];
break;
}
}
}else{
this.inputWidget = dojo.widget.getWidgetById(this.inputWidgetId);
}
if(typeof this.inputWidget != 'object'){
dojo.lang.setTimeout(this, "postCreate", 100);
return;
}
var widgetNode = this.inputWidget.domNode;
var inputNodes = widgetNode.getElementsByTagName('INPUT');
this.inputNode = inputNodes[0];
/*
// unlink existing dom nodes from domNode
this.downArrowNode = dojo.dom.removeNode(this.downArrowNode);
this.upArrowNode = dojo.dom.removeNode(this.upArrowNode);
this.spacerNode = dojo.dom.removeNode(this.spacerNode);
this.innerRelNode = dojo.dom.removeNode(this.innerRelNode);
this.absNode = dojo.dom.removeNode(this.absNode);
this.relNode = dojo.dom.removeNode(this.relNode);
*/
// create a disconnected node
this.innerRelNode.appendChild(this.upArrowNode);
this.innerRelNode.appendChild(this.downArrowNode);
this.absNode.appendChild(this.innerRelNode);
this.relNode.appendChild(this.absNode);
this.relNode.appendChild(this.spacerNode);
dojo.event.connect(this.inputNode, "onkeypress", this, "onKeyPress");
dojo.event.connect(this.inputNode, "onkeydown", this, "onKeyDown");
dojo.event.connect(this.inputNode, "onkeyup", this, "arrowReleased");
dojo.event.connect(this.downArrowNode, "onmousedown", this, "downArrowPressed");
dojo.event.connect(this.downArrowNode, "onmouseup", this, "arrowReleased");
dojo.event.connect(this.upArrowNode, "onmousedown", this, "upArrowPressed");
dojo.event.connect(this.upArrowNode, "onmouseup", this, "arrowReleased");
if(this.inputNode.addEventListener){
// FIXME: why not use dojo.event.connect() to DOMMouseScroll here?
this.inputNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "mouseWheeled"), false); // Mozilla + Firefox + Netscape
}else{
dojo.event.connect(this.inputNode, "onmousewheel", this, "mouseWheeled"); // IE + Safari
}
this.resizeDownArrow();
this.resizeUpArrow();
this.resizeSpacer();
// make sure the disconnected node will fit right next to the INPUT tag w/o any interference
dojo.html.copyStyle(this.relNode, this.inputNode);
with(this.relNode.style){
display = "inline";
position = "relative";
backgroundColor = "";
marginLeft = "-1px";
paddingLeft = "0";
}
this.inputNode.style.marginRight = "0px";
this.inputNode.style.paddingRight = "0px";
// add the disconnected node right after the INPUT tag
dojo.dom.insertAfter(this.relNode, this.inputNode, false);
this.domNode = dojo.dom.removeNode(this.domNode);
// realign the spinner vertically in case there's a slight difference
var absOffset = dojo.html.getAbsoluteY(this.relNode,true)-dojo.html.getAbsoluteY(this.absNode,true);
this.absNode.style.top = absOffset-dojo.style.getBorderExtent(this.inputNode, "top")+"px";
var s = dojo.widget.html.stabile.getState(this.widgetId);
this.setValue(this.getValue());
if(s){
this.setState(s);
}
}
});

View file

@ -0,0 +1,85 @@
/*
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.html.TaskBar");
dojo.provide("dojo.widget.html.TaskBarItem");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.FloatingPane");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.event");
// Icon associated w/a floating pane
dojo.widget.html.TaskBarItem = function(){
dojo.widget.TaskBarItem.call(this);
dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.TaskBarItem, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.TaskBarItem, {
// constructor arguments
iconSrc: '',
caption: 'Untitled',
window: null,
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBarItemTemplate.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBar.css"),
fillInTemplate: function() {
if ( this.iconSrc != '' ) {
var img = document.createElement("img");
img.src = this.iconSrc;
this.domNode.appendChild(img);
}
this.domNode.appendChild(document.createTextNode(this.caption));
dojo.html.disableSelection(this.domNode);
},
postCreate: function() {
this.window=dojo.widget.getWidgetById(this.windowId);
this.window.explodeSrc = this.domNode;
dojo.event.connect(this.window, "destroy", this, "destroy")
},
onClick: function() {
this.window.show();
}
});
// Collection of widgets in a bar, like Windows task bar
dojo.widget.html.TaskBar = function(){
dojo.widget.html.FloatingPane.call(this);
dojo.widget.TaskBar.call(this);
this._addChildStack = [];
}
dojo.inherits(dojo.widget.html.TaskBar, dojo.widget.html.FloatingPane);
dojo.lang.extend(dojo.widget.html.TaskBar, {
resizable: false,
titleBarDisplay: "none",
addChild: function(child) {
if(!this.containerNode){
this._addChildStack.push(child);
}else if(this._addChildStack.length > 0){
var oarr = this._addChildStack;
this._addChildStack = [];
dojo.lang.forEach(oarr, this.addChild, this);
}
var tbi = dojo.widget.createWidget("TaskBarItem",
{ windowId: child.widgetId,
caption: child.title,
iconSrc: child.iconSrc
});
dojo.widget.html.TaskBar.superclass.addChild.call(this,tbi);
}
});

View file

@ -0,0 +1,249 @@
/*
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.html.TimePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.TimePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.date");
dojo.require("dojo.html");
dojo.widget.html.TimePicker = function(){
dojo.widget.TimePicker.call(this);
dojo.widget.HtmlWidget.call(this);
var _this = this;
// selected time, JS Date object
this.time = "";
// set following flag to true if a default time should be set
this.useDefaultTime = false;
// set the following to true to set default minutes to current time, false to // use zero
this.useDefaultMinutes = false;
// rfc 3339 date
this.storedTime = "";
// time currently selected in the UI, stored in hours, minutes, seconds in the format that will be actually displayed
this.currentTime = {};
this.classNames = {
selectedTime: "selectedItem"
}
this.any = "any"
// dom node indecies for selected hour, minute, amPm, and "any time option"
this.selectedTime = {
hour: "",
minute: "",
amPm: "",
anyTime: false
}
// minutes are ordered as follows: ["12", "6", "1", "7", "2", "8", "3", "9", "4", "10", "5", "11"]
this.hourIndexMap = ["", 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11, 0];
// minutes are ordered as follows: ["00", "30", "05", "35", "10", "40", "15", "45", "20", "50", "25", "55"]
this.minuteIndexMap = [0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11];
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlTimePicker.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlTimePicker.css");
this.fillInTemplate = function(){
this.initData();
this.initUI();
}
this.initData = function() {
// FIXME: doesn't currently validate the time before trying to set it
// Determine the date/time from stored info, or by default don't
// have a set time
// FIXME: should normalize against whitespace on storedTime... for now
// just a lame hack
if(this.storedTime.indexOf("T")!=-1 && this.storedTime.split("T")[1] && this.storedTime!=" " && this.storedTime.split("T")[1]!="any") {
this.time = dojo.widget.TimePicker.util.fromRfcDateTime(this.storedTime, this.useDefaultMinutes, this.selectedTime.anyTime);
} else if (this.useDefaultTime) {
this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes, this.selectedTime.anyTime);
} else {
this.selectedTime.anyTime = true;
this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", 0, 1);
}
}
this.initUI = function() {
// set UI to match the currently selected time
if(!this.selectedTime.anyTime && this.time) {
var amPmHour = dojo.widget.TimePicker.util.toAmPmHour(this.time.getHours());
var hour = amPmHour[0];
var isAm = amPmHour[1];
var minute = this.time.getMinutes();
var minuteIndex = parseInt(minute/5);
this.onSetSelectedHour(this.hourIndexMap[hour]);
this.onSetSelectedMinute(this.minuteIndexMap[minuteIndex]);
this.onSetSelectedAmPm(isAm);
} else {
this.onSetSelectedAnyTime();
}
}
this.setDateTime = function(rfcDate) {
this.storedTime = rfcDate;
}
this.onClearSelectedHour = function(evt) {
this.clearSelectedHour();
}
this.onClearSelectedMinute = function(evt) {
this.clearSelectedMinute();
}
this.onClearSelectedAmPm = function(evt) {
this.clearSelectedAmPm();
}
this.onClearSelectedAnyTime = function(evt) {
this.clearSelectedAnyTime();
if(this.selectedTime.anyTime) {
this.selectedTime.anyTime = false;
this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes);
this.initUI();
}
}
this.clearSelectedHour = function() {
var hourNodes = this.hourContainerNode.getElementsByTagName("td");
for (var i=0; i<hourNodes.length; i++) {
dojo.html.setClass(hourNodes.item(i), "");
}
}
this.clearSelectedMinute = function() {
var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
for (var i=0; i<minuteNodes.length; i++) {
dojo.html.setClass(minuteNodes.item(i), "");
}
}
this.clearSelectedAmPm = function() {
var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
for (var i=0; i<amPmNodes.length; i++) {
dojo.html.setClass(amPmNodes.item(i), "");
}
}
this.clearSelectedAnyTime = function() {
dojo.html.setClass(this.anyTimeContainerNode, "anyTimeContainer");
}
this.onSetSelectedHour = function(evt) {
this.onClearSelectedAnyTime();
this.onClearSelectedHour();
this.setSelectedHour(evt);
this.onSetTime();
}
this.setSelectedHour = function(evt) {
if(evt && evt.target) {
dojo.html.setClass(evt.target, this.classNames.selectedTime);
this.selectedTime["hour"] = evt.target.innerHTML;
} else if (!isNaN(evt)) {
var hourNodes = this.hourContainerNode.getElementsByTagName("td");
if(hourNodes.item(evt)) {
dojo.html.setClass(hourNodes.item(evt), this.classNames.selectedTime);
this.selectedTime["hour"] = hourNodes.item(evt).innerHTML;
}
}
this.selectedTime.anyTime = false;
}
this.onSetSelectedMinute = function(evt) {
this.onClearSelectedAnyTime();
this.onClearSelectedMinute();
this.setSelectedMinute(evt);
this.selectedTime.anyTime = false;
this.onSetTime();
}
this.setSelectedMinute = function(evt) {
if(evt && evt.target) {
dojo.html.setClass(evt.target, this.classNames.selectedTime);
this.selectedTime["minute"] = evt.target.innerHTML;
} else if (!isNaN(evt)) {
var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
if(minuteNodes.item(evt)) {
dojo.html.setClass(minuteNodes.item(evt), this.classNames.selectedTime);
this.selectedTime["minute"] = minuteNodes.item(evt).innerHTML;
}
}
}
this.onSetSelectedAmPm = function(evt) {
this.onClearSelectedAnyTime();
this.onClearSelectedAmPm();
this.setSelectedAmPm(evt);
this.selectedTime.anyTime = false;
this.onSetTime();
}
this.setSelectedAmPm = function(evt) {
if(evt && evt.target) {
dojo.html.setClass(evt.target, this.classNames.selectedTime);
this.selectedTime["amPm"] = evt.target.innerHTML;
} else {
evt = evt ? 0 : 1;
var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
if(amPmNodes.item(evt)) {
dojo.html.setClass(amPmNodes.item(evt), this.classNames.selectedTime);
this.selectedTime["amPm"] = amPmNodes.item(evt).innerHTML;
}
}
}
this.onSetSelectedAnyTime = function(evt) {
this.onClearSelectedHour();
this.onClearSelectedMinute();
this.onClearSelectedAmPm();
this.setSelectedAnyTime();
this.onSetTime();
}
this.setSelectedAnyTime = function(evt) {
this.selectedTime.anyTime = true;
dojo.html.setClass(this.anyTimeContainerNode, this.classNames.selectedTime + " " + "anyTimeContainer");
}
this.onClick = function(evt) {
dojo.event.browser.stopEvent(evt)
}
this.onSetTime = function() {
if(this.selectedTime.anyTime) {
this.time = new Date();
var tempDateTime = dojo.widget.TimePicker.util.toRfcDateTime(this.time);
this.setDateTime(tempDateTime.split("T")[0]);
} else {
var hour = 12;
var minute = 0;
var isAm = false;
if(this.selectedTime["hour"]) {
hour = parseInt(this.selectedTime["hour"], 10);
}
if(this.selectedTime["minute"]) {
minute = parseInt(this.selectedTime["minute"], 10);
}
if(this.selectedTime["amPm"]) {
isAm = (this.selectedTime["amPm"].toLowerCase() == "am");
}
this.time = new Date();
this.time.setHours(dojo.widget.TimePicker.util.fromAmPmHour(hour, isAm));
this.time.setMinutes(minute);
this.setDateTime(dojo.widget.TimePicker.util.toRfcDateTime(this.time));
}
}
}
dojo.inherits(dojo.widget.html.TimePicker, dojo.widget.HtmlWidget);

View file

@ -0,0 +1,70 @@
/*
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.html.TitlePane");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lfx.*");
dojo.widget.html.TitlePane = function(){
dojo.widget.HtmlWidget.call(this);
this.widgetType = "TitlePane";
this.labelNode="";
this.labelNodeClass="";
this.containerNodeClass="";
this.label="";
this.open=true;
this.templatePath = dojo.uri.dojoUri("src/widget/templates/TitlePane.html");
}
dojo.inherits(dojo.widget.html.TitlePane, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.TitlePane, {
isContainer: true,
postCreate: function() {
if (this.label) {
this.labelNode.appendChild(document.createTextNode(this.label));
}
if (this.labelNodeClass) {
dojo.html.addClass(this.labelNode, this.labelNodeClass);
}
if (this.containerNodeClass) {
dojo.html.addClass(this.containerNode, this.containerNodeClass);
}
if (!this.open) {
dojo.lfx.wipeOut(this.containerNode,0).play();
}
},
onLabelClick: function() {
if (this.open) {
dojo.lfx.wipeOut(this.containerNode,250).play();
this.open=false;
}else {
dojo.lfx.wipeIn(this.containerNode,250).play();
this.open=true;
}
},
setContent: function(content) {
this.containerNode.innerHTML=content;
},
setLabel: function(label) {
this.labelNode.innerHTML=label;
}
});
dojo.widget.tags.addParseTreeHandler("dojo:TitlePane");

View file

@ -0,0 +1,183 @@
/*
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.html.Tooltip");
dojo.require("dojo.widget.html.ContentPane");
dojo.require("dojo.widget.Tooltip");
dojo.require("dojo.uri");
dojo.require("dojo.widget.*");
dojo.require("dojo.event");
dojo.require("dojo.style");
dojo.require("dojo.html");
dojo.widget.defineWidget(
"dojo.widget.html.Tooltip",
dojo.widget.html.ContentPane,
{
widgetType: "Tooltip",
isContainer: true,
// Constructor arguments
caption: "",
showDelay: 500,
hideDelay: 100,
connectId: "",
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.css"),
connectNode: null,
// Tooltip has the following possible states:
// erased - nothing on screen
// displaying - currently being faded in (partially displayed)
// displayed - fully displayed
// erasing - currently being faded out (partially erased)
state: "erased",
fillInTemplate: function(args, frag){
if(this.caption != ""){
this.domNode.appendChild(document.createTextNode(this.caption));
}
this.connectNode = dojo.byId(this.connectId);
dojo.widget.html.Tooltip.superclass.fillInTemplate.call(this, args, frag);
},
postCreate: function(args, frag){
// The domnode was appended to my parent widget's domnode, but the positioning
// only works if the domnode is a child of document.body
document.body.appendChild(this.domNode);
dojo.event.connect(this.connectNode, "onmouseover", this, "onMouseOver");
dojo.widget.html.Tooltip.superclass.postCreate.call(this, args, frag);
},
onMouseOver: function(e) {
this.mouse = {x: e.pageX, y: e.pageY};
if(!this.showTimer){
this.showTimer = setTimeout(dojo.lang.hitch(this, "show"), this.showDelay);
dojo.event.connect(document.documentElement, "onmousemove", this, "onMouseMove");
}
},
onMouseMove: function(e) {
this.mouse = {x: e.pageX, y: e.pageY};
if(dojo.html.overElement(this.connectNode, e) || dojo.html.overElement(this.domNode, e)) {
// If the tooltip has been scheduled to be erased, cancel that timer
// since we are hovering over element/tooltip again
if(this.hideTimer) {
clearTimeout(this.hideTimer);
delete this.hideTimer;
}
} else {
// mouse has been moved off the element/tooltip
// note: can't use onMouseOut to detect this because the "explode" effect causes
// spurious onMouseOut/onMouseOver events (due to interference from outline)
if(this.showTimer){
clearTimeout(this.showTimer);
delete this.showTimer;
}
if((this.state=="displaying"||this.state=="displayed") && !this.hideTimer){
this.hideTimer = setTimeout(dojo.lang.hitch(this, "hide"), this.hideDelay);
}
}
},
show: function() {
if(this.state=="erasing"){
// we are in the process of erasing; when that is finished, display it.
this.displayScheduled=true;
return;
}
if ( this.state=="displaying" || this.state=="displayed" ) { return; }
// prevent IE bleed through (iframe creation is deferred until first show()
// call because apparently it takes a long time)
if(!this.bgIframe){
this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);
}
this.position();
// if rendering using explosion effect, need to set explosion source
this.explodeSrc = [this.mouse.x, this.mouse.y];
this.state="displaying";
dojo.widget.html.Tooltip.superclass.show.call(this);
},
onShow: function() {
dojo.widget.html.Tooltip.superclass.onShow.call(this);
this.state="displayed";
// in the corner case where the user has moved his mouse away
// while the tip was fading in
if(this.eraseScheduled){
this.hide();
this.eraseScheduled=false;
}
},
hide: function() {
if(this.state=="displaying"){
// in the process of fading in. wait until that is finished and then fade out
this.eraseScheduled=true;
return;
}
if ( this.state=="displayed" ) {
this.state="erasing";
if ( this.showTimer ) {
clearTimeout(this.showTimer);
delete this.showTimer;
}
if ( this.hideTimer ) {
clearTimeout(this.hideTimer);
delete this.hideTimer;
}
dojo.event.disconnect(document.documentElement, "onmousemove", this, "onMouseMove");
dojo.widget.html.Tooltip.superclass.hide.call(this);
}
},
onHide: function(){
this.state="erased";
// in the corner case where the user has moved his mouse back
// while the tip was fading out
if(this.displayScheduled){
this.display();
this.displayScheduled=false;
}
},
position: function(){
dojo.html.placeOnScreenPoint(this.domNode, this.mouse.x, this.mouse.y, [10,15], true);
this.bgIframe.onResized();
},
onLoad: function(){
if(this.isShowing()){
// the tooltip has changed size due to downloaded contents, so reposition it
dojo.lang.setTimeout(this, this.position, 50);
dojo.widget.html.Tooltip.superclass.onLoad.apply(this, arguments);
}
},
checkSize: function() {
// checkSize() is called when the user has resized the browser window,
// but that doesn't affect this widget (or this widget's children)
// so it can be safely ignored
}
}
);

View file

@ -0,0 +1,180 @@
/*
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.html.YahooMap");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.math");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.YahooMap");
(function(){
var yappid = djConfig["yAppId"]||djConfig["yahooAppId"]||"dojotoolkit";
if(!dojo.hostenv.post_load_){
if(yappid == "dojotoolkit"){
dojo.debug("please provide a unique Yahoo App ID in djConfig.yahooAppId when using the map widget");
}
var tag = "<scr"+"ipt src='http://api.maps.yahoo.com/ajaxymap?v=3.0&appid="+yappid+"'></scri"+"pt>";
if(!dj_global["YMap"]){
document.write(tag);
}
}else{
dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Yahoo in your page or require() the YahooMap widget before onload has fired");
}
})();
dojo.widget.html.YahooMap=function(){
dojo.widget.HtmlWidget.call(this);
dojo.widget.YahooMap.call(this);
this.map=null;
this.datasrc="";
this.data=[];
this.width=0;
this.height=0;
this.controls=["zoomlong","maptype","pan"];
};
dojo.inherits(dojo.widget.html.YahooMap, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.YahooMap, {
widgetType: "YahooMap",
templatePath:null,
templateCssPath:null,
findCenter:function(aPts){
var start=new YGeoPoint(37,-90);
if(aPts.length==0) return start;
var minLat,maxLat, minLon, maxLon, cLat, cLon;
minLat=maxLat=aPts[0].Lat;
minLon=maxLon=aPts[0].Lon;
for(var i=0; i<aPts.length; i++){
minLat=Math.min(minLat,aPts[i].Lat);
maxLat=Math.max(maxLat,aPts[i].Lat);
minLon=Math.min(minLon,aPts[i].Lon);
maxLon=Math.max(maxLon,aPts[i].Lon);
}
cLat=dojo.math.round((minLat+maxLat)/2,6);
cLon=dojo.math.round((minLon+maxLon)/2,6);
return new YGeoPoint(cLat,cLon);
},
setControls:function(){
var c=this.controls;
var t=dojo.widget.YahooMap.Controls;
for(var i=0; i<c.length; i++){
switch(c[i]){
case t.MapType:{
this.map.addTypeControl();
break;
}
case t.Pan:{
this.map.addPanControl();
break;
}
case t.ZoomLong:{
this.map.addZoomLong();
break;
}
case t.ZoomShort:{
this.map.addZoomShort();
break;
}
}
}
},
parse:function(table){
this.data=[];
// get the column indices
var h=table.getElementsByTagName("thead")[0];
if(!h){
return;
}
var a=[];
var cols=h.getElementsByTagName("td");
if(cols.length==0){
cols=h.getElementsByTagName("th");
}
for(var i=0; i<cols.length; i++){
var c=cols[i].innerHTML.toLowerCase();
if(c=="long") c="lng";
a.push(c);
}
// parse the data
var b=table.getElementsByTagName("tbody")[0];
if(!b){
return;
}
for(var i=0; i<b.childNodes.length; i++){
if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
continue;
}
var cells=b.childNodes[i].getElementsByTagName("td");
var o={};
for(var j=0; j<a.length; j++){
var col=a[j];
if(col=="lat"||col=="lng"){
o[col]=parseFloat(cells[j].innerHTML);
}else{
o[col]=cells[j].innerHTML;
}
}
this.data.push(o);
}
},
render:function(){
var pts=[];
var d=this.data;
for(var i=0; i<d.length; i++){
var pt=new YGeoPoint(d[i].lat, d[i].lng);
pts.push(pt);
var icon=d[i].icon||null;
if(icon){
icon=new YImage(icon);
}
var m=new YMarker(pt,icon);
if(d[i].description){
m.addAutoExpand("<div>"+d[i].description+"</div>");
}
this.map.addOverlay(m);
}
var c=this.findCenter(pts);
var z=this.map.getZoomLevel(pts);
this.map.drawZoomAndCenter(c,z);
},
initialize:function(args, frag){
if(!YMap || !YGeoPoint){
dojo.raise("dojo.widget.YahooMap: The Yahoo Map script must be included in order to use this widget.");
}
if(this.datasrc){
this.parse(dojo.byId(this.datasrc));
}
else if(this.domNode.getElementsByTagName("table")[0]){
this.parse(this.domNode.getElementsByTagName("table")[0]);
}
},
postCreate:function(){
// clean the domNode before creating the map.
while(this.domNode.childNodes.length>0){
this.domNode.removeChild(this.domNode.childNodes[0]);
}
if(this.width>0&&this.height>0){
this.map=new YMap(this.domNode, YAHOO_MAP_REG, new YSize(this.width, this.height));
}else{
this.map=new YMap(this.domNode);
}
this.setControls();
this.render();
}
});

View file

@ -0,0 +1,213 @@
/*
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
*/
// Maintain state of widgets when user hits back/forward button
dojo.provide("dojo.widget.html.stabile");
dojo.widget.html.stabile = {
// Characters to quote in single-quoted regexprs
_sqQuotables: new RegExp("([\\\\'])", "g"),
// Current depth.
_depth: 0,
// Set to true when calling v.toString, to sniff for infinite
// recursion.
_recur: false,
// Levels of nesting of Array and object displays.
// If when >= depth, no display or array or object internals.
depthLimit: 2
};
//// PUBLIC METHODS
// Get the state stored for the widget with the given ID, or undefined
// if none.
//
dojo.widget.html.stabile.getState = function(id){
dojo.widget.html.stabile.setup();
return dojo.widget.html.stabile.widgetState[id];
}
// Set the state stored for the widget with the given ID. If isCommit
// is true, commits all widget state to more stable storage.
//
dojo.widget.html.stabile.setState = function(id, state, isCommit){
dojo.widget.html.stabile.setup();
dojo.widget.html.stabile.widgetState[id] = state;
if(isCommit){
dojo.widget.html.stabile.commit(dojo.widget.html.stabile.widgetState);
}
}
// Sets up widgetState: a hash keyed by widgetId, maps to an object
// or array writable with "describe". If there is data in the widget
// storage area, use it, otherwise initialize an empty object.
//
dojo.widget.html.stabile.setup = function(){
if(!dojo.widget.html.stabile.widgetState){
var text = dojo.widget.html.stabile.getStorage().value;
dojo.widget.html.stabile.widgetState = text ? dj_eval("("+text+")") : {};
}
}
// Commits all widget state to more stable storage, so if the user
// navigates away and returns, it can be restored.
//
dojo.widget.html.stabile.commit = function(state){
dojo.widget.html.stabile.getStorage().value = dojo.widget.html.stabile.description(state);
}
// Return a JSON "description string" for the given value.
// Supports only core JavaScript types with literals, plus Date,
// and cyclic structures are unsupported.
// showAll defaults to false -- if true, this becomes a simple symbolic
// object dumper, but you cannot "eval" the output.
//
dojo.widget.html.stabile.description = function(v, showAll){
// Save and later restore dojo.widget.html.stabile._depth;
var depth = dojo.widget.html.stabile._depth;
var describeThis = function() {
return this.description(this, true);
}
try {
if(v===void(0)){
return "undefined";
}
if(v===null){
return "null";
}
if(typeof(v)=="boolean" || typeof(v)=="number"
|| v instanceof Boolean || v instanceof Number){
return v.toString();
}
if(typeof(v)=="string" || v instanceof String){
// Quote strings and their contents as required.
// Replacing by $& fails in IE 5.0
var v1 = v.replace(dojo.widget.html.stabile._sqQuotables, "\\$1");
v1 = v1.replace(/\n/g, "\\n");
v1 = v1.replace(/\r/g, "\\r");
// Any other important special cases?
return "'"+v1+"'";
}
if(v instanceof Date){
// Create a data constructor.
return "new Date("+d.getFullYear+","+d.getMonth()+","+d.getDate()+")";
}
var d;
if(v instanceof Array || v.push){
// "push" test needed for KHTML/Safari, don't know why -cp
if(depth>=dojo.widget.html.stabile.depthLimit)
return "[ ... ]";
d = "[";
var first = true;
dojo.widget.html.stabile._depth++;
for(var i=0; i<v.length; i++){
// Skip functions and undefined values
// if(v[i]==undef || typeof(v[i])=="function")
// continue;
if(first){
first = false;
}else{
d += ",";
}
d+=arguments.callee(v[i], showAll);
}
return d+"]";
}
if(v.constructor==Object
|| v.toString==describeThis){
if(depth>=dojo.widget.html.stabile.depthLimit)
return "{ ... }";
// Instanceof Hash is good, or if we just use Objects,
// we can say v.constructor==Object.
// IE (5?) lacks hasOwnProperty, but perhaps objects do not always
// have prototypes??
if(typeof(v.hasOwnProperty)!="function" && v.prototype){
throw new Error("description: "+v+" not supported by script engine");
}
var first = true;
d = "{";
dojo.widget.html.stabile._depth++;
for(var key in v){
// Skip values that are functions or undefined.
if(v[key]==void(0) || typeof(v[key])=="function")
continue;
if(first){
first = false;
}else{
d += ", ";
}
var kd = key;
// If the key is not a legal identifier, use its description.
// For strings this will quote the stirng.
if(!kd.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)){
kd = arguments.callee(key, showAll);
}
d += kd+": "+arguments.callee(v[key], showAll);
}
return d+"}";
}
if(showAll){
if(dojo.widget.html.stabile._recur){
// Save the original definitions of toString;
var objectToString = Object.prototype.toString;
return objectToString.apply(v, []);
}else{
dojo.widget.html.stabile._recur = true;
return v.toString();
}
}else{
// log("Description? "+v.toString()+", "+typeof(v));
throw new Error("Unknown type: "+v);
return "'unknown'";
}
} finally {
// Always restore the global current depth.
dojo.widget.html.stabile._depth = depth;
}
}
//// PRIVATE TO MODULE
// Gets an object (form field) with a read/write "value" property.
//
dojo.widget.html.stabile.getStorage = function(){
if (dojo.widget.html.stabile.dataField) {
return dojo.widget.html.stabile.dataField;
}
var form = document.forms._dojo_form;
return dojo.widget.html.stabile.dataField = form ? form.stabile : {value: ""};
}