123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /**
- * Retrieve an array of ids of checked nodes
- * @return {Array} array of ids of checked nodes
- */
- Ext.tree.TreePanel.prototype.getChecked = function(node){
- var checked = [], i;
- if( typeof node == 'undefined' ) {
- //node = this.rootVisible ? this.getRootNode() : this.getRootNode().firstChild;
- node = this.getRootNode();
- }
- if( node.attributes.checked ) {
- checked.push(node.id);
- }
- if( node.childNodes.length ) {
- for( i = 0; i < node.childNodes.length; i++ ) {
- checked = checked.concat( this.getChecked(node.childNodes[i]) );
- }
- }
- return checked;
- };
- /**
- * @class Ext.tree.CustomUITreeLoader
- * @extends Ext.tree.TreeLoader
- * Overrides createNode to force uiProvider to be an arbitrary TreeNodeUI to save bandwidth
- */
- Ext.tree.CustomUITreeLoader = function() {
- Ext.tree.CustomUITreeLoader.superclass.constructor.apply(this, arguments);
- };
- Ext.extend(Ext.tree.CustomUITreeLoader, Ext.tree.TreeLoader, {
- createNode : function(attr){
- Ext.apply(attr, this.baseAttr || {});
- if(this.applyLoader !== false){
- attr.loader = this;
- }
- if(typeof attr.uiProvider == 'string'){
- attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
- }
- return(attr.leaf ?
- new Ext.tree.TreeNode(attr) :
- new Ext.tree.AsyncTreeNode(attr));
- }
- });
- /**
- * @class Ext.tree.CheckboxNodeUI
- * @extends Ext.tree.TreeNodeUI
- * Adds a checkbox to all nodes
- */
- Ext.tree.CheckboxNodeUI = function() {
- Ext.tree.CheckboxNodeUI.superclass.constructor.apply(this, arguments);
- };
- Ext.extend(Ext.tree.CheckboxNodeUI, Ext.tree.TreeNodeUI, {
- /**
- * This is virtually identical to Ext.tree.TreeNodeUI.render, modifications are indicated inline
- */
- render : function(bulkRender){
- var n = this.node;
- var targetNode = n.parentNode ?
- n.parentNode.ui.getContainer() : n.ownerTree.container.dom; /* in later svn builds this changes to n.ownerTree.innerCt.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();
- }
- // modification: added checkbox
- var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', n.attributes.cls,'">',
- '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
- '<img src="', this.emptyIcon, '" class="x-tree-ec-icon">',
- '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
- '<input class="l-tcb" '+ (n.disabled ? 'disabled="disabled" ' : '') +' type="checkbox" ', (a.checked ? "checked>" : '>'),
- '<a hidefocus="on" href="',a.href ? a.href : "#",'" ',
- a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
- '<span unselectable="on">',n.text,"</span></a></div>",
- '<ul class="x-tree-node-ct" style="display:none;"></ul>',
- "</li>"];
- if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
- this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
- n.nextSibling.ui.getEl(), buf.join(""));
- }else{
- this.wrap = 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.checkbox = cs[3]; // modification: inserted checkbox
- this.anchor = cs[4];
- this.textNode = cs[4].firstChild;
- if(a.qtip){
- if(this.textNode.setAttributeNS){
- this.textNode.setAttributeNS("ext", "qtip", a.qtip);
- if(a.qtipTitle){
- this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
- }
- }else{
- this.textNode.setAttribute("ext:qtip", a.qtip);
- if(a.qtipTitle){
- this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
- }
- }
- } else if(a.qtipCfg) {
- a.qtipCfg.target = Ext.id(this.textNode);
- Ext.QuickTips.register(a.qtipCfg);
- }
- this.initEvents();
- // modification: Add additional handlers here to avoid modifying Ext.tree.TreeNodeUI
- Ext.fly(this.checkbox).on('click', this.check.createDelegate(this, [null]));
- n.on('dblclick', function(e) {
- if( this.isLeaf() ) {
- this.getUI().toggleCheck();
- }
- });
- if(!this.node.expanded){
- this.updateExpandIcon();
- }
- }else{
- if(bulkRender === true) {
- targetNode.appendChild(this.wrap);
- }
- }
- },
- checked : function() {
- return this.checkbox.checked;
- },
- /**
- * Sets a checkbox appropriately. By default only walks down through child nodes
- * if called with no arguments (onchange event from the checkbox), otherwise
- * it's assumed the call is being made programatically and the correct arguments are provided.
- * @param {Boolean} state true to check the checkbox, false to clear it. (defaults to the opposite of the checkbox.checked)
- * @param {Boolean} descend true to walk through the nodes children and set their checkbox values. (defaults to false)
- */
- check : function(state, descend, bulk) {
- if (this.node.disabled) {
- return;
- }
- var n = this.node;
- var tree = n.getOwnerTree();
- var parentNode = n.parentNode;n
- if( !n.expanded && !n.childrenRendered ) {
- n.expand(false, false, this.check.createDelegate(this, arguments));
- }
- if( typeof bulk == 'undefined' ) {
- bulk = false;
- }
- if( typeof state == 'undefined' || state === null ) {
- state = this.checkbox.checked;
- descend = !state;
- if( state ) {
- n.expand(false, false);
- }
- } else {
- this.checkbox.checked = state;
- }
- n.attributes.checked = state;
- // do we have parents?
- if( parentNode !== null && state ) {
- // if we're checking the box, check it all the way up
- if( parentNode.getUI().check ) {
- //parentNode.getUI().check(state, false, true);
- }
- }
- if( descend && !n.isLeaf() ) {
- var cs = n.childNodes;
- for(var i = 0; i < cs.length; i++) {
- //cs[i].getUI().check(state, true, true);
- }
- }
- if( !bulk ) {
- tree.fireEvent('check', n, state);
- }
- },
- toggleCheck : function(state) {
- this.check(!this.checkbox.checked, true);
- }
- });
- /**
- * @class Ext.tree.CheckNodeMultiSelectionModel
- * @extends Ext.tree.MultiSelectionModel
- * Multi selection for a TreePanel containing Ext.tree.CheckboxNodeUI.
- * Adds enhanced selection routines for selecting multiple items
- * and key processing to check/clear checkboxes.
- */
- Ext.tree.CheckNodeMultiSelectionModel = function(){
- Ext.tree.CheckNodeMultiSelectionModel.superclass.constructor.call(this);
- };
- Ext.extend(Ext.tree.CheckNodeMultiSelectionModel, Ext.tree.MultiSelectionModel, {
- init : function(tree){
- this.tree = tree;
- tree.el.on("keydown", this.onKeyDown, this);
- tree.on("click", this.onNodeClick, this);
- },
- /**
- * Handle a node click
- * If ctrl key is down and node is selected will unselect the node.
- * If the shift key is down it will create a contiguous selection
- * (see {@link Ext.tree.CheckNodeMultiSelectionModel#extendSelection} for the limitations)
- */
- onNodeClick : function(node, e){
- if (node.disabled) {
- return;
- }
- if( e.shiftKey && this.extendSelection(node) ) {
- return true;
- }
- if( e.ctrlKey && this.isSelected(node) ) {
- this.unselect(node);
- } else {
- this.select(node, e, e.ctrlKey);
- }
- },
- /**
- * Selects all nodes between the previously selected node and the one that the user has just selected.
- * Will not span multiple depths, so only children of the same parent will be selected.
- */
- extendSelection : function(node) {
- var last = this.lastSelNode;
- if( node == last || !last ) {
- return false; /* same selection, process normally normally */
- }
- if( node.parentNode == last.parentNode ) {
- var cs = node.parentNode.childNodes;
- var i = 0, attr='id', selecting=false, lastSelect=false;
- this.clearSelections(true);
- for( i = 0; i < cs.length; i++ ) {
- // We have to traverse the entire tree b/c don't know of a way to find
- // a numerical representation of a nodes position in a tree.
- if( cs[i].attributes[attr] == last.attributes[attr] || cs[i].attributes[attr] == node.attributes[attr] ) {
- // lastSelect ensures that we select the final node in the list
- lastSelect = selecting;
- selecting = !selecting;
- }
- if( selecting || lastSelect ) {
- this.select(cs[i], null, true);
- // if we're selecting the last node break to avoid traversing the entire tree
- if( lastSelect ) {
- break;
- }
- }
- }
- return true;
- } else {
- return false;
- }
- },
- /**
- * Traps the press of the SPACE bar and sets the check state of selected nodes to the opposite state of
- * the selected or last selected node. Assume you have the following five Ext.tree.CheckboxNodeUIs:
- * [X] One, [X] Two, [X] Three, [ ] Four, [ ] Five
- * If you select them in this order: One, Two, Three, Four, Five and press the space bar they all
- * will be <b>checked</b> (the opposite of the checkbox state of Five).
- * If you select them in this order: Five, Four, Three, Two, One and press the space bar they all
- * will be <b>unchecked</b> which is the opposite of the checkbox state of One.
- */
- onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown.createInterceptor(function(e) {
- var s = this.selNode || this.lastSelNode;
- // undesirable, but required
- var sm = this;
- if(!s){
- return;
- }
- var k = e.getKey();
- switch(k){
- case e.SPACE:
- e.stopEvent();
- var sel = this.getSelectedNodes();
- var state = !s.getUI().checked();
- if( sel.length == 1 ) {
- s.getUI().check(state, !s.isLeaf());
- } else {
- for( var i = 0; i < sel.length; i++ ) {
- sel[i].getUI().check(state, !sel[i].isLeaf() );
- }
- }
- break;
- }
- return true;
- })
- });
|