1
0
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:
Giulio Cesare Solaroli
2011-10-03 00:56:18 +01:00
parent 597ecfbc02
commit ef68436ac0
729 changed files with 232898 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
YAHOO.ext.tree.AsyncTreeNode = function(config){
this.loaded = false;
this.loading = false;
YAHOO.ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
this.events['beforeload'] = true;
this.events['load'] = true;
};
YAHOO.extendX(YAHOO.ext.tree.AsyncTreeNode, YAHOO.ext.tree.TreeNode, {
expand : function(deep, anim, callback){
if(this.loading){ // if an async load is already running, waiting til it's done
var timer;
var f = function(){
if(!this.loading){ // done loading
clearInterval(timer);
this.expand(deep, anim, callback);
}
}.createDelegate(this);
timer = setInterval(f, 200);
}
if(!this.loaded){
if(this.fireEvent('beforeload', this) === false){
return;
}
this.loading = true;
this.ui.beforeLoad(this);
var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
if(loader){
loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
return;
}
}
YAHOO.ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
},
isLoading : function(){
return this.loading;
},
loadComplete : function(deep, anim, callback){
this.loading = false;
this.loaded = true;
this.ui.afterLoad(this);
this.fireEvent('load', this);
this.expand(deep, anim, callback);
},
isLoaded : function(){
return this.loaded;
},
hasChildNodes : function(){
if(!this.isLeaf() && !this.loaded){
return true;
}else{
return YAHOO.ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
}
}
});

View File

@@ -0,0 +1,43 @@
YAHOO.ext.tree.TreeDragZone = function(tree, config){
YAHOO.ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getEl(), config);
this.tree = tree;
};
YAHOO.extendX(YAHOO.ext.tree.TreeDragZone, YAHOO.ext.dd.DragZone, {
ddGroup : 'TreeDD',
onBeforeDrag : function(data, e){
var n = data.node;
return n && n.draggable && !n.disabled;
},
onInitDrag : function(e){
var data = this.dragData;
this.tree.getSelectionModel().select(data.node);
this.proxy.update('');
data.node.ui.appendDDGhost(this.proxy.ghost.dom);
this.tree.fireEvent('startdrag', this.tree, data.node, e);
},
getRepairXY : function(e, data){
return data.node.ui.getDDRepairXY();
},
onEndDrag : function(data, e){
this.tree.fireEvent('enddrag', this.tree, data.node, e);
},
onValidDrop : function(dd, e, id){
this.tree.fireEvent('dragdrop', this.tree, this.dragData.node, dd, e);
this.hideProxy();
},
beforeInvalidDrop : function(e, id){
if(YAHOO.util.Anim){
// this scrolls the original position back into view
var sm = this.tree.getSelectionModel();
sm.clearSelections();
sm.select(this.dragData.node);
}
}
});

View File

