dojo.provide("dojo.widget.Toolbar");
dojo.require("dojo.widget.*");
dojo.require("dojo.html.style");
/* ToolbarContainer
*******************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarContainer",
dojo.widget.HtmlWidget,
{
isContainer: true,
templateString: '<div class="toolbarContainer" dojoAttachPoint="containerNode"></div>',
templateCssPath: dojo.uri.dojoUri("src/widget/templates/Toolbar.css"),
getItem: function(name) {
if(name instanceof dojo.widget.ToolbarItem) { return name; }
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
var item = child.getItem(name);
if(item) { return item; }
}
}
return null;
},
getItems: function() {
var items = [];
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
items = items.concat(child.getItems());
}
}
return items;
},
enable: function() {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
child.enable.apply(child, arguments);
}
}
},
disable: function() {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
child.disable.apply(child, arguments);
}
}
},
select: function(name) {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
child.select(arguments);
}
}
},
deselect: function(name) {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
child.deselect(arguments);
}
}
},
getItemsState: function() {
var values = {};
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
dojo.lang.mixin(values, child.getItemsState());
}
}
return values;
},
getItemsActiveState: function() {
var values = {};
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
dojo.lang.mixin(values, child.getItemsActiveState());
}
}
return values;
},
getItemsSelectedState: function() {
var values = {};
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.Toolbar) {
dojo.lang.mixin(values, child.getItemsSelectedState());
}
}
return values;
}
});
/* Toolbar
**********/
dojo.widget.defineWidget(
"dojo.widget.Toolbar",
dojo.widget.HtmlWidget,
{
isContainer: true,
templateString: '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on" dojoOnMouseover="_onmouseover" dojoOnMouseout="_onmouseout" dojoOnClick="_onclick" dojoOnMousedown="_onmousedown" dojoOnMouseup="_onmouseup"></div>',
// given a node, tries to find it's toolbar item
_getItem: function(node) {
var start = new Date();
var widget = null;
while(node && node != this.domNode) {
if(dojo.html.hasClass(node, "toolbarItem")) {
var widgets = dojo.widget.manager.getWidgetsByFilter(function(w) { return w.domNode == node; });
if(widgets.length == 1) {
widget = widgets[0];
break;
} else if(widgets.length > 1) {
dojo.raise("Toolbar._getItem: More than one widget matches the node");
}
}
node = node.parentNode;
}
return widget;
},
_onmouseover: function(e) {
var widget = this._getItem(e.target);
if(widget && widget._onmouseover) { widget._onmouseover(e); }
},
_onmouseout: function(e) {
var widget = this._getItem(e.target);
if(widget && widget._onmouseout) { widget._onmouseout(e); }
},
_onclick: function(e) {
var widget = this._getItem(e.target);
if(widget && widget._onclick){
widget._onclick(e);
}
},
_onmousedown: function(e) {
var widget = this._getItem(e.target);
if(widget && widget._onmousedown) { widget._onmousedown(e); }
},
_onmouseup: function(e) {
var widget = this._getItem(e.target);
if(widget && widget._onmouseup) { widget._onmouseup(e); }
},
addChild: function(item, pos, props) {
var widget = dojo.widget.ToolbarItem.make(item, null, props);
var ret = dojo.widget.Toolbar.superclass.addChild.call(this, widget, null, pos, null);
return ret;
},
push: function() {
for(var i = 0; i < arguments.length; i++) {
this.addChild(arguments[i]);
}
},
getItem: function(name) {
if(name instanceof dojo.widget.ToolbarItem) { return name; }
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem
&& child._name == name) { return child; }
}
return null;
},
getItems: function() {
var items = [];
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
items.push(child);
}
}
return items;
},
getItemsState: function() {
var values = {};
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
values[child._name] = {
selected: child._selected,
enabled: !child.disabled
};
}
}
return values;
},
getItemsActiveState: function() {
var values = this.getItemsState();
for(var item in values) {
values[item] = values[item].enabled;
}
return values;
},
getItemsSelectedState: function() {
var values = this.getItemsState();
for(var item in values) {
values[item] = values[item].selected;
}
return values;
},
enable: function() {
var items = arguments.length ? arguments : this.children;
for(var i = 0; i < items.length; i++) {
var child = this.getItem(items[i]);
if(child instanceof dojo.widget.ToolbarItem) {
child.enable(false, true);
}
}
},
disable: function() {
var items = arguments.length ? arguments : this.children;
for(var i = 0; i < items.length; i++) {
var child = this.getItem(items[i]);
if(child instanceof dojo.widget.ToolbarItem) {
child.disable();
}
}
},
select: function() {
for(var i = 0; i < arguments.length; i++) {
var name = arguments[i];
var item = this.getItem(name);
if(item) { item.select(); }
}
},
deselect: function() {
for(var i = 0; i < arguments.length; i++) {
var name = arguments[i];
var item = this.getItem(name);
if(item) { item.disable(); }
}
},
setValue: function() {
for(var i = 0; i < arguments.length; i += 2) {
var name = arguments[i], value = arguments[i+1];
var item = this.getItem(name);
if(item) {
if(item instanceof dojo.widget.ToolbarItem) {
item.setValue(value);
}
}
}
}
});
/* ToolbarItem hierarchy:
- ToolbarItem
- ToolbarButton
- ToolbarDialog
- ToolbarMenu
- ToolbarSeparator
- ToolbarSpace
- ToolbarFlexibleSpace
*/
/* ToolbarItem
**************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarItem",
dojo.widget.HtmlWidget,
{
templateString: '<span unselectable="on" class="toolbarItem"></span>',
_name: null,
getName: function() { return this._name; },
setName: function(value) { return (this._name = value); },
getValue: function() { return this.getName(); },
setValue: function(value) { return this.setName(value); },
_selected: false,
isSelected: function() { return this._selected; },
setSelected: function(is, force, preventEvent) {
if(!this._toggleItem && !force) { return; }
is = Boolean(is);
if(force || !this.disabled && this._selected != is) {
this._selected = is;
this.update();
if(!preventEvent) {
this._fireEvent(is ? "onSelect" : "onDeselect");
this._fireEvent("onChangeSelect");
}
}
},
select: function(force, preventEvent) {
return this.setSelected(true, force, preventEvent);
},
deselect: function(force, preventEvent) {
return this.setSelected(false, force, preventEvent);
},
_toggleItem: false,
isToggleItem: function() { return this._toggleItem; },
setToggleItem: function(value) { this._toggleItem = Boolean(value); },
toggleSelected: function(force) {
return this.setSelected(!this._selected, force);
},
isEnabled: function() { return !this.disabled; },
setEnabled: function(is, force, preventEvent) {
is = Boolean(is);
if(force || this.disabled == is) {
this.disabled = !is;
this.update();
if(!preventEvent) {
this._fireEvent(this.disabled ? "onDisable" : "onEnable");
this._fireEvent("onChangeEnabled");
}
}
return !this.disabled;
},
enable: function(force, preventEvent) {
return this.setEnabled(true, force, preventEvent);
},
disable: function(force, preventEvent) {
return this.setEnabled(false, force, preventEvent);
},
toggleEnabled: function(force, preventEvent) {
return this.setEnabled(this.disabled, force, preventEvent);
},
_icon: null,
getIcon: function() { return this._icon; },
setIcon: function(value) {
var icon = dojo.widget.Icon.make(value);
if(this._icon) {
this._icon.setIcon(icon);
} else {
this._icon = icon;
}
var iconNode = this._icon.getNode();
if(iconNode.parentNode != this.domNode) {
if(this.domNode.hasChildNodes()) {
this.domNode.insertBefore(iconNode, this.domNode.firstChild);
} else {
this.domNode.appendChild(iconNode);
}
}
return this._icon;
},
// TODO: update the label node (this.labelNode?)
_label: "",
getLabel: function() { return this._label; },
setLabel: function(value) {
var ret = (this._label = value);
if(!this.labelNode) {
this.labelNode = document.createElement("span");
this.domNode.appendChild(this.labelNode);
}
this.labelNode.innerHTML = "";
this.labelNode.appendChild(document.createTextNode(this._label));
this.update();
return ret;
},
// fired from: setSelected, setEnabled, setLabel
update: function() {
if(this.disabled) {
this._selected = false;
dojo.html.addClass(this.domNode, "disabled");
dojo.html.removeClass(this.domNode, "down");
dojo.html.removeClass(this.domNode, "hover");
} else {
dojo.html.removeClass(this.domNode, "disabled");
if(this._selected) {
dojo.html.addClass(this.domNode, "selected");
} else {
dojo.html.removeClass(this.domNode, "selected");
}
}
this._updateIcon();
},
_updateIcon: function() {
if(this._icon) {
if(this.disabled) {
this._icon.disable();
} else {
if(this._cssHover) {
this._icon.hover();
} else if(this._selected) {
this._icon.select();
} else {
this._icon.enable();
}
}
}
},
_fireEvent: function(evt) {
if(typeof this[evt] == "function") {
var args = [this];
for(var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
this[evt].apply(this, args);
}
},
_onmouseover: function(e) {
if(this.disabled) { return; }
dojo.html.addClass(this.domNode, "hover");
this._fireEvent("onMouseOver");
},
_onmouseout: function(e) {
dojo.html.removeClass(this.domNode, "hover");
dojo.html.removeClass(this.domNode, "down");
if(!this._selected) {
dojo.html.removeClass(this.domNode, "selected");
}
this._fireEvent("onMouseOut");
},
_onclick: function(e) {
// dojo.debug("widget:", this.widgetType, ":", this.getName(), ", disabled:", this.disabled);
if(!this.disabled && !this._toggleItem) {
this._fireEvent("onClick");
}
},
_onmousedown: function(e) {
if(e.preventDefault) { e.preventDefault(); }
if(this.disabled) { return; }
dojo.html.addClass(this.domNode, "down");
if(this._toggleItem) {
if(this.parent.preventDeselect && this._selected) {
return;
}
this.toggleSelected();
}
this._fireEvent("onMouseDown");
},
_onmouseup: function(e) {
dojo.html.removeClass(this.domNode, "down");
this._fireEvent("onMouseUp");
},
onClick: function() { },
onMouseOver: function() { },
onMouseOut: function() { },
onMouseDown: function() { },
onMouseUp: function() { },
fillInTemplate: function(args, frag) {
if(args.name) { this._name = args.name; }
if(args.selected) { this.select(); }
if(args.disabled) { this.disable(); }
if(args.label) { this.setLabel(args.label); }
if(args.icon) { this.setIcon(args.icon); }
if(args.toggleitem||args.toggleItem) { this.setToggleItem(true); }
}
});
dojo.widget.ToolbarItem.make = function(wh, whIsType, props) {
var item = null;
if(wh instanceof Array) {
item = dojo.widget.createWidget("ToolbarButtonGroup", props);
item.setName(wh[0]);
for(var i = 1; i < wh.length; i++) {
item.addChild(wh[i]);
}
} else if(wh instanceof dojo.widget.ToolbarItem) {
item = wh;
} else if(wh instanceof dojo.uri.Uri) {
item = dojo.widget.createWidget("ToolbarButton",
dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
} else if(whIsType) {
item = dojo.widget.createWidget(wh, props);
} else if(typeof wh == "string" || wh instanceof String) {
switch(wh.charAt(0)) {
case "|":
case "-":
case "/":
item = dojo.widget.createWidget("ToolbarSeparator", props);
break;
case " ":
if(wh.length == 1) {
item = dojo.widget.createWidget("ToolbarSpace", props);
} else {
item = dojo.widget.createWidget("ToolbarFlexibleSpace", props);
}
break;
default:
if(/\.(gif|jpg|jpeg|png)$/i.test(wh)) {
item = dojo.widget.createWidget("ToolbarButton",
dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
} else {
item = dojo.widget.createWidget("ToolbarButton",
dojo.lang.mixin(props||{}, {label: wh.toString()}));
}
}
} else if(wh && wh.tagName && /^img$/i.test(wh.tagName)) {
item = dojo.widget.createWidget("ToolbarButton",
dojo.lang.mixin(props||{}, {icon: wh}));
} else {
item = dojo.widget.createWidget("ToolbarButton",
dojo.lang.mixin(props||{}, {label: wh.toString()}));
}
return item;
}
/* ToolbarButtonGroup
*********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarButtonGroup",
dojo.widget.ToolbarItem,
{
isContainer: true,
templateString: '<span unselectable="on" class="toolbarButtonGroup" dojoAttachPoint="containerNode"></span>',
// if a button has the same name, it will be selected
// if this is set to a number, the button at that index will be selected
defaultButton: "",
postCreate: function() {
for (var i = 0; i < this.children.length; i++) {
this._injectChild(this.children[i]);
}
},
addChild: function(item, pos, props) {
var widget = dojo.widget.ToolbarItem.make(item, null, dojo.lang.mixin(props||{}, {toggleItem:true}));
var ret = dojo.widget.ToolbarButtonGroup.superclass.addChild.call(this, widget, null, pos, null);
this._injectChild(widget);
return ret;
},
_injectChild: function(widget) {
dojo.event.connect(widget, "onSelect", this, "onChildSelected");
dojo.event.connect(widget, "onDeselect", this, "onChildDeSelected");
if(widget._name == this.defaultButton
|| (typeof this.defaultButton == "number"
&& this.children.length-1 == this.defaultButton)) {
widget.select(false, true);
}
},
getItem: function(name) {
if(name instanceof dojo.widget.ToolbarItem) { return name; }
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem
&& child._name == name) { return child; }
}
return null;
},
getItems: function() {
var items = [];
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
items.push(child);
}
}
return items;
},
onChildSelected: function(e) {
this.select(e._name);
},
onChildDeSelected: function(e) {
this._fireEvent("onChangeSelect", this._value);
},
enable: function(force, preventEvent) {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
child.enable(force, preventEvent);
if(child._name == this._value) {
child.select(force, preventEvent);
}
}
}
},
disable: function(force, preventEvent) {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
child.disable(force, preventEvent);
}
}
},
_value: "",
getValue: function() { return this._value; },
select: function(name, force, preventEvent) {
for(var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if(child instanceof dojo.widget.ToolbarItem) {
if(child._name == name) {
child.select(force, preventEvent);
this._value = name;
} else {
child.deselect(true, true);
}
}
}
if(!preventEvent) {
this._fireEvent("onSelect", this._value);
this._fireEvent("onChangeSelect", this._value);
}
},
setValue: this.select,
preventDeselect: false // if true, once you select one, you can't have none selected
});
/* ToolbarButton
***********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarButton",
dojo.widget.ToolbarItem,
{
fillInTemplate: function(args, frag) {
dojo.widget.ToolbarButton.superclass.fillInTemplate.call(this, args, frag);
dojo.html.addClass(this.domNode, "toolbarButton");
if(this._icon) {
this.setIcon(this._icon);
}
if(this._label) {
this.setLabel(this._label);
}
if(!this._name) {
if(this._label) {
this.setName(this._label);
} else if(this._icon) {
var src = this._icon.getSrc("enabled").match(/[\/^]([^\.\/]+)\.(gif|jpg|jpeg|png)$/i);
if(src) { this.setName(src[1]); }
} else {
this._name = this._widgetId;
}
}
}
});
/* ToolbarDialog
**********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarDialog",
dojo.widget.ToolbarButton,
{
fillInTemplate: function (args, frag) {
dojo.widget.ToolbarDialog.superclass.fillInTemplate.call(this, args, frag);
dojo.event.connect(this, "onSelect", this, "showDialog");
dojo.event.connect(this, "onDeselect", this, "hideDialog");
},
showDialog: function (e) {
dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "deselect");
},
hideDialog: function (e) {
dojo.event.disconnect(document, "onmousedown", this, "deselect");
}
});
/* ToolbarMenu
**********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarMenu",
dojo.widget.ToolbarDialog,
{}
);
/* ToolbarMenuItem
******************/
dojo.widget.ToolbarMenuItem = function() {
}
/* ToolbarSeparator
**********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarSeparator",
dojo.widget.ToolbarItem,
{
templateString: '<span unselectable="on" class="toolbarItem toolbarSeparator"></span>',
defaultIconPath: new dojo.uri.dojoUri("src/widget/templates/buttons/sep.gif"),
fillInTemplate: function(args, frag, skip) {
dojo.widget.ToolbarSeparator.superclass.fillInTemplate.call(this, args, frag);
this._name = this.widgetId;
if(!skip) {
if(!this._icon) {
this.setIcon(this.defaultIconPath);
}
this.domNode.appendChild(this._icon.getNode());
}
},
// don't want events!
_onmouseover: null,
_onmouseout: null,
_onclick: null,
_onmousedown: null,
_onmouseup: null
});
/* ToolbarSpace
**********************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarSpace",
dojo.widget.ToolbarSeparator,
{
fillInTemplate: function(args, frag, skip) {
dojo.widget.ToolbarSpace.superclass.fillInTemplate.call(this, args, frag, true);
if(!skip) {
dojo.html.addClass(this.domNode, "toolbarSpace");
}
}
});
/* ToolbarSelect
******************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarSelect",
dojo.widget.ToolbarItem,
{
templateString: '<span class="toolbarItem toolbarSelect" unselectable="on"><select dojoAttachPoint="selectBox" dojoOnChange="changed"></select></span>',
fillInTemplate: function(args, frag) {
dojo.widget.ToolbarSelect.superclass.fillInTemplate.call(this, args, frag, true);
var keys = args.values;
var i = 0;
for(var val in keys) {
var opt = document.createElement("option");
opt.setAttribute("value", keys[val]);
opt.innerHTML = val;
this.selectBox.appendChild(opt);
}
},
changed: function(e) {
this._fireEvent("onSetValue", this.selectBox.value);
},
setEnabled: function(is, force, preventEvent) {
var ret = dojo.widget.ToolbarSelect.superclass.setEnabled.call(this, is, force, preventEvent);
this.selectBox.disabled = this.disabled;
return ret;
},
// don't want events!
_onmouseover: null,
_onmouseout: null,
_onclick: null,
_onmousedown: null,
_onmouseup: null
});
/* Icon
*********/
// arguments can be IMG nodes, Image() instances or URLs -- enabled is the only one required
dojo.widget.Icon = function(enabled, disabled, hovered, selected){
if(!arguments.length){
// FIXME: should this be dojo.raise?
throw new Error("Icon must have at least an enabled state");
}
var states = ["enabled", "disabled", "hovered", "selected"];
var currentState = "enabled";
var domNode = document.createElement("img");
this.getState = function(){ return currentState; }
this.setState = function(value){
if(dojo.lang.inArray(states, value)){
if(this[value]){
currentState = value;
var img = this[currentState];
if ((dojo.render.html.ie55 || dojo.render.html.ie60) && img.src && img.src.match(/[.]png$/i) ) {
domNode.width = img.width||img.offsetWidth;
domNode.height = img.height||img.offsetHeight;
domNode.setAttribute("src", dojo.uri.dojoUri("src/widget/templates/images/blank.gif").uri);
domNode.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+img.src+"',sizingMethod='image')";
} else {
domNode.setAttribute("src", img.src);
}
}
}else{
throw new Error("Invalid state set on Icon (state: " + value + ")");
}
}
this.setSrc = function(state, value){
if(/^img$/i.test(value.tagName)){
this[state] = value;
}else if(typeof value == "string" || value instanceof String
|| value instanceof dojo.uri.Uri){
this[state] = new Image();
this[state].src = value.toString();
}
return this[state];
}
this.setIcon = function(icon){
for(var i = 0; i < states.length; i++){
if(icon[states[i]]){
this.setSrc(states[i], icon[states[i]]);
}
}
this.update();
}
this.enable = function(){ this.setState("enabled"); }
this.disable = function(){ this.setState("disabled"); }
this.hover = function(){ this.setState("hovered"); }
this.select = function(){ this.setState("selected"); }
this.getSize = function(){
return {
width: domNode.width||domNode.offsetWidth,
height: domNode.height||domNode.offsetHeight
};
}
this.setSize = function(w, h){
domNode.width = w;
domNode.height = h;
return { width: w, height: h };
}
this.getNode = function(){
return domNode;
}
this.getSrc = function(state){
if(state){ return this[state].src; }
return domNode.src||"";
}
this.update = function(){
this.setState(currentState);
}
for(var i = 0; i < states.length; i++){
var arg = arguments[i];
var state = states[i];
this[state] = null;
if(!arg){ continue; }
this.setSrc(state, arg);
}
this.enable();
}
dojo.widget.Icon.make = function(a,b,c,d){
for(var i = 0; i < arguments.length; i++){
if(arguments[i] instanceof dojo.widget.Icon){
return arguments[i];
}
}
return new dojo.widget.Icon(a,b,c,d);
}
/* ToolbarColorDialog
******************/
dojo.widget.defineWidget(
"dojo.widget.ToolbarColorDialog",
dojo.widget.ToolbarDialog,
{
palette: "7x10",
fillInTemplate: function (args, frag) {
dojo.widget.ToolbarColorDialog.superclass.fillInTemplate.call(this, args, frag);
this.dialog = dojo.widget.createWidget("ColorPalette", {palette: this.palette});
this.dialog.domNode.style.position = "absolute";
dojo.event.connect(this.dialog, "onColorSelect", this, "_setValue");
},
_setValue: function(color) {
this._value = color;
this._fireEvent("onSetValue", color);
},
showDialog: function (e) {
dojo.widget.ToolbarColorDialog.superclass.showDialog.call(this, e);
var abs = dojo.html.getAbsolutePosition(this.domNode, true);
var y = abs.y + dojo.html.getBorderBox(this.domNode).height;
this.dialog.showAt(abs.x, y);
},
hideDialog: function (e) {
dojo.widget.ToolbarColorDialog.superclass.hideDialog.call(this, e);
this.dialog.hide();
}
});