diff options
Diffstat (limited to 'includes/js/dojox/widget/SortList.js')
-rw-r--r-- | includes/js/dojox/widget/SortList.js | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/includes/js/dojox/widget/SortList.js b/includes/js/dojox/widget/SortList.js new file mode 100644 index 0000000..e50ec2b --- /dev/null +++ b/includes/js/dojox/widget/SortList.js @@ -0,0 +1,151 @@ +if(!dojo._hasResource["dojox.widget.SortList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.widget.SortList"] = true; +dojo.provide("dojox.widget.SortList"); +dojo.experimental("dojox.widget.SortList"); // level: prototype, designed for dijit.chat.demo + +dojo.require("dijit.layout._LayoutWidget"); +dojo.require("dijit._Templated"); + +dojo.declare("dojox.widget.SortList", + [dijit.layout._LayoutWidget, dijit._Templated], + { + // summary: A sortable unordered-list with a fixed header for use in dijit.demos.chat + // for demonstration purposes only for now. feel free to make API suggestions + // or fixes. + // + // title: String + // The title in the header + title: "", + + // heading: String + // In the event a parent container is expecting a title="" attribute, set it for the parent + // via title, and the title of this widget via heading="" ... assuming you want different + // titles for each. eg: TabContainer, AccordionContainer, etc. + heading: "", + + // descending: Boolean + // Toggle sort order based on this value. + descending: true, + + // selected: Array + // A list of the selected <li> nodes at any given time. + selected: null, + + // sortable: Boolean + // toggle to enable/disable sorting + sortable: true, + + // FIXME: this is really simple store support + store: "", + key: "name", + + 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", + + _addItem: function(item){ + var node = dojo.doc.createElement("li"); + var text = this.store.getValue(item,this.key); + node.innerHTML = text; + this.containerNode.appendChild(node); + }, + + postCreate: function(){ + if(this.store){ + this.store = dojo.getObject(this.store); + var props = { + onItem: dojo.hitch(this,"_addItem"), + onComplete: dojo.hitch(this,"onSort") + }; + this.store.fetch(props); + }else{ this.onSort(); } + this.inherited(arguments); + }, + + startup: function(){ + this.inherited(arguments); + if(this.heading){ + this.setTitle(this.heading); this.title=this.heading; + } + // we cheat, and give the browser just enough time so we know our height + setTimeout(dojo.hitch(this,"resize"),5); + if (this.sortable){ this.connect(this.titleNode,"onclick", "onSort"); } + }, + + resize: function(){ + // summary: do our additional calculations when resize() is called by or in a parent + this.inherited(arguments); + // FIXME: + // the 10 comes from the difference between the contentBox and calculated height + // because of badding and border extents. this shouldn't be done this way, a theme change will + // break it: but we also don't want to run getComputedStyle or dojo.coords() every time resize() + // is fired. + var offset = ((this._contentBox.h) - (dojo.style(this.titleNode,"height")))-10; + this.bodyWrapper.style.height = Math.abs(offset) + "px"; + }, + + onSort: function(/* Event */e){ + // summary: sort the data, and style the nodes. + + var arr = dojo.query("li",this.domNode); + if (this.sortable){ + this.descending = !this.descending; + dojo.addClass(this.titleNode,((this.descending)?"sortListDesc":"sortListAsc")); + dojo.removeClass(this.titleNode,((this.descending)?"sortListAsc":"sortListDesc")); + arr.sort(this._sorter); + if(this.descending){ arr.reverse(); } + } + var i=0; + dojo.forEach(arr,function(item){ + dojo[(i++)%2 === 0 ? "addClass" : "removeClass"](item,"sortListItemOdd"); + this.containerNode.appendChild(item); + },this); + }, + + _set: function(/* Event */e){ + // summary: set hover state + if(e.target !== this.bodyWrapper){ + dojo.addClass(e.target,"sortListItemHover"); + } + }, + + _unset: function(/* Event */e){ + // summary: remove hover state (FIXME: combine with _set?) + dojo.removeClass(e.target,"sortListItemHover"); + }, + + _handleClick: function(/* Event */e){ + // summary: click listener for data portion of widget. toggle selected state + // of node, and update this.selected array accordingly + dojo.toggleClass(e.target,"sortListItemSelected"); + e.target.focus(); + this._updateValues(e.target.innerHTML); + }, + + _updateValues: function(){ + this._selected = dojo.query("li.sortListItemSelected",this.containerNode); + this.selected = []; + dojo.forEach(this._selected,function(node){ + this.selected.push(node.innerHTML); + },this); + this.onChanged(arguments); + }, + + _sorter: function(a,b){ + // summary: a basic sort function, use query sort, or keep this? + var aStr = a.innerHTML; + var bStr = b.innerHTML; + if(aStr>bStr){ return 1; } + if(aStr<bStr){ return -1; } + return 0; + }, + + setTitle: function(/* String */title){ + // summary: Sets the widget title to a String + this.focusNode.innerHTML = this.title = title; + }, + + onChanged: function(){ + // summary: stub function, passes the last changed item, and is fired after current state + } +}); + +} |