@@ -0,0 +1,228 @@
YAHOO.ext.tree.TreeDropZone = function(tree, config){
this.allowParentInsert = false;
this.allowContainerDrop = false;
this.appendOnly = false;
YAHOO.ext.tree.TreeDropZone.superclass.constructor.call(this, tree.container, config);
this.tree = tree;
this.lastInsertClass = 'ytree-no-status';
this.dragOverData = {};
};
YAHOO.extendX(YAHOO.ext.tree.TreeDropZone, YAHOO.ext.dd.DropZone, {
ddGroup : 'TreeDD',
expandDelay : 1000,
expandNode : function(node){
if(node.hasChildNodes() && !node.isExpanded()){
node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
}
},
queueExpand : function(node){
this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
},
cancelExpand : function(){
if(this.expandProcId){
clearTimeout(this.expandProcId);
this.expandProcId = false;
}
},
isValidDropPoint : function(n, pt, dd, e, data){
if(!n || !data){ return false; }
var targetNode = n.node;
var dropNode = data.node;
// default drop rules
if(!(targetNode && targetNode.isTarget && pt)){
return false;
}
if(pt == 'append' && targetNode.allowChildren === false){
return false;
}
if((pt == 'above' || pt == 'below') && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
return false;
}
if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
return false;
}
// reuse the object
var overEvent = this.dragOverData;
overEvent.tree = this.tree;
overEvent.target = targetNode;
overEvent.data = data;
overEvent.point = pt;
overEvent.source = dd;
overEvent.rawEvent = e;
overEvent.dropNode = dropNode;
overEvent.cancel = false;
var result = this.tree.fireEvent('nodedragover', overEvent);
return overEvent.cancel === false && result !== false;
},
getDropPoint : function(e, n, dd){
var tn = n.node;
if(tn.isRoot){
return tn.allowChildren !== false ? 'ap-pend' : false; // always append for root
}
var dragEl = n.ddel;
var t = YAHOO.util.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
var y = YAHOO.util.Event.getPageY(e);
var noAppend = tn.allowChildren === false || tn.isLeaf();
if(this.appendOnly || tn.parentNode.allowChildren === false){
return noAppend ? false : 'append';
}
var noBelow = false;
if(!this.allowParentInsert){
noBelow = tn.hasChildNodes() && tn.isExpanded();
}
var q = (b - t) / (noAppend ? 2 : 3);
if(y >= t && y < t + q){
return 'above';
}else if(!noBelow && (noAppend || y >= b-q && y <= b)){
return 'below';
}else{
return 'append';
}
return false;
},
onNodeEnter : function(n, dd, e, data){
this.cancelExpand();
},
onNodeOver : function(n, dd, e, data){
var pt = this.getDropPoint(e, n, dd);
var node = n.node;
// auto node expand check
if(!this.expandProcId && pt == 'append' && node.hasChildNodes() && !n.node.isExpanded()){
this.queueExpand(node);
}else if(pt != 'append'){
this.cancelExpand();
}
// set the insert point style on the target node
var returnCls = this.dropNotAllowed;
if(this.isValidDropPoint(n, pt, dd, e, data)){
if(pt){
var el = n.ddel;
var cls, returnCls;
if(pt == 'above'){
returnCls = n.node.isFirst() ? 'ytree-drop-ok-above' : 'ytree-drop-ok-between';
cls = 'ytree-drag-insert-above';
}else if(pt == 'below'){
returnCls = n.node.isLast() ? 'ytree-drop-ok-below' : 'ytree-drop-ok-between';
cls = 'ytree-drag-insert-below';
}else{
returnCls = 'ytree-drop-ok-append';
cls = 'ytree-drag-append';
}
if(this.lastInsertClass != cls){
YAHOO.util.Dom.replaceClass(el, this.lastInsertClass, cls);
this.lastInsertClass = cls;
}
}
}
return returnCls;
},
onNodeOut : function(n, dd, e, data){
this.cancelExpand();
this.removeDropIndicators(n);
},
onNodeDrop : function(n, dd, e, data){
var point = this.getDropPoint(e, n, dd);
var targetNode = n.node;
targetNode.ui.startDrop();
if(!this.isValidDropPoint(n, point, dd, e, data)){
targetNode.ui.endDrop();
return false;
}
// first try to find the drop node
var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
var dropEvent = {
tree : this.tree,
target: targetNode,
data: data,
point: point,
source: dd,
rawEvent: e,
dropNode: dropNode,
cancel: dropNode ? false : true
};
var retval = this.tree.fireEvent('beforenodedrop', dropEvent);
if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
targetNode.ui.endDrop();
return false;
}
if(point == 'append' && !targetNode.isExpanded()){
targetNode.expand(false, null, function(){
this.completeDrop(dropEvent);
}.createDelegate(this));
}else{
this.completeDrop(dropEvent);
}
return true;
},
completeDrop : function(de){
var ns = de.dropNode, p = de.point, t = de.target;
if(!(ns instanceof Array)){
ns = [ns];
}
var n;
for(var i = 0, len = ns.length; i < len; i++){
n = ns[i];
if(p == 'above'){
t.parentNode.insertBefore(n, t);
}else if(p == 'below'){
t.parentNode.insertBefore(n, t.nextSibling);
}else{
t.appendChild(n);
}
}
n.select(); // select and highlight the last insert
if(this.tree.hlDrop){
n.ui.highlight();
}
t.ui.endDrop();
this.tree.fireEvent('nodedrop', de);
},
afterNodeMoved : function(dd, data, e, targetNode, dropNode){
if(this.tree.hlDrop){
dropNode.select();
dropNode.ui.highlight();
}
this.tree.fireEvent('nodedrop', this.tree, targetNode, data, dd, e);
},
getTree : function(){
return this.tree;
},
removeDropIndicators : function(n){
if(n && n.ddel){
var el = n.ddel;
YAHOO.util.Dom.removeClass(el, 'ytree-drag-insert-above');
YAHOO.util.Dom.removeClass(el, 'ytree-drag-insert-below');
YAHOO.util.Dom.removeClass(el, 'ytree-drag-append');
this.lastInsertClass = '_noclass';
}
},
beforeDragDrop : function(target, e, id){
this.cancelExpand();
return true;
},
afterRepair : function(data){
if(data){
data.node.ui.highlight();
}
this.hideProxy();
}
});

View File

@@ -0,0 +1,105 @@
/**
* This doesn't update the indent (lines) or expand collapse icons of the nodes
*/
YAHOO.ext.tree.TreeFilter = function(tree, config){
this.tree = tree;
this.filtered = {};
YAHOO.ext.util.Config.apply(this, config, {
clearBlank:false,
reverse:false,
autoClear:false,
remove:false
});
};
YAHOO.ext.tree.TreeFilter.prototype = {
/**
* Filter the data by a specific attribute.
* @param {String/RegExp} value Either string that the attribute value
* should start with or a RegExp to test against the attribute
* @param {String} attr (optional) The attribute passed in your node's attributes collection. Defaults to "text".
* @param {TreeNode} startNode (optional) The node to start the filter at.
*/
filter : function(value, attr, startNode){
attr = attr || 'text';
var f;
if(typeof value == 'string'){
var vlen = value.length;
// auto clear empty filter
if(vlen == 0 && this.clearBlank){
this.clearFilter();
return;
}
value = value.toLowerCase();
f = function(n){
return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
}
}else if(value.exec){ // regex?
f = function(n){
return value.test(n.attributes[attr]);
}
}else{
throw 'Illegal filter type, must be string or regex';
}
this.filterBy(f, null, startNode);
},
/**
* Filter by a function. The passed function will be called with each
* node in the tree (or from the startNode). If the function returns true, the node is kept
* otherwise it is filtered. If a node is filtered, it's children are also filtered.
* @param {Function} fn The filter function
* @param {Object} scope (optional) The scope of the function (defaults to the current node)
*/
filterBy : function(fn, scope, startNode){
startNode = startNode || this.tree.root;
if(this.autoClear){
this.clearFilter();
}
var af = this.filtered, rv = this.reverse;
var f = function(n){
if(n == startNode){
return true;
}
if(af[n.id]){
return false;
}
var m = fn.call(scope || n, n);
if(!m || rv){
af[n.id] = n;
n.ui.hide();
return false;
}
return true;
}
startNode.cascade(f);
if(this.remove){
for(var id in af){
if(typeof id != 'function'){
var n = af[id];
if(n && n.parentNode){
n.parentNode.removeChild(n);
}
}
}
}
},
/**
* Clears the current filter. Note: with the "remove" option
* set a filter cannot be cleared.
*/
clear : function(){
var t = this.tree;
var af = this.filtered;
for(var id in af){
if(typeof id != 'function'){
var n = af[id];
if(n){
n.ui.show();
}
}
}
this.filtered = {};
}
};

