mirror of
http://git.whoc.org.uk/git/password-manager.git
synced 2025-10-25 01:37:34 +02:00
First version of the newly restructured repository
This commit is contained in:
1046
frontend/beta/js/YUI-extensions/widgets/BasicDialog.js
Normal file
1046
frontend/beta/js/YUI-extensions/widgets/BasicDialog.js
Normal file
File diff suppressed because it is too large
Load Diff
185
frontend/beta/js/YUI-extensions/widgets/Button.js
Normal file
185
frontend/beta/js/YUI-extensions/widgets/Button.js
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @class YAHOO.ext.Button
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
* Simple Button class
|
||||
* @cfg {String} text The button text
|
||||
* @cfg {Function} handler A function called when the button is clicked (can be used instead of click event)
|
||||
* @cfg {Object} scope The scope of the handler
|
||||
* @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width)
|
||||
* @constructor
|
||||
* Create a new button
|
||||
* @param {String/HTMLElement/Element} renderTo The element to append the button to
|
||||
* @param {Object} config The config object
|
||||
*/
|
||||
YAHOO.ext.Button = function(renderTo, config){
|
||||
YAHOO.ext.util.Config.apply(this, config);
|
||||
this.events = {
|
||||
/**
|
||||
* @event click
|
||||
* Fires when this button is clicked
|
||||
* @param {Button} this
|
||||
* @param {EventObject} e The click event
|
||||
*/
|
||||
'click' : true
|
||||
};
|
||||
if(renderTo){
|
||||
this.render(renderTo);
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.extendX(YAHOO.ext.Button, YAHOO.ext.util.Observable, {
|
||||
render : function(renderTo){
|
||||
var btn;
|
||||
if(!this.dhconfig){
|
||||
if(!YAHOO.ext.Button.buttonTemplate){
|
||||
// hideous table template
|
||||
YAHOO.ext.Button.buttonTemplate = new YAHOO.ext.DomHelper.Template('<a href="#" class="ybtn-focus"><table border="0" cellpadding="0" cellspacing="0" class="ybtn-wrap"><tbody><tr><td class="ybtn-left"> </td><td class="ybtn-center" unselectable="on">{0}</td><td class="ybtn-right"> </td></tr></tbody></table></a>');
|
||||
}
|
||||
btn = YAHOO.ext.Button.buttonTemplate.append(
|
||||
getEl(renderTo).dom, [this.text], true);
|
||||
this.tbl = getEl(btn.dom.firstChild, true);
|
||||
}else{
|
||||
btn = YAHOO.ext.DomHelper.append(this.footer.dom, this.dhconfig, true);
|
||||
}
|
||||
this.el = btn;
|
||||
this.autoWidth();
|
||||
btn.addClass('ybtn');
|
||||
btn.mon('click', this.onClick, this, true);
|
||||
btn.on('mouseover', this.onMouseOver, this, true);
|
||||
btn.on('mouseout', this.onMouseOut, this, true);
|
||||
btn.on('mousedown', this.onMouseDown, this, true);
|
||||
btn.on('mouseup', this.onMouseUp, this, true);
|
||||
},
|
||||
/**
|
||||
* Returns the buttons element
|
||||
* @return {YAHOO.ext.Element}
|
||||
*/
|
||||
getEl : function(){
|
||||
return this.el;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys this Button.
|
||||
*/
|
||||
destroy : function(){
|
||||
this.el.removeAllListeners();
|
||||
this.purgeListeners();
|
||||
this.el.update('');
|
||||
this.el.remove();
|
||||
},
|
||||
|
||||
autoWidth : function(){
|
||||
if(this.tbl){
|
||||
this.el.setWidth('auto');
|
||||
this.tbl.setWidth('auto');
|
||||
if(this.minWidth){
|
||||
if(this.tbl.getWidth() < this.minWidth){
|
||||
this.tbl.setWidth(this.minWidth);
|
||||
}
|
||||
}
|
||||
this.el.setWidth(this.tbl.getWidth());
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Sets this buttons click handler
|
||||
* @param {Function} handler The function to call when the button is clicked
|
||||
* @param {Object} scope (optional) Scope for the function passed above
|
||||
*/
|
||||
setHandler : function(handler, scope){
|
||||
this.handler = handler;
|
||||
this.scope = scope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set this buttons text
|
||||
* @param {String} text
|
||||
*/
|
||||
setText : function(text){
|
||||
this.text = text;
|
||||
this.el.dom.firstChild.firstChild.firstChild.childNodes[1].innerHTML = text;
|
||||
this.autoWidth();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the text for this button
|
||||
* @return {String}
|
||||
*/
|
||||
getText : function(){
|
||||
return this.text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show this button
|
||||
*/
|
||||
show: function(){
|
||||
this.el.setStyle('display', '');
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide this button
|
||||
*/
|
||||
hide: function(){
|
||||
this.el.setStyle('display', 'none');
|
||||
},
|
||||
|
||||
/**
|
||||
* Convenience function for boolean show/hide
|
||||
* @param {Boolean} visible true to show/false to hide
|
||||
*/
|
||||
setVisible: function(visible){
|
||||
if(visible) {
|
||||
this.show();
|
||||
}else{
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Focus the button
|
||||
*/
|
||||
focus : function(){
|
||||
this.el.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable this button
|
||||
*/
|
||||
disable : function(){
|
||||
this.el.addClass('ybtn-disabled');
|
||||
this.disabled = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable this button
|
||||
*/
|
||||
enable : function(){
|
||||
this.el.removeClass('ybtn-disabled');
|
||||
this.disabled = false;
|
||||
},
|
||||
|
||||
onClick : function(e){
|
||||
e.preventDefault();
|
||||
if(!this.disabled){
|
||||
this.fireEvent('click', this, e);
|
||||
if(this.handler){
|
||||
this.handler.call(this.scope || this, this, e);
|
||||
}
|
||||
}
|
||||
},
|
||||
onMouseOver : function(e){
|
||||
if(!this.disabled){
|
||||
this.el.addClass('ybtn-over');
|
||||
}
|
||||
},
|
||||
onMouseOut : function(e){
|
||||
this.el.removeClass('ybtn-over');
|
||||
},
|
||||
onMouseDown : function(){
|
||||
if(!this.disabled){
|
||||
this.el.addClass('ybtn-click');
|
||||
}
|
||||
},
|
||||
onMouseUp : function(){
|
||||
this.el.removeClass('ybtn-click');
|
||||
}
|
||||
});
|
||||
344
frontend/beta/js/YUI-extensions/widgets/DatePicker.js
Normal file
344
frontend/beta/js/YUI-extensions/widgets/DatePicker.js
Normal file
@@ -0,0 +1,344 @@
|
||||
YAHOO.ext.DatePicker = function(id, parentElement){
|
||||
this.id = id;
|
||||
this.selectedDate = new Date();
|
||||
this.visibleDate = new Date();
|
||||
this.element = null;
|
||||
this.shadow = null;
|
||||
this.callback = null;
|
||||
this.buildControl(parentElement || document.body);
|
||||
this.mouseDownHandler = YAHOO.ext.EventManager.wrap(this.handleMouseDown, this, true);
|
||||
this.keyDownHandler = YAHOO.ext.EventManager.wrap(this.handleKeyDown, this, true);
|
||||
this.wheelHandler = YAHOO.ext.EventManager.wrap(this.handleMouseWheel, this, true);
|
||||
};
|
||||
|
||||
YAHOO.ext.DatePicker.prototype = {
|
||||
show : function(x, y, value, callback){
|
||||
this.hide();
|
||||
this.selectedDate = value;
|
||||
this.visibleDate = value;
|
||||
this.callback = callback;
|
||||
this.refresh();
|
||||
this.element.show();
|
||||
this.element.setXY(this.constrainToViewport ? this.constrainXY(x, y) : [x, y]);
|
||||
this.shadow.show();
|
||||
this.shadow.setRegion(this.element.getRegion());
|
||||
this.element.dom.tabIndex = 1;
|
||||
this.element.focus();
|
||||
YAHOO.util.Event.on(document, "mousedown", this.mouseDownHandler);
|
||||
YAHOO.util.Event.on(document, "keydown", this.keyDownHandler);
|
||||
YAHOO.util.Event.on(document, "mousewheel", this.wheelHandler);
|
||||
YAHOO.util.Event.on(document, "DOMMouseScroll", this.wheelHandler);
|
||||
},
|
||||
|
||||
constrainXY : function(x, y){
|
||||
var w = YAHOO.util.Dom.getViewportWidth();
|
||||
var h = YAHOO.util.Dom.getViewportHeight();
|
||||
var size = this.element.getSize();
|
||||
return [
|
||||
Math.min(w-size.width, x),
|
||||
Math.min(h-size.height, y)
|
||||
];
|
||||
},
|
||||
|
||||
hide : function(){
|
||||
this.shadow.hide();
|
||||
this.element.hide();
|
||||
YAHOO.util.Event.removeListener(document, "mousedown", this.mouseDownHandler);
|
||||
YAHOO.util.Event.removeListener(document, "keydown", this.keyDownHandler);
|
||||
YAHOO.util.Event.removeListener(document, "mousewheel", this.wheelHandler);
|
||||
YAHOO.util.Event.removeListener(document, "DOMMouseScroll", this.wheelHandler);
|
||||
},
|
||||
|
||||
setSelectedDate : function(date){
|
||||
this.selectedDate = date;
|
||||
},
|
||||
|
||||
getSelectedDate : function(){
|
||||
return this.selectedDate;
|
||||
},
|
||||
|
||||
showPrevMonth : function(){
|
||||
this.visibleDate = this.getPrevMonth(this.visibleDate);
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
showNextMonth : function(){
|
||||
this.visibleDate = this.getNextMonth(this.visibleDate);
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
showPrevYear : function(){
|
||||
var d = this.visibleDate;
|
||||
this.visibleDate = new Date(d.getFullYear()-1, d.getMonth(), d.getDate());
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
showNextYear : function(){
|
||||
var d = this.visibleDate;
|
||||
this.visibleDate = new Date(d.getFullYear()+1, d.getMonth(), d.getDate());
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
handleMouseDown : function(e){
|
||||
var target = e.getTarget();
|
||||
if(target != this.element.dom && !YAHOO.util.Dom.isAncestor(this.element.dom, target)){
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
handleKeyDown : function(e){
|
||||
switch(e.browserEvent.keyCode){
|
||||
case e.LEFT:
|
||||
this.showPrevMonth();
|
||||
e.stopEvent();
|
||||
break;
|
||||
case e.RIGHT:
|
||||
this.showNextMonth();
|
||||
e.stopEvent();
|
||||
break;
|
||||
case e.DOWN:
|
||||
this.showPrevYear();
|
||||
e.stopEvent();
|
||||
break;
|
||||
case e.UP:
|
||||
this.showNextYear();
|
||||
e.stopEvent();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleMouseWheel : function(e){
|
||||
var delta = e.getWheelDelta();
|
||||
if(delta > 0){
|
||||
this.showPrevMonth();
|
||||
e.stopEvent();
|
||||
} else if(delta < 0){
|
||||
this.showNextMonth();
|
||||
e.stopEvent();
|
||||
}
|
||||
},
|
||||
|
||||
handleClick : function(e){
|
||||
var d = this.visibleDate;
|
||||
var t = e.getTarget();
|
||||
if(t && t.className){
|
||||
var cls = t.className.split(' ')[0];
|
||||
switch(cls){
|
||||
case 'active':
|
||||
this.handleSelection(new Date(d.getFullYear(), d.getMonth(), parseInt(t.innerHTML)));
|
||||
break;
|
||||
case 'prevday':
|
||||
var p = this.getPrevMonth(d);
|
||||
this.handleSelection(new Date(p.getFullYear(), p.getMonth(), parseInt(t.innerHTML)));
|
||||
break;
|
||||
case 'nextday':
|
||||
var n = this.getNextMonth(d);
|
||||
this.handleSelection(new Date(n.getFullYear(), n.getMonth(), parseInt(t.innerHTML)));
|
||||
break;
|
||||
case 'ypopcal-today':
|
||||
this.handleSelection(new Date());
|
||||
break;
|
||||
case 'next-month':
|
||||
this.showNextMonth();
|
||||
break;
|
||||
case 'prev-month':
|
||||
this.showPrevMonth();
|
||||
break;
|
||||
}
|
||||
}
|
||||
e.stopEvent();
|
||||
},
|
||||
|
||||
selectToday : function(){
|
||||
this.handleSelection(new Date());
|
||||
},
|
||||
|
||||
handleSelection: function(date){
|
||||
this.selectedDate = date;
|
||||
this.callback(date);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
getPrevMonth : function(d){
|
||||
var m = d.getMonth();var y = d.getFullYear();
|
||||
return (m == 0 ? new Date(--y, 11, 1) : new Date(y, --m, 1));
|
||||
},
|
||||
|
||||
getNextMonth : function(d){
|
||||
var m = d.getMonth();var y = d.getFullYear();
|
||||
return (m == 11 ? new Date(++y, 0, 1) : new Date(y, ++m, 1));
|
||||
},
|
||||
|
||||
getDaysInMonth : function(m, y){
|
||||
return (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) ? 31 : (m == 4 || m == 6 || m == 9 || m == 11) ? 30 : this.isLeapYear(y) ? 29 : 28;
|
||||
},
|
||||
|
||||
isLeapYear : function(y){
|
||||
return (((y % 4) == 0) && ((y % 100) != 0) || ((y % 400) == 0));
|
||||
},
|
||||
|
||||
clearTime : function(date){
|
||||
if(date){
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
date.setMilliseconds(0);
|
||||
}
|
||||
return date;
|
||||
},
|
||||
|
||||
refresh : function(){
|
||||
var d = this.visibleDate;
|
||||
this.buildInnerCal(d);
|
||||
this.calHead.update(this.monthNames[d.getMonth()] + ' ' + d.getFullYear());
|
||||
if(this.element.isVisible()){
|
||||
this.shadow.setRegion(this.element.getRegion());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This code is not pretty, but it is fast!
|
||||
* @ignore
|
||||
*/
|
||||
YAHOO.ext.DatePicker.prototype.buildControl = function(parentElement){
|
||||
var c = document.createElement('div');
|
||||
c.style.position = 'absolute';
|
||||
c.style.visibility = 'hidden';
|
||||
document.body.appendChild(c);
|
||||
var html = '<iframe id="'+this.id+'_shdw" frameborder="0" class="ypopcal-shadow" src="'+YAHOO.ext.SSL_SECURE_URL+'"></iframe>' +
|
||||
'<div hidefocus="true" class="ypopcal" id="'+this.id+'">' +
|
||||
'<table class="ypopcal-head" border=0 cellpadding=0 cellspacing=0><tbody><tr><td class="ypopcal-arrow"><div class="prev-month"> </div></td><td class="ypopcal-month"> </td><td class="ypopcal-arrow"><div class="next-month"> </div></td></tr></tbody></table>' +
|
||||
'<center><div class="ypopcal-inner">';
|
||||
html += "<table border=0 cellspacing=0 class=\"ypopcal-table\"><thead><tr class=\"ypopcal-daynames\">";
|
||||
var names = this.dayNames;
|
||||
for(var i = 0; i < names.length; i++){
|
||||
html += '<td>' + names[i].substr(0, 1) + '</td>';
|
||||
}
|
||||
html+= "</tr></thead><tbody><tr>";
|
||||
for(var i = 0; i < 42; i++) {
|
||||
if(i % 7 == 0 && i != 0){
|
||||
html += '</tr><tr>';
|
||||
}
|
||||
html += "<td> </td>";
|
||||
}
|
||||
html += "</tr></tbody></table>";
|
||||
html += '</div><button class="ypopcal-today">'+this.todayText+'</button></center></div>';
|
||||
c.innerHTML = html;
|
||||
this.shadow = getEl(c.childNodes[0], true);
|
||||
this.shadow.enableDisplayMode('block');
|
||||
this.element = getEl(c.childNodes[1], true);
|
||||
this.element.enableDisplayMode('block');
|
||||
document.body.appendChild(this.shadow.dom);
|
||||
document.body.appendChild(this.element.dom);
|
||||
document.body.removeChild(c);
|
||||
this.element.on("selectstart", function(){return false;});
|
||||
var tbody = this.element.dom.getElementsByTagName('tbody')[1];
|
||||
this.cells = tbody.getElementsByTagName('td');
|
||||
this.calHead = this.element.getChildrenByClassName('ypopcal-month', 'td')[0];
|
||||
this.element.mon('mousedown', this.handleClick, this, true);
|
||||
};
|
||||
|
||||
YAHOO.ext.DatePicker.prototype.buildInnerCal = function(dateVal){
|
||||
var days = this.getDaysInMonth(dateVal.getMonth() + 1, dateVal.getFullYear());
|
||||
var firstOfMonth = new Date(dateVal.getFullYear(), dateVal.getMonth(), 1);
|
||||
var startingPos = firstOfMonth.getDay();
|
||||
if(startingPos == 0) startingPos = 7;
|
||||
var pm = this.getPrevMonth(dateVal);
|
||||
var prevStart = this.getDaysInMonth(pm.getMonth()+1, pm.getFullYear())-startingPos;
|
||||
var cells = this.cells;
|
||||
days += startingPos;
|
||||
|
||||
// convert everything to numbers so it's fast
|
||||
var day = 86400000;
|
||||
var date = this.clearTime(new Date(pm.getFullYear(), pm.getMonth(), prevStart));
|
||||
var today = this.clearTime(new Date()).getTime();
|
||||
var sel = this.selectedDate ? this.clearTime(this.selectedDate).getTime() : today + 1; //today +1 will never match anything
|
||||
var min = this.minDate ? this.clearTime(this.minDate).getTime() : Number.NEGATIVE_INFINITY;
|
||||
var max = this.maxDate ? this.clearTime(this.maxDate).getTime() : Number.POSITIVE_INFINITY;
|
||||
var ddMatch = this.disabledDatesRE;
|
||||
var ddText = this.disabledDatesText;
|
||||
var ddays = this.disabledDays;
|
||||
var ddaysText = this.disabledDaysText;
|
||||
var format = this.format;
|
||||
|
||||
var setCellClass = function(cal, cell, d){
|
||||
cell.title = '';
|
||||
var t = d.getTime();
|
||||
if(t == today){
|
||||
cell.className += ' today';
|
||||
cell.title = cal.todayText;
|
||||
}
|
||||
if(t == sel){
|
||||
cell.className += ' selected';
|
||||
}
|
||||
// disabling
|
||||
if(t < min) {
|
||||
cell.className = ' ypopcal-disabled';
|
||||
cell.title = cal.minText;
|
||||
return;
|
||||
}
|
||||
if(t > max) {
|
||||
cell.className = ' ypopcal-disabled';
|
||||
cell.title = cal.maxText;
|
||||
return;
|
||||
}
|
||||
if(ddays){
|
||||
var day = d.getDay();
|
||||
for(var i = 0; i < ddays.length; i++) {
|
||||
if(day === ddays[i]){
|
||||
cell.title = ddaysText;
|
||||
cell.className = ' ypopcal-disabled';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ddMatch && format){
|
||||
var fvalue = d.format(format);
|
||||
if(ddMatch.test(fvalue)){
|
||||
cell.title = ddText.replace('%0', fvalue);
|
||||
cell.className = ' ypopcal-disabled';
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var i = 0;
|
||||
for(; i < startingPos; i++) {
|
||||
cells[i].innerHTML = (++prevStart);
|
||||
date.setDate(date.getDate()+1);
|
||||
cells[i].className = 'prevday';
|
||||
setCellClass(this, cells[i], date);
|
||||
}
|
||||
for(; i < days; i++){
|
||||
intDay = i - startingPos + 1;
|
||||
cells[i].innerHTML = (intDay);
|
||||
date.setDate(date.getDate()+1);
|
||||
cells[i].className = 'active';
|
||||
setCellClass(this, cells[i], date);
|
||||
}
|
||||
var extraDays = 0;
|
||||
for(; i < 42; i++) {
|
||||
cells[i].innerHTML = (++extraDays);
|
||||
date.setDate(date.getDate()+1);
|
||||
cells[i].className = 'nextday';
|
||||
setCellClass(this, cells[i], date);
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.ext.DatePicker.prototype.todayText = "Today";
|
||||
YAHOO.ext.DatePicker.prototype.minDate = null;
|
||||
YAHOO.ext.DatePicker.prototype.maxDate = null;
|
||||
YAHOO.ext.DatePicker.prototype.minText = "This date is before the minimum date";
|
||||
YAHOO.ext.DatePicker.prototype.maxText = "This date is after the maximum date";
|
||||
YAHOO.ext.DatePicker.prototype.format = 'm/d/y';
|
||||
YAHOO.ext.DatePicker.prototype.disabledDays = null;
|
||||
YAHOO.ext.DatePicker.prototype.disabledDaysText = '';
|
||||
YAHOO.ext.DatePicker.prototype.disabledDatesRE = null;
|
||||
YAHOO.ext.DatePicker.prototype.disabledDatesText = '';
|
||||
YAHOO.ext.DatePicker.prototype.constrainToViewport = true;
|
||||
|
||||
|
||||
YAHOO.ext.DatePicker.prototype.monthNames = Date.monthNames;
|
||||
|
||||
YAHOO.ext.DatePicker.prototype.dayNames = Date.dayNames;
|
||||
216
frontend/beta/js/YUI-extensions/widgets/InlineEditor.js
Normal file
216
frontend/beta/js/YUI-extensions/widgets/InlineEditor.js
Normal file
@@ -0,0 +1,216 @@
|
||||
YAHOO.ext.InlineEditor = function(config, existingEl){
|
||||
YAHOO.ext.util.Config.apply(this, config);
|
||||
var dh = YAHOO.ext.DomHelper;
|
||||
this.wrap = dh.append(this.container || document.body, {
|
||||
tag:'div',
|
||||
cls:'yinline-editor-wrap'
|
||||
}, true);
|
||||
|
||||
this.textSizeEl = dh.append(document.body, {
|
||||
tag: 'div',
|
||||
cls: 'yinline-editor-sizer ' + (this.cls || '')
|
||||
});
|
||||
if(YAHOO.ext.util.Browser.isSafari){ // extra padding for safari's textboxes
|
||||
this.textSizeEl.style.padding = '4px';
|
||||
YAHOO.util.Dom.setStyle(this.textSizeEl, 'padding-right', '10px');
|
||||
}
|
||||
|
||||
if(!YAHOO.ext.util.Browser.isGecko){ // no one else needs FireFox cursor fix
|
||||
this.wrap.setStyle('overflow', 'hidden');
|
||||
}
|
||||
|
||||
if(existingEl){
|
||||
this.el = getEl(existingEl);
|
||||
}
|
||||
if(!this.el){
|
||||
this.id = this.id || YAHOO.util.Dom.generateId();
|
||||
if(!this.multiline){
|
||||
this.el = this.wrap.createChild({
|
||||
tag: 'input',
|
||||
name: this.name || this.id,
|
||||
id: this.id,
|
||||
type: this.type || 'text',
|
||||
autocomplete: 'off',
|
||||
value: this.value || '',
|
||||
cls: 'yinline-editor ' + (this.cls || ''),
|
||||
maxlength: this.maxLength || ''
|
||||
});
|
||||
}else{
|
||||
this.el = this.wrap.createChild({
|
||||
tag: 'textarea',
|
||||
name: this.name || this.id,
|
||||
id: this.id,
|
||||
html: this.value || '',
|
||||
cls: 'yinline-editor yinline-editor-multiline ' + (this.cls || ''),
|
||||
wrap: 'none'
|
||||
});
|
||||
}
|
||||
}else{
|
||||
this.wrap.dom.appendChild(this.el.dom);
|
||||
}
|
||||
this.el.addKeyMap([{
|
||||
key: [10, 13],
|
||||
fn: this.onEnter,
|
||||
scope: this
|
||||
},{
|
||||
key: 27,
|
||||
fn: this.onEsc,
|
||||
scope: this
|
||||
}]);
|
||||
this.el.mon('keyup', this.onKeyUp, this, true);
|
||||
this.el.on('blur', this.onBlur, this, true);
|
||||
this.el.swallowEvent('keydown');
|
||||
this.events = {
|
||||
'startedit' : true,
|
||||
'beforecomplete' : true,
|
||||
'complete' : true
|
||||
};
|
||||
this.editing = false;
|
||||
this.autoSizeTask = new YAHOO.ext.util.DelayedTask(this.autoSize, this);
|
||||
};
|
||||
|
||||
YAHOO.extendX(YAHOO.ext.InlineEditor, YAHOO.ext.util.Observable, {
|
||||
onEnter : function(k, e){
|
||||
if(this.multiline && (e.ctrlKey || e.shiftKey)){
|
||||
return;
|
||||
}else{
|
||||
this.completeEdit();
|
||||
e.stopEvent();
|
||||
}
|
||||
},
|
||||
|
||||
onEsc : function(){
|
||||
if(this.ignoreNoChange){
|
||||
this.revert(true);
|
||||
}else{
|
||||
this.revert(false);
|
||||
this.completeEdit();
|
||||
}
|
||||
},
|
||||
|
||||
onBlur : function(){
|
||||
if(this.editing && this.completeOnBlur !== false){
|
||||
this.completeEdit();
|
||||
}
|
||||
},
|
||||
|
||||
startEdit : function(el, value){
|
||||
this.boundEl = YAHOO.util.Dom.get(el);
|
||||
if(this.hideEl !== false){
|
||||
this.boundEl.style.visibility = 'hidden';
|
||||
}
|
||||
var v = value || this.boundEl.innerHTML;
|
||||
this.startValue = v;
|
||||
this.setValue(v);
|
||||
this.moveTo(YAHOO.util.Dom.getXY(this.boundEl));
|
||||
this.editing = true;
|
||||
if(YAHOO.ext.QuickTips){
|
||||
YAHOO.ext.QuickTips.disable();
|
||||
}
|
||||
this.show.defer(10, this);
|
||||
},
|
||||
|
||||
onKeyUp : function(e){
|
||||
var k = e.getKey();
|
||||
if(this.editing && (k < 33 || k > 40) && k != 27){
|
||||
this.autoSizeTask.delay(50);
|
||||
}
|
||||
},
|
||||
|
||||
completeEdit : function(){
|
||||
var v = this.getValue();
|
||||
if(this.revertBlank !== false && v.length < 1){
|
||||
v = this.startValue;
|
||||
this.revert();
|
||||
}
|
||||
if(v == this.startValue && this.ignoreNoChange){
|
||||
this.hide();
|
||||
}
|
||||
if(this.fireEvent('beforecomplete', this, v, this.startValue) !== false){
|
||||
if(this.updateEl !== false && this.boundEl){
|
||||
this.boundEl.innerHTML = v;
|
||||
}
|
||||
this.hide();
|
||||
this.fireEvent('complete', this, v, this.startValue);
|
||||
}
|
||||
},
|
||||
|
||||
revert : function(hide){
|
||||
this.setValue(this.startValue);
|
||||
if(hide){
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
show : function(){
|
||||
this.autoSize();
|
||||
this.wrap.show();
|
||||
this.el.focus();
|
||||
if(this.selectOnEdit !== false){
|
||||
this.el.dom.select();
|
||||
}
|
||||
},
|
||||
|
||||
hide : function(){
|
||||
this.editing = false;
|
||||
this.wrap.hide();
|
||||
this.wrap.setLeftTop(-10000,-10000);
|
||||
this.el.blur();
|
||||
if(this.hideEl !== false){
|
||||
this.boundEl.style.visibility = 'visible';
|
||||
}
|
||||
if(YAHOO.ext.QuickTips){
|
||||
YAHOO.ext.QuickTips.enable();
|
||||
}
|
||||
},
|
||||
|
||||
setValue : function(v){
|
||||
this.el.dom.value = v;
|
||||
},
|
||||
|
||||
getValue : function(){
|
||||
return this.el.dom.value;
|
||||
},
|
||||
|
||||
autoSize : function(){
|
||||
var el = this.el;
|
||||
var wrap = this.wrap;
|
||||
var v = el.dom.value;
|
||||
var ts = this.textSizeEl;
|
||||
if(v.length < 1){
|
||||
ts.innerHTML = "  ";
|
||||
}else{
|
||||
v = v.replace(/[<> ]/g, ' ');
|
||||
if(this.multiline){
|
||||
v = v.replace(/\n/g, '<br /> ');
|
||||
}
|
||||
ts.innerHTML = v;
|
||||
}
|
||||
var ww = wrap.dom.offsetWidth;
|
||||
var wh = wrap.dom.offsetHeight;
|
||||
var w = ts.offsetWidth;
|
||||
var h = ts.offsetHeight;
|
||||
// lots of magic numbers in this block - wtf?
|
||||
// the logic is to prevent the scrollbars from flashing
|
||||
// in firefox. Updates the right element first
|
||||
// so there's never overflow.
|
||||
if(ww > w+4){
|
||||
el.setWidth(w+4);
|
||||
wrap.setWidth(w+8);
|
||||
}else{
|
||||
wrap.setWidth(w+8);
|
||||
el.setWidth(w+4);
|
||||
}
|
||||
if(wh > h+4){
|
||||
el.setHeight(h);
|
||||
wrap.setHeight(h+4);
|
||||
}else{
|
||||
wrap.setHeight(h+4);
|
||||
el.setHeight(h);
|
||||
}
|
||||
},
|
||||
|
||||
moveTo : function(xy){
|
||||
this.wrap.setXY(xy);
|
||||
}
|
||||
});
|
||||
230
frontend/beta/js/YUI-extensions/widgets/MessageBox.js
Normal file
230
frontend/beta/js/YUI-extensions/widgets/MessageBox.js
Normal file
@@ -0,0 +1,230 @@
|
||||
YAHOO.ext.MessageBox = function(){
|
||||
var dlg, opt, mask;
|
||||
var bodyEl, msgEl, textboxEl, textareaEl, progressEl, pp;
|
||||
var buttons, activeTextEl, bwidth;
|
||||
|
||||
var handleButton = function(button){
|
||||
if(typeof opt.fn == 'function'){
|
||||
if(opt.fn.call(opt.scope||window, button, activeTextEl.dom.value) !== false){
|
||||
dlg.hide();
|
||||
}
|
||||
}else{
|
||||
dlg.hide();
|
||||
}
|
||||
};
|
||||
var updateButtons = function(b){
|
||||
var width = 0;
|
||||
if(!b){
|
||||
buttons['ok'].hide();
|
||||
buttons['cancel'].hide();
|
||||
buttons['yes'].hide();
|
||||
buttons['no'].hide();
|
||||
return width;
|
||||
}
|
||||
for(var k in buttons){
|
||||
if(typeof buttons[k] != 'function'){
|
||||
if(b[k]){
|
||||
buttons[k].show();
|
||||
buttons[k].setText(typeof b[k] == 'string' ? b[k] : YAHOO.ext.MessageBox.buttonText[k]);
|
||||
width += buttons[k].el.getWidth()+15;
|
||||
}else{
|
||||
buttons[k].hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
return width;
|
||||
};
|
||||
|
||||
return {
|
||||
getDialog : function(){
|
||||
if(!dlg){
|
||||
dlg = new YAHOO.ext.BasicDialog('mb-dlg', {
|
||||
autoCreate : true,
|
||||
shadow: true,
|
||||
draggable: true,
|
||||
resizable:false,
|
||||
constraintoviewport:true,
|
||||
fixedcenter:true,
|
||||
shim:true,
|
||||
modal: true,
|
||||
width:400, height:100,
|
||||
buttonAlign:'center',
|
||||
closeClick : function(){
|
||||
if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
|
||||
handleButton('no');
|
||||
}else{
|
||||
handleButton('cancel');
|
||||
}
|
||||
}
|
||||
});
|
||||
dlg.closeClick = function(){
|
||||
alert('wtf');
|
||||
};
|
||||
mask = dlg.mask;
|
||||
dlg.addKeyListener(27, dlg.hide, dlg);
|
||||
buttons = {};
|
||||
buttons['ok'] = dlg.addButton(this.buttonText['ok'], handleButton.createCallback('ok'));
|
||||
buttons['yes'] = dlg.addButton(this.buttonText['yes'], handleButton.createCallback('yes'));
|
||||
buttons['no'] = dlg.addButton(this.buttonText['no'], handleButton.createCallback('no'));
|
||||
buttons['cancel'] = dlg.addButton(this.buttonText['cancel'], handleButton.createCallback('cancel'));
|
||||
bodyEl = dlg.body.createChild({
|
||||
tag:'div',
|
||||
html:'<span class="ext-mb-text"></span><br /><input type="text" class="ext-mb-input"><textarea class="ext-mb-textarea"></textarea><div class="ext-mb-progress-wrap"><div class="ext-mb-progress"><div class="ext-mb-progress-bar"> </div></div></div>'
|
||||
});
|
||||
msgEl = bodyEl.dom.firstChild;
|
||||
textboxEl = getEl(bodyEl.dom.childNodes[2]);
|
||||
textboxEl.enableDisplayMode();
|
||||
textboxEl.addKeyListener([10,13], function(){
|
||||
if(dlg.isVisible() && opt && opt.buttons){
|
||||
if(opt.buttons.ok){
|
||||
handleButton('ok');
|
||||
}else if(opt.buttons.yes){
|
||||
handleButton('yes');
|
||||
}
|
||||
}
|
||||
});
|
||||
textareaEl = getEl(bodyEl.dom.childNodes[3]);
|
||||
textareaEl.enableDisplayMode();
|
||||
progressEl = getEl(bodyEl.dom.childNodes[4]);
|
||||
progressEl.enableDisplayMode();
|
||||
pp = getEl(progressEl.dom.firstChild.firstChild);
|
||||
}
|
||||
return dlg;
|
||||
},
|
||||
|
||||
updateText : function(text){
|
||||
if(!dlg.isVisible() && !opt.width){
|
||||
dlg.resizeTo(this.maxWidth, 100); // resize first so content is never clipped from previous shows
|
||||
}
|
||||
msgEl.innerHTML = text;
|
||||
var w = Math.max(Math.min(opt.width || msgEl.offsetWidth, this.maxWidth),
|
||||
Math.max(opt.minWidth || this.minWidth, bwidth));
|
||||
if(opt.prompt){
|
||||
activeTextEl.setWidth(w);
|
||||
}
|
||||
dlg.setContentSize(w, bodyEl.getHeight());
|
||||
},
|
||||
|
||||
updateProgress : function(value, text){
|
||||
if(text){
|
||||
this.updateText(text);
|
||||
}
|
||||
pp.setWidth(value*progressEl.dom.firstChild.offsetWidth);
|
||||
},
|
||||
|
||||
isVisible : function(){
|
||||
return dlg && dlg.isVisible();
|
||||
},
|
||||
|
||||
hide : function(){
|
||||
if(this.isVisible()){
|
||||
dlg.hide();
|
||||
}
|
||||
},
|
||||
|
||||
show : function(options){
|
||||
var d = this.getDialog();
|
||||
opt = options;
|
||||
d.setTitle(opt.title || ' ');
|
||||
d.close.setDisplayed(opt.closable !== false);
|
||||
activeTextEl = textboxEl;
|
||||
opt.prompt = opt.prompt || (opt.multiline ? true : false)
|
||||
if(opt.prompt){
|
||||
if(opt.multiline){
|
||||
textboxEl.hide();
|
||||
textareaEl.show();
|
||||
textareaEl.setHeight(typeof opt.multiline == 'number' ?
|
||||
opt.multiline : this.defaultTextHeight);
|
||||
activeTextEl = textareaEl;
|
||||
}else{
|
||||
textboxEl.show();
|
||||
textareaEl.hide();
|
||||
}
|
||||
}else{
|
||||
textboxEl.hide();
|
||||
textareaEl.hide();
|
||||
}
|
||||
progressEl.setDisplayed(opt.progress === true);
|
||||
this.updateProgress(0);
|
||||
activeTextEl.dom.value = opt.value || '';
|
||||
if(opt.prompt){
|
||||
dlg.setDefaultButton(activeTextEl);
|
||||
}else{
|
||||
var bs = opt.buttons;
|
||||
var db = null;
|
||||
if(bs && bs.ok){
|
||||
db = buttons['ok'];
|
||||
}else if(bs && bs.yes){
|
||||
db = buttons['yes'];
|
||||
}
|
||||
dlg.setDefaultButton(db);
|
||||
}
|
||||
bwidth = updateButtons(opt.buttons);
|
||||
this.updateText(opt.msg);
|
||||
d.modal = opt.modal !== false;
|
||||
d.mask = opt.modal !== false ? mask : false;
|
||||
d.animateTarget = null;
|
||||
d.show(options.animEl);
|
||||
},
|
||||
|
||||
progress : function(title, msg){
|
||||
this.show({
|
||||
title : title,
|
||||
msg : msg,
|
||||
buttons: false,
|
||||
progress:true,
|
||||
closable:false
|
||||
});
|
||||
},
|
||||
|
||||
alert : function(title, msg, fn, scope){
|
||||
this.show({
|
||||
title : title,
|
||||
msg : msg,
|
||||
buttons: this.OK,
|
||||
fn: fn,
|
||||
scope : scope
|
||||
});
|
||||
},
|
||||
|
||||
confirm : function(title, msg, fn, scope){
|
||||
this.show({
|
||||
title : title,
|
||||
msg : msg,
|
||||
buttons: this.YESNO,
|
||||
fn: fn,
|
||||
scope : scope
|
||||
});
|
||||
},
|
||||
|
||||
prompt : function(title, msg, fn, scope, multiline){
|
||||
this.show({
|
||||
title : title,
|
||||
msg : msg,
|
||||
buttons: this.OKCANCEL,
|
||||
fn: fn,
|
||||
minWidth:250,
|
||||
scope : scope,
|
||||
prompt:true,
|
||||
multiline: multiline
|
||||
});
|
||||
},
|
||||
|
||||
OK : {ok:true},
|
||||
YESNO : {yes:true, no:true},
|
||||
OKCANCEL : {ok:true, cancel:true},
|
||||
YESNOCANCEL : {yes:true, no:true, cancel:true},
|
||||
|
||||
defaultTextHeight:75,
|
||||
maxWidth : 500,
|
||||
minWidth : 100,
|
||||
buttonText : {
|
||||
ok : 'OK',
|
||||
cancel : 'Cancel',
|
||||
yes : 'Yes',
|
||||
no : 'No'
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
YAHOO.ext.Msg = YAHOO.ext.MessageBox;
|
||||
311
frontend/beta/js/YUI-extensions/widgets/QuickTips.js
Normal file
311
frontend/beta/js/YUI-extensions/widgets/QuickTips.js
Normal file
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* @class YAHOO.ext.QuickTips
|
||||
* @singleton
|
||||
*/
|
||||
YAHOO.ext.QuickTips = function(){
|
||||
var el, tipBody, tipTitle, tm, cfg, close, tagEls = {}, reader, esc, anim, removeCls = null;
|
||||
var ce, bd, xy;
|
||||
var visible = false, disabled = true, inited = false;
|
||||
var showProc = hideProc = dismissProc = 1, locks = [];
|
||||
var E = YAHOO.util.Event, dd;
|
||||
|
||||
var onOver = function(e){
|
||||
if(disabled){
|
||||
return;
|
||||
}
|
||||
var t = E.getTarget(e);
|
||||
if(!t){
|
||||
return;
|
||||
}
|
||||
if(ce && t == ce.el){
|
||||
clearTimeout(hideProc);
|
||||
return;
|
||||
}
|
||||
if(t && tagEls[t.id]){
|
||||
tagEls[t.id].el = t;
|
||||
showProc = show.defer(tm.showDelay, tm, [tagEls[t.id]]);
|
||||
return;
|
||||
}
|
||||
var ttp = reader.getAttribute(t, cfg.attribute);
|
||||
if(!ttp && tm.interceptTitles && t.title){
|
||||
ttp = t.title;
|
||||
t.title = '';
|
||||
if(reader.useNS){
|
||||
t.setAttributeNS('y', 'qtip', ttp);
|
||||
}else{
|
||||
t.setAttribute('qtip', ttp);
|
||||
}
|
||||
}
|
||||
if(ttp){
|
||||
xy = E.getXY(e);
|
||||
xy[0] += 12; xy[1] += 20;
|
||||
showProc = show.defer(tm.showDelay, tm, [{
|
||||
el: t,
|
||||
text: ttp,
|
||||
width: reader.getAttribute(t, cfg.width),
|
||||
autoHide: reader.getAttribute(t, cfg.hide) != 'user',
|
||||
title: reader.getAttribute(t, cfg.title),
|
||||
cls: reader.getAttribute(t, cfg.cls)
|
||||
}]);
|
||||
}
|
||||
};
|
||||
|
||||
var onOut = function(e){
|
||||
clearTimeout(showProc);
|
||||
var t = E.getTarget(e);
|
||||
if(t && ce && ce.el == t && (tm.autoHide && ce.autoHide !== false)){
|
||||
hideProc = setTimeout(hide, tm.hideDelay);
|
||||
}
|
||||
};
|
||||
|
||||
var onMove = function(e){
|
||||
if(disabled){
|
||||
return;
|
||||
}
|
||||
xy = E.getXY(e);
|
||||
xy[0] += 12; xy[1] += 20;
|
||||
if(tm.trackMouse && ce){
|
||||
el.setXY(xy);
|
||||
}
|
||||
};
|
||||
|
||||
var onDown = function(e){
|
||||
clearTimeout(showProc);
|
||||
clearTimeout(hideProc);
|
||||
if(!e.within(el)){
|
||||
if(tm.hideOnClick && ce && ce.autoHide !== false){
|
||||
hide();
|
||||
tm.disable();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var onUp = function(e){
|
||||
tm.enable();
|
||||
}
|
||||
|
||||
var show = function(o){
|
||||
if(disabled){
|
||||
return;
|
||||
}
|
||||
clearTimeout(dismissProc);
|
||||
stopAnim();
|
||||
ce = o;
|
||||
if(removeCls){ // in case manually hidden
|
||||
el.removeClass(removeCls);
|
||||
removeCls = null;
|
||||
}
|
||||
if(ce.cls){
|
||||
el.addClass(ce.cls);
|
||||
removeCls = ce.cls;
|
||||
}
|
||||
if(ce.title){
|
||||
tipTitleText.update(ce.title);
|
||||
tipTitle.show();
|
||||
}else{
|
||||
tipTitle.hide();
|
||||
}
|
||||
tipBody.update(o.text);
|
||||
if(!ce.width){
|
||||
if(tipBody.dom.style.width){
|
||||
tipBody.dom.style.width = '';
|
||||
}
|
||||
if(tipBody.dom.offsetWidth > tm.maxWidth){
|
||||
tipBody.setWidth(tm.maxWidth);
|
||||
}
|
||||
}else{
|
||||
tipBody.setWidth(ce.width);
|
||||
}
|
||||
if(!ce.autoHide){
|
||||
close.setDisplayed(true);
|
||||
if(dd){
|
||||
dd.unlock();
|
||||
}
|
||||
}else{
|
||||
close.setDisplayed(false);
|
||||
if(dd){
|
||||
dd.lock();
|
||||
}
|
||||
}
|
||||
if(xy){
|
||||
el.setXY(xy);
|
||||
}
|
||||
if(tm.animate){
|
||||
anim.attributes = {opacity:{to:1}};
|
||||
el.setOpacity(.1);
|
||||
el.setStyle('visibility', 'visible');
|
||||
anim.animateX(afterShow);
|
||||
}else{
|
||||
afterShow();
|
||||
}
|
||||
};
|
||||
|
||||
var afterShow = function(){
|
||||
if(ce){
|
||||
el.show();
|
||||
esc.enable();
|
||||
if(tm.autoDismiss && ce.autoHide !== false){
|
||||
dismissProc = setTimeout(hide, tm.autoDismissDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var hide = function(noanim){
|
||||
clearTimeout(dismissProc);
|
||||
clearTimeout(hideProc);
|
||||
ce = null;
|
||||
if(el.isVisible()){
|
||||
esc.disable();
|
||||
stopAnim();
|
||||
if(noanim !== true && tm.animate){
|
||||
anim.attributes = {opacity:{to:.1}};
|
||||
el.beforeAction();
|
||||
anim.animateX(afterHide);
|
||||
}else{
|
||||
afterHide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var afterHide = function(){
|
||||
el.hide();
|
||||
if(removeCls){
|
||||
el.removeClass(removeCls);
|
||||
removeCls = null;
|
||||
}
|
||||
}
|
||||
|
||||
var stopAnim = function(){
|
||||
if(anim && anim.isAnimated()){
|
||||
anim.stop();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init : function(){
|
||||
if(YAHOO.ext.util.Browser.isIE && !YAHOO.ext.util.Browser.isIE7){
|
||||
return;
|
||||
}
|
||||
tm = YAHOO.ext.QuickTips;
|
||||
cfg = tm.tagConfig;
|
||||
reader = new YAHOO.ext.CustomTagReader(cfg.namespace);
|
||||
if(!inited){
|
||||
el = new YAHOO.ext.Layer({cls:'ytip', shadow:true, useDisplay: false});
|
||||
el.update('<div class="ytip-hd-left"><div class="ytip-hd-right"><div class="ytip-hd"></div></div></div>');
|
||||
tipTitle = getEl(el.dom.firstChild);
|
||||
tipTitleText = getEl(el.dom.firstChild.firstChild.firstChild);
|
||||
tipTitle.enableDisplayMode('block');
|
||||
tipBody = el.createChild({tag:'div', cls:'ytip-bd'});
|
||||
close = el.createChild({tag:'div', cls:'ytip-close'});
|
||||
close.on('click', hide);
|
||||
d = getEl(document);
|
||||
d.mon('mousedown', onDown);
|
||||
d.on('mouseup', onUp);
|
||||
d.on('mouseover', onOver);
|
||||
d.on('mouseout', onOut);
|
||||
d.on('mousemove', onMove);
|
||||
esc = d.addKeyListener(27, hide);
|
||||
esc.disable();
|
||||
if(tm.animate){
|
||||
anim = new YAHOO.util.Anim(el.dom, {}, .1);
|
||||
}
|
||||
if(YAHOO.util.DD){
|
||||
dd = el.initDD('default', null, {
|
||||
onDrag : function(){
|
||||
el.sync();
|
||||
}
|
||||
});
|
||||
dd.setHandleElId(tipTitleText.id);
|
||||
dd.lock();
|
||||
}
|
||||
inited = true;
|
||||
}
|
||||
this.scan(document.body);
|
||||
this.enable();
|
||||
},
|
||||
|
||||
tips : function(config){
|
||||
var cs = config instanceof Array ? config : arguments;
|
||||
for(var i = 0, len = cs.length; i < len; i++) {
|
||||
var c = cs[i];
|
||||
var target = c.target;
|
||||
if(target){
|
||||
if(target instanceof Array){
|
||||
for(var j = 0, jlen = target.length; j < jlen; j++){
|
||||
tagEls[target[j]] = c;
|
||||
}
|
||||
}else{
|
||||
tagEls[target] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
enable : function(){
|
||||
if(inited){
|
||||
locks.pop();
|
||||
if(locks.length < 1){
|
||||
disabled = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
disable : function(){
|
||||
disabled = true;
|
||||
clearTimeout(showProc);
|
||||
clearTimeout(hideProc);
|
||||
clearTimeout(dismissProc);
|
||||
if(ce){
|
||||
hide(true);
|
||||
}
|
||||
locks.push(1);
|
||||
},
|
||||
|
||||
scan : function(toScan){
|
||||
toScan = toScan.dom ? toScan.dom : YAHOO.util.Dom.get(toScan);
|
||||
var found = [];
|
||||
reader.eachElement(cfg.tag, toScan, function(el){
|
||||
var t = reader.getAttribute(el, cfg.target);
|
||||
if(t){
|
||||
found.push({
|
||||
target: t.indexOf(',') != -1 ? t.split(',') : t,
|
||||
text: el.innerHTML,
|
||||
autoHide: reader.getAttribute(el, cfg.hide) != 'user',
|
||||
width: reader.getAttribute(el, cfg.width),
|
||||
title: reader.getAttribute(el, cfg.title),
|
||||
cls: reader.getAttribute(el, cfg.cls)
|
||||
});
|
||||
}
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
this.tips(found);
|
||||
},
|
||||
|
||||
tagConfig : {
|
||||
namespace : 'y',
|
||||
tag : 'qtip',
|
||||
attribute : 'qtip',
|
||||
width : 'width',
|
||||
target : 'target',
|
||||
title : 'qtitle',
|
||||
hide : 'hide',
|
||||
cls : 'qclass'
|
||||
},
|
||||
|
||||
maxWidth : 300,
|
||||
interceptTitles : true,
|
||||
trackMouse : false,
|
||||
hideOnClick : true,
|
||||
showDelay : 500,
|
||||
hideDelay : 200,
|
||||
autoHide : true,
|
||||
autoDismiss : true,
|
||||
autoDismissDelay : 5000,
|
||||
/**
|
||||
* True to turn on fade animation. Defaults to true
|
||||
* except in IE7 (ClearType/scrollbar flicker issues in IE7 with filters).
|
||||
* @type Boolean
|
||||
*/
|
||||
animate : YAHOO.util.Anim && !YAHOO.ext.util.Browser.isIE7
|
||||
}
|
||||
}();
|
||||
586
frontend/beta/js/YUI-extensions/widgets/Resizable.js
Normal file
586
frontend/beta/js/YUI-extensions/widgets/Resizable.js
Normal file
@@ -0,0 +1,586 @@
|
||||
/**
|
||||
* @class YAHOO.ext.Resizable
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
* <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element
|
||||
* and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap
|
||||
* the textarea in a div and set "resizeChild" to true (or the id of the textarea), <b>or</b> set wrap:true in your config and
|
||||
* the element will be wrapped for you automatically.</p><br/>
|
||||
* Here's a Resizable with every possible config option and it's default value:
|
||||
<pre><code>
|
||||
var resizer = new YAHOO.ext.Resizable('element-id', {
|
||||
resizeChild : false,
|
||||
adjustments : [0, 0],
|
||||
minWidth : 5,
|
||||
minHeight : 5,
|
||||
maxWidth : 10000,
|
||||
maxHeight : 10000,
|
||||
enabled : true,
|
||||
wrap: false, // true to wrap the element
|
||||
width: null, // initial size
|
||||
height: null, // initial size
|
||||
animate : false,
|
||||
duration : .35,
|
||||
dynamic : false,
|
||||
handles : false,
|
||||
multiDirectional : false,
|
||||
disableTrackOver : false,
|
||||
easing : YAHOO.util.Easing ? YAHOO.util.Easing.easeOutStrong : null,
|
||||
widthIncrement : 0,
|
||||
heightIncrement : 0,
|
||||
pinned : false,
|
||||
width : null,
|
||||
height : null,
|
||||
preserveRatio : false,
|
||||
transparent: false,
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
draggable: false
|
||||
});
|
||||
resizer.on('resize', myHandler);
|
||||
</code></pre>
|
||||
* <p>
|
||||
* To hide a particular handle, set it's display to none in CSS, or through script:<br>
|
||||
* resizer.east.setDisplayed(false);
|
||||
* </p>
|
||||
* @constructor
|
||||
* Create a new resizable component
|
||||
* @param {String/HTMLElement/YAHOO.ext.Element} el The id or element to resize
|
||||
* @param {Object} config configuration options
|
||||
*/
|
||||
YAHOO.ext.Resizable = function(el, config){
|
||||
this.el = getEl(el);
|
||||
|
||||
if(config && config.wrap){
|
||||
config.resizeChild = this.el;
|
||||
this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : null);
|
||||
this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
|
||||
this.el.setStyle('overflow', 'hidden');
|
||||
this.el.setPositioning(config.resizeChild.getPositioning());
|
||||
config.resizeChild.clearPositioning();
|
||||
if(!config.width || !config.height){
|
||||
var csize = config.resizeChild.getSize();
|
||||
//csize.width -= config.adjustments[0];
|
||||
//csize.height -= config.adjustments[1];
|
||||
this.el.setSize(csize.width, csize.height);
|
||||
}
|
||||
if(config.pinned && !config.adjustments){
|
||||
config.adjustments = 'auto';
|
||||
}
|
||||
}
|
||||
|
||||
this.proxy = this.el.createProxy({tag: 'div', cls: 'yresizable-proxy', id: this.el.id + '-rzproxy'})
|
||||
this.proxy.unselectable();
|
||||
|
||||
// the overlay traps mouse events while dragging and fixes iframe issue
|
||||
this.overlay = this.el.createProxy({tag: 'div', cls: 'yresizable-overlay', html: ' '});
|
||||
this.overlay.unselectable();
|
||||
this.overlay.enableDisplayMode('block');
|
||||
this.overlay.mon('mousemove', this.onMouseMove, this, true);
|
||||
this.overlay.mon('mouseup', this.onMouseUp, this, true);
|
||||
|
||||
YAHOO.ext.util.Config.apply(this, config, {
|
||||
/** True to resizeSize the first child or id/element to resize @type YAHOO.ext.Element */
|
||||
resizeChild : false,
|
||||
/** String "auto" or an array [width, height] with values to be <b>added</b> to the resize operation's new size. @type Array/String */
|
||||
adjustments : [0, 0],
|
||||
/** The minimum width for the element @type Number */
|
||||
minWidth : 5,
|
||||
/** The minimum height for the element @type Number */
|
||||
minHeight : 5,
|
||||
/** The maximum width for the element @type Number */
|
||||
maxWidth : 10000,
|
||||
/** The maximum height for the element @type Number */
|
||||
maxHeight : 10000,
|
||||
/** false to disable resizing @type Boolean */
|
||||
enabled : true,
|
||||
/** True to animate the resize (not compatible with dynamic sizing) @type Boolean */
|
||||
animate : false,
|
||||
/** Animation duration @type Float */
|
||||
duration : .35,
|
||||
/** True to resize the element while dragging instead of using a proxy @type Boolean */
|
||||
dynamic : false,
|
||||
// these 3 are only available at config time
|
||||
/** String consisting of the resize handles to display. Valid handles are
|
||||
* n (north), s (south) e (east), w (west), ne (northeast), nw (northwest), se (southeast), sw (southwest)
|
||||
* and all (which applies them all). If this is blank it defaults to "e,s,se". Handles can be delimited using
|
||||
* a space, comma or semi-colon. This is only applied at config time. @type String*/
|
||||
handles : false,
|
||||
multiDirectional : false,
|
||||
/** true to disable mouse tracking. This is only applied at config time. @type Boolean*/
|
||||
disableTrackOver : false,
|
||||
/** Animation easing @type YAHOO.util.Easing */
|
||||
easing : YAHOO.util.Easing ? YAHOO.util.Easing.easeOutStrong : null,
|
||||
/** The increment to snap the width resize in pixels (dynamic must be true) @type Number */
|
||||
widthIncrement : 0,
|
||||
/** The increment to snap the height resize in pixels (dynamic must be true) @type Number */
|
||||
heightIncrement : 0,
|
||||
/** true to pin the resize handles. This is only applied at config time. @type Boolean*/
|
||||
pinned : false,
|
||||
/** The initial width for the element @type Number */
|
||||
width : null,
|
||||
/** The initial height for the element @type Number */
|
||||
height : null,
|
||||
/** true to preserve the initial size ratio. @type Boolean*/
|
||||
preserveRatio : false,
|
||||
/** true for transparent handles. This is only applied at config time. @type Boolean*/
|
||||
transparent: false,
|
||||
/** The minimum allowed page X for the element (only used for west resizing, defaults to 0) @type Number */
|
||||
minX: 0,
|
||||
/** The minimum allowed page Y for the element (only used for north resizing, defaults to 0) @type Number */
|
||||
minY: 0,
|
||||
/** convenience to initialize drag drop. @type Boolean*/
|
||||
draggable: false
|
||||
});
|
||||
|
||||
if(this.pinned){
|
||||
this.disableTrackOver = true;
|
||||
this.el.addClass('yresizable-pinned');
|
||||
}
|
||||
// if the element isn't positioned, make it relative
|
||||
var position = this.el.getStyle('position');
|
||||
if(position != 'absolute' && position != 'fixed'){
|
||||
this.el.setStyle('position', 'relative');
|
||||
}
|
||||
if(!this.handles){ // no handles passed, must be legacy style
|
||||
this.handles = 's,e,se';
|
||||
if(this.multiDirectional){
|
||||
this.handles += ',n,w';
|
||||
}
|
||||
}
|
||||
if(this.handles == 'all'){
|
||||
this.handles = 'n s e w ne nw se sw';
|
||||
}
|
||||
var hs = this.handles.split(/\s*?[,;]\s*?| /);
|
||||
var ps = YAHOO.ext.Resizable.positions;
|
||||
for(var i = 0, len = hs.length; i < len; i++){
|
||||
if(hs[i] && ps[hs[i]]){
|
||||
var pos = ps[hs[i]];
|
||||
this[pos] = new YAHOO.ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
|
||||
}
|
||||
}
|
||||
// legacy
|
||||
this.corner = this.southeast;
|
||||
|
||||
this.activeHandle = null;
|
||||
|
||||
if(this.resizeChild){
|
||||
if(typeof this.resizeChild == 'boolean'){
|
||||
this.resizeChild = YAHOO.ext.Element.get(this.el.dom.firstChild, true);
|
||||
}else{
|
||||
this.resizeChild = YAHOO.ext.Element.get(this.resizeChild, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.adjustments == 'auto'){
|
||||
var rc = this.resizeChild;
|
||||
var hw = this.west, he = this.east, hn = this.north, hs = this.south;
|
||||
if(rc && (hw || hn)){
|
||||
rc.setRelativePositioned();
|
||||
rc.setLeft(hw ? hw.el.getWidth() : 0);
|
||||
rc.setTop(hn ? hn.el.getHeight() : 0);
|
||||
}
|
||||
this.adjustments = [
|
||||
(he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
|
||||
(hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
|
||||
];
|
||||
}
|
||||
|
||||
if(this.draggable){
|
||||
this.dd = this.dynamic ?
|
||||
this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
|
||||
this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
|
||||
}
|
||||
|
||||
// public events
|
||||
this.events = {
|
||||
/**
|
||||
* @event beforeresize
|
||||
* Fired before resize is allowed. Set enabled to false to cancel resize.
|
||||
* @param {YAHOO.ext.Resizable} this
|
||||
* @param {YAHOO.ext.EventObject} e The mousedown event
|
||||
*/
|
||||
'beforeresize' : new YAHOO.util.CustomEvent(),
|
||||
/**
|
||||
* @event resize
|
||||
* Fired after a resize.
|
||||
* @param {YAHOO.ext.Resizable} this
|
||||
* @param {Number} width The new width
|
||||
* @param {Number} height The new height
|
||||
* @param {YAHOO.ext.EventObject} e The mouseup event
|
||||
*/
|
||||
'resize' : new YAHOO.util.CustomEvent()
|
||||
};
|
||||
|
||||
if(this.width !== null && this.height !== null){
|
||||
this.resizeTo(this.width, this.height);
|
||||
}else{
|
||||
this.updateChildSize();
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.extendX(YAHOO.ext.Resizable, YAHOO.ext.util.Observable, {
|
||||
/**
|
||||
* Perform a manual resize
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
*/
|
||||
resizeTo : function(width, height){
|
||||
this.el.setSize(width, height);
|
||||
this.updateChildSize();
|
||||
this.fireEvent('resize', this, width, height, null);
|
||||
},
|
||||
|
||||
startSizing : function(e){
|
||||
this.fireEvent('beforeresize', this, e);
|
||||
if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
|
||||
this.resizing = true;
|
||||
this.startBox = this.el.getBox();
|
||||
this.startPoint = e.getXY();
|
||||
this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
|
||||
(this.startBox.y + this.startBox.height) - this.startPoint[1]];
|
||||
this.proxy.setBox(this.startBox);
|
||||
|
||||
this.overlay.setSize(YAHOO.util.Dom.getDocumentWidth(), YAHOO.util.Dom.getDocumentHeight());
|
||||
this.overlay.show();
|
||||
|
||||
if(!this.dynamic){
|
||||
this.proxy.show();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMouseDown : function(handle, e){
|
||||
if(this.enabled){
|
||||
e.stopEvent();
|
||||
this.activeHandle = handle;
|
||||
this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
|
||||
this.startSizing(e);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseUp : function(e){
|
||||
var size = this.resizeElement();
|
||||
this.resizing = false;
|
||||
this.handleOut();
|
||||
this.overlay.hide();
|
||||
this.fireEvent('resize', this, size.width, size.height, e);
|
||||
},
|
||||
|
||||
updateChildSize : function(){
|
||||
if(this.resizeChild){
|
||||
var el = this.el;
|
||||
var child = this.resizeChild;
|
||||
var adj = this.adjustments;
|
||||
if(el.dom.offsetWidth){
|
||||
var b = el.getSize(true);
|
||||
child.setSize(b.width+adj[0], b.height+adj[1]);
|
||||
}
|
||||
// Second call here for IE
|
||||
// The first call enables instant resizing and
|
||||
// the second call corrects scroll bars if they
|
||||
// exist
|
||||
if(YAHOO.ext.util.Browser.isIE){
|
||||
setTimeout(function(){
|
||||
if(el.dom.offsetWidth){
|
||||
var b = el.getSize(true);
|
||||
child.setSize(b.width+adj[0], b.height+adj[1]);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
snap : function(value, inc, min){
|
||||
if(!inc || !value) return value;
|
||||
var newValue = value;
|
||||
var m = value % inc;
|
||||
if(m > 0){
|
||||
if(m > (inc/2)){
|
||||
newValue = value + (inc-m);
|
||||
}else{
|
||||
newValue = value - m;
|
||||
}
|
||||
}
|
||||
return Math.max(min, newValue);
|
||||
},
|
||||
|
||||
resizeElement : function(){
|
||||
var box = this.proxy.getBox();
|
||||
//box.width = this.snap(box.width, this.widthIncrement);
|
||||
//box.height = this.snap(box.height, this.heightIncrement);
|
||||
//if(this.multiDirectional){
|
||||
this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
|
||||
//}else{
|
||||
// this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
|
||||
//}
|
||||
this.updateChildSize();
|
||||
this.proxy.hide();
|
||||
return box;
|
||||
},
|
||||
|
||||
constrain : function(v, diff, m, mx){
|
||||
if(v - diff < m){
|
||||
diff = v - m;
|
||||
}else if(v - diff > mx){
|
||||
diff = mx - v;
|
||||
}
|
||||
return diff;
|
||||
},
|
||||
|
||||
onMouseMove : function(e){
|
||||
if(this.enabled){
|
||||
try{// try catch so if something goes wrong the user doesn't get hung
|
||||
|
||||
//var curXY = this.startPoint;
|
||||
var curSize = this.curSize || this.startBox;
|
||||
var x = this.startBox.x, y = this.startBox.y;
|
||||
var ox = x, oy = y;
|
||||
var w = curSize.width, h = curSize.height;
|
||||
var ow = w, oh = h;
|
||||
var mw = this.minWidth, mh = this.minHeight;
|
||||
var mxw = this.maxWidth, mxh = this.maxHeight;
|
||||
var wi = this.widthIncrement;
|
||||
var hi = this.heightIncrement;
|
||||
|
||||
var eventXY = e.getXY();
|
||||
var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
|
||||
var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
|
||||
|
||||
var pos = this.activeHandle.position;
|
||||
|
||||
switch(pos){
|
||||
case 'east':
|
||||
w += diffX;
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
break;
|
||||
case 'south':
|
||||
h += diffY;
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
break;
|
||||
case 'southeast':
|
||||
w += diffX;
|
||||
h += diffY;
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
break;
|
||||
case 'north':
|
||||
diffY = this.constrain(h, diffY, mh, mxh);
|
||||
y += diffY;
|
||||
h -= diffY;
|
||||
break;
|
||||
case 'west':
|
||||
diffX = this.constrain(w, diffX, mw, mxw);
|
||||
x += diffX;
|
||||
w -= diffX;
|
||||
break;
|
||||
case 'northeast':
|
||||
w += diffX;
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
diffY = this.constrain(h, diffY, mh, mxh);
|
||||
y += diffY;
|
||||
h -= diffY;
|
||||
break;
|
||||
case 'northwest':
|
||||
diffX = this.constrain(w, diffX, mw, mxw);
|
||||
diffY = this.constrain(h, diffY, mh, mxh);
|
||||
y += diffY;
|
||||
h -= diffY;
|
||||
x += diffX;
|
||||
w -= diffX;
|
||||
break;
|
||||
case 'southwest':
|
||||
diffX = this.constrain(w, diffX, mw, mxw);
|
||||
h += diffY;
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
x += diffX;
|
||||
w -= diffX;
|
||||
break;
|
||||
}
|
||||
|
||||
var sw = this.snap(w, wi, mw);
|
||||
var sh = this.snap(h, hi, mh);
|
||||
if(sw != w || sh != h){
|
||||
switch(pos){
|
||||
case 'northeast':
|
||||
y -= sh - h;
|
||||
break;
|
||||
case 'north':
|
||||
y -= sh - h;
|
||||
break;
|
||||
case 'southwest':
|
||||
x -= sw - w;
|
||||
break;
|
||||
case 'west':
|
||||
x -= sw - w;
|
||||
break;
|
||||
case 'northwest':
|
||||
x -= sw - w;
|
||||
y -= sh - h;
|
||||
break;
|
||||
}
|
||||
w = sw;
|
||||
h = sh;
|
||||
}
|
||||
|
||||
if(this.preserveRatio){
|
||||
switch(pos){
|
||||
case 'southeast':
|
||||
case 'east':
|
||||
h = oh * (w/ow);
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
w = ow * (h/oh);
|
||||
break;
|
||||
case 'south':
|
||||
w = ow * (h/oh);
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
h = oh * (w/ow);
|
||||
break;
|
||||
case 'northeast':
|
||||
w = ow * (h/oh);
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
h = oh * (w/ow);
|
||||
break;
|
||||
case 'north':
|
||||
var tw = w;
|
||||
w = ow * (h/oh);
|
||||
w = Math.min(Math.max(mw, w), mxw);
|
||||
h = oh * (w/ow);
|
||||
x += (tw - w) / 2;
|
||||
break;
|
||||
case 'southwest':
|
||||
h = oh * (w/ow);
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
var tw = w;
|
||||
w = ow * (h/oh);
|
||||
x += tw - w;
|
||||
break;
|
||||
case 'west':
|
||||
var th = h;
|
||||
h = oh * (w/ow);
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
y += (th - h) / 2;
|
||||
var tw = w;
|
||||
w = ow * (h/oh);
|
||||
x += tw - w;
|
||||
break;
|
||||
case 'northwest':
|
||||
var tw = w;
|
||||
var th = h;
|
||||
h = oh * (w/ow);
|
||||
h = Math.min(Math.max(mh, h), mxh);
|
||||
w = ow * (h/oh);
|
||||
y += th - h;
|
||||
x += tw - w;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
this.proxy.setBounds(x, y, w, h);
|
||||
if(this.dynamic){
|
||||
this.resizeElement();
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
},
|
||||
|
||||
handleOver : function(){
|
||||
if(this.enabled){
|
||||
this.el.addClass('yresizable-over');
|
||||
}
|
||||
},
|
||||
|
||||
handleOut : function(){
|
||||
if(!this.resizing){
|
||||
this.el.removeClass('yresizable-over');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the element this component is bound to.
|
||||
* @return {YAHOO.ext.Element}
|
||||
*/
|
||||
getEl : function(){
|
||||
return this.el;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the resizeChild element (or null).
|
||||
* @return {YAHOO.ext.Element}
|
||||
*/
|
||||
getResizeChild : function(){
|
||||
return this.resizeChild;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys this resizable. If the element was wrapped and
|
||||
* removeEl is not true then the wrap remains.
|
||||
* @param {Boolean} removeEl (optional) true to remove the element from the DOM
|
||||
*/
|
||||
destroy : function(removeEl){
|
||||
this.proxy.remove();
|
||||
this.overlay.removeAllListeners();
|
||||
this.overlay.remove();
|
||||
var ps = YAHOO.ext.Resizable.positions;
|
||||
for(var k in ps){
|
||||
if(typeof ps[k] != 'function' && this[ps[k]]){
|
||||
var h = this[ps[k]];
|
||||
h.el.removeAllListeners();
|
||||
h.el.remove();
|
||||
}
|
||||
}
|
||||
if(removeEl){
|
||||
this.el.update('');
|
||||
this.el.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// hash to map config positions to true positions
|
||||
YAHOO.ext.Resizable.positions = {
|
||||
n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
|
||||
};
|
||||
|
||||
|
||||
YAHOO.ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
|
||||
if(!this.tpl){
|
||||
// only initialize the template if resizable is used
|
||||
var tpl = YAHOO.ext.DomHelper.createTemplate(
|
||||
{tag: 'div', cls: 'yresizable-handle yresizable-handle-{0}', html: ' '}
|
||||
);
|
||||
tpl.compile();
|
||||
YAHOO.ext.Resizable.Handle.prototype.tpl = tpl;
|
||||
}
|
||||
this.position = pos;
|
||||
this.rz = rz;
|
||||
this.el = this.tpl.append(rz.el.dom, [this.position], true);
|
||||
this.el.unselectable();
|
||||
if(transparent){
|
||||
this.el.setOpacity(0);
|
||||
}
|
||||
this.el.mon('mousedown', this.onMouseDown, this, true);
|
||||
if(!disableTrackOver){
|
||||
this.el.mon('mouseover', this.onMouseOver, this, true);
|
||||
this.el.mon('mouseout', this.onMouseOut, this, true);
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.ext.Resizable.Handle.prototype = {
|
||||
afterResize : function(rz){
|
||||
// do nothing
|
||||
},
|
||||
|
||||
onMouseDown : function(e){
|
||||
this.rz.onMouseDown(this, e);
|
||||
},
|
||||
|
||||
onMouseOver : function(e){
|
||||
this.rz.handleOver(this, e);
|
||||
},
|
||||
|
||||
onMouseOut : function(e){
|
||||
this.rz.handleOut(this, e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
468
frontend/beta/js/YUI-extensions/widgets/SplitBar.js
Normal file
468
frontend/beta/js/YUI-extensions/widgets/SplitBar.js
Normal file
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* splitbar.js, version .7
|
||||
* Copyright(c) 2006, Jack Slocum.
|
||||
* Code licensed under the BSD License
|
||||
*/
|
||||
if(YAHOO.util.DragDropMgr){
|
||||
YAHOO.util.DragDropMgr.clickTimeThresh = 350;
|
||||
}
|
||||
/**
|
||||
* @class YAHOO.ext.SplitBar
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
* Creates draggable splitter bar functionality from two elements.
|
||||
* <br><br>
|
||||
* Usage:
|
||||
* <pre><code>
|
||||
var split = new YAHOO.ext.SplitBar('elementToDrag', 'elementToSize',
|
||||
YAHOO.ext.SplitBar.HORIZONTAL, YAHOO.ext.SplitBar.LEFT);
|
||||
split.setAdapter(new YAHOO.ext.SplitBar.AbsoluteLayoutAdapter("container"));
|
||||
split.minSize = 100;
|
||||
split.maxSize = 600;
|
||||
split.animate = true;
|
||||
split.onMoved.subscribe(splitterMoved);
|
||||
</code></pre>
|
||||
* @requires YAHOO.ext.Element
|
||||
* @requires YAHOO.util.Dom
|
||||
* @requires YAHOO.util.Event
|
||||
* @requires YAHOO.util.CustomEvent
|
||||
* @requires YAHOO.util.DDProxy
|
||||
* @requires YAHOO.util.Anim (optional) to support animation
|
||||
* @requires YAHOO.util.Easing (optional) to support animation
|
||||
* @constructor
|
||||
* Create a new SplitBar
|
||||
* @param {String/HTMLElement/Element} dragElement The element to be dragged and act as the SplitBar.
|
||||
* @param {String/HTMLElement/Element} resizingElement The element to be resized based on where the SplitBar element is dragged
|
||||
* @param {Number} orientation (optional) Either YAHOO.ext.SplitBar.HORIZONTAL or YAHOO.ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
|
||||
* @param {Number} placement (optional) Either YAHOO.ext.SplitBar.LEFT or YAHOO.ext.SplitBar.RIGHT for horizontal or
|
||||
YAHOO.ext.SplitBar.TOP or YAHOO.ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the intial position
|
||||
position of the SplitBar).
|
||||
*/
|
||||
YAHOO.ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
|
||||
|
||||
/** @private */
|
||||
this.el = YAHOO.ext.Element.get(dragElement, true);
|
||||
this.el.dom.unselectable = 'on';
|
||||
/** @private */
|
||||
this.resizingEl = YAHOO.ext.Element.get(resizingElement, true);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The orientation of the split. Either YAHOO.ext.SplitBar.HORIZONTAL or YAHOO.ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
|
||||
* Note: If this is changed after creating the SplitBar, the placement property must be manually updated
|
||||
* @type Number
|
||||
*/
|
||||
this.orientation = orientation || YAHOO.ext.SplitBar.HORIZONTAL;
|
||||
|
||||
/**
|
||||
* The minimum size of the resizing element. (Defaults to 0)
|
||||
* @type Number
|
||||
*/
|
||||
this.minSize = 0;
|
||||
|
||||
/**
|
||||
* The maximum size of the resizing element. (Defaults to 2000)
|
||||
* @type Number
|
||||
*/
|
||||
this.maxSize = 2000;
|
||||
|
||||
this.onMoved = new YAHOO.util.CustomEvent("SplitBarMoved", this);
|
||||
|
||||
/**
|
||||
* Whether to animate the transition to the new size
|
||||
* @type Boolean
|
||||
*/
|
||||
this.animate = false;
|
||||
|
||||
/**
|
||||
* Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
|
||||
* @type Boolean
|
||||
*/
|
||||
this.useShim = false;
|
||||
|
||||
/** @private */
|
||||
this.shim = null;
|
||||
|
||||
if(!existingProxy){
|
||||
/** @private */
|
||||
this.proxy = YAHOO.ext.SplitBar.createProxy(this.orientation);
|
||||
}else{
|
||||
this.proxy = getEl(existingProxy).dom;
|
||||
}
|
||||
/** @private */
|
||||
this.dd = new YAHOO.util.DDProxy(this.el.dom.id, "SplitBars", {dragElId : this.proxy.id});
|
||||
|
||||
/** @private */
|
||||
this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
|
||||
|
||||
/** @private */
|
||||
this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
|
||||
|
||||
/** @private */
|
||||
this.dragSpecs = {};
|
||||
|
||||
/**
|
||||
* @private The adapter to use to positon and resize elements
|
||||
*/
|
||||
this.adapter = new YAHOO.ext.SplitBar.BasicLayoutAdapter();
|
||||
this.adapter.init(this);
|
||||
|
||||
if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
/** @private */
|
||||
this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? YAHOO.ext.SplitBar.LEFT : YAHOO.ext.SplitBar.RIGHT);
|
||||
this.el.setStyle('cursor', 'e-resize');
|
||||
}else{
|
||||
/** @private */
|
||||
this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? YAHOO.ext.SplitBar.TOP : YAHOO.ext.SplitBar.BOTTOM);
|
||||
this.el.setStyle('cursor', 'n-resize');
|
||||
}
|
||||
|
||||
this.events = {
|
||||
/**
|
||||
* @event resize
|
||||
* Fires when the splitter is moved (alias for moved)
|
||||
* @param {YAHOO.ext.SplitBar} this
|
||||
* @param {Number} newSize the new width or height
|
||||
*/
|
||||
'resize' : this.onMoved,
|
||||
/**
|
||||
* @event moved
|
||||
* Fires when the splitter is moved
|
||||
* @param {YAHOO.ext.SplitBar} this
|
||||
* @param {Number} newSize the new width or height
|
||||
*/
|
||||
'moved' : this.onMoved,
|
||||
/**
|
||||
* @event beforeresize
|
||||
* Fires before the splitter is dragged
|
||||
* @param {YAHOO.ext.SplitBar} this
|
||||
*/
|
||||
'beforeresize' : new YAHOO.util.CustomEvent('beforeresize')
|
||||
}
|
||||
}
|
||||
|
||||
YAHOO.extendX(YAHOO.ext.SplitBar, YAHOO.ext.util.Observable, {
|
||||
onStartProxyDrag : function(x, y){
|
||||
this.fireEvent('beforeresize', this);
|
||||
if(this.useShim){
|
||||
if(!this.shim){
|
||||
this.shim = YAHOO.ext.SplitBar.createShim();
|
||||
}
|
||||
this.shim.setVisible(true);
|
||||
}
|
||||
YAHOO.util.Dom.setStyle(this.proxy, 'display', 'block');
|
||||
var size = this.adapter.getElementSize(this);
|
||||
this.activeMinSize = this.getMinimumSize();;
|
||||
this.activeMaxSize = this.getMaximumSize();;
|
||||
var c1 = size - this.activeMinSize;
|
||||
var c2 = Math.max(this.activeMaxSize - size, 0);
|
||||
if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
this.dd.resetConstraints();
|
||||
this.dd.setXConstraint(
|
||||
this.placement == YAHOO.ext.SplitBar.LEFT ? c1 : c2,
|
||||
this.placement == YAHOO.ext.SplitBar.LEFT ? c2 : c1
|
||||
);
|
||||
this.dd.setYConstraint(0, 0);
|
||||
}else{
|
||||
this.dd.resetConstraints();
|
||||
this.dd.setXConstraint(0, 0);
|
||||
this.dd.setYConstraint(
|
||||
this.placement == YAHOO.ext.SplitBar.TOP ? c1 : c2,
|
||||
this.placement == YAHOO.ext.SplitBar.TOP ? c2 : c1
|
||||
);
|
||||
}
|
||||
this.dragSpecs.startSize = size;
|
||||
this.dragSpecs.startPoint = [x, y];
|
||||
|
||||
YAHOO.util.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private Called after the drag operation by the DDProxy
|
||||
*/
|
||||
onEndProxyDrag : function(e){
|
||||
YAHOO.util.Dom.setStyle(this.proxy, 'display', 'none');
|
||||
var endPoint = YAHOO.util.Event.getXY(e);
|
||||
if(this.useShim){
|
||||
this.shim.setVisible(false);
|
||||
}
|
||||
var newSize;
|
||||
if(this.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
newSize = this.dragSpecs.startSize +
|
||||
(this.placement == YAHOO.ext.SplitBar.LEFT ?
|
||||
endPoint[0] - this.dragSpecs.startPoint[0] :
|
||||
this.dragSpecs.startPoint[0] - endPoint[0]
|
||||
);
|
||||
}else{
|
||||
newSize = this.dragSpecs.startSize +
|
||||
(this.placement == YAHOO.ext.SplitBar.TOP ?
|
||||
endPoint[1] - this.dragSpecs.startPoint[1] :
|
||||
this.dragSpecs.startPoint[1] - endPoint[1]
|
||||
);
|
||||
}
|
||||
newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
|
||||
if(newSize != this.dragSpecs.startSize){
|
||||
this.adapter.setElementSize(this, newSize);
|
||||
this.onMoved.fireDirect(this, newSize);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the adapter this SplitBar uses
|
||||
* @return The adapter object
|
||||
*/
|
||||
getAdapter : function(){
|
||||
return this.adapter;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the adapter this SplitBar uses
|
||||
* @param {Object} adapter A SplitBar adapter object
|
||||
*/
|
||||
setAdapter : function(adapter){
|
||||
this.adapter = adapter;
|
||||
this.adapter.init(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the minimum size for the resizing element
|
||||
* @return {Number} The minimum size
|
||||
*/
|
||||
getMinimumSize : function(){
|
||||
return this.minSize;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the minimum size for the resizing element
|
||||
* @param {Number} minSize The minimum size
|
||||
*/
|
||||
setMinimumSize : function(minSize){
|
||||
this.minSize = minSize;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the maximum size for the resizing element
|
||||
* @return {Number} The maximum size
|
||||
*/
|
||||
getMaximumSize : function(){
|
||||
return this.maxSize;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the maximum size for the resizing element
|
||||
* @param {Number} maxSize The maximum size
|
||||
*/
|
||||
setMaximumSize : function(maxSize){
|
||||
this.maxSize = maxSize;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the initialize size for the resizing element
|
||||
* @param {Number} size The initial size
|
||||
*/
|
||||
setCurrentSize : function(size){
|
||||
var oldAnimate = this.animate;
|
||||
this.animate = false;
|
||||
this.adapter.setElementSize(this, size);
|
||||
this.animate = oldAnimate;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy this splitbar.
|
||||
* @param {Boolean} removeEl True to remove the element
|
||||
*/
|
||||
destroy : function(removeEl){
|
||||
if(this.shim){
|
||||
this.shim.remove();
|
||||
}
|
||||
this.dd.unreg();
|
||||
this.proxy.parentNode.removeChild(this.proxy);
|
||||
if(removeEl){
|
||||
this.el.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @private static Create the shim to drag over iframes
|
||||
*/
|
||||
YAHOO.ext.SplitBar.createShim = function(){
|
||||
var shim = document.createElement('div');
|
||||
shim.unselectable = 'on';
|
||||
YAHOO.util.Dom.generateId(shim, 'split-shim');
|
||||
YAHOO.util.Dom.setStyle(shim, 'width', '100%');
|
||||
YAHOO.util.Dom.setStyle(shim, 'height', '100%');
|
||||
YAHOO.util.Dom.setStyle(shim, 'position', 'absolute');
|
||||
YAHOO.util.Dom.setStyle(shim, 'background', 'white');
|
||||
YAHOO.util.Dom.setStyle(shim, 'z-index', 11000);
|
||||
window.document.body.appendChild(shim);
|
||||
var shimEl = YAHOO.ext.Element.get(shim);
|
||||
shimEl.setOpacity(.01);
|
||||
shimEl.setXY([0, 0]);
|
||||
return shimEl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
|
||||
*/
|
||||
YAHOO.ext.SplitBar.createProxy = function(orientation){
|
||||
var proxy = document.createElement('div');
|
||||
proxy.unselectable = 'on';
|
||||
YAHOO.util.Dom.generateId(proxy, 'split-proxy');
|
||||
YAHOO.util.Dom.setStyle(proxy, 'position', 'absolute');
|
||||
YAHOO.util.Dom.setStyle(proxy, 'visibility', 'hidden');
|
||||
YAHOO.util.Dom.setStyle(proxy, 'z-index', 11001);
|
||||
YAHOO.util.Dom.setStyle(proxy, 'background-color', "#aaa");
|
||||
if(orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
YAHOO.util.Dom.setStyle(proxy, 'cursor', 'e-resize');
|
||||
}else{
|
||||
YAHOO.util.Dom.setStyle(proxy, 'cursor', 'n-resize');
|
||||
}
|
||||
// the next 2 fix IE abs position div height problem
|
||||
YAHOO.util.Dom.setStyle(proxy, 'line-height', '0px');
|
||||
YAHOO.util.Dom.setStyle(proxy, 'font-size', '0px');
|
||||
window.document.body.appendChild(proxy);
|
||||
return proxy;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class YAHOO.ext.SplitBar.BasicLayoutAdapter
|
||||
* Default Adapter. It assumes the splitter and resizing element are not positioned
|
||||
* elements and only gets/sets the width of the element. Generally used for table based layouts.
|
||||
*/
|
||||
YAHOO.ext.SplitBar.BasicLayoutAdapter = function(){
|
||||
};
|
||||
|
||||
YAHOO.ext.SplitBar.BasicLayoutAdapter.prototype = {
|
||||
// do nothing for now
|
||||
init : function(s){
|
||||
|
||||
},
|
||||
/**
|
||||
* Called before drag operations to get the current size of the resizing element.
|
||||
* @param {YAHOO.ext.SplitBar} s The SplitBar using this adapter
|
||||
*/
|
||||
getElementSize : function(s){
|
||||
if(s.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
return s.resizingEl.getWidth();
|
||||
}else{
|
||||
return s.resizingEl.getHeight();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called after drag operations to set the size of the resizing element.
|
||||
* @param {YAHOO.ext.SplitBar} s The SplitBar using this adapter
|
||||
* @param {Number} newSize The new size to set
|
||||
* @param {Function} onComplete A function to be invoke when resizing is complete
|
||||
*/
|
||||
setElementSize : function(s, newSize, onComplete){
|
||||
if(s.orientation == YAHOO.ext.SplitBar.HORIZONTAL){
|
||||
if(!YAHOO.util.Anim || !s.animate){
|
||||
s.resizingEl.setWidth(newSize);
|
||||
if(onComplete){
|
||||
onComplete(s, newSize);
|
||||
}
|
||||
}else{
|
||||
s.resizingEl.setWidth(newSize, true, .1, onComplete, YAHOO.util.Easing.easeOut);
|
||||
}
|
||||
}else{
|
||||
|
||||
if(!YAHOO.util.Anim || !s.animate){
|
||||
s.resizingEl.setHeight(newSize);
|
||||
if(onComplete){
|
||||
onComplete(s, newSize);
|
||||
}
|
||||
}else{
|
||||
s.resizingEl.setHeight(newSize, true, .1, onComplete, YAHOO.util.Easing.easeOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*@class YAHOO.ext.SplitBar.AbsoluteLayoutAdapter
|
||||
* @extends YAHOO.ext.SplitBar.BasicLayoutAdapter
|
||||
* Adapter that moves the splitter element to align with the resized sizing element.
|
||||
* Used with an absolute positioned SplitBar.
|
||||
* @param {String/HTMLElement/Element} container The container that wraps around the absolute positioned content. If it's
|
||||
* document.body, make sure you assign an id to the body element.
|
||||
*/
|
||||
YAHOO.ext.SplitBar.AbsoluteLayoutAdapter = function(container){
|
||||
this.basic = new YAHOO.ext.SplitBar.BasicLayoutAdapter();
|
||||
this.container = getEl(container);
|
||||
}
|
||||
|
||||
YAHOO.ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
|
||||
init : function(s){
|
||||
this.basic.init(s);
|
||||
//YAHOO.util.Event.on(window, 'resize', this.moveSplitter.createDelegate(this, [s]));
|
||||
},
|
||||
|
||||
getElementSize : function(s){
|
||||
return this.basic.getElementSize(s);
|
||||
},
|
||||
|
||||
setElementSize : function(s, newSize, onComplete){
|
||||
this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
|
||||
},
|
||||
|
||||
moveSplitter : function(s){
|
||||
var yes = YAHOO.ext.SplitBar;
|
||||
switch(s.placement){
|
||||
case yes.LEFT:
|
||||
s.el.setX(s.resizingEl.getRight());
|
||||
break;
|
||||
case yes.RIGHT:
|
||||
s.el.setStyle('right', (this.container.getWidth() - s.resizingEl.getLeft()) + 'px');
|
||||
break;
|
||||
case yes.TOP:
|
||||
s.el.setY(s.resizingEl.getBottom());
|
||||
break;
|
||||
case yes.BOTTOM:
|
||||
s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Orientation constant - Create a vertical SplitBar
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.VERTICAL = 1;
|
||||
|
||||
/**
|
||||
* Orientation constant - Create a horizontal SplitBar
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.HORIZONTAL = 2;
|
||||
|
||||
/**
|
||||
* Placement constant - The resizing element is to the left of the splitter element
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.LEFT = 1;
|
||||
|
||||
/**
|
||||
* Placement constant - The resizing element is to the right of the splitter element
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.RIGHT = 2;
|
||||
|
||||
/**
|
||||
* Placement constant - The resizing element is positioned above the splitter element
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.TOP = 3;
|
||||
|
||||
/**
|
||||
* Placement constant - The resizing element is positioned under splitter element
|
||||
* @static
|
||||
* @type Number
|
||||
*/
|
||||
YAHOO.ext.SplitBar.BOTTOM = 4;
|
||||
756
frontend/beta/js/YUI-extensions/widgets/TabPanel.js
Normal file
756
frontend/beta/js/YUI-extensions/widgets/TabPanel.js
Normal file
@@ -0,0 +1,756 @@
|
||||
/**
|
||||
* @class YAHOO.ext.TabPanel
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
* Creates a lightweight TabPanel component using Yahoo! UI.
|
||||
* <br><br>
|
||||
* Usage:
|
||||
* <pre><code>
|
||||
<font color="#008000">// basic tabs 1, built from existing content</font>
|
||||
var tabs = new YAHOO.ext.TabPanel('tabs1');
|
||||
tabs.addTab('script', "View Script");
|
||||
tabs.addTab('markup', "View Markup");
|
||||
tabs.activate('script');
|
||||
|
||||
<font color="#008000">// more advanced tabs, built from javascript</font>
|
||||
var jtabs = new YAHOO.ext.TabPanel('jtabs');
|
||||
jtabs.addTab('jtabs-1', "Normal Tab", "My content was added during construction.");
|
||||
|
||||
<font color="#008000">// set up the UpdateManager</font>
|
||||
var tab2 = jtabs.addTab('jtabs-2', "Ajax Tab 1");
|
||||
var updater = tab2.getUpdateManager();
|
||||
updater.setDefaultUrl('ajax1.htm');
|
||||
tab2.onActivate.subscribe(updater.refresh, updater, true);
|
||||
|
||||
<font color="#008000">// Use setUrl for Ajax loading</font>
|
||||
var tab3 = jtabs.addTab('jtabs-3', "Ajax Tab 2");
|
||||
tab3.setUrl('ajax2.htm', null, true);
|
||||
|
||||
<font color="#008000">// Disabled tab</font>
|
||||
var tab4 = jtabs.addTab('tabs1-5', "Disabled Tab", "Can't see me cause I'm disabled");
|
||||
tab4.disable();
|
||||
|
||||
jtabs.activate('jtabs-1');
|
||||
}
|
||||
* </code></pre>
|
||||
* @requires YAHOO.ext.Element
|
||||
* @requires YAHOO.ext.UpdateManager
|
||||
* @requires YAHOO.util.Dom
|
||||
* @requires YAHOO.util.Event
|
||||
* @requires YAHOO.util.CustomEvent
|
||||
* @requires YAHOO.util.Connect (optional)
|
||||
* @constructor
|
||||
* Create new TabPanel.
|
||||
* @param {String/HTMLElement/Element} container The id, DOM element or YAHOO.ext.Element container where this TabPanel is to be rendered.
|
||||
* @param {Boolean} config Config object to set any properties for this TabPanel or true to render the tabs on the bottom.
|
||||
*/
|
||||
YAHOO.ext.TabPanel = function(container, config){
|
||||
/**
|
||||
* The container element for this TabPanel.
|
||||
* @type YAHOO.ext.Element
|
||||
*/
|
||||
this.el = getEl(container, true);
|
||||
/** The position of the tabs. Can be 'top' or 'bottom' @type String */
|
||||
this.tabPosition = 'top';
|
||||
this.currentTabWidth = 0;
|
||||
/** The minimum width of a tab (ignored if resizeTabs is not true). @type Number */
|
||||
this.minTabWidth = 40;
|
||||
/** The maximum width of a tab (ignored if resizeTabs is not true). @type Number */
|
||||
this.maxTabWidth = 250;
|
||||
/** The preferred (default) width of a tab (ignored if resizeTabs is not true). @type Number */
|
||||
this.preferredTabWidth = 175;
|
||||
/** Set this to true to enable dynamic tab resizing. @type Boolean */
|
||||
this.resizeTabs = false;
|
||||
/** Set this to true to turn on window resizing monitoring (ignored if resizeTabs is not true). @type Boolean */
|
||||
this.monitorResize = true;
|
||||
|
||||
if(config){
|
||||
if(typeof config == 'boolean'){
|
||||
this.tabPosition = config ? 'bottom' : 'top';
|
||||
}else{
|
||||
YAHOO.ext.util.Config.apply(this, config);
|
||||
}
|
||||
}
|
||||
if(this.tabPosition == 'bottom'){
|
||||
this.bodyEl = getEl(this.createBody(this.el.dom));
|
||||
this.el.addClass('ytabs-bottom');
|
||||
}
|
||||
this.stripWrap = getEl(this.createStrip(this.el.dom), true);
|
||||
this.stripEl = getEl(this.createStripList(this.stripWrap.dom), true);
|
||||
this.stripBody = getEl(this.stripWrap.dom.firstChild.firstChild, true);
|
||||
if(YAHOO.ext.util.Browser.isIE){
|
||||
YAHOO.util.Dom.setStyle(this.stripWrap.dom.firstChild, 'overflow-x', 'hidden');
|
||||
}
|
||||
if(this.tabPosition != 'bottom'){
|
||||
/** The body element that contains TabPaneItem bodies.
|
||||
* @type YAHOO.ext.Element
|
||||
*/
|
||||
this.bodyEl = getEl(this.createBody(this.el.dom));
|
||||
this.el.addClass('ytabs-top');
|
||||
}
|
||||
this.items = [];
|
||||
|
||||
this.bodyEl.setStyle('position', 'relative');
|
||||
|
||||
// add indexOf to array if it isn't present
|
||||
if(!this.items.indexOf){
|
||||
this.items.indexOf = function(o){
|
||||
for(var i = 0, len = this.length; i < len; i++){
|
||||
if(this[i] == o) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
this.active = null;
|
||||
this.onTabChange = new YAHOO.util.CustomEvent('TabItem.onTabChange');
|
||||
this.activateDelegate = this.activate.createDelegate(this);
|
||||
|
||||
this.events = {
|
||||
/**
|
||||
* @event tabchange
|
||||
* Fires when the active tab changes
|
||||
* @param {YAHOO.ext.TabPanel} this
|
||||
* @param {YAHOO.ext.TabPanelItem} activePanel The new active tab
|
||||
*/
|
||||
'tabchange': this.onTabChange,
|
||||
/**
|
||||
* @event beforetabchange
|
||||
* Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
|
||||
* @param {YAHOO.ext.TabPanel} this
|
||||
* @param {Object} e Set cancel to true on this object to cancel the tab change
|
||||
* @param {YAHOO.ext.TabPanelItem} tab The tab being changed to
|
||||
*/
|
||||
'beforetabchange' : new YAHOO.util.CustomEvent('beforechange')
|
||||
};
|
||||
|
||||
YAHOO.ext.EventManager.onWindowResize(this.onResize, this, true);
|
||||
this.cpad = this.el.getPadding('lr');
|
||||
this.hiddenCount = 0;
|
||||
}
|
||||
|
||||
YAHOO.ext.TabPanel.prototype = {
|
||||
fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
|
||||
on : YAHOO.ext.util.Observable.prototype.on,
|
||||
addListener : YAHOO.ext.util.Observable.prototype.addListener,
|
||||
delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
|
||||
removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
|
||||
purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
|
||||
/**
|
||||
* Creates a new TabPanelItem by looking for an existing element with the provided id - if it's not found it creates one.
|
||||
* @param {String} id The id of the div to use <b>or create</b>
|
||||
* @param {String} text The text for the tab
|
||||
* @param {<i>String</i>} content (optional) Content to put in the TabPanelItem body
|
||||
* @param {<i>Boolean</i>} closable (optional) True to create a close icon on the tab
|
||||
* @return {YAHOO.ext.TabPanelItem} The created TabPanelItem
|
||||
*/
|
||||
addTab : function(id, text, content, closable){
|
||||
var item = new YAHOO.ext.TabPanelItem(this, id, text, closable);
|
||||
this.addTabItem(item);
|
||||
if(content){
|
||||
item.setContent(content);
|
||||
}
|
||||
return item;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the TabPanelItem with the specified id/index
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to fetch.
|
||||
* @return {YAHOO.ext.TabPanelItem}
|
||||
*/
|
||||
getTab : function(id){
|
||||
return this.items[id];
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the TabPanelItem with the specified id/index
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to hide.
|
||||
*/
|
||||
hideTab : function(id){
|
||||
var t = this.items[id];
|
||||
if(!t.isHidden()){
|
||||
t.setHidden(true);
|
||||
this.hiddenCount++;
|
||||
this.autoSizeTabs();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* "Unhides" the TabPanelItem with the specified id/index
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to unhide.
|
||||
*/
|
||||
unhideTab : function(id){
|
||||
var t = this.items[id];
|
||||
if(t.isHidden()){
|
||||
t.setHidden(false);
|
||||
this.hiddenCount--;
|
||||
this.autoSizeTabs();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an existing TabPanelItem.
|
||||
* @param {YAHOO.ext.TabPanelItem} item The TabPanelItem to add
|
||||
*/
|
||||
addTabItem : function(item){
|
||||
this.items[item.id] = item;
|
||||
this.items.push(item);
|
||||
if(this.resizeTabs){
|
||||
item.setWidth(this.currentTabWidth || this.preferredTabWidth)
|
||||
this.autoSizeTabs();
|
||||
}else{
|
||||
item.autoSize();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a TabPanelItem.
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to remove.
|
||||
*/
|
||||
removeTab : function(id){
|
||||
var items = this.items;
|
||||
var tab = items[id];
|
||||
if(!tab) return;
|
||||
var index = items.indexOf(tab);
|
||||
if(this.active == tab && items.length > 1){
|
||||
var newTab = this.getNextAvailable(index);
|
||||
if(newTab)newTab.activate();
|
||||
}
|
||||
this.stripEl.dom.removeChild(tab.pnode.dom);
|
||||
if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
|
||||
this.bodyEl.dom.removeChild(tab.bodyEl.dom);
|
||||
}
|
||||
items.splice(index, 1);
|
||||
delete this.items[tab.id];
|
||||
tab.fireEvent('close', tab);
|
||||
tab.purgeListeners();
|
||||
this.autoSizeTabs();
|
||||
},
|
||||
|
||||
getNextAvailable : function(start){
|
||||
var items = this.items;
|
||||
var index = start;
|
||||
// look for a next tab that will slide over to
|
||||
// replace the one being removed
|
||||
while(index < items.length){
|
||||
var item = items[++index];
|
||||
if(item && !item.isHidden()){
|
||||
return item;
|
||||
}
|
||||
}
|
||||
// if one isn't found select the previous tab (on the left)
|
||||
var index = start;
|
||||
while(index >= 0){
|
||||
var item = items[--index];
|
||||
if(item && !item.isHidden()){
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable a TabPanelItem. <b>It cannot be the active tab, if it is this call is ignored.</b>.
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to disable.
|
||||
*/
|
||||
disableTab : function(id){
|
||||
var tab = this.items[id];
|
||||
if(tab && this.active != tab){
|
||||
tab.disable();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable a TabPanelItem that is disabled.
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to enable.
|
||||
*/
|
||||
enableTab : function(id){
|
||||
var tab = this.items[id];
|
||||
tab.enable();
|
||||
},
|
||||
|
||||
/**
|
||||
* Activate a TabPanelItem. The currently active will be deactivated.
|
||||
* @param {String/Number} id The id or index of the TabPanelItem to activate.
|
||||
*/
|
||||
activate : function(id){
|
||||
var tab = this.items[id];
|
||||
if(tab == this.active){
|
||||
return tab;
|
||||
}
|
||||
var e = {};
|
||||
this.fireEvent('beforetabchange', this, e, tab);
|
||||
if(e.cancel !== true && !tab.disabled){
|
||||
if(this.active){
|
||||
this.active.hide();
|
||||
}
|
||||
this.active = this.items[id];
|
||||
this.active.show();
|
||||
this.onTabChange.fireDirect(this, this.active);
|
||||
}
|
||||
return tab;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the active TabPanelItem
|
||||
* @return {YAHOO.ext.TabPanelItem} The active TabPanelItem or null if none are active.
|
||||
*/
|
||||
getActiveTab : function(){
|
||||
return this.active;
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the tab body element to fit the height of the container element
|
||||
* for overflow scrolling
|
||||
* @param {Number} targetHeight (optional) Override the starting height from the elements height
|
||||
*/
|
||||
syncHeight : function(targetHeight){
|
||||
var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth('tb')-this.el.getPadding('tb');
|
||||
var bm = this.bodyEl.getMargins();
|
||||
var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
|
||||
this.bodyEl.setHeight(newHeight);
|
||||
return newHeight;
|
||||
},
|
||||
|
||||
onResize : function(){
|
||||
if(this.monitorResize){
|
||||
this.autoSizeTabs();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables tab resizing while tabs are being added (if resizeTabs is false this does nothing)
|
||||
*/
|
||||
beginUpdate : function(){
|
||||
this.updating = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops an update and resizes the tabs (if resizeTabs is false this does nothing)
|
||||
*/
|
||||
endUpdate : function(){
|
||||
this.updating = false;
|
||||
this.autoSizeTabs();
|
||||
},
|
||||
|
||||
/**
|
||||
* Manual call to resize the tabs (if resizeTabs is false this does nothing)
|
||||
*/
|
||||
autoSizeTabs : function(){
|
||||
var count = this.items.length;
|
||||
var vcount = count - this.hiddenCount;
|
||||
if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) return;
|
||||
var w = Math.max(this.el.getWidth() - this.cpad, 10);
|
||||
var availWidth = Math.floor(w / vcount);
|
||||
var b = this.stripBody;
|
||||
if(b.getWidth() > w){
|
||||
var tabs = this.items;
|
||||
this.setTabWidth(Math.max(availWidth, this.minTabWidth));
|
||||
if(availWidth < this.minTabWidth){
|
||||
/*if(!this.sleft){ // incomplete scrolling code
|
||||
this.createScrollButtons();
|
||||
}
|
||||
this.showScroll();
|
||||
this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
|
||||
}
|
||||
}else{
|
||||
if(this.currentTabWidth < this.preferredTabWidth){
|
||||
this.setTabWidth(Math.min(availWidth, this.preferredTabWidth));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the number of tabs
|
||||
* @return {Number}
|
||||
*/
|
||||
getCount : function(){
|
||||
return this.items.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resizes all the tabs to the passed width
|
||||
* @param {Number} The new width
|
||||
*/
|
||||
setTabWidth : function(width){
|
||||
this.currentTabWidth = width;
|
||||
for(var i = 0, len = this.items.length; i < len; i++) {
|
||||
if(!this.items[i].isHidden())this.items[i].setWidth(width);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys this TabPanel
|
||||
* @param {Boolean} removeEl (optional) True to remove the element from the DOM as well
|
||||
*/
|
||||
destroy : function(removeEl){
|
||||
YAHOO.ext.EventManager.removeResizeListener(this.onResize, this);
|
||||
for(var i = 0, len = this.items.length; i < len; i++){
|
||||
this.items[i].purgeListeners();
|
||||
}
|
||||
if(removeEl === true){
|
||||
this.el.update('');
|
||||
this.el.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class YAHOO.ext.TabPanelItem
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
*/
|
||||
YAHOO.ext.TabPanelItem = function(tabPanel, id, text, closable){
|
||||
/**
|
||||
* The TabPanel this TabPanelItem belongs to
|
||||
* @type YAHOO.ext.TabPanel
|
||||
*/
|
||||
this.tabPanel = tabPanel;
|
||||
/**
|
||||
* The id for this TabPanelItem
|
||||
* @type String
|
||||
*/
|
||||
this.id = id;
|
||||
/** @private */
|
||||
this.disabled = false;
|
||||
/** @private */
|
||||
this.text = text;
|
||||
/** @private */
|
||||
this.loaded = false;
|
||||
this.closable = closable;
|
||||
|
||||
/**
|
||||
* The body element for this TabPanelItem
|
||||
* @type YAHOO.ext.Element
|
||||
*/
|
||||
this.bodyEl = getEl(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
|
||||
this.bodyEl.setVisibilityMode(YAHOO.ext.Element.VISIBILITY);
|
||||
this.bodyEl.setStyle('display', 'block');
|
||||
this.bodyEl.setStyle('zoom', '1');
|
||||
this.hideAction();
|
||||
|
||||
var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
|
||||
/** @private */
|
||||
this.el = getEl(els.el, true);
|
||||
this.inner = getEl(els.inner, true);
|
||||
this.textEl = getEl(this.el.dom.firstChild.firstChild.firstChild, true);
|
||||
this.pnode = getEl(els.el.parentNode, true);
|
||||
this.el.mon('click', this.onTabClick, this, true);
|
||||
/** @private */
|
||||
if(closable){
|
||||
var c = getEl(els.close, true);
|
||||
c.dom.title = this.closeText;
|
||||
c.addClassOnOver('close-over');
|
||||
c.mon('click', this.closeClick, this, true);
|
||||
}
|
||||
|
||||
// these two are now private and deprecated
|
||||
this.onActivate = new YAHOO.util.CustomEvent('TabItem.onActivate');
|
||||
this.onDeactivate = new YAHOO.util.CustomEvent('TabItem.onDeactivate');
|
||||
|
||||
this.events = {
|
||||
/**
|
||||
* @event activate
|
||||
* Fires when this tab becomes the active tab
|
||||
* @param {YAHOO.ext.TabPanel} tabPanel
|
||||
* @param {YAHOO.ext.TabPanelItem} this
|
||||
*/
|
||||
'activate': this.onActivate,
|
||||
/**
|
||||
* @event beforeclose
|
||||
* Fires before this tab is closed. To cancal the close, set cancel to true on e. (e.cancel = true)
|
||||
* @param {YAHOO.ext.TabPanelItem} this
|
||||
* @param {Object} e Set cancel to true on this object to cancel the close.
|
||||
*/
|
||||
'beforeclose': new YAHOO.util.CustomEvent('beforeclose'),
|
||||
/**
|
||||
* @event close
|
||||
* Fires when this tab is closed
|
||||
* @param {YAHOO.ext.TabPanelItem} this
|
||||
*/
|
||||
'close': new YAHOO.util.CustomEvent('close'),
|
||||
/**
|
||||
* @event deactivate
|
||||
* Fires when this tab is no longer the active tab
|
||||
* @param {YAHOO.ext.TabPanel} tabPanel
|
||||
* @param {YAHOO.ext.TabPanelItem} this
|
||||
*/
|
||||
'deactivate' : this.onDeactivate
|
||||
};
|
||||
this.hidden = false;
|
||||
};
|
||||
|
||||
YAHOO.ext.TabPanelItem.prototype = {
|
||||
fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
|
||||
on : YAHOO.ext.util.Observable.prototype.on,
|
||||
addListener : YAHOO.ext.util.Observable.prototype.addListener,
|
||||
delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
|
||||
removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
|
||||
purgeListeners : function(){
|
||||
YAHOO.ext.util.Observable.prototype.purgeListeners.call(this);
|
||||
this.el.removeAllListeners();
|
||||
},
|
||||
/**
|
||||
* Show this TabPanelItem - this <b>does not</b> deactivate the currently active TabPanelItem.
|
||||
*/
|
||||
show : function(){
|
||||
this.pnode.addClass('on');
|
||||
this.showAction();
|
||||
if(YAHOO.ext.util.Browser.isOpera){
|
||||
this.tabPanel.stripWrap.repaint();
|
||||
}
|
||||
this.onActivate.fireDirect(this.tabPanel, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if this tab is the active tab
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isActive : function(){
|
||||
return this.tabPanel.getActiveTab() == this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide this TabPanelItem - if you don't activate another TabPanelItem this could look odd.
|
||||
*/
|
||||
hide : function(){
|
||||
this.pnode.removeClass('on');
|
||||
this.hideAction();
|
||||
this.onDeactivate.fireDirect(this.tabPanel, this);
|
||||
},
|
||||
|
||||
hideAction : function(){
|
||||
this.bodyEl.setStyle('position', 'absolute');
|
||||
this.bodyEl.setLeft('-20000px');
|
||||
this.bodyEl.setTop('-20000px');
|
||||
this.bodyEl.hide();
|
||||
},
|
||||
|
||||
showAction : function(){
|
||||
this.bodyEl.setStyle('position', 'relative');
|
||||
this.bodyEl.setTop('');
|
||||
this.bodyEl.setLeft('');
|
||||
this.bodyEl.show();
|
||||
this.tabPanel.el.repaint.defer(1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the tooltip (title attribute) for the tab
|
||||
* @param {String} tooltip
|
||||
*/
|
||||
setTooltip : function(text){
|
||||
this.textEl.dom.title = text;
|
||||
},
|
||||
|
||||
onTabClick : function(e){
|
||||
e.preventDefault();
|
||||
this.tabPanel.activate(this.id);
|
||||
},
|
||||
|
||||
getWidth : function(){
|
||||
return this.inner.getWidth();
|
||||
},
|
||||
|
||||
setWidth : function(width){
|
||||
var iwidth = width - this.pnode.getPadding("lr");
|
||||
this.inner.setWidth(iwidth);
|
||||
this.textEl.setWidth(iwidth-this.inner.getPadding('lr'));
|
||||
this.pnode.setWidth(width);
|
||||
},
|
||||
|
||||
setHidden : function(hidden){
|
||||
this.hidden = hidden;
|
||||
this.pnode.setStyle('display', hidden ? 'none' : '');
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if this tab is "hidden"
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isHidden : function(){
|
||||
return this.hidden;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the text for this tab
|
||||
* @return {String}
|
||||
*/
|
||||
getText : function(){
|
||||
return this.text;
|
||||
},
|
||||
|
||||
autoSize : function(){
|
||||
this.el.beginMeasure();
|
||||
this.textEl.setWidth(1);
|
||||
this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding('lr'));
|
||||
this.el.endMeasure();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the text for the tab (Note: this also sets the tooltip)
|
||||
* @param {String} text
|
||||
*/
|
||||
setText : function(text){
|
||||
this.text = text;
|
||||
this.textEl.update(text);
|
||||
this.textEl.dom.title = text;
|
||||
if(!this.tabPanel.resizeTabs){
|
||||
this.autoSize();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Activate this TabPanelItem - this <b>does</b> deactivate the currently active TabPanelItem.
|
||||
*/
|
||||
activate : function(){
|
||||
this.tabPanel.activate(this.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable this TabPanelItem - this call is ignore if this is the active TabPanelItem.
|
||||
*/
|
||||
disable : function(){
|
||||
if(this.tabPanel.active != this){
|
||||
this.disabled = true;
|
||||
this.pnode.addClass('disabled');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable this TabPanelItem if it was previously disabled.
|
||||
*/
|
||||
enable : function(){
|
||||
this.disabled = false;
|
||||
this.pnode.removeClass('disabled');
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the content for this TabPanelItem.
|
||||
* @param {String} content The content
|
||||
* @param {Boolean} loadScripts true to look for and load scripts
|
||||
*/
|
||||
setContent : function(content, loadScripts){
|
||||
this.bodyEl.update(content, loadScripts);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the {@link YAHOO.ext.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
|
||||
* @return {YAHOO.ext.UpdateManager} The UpdateManager
|
||||
*/
|
||||
getUpdateManager : function(){
|
||||
return this.bodyEl.getUpdateManager();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set a URL to be used to load the content for this TabPanelItem.
|
||||
* @param {String/Function} url The url to load the content from or a function to call to get the url
|
||||
* @param {<i>String/Object</i>} params (optional) The string params for the update call or an object of the params. See {@link YAHOO.ext.UpdateManager#update} for more details. (Defaults to null)
|
||||
* @param {<i>Boolean</i>} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
|
||||
* @return {YAHOO.ext.UpdateManager} The UpdateManager
|
||||
*/
|
||||
setUrl : function(url, params, loadOnce){
|
||||
if(this.refreshDelegate){
|
||||
this.onActivate.unsubscribe(this.refreshDelegate);
|
||||
}
|
||||
this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
|
||||
this.onActivate.subscribe(this.refreshDelegate);
|
||||
return this.bodyEl.getUpdateManager();
|
||||
},
|
||||
|
||||
/** @private */
|
||||
_handleRefresh : function(url, params, loadOnce){
|
||||
if(!loadOnce || !this.loaded){
|
||||
var updater = this.bodyEl.getUpdateManager();
|
||||
updater.update(url, params, this._setLoaded.createDelegate(this));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Force a content refresh from the URL specified in the setUrl() method.
|
||||
* Will fail silently if the setUrl method has not been called.
|
||||
* This does not activate the panel, just updates its content.
|
||||
*/
|
||||
refresh : function(){
|
||||
if(this.refreshDelegate){
|
||||
this.loaded = false;
|
||||
this.refreshDelegate();
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
_setLoaded : function(){
|
||||
this.loaded = true;
|
||||
},
|
||||
|
||||
/** @private */
|
||||
closeClick : function(e){
|
||||
var e = {};
|
||||
this.fireEvent('beforeclose', this, e);
|
||||
if(e.cancel !== true){
|
||||
this.tabPanel.removeTab(this.id);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* The text displayed in the tooltip for the close icon.
|
||||
* @type String
|
||||
*/
|
||||
closeText : 'Close this tab'
|
||||
};
|
||||
|
||||
/** @private */
|
||||
YAHOO.ext.TabPanel.prototype.createStrip = function(container){
|
||||
var strip = document.createElement('div');
|
||||
strip.className = 'ytab-wrap';
|
||||
container.appendChild(strip);
|
||||
return strip;
|
||||
};
|
||||
/** @private */
|
||||
YAHOO.ext.TabPanel.prototype.createStripList = function(strip){
|
||||
// div wrapper for retard IE
|
||||
strip.innerHTML = '<div class="ytab-strip-wrap"><table class="ytab-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr></tr></tbody></table></div>';
|
||||
return strip.firstChild.firstChild.firstChild.firstChild;
|
||||
};
|
||||
/** @private */
|
||||
YAHOO.ext.TabPanel.prototype.createBody = function(container){
|
||||
var body = document.createElement('div');
|
||||
YAHOO.util.Dom.generateId(body, 'tab-body');
|
||||
YAHOO.util.Dom.addClass(body, 'yui-ext-tabbody');
|
||||
container.appendChild(body);
|
||||
return body;
|
||||
};
|
||||
/** @private */
|
||||
YAHOO.ext.TabPanel.prototype.createItemBody = function(bodyEl, id){
|
||||
var body = YAHOO.util.Dom.get(id);
|
||||
if(!body){
|
||||
body = document.createElement('div');
|
||||
body.id = id;
|
||||
}
|
||||
YAHOO.util.Dom.addClass(body, 'yui-ext-tabitembody');
|
||||
bodyEl.insertBefore(body, bodyEl.firstChild);
|
||||
return body;
|
||||
};
|
||||
/** @private */
|
||||
YAHOO.ext.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
|
||||
var td = document.createElement('td');
|
||||
stripEl.appendChild(td);
|
||||
if(closable){
|
||||
td.className = "ytab-closable";
|
||||
if(!this.closeTpl){
|
||||
this.closeTpl = new YAHOO.ext.Template(
|
||||
'<a href="#" class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
|
||||
'<span unselectable="on" title="{text}" class="ytab-text">{text}</span>' +
|
||||
'<div unselectable="on" class="close-icon"> </div></em></span></a>'
|
||||
);
|
||||
}
|
||||
var el = this.closeTpl.overwrite(td, {'text': text});
|
||||
var close = el.getElementsByTagName('div')[0];
|
||||
var inner = el.getElementsByTagName('em')[0];
|
||||
return {'el': el, 'close': close, 'inner': inner};
|
||||
} else {
|
||||
if(!this.tabTpl){
|
||||
this.tabTpl = new YAHOO.ext.Template(
|
||||
'<a href="#" class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
|
||||
'<span unselectable="on" title="{text}" class="ytab-text">{text}</span></em></span></a>'
|
||||
);
|
||||
}
|
||||
var el = this.tabTpl.overwrite(td, {'text': text});
|
||||
var inner = el.getElementsByTagName('em')[0];
|
||||
return {'el': el, 'inner': inner};
|
||||
}
|
||||
};
|
||||
766
frontend/beta/js/YUI-extensions/widgets/TemplateView.js
Normal file
766
frontend/beta/js/YUI-extensions/widgets/TemplateView.js
Normal file
@@ -0,0 +1,766 @@
|
||||
/**
|
||||
* @class YAHOO.ext.View
|
||||
* @extends YAHOO.ext.util.Observable
|
||||
* Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
|
||||
* This class also supports single and multi selection modes. <br>
|
||||
* Create a data model bound view:
|
||||
<pre><code>
|
||||
var dataModel = new YAHOO.ext.grid.XMLDataModel(...);
|
||||
var view = new YAHOO.ext.View('my-element',
|
||||
'<div id="{0}">{2} - {1}</div>', // auto create template
|
||||
dataModel, {
|
||||
singleSelect: true,
|
||||
selectedClass: 'ydataview-selected'
|
||||
});
|
||||
|
||||
// listen for node click?
|
||||
view.on('click', function(vw, index, node, e){
|
||||
alert('Node "' + node.id + '" at index: ' + index + ' was clicked.');
|
||||
});
|
||||
|
||||
// load XML data
|
||||
dataModel.load('foobar.xml');
|
||||
</code></pre>
|
||||
For an example of creating a JSON/UpdateManager view, see {@link YAHOO.ext.JsonView}.
|
||||
* <br><br>
|
||||
* <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
|
||||
* IE's limited insertion support with tables and Opera's faulty event bubbling.</b>
|
||||
* @constructor
|
||||
* Create a new View
|
||||
* @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
|
||||
* @param {String/DomHelper.Template} tpl The rendering template or a string to create a template with
|
||||
* @param {DataModel} dataModel The bound data model
|
||||
* @param {Object} config The config object
|
||||
*/
|
||||
YAHOO.ext.View = function(container, tpl, dataModel, config){
|
||||
this.el = getEl(container, true);
|
||||
this.nodes = this.el.dom.childNodes;
|
||||
if(typeof tpl == 'string'){
|
||||
tpl = new YAHOO.ext.Template(tpl);
|
||||
}
|
||||
tpl.compile();
|
||||
/**
|
||||
* The template used by this View
|
||||
* @type {YAHOO.ext.DomHelper.Template}
|
||||
*/
|
||||
this.tpl = tpl;
|
||||
this.setDataModel(dataModel);
|
||||
var CE = YAHOO.util.CustomEvent;
|
||||
/** @private */
|
||||
this.events = {
|
||||
/**
|
||||
* @event beforeclick
|
||||
* Fires before a click is processed. Returns false to cancel the default action.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Number} index The index of the target node
|
||||
* @param {HTMLElement} node The target node
|
||||
* @param {YAHOO.ext.EventObject} e The raw event object
|
||||
*/
|
||||
'beforeclick' : true,
|
||||
/**
|
||||
* @event click
|
||||
* Fires when a template node is clicked.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Number} index The index of the target node
|
||||
* @param {HTMLElement} node The target node
|
||||
* @param {YAHOO.ext.EventObject} e The raw event object
|
||||
*/
|
||||
'click' : true,
|
||||
/**
|
||||
* @event dblclick
|
||||
* Fires when a template node is double clicked.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Number} index The index of the target node
|
||||
* @param {HTMLElement} node The target node
|
||||
* @param {YAHOO.ext.EventObject} e The raw event object
|
||||
*/
|
||||
'dblclick' : true,
|
||||
/**
|
||||
* @event contextmenu
|
||||
* Fires when a template node is right clicked.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Number} index The index of the target node
|
||||
* @param {HTMLElement} node The target node
|
||||
* @param {YAHOO.ext.EventObject} e The raw event object
|
||||
*/
|
||||
'contextmenu' : true,
|
||||
/**
|
||||
* @event selectionchange
|
||||
* Fires when the selected nodes change.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Array} selections Array of the selected nodes
|
||||
*/
|
||||
'selectionchange' : true,
|
||||
|
||||
/**
|
||||
* @event beforeselect
|
||||
* Fires before a selection is made. If any handlers return false, the selection is cancelled.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {HTMLElement} node The node to be selected
|
||||
* @param {Array} selections Array of currently selected nodes
|
||||
*/
|
||||
'beforeselect' : true
|
||||
};
|
||||
this.el.mon("click", this.onClick, this, true);
|
||||
this.el.mon("dblclick", this.onDblClick, this, true);
|
||||
this.el.mon("contextmenu", this.onContextMenu, this, true);
|
||||
|
||||
/**
|
||||
* The css class to add to selected nodes
|
||||
* @type {YAHOO.ext.DomHelper.Template}
|
||||
*/
|
||||
this.selectedClass = 'ydataview-selected';
|
||||
|
||||
this.emptyText = '';
|
||||
|
||||
this.selections = [];
|
||||
|
||||
this.lastSelection = null;
|
||||
|
||||
/**
|
||||
* The root property in the loaded json object that contains the data
|
||||
* @type {String}
|
||||
*/
|
||||
this.jsonRoot = null;
|
||||
YAHOO.ext.util.Config.apply(this, config);
|
||||
if(this.renderUpdates || this.jsonRoot){
|
||||
var um = this.el.getUpdateManager();
|
||||
um.setRenderer(this);
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.extendX(YAHOO.ext.View, YAHOO.ext.util.Observable, {
|
||||
/**
|
||||
* Returns the element this view is bound to.
|
||||
* @return {YAHOO.ext.Element}
|
||||
*/
|
||||
getEl : function(){
|
||||
return this.el;
|
||||
},
|
||||
|
||||
render : function(el, response){
|
||||
this.clearSelections();
|
||||
this.el.update('');
|
||||
var o;
|
||||
try{
|
||||
o = YAHOO.ext.util.JSON.decode(response.responseText);
|
||||
if(this.jsonRoot){
|
||||
o = eval('o.' + this.jsonRoot);
|
||||
}
|
||||
}catch(e){}
|
||||
/**
|
||||
* The current json data or null
|
||||
*/
|
||||
this.jsonData = o;
|
||||
this.beforeRender();
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
beforeRender : function(){
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the view.
|
||||
*/
|
||||
refresh : function(){
|
||||
this.clearSelections();
|
||||
this.el.update('');
|
||||
this.html = [];
|
||||
if(this.renderUpdates || this.jsonRoot){
|
||||
var o = this.jsonData;
|
||||
if(o){
|
||||
for(var i = 0, len = o.length; i < len; i++) {
|
||||
this.renderEach(o[i]);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.dataModel.each(this.renderEach, this);
|
||||
}
|
||||
var strHtml;
|
||||
if(this.html.length > 0){
|
||||
strHtml = this.html.join('');
|
||||
}else{
|
||||
strHtml = this.emptyText;
|
||||
}
|
||||
this.el.update(strHtml);
|
||||
this.html = null;
|
||||
this.nodes = this.el.dom.childNodes;
|
||||
this.updateIndexes(0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Function to override to reformat the data that is sent to
|
||||
* the template for each node.
|
||||
* @param {Array/Object} data The raw data (array of colData for a data model bound view or
|
||||
* a JSON object for an UpdateManager bound view).
|
||||
* @param {Number} index The index of the data within the data model
|
||||
*/
|
||||
prepareData : function(data, index){
|
||||
return data;
|
||||
},
|
||||
|
||||
renderEach : function(data){
|
||||
this.html[this.html.length] = this.tpl.applyTemplate(this.prepareData(data));
|
||||
},
|
||||
|
||||
/**
|
||||
* Refresh an individual node.
|
||||
* @param {Number} index
|
||||
*/
|
||||
refreshNode : function(index){
|
||||
this.refreshNodes(index, index);
|
||||
},
|
||||
|
||||
refreshNodes : function(dm, startIndex, endIndex){
|
||||
this.clearSelections();
|
||||
var dm = this.dataModel;
|
||||
var ns = this.nodes;
|
||||
for(var i = startIndex; i <= endIndex; i++){
|
||||
var d = this.prepareData(dm.getRow(i), i);
|
||||
if(i < ns.length-1){
|
||||
var old = ns[i];
|
||||
this.tpl.insertBefore(old, d);
|
||||
this.el.dom.removeChild(old);
|
||||
}else{
|
||||
this.tpl.append(this.el.dom, d);
|
||||
}
|
||||
}
|
||||
this.updateIndexes(startIndex, endIndex);
|
||||
},
|
||||
|
||||
deleteNodes : function(dm, startIndex, endIndex){
|
||||
this.clearSelections();
|
||||
if(startIndex == 0 && endIndex >= this.nodes.length-1){
|
||||
this.el.update('');
|
||||
}else{
|
||||
var el = this.el.dom;
|
||||
for(var i = startIndex; i <= endIndex; i++){
|
||||
el.removeChild(this.nodes[startIndex]);
|
||||
}
|
||||
this.updateIndexes(startIndex);
|
||||
}
|
||||
},
|
||||
|
||||
insertNodes : function(dm, startIndex, endIndex){
|
||||
if(this.nodes.length == 0){
|
||||
this.refresh();
|
||||
}else{
|
||||
this.clearSelections();
|
||||
var t = this.tpl;
|
||||
var before = this.nodes[startIndex];
|
||||
var dm = this.dataModel;
|
||||
if(before){
|
||||
for(var i = startIndex; i <= endIndex; i++){
|
||||
t.insertBefore(before, this.prepareData(dm.getRow(i), i));
|
||||
}
|
||||
}else{
|
||||
var el = this.el.dom;
|
||||
for(var i = startIndex; i <= endIndex; i++){
|
||||
t.append(el, this.prepareData(dm.getRow(i), i));
|
||||
}
|
||||
}
|
||||
this.updateIndexes(startIndex);
|
||||
}
|
||||
},
|
||||
|
||||
updateIndexes : function(dm, startIndex, endIndex){
|
||||
var ns = this.nodes;
|
||||
startIndex = startIndex || 0;
|
||||
endIndex = endIndex || ns.length-1;
|
||||
for(var i = startIndex; i <= endIndex; i++){
|
||||
ns[i].nodeIndex = i;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the data model this view uses and refresh the view.
|
||||
* @param {DataModel} dataModel
|
||||
*/
|
||||
setDataModel : function(dm){
|
||||
if(!dm) return;
|
||||
this.unplugDataModel(this.dataModel);
|
||||
this.dataModel = dm;
|
||||
dm.on('cellupdated', this.refreshNode, this, true);
|
||||
dm.on('datachanged', this.refresh, this, true);
|
||||
dm.on('rowsdeleted', this.deleteNodes, this, true);
|
||||
dm.on('rowsinserted', this.insertNodes, this, true);
|
||||
dm.on('rowsupdated', this.refreshNodes, this, true);
|
||||
dm.on('rowssorted', this.refresh, this, true);
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
/**
|
||||
* Unplug the data model and stop updates.
|
||||
* @param {DataModel} dataModel
|
||||
*/
|
||||
unplugDataModel : function(dm){
|
||||
if(!dm) return;
|
||||
dm.removeListener('cellupdated', this.refreshNode, this);
|
||||
dm.removeListener('datachanged', this.refresh, this);
|
||||
dm.removeListener('rowsdeleted', this.deleteNodes, this);
|
||||
dm.removeListener('rowsinserted', this.insertNodes, this);
|
||||
dm.removeListener('rowsupdated', this.refreshNodes, this);
|
||||
dm.removeListener('rowssorted', this.refresh, this);
|
||||
this.dataModel = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the template node the passed child belongs to or null if it doesn't belong to one.
|
||||
* @param {HTMLElement} node
|
||||
* @return {HTMLElement} The template node
|
||||
*/
|
||||
findItemFromChild : function(node){
|
||||
var el = this.el.dom;
|
||||
if(!node || node.parentNode == el){
|
||||
return node;
|
||||
}
|
||||
var p = node.parentNode;
|
||||
while(p && p != el){
|
||||
if(p.parentNode == el){
|
||||
return p;
|
||||
}
|
||||
p = p.parentNode;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/** @ignore */
|
||||
onClick : function(e){
|
||||
var item = this.findItemFromChild(e.getTarget());
|
||||
if(item){
|
||||
var index = this.indexOf(item);
|
||||
if(this.onItemClick(item, index, e) !== false){
|
||||
this.fireEvent('click', this, index, item, e);
|
||||
}
|
||||
}else{
|
||||
this.clearSelections();
|
||||
}
|
||||
},
|
||||
|
||||
/** @ignore */
|
||||
onContextMenu : function(e){
|
||||
var item = this.findItemFromChild(e.getTarget());
|
||||
if(item){
|
||||
this.fireEvent('contextmenu', this, this.indexOf(item), item, e);
|
||||
}
|
||||
},
|
||||
|
||||
/** @ignore */
|
||||
onDblClick : function(e){
|
||||
var item = this.findItemFromChild(e.getTarget());
|
||||
if(item){
|
||||
this.fireEvent('dblclick', this, this.indexOf(item), item, e);
|
||||
}
|
||||
},
|
||||
|
||||
onItemClick : function(item, index, e){
|
||||
if(this.fireEvent('beforeclick', this, index, item, e) !== false){
|
||||
if(this.multiSelect || this.singleSelect){
|
||||
if(this.multiSelect && e.shiftKey && this.lastSelection){
|
||||
this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
|
||||
}else{
|
||||
this.select(item, this.multiSelect && e.ctrlKey);
|
||||
this.lastSelection = item;
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of selected nodes.
|
||||
* @return {Number}
|
||||
*/
|
||||
getSelectionCount : function(){
|
||||
return this.selections.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the currently selected nodes.
|
||||
* @return {Array} An array of HTMLElements
|
||||
*/
|
||||
getSelectedNodes : function(){
|
||||
return this.selections;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the indexes of the selected nodes.
|
||||
* @return {Array}
|
||||
*/
|
||||
getSelectedIndexes : function(){
|
||||
var indexes = [];
|
||||
for(var i = 0, len = this.selections.length; i < len; i++) {
|
||||
indexes.push(this.selections[i].nodeIndex);
|
||||
}
|
||||
return indexes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all selections
|
||||
* @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
|
||||
*/
|
||||
clearSelections : function(suppressEvent){
|
||||
if(this.multiSelect || this.singleSelect){
|
||||
YAHOO.util.Dom.removeClass(this.selections, this.selectedClass);
|
||||
this.selections = [];
|
||||
if(!suppressEvent){
|
||||
this.fireEvent('selectionchange', this, this.selections);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the passed node is selected
|
||||
* @param {HTMLElement/Number} node The node or node index
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isSelected : function(node){
|
||||
node = this.getNode(node);
|
||||
var s = this.selections;
|
||||
if(s.length < 1){
|
||||
return false;
|
||||
}
|
||||
if(s.indexOf){
|
||||
return s.indexOf(node) !== -1;
|
||||
}else{
|
||||
for(var i = 0, len = s.length; i < len; i++){
|
||||
if (s[i] == node){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects nodes.
|
||||
* @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
|
||||
* @param {Boolean} keepExisting (optional) true to keep existing selections
|
||||
* @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
|
||||
*/
|
||||
select : function(nodeInfo, keepExisting, suppressEvent){
|
||||
if(!keepExisting){
|
||||
this.clearSelections(true);
|
||||
}
|
||||
if(nodeInfo instanceof Array){
|
||||
for(var i = 0, len = nodeInfo.length; i < len; i++) {
|
||||
this.select(nodeInfo[i], true, true);
|
||||
}
|
||||
}else{
|
||||
var node = this.getNode(nodeInfo);
|
||||
if(node && !this.isSelected(node)){
|
||||
if(this.fireEvent('beforeselect', this, node, this.selections) !== false){
|
||||
YAHOO.util.Dom.addClass(node, this.selectedClass);
|
||||
this.selections.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!suppressEvent){
|
||||
this.fireEvent('selectionchange', this, this.selections);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a template node.
|
||||
* @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
|
||||
* @return {HTMLElement} The node or null if it wasn't found
|
||||
*/
|
||||
getNode : function(nodeInfo){
|
||||
if(typeof nodeInfo == 'object'){
|
||||
return nodeInfo;
|
||||
}else if(typeof nodeInfo == 'string'){
|
||||
return document.getElementById(nodeInfo);
|
||||
}else if(typeof nodeInfo == 'number'){
|
||||
return this.nodes[nodeInfo];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a range template nodes.
|
||||
* @param {Number} startIndex
|
||||
* @param {Number} endIndex
|
||||
* @return {Array} An array of nodes
|
||||
*/
|
||||
getNodes : function(start, end){
|
||||
var ns = this.nodes;
|
||||
start = start || 0;
|
||||
end = typeof end == 'undefined' ? ns.length-1 : end;
|
||||
var nodes = [];
|
||||
if(start <= end){
|
||||
for(var i = start; i <= end; i++) {
|
||||
nodes.push(ns[i]);
|
||||
}
|
||||
}else{
|
||||
for(var i = start; i >= end; i--) {
|
||||
nodes.push(ns[i]);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the index of the passed node
|
||||
* @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
|
||||
* @return {Number} The index of the node or -1
|
||||
*/
|
||||
indexOf : function(node){
|
||||
node = this.getNode(node);
|
||||
if(typeof node.nodeIndex == 'number'){
|
||||
return node.nodeIndex;
|
||||
}
|
||||
var ns = this.nodes;
|
||||
for(var i = 0, len = ns.length; i < len; i++) {
|
||||
if(ns[i] == node){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @class YAHOO.ext.JsonView
|
||||
* @extends YAHOO.ext.View
|
||||
* Shortcut class to create a JSON + UpdateManager template view. Usage:
|
||||
<pre><code>
|
||||
var view = new YAHOO.ext.JsonView('my-element',
|
||||
'<div id="{id}">{foo} - {bar}</div>', // auto create template
|
||||
{ multiSelect: true, jsonRoot: 'data' });
|
||||
|
||||
// listen for node click?
|
||||
view.on('click', function(vw, index, node, e){
|
||||
alert('Node "' + node.id + '" at index: ' + index + ' was clicked.');
|
||||
});
|
||||
|
||||
// direct load of JSON data
|
||||
view.load('foobar.php');
|
||||
|
||||
|
||||
// Example from my blog list
|
||||
var tpl = new YAHOO.ext.Template(
|
||||
'<div class="entry">' +
|
||||
'<a class="entry-title" href="{link}">{title}</a>' +
|
||||
'<h4>{date} by {author} | {comments} Comments</h4>{description}' +
|
||||
'</div><hr />'
|
||||
);
|
||||
|
||||
var moreView = new YAHOO.ext.JsonView('entry-list', tpl, {
|
||||
jsonRoot: 'posts'
|
||||
});
|
||||
moreView.on('beforerender', this.sortEntries, this, true);
|
||||
moreView.load({
|
||||
url:'/blog/get-posts.php',
|
||||
params: 'allposts=true',
|
||||
text:'Loading Blog Entries...'
|
||||
});
|
||||
</code></pre>
|
||||
* @constructor
|
||||
* Create a new JsonView
|
||||
* @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
|
||||
* @param {DomHelper.Template} tpl The rendering template
|
||||
* @param {Object} config The config object
|
||||
*/
|
||||
YAHOO.ext.JsonView = function(container, tpl, config){
|
||||
var cfg = config || {};
|
||||
cfg.renderUpdates = true;
|
||||
YAHOO.ext.JsonView.superclass.constructor.call(this, container, tpl, null, cfg);
|
||||
/**
|
||||
* @event beforerender
|
||||
* Fires before rendering of the downloaded json data.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Object} data The json data loaded
|
||||
*/
|
||||
this.events['beforerender'] = true;
|
||||
/**
|
||||
* @event load
|
||||
* Fires when data is loaded.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Object} data The json data loaded
|
||||
* @param {Object} response The raw Connect response object
|
||||
*/
|
||||
this.events['load'] = true;
|
||||
/**
|
||||
* @event loadexception
|
||||
* Fires when loading fails.
|
||||
* @param {YAHOO.ext.View} this
|
||||
* @param {Object} response The raw Connect response object
|
||||
*/
|
||||
this.events['loadexception'] = true;
|
||||
this.el.getUpdateManager().on('update', this.onLoad, this, true);
|
||||
this.el.getUpdateManager().on('failure', this.onLoadException, this, true);
|
||||
};
|
||||
YAHOO.extendX(YAHOO.ext.JsonView, YAHOO.ext.View, {
|
||||
/**
|
||||
* Performs an async request, loading the JSON from the response. If params are specified it uses POST, otherwise it uses GET.
|
||||
* @param {Object/String/Function} url The url for this request or a function to call to get the url or a config object containing any of the following options:
|
||||
<pre><code>
|
||||
view.load({
|
||||
url: 'your-url.php',<br/>
|
||||
params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string<br/>
|
||||
callback: yourFunction,<br/>
|
||||
scope: yourObject, //(optional scope) <br/>
|
||||
discardUrl: false, <br/>
|
||||
nocache: false,<br/>
|
||||
text: 'Loading...',<br/>
|
||||
timeout: 30,<br/>
|
||||
scripts: false<br/>
|
||||
});
|
||||
</code></pre>
|
||||
* The only required property is url. The optional properties nocache, text and scripts
|
||||
* are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
|
||||
* @param {<i>String/Object</i>} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or an object {param1: 1, param2: 2}
|
||||
* @param {<i>Function</i>} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
|
||||
* @param {<i>Boolean</i>} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used url. If true, it will not store the url.
|
||||
*/
|
||||
load : function(){
|
||||
var um = this.el.getUpdateManager();
|
||||
um.update.apply(um, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of records in the current JSON dataset
|
||||
* @return {Number}
|
||||
*/
|
||||
getCount : function(){
|
||||
return this.jsonData ? this.jsonData.length : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the JSON object for the specified node(s)
|
||||
* @param {HTMLElement/Array} node The node or an array of nodes
|
||||
* @return {Object/Array} If you pass in an array, you get an array back, otherwise
|
||||
* you get the JSON object for the node
|
||||
*/
|
||||
getNodeData : function(node){
|
||||
if(node instanceof Array){
|
||||
var data = [];
|
||||
for(var i = 0, len = node.length; i < len; i++){
|
||||
data.push(this.getNodeData(node[i]));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
return this.jsonData[this.indexOf(node)] || null;
|
||||
},
|
||||
|
||||
beforeRender : function(){
|
||||
this.snapshot = this.jsonData;
|
||||
if(this.sortInfo){
|
||||
this.sort.apply(this, this.sortInfo);
|
||||
}
|
||||
this.fireEvent('beforerender', this, this.jsonData);
|
||||
},
|
||||
|
||||
onLoad : function(el, o){
|
||||
this.fireEvent('load', this, this.jsonData, o);
|
||||
},
|
||||
|
||||
onLoadException : function(el, o){
|
||||
this.fireEvent('loadexception', this, o);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter the data by a specific property.
|
||||
* @param {String} property A property on your JSON objects
|
||||
* @param {String/RegExp} value Either string that the property values
|
||||
* should start with or a RegExp to test against the property
|
||||
*/
|
||||
filter : function(property, value){
|
||||
if(this.jsonData){
|
||||
var data = [];
|
||||
var ss = this.snapshot;
|
||||
if(typeof value == 'string'){
|
||||
var vlen = value.length;
|
||||
if(vlen == 0){
|
||||
this.clearFilter();
|
||||
return;
|
||||
}
|
||||
value = value.toLowerCase();
|
||||
for(var i = 0, len = ss.length; i < len; i++){
|
||||
var o = ss[i];
|
||||
if(o[property].substr(0, vlen).toLowerCase() == value){
|
||||
data.push(o);
|
||||
}
|
||||
}
|
||||
}else if(value.exec){ // regex?
|
||||
for(var i = 0, len = ss.length; i < len; i++){
|
||||
var o = ss[i];
|
||||
if(value.test(o[property])){
|
||||
data.push(o);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
this.jsonData = data;
|
||||
this.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter by a function. The passed function will be called with each
|
||||
* object in the current dataset. If the function returns true, the value is kept
|
||||
* otherwise it is filtered.
|
||||
* @param {Function} fn
|
||||
* @param {Object} scope (optional) The scope of the function (defaults to this JsonView)
|
||||
*/
|
||||
filterBy : function(fn, scope){
|
||||
if(this.jsonData){
|
||||
var data = [];
|
||||
var ss = this.snapshot;
|
||||
for(var i = 0, len = ss.length; i < len; i++){
|
||||
var o = ss[i];
|
||||
if(fn.call(scope|| this, o)){
|
||||
data.push(o);
|
||||
}
|
||||
}
|
||||
this.jsonData = data;
|
||||
this.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the current filter.
|
||||
*/
|
||||
clearFilter : function(){
|
||||
if(this.snapshot && this.jsonData != this.snapshot){
|
||||
this.jsonData = this.snapshot;
|
||||
this.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the data for this view and refreshes it.
|
||||
* @param {String} property A property on your JSON objects to sort on
|
||||
* @param {String} direction (optional) desc or asc (defaults to asc)
|
||||
* @param {Function} sortType (optional) A function to call to convert the data to a sortable value.
|
||||
*/
|
||||
sort : function(property, dir, sortType){
|
||||
this.sortInfo = Array.prototype.slice.call(arguments, 0);
|
||||
if(this.jsonData){
|
||||
var p = property;
|
||||
var dsc = dir && dir.toLowerCase() == 'desc';
|
||||
var f = function(o1, o2){
|
||||
var v1 = sortType ? sortType(o1[p]) : o1[p];
|
||||
var v2 = sortType ? sortType(o2[p]) : o2[p];;
|
||||
if(v1 < v2){
|
||||
return dsc ? +1 : -1;
|
||||
}else if(v1 > v2){
|
||||
return dsc ? -1 : +1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
this.jsonData.sort(f);
|
||||
this.refresh();
|
||||
if(this.jsonData != this.snapshot){
|
||||
this.snapshot.sort(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
296
frontend/beta/js/YUI-extensions/widgets/Toolbar.js
Normal file
296
frontend/beta/js/YUI-extensions/widgets/Toolbar.js
Normal file
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* @class YAHOO.ext.Toolbar
|
||||
* Basic Toolbar used by the Grid to create the paging toolbar. This class is reusable but functionality
|
||||
* is limited. Look for more functionality in a future version.
|
||||
* @constructor
|
||||
* @param {String/HTMLElement/Element} container
|
||||
* @param {Array} buttons (optional) array of button configs or elements to add
|
||||
*/
|
||||
YAHOO.ext.Toolbar = function(container, buttons){
|
||||
this.el = getEl(container, true);
|
||||
var div = document.createElement('div');
|
||||
div.className = 'ytoolbar';
|
||||
var tb = document.createElement('table');
|
||||
tb.border = 0;
|
||||
tb.cellPadding = 0;
|
||||
tb.cellSpacing = 0;
|
||||
div.appendChild(tb);
|
||||
var tbody = document.createElement('tbody');
|
||||
tb.appendChild(tbody);
|
||||
var tr = document.createElement('tr');
|
||||
tbody.appendChild(tr);
|
||||
this.el.dom.appendChild(div);
|
||||
this.tr = tr;
|
||||
if(buttons){
|
||||
this.add.apply(this, buttons);
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.ext.Toolbar.prototype = {
|
||||
/**
|
||||
* Adds element(s) to the toolbar - this function takes a variable number of
|
||||
* arguments of mixed type and adds them to the toolbar...
|
||||
*
|
||||
* @param {Mixed} arg If arg is a ToolbarButton, it is added. If arg is a string, it is wrapped
|
||||
* in a ytb-text element and added unless the text is "separator" in which case a separator
|
||||
* is added. Otherwise, it is assumed the element is an HTMLElement and it is added directly.
|
||||
*/
|
||||
add : function(){
|
||||
for(var i = 0; i < arguments.length; i++){
|
||||
var el = arguments[i];
|
||||
var td = document.createElement('td');
|
||||
this.tr.appendChild(td);
|
||||
if(el instanceof YAHOO.ext.ToolbarButton){
|
||||
el.init(td);
|
||||
}else if(el instanceof Array){
|
||||
this.addButton(el);
|
||||
}else if(typeof el == 'string'){
|
||||
var span = document.createElement('span');
|
||||
if(el == 'separator'){
|
||||
span.className = 'ytb-sep';
|
||||
}else{
|
||||
span.innerHTML = el;
|
||||
span.className = 'ytb-text';
|
||||
}
|
||||
td.appendChild(span);
|
||||
}else if(typeof el == 'object' && el.nodeType){ // must be element?
|
||||
td.appendChild(el);
|
||||
}else if(typeof el == 'object'){ // must be button config?
|
||||
this.addButton(el);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the element for this toolbar
|
||||
* @return {YAHOO.ext.Element}
|
||||
*/
|
||||
getEl : function(){
|
||||
return this.el;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a separator
|
||||
*/
|
||||
addSeparator : function(){
|
||||
var td = document.createElement('td');
|
||||
this.tr.appendChild(td);
|
||||
var span = document.createElement('span');
|
||||
span.className = 'ytb-sep';
|
||||
td.appendChild(span);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a button (or buttons), see {@link YAHOO.ext.ToolbarButton} for more info on the config
|
||||
* @param {Object/Array} config A button config or array of configs
|
||||
* @return {YAHOO.ext.ToolbarButton/Array}
|
||||
*/
|
||||
addButton : function(config){
|
||||
if(config instanceof Array){
|
||||
var buttons = [];
|
||||
for(var i = 0, len = config.length; i < len; i++) {
|
||||
buttons.push(this.addButton(config[i]));
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
var b = config;
|
||||
if(!(config instanceof YAHOO.ext.ToolbarButton)){
|
||||
b = new YAHOO.ext.ToolbarButton(config);
|
||||
}
|
||||
this.add(b);
|
||||
return b;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds text to the toolbar
|
||||
* @param {String} text The text to add
|
||||
* @return {HTMLElement} The span element created which you can use to update the text.
|
||||
*/
|
||||
addText : function(text){
|
||||
var td = document.createElement('td');
|
||||
this.tr.appendChild(td);
|
||||
var span = document.createElement('span');
|
||||
span.className = 'ytb-text';
|
||||
span.innerHTML = text;
|
||||
td.appendChild(span);
|
||||
return span;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts a button (or buttons) at the specified index
|
||||
* @param {Number} index The index where the buttons are to be inserted
|
||||
* @param {Object/Array} config A button config or array of configs
|
||||
* @return {YAHOO.ext.ToolbarButton/Array}
|
||||
*/
|
||||
insertButton : function(index, config){
|
||||
if(config instanceof Array){
|
||||
var buttons = [];
|
||||
for(var i = 0, len = config.length; i < len; i++) {
|
||||
buttons.push(this.insertButton(index + i, config[i]));
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
var b = new YAHOO.ext.ToolbarButton(config);
|
||||
var td = document.createElement('td');
|
||||
var nextSibling = this.tr.childNodes[index];
|
||||
if (nextSibling)
|
||||
this.tr.insertBefore(td, nextSibling);
|
||||
else
|
||||
this.tr.appendChild(td);
|
||||
b.init(td);
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class YAHOO.ext.ToolbarButton
|
||||
* A toolbar button. The config has the following options:
|
||||
* <ul>
|
||||
* <li>className - The CSS class for the button. Use this to attach a background image for an icon.</li>
|
||||
* <li>text - The button's text</li>
|
||||
* <li>tooltip - The buttons tooltip text</li>
|
||||
* <li>click - function to call when the button is clicked</li>
|
||||
* <li>mouseover - function to call when the mouse moves over the button</li>
|
||||
* <li>mouseout - function to call when the mouse moves off the button</li>
|
||||
* <li>scope - The scope of the above event handlers</li>
|
||||
* <li></li>
|
||||
* <li></li>
|
||||
* @constructor
|
||||
* @param {Object} config
|
||||
*/
|
||||
YAHOO.ext.ToolbarButton = function(config){
|
||||
YAHOO.ext.util.Config.apply(this, config);
|
||||
};
|
||||
|
||||
YAHOO.ext.ToolbarButton.prototype = {
|
||||
/** @private */
|
||||
init : function(appendTo){
|
||||
var element = document.createElement('span');
|
||||
element.className = 'ytb-button';
|
||||
if(this.id){
|
||||
element.id = this.id;
|
||||
}
|
||||
this.setDisabled(this.disabled === true);
|
||||
var inner = document.createElement('span');
|
||||
inner.className = 'ytb-button-inner ' + (this.className || this.cls);
|
||||
inner.unselectable = 'on';
|
||||
if(this.tooltip){
|
||||
element.setAttribute('title', this.tooltip);
|
||||
}
|
||||
if(this.style){
|
||||
YAHOO.ext.DomHelper.applyStyles(inner, this.style);
|
||||
}
|
||||
element.appendChild(inner);
|
||||
appendTo.appendChild(element);
|
||||
this.el = getEl(element, true);
|
||||
this.el.unselectable();
|
||||
inner.innerHTML = (this.text ? this.text : ' ');
|
||||
this.inner = inner;
|
||||
this.el.mon('click', this.onClick, this, true);
|
||||
this.el.mon('mouseover', this.onMouseOver, this, true);
|
||||
this.el.mon('mouseout', this.onMouseOut, this, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets this buttons click handler
|
||||
* @param {Function} click The function to call when the button is clicked
|
||||
* @param {Object} scope (optional) Scope for the function passed above
|
||||
*/
|
||||
setHandler : function(click, scope){
|
||||
this.click = click;
|
||||
this.scope = scope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set this buttons text
|
||||
* @param {String} text
|
||||
*/
|
||||
setText : function(text){
|
||||
this.inner.innerHTML = text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set this buttons tooltip text
|
||||
* @param {String} text
|
||||
*/
|
||||
setTooltip : function(text){
|
||||
this.el.dom.title = text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show this button
|
||||
*/
|
||||
show: function(){
|
||||
this.el.dom.parentNode.style.display = '';
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide this button
|
||||
*/
|
||||
hide: function(){
|
||||
this.el.dom.parentNode.style.display = 'none';
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable this button
|
||||
*/
|
||||
disable : function(){
|
||||
this.disabled = true;
|
||||
if(this.el){
|
||||
this.el.addClass('ytb-button-disabled');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable this button
|
||||
*/
|
||||
enable : function(){
|
||||
this.disabled = false;
|
||||
if(this.el){
|
||||
this.el.removeClass('ytb-button-disabled');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if this button is disabled.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isDisabled : function(){
|
||||
return this.disabled === true;
|
||||
},
|
||||
|
||||
setDisabled : function(disabled){
|
||||
if(disabled){
|
||||
this.disable();
|
||||
}else{
|
||||
this.enable();
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onClick : function(){
|
||||
if(!this.disabled && this.click){
|
||||
this.click.call(this.scope || window, this);
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onMouseOver : function(){
|
||||
if(!this.disabled){
|
||||
this.el.addClass('ytb-button-over');
|
||||
if(this.mouseover){
|
||||
this.mouseover.call(this.scope || window, this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
onMouseOut : function(){
|
||||
this.el.removeClass('ytb-button-over');
|
||||
if(!this.disabled){
|
||||
if(this.mouseout){
|
||||
this.mouseout.call(this.scope || window, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user