SortList.js 5.3 KB

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