View File

@@ -0,0 +1,107 @@
YAHOO.ext.tree.TreeLoader = function(config){
this.baseParams = {};
this.requestMethod = 'POST';
YAHOO.ext.util.Config.apply(this, config);
this.events = {
'beforeload' : true,
'load' : true,
'loadexception' : true
};
};
YAHOO.extendX(YAHOO.ext.tree.TreeLoader, YAHOO.ext.util.Observable, {
load : function(node, callback){
if(node.attributes.children){ // preloaded json children
var cs = node.attributes.children;
for(var i = 0, len = cs.length; i < len; i++){
node.appendChild(this.createNode(cs[i]));
}
if(typeof callback == 'function'){
callback();
}
}else if(this.dataUrl){
this.requestData(node, callback);
}
},
getParams: function(node){
var buf = [], bp = this.baseParams;
for(var key in bp){
if(typeof bp[key] != 'function'){
buf.push(encodeURIComponent(key), '=', encodeURIComponent(bp[key]), '&');
}
}
buf.push('node=', encodeURIComponent(node.id));
return buf.join('');
},
requestData : function(node, callback){
if(this.fireEvent('beforeload', this, node, callback) !== false){
var params = this.getParams(node);
var cb = {
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {callback: callback, node: node}
};
this.transId = YAHOO.util.Connect.asyncRequest(this.requestMethod, this.dataUrl, cb, params);
}else{
// if the load is cancelled, make sure we notify
// the node that we are done
if(typeof callback == 'function'){
callback();
}
}
},
isLoading : function(){
return this.transId ? true : false;
},
abort : function(){
if(this.isLoading()){
YAHOO.util.Connect.abort(this.transId);
}
},
createNode : function(attr){
if(this.applyLoader !== false){
attr.loader = this;
}
return(attr.leaf ?
new YAHOO.ext.tree.TreeNode(attr) :
new YAHOO.ext.tree.AsyncTreeNode(attr));
},
processResponse : function(response, node, callback){
var json = response.responseText;
try {
var o = eval('('+json+')');
for(var i = 0, len = o.length; i < len; i++){
node.appendChild(this.createNode(o[i]));
}
if(typeof callback == 'function'){
callback();
}
}catch(e){
this.handleFailure(response);
}
},
handleResponse : function(response){
this.transId = false;
var a = response.argument;
this.processResponse(response, a.node, a.callback);
this.fireEvent('load', this, a.node, response);
},
handleFailure : function(response){
this.transId = false;
var a = response.argument;
this.fireEvent('loadexception', this, a.node, response);
if(typeof a.callback == 'function'){
a.callback();
}
}
});

View File

