You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
6.8 KiB
245 lines
6.8 KiB
|
|
//** ButtonList Widget *************************************************************
|
|
|
|
/**
|
|
* ButtonList Constructor
|
|
*/
|
|
bobj.crv.newButtonList = function(kwArgs) {
|
|
kwArgs = MochiKit.Base.update({
|
|
id: bobj.uniqueId(),
|
|
numLines: null, // null allows the height to grow (will fit within the viewport)
|
|
buttonWidth: 24,
|
|
buttonTooltip: L_bobj_crv_TabList,
|
|
changeCB: null,
|
|
label: null,
|
|
tabIndex: 0,
|
|
multiSelect: false,
|
|
menuWidth: null,
|
|
menuTooltip: null
|
|
}, kwArgs);
|
|
|
|
var o = newButtonWidget(
|
|
kwArgs.id,
|
|
kwArgs.label,
|
|
bobj.crv.ButtonList._onClick,
|
|
kwArgs.buttonWidth,
|
|
null,
|
|
kwArgs.buttonTooltip,
|
|
kwArgs.tabIndex,
|
|
0, _skin+"menus.gif", 7, 16, 0, 81, true, 0, 97);
|
|
|
|
o._menu = newListWidget(
|
|
kwArgs.id + "_menu",
|
|
MochiKit.Base.bind(bobj.crv.ButtonList._onChange, o),
|
|
kwArgs.multiSelect,
|
|
kwArgs.menuWidth,
|
|
kwArgs.numLines || 2,
|
|
kwArgs.menuTooltip,
|
|
null, //dblClickCB
|
|
null); //keyUpCB
|
|
|
|
o._listItems = [];
|
|
o._blOldInit = o.init;
|
|
o._blOldGetHTML = o.getHTML;
|
|
o._menuDiv = null;
|
|
|
|
o._captureClicks = MenuWidget_captureClicks;
|
|
o._releaseClicks = MenuWidget_releaseClicks;
|
|
|
|
bobj.fillIn(o, kwArgs);
|
|
o.widgetType = 'ButtonList';
|
|
MochiKit.Base.update(o, bobj.crv.ButtonList);
|
|
|
|
return o;
|
|
};
|
|
|
|
bobj.crv.ButtonList = {
|
|
/**
|
|
* @return [Widget] Menu/list widget associated with this button.
|
|
*/
|
|
getMenu : function() {
|
|
return this._menu;
|
|
},
|
|
|
|
/**
|
|
* Add an item to the menu
|
|
*
|
|
* @param label [String] The text to display in the menu
|
|
* @param value [any - opt.] The value associated with the new menu item
|
|
* @param isSelected [bool - opt.] True if item should be selected after being added
|
|
* @param id [String - opt.] DHTML id associated with menu item;
|
|
*/
|
|
add : function(label, value, isSelected, id) {
|
|
if (this._menu && this._menu.layer)
|
|
this._menu.add (label, value, isSelected, id);
|
|
|
|
else
|
|
this._listItems.push ( {
|
|
lbl : label,
|
|
val : value,
|
|
sel : isSelected,
|
|
id : id
|
|
});
|
|
},
|
|
|
|
init : function() {
|
|
var menu = this._menu;
|
|
this._blOldInit ();
|
|
menu.init ();
|
|
|
|
this._menuDiv = getLayer (this.id + '_menuDiv');
|
|
|
|
var listItems = this._listItems;
|
|
for ( var i = 0, len = listItems.length; i < len; ++i) {
|
|
var it = listItems[i];
|
|
menu.add (it.lbl, it.val, it.sel, it.id);
|
|
}
|
|
this._listItems = [];
|
|
},
|
|
|
|
getHTML : function() {
|
|
var h = bobj.html;
|
|
|
|
var menuDivAtts = {
|
|
id : this.id + '_menuDiv',
|
|
onmousedown : 'event.cancelBubble=true',
|
|
'class' : 'menuFrame',
|
|
style : {
|
|
visibility : 'hidden',
|
|
position : 'absolute',
|
|
'z-index' : 5000
|
|
}
|
|
};
|
|
return this._blOldGetHTML () + h.DIV (menuDivAtts, this._menu.getHTML ());
|
|
},
|
|
|
|
/**
|
|
* @return [bool] True if and only if the menu is visible
|
|
*/
|
|
isMenuShowing : function() {
|
|
return this._menuDiv && this._menuDiv.style.visibility != 'hidden';
|
|
},
|
|
|
|
/**
|
|
* Hide the menu
|
|
*/
|
|
hideMenu : function() {
|
|
if (this._menuDiv) {
|
|
this._menuDiv.style.visibility = 'hidden';
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Position and show the menu
|
|
*/
|
|
showMenu : function() {
|
|
if (this._menuDiv) {
|
|
this._captureClicks ();
|
|
|
|
var body = document.body;
|
|
|
|
if (this._menuDiv.parentNode !== body) {
|
|
body.appendChild (this._menuDiv);
|
|
}
|
|
|
|
var divStyle = this._menuDiv.style;
|
|
divStyle.left = '-1000px';
|
|
divStyle.top = '-1000px';
|
|
divStyle.visibility = 'visible';
|
|
|
|
var winDim = MochiKit.Style.getViewportDimensions ();
|
|
|
|
var w = this._menu.layer.offsetWidth;
|
|
var h = this._menu.getHeight ();
|
|
|
|
/*
|
|
* If numLines wasn't specified, use as much space as necessary while remaining within the viewport
|
|
*/
|
|
if (!this.numLines) {
|
|
h = Math.min (this._menu.layer.scrollHeight + 10, winDim.h - 10);
|
|
this._menu.resize (null, h);
|
|
}
|
|
|
|
/* Place the menu below the button and aligned with the left edge */
|
|
var btnPos = getPosScrolled (this.layer);
|
|
var x = btnPos.x;
|
|
var y = btnPos.y + this.getHeight ();
|
|
|
|
/* Change coordinates so the whole menu is on the screen */
|
|
var xRight = x + w + 4;
|
|
var yBottom = y + h + 4;
|
|
|
|
var xMax = winDim.w + body.scrollLeft - Math.max (0, (winDim.w - body.offsetWidth));
|
|
if (xRight > xMax) {
|
|
x = Math.max (0, x - (xRight - xMax));
|
|
}
|
|
|
|
var yMax = winDim.h + body.scrollTop;
|
|
if (yBottom > yMax) {
|
|
y = Math.max (0, y - (yBottom - yMax));
|
|
}
|
|
|
|
divStyle.left = x + 'px';
|
|
divStyle.top = y + 'px';
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Private. Capture clicks in the current document so that the menu can be hidden automatically.
|
|
*/
|
|
_captureClicks : function() {
|
|
var BIND = MochiKit.Base.bind;
|
|
try {
|
|
this.layer.onmousedown = BIND (this._onCaptureClick, this, true);
|
|
this._oldMousedown = document.onmousedown;
|
|
document.onmousedown = BIND (this._onCaptureClick, this, false);
|
|
} catch (ex) {
|
|
if (bobj.crv.config.isDebug) {
|
|
throw ex;
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Private. Stop capturing clicks.
|
|
*/
|
|
_releaseClicks : function() {
|
|
if (this.layer.onmousedown) { /* non-null if clicks are being captured */
|
|
this.layer.onmousedown = null;
|
|
document.onmousedown = this._oldMousedown;
|
|
}
|
|
},
|
|
|
|
|
|
/**
|
|
* Private. Button click callback.
|
|
*/
|
|
_onClick : function() {
|
|
if (!this._cancelNextClick)
|
|
this.showMenu ();
|
|
|
|
this._cancelNextClick = false;
|
|
},
|
|
|
|
/**
|
|
* Private. Menu change callback.
|
|
*/
|
|
_onChange : function() {
|
|
this._releaseClicks ();
|
|
this.hideMenu ();
|
|
|
|
if (this.changeCB)
|
|
this.changeCB ();
|
|
},
|
|
|
|
/**
|
|
* Private. Called when a click is captured (after _captureClicks has been called)
|
|
*/
|
|
_onCaptureClick : function(cancelNext, e) {
|
|
this._cancelNextClick = cancelNext;
|
|
eventCancelBubble (e);
|
|
this.hideMenu ();
|
|
this._releaseClicks ();
|
|
}
|
|
};
|