2150 |
mathias |
1 |
if(!dojo._hasResource["dojox.widget.SortList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojox.widget.SortList"] = true;
|
|
|
3 |
dojo.provide("dojox.widget.SortList");
|
|
|
4 |
dojo.experimental("dojox.widget.SortList"); // level: prototype, designed for dijit.chat.demo
|
|
|
5 |
|
|
|
6 |
dojo.require("dijit.layout._LayoutWidget");
|
|
|
7 |
dojo.require("dijit._Templated");
|
|
|
8 |
|
|
|
9 |
dojo.declare("dojox.widget.SortList",
|
|
|
10 |
[dijit.layout._LayoutWidget, dijit._Templated],
|
|
|
11 |
{
|
|
|
12 |
// summary: a sortable <ul> with a fixed header for use in dijit.demos.chat
|
|
|
13 |
// for demonstration purposes only for now. feel free to make API suggestions
|
|
|
14 |
// or fixes.
|
|
|
15 |
//
|
|
|
16 |
// title: String
|
|
|
17 |
// the title in the header
|
|
|
18 |
title: "",
|
|
|
19 |
|
|
|
20 |
// heading: String
|
|
|
21 |
// in the event a parent container is expecting a title="" attribute, set it for the parent
|
|
|
22 |
// via title, and the title of this widget via heading="" ... assuming you want different
|
|
|
23 |
// titles for each. eg: TabContainer, AccordionContainer, etc.
|
|
|
24 |
heading: "",
|
|
|
25 |
|
|
|
26 |
// descending: Boolean
|
|
|
27 |
// toggle sort order based on this value.
|
|
|
28 |
descending: true,
|
|
|
29 |
|
|
|
30 |
// selected: Array
|
|
|
31 |
// a list of the selected <li> nodes at any given time.
|
|
|
32 |
selected: null,
|
|
|
33 |
|
|
|
34 |
|
|
|
35 |
// sortable: Boolean
|
|
|
36 |
// toggle to enable/disable sorting
|
|
|
37 |
sortable: true,
|
|
|
38 |
|
|
|
39 |
// FIXME: this is really simple store support
|
|
|
40 |
store: "",
|
|
|
41 |
key: "name",
|
|
|
42 |
|
|
|
43 |
templateString:"<div class=\"sortList\" id=\"${id}\">\n\t\t<div class=\"sortListTitle\" dojoAttachPoint=\"titleNode\">\n\t\t<div class=\"sortListIcon\"></div>\n\t\t<span dojoAttachPoint=\"focusNode\">${title}</span>\n\t\t</div>\n\t\t<div class=\"sortListBodyWrapper\" dojoAttachEvent=\"onmouseover: _set, onmouseout: _unset, onclick:_handleClick\" dojoAttachPoint=\"bodyWrapper\">\n\t\t<ul dojoAttachPoint=\"containerNode\" class=\"sortListBody\"></ul>\n\t</div>\n</div>\n",
|
|
|
44 |
|
|
|
45 |
_addItem: function(item){
|
|
|
46 |
var node = document.createElement("li");
|
|
|
47 |
var text = this.store.getValue(item,this.key);
|
|
|
48 |
node.innerHTML = text;
|
|
|
49 |
this.containerNode.appendChild(node);
|
|
|
50 |
},
|
|
|
51 |
|
|
|
52 |
postCreate: function(){
|
|
|
53 |
if (this.store){
|
|
|
54 |
// FIXME: is this right?
|
|
|
55 |
this.store = eval(this.store);
|
|
|
56 |
var props = {
|
|
|
57 |
onItem: dojo.hitch(this,"_addItem"),
|
|
|
58 |
onComplete: dojo.hitch(this,"onSort")
|
|
|
59 |
};
|
|
|
60 |
this.store.fetch(props);
|
|
|
61 |
}else{ this.onSort(); }
|
|
|
62 |
this.inherited("postCreate",arguments);
|
|
|
63 |
},
|
|
|
64 |
|
|
|
65 |
startup: function(){
|
|
|
66 |
this.inherited("startup",arguments);
|
|
|
67 |
if(this.heading){
|
|
|
68 |
this.setTitle(this.heading); this.title=this.heading;
|
|
|
69 |
}
|
|
|
70 |
// we cheat, and give the browser just enough time so we know our height
|
|
|
71 |
setTimeout(dojo.hitch(this,"resize"),5);
|
|
|
72 |
if (this.sortable){ this.connect(this.titleNode,"onclick", "onSort"); }
|
|
|
73 |
},
|
|
|
74 |
|
|
|
75 |
resize: function(){
|
|
|
76 |
// summary: do our additional calculations when resize() is called by or in a parent
|
|
|
77 |
this.inherited("resize",arguments);
|
|
|
78 |
// FIXME:
|
|
|
79 |
// the 10 comes from the difference between the contentBox and calculated height
|
|
|
80 |
// because of badding and border extents. this shouldn't be done this way, a theme change will
|
|
|
81 |
// break it: but we also don't want to run getComputedStyle or dojo.coords() every time resize()
|
|
|
82 |
// is fired.
|
|
|
83 |
var offset = ((this._contentBox.h) - (dojo.style(this.titleNode,"height")))-10;
|
|
|
84 |
this.bodyWrapper.style.height = Math.abs(offset) + "px";
|
|
|
85 |
},
|
|
|
86 |
|
|
|
87 |
onSort: function(/* Event */e){
|
|
|
88 |
// summary: sort the data, and style the nodes.
|
|
|
89 |
|
|
|
90 |
var arr = dojo.query("li",this.domNode);
|
|
|
91 |
if (this.sortable){
|
|
|
92 |
this.descending = !this.descending;
|
|
|
93 |
dojo.addClass(this.titleNode,((this.descending)?"sortListDesc":"sortListAsc"));
|
|
|
94 |
dojo.removeClass(this.titleNode,((this.descending)?"sortListAsc":"sortListDesc"));
|
|
|
95 |
arr.sort(this._sorter);
|
|
|
96 |
if(this.descending){ arr.reverse(); }
|
|
|
97 |
}
|
|
|
98 |
var i=0;
|
|
|
99 |
dojo.forEach(arr,function(item){
|
|
|
100 |
dojo[(((i++)%2)===0)?"addClass":"removeClass"](item,"sortListItemOdd");
|
|
|
101 |
this.containerNode.appendChild(item);
|
|
|
102 |
},this);
|
|
|
103 |
},
|
|
|
104 |
|
|
|
105 |
_set: function(/* Event */e){
|
|
|
106 |
// summary: set hover state
|
|
|
107 |
if (e.target != this.bodyWrapper){
|
|
|
108 |
dojo.addClass(e.target,"sortListItemHover");
|
|
|
109 |
}
|
|
|
110 |
},
|
|
|
111 |
|
|
|
112 |
_unset: function(/* Event */e){
|
|
|
113 |
// summary: remove hover state (FIXME: combine with _set?)
|
|
|
114 |
dojo.removeClass(e.target,"sortListItemHover");
|
|
|
115 |
},
|
|
|
116 |
|
|
|
117 |
_handleClick: function(/* Event */e){
|
|
|
118 |
// summary: click listener for data portion of widget. toggle selected state
|
|
|
119 |
// of node, and update this.selected array accordingly
|
|
|
120 |
dojo.toggleClass(e.target,"sortListItemSelected");
|
|
|
121 |
e.target.focus();
|
|
|
122 |
this._updateValues(e.target.innerHTML);
|
|
|
123 |
},
|
|
|
124 |
|
|
|
125 |
_updateValues: function(){
|
|
|
126 |
this._selected = dojo.query("li.sortListItemSelected",this.containerNode);
|
|
|
127 |
this.selected = [];
|
|
|
128 |
dojo.forEach(this._selected,function(node){
|
|
|
129 |
this.selected.push(node.innerHTML);
|
|
|
130 |
},this);
|
|
|
131 |
this.onChanged(arguments);
|
|
|
132 |
},
|
|
|
133 |
|
|
|
134 |
_sorter: function(a,b){
|
|
|
135 |
// summary: a basic sort function, use query sort, or keep this?
|
|
|
136 |
var aStr = a.innerHTML;
|
|
|
137 |
var bStr = b.innerHTML;
|
|
|
138 |
if(aStr>bStr){ return 1; }
|
|
|
139 |
if(aStr<bStr){ return -1; }
|
|
|
140 |
return 0;
|
|
|
141 |
},
|
|
|
142 |
|
|
|
143 |
setTitle: function(/* String */title){
|
|
|
144 |
// summary: Sets the widget title to a String
|
|
|
145 |
this.focusNode.innerHTML = title;
|
|
|
146 |
},
|
|
|
147 |
|
|
|
148 |
onChanged: function(){
|
|
|
149 |
// summary: stub function, passes the last changed item, and is fired after current state
|
|
|
150 |
}
|
|
|
151 |
});
|
|
|
152 |
|
|
|
153 |
}
|