@@ -0,0 +1,300 @@
/**
* @class YAHOO.ext.tree.TreeNode
* @extends YAHOO.ext.data.Node
* @cfg {Boolean} leaf true if this node is a leaf and does not have or cannot have children
* @cfg {Boolean} expanded true to start the node expanded
* @cfg {Boolean} draggable false to make this node undraggable if DD is on (default to true)
* @cfg {Boolean} isTarget false if this node cannot be drop on
* @cfg {Boolean} disabled true to start the node disabled
* @constructor
* @param {Object} attributes The attributes/config for the node
*/
YAHOO.ext.tree.TreeNode = function(attributes){
attributes = attributes || {};
if(typeof attributes == 'string'){
attributes = {text: attributes};
}
this.el = null;
this.childrenRendered = false;
this.rendered = false;
YAHOO.ext.tree.TreeNode.superclass.constructor.call(this, attributes);
this.expanded = attributes.expanded === true;
this.isTarget = attributes.isTarget !== false;
this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
this.text = attributes.text;
this.disabled = attributes.disabled === true;
YAHOO.ext.util.Config.apply(this.events, {
'textchange' : true,
'beforeexpand' : true,
'beforecollapse' : true,
'expand' : true,
'disabledchange' : true,
'collapse' : true,
'beforeclick':true,
'click':true,
'dblclick':true,
'contentmenu':true,
'beforechildrenrendered':true
});
var uiClass = this.attributes.uiProvider || YAHOO.ext.tree.TreeNodeUI;
this.ui = new uiClass(this);
};
YAHOO.extendX(YAHOO.ext.tree.TreeNode, YAHOO.ext.data.Node, {
isExpanded : function(){
return this.expanded;
},
getUI : function(){
return this.ui;
},
setFirstChild : function(node){
var of = this.firstChild;
YAHOO.ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
if(this.childrenRendered && of && node != of){
of.renderIndent(true, true);
}
if(this.rendered){
this.renderIndent(true, true);
}
},
setLastChild : function(node){
var ol = this.lastChild;
YAHOO.ext.tree.TreeNode.superclass.setLastChild.call(this, node);
if(this.childrenRendered && ol && node != ol){
ol.renderIndent(true, true);
}
if(this.rendered){
this.renderIndent(true, true);
}
},
// these methods are overridden to provide lazy rendering support
appendChild : function(){
var node = YAHOO.ext.tree.TreeNode.superclass.appendChild.apply(this, arguments);
if(node && this.childrenRendered){
node.render();
}
this.ui.updateExpandIcon();
return node;
},
removeChild : function(node){
this.ownerTree.getSelectionModel().unselect(node);
YAHOO.ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
// if it's been rendered remove dom node
if(this.childrenRendered){
node.ui.remove();
}
if(this.childNodes.length < 1){
this.collapse(false, false);
}else{
this.ui.updateExpandIcon();
}
return node;
},
insertBefore : function(node, refNode){
var newNode = YAHOO.ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
if(newNode && refNode && this.childrenRendered){
node.render();
}
this.ui.updateExpandIcon();
return newNode;
},
setText : function(text){
var oldText = this.text;
this.text = text;
this.attributes.text = text;
if(this.rendered){ // event without subscribing
this.ui.onTextChange(this, text, oldText);
}
this.fireEvent('textchange', this, text, oldText);
},
select : function(){
this.getOwnerTree().getSelectionModel().select(this);
},
unselect : function(){
this.getOwnerTree().getSelectionModel().unselect(this);
},
isSelected : function(){
return this.getOwnerTree().getSelectionModel().isSelected(node);
},
expand : function(deep, anim, callback){
if(!this.expanded){
if(this.fireEvent('beforeexpand', this, deep, anim) === false){
return;
}
if(!this.childrenRendered){
this.renderChildren();
}
this.expanded = true;
if((this.getOwnerTree().animate && anim !== false) || anim){
this.ui.animExpand(function(){
this.fireEvent('expand', this);
if(typeof callback == 'function'){
callback(this);
}
if(deep === true){
this.expandChildNodes(true);
}
}.createDelegate(this));
return;
}else{
this.ui.expand();
this.fireEvent('expand', this);
if(typeof callback == 'function'){
callback(this);
}
}
}else{
if(typeof callback == 'function'){
callback(this);
}
}
if(deep === true){
this.expandChildNodes(true);
}
},
collapse : function(deep, anim){
if(this.expanded && (!this.isRoot || (this.isRoot && this.getOwnerTree().rootVisible))){
if(this.fireEvent('beforecollapse', this, deep, anim) === false){
return;
}
this.expanded = false;
if((this.getOwnerTree().animate && anim !== false) || anim){
this.ui.animCollapse(function(){
this.fireEvent('collapse', this);
if(deep === true){
this.collapseChildNodes(true);
}
}.createDelegate(this));
return;
}else{
this.ui.collapse();
this.fireEvent('collapse', this);
}
}
if(deep === true){
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++) {
cs[i].collapse(true)
}
}
},
delayedExpand : function(delay){
if(!this.expandProcId){
this.expandProcId = this.expand.defer(delay, this);
}
},
cancelExpand : function(){
if(this.expandProcId){
clearTimeout(this.expandProcId);
}
this.expandProcId = false;
},
toggle : function(){
if(this.expanded){
this.collapse();
}else{
this.expand();
}
},
ensureVisible : function(){
if(this.parentNode){
this.parentNode.bubble(function(){
this.expand(false, false);
});
}
},
expandChildNodes : function(deep){
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++) {
cs[i].expand(deep);
}
},
collapseChildNodes : function(deep){
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++) {
cs[i].expand(deep);
}
},
disable : function(){
this.disabled = true;
this.unselect();
if(this.rendered && this.ui.onDisableChange){ // event without subscribing
this.ui.onDisableChange(this, true);
}
this.fireEvent('disabledchange', this, true);
},
enable : function(){
this.disabled = false;
if(this.rendered && this.ui.onDisableChange){ // event without subscribing
this.ui.onDisableChange(this, false);
}
this.fireEvent('disabledchange', this, false);
},
renderChildren : function(suppressEvent){
if(suppressEvent !== false){
this.fireEvent('beforechildrenrendered', this);
}
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++){
cs[i].render(true);
}
this.childrenRendered = true;
},
sort : function(fn, scope){
YAHOO.ext.tree.TreeNode.superclass.sort.apply(this, arguments);
if(this.childrenRendered){
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++){
cs[i].render(true);
}
}
},
render : function(bulkRender){
this.ui.render(bulkRender);
if(!this.rendered){
this.rendered = true;
if(this.expanded){
this.expanded = false;
this.expand(false, false);
}
}
},
renderIndent : function(deep, refresh){
if(refresh){
this.ui.childIndent = null;
}
this.ui.renderIndent();
if(deep === true && this.childrenRendered){
var cs = this.childNodes;
for(var i = 0, len = cs.length; i < len; i++){
cs[i].renderIndent(true, refresh);
}
}
}
});

View File

