Changeset 10580

Show
Ignore:
Timestamp:
09/20/07 22:56:56 (14 months ago)
Author:
bill
Message:

Refactor tree to have a special node (without a corresponding item) at the top of
the tree, so that (for example) the continents/countries tree in test_Tree.html can
have a top node marked "Continents" even though there is no such item in the
data store.

This change requires handlers like onClick() to not fail when item==null, but
rather to assume that's the root node.

Fixes #4527, #4419, #4457.

Files:
13 modified

Legend:

Unmodified
Added
Removed
  • dijit/trunk/demos/i18n.html

    r10465 r10580  
    6868                <tr> 
    6969                        <td width="30%" style="vertical-align: top;"> 
    70                                 <div dojoType="dijit.Tree" id="mytree" store="store"> 
     70                                <div dojoType="dijit.Tree" id="mytree" store="store" label="Continents"> 
    7171                                        <!-- Override all the data access functions to work from the I18N data store --> 
    7272                                        <script type="dojo/method" event="getItemChildren" args="item, onComplete"> 
     
    9191                                        <script type="dojo/method" event="getIconClass" args="item"> 
    9292                                                var icon = 
    93                                                         (store.getValue(item, "type") == "country") ? 
     93                                                        (item && store.getValue(item, "type") == "country") ? 
    9494                                                        ("countryIcon country" + store.getValue(item, "iso") + "Icon") : 
    9595                                                        null; 
  • dijit/trunk/demos/mail.html

    r10564 r10580  
    310310                                        <div dojoType="dijit.layout.AccordionPane" title="Folders"> 
    311311                                                <div dojoType="dijit.Tree" id="mytree" store="mailStore" 
    312                                                         labelAttr="label" childrenAttr="folders" query="{type:'folder'}"> 
     312                                                        labelAttr="label" childrenAttr="folders" query="{type:'folder'}" label="Folders"> 
    313313                                                        <script type="dojo/method" event="onClick" args="item"> 
     314                                                                if(!item){ 
     315                                                                        return; // top level node in tree doesn't correspond to any item 
     316                                                                } 
    314317                                                                /* filter the message list to messages in this folder */ 
    315318                                                                table.query.query = { 
     
    320323                                                        </script> 
    321324                                                        <script type="dojo/method" event="getIconClass" args="item"> 
    322                                                                 var specifiedIcon = mailStore.getValue(item, "icon"); 
    323                                                                 return specifiedIcon || "mailIconFolderDocuments"; 
     325                                                                return (item && mailStore.getValue(item, "icon")) || "mailIconFolderDocuments"; 
    324326                                                        </script> 
    325327                                                </div> 
    326328                                        </div> 
    327329                                        <div dojoType="dijit.layout.AccordionPane" title="Address Book"> 
    328  
    329                                                 <!-- 
    330                                                         TODO: want to use a table here but somehow can't have two table instances on the same page. 
    331                                                         Debug later 
    332                                                         <span dojoType="demo.Table" store="mailStore" 
    333                                                                 query="{ query: { type: 'address' }, columns: [ {name: 'User name', attribute: 'label'} ], sort: [ { attribute: 'label' } ]  }" 
    334                                                                 id="addresses" style="width: 100%"> 
    335                                                                 <script type="dojo/method" event="preamble"> 
    336                                                                         this.query = { type: "address" }; 
    337                                                                         this.columns = [ 
    338                                                                                 { 
    339                                                                                         name: "Name", 
    340                                                                                         attribute: "label" 
    341                                                                                 } 
    342                                                                         ]; 
    343                                                                 </script> 
    344                                                                 <script type="dojo/method" event="onClick" args="item"> 
    345                                                                         table.query.query.sender = mailStore.getValue(item, "sender"); 
    346                                                                         delete table.query.query.folder; 
    347                                                                         table.runQuery(); 
    348                                                                 </script> 
    349                                                         </span> 
    350                                                 --> 
    351                                                 <div dojoType="dijit.Tree" id="addrTree" store="mailStore" 
    352                                                         labelAttr="label" childrenAttr="folders" query="{type:'address'}"> 
     330                                                <span dojoType="demo.Table" store="mailStore" 
     331                                                        query="{ query: { type: 'address' }, columns: [ {name: 'User name', attribute: 'label'} ], sort: [ { attribute: 'label' } ]  }" 
     332                                                        id="addresses" style="width: 100%"> 
     333                                                        <script type="dojo/method" event="preamble"> 
     334                                                                this.query = { type: "address" }; 
     335                                                                this.columns = [ 
     336                                                                        { 
     337                                                                                name: "Name", 
     338                                                                                attribute: "label" 
     339                                                                        } 
     340                                                                ]; 
     341                                                        </script> 
    353342                                                        <script type="dojo/method" event="onClick" args="item"> 
    354                                                                 /* filter the message list to messages from this user */ 
    355                                                                 table.query.query = { 
    356                                                                         type: "message", 
    357                                                                         sender: mailStore.getValue(item, "label") 
    358                                                                 }; 
     343                                                                table.query.query.sender = mailStore.getValue(item, "sender"); 
     344                                                                delete table.query.query.folder; 
    359345                                                                table.runQuery(); 
    360346                                                        </script> 
    361                                                         <script type="dojo/method" event="getIconClass" args="item"> 
    362                                                                 var specifiedIcon = mailStore.getValue(item, "icon"); 
    363                                                                 return specifiedIcon || "mailIconFolderDocuments"; 
    364                                                         </script> 
    365                                                 </div> 
     347                                                </span> 
    366348                                        </div> 
    367349                                </div>  <!-- end of Accordion --> 
  • dijit/trunk/demos/mail/mail.json

    r10319 r10580  
    55 
    66                // Hierarchy of folders 
    7                 { type: 'folder', id: 'mailbox', label:'Folders', folders: [ 
    8                         { type: 'folder', id: 'inbox', label:'Inbox', icon:'mailIconFolderInbox' }, 
    9                         { type: 'folder', id: 'deleted', label:'Trash', icon:'mailIconTrashcanFull' }, 
    10                         { type: 'folder', id: 'save', label:'Save',  folders:[ 
    11                                 { id: 'work', label:'stuff for work'}, 
    12                                 { id: 'fun', label:'stuff for fun'} 
    13                         ]} 
     7                { type: 'folder', id: 'inbox', label:'Inbox', icon:'mailIconFolderInbox' }, 
     8                { type: 'folder', id: 'deleted', label:'Trash', icon:'mailIconTrashcanFull' }, 
     9                { type: 'folder', id: 'save', label:'Save',  folders:[ 
     10                        { id: 'work', label:'stuff for work'}, 
     11                        { id: 'fun', label:'stuff for fun'} 
    1412                ]}, 
    1513 
  • dijit/trunk/tests/test_Tree.html

    r10506 r10580  
    3232 
    3333        <div dojoType="dijit.Tree" id="mytree" store="continentStore" query="{type:'continent'}" 
    34                 labelAttr="name"> 
     34                labelAttr="name" label="Continents"> 
    3535                <script type="dojo/method" event="onClick" args="item"> 
    3636                        alert("Execute of node " + continentStore.getLabel(item) 
     
    8080 
    8181        <div dojoType="dijit.Tree" id="tree2" store="continentStore" query="{type:'continent'}" 
    82                 labelAttr="name"> 
     82                labelAttr="name" label="Continents"> 
    8383                <script type="dojo/connect"> 
    8484                        var menu = dijit.byId("tree_menu"); 
  • dijit/trunk/tests/test_Tree_Notification_API_Support.html

    r10409 r10580  
    2222                dojo.require("dojo.parser");    // scan page for widgets and instantiate them 
    2323 
    24                 function deleteNode(){ 
     24                function deleteItem(){ 
    2525                        var store = dijit.byId("myTree").store; 
    26                         store.deleteItem(selectedNode); 
     26                        store.deleteItem(selectedItem); 
    2727                        resetForms(); 
    2828                } 
    2929 
    30                 function addNodeToStore(){ 
     30                function addItem(){ 
    3131                        var store = dijit.byId("myTree").store; 
    32                         if(selectedNode!=null){ 
    33                                 var pInfo = {parent: selectedNode, attribute:"children"}; 
    34                                 store.newItem({id: dojo.byId('newId').value,name:dojo.byId("label").value,someProperty:dojo.byId("someProperty")},pInfo); 
    35                         }else{ 
    36                                 store.newItem({id: dojo.byId('newId').value,name:dojo.byId("label").value,someProperty:dojo.byId("someProperty")}); 
    37                         } 
     32                        var pInfo = selectedItem ? {parent: selectedItem, attribute:"children"} : null; 
     33                        console.debug(pInfo); 
     34                        store.newItem({id: dojo.byId('newId').value,name:dojo.byId("label").value,someProperty:dojo.byId("someProperty")},pInfo); 
    3835                        resetForms(); 
    3936                } 
     
    4138                function resetForms() { 
    4239                        dojo.byId('selected').innerHTML="Tree Root" 
    43                         selectedNode=null; 
     40                        selectedItem=null; 
    4441                        dojo.byId("uLabel").value = ""; 
    4542                        dojo.byId("uSomeProperty").value = ""; 
     
    5047                        var store = dijit.byId("myTree").store; 
    5148 
    52                         if (selectedNode!=null){ 
    53                                 if (dojo.byId("uLabel").value != store.getValue(selectedNode, "name")){ 
    54                                         store.setValue(selectedNode, "name", dojo.byId("uLabel").value); 
     49                        if (selectedItem!=null){ 
     50                                if (dojo.byId("uLabel").value != store.getValue(selectedItem, "name")){ 
     51                                        store.setValue(selectedItem, "name", dojo.byId("uLabel").value); 
    5552                                } 
    5653 
    57                                 if (dojo.byId("uSomeProperty").value != store.getValue(selectedNode, "someProperty")){ 
    58                                         store.setValue(selectedNode, "someProperty", dojo.byId("uSomeProperty").value); 
     54                                if (dojo.byId("uSomeProperty").value != store.getValue(selectedItem, "someProperty")){ 
     55                                        store.setValue(selectedItem, "someProperty", dojo.byId("uSomeProperty").value); 
    5956                                } 
    6057 
    6158                        }else{ 
    62                                 console.error("Cant update the tree root"); 
     59                                console.error("Can't update the tree root"); 
    6360                        } 
    6461                } 
     
    6663                dojo.addOnLoad(function(){ 
    6764                        resetForms(); 
    68                         dojo.subscribe("myTree", null, function(message){ 
    69                                 if(message.event=="execute"){ 
    70                                         selectedNode = message.item; 
    71                                         dojo.byId('selected').innerHTML=treeTestStore.getLabel(message.item); 
    72                                         dojo.byId('uLabel').value = treeTestStore.getLabel(message.item); 
    73                                         dojo.byId('uSomeProperty').value = treeTestStore.getValue(message.item,"someProperty"); 
    74                                 } 
    75                         }); 
    7665                }); 
    7766 
     67                function onClick(item){ 
     68                        selectedItem = item; 
     69                        dojo.byId('selected').innerHTML= item ? treeTestStore.getLabel(item) : ""; 
     70                        dojo.byId('uLabel').value = item ? treeTestStore.getLabel(item) : ""; 
     71                        dojo.byId('uSomeProperty').value = item ? treeTestStore.getValue(item,"someProperty") : ""; 
     72                } 
    7873        </script> 
    7974 
     
    8681                url="../tests/treeTest.json"></div> 
    8782 
    88         <div dojoType="dijit.Tree" id="myTree" store="treeTestStore" labelAttr="name" somePropertyAttr="someProperty"></div> 
     83        <div dojoType="dijit.Tree" id="myTree" label="root" store="treeTestStore" onClick="onClick" labelAttr="name" somePropertyAttr="someProperty"></div> 
    8984 
    9085        <br /> 
     
    10297        Description: <input id="someProperty" width="50" value="Enter Some Property Value" /><br /><br /> 
    10398 
    104         <div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="addNodeToStore();">Add Item to Store</div> 
     99        <div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="addItem();">Add Item to Store</div> 
    105100        <br /> 
    106         <button dojoType="dijit.form.Button" iconClass="noteIcon" onClick="deleteNode()">Delete Node (and children)</button> 
     101        <button dojoType="dijit.form.Button" iconClass="noteIcon" onClick="deleteItem()">Delete Node (and children)</button> 
    107102 
    108103 
  • dijit/trunk/tests/tree/test_Tree_DnD.html

    r10488 r10580  
    1111                @import "../css/dijitTests.css"; 
    1212                @import "../dndDefault.css";  
    13  
    14                 @import "../../../dojo/resources/dojo.css"; 
    15                 @import "../../../dojo/resources/dnd.css"; 
    16                 @import "../../../dojo/tests/dnd/dndDefault.css"; 
    17  
    18  
    19  
    20  
     13                @import "../../../dojo/resources/dojo.css"; 
     14                @import "../../../dojo/resources/dnd.css"; 
     15                @import "../../../dojo/tests/dnd/dndDefault.css"; 
    2116        </style> 
    2217 
     
    4035 
    4136                globalId=1000; 
     37                lastSelected=null; 
    4238 
    4339                dojo.addOnLoad(function(){ 
     
    6460                                        parent: lastSelected,            
    6561                                        attribute: "children"    
    66                                 } 
     62                                }; 
    6763 
    6864                                //store.newItem({name: dojo.byId('newCat').value, id:globalId++, numberOfItems:dojo.byId('numItems').value}, pInfo); 
     
    118114                function tree2CheckItemAcceptance(node,source) { 
    119115                        var item = this.tree._domElement2TreeNode(node).item; 
    120                         if (this.tree.store.hasAttribute(item,"numberOfItems")){ 
     116                        if (item && this.tree.store.hasAttribute(item,"numberOfItems")){ 
    121117                                var numItems=this.tree.store.getValues(item, "numberOfItems"); 
    122118                                return true; 
     
    145141 
    146142                function getIcon(item) { 
    147                         if (catStore.hasAttribute(item, "numberOfItems")) { 
     143                        if (!item || catStore.hasAttribute(item, "numberOfItems")) { 
    148144                                console.log("returning folder class"); 
    149145                                return "myFolder"; 
     
    152148                        return "myItem" 
    153149                } 
    154  
    155150        </script> 
    156151 
     
    178173        <div dojoType="dojo.data.ItemFileWriteStore" jsId="catStore" 
    179174                url="categories.json"></div> 
    180  
    181  
    182  
    183175 
    184176        <table width="100%" style="margin:5px solid gray" > 
     
    218210                        <h2>Collection Count Summary</h2> 
    219211                        <p>You can't drop items onto this tree.</p> 
    220                         <div class="container" dojoType="dijit.Tree" id="myTree" store="catStore" labelAttr="name" getLabel="tree1CustomLabel"  childrenAttr="children" dndController="dijit._tree.dndSource" checkAcceptance="dndAccept" getIconClass="getIcon"></div> 
     212                        <div class="container" dojoType="dijit.Tree" id="myTree" store="catStore" label="Collections" 
     213                                labelAttr="name" getLabel="tree1CustomLabel"  childrenAttr="children" dndController="dijit._tree.dndSource" 
     214                                checkAcceptance="dndAccept" getIconClass="getIcon"></div> 
    221215                </td> 
    222216                <td> 
    223217                        <h2>Collection</h2> 
    224218                        <p>Drop items onto this tree, but only on categories, should fail to let you drop on other items.</p> 
    225                         <div class="container" dojoType="dijit.Tree" id="myTree2" store="catStore"  labelAttr="name"  childrenAttr="children, items" dndController="dijit._tree.dndSource" onDndDrop="tree2CustomDrop" checkAcceptance="dndAccept" checkItemAcceptance="tree2CheckItemAcceptance" getIconClass="getIcon"></div>  
     219                        <div class="container" dojoType="dijit.Tree" id="myTree2" label="Collections" store="catStore"  labelAttr="name"  childrenAttr="children, items" dndController="dijit._tree.dndSource" onDndDrop="tree2CustomDrop" checkAcceptance="dndAccept" checkItemAcceptance="tree2CheckItemAcceptance" getIconClass="getIcon"></div>  
    226220                </td> 
    227221        </tr> 
    228222        </table> 
    229223 
    230  
    231224        </body> 
    232225</html> 
  • dijit/trunk/themes/themeTester.html

    r10495 r10580  
    292292                                        <!-- tree widget --> 
    293293                                        <div dojoType="dijit.Tree" store="continentStore" query="{type:'continent'}" 
    294                                                 labelAttr="name" typeAttr="type"> 
     294                                                labelAttr="name" typeAttr="type" label="Continents"> 
    295295                                        </div> 
    296296                                </div> 
  • dijit/trunk/themes/tundra/tundra.css

    r10509 r10580  
    891891    zoom: 1;    /* MOW: what the heck is this doing in here? */ 
    892892} 
    893 .tundra .dijitTreeIsRoot { 
    894     margin-left: 0; 
    895 } 
    896893  
    897894/* left vertical line (grid) for all nodes */ 
    898895.tundra .dijitTreeIsLast { 
    899896    background: url('images/i_half.gif') no-repeat; 
     897} 
     898 
     899.tundra .dijitTreeIsRoot { 
     900    margin-left: 0; 
     901    background: none; 
    900902} 
    901903 
  • dijit/trunk/Tree.js

    r10569 r10580  
    88 
    99dojo.declare( 
    10         "dijit._TreeBase", 
     10        "dijit._TreeNode", 
    1111        [dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained], 
    1212{ 
    13         // summary: 
    14         //      Base class for Tree and _TreeNode 
     13        // summary 
     14        //              Single node within a tree 
     15 
     16        // item: dojo.data.Item 
     17        //              the dojo.data entry this tree represents 
     18        item: null,      
     19 
     20        isTreeNode: true, 
     21 
     22        // label: String 
     23        //              Text of this tree node 
     24        label: "", 
     25 
     26        isExpandable: null, // show expando node 
     27         
     28        isExpanded: false, 
    1529 
    1630        // state: String 
     
    1933        //              then after dojo.data query it becomes "LOADING" and, finally "LOADED"    
    2034        state: "UNCHECKED", 
    21         locked: false, 
    22         startExpanded: true, 
    23  
    24         lock: function(){ 
    25                 // summary: lock this node (and it's descendants) while a delete is taking place? 
    26                 this.locked = true; 
    27         }, 
    28         unlock: function(){ 
    29                 if(!this.locked){ 
    30                         //dojo.debug((new Error()).stack); 
    31                         throw new Error(this.declaredClass+" unlock: not locked"); 
    32                 } 
    33                 this.locked = false; 
    34         }, 
    35  
    36         isLocked: function(){ 
    37                 // summary: can this node be modified? 
    38                 // returns: false if this node or any of it's ancestors are locked 
    39                 var node = this; 
    40                 while(true){ 
    41                         if(node.lockLevel){ 
    42                                 return true; 
    43                         } 
    44                         if(!node.getParent() || node.isTree){ 
    45                                 break; 
    46                         }        
    47                         node = node.getParent();         
    48                 } 
    49                 return false; 
    50         }, 
    51  
     35 
     36        templatePath: dojo.moduleUrl("dijit", "_tree/Node.html"),                
     37 
     38        postCreate: function(){ 
     39                // set label, escaping special characters 
     40                this.setLabelNode(this.label); 
     41 
     42                // set expand icon for leaf      
     43                this._setExpando(); 
     44 
     45                // set icon based on item 
     46                dojo.addClass(this.iconNode, this.tree.getIconClass(this.item)); 
     47 
     48                if(this.isExpandable){ 
     49                        dijit.wai.setAttr(this.labelNode, "waiState", "expanded", this.isExpanded); 
     50                } 
     51        }, 
     52 
     53        markProcessing: function(){ 
     54                // summary: visually denote that tree is loading data, etc. 
     55                this.state = "LOADING"; 
     56                this._setExpando(true);  
     57        }, 
     58 
     59        unmarkProcessing: function(){ 
     60                // summary: clear markup from markProcessing() call 
     61                this._setExpando(false);         
     62        }, 
     63 
     64        _updateLayout: function(){ 
     65                // summary: set appropriate CSS classes for this.domNode 
     66                dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling()); 
     67        }, 
     68 
     69        _setExpando: function(/*Boolean*/ processing){ 
     70                // summary: set the right image for the expando node 
     71 
     72                // apply the appropriate class to the expando node 
     73                var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened", 
     74                        "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"]; 
     75                var idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3); 
     76                dojo.forEach(styles, 
     77                        function(s){ 
     78                                dojo.removeClass(this.expandoNode, s); 
     79                        }, this 
     80                ); 
     81                dojo.addClass(this.expandoNode, styles[idx]); 
     82 
     83                // provide a non-image based indicator for images-off mode 
     84                this.expandoNodeText.innerHTML = 
     85                        processing ? "*" : 
     86                                (this.isExpandable ? 
     87                                        (this.isExpanded ? "-" : "+") : "*"); 
     88        },       
     89 
     90        expand: function(){ 
     91                // summary: show my children 
     92                if(this.isExpanded){ return; } 
     93                // cancel in progress collapse operation 
     94                if(this._wipeOut.status() == "playing"){ 
     95            &nb