@@ -0,0 +1,452 @@
/**
* The TreeNode UI implementation is separate from the
* tree implementation. Unless you are customizing the tree UI,
* you should never have to use this directly.
*/
YAHOO.ext.tree.TreeNodeUI = function(node){
this.node = node;
this.rendered = false;
this.animating = false;
};
YAHOO.ext.tree.TreeNodeUI.prototype = {
emptyIcon : Ext.BLANK_IMAGE_URL,
removeChild : function(node){
if(this.rendered){
this.ctNode.removeChild(node.ui.getEl());
}
},
beforeLoad : function(){
YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-loading');
},
afterLoad : function(){
YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-loading');
},
onTextChange : function(node, text, oldText){
if(this.rendered){
this.textNode.innerHTML = text;
}
},
onDisableChange : function(node, state){
this.disabled = state;
if(state){
YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled');
}else{
YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-disabled');
}
},
onSelectedChange : function(state){
if(state){
this.focus();
YAHOO.util.Dom.addClass(this.elNode, 'ytree-selected');
}else{
this.blur();
YAHOO.util.Dom.removeClass(this.elNode, 'ytree-selected');
}
},
onMove : function(tree, node, oldParent, newParent, index, refNode){
this.childIndent = null;
if(this.rendered){
var targetNode = newParent.ui.getContainer();
if(!targetNode){//target not rendered
this.holder = document.createElement('div');
this.holder.appendChild(this.wrap);
return;
}
var insertBefore = refNode ? refNode.ui.getEl() : null;
if(insertBefore){
targetNode.insertBefore(this.wrap, insertBefore);
}else{
targetNode.appendChild(this.wrap);
}
this.node.renderIndent(true);
}
},
remove : function(){
if(this.rendered){
this.holder = document.createElement('div');
this.holder.appendChild(this.wrap);
}
},
fireEvent : function(){
this.node.fireEvent.apply(this.node, arguments);
},
initEvents : function(){
this.node.on('move', this.onMove, this, true);
//this.node.on('hiddenchange', this.onHiddenChange, this, true);
// these were optimized out but a custom UI could use them
//this.node.on('remove', this.onChildRemoved, this, true);
//this.node.on('selectedstatechange', this.onSelectedChange, this, true);
//this.node.on('disabledchange', this.onDisableChange, this, true);
//this.node.on('textchange', this.onTextChange, this, true);
var E = YAHOO.util.Event;
var a = this.anchor;
var el = YAHOO.ext.Element.fly(a);
if(YAHOO.ext.util.Browser.isOpera){ // opera render bug ignores the CSS
el.setStyle('text-decoration', 'none');
}
el.mon('click', this.onClick, this, true);
el.mon('dblclick', this.onDblClick, this, true);
el.mon('contextmenu', this.onContextMenu, this, true);
//el.on('focus', function(){
// this.node.getOwnerTree().getSelectionModel().select(this.node);
//}, this, true);
var icon = YAHOO.ext.Element.fly(this.iconNode);
icon.mon('click', this.onClick, this, true);
icon.mon('dblclick', this.onDblClick, this, true);
icon.mon('contextmenu', this.onContextMenu, this, true);
E.on(this.ecNode, 'click', this.ecClick, this, true);
if(this.node.disabled){
YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled');
}
if(this.node.hidden){
YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled');
}
var dd = this.node.ownerTree.enableDD || this.node.ownerTree.enableDrag || this.node.ownerTree.enableDrop;
if(dd && (!this.node.isRoot || this.node.ownerTree.rootVisible)){
YAHOO.ext.dd.Registry.register(this.elNode, {
node: this.node,
handles: [this.iconNode, this.textNode],
isHandle: false
});
}
},
hide : function(){
if(this.rendered){
this.wrap.style.display = 'none';
}
},
show : function(){
if(this.rendered){
this.wrap.style.display = '';
}
},
onContextMenu : function(e){
e.preventDefault();
this.focus();
this.fireEvent('contextmenu', this.node, e);
},
onClick : function(e){
if(this.dropping){
return;
}
if(this.fireEvent('beforeclick', this.node, e) !== false){
if(!this.disabled && this.node.attributes.href){
this.focus();
this.fireEvent('click', this.node, e);
return;
}
e.preventDefault();
if(this.disabled){
return;
}
this.focus();
this.fireEvent('click', this.node, e);
}else{
e.stopEvent();
}
},
onDblClick : function(e){
e.preventDefault();
if(this.disabled){
return;
}
if(!this.animating && this.node.hasChildNodes()){
this.node.toggle();
}
this.fireEvent('dblclick', this.node, e);
},
ecClick : function(e){
if(!this.animating && this.node.hasChildNodes()){
this.node.toggle();
}
},
startDrop : function(){
this.dropping = true;
},
// delayed drop so the click event doesn't get fired on a drop
endDrop : function(){
setTimeout(function(){
this.dropping = false;
}.createDelegate(this), 50);
},
expand : function(){
this.updateExpandIcon();
this.ctNode.style.display = '';
},
focus : function(){
try{
this.anchor.focus();
}catch(e){}
},
blur : function(){
try{
this.anchor.blur();
}catch(e){}
},
animExpand : function(callback){
if(this.animating && this.anim){
this.anim.stop();
}
this.animating = true;
this.updateExpandIcon();
var ct = this.ctNode;
var cs = ct.style;
cs.position = 'absolute';
cs.visibility = 'hidden';
cs.display = '';
var h = ct.clientHeight;
cs.overflow = 'hidden';
cs.height = '1px';
cs.position = '';
cs.visibility = '';
var anim = new YAHOO.util.Anim(ct, {
height: {to: h}
}, this.node.ownerTree.duration || .25, YAHOO.util.Easing.easeOut);
anim.onComplete.subscribe(function(){
cs.overflow = '';
cs.height = '';
this.animating = false;
this.anim = null;
if(typeof callback == 'function'){
callback();
}
}, this, true);
this.anim = anim;
anim.animate();
},
highlight : function(){
var tree = this.node.getOwnerTree();
var hlColor = tree.hlColor || 'C3DAF9';
var hlBaseColor = tree.hlBaseColor || 'FFFFFF';
var anim = new YAHOO.util.ColorAnim(this.wrap, {
backgroundColor: {from: hlColor, to: hlBaseColor}
}, .75, YAHOO.util.Easing.easeNone);
anim.onComplete.subscribe(function(){
YAHOO.util.Dom.setStyle(this.wrap, 'background-color', '');
}, this, true);
anim.animate();
},
collapse : function(){
this.updateExpandIcon();
this.ctNode.style.display = 'none';
},
animCollapse : function(callback){
if(this.animating && this.anim){
this.anim.stop();
}
this.animating = true;
this.updateExpandIcon();
var ct = this.ctNode;
var cs = ct.style;
cs.height = ct.offsetHeight +'px';
cs.overflow = 'hidden';
var anim = new YAHOO.util.Anim(ct, {
height: {to: 1}
}, this.node.ownerTree.duration || .25, YAHOO.util.Easing.easeOut);
anim.onComplete.subscribe(function(){
cs.display = 'none';
cs.overflow = '';
cs.height = '';
this.animating = false;
this.anim = null;
if(typeof callback == 'function'){
callback();
}
}, this, true);
this.anim = anim;
anim.animate();
},
getContainer : function(){
return this.ctNode;
},
getEl : function(){
return this.wrap;
},
appendDDGhost : function(ghostNode){
ghostNode.appendChild(this.elNode.cloneNode(true));
},
getDDRepairXY : function(){
return YAHOO.util.Dom.getXY(this.iconNode);
},
onRender : function(){
this.render();
},
render : function(bulkRender){
var n = this.node;
var targetNode = n.parentNode ?
n.parentNode.ui.getContainer() : n.ownerTree.container.dom;
if(!this.rendered){
this.rendered = true;
var a = n.attributes;
// add some indent caching, this helps performance when rendering a large tree
this.indentMarkup = '';
if(n.parentNode){
this.indentMarkup = n.parentNode.ui.getChildIndent();
}
var buf = ['<li class="ytree-node"><div class="ytree-node-el ', n.attributes.cls,'">',
'<span class="ytree-node-indent">',this.indentMarkup,'</span>',
'<img src="', this.emptyIcon, '" class="ytree-ec-icon">',
'<img src="', a.icon || this.emptyIcon, '" class="ytree-node-icon',(a.icon ? ' ytree-node-inline-icon' : ''),'" unselectable="on">',
'<a href="',a.href ? a.href : '#','" tabIndex="1" ',
a.hrefTarget ? ' target="'+a.hrefTarget+'"' : '','><span unselectable="on">',n.text,'</span></a></div>',
'<ul class="ytree-node-ct" style="display:none;"></ul>',
'</li>'];
if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
this.wrap = YAHOO.ext.DomHelper.insertHtml('beforeBegin',
n.nextSibling.ui.getEl(), buf.join(''));
}else{
this.wrap = YAHOO.ext.DomHelper.insertHtml('beforeEnd', targetNode, buf.join(''));
}
this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
this.anchor = cs[3];
this.textNode = cs[3].firstChild;
if(a.qtip){
if(this.textNode.setAttributeNS){
this.textNode.setAttributeNS('y', 'qtip', a.qtip);
if(a.qtipTitle){
this.textNode.setAttributeNS('y', 'qtitle', a.qtipTitle);
}
}else{
this.textNode.setAttribute('y:qtip', a.qtip);
if(a.qtipTitle){
this.textNode.setAttribute('y:qtitle', a.qtipTitle);
}
}
}
this.initEvents();
//this.renderIndent(); cached above now instead call updateExpandIcon
this.updateExpandIcon();
}else{
if(bulkRender === true) {
targetNode.appendChild(this.wrap);
}
}
},
getAnchor : function(){
return this.anchor;
},
getTextEl : function(){
return this.textNode;
},
getIconEl : function(){
return this.iconNode;
},
updateExpandIcon : function(){
if(this.rendered){
var n = this.node;
var cls = n.isLast() ? "ytree-elbow-end" : "ytree-elbow";
var hasChild = n.hasChildNodes();
if(hasChild){
cls += n.expanded ? '-minus' : '-plus';
var c1 = n.expanded ? 'ytree-node-collapsed' : 'ytree-node-expanded';
var c2 = n.expanded ? 'ytree-node-expanded' : 'ytree-node-collapsed';
YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-leaf');
YAHOO.util.Dom.replaceClass(this.elNode, c1, c2);
}else{
YAHOO.util.Dom.replaceClass(this.elNode, 'ytree-node-expanded', 'ytree-node-leaf');
}
this.ecNode.className = 'ytree-ec-icon '+cls;
}
},
getChildIndent : function(){
if(!this.childIndent){
var buf = [];
var p = this.node;
while(p){
if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
if(!p.isLast()) {
buf.unshift('<img src="'+this.emptyIcon+'" class="ytree-elbow-line">');
} else {
buf.unshift('<img src="'+this.emptyIcon+'" class="ytree-icon">');
}
}
p = p.parentNode;
}
this.childIndent = buf.join('');
}
return this.childIndent;
},
renderIndent : function(){
if(this.rendered){
var indent = '';
var p = this.node.parentNode;
if(p){
indent = p.ui.getChildIndent();
}
if(this.indentMarkup != indent){ // don't rerender if not required
this.indentNode.innerHTML = indent;
this.indentMarkup = indent;
}
this.updateExpandIcon();
}
}
};
YAHOO.ext.tree.RootTreeNodeUI = function(){
YAHOO.ext.tree.RootTreeNodeUI.superclass.constructor.apply(this, arguments);
};
YAHOO.extendX(YAHOO.ext.tree.RootTreeNodeUI, YAHOO.ext.tree.TreeNodeUI);
YAHOO.ext.tree.RootTreeNodeUI.prototype.render = function(){
if(!this.rendered){
var targetNode = this.node.ownerTree.container.dom;
this.node.expanded = true;
targetNode.innerHTML = '<div class="ytree-root-node"></div>';
this.wrap = this.ctNode = targetNode.firstChild;
}
};
YAHOO.ext.tree.RootTreeNodeUI.prototype.collapse = function(){
};

View File

@@ -0,0 +1,213 @@
YAHOO.namespace('ext.tree');
YAHOO.ext.tree.TreePanel = function(el, config){
YAHOO.ext.tree.TreePanel.superclass.constructor.call(this);
this.el = getEl(el);
this.id = this.el.id;
YAHOO.ext.util.Config.apply(this, config || {}, {
rootVisible : true,
lines : true,
enableDD : false,
hlDrop : true/*,
hlColor: null,
ddGroup : 'TreeDD'
hlBaseColor : 'FFFFFF'*/
});
YAHOO.ext.util.Config.apply(this.events, {
'beforeload' : true,
'load' : true,
'textchange' : true,
'beforeexpand' : true,
'beforecollapse' : true,
'expand' : true,
'collapse' : true,
'disabledchange' : true,
'beforeclick':true,
'click':true,
'dblclick':true,
'contentmenu':true,
'beforechildrenrendered':true,
/**
* @event startdrag
* Fires when a node starts being dragged
* @param {YAHOO.ext.tree.TreePanel} this
* @param {YAHOO.ext.tree.TreeNode} node
* @param {event} e The raw browser event
*/
'startdrag' : true,
/**
* @event enddrag
* Fires when a drag operation is complete
* @param {YAHOO.ext.tree.TreePanel} this
* @param {YAHOO.ext.tree.TreeNode} node
* @param {event} e The raw browser event
*/
'enddrag' : true,
/**
* @event dragdrop
* Fires when a dragged node is dropped on a valid DD target
* @param {YAHOO.ext.tree.TreePanel} this
* @param {YAHOO.ext.tree.TreeNode} node
* @param {DD} dd The dd it was dropped on
* @param {event} e The raw browser event
*/
'dragdrop' : true,
/**
* @event beforenodedrop
* Fires when a DD object is dropped on a node in this tree for preprocessing. This event can cancel.
* @param {Object} dropEvent
*/
'beforenodedrop' : true,
/**
* @event nodedrop
* Fires after a DD object is dropped on a node in this tree
* @param {Object} dropEvent
*/
'nodedrop' : true,
/**
* @event nodedragover
* Fires when a tree node is being target
* @param {Object} dragOverEvent
*/
'nodedragover' : true
});
if(this.singleExpand){
this.on('beforeexpand', this.restrictExpand, this, true);
}
// problem with safari and animation
// I am investigating
if(YAHOO.ext.util.Browser.isSafari){
this.animate = false;
}
};
YAHOO.extendX(YAHOO.ext.tree.TreePanel, YAHOO.ext.data.Tree, {
restrictExpand : function(node){
var p = node.parentNode;
if(p){
if(p.expandedChild && p.expandedChild.parentNode == p){
p.expandedChild.collapse();
}
p.expandedChild = node;
}
},
setRootNode : function(node){
YAHOO.ext.tree.TreePanel.superclass.setRootNode.call(this, node);
if(!this.rootVisible){
node.ui = new YAHOO.ext.tree.RootTreeNodeUI(node);
}
return node;
},
getEl : function(){
return this.el;
},
getLoader : function(){
return this.loader;
},
expandAll : function(){
this.root.expand(true);
},
collapseAll : function(){
this.root.collapse(true);
},
getSelectionModel : function(){
if(!this.selModel){
this.selModel = new YAHOO.ext.tree.DefaultSelectionModel();
}
return this.selModel;
},
expandPath : function(path, attr, callback){
attr = attr || 'id';
var keys = path.split(this.pathSeparator);
var curNode = this.root;
if(curNode.attributes[attr] != keys[1]){ // invalid root
if(callback){
callback(false, null);
}
return;
}
var index = 1;
var f = function(){
if(++index == keys.length){
if(callback){
callback(true, curNode);
}
return;
}
var c = curNode.findChild(attr, keys[index]);
if(!c){
if(callback){
callback(false, curNode);
}
return;
}
curNode = c;
c.expand(false, false, f);
}
curNode.expand(false, false, f);
},
selectPath : function(path, attr, callback){
attr = attr || 'id';
var keys = path.split(this.pathSeparator);
var v = keys.pop();
if(keys.length > 0){
var f = function(success, node){
if(success && node){
var n = node.findChild(attr, v);
if(n){
n.select();
if(callback){
callback(true, n);
}
}
}else{
if(callback){
callback(false, n);
}
}
};
this.expandPath(keys.join(this.pathSeparator), attr, f);
}else{
this.root.select();
if(callback){
callback(true, this.root);
}
}
},
render : function(){
this.container = this.el.createChild({tag:'ul',
cls:'ytree-root-ct ' +
(this.lines ? 'ytree-lines' : 'ytree-no-lines')});
if(this.containerScroll){
YAHOO.ext.dd.ScrollManager.register(this.el);
}
if((this.enableDD || this.enableDrop) && !this.dropZone){
this.dropZone = new YAHOO.ext.tree.TreeDropZone(this, this.dropConfig || {
ddGroup: this.ddGroup || 'TreeDD'
});
}
if((this.enableDD || this.enableDrag) && !this.dragZone){
this.dragZone = new YAHOO.ext.tree.TreeDragZone(this, this.dragConfig || {
ddGroup: this.ddGroup || 'TreeDD',
scroll: this.ddScroll
});
}
this.getSelectionModel().init(this);
this.root.render();
if(!this.rootVisible){
this.root.renderChildren();
}
return this;
}
});

View File

@@ -0,0 +1,195 @@
YAHOO.ext.tree.DefaultSelectionModel = function(){
this.selNode = null;
this.events = {
'selectionchange' : true
};
};
YAHOO.extendX(YAHOO.ext.tree.DefaultSelectionModel, YAHOO.ext.util.Observable, {
init : function(tree){
this.tree = tree;
tree.el.mon('keydown', this.onKeyDown, this, true);
tree.on('click', this.onNodeClick, this, true);
},
onNodeClick : function(node, e){
this.select(node);
},
select : function(node){
if(this.selNode && this.selNode != node){
this.selNode.ui.onSelectedChange(false);
}
this.selNode = node;
node.ui.onSelectedChange(true);
this.fireEvent('selectionchange', this, node);
return node;
},
unselect : function(node){
if(this.selNode == node){
this.clearSelections();
}
},
clearSelections : function(){
var n = this.selNode;
if(n){
n.ui.onSelectedChange(false);
this.selNode = null;
this.fireEvent('selectionchange', this, null);
}
return n;
},
getSelectedNode : function(){
return this.selNode;
},
isSelected : function(node){
return this.selNode == node;
},
onKeyDown : function(e){
var s = this.selNode || this.lastSelNode;
// undesirable, but required
var sm = this;
if(!s){
return;
}
var k = e.getKey();
//alert(k)
switch(k){
case e.DOWN:
e.preventDefault();
if(s.firstChild && s.isExpanded()){
this.select(s.firstChild, e);
}else if(s.nextSibling){
this.select(s.nextSibling, e);
}else if(s.parentNode){
s.parentNode.bubble(function(){
if(this.nextSibling){
sm.select(this.nextSibling, e);
return false;
}
});
}
break;
case e.UP:
e.preventDefault();
var ps = s.previousSibling;
if(ps){
if(!ps.isExpanded()){
this.select(ps, e);
}else{
var lc = ps.lastChild;
while(lc && lc.isExpanded()){
lc = lc.lastChild;
}
this.select(lc, e);
}
}else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
this.select(s.parentNode, e);
}
break;
case e.RIGHT:
e.preventDefault();
if(s.hasChildNodes()){
if(!s.isExpanded()){
s.expand();
}else if(s.firstChild){
this.select(s.firstChild, e);
}
}
break;
case e.LEFT:
e.preventDefault();
if(s.hasChildNodes() && s.isExpanded()){
s.collapse();
}else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
this.select(s.parentNode, e);
}
break;
};
}
});
YAHOO.ext.tree.MultiSelectionModel = function(){
this.selNodes = [];
this.selMap = {};
this.events = {
'selectionchange' : true
};
};
YAHOO.extendX(YAHOO.ext.tree.MultiSelectionModel, YAHOO.ext.util.Observable, {
init : function(tree){
this.tree = tree;
tree.el.mon('keydown', this.onKeyDown, this, true);
tree.on('click', this.onNodeClick, this, true);
},
onNodeClick : function(node, e){
this.select(node, e, e.ctrlKey);
},
select : function(node, e, keepExisting){
if(keepExisting !== true){
this.clearSelections(true);
}
this.selNodes.push(node);
this.selMap[node.id] = node;
this.lastSelNode = node;
node.ui.onSelectedChange(true);
this.fireEvent('selectionchange', this, this.selNodes);
return node;
},
unselect : function(node){
if(this.selMap[node.id]){
node.ui.onSelectedChange(false);
var sn = this.selNodes;
var index = -1;
if(sn.indexOf){
index = sn.indexOf(node);
}else{
for(var i = 0, len = sn.length; i < len; i++){
if(sn[i] == node){
index = i;
break;
}
}
}
if(index != -1){
this.selNodes.splice(index, 1);
}
delete this.selMap[node.id];
this.fireEvent('selectionchange', this, this.selNodes);
}
},
clearSelections : function(suppressEvent){
var sn = this.selNodes;
if(sn.length > 0){
for(var i = 0, len = sn.length; i < len; i++){
sn[i].ui.onSelectedChange(false);
}
this.selNodes = [];
this.selMap = {};
if(suppressEvent !== true){
this.fireEvent('selectionchange', this, this.selNodes);
}
}
},
isSelected : function(node){
return this.selMap[node.id] ? true : false;
},
getSelectedNodes : function(){
return this.selNodes;
},
onKeyDown : YAHOO.ext.tree.DefaultSelectionModel.prototype.onKeyDown
});

View File

@@ -0,0 +1,49 @@
YAHOO.ext.tree.TreeSorter = function(tree, config){
YAHOO.ext.util.Config.apply(this, config);
tree.on('beforechildrenrendered', this.doSort, this, true);
tree.on('append', this.updateSort, this, true);
tree.on('insert', this.updateSort, this, true);
var dsc = this.dir && this.dir.toLowerCase() == 'desc';
var p = this.property || 'text';
var sortType = this.sortType;
var fs = this.folderSort;
var cs = this.caseSensitive === true;
this.sortFn = function(n1, n2){
if(fs){
if(n1.leaf && !n2.leaf){
return 1;
}
if(!n1.leaf && n2.leaf){
return -1;
}
}
var v1 = sortType ? sortType(n1) : (cs ? n1[p] : n1[p].toUpperCase());
var v2 = sortType ? sortType(n2) : (cs ? n2[p] : n2[p].toUpperCase());
if(v1 < v2){
return dsc ? +1 : -1;
}else if(v1 > v2){
return dsc ? -1 : +1;
}else{
return 0;
}
};
};
YAHOO.ext.tree.TreeSorter.prototype = {
doSort : function(node){
node.sort(this.sortFn);
},
compareNodes : function(n1, n2){
return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
},
updateSort : function(tree, node){
if(node.childrenRendered){
this.doSort.defer(1, this, [node]);
}
}
};