Skip to content
Browse files

Merge branch 'clanceyp-master' into dev-master

  • Loading branch information...
2 parents 044aac2 + 8dcfea5 commit a8cad679d9db3f06a733c0f30638df8853b61a09 @ericf ericf committed Jan 11, 2013
View
3 build/datatable-scroll/datatable-scroll-min.js
@@ -1,2 +1 @@
-YUI.add("datatable-scroll",function(e,t){function u(e,t){return parseInt(e.getComputedStyle(t),10)|0}var n=e.Lang,r=n.isString,i=n.isNumber,s=n.isArray,o;e.DataTable.Scrollable=o=function(){},o.ATTRS={scrollable:{value:!1,setter:"_setScrollable"}},e.mix(o.prototype,{scrollTo:function(t){var n;return t&&this._tbodyNode&&(this._yScrollNode||this._xScrollNode)&&(s(t)?n=this.getCell(t):i(t)?n=this.getRow(t):r(t)?n=this._tbodyNode.one("#"+t):t instanceof e.Node&&t.ancestor(".yui3-datatable")===this.get("boundingBox")&&(n=t),n&&n.scrollIntoView()),this},_CAPTION_TABLE_TEMPLATE:'<table class="{className}" role="presentation"></table>',_SCROLL_LINER_TEMPLATE:'<div class="{className}"></div>',_SCROLLBAR_TEMPLATE:'<div class="{className}"><div></div></div>',_X_SCROLLER_TEMPLATE:'<div class="{className}"></div>',_Y_SCROLL_HEADER_TEMPLATE:'<table cellspacing="0" aria-hidden="true" class="{className}"></table>',_Y_SCROLLER_TEMPLATE:'<div class="{className}"><div class="{scrollerClassName}"></div></div>',_addScrollbarPadding:function(){var t=this._yScrollHeader,n="."+this.getClassName("header"),r,i,s,o,u;if(t){r=e.DOM.getScrollbarWidth()+"px",i=t.all("tr");for(o=0,u=i.size();o<u;o+=+s.get("rowSpan"))s=i.item(o).all(n).pop(),s.setStyle("paddingRight",r)}},_afterScrollableChange:function(t){var n=this._xScrollNode;this._xScroll&&n&&(this._yScroll&&!this._yScrollNode?n.setStyle("paddingRight",e.DOM.getScrollbarWidth()+"px"):!this._yScroll&&this._yScrollNode&&n.setStyle("paddingRight","")),this._syncScrollUI()},_afterScrollCaptionChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollColumnsChange:function(e){if(this._xScroll||this._yScroll)this._yScroll&&this._yScrollHeader&&this._syncScrollHeaders(),this._syncScrollUI()},_afterScrollDataChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollHeightChange:function(e){this._yScroll&&this._syncScrollUI()},_afterScrollSort:function(e){var t,n;this._yScroll&&this._yScrollHeader&&(n="."+this.getClassName("header"),t=this._theadNode.all(n),this._yScrollHeader.all(n).each(function(e,n){e.set("className",t.item(n).get("className"))}))},_afterScrollWidthChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_bindScrollbar:function(){var t=this._scrollbarNode,n=this._yScrollNode;t&&n&&!this._scrollbarEventHandle&&(this._scrollbarEventHandle=new e.Event.Handle([t.on("scroll",this._syncScrollPosition,this),n.on("scroll",this._syncScrollPosition,this)]))},_bindScrollResize:function(){this._scrollResizeHandle||(this._scrollResizeHandle=e.on("resize",this._syncScrollUI,null,this))},_bindScrollUI:function(){this.after({columnsChange:e.bind("_afterScrollColumnsChange",this),heightChange:e.bind("_afterScrollHeightChange",this),widthChange:e.bind("_afterScrollWidthChange",this),captionChange:e.bind("_afterScrollCaptionChange",this),scrollableChange:e.bind("_afterScrollableChange",this),sort:e.bind("_afterScrollSort",this)}),this.after(["dataChange","*:add","*:remove","*:reset","*:change"],e.bind("_afterScrollDataChange",this))},_clearScrollLock:function(){this._scrollLock&&(this._scrollLock.cancel(),delete this._scrollLock)},_createScrollbar:function(){var t=this._scrollbarNode;return t||(t=this._scrollbarNode=e.Node.create(e.Lang.sub(this._SCROLLBAR_TEMPLATE,{className:this.getClassName("scrollbar")})),t.setStyle("width",e.DOM.getScrollbarWidth()+1+"px")),t},_createScrollCaptionTable:function(){return this._captionTable||(this._captionTable=e.Node.create(e.Lang.sub(this._CAPTION_TABLE_TEMPLATE,{className:this.getClassName("caption","table")})),this._captionTable.empty()),this._captionTable},_createXScrollNode:function(){return this._xScrollNode||(this._xScrollNode=e.Node.create(e.Lang.sub(this._X_SCROLLER_TEMPLATE,{className:this.getClassName("x","scroller")}))),this._xScrollNode},_createYScrollHeader:function(){var t=this._yScrollHeader;return t||(t=this._yScrollHeader=e.Node.create(e.Lang.sub(this._Y_SCROLL_HEADER_TEMPLATE,{className:this.getClassName("scroll","columns")}))),t},_createYScrollNode:function(){var t;return this._yScrollNode||(t=this.getClassName("y","scroller"),this._yScrollContainer=e.Node.create(e.Lang.sub(this._Y_SCROLLER_TEMPLATE,{className:this.getClassName("y","scroller","container"),scrollerClassName:t})),this._yScrollNode=this._yScrollContainer.one("."+t)),this._yScrollContainer},_disableScrolling:function(){this._removeScrollCaptionTable(),this._disableXScrolling(),this._disableYScrolling(),this._unbindScrollResize(),this._uiSetWidth(this.get("width"))},_disableXScrolling:function(){this._removeXScrollNode()},_disableYScrolling:function(){this._removeYScrollHeader(),this._removeYScrollNode(),this._removeYScrollContainer(),this._removeScrollbar()},destructor:function(){this._unbindScrollbar(),this._unbindScrollResize(),this._clearScrollLock()},initializer:function(){this._setScrollProperties(),this.after(["scrollableChange","heightChange","widthChange"],this._setScrollProperties),this.after("renderView",e.bind("_syncScrollUI",this)),e.Do.after(this._bindScrollUI,this,"bindUI")},_removeScrollCaptionTable:function(){this._captionTable&&(this._captionNode&&this._tableNode.prepend(this._captionNode),this._captionTable.remove().destroy(!0),delete this._captionTable)},_removeXScrollNode:function(){var e=this._xScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._xScrollNode)},_removeYScrollContainer:function(){var e=this._yScrollContainer;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollContainer)},_removeYScrollHeader:function(){this._yScrollHeader&&(this._yScrollHeader.remove().destroy(!0),delete this._yScrollHeader)},_removeYScrollNode:function(){var e=this._yScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollNode)},_removeScrollbar:function(){this._scrollbarNode&&(this._scrollbarNode.remove().destroy(!0),delete this._scrollbarNode),this._scrollbarEventHandle&&
-(this._scrollbarEventHandle.detach(),delete this._scrollbarEventHandle)},_setScrollable:function(t){return t===!0&&(t="xy"),r(t)&&(t=t.toLowerCase()),t===!1||t==="y"||t==="x"||t==="xy"?t:e.Attribute.INVALID_VALUE},_setScrollProperties:function(){var e=this.get("scrollable")||"",t=this.get("width"),n=this.get("height");this._xScroll=t&&e.indexOf("x")>-1,this._yScroll=n&&e.indexOf("y")>-1},_syncScrollPosition:function(t){var n=this._scrollbarNode,r=this._yScrollNode,i=t.currentTarget,s;if(n&&r){if(this._scrollLock&&this._scrollLock.source!==i)return;this._clearScrollLock(),this._scrollLock=e.later(300,this,this._clearScrollLock),this._scrollLock.source=i,s=i===n?r:n,s.set("scrollTop",i.get("scrollTop"))}},_syncScrollCaptionUI:function(){var t=this._captionNode,n=this._tableNode,r=this._captionTable,i;t?(i=t.getAttribute("id"),r||(r=this._createScrollCaptionTable(),this.get("contentBox").prepend(r)),t.get("parentNode").compareTo(r)||(r.empty().insert(t),i||(i=e.stamp(t),t.setAttribute("id",i)),n.setAttribute("aria-describedby",i))):r&&this._removeScrollCaptionTable()},_syncScrollColumnWidths:function(){var t=[];this._theadNode&&this._yScrollHeader&&(this._theadNode.all("."+this.getClassName("header")).each(function(n){t.push(e.UA.ie&&e.UA.ie<8?n.get("clientWidth")-u(n,"paddingLeft")-u(n,"paddingRight")+"px":n.getComputedStyle("width"))}),this._yScrollHeader.all("."+this.getClassName("scroll","liner")).each(function(e,n){e.setStyle("width",t[n])}))},_syncScrollHeaders:function(){var t=this._yScrollHeader,n=this._SCROLL_LINER_TEMPLATE,r=this.getClassName("scroll","liner"),i=this.getClassName("header"),s=this._theadNode.all("."+i);this._theadNode&&t&&(t.empty().appendChild(this._theadNode.cloneNode(!0)),t.all("[id]").removeAttribute("id"),t.all("."+i).each(function(t,i){var o=e.Node.create(e.Lang.sub(n,{className:r})),u=s.item(i);o.setStyle("padding",u.getComputedStyle("paddingTop")+" "+u.getComputedStyle("paddingRight")+" "+u.getComputedStyle("paddingBottom")+" "+u.getComputedStyle("paddingLeft")),o.appendChild(t.get("childNodes").toFrag()),t.appendChild(o)},this),this._syncScrollColumnWidths(),this._addScrollbarPadding())},_syncScrollUI:function(){var e=this._xScroll,t=this._yScroll,n=this._xScrollNode,r=this._yScrollNode,i=n&&n.get("scrollLeft"),s=r&&r.get("scrollTop");this._uiSetScrollable(),e||t?((this.get("width")||"").slice(-1)==="%"?this._bindScrollResize():this._unbindScrollResize(),this._syncScrollCaptionUI()):this._disableScrolling(),this._yScrollHeader&&this._yScrollHeader.setStyle("display","none"),e&&(t||this._disableYScrolling(),this._syncXScrollUI(t)),t&&(e||this._disableXScrolling(),this._syncYScrollUI(e)),i&&this._xScrollNode&&this._xScrollNode.set("scrollLeft",i),s&&this._yScrollNode&&this._yScrollNode.set("scrollTop",s)},_syncXScrollUI:function(t){var n=this._xScrollNode,r=this._yScrollContainer,i=this._tableNode,s=this.get("width"),o=this.get("boundingBox").get("offsetWidth"),a=e.DOM.getScrollbarWidth(),f,l;n||(n=this._createXScrollNode(),(r||i).replace(n).appendTo(n)),f=u(n,"borderLeftWidth")+u(n,"borderRightWidth"),n.setStyle("width",""),this._uiSetDim("width",""),t&&this._yScrollContainer&&this._yScrollContainer.setStyle("width",""),e.UA.ie&&e.UA.ie<8&&(i.setStyle("width",s),i.get("offsetWidth")),i.setStyle("width",""),l=i.get("offsetWidth"),i.setStyle("width",l+"px"),this._uiSetDim("width",s),n.setStyle("width",o-f+"px"),n.get("offsetWidth")-f>l&&(t?i.setStyle("width",n.get("offsetWidth")-f-a+"px"):i.setStyle("width","100%"))},_syncYScrollUI:function(t){var n=this._yScrollContainer,r=this._yScrollNode,i=this._xScrollNode,s=this._yScrollHeader,o=this._scrollbarNode,a=this._tableNode,f=this._theadNode,l=this._captionTable,c=this.get("boundingBox"),h=this.get("contentBox"),p=this.get("width"),d=c.get("offsetHeight"),v=e.DOM.getScrollbarWidth(),m;l&&!t&&l.setStyle("width",p||"100%"),n||(n=this._createYScrollNode(),r=this._yScrollNode,a.replace(n).appendTo(r)),m=t?i:n,t||a.setStyle("width",""),t&&(d-=v),r.setStyle("height",d-m.get("offsetTop")-u(m,"borderTopWidth")-u(m,"borderBottomWidth")+"px"),t?n.setStyle("width",a.get("offsetWidth")+v+"px"):this._uiSetYScrollWidth(p),l&&!t&&l.setStyle("width",n.get("offsetWidth")+"px"),f&&!s&&(s=this._createYScrollHeader(),n.prepend(s),this._syncScrollHeaders()),s&&(this._syncScrollColumnWidths(),s.setStyle("display",""),o||(o=this._createScrollbar(),this._bindScrollbar(),h.prepend(o)),this._uiSetScrollbarHeight(),this._uiSetScrollbarPosition(m))},_uiSetScrollable:function(){this.get("boundingBox").toggleClass(this.getClassName("scrollable","x"),this._xScroll).toggleClass(this.getClassName("scrollable","y"),this._yScroll)},_uiSetScrollbarHeight:function(){var e=this._scrollbarNode,t=this._yScrollNode,n=this._yScrollHeader;e&&t&&n&&(e.get("firstChild").setStyle("height",this._tbodyNode.get("scrollHeight")+"px"),e.setStyle("height",parseFloat(t.getComputedStyle("height"))-parseFloat(n.getComputedStyle("height"))+"px"))},_uiSetScrollbarPosition:function(t){var n=this._scrollbarNode,r=this._yScrollHeader;n&&t&&r&&n.setStyles({top:parseFloat(r.getComputedStyle("height"))+u(t,"borderTopWidth")+t.get("offsetTop")+"px",left:t.get("offsetWidth")-e.DOM.getScrollbarWidth()-1-u(t,"borderRightWidth")+"px"})},_uiSetYScrollWidth:function(t){var n=this._yScrollContainer,r=this._tableNode,i,s,o,u;n&&r&&(u=e.DOM.getScrollbarWidth(),t?(s=n.get("offsetWidth")-n.get("clientWidth")+u,n.setStyle("width",t),o=n.get("clientWidth")-s,r.setStyle("width",o+"px"),i=r.get("offsetWidth"),n.setStyle("width",i+u+"px")):(r.setStyle("width",""),n.setStyle("width",""),n.setStyle("width",r.get("offsetWidth")+u+"px")))},_unbindScrollbar:function(){this._scrollbarEventHandle&&this._scrollbarEventHandle.detach()},_unbindScrollResize:function(){this._scrollResizeHandle&&(this._scrollResizeHandle.detach(),delete this._scrollResizeHandle)}},!0),e.Base.mix(e.DataTable,[o])},"@VERSION@",{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0});
+YUI.add("datatable-scroll",function(e,t){function u(e,t){return parseInt(e.getComputedStyle(t),10)|0}var n=e.Lang,r=n.isString,i=n.isNumber,s=n.isArray,o;e.DataTable.Scrollable=o=function(){},o.ATTRS={scrollable:{value:!1,setter:"_setScrollable"}},e.mix(o.prototype,{scrollTo:function(t){var n;return t&&this._tbodyNode&&(this._yScrollNode||this._xScrollNode)&&(s(t)?n=this.getCell(t):i(t)?n=this.getRow(t):r(t)?n=this._tbodyNode.one("#"+t):t instanceof e.Node&&t.ancestor(".yui3-datatable")===this.get("boundingBox")&&(n=t),n&&n.scrollIntoView()),this},_CAPTION_TABLE_TEMPLATE:'<table class="{className}" role="presentation"></table>',_SCROLL_LINER_TEMPLATE:'<div class="{className}"></div>',_SCROLLBAR_TEMPLATE:'<div class="{className}"><div></div></div>',_X_SCROLLER_TEMPLATE:'<div class="{className}"></div>',_Y_SCROLL_HEADER_TEMPLATE:'<table cellspacing="0" aria-hidden="true" class="{className}"></table>',_Y_SCROLLER_TEMPLATE:'<div class="{className}"><div class="{scrollerClassName}"></div></div>',_addScrollbarPadding:function(){var t=this._yScrollHeader,n="."+this.getClassName("header"),r,i,s,o,u;if(t){r=e.DOM.getScrollbarWidth()+"px",i=t.all("tr");for(o=0,u=i.size();o<u;o+=+s.get("rowSpan"))s=i.item(o).all(n).pop(),s.setStyle("paddingRight",r)}},_afterScrollableChange:function(t){var n=this._xScrollNode;this._xScroll&&n&&(this._yScroll&&!this._yScrollNode?n.setStyle("paddingRight",e.DOM.getScrollbarWidth()+"px"):!this._yScroll&&this._yScrollNode&&n.setStyle("paddingRight","")),this._syncScrollUI()},_afterScrollCaptionChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollColumnsChange:function(e){if(this._xScroll||this._yScroll)this._yScroll&&this._yScrollHeader&&this._syncScrollHeaders(),this._syncScrollUI()},_afterScrollDataChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollHeightChange:function(e){this._yScroll&&this._syncScrollUI()},_afterScrollSort:function(e){var t,n;this._yScroll&&this._yScrollHeader&&(n="."+this.getClassName("header"),t=this._theadNode.all(n),this._yScrollHeader.all(n).each(function(e,n){e.set("className",t.item(n).get("className"))}))},_afterScrollWidthChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_bindScrollbar:function(){var t=this._scrollbarNode,n=this._yScrollNode;t&&n&&!this._scrollbarEventHandle&&(this._scrollbarEventHandle=new e.Event.Handle([t.on("scroll",this._syncScrollPosition,this),n.on("scroll",this._syncScrollPosition,this)]))},_bindScrollResize:function(){this._scrollResizeHandle||(this._scrollResizeHandle=e.on("resize",this._syncScrollUI,null,this))},_bindScrollUI:function(){this.after({columnsChange:e.bind("_afterScrollColumnsChange",this),heightChange:e.bind("_afterScrollHeightChange",this),widthChange:e.bind("_afterScrollWidthChange",this),captionChange:e.bind("_afterScrollCaptionChange",this),scrollableChange:e.bind("_afterScrollableChange",this),sort:e.bind("_afterScrollSort",this)}),this.after(["dataChange","*:add","*:remove","*:reset","*:change"],e.bind("_afterScrollDataChange",this))},_clearScrollLock:function(){this._scrollLock&&(this._scrollLock.cancel(),delete this._scrollLock)},_createScrollbar:function(){var t=this._scrollbarNode;return t||(t=this._scrollbarNode=e.Node.create(e.Lang.sub(this._SCROLLBAR_TEMPLATE,{className:this.getClassName("scrollbar")})),t.setStyle("width",e.DOM.getScrollbarWidth()+1+"px")),t},_createScrollCaptionTable:function(){return this._captionTable||(this._captionTable=e.Node.create(e.Lang.sub(this._CAPTION_TABLE_TEMPLATE,{className:this.getClassName("caption","table")})),this._captionTable.empty()),this._captionTable},_createXScrollNode:function(){return this._xScrollNode||(this._xScrollNode=e.Node.create(e.Lang.sub(this._X_SCROLLER_TEMPLATE,{className:this.getClassName("x","scroller")}))),this._xScrollNode},_createYScrollHeader:function(){var t=this._yScrollHeader;return t||(t=this._yScrollHeader=e.Node.create(e.Lang.sub(this._Y_SCROLL_HEADER_TEMPLATE,{className:this.getClassName("scroll","columns")}))),t},_createYScrollNode:function(){var t;return this._yScrollNode||(t=this.getClassName("y","scroller"),this._yScrollContainer=e.Node.create(e.Lang.sub(this._Y_SCROLLER_TEMPLATE,{className:this.getClassName("y","scroller","container"),scrollerClassName:t})),this._yScrollNode=this._yScrollContainer.one("."+t)),this._yScrollContainer},_disableScrolling:function(){this._removeScrollCaptionTable(),this._disableXScrolling(),this._disableYScrolling(),this._unbindScrollResize(),this._uiSetWidth(this.get("width"))},_disableXScrolling:function(){this._removeXScrollNode()},_disableYScrolling:function(){this._removeYScrollHeader(),this._removeYScrollNode(),this._removeYScrollContainer(),this._removeScrollbar()},destructor:function(){this._unbindScrollbar(),this._unbindScrollResize(),this._clearScrollLock()},initializer:function(){this._setScrollProperties(),this.after(["scrollableChange","heightChange","widthChange"],this._setScrollProperties),this.after("renderView",e.bind("_syncScrollUI",this)),e.Do.after(this._bindScrollUI,this,"bindUI")},_removeScrollCaptionTable:function(){this._captionTable&&(this._captionNode&&this._tableNode.prepend(this._captionNode),this._captionTable.remove().destroy(!0),delete this._captionTable)},_removeXScrollNode:function(){var e=this._xScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._xScrollNode)},_removeYScrollContainer:function(){var e=this._yScrollContainer;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollContainer)},_removeYScrollHeader:function(){this._yScrollHeader&&(this._yScrollHeader.remove().destroy(!0),delete this._yScrollHeader)},_removeYScrollNode:function(){var e=this._yScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollNode)},_removeScrollbar:function(){this._scrollbarNode&&(this._scrollbarNode.remove().destroy(!0),delete this._scrollbarNode),this._scrollbarEventHandle&&(this._scrollbarEventHandle.detach(),delete this._scrollbarEventHandle)},_setScrollable:function(t){return t===!0&&(t="xy"),r(t)&&(t=t.toLowerCase()),t===!1||t==="y"||t==="x"||t==="xy"?t:e.Attribute.INVALID_VALUE},_setScrollProperties:function(){var e=this.get("scrollable")||"",t=this.get("width"),n=this.get("height");this._xScroll=t&&e.indexOf("x")>-1,this._yScroll=n&&e.indexOf("y")>-1},_syncScrollPosition:function(t){var n=this._scrollbarNode,r=this._yScrollNode,i=t.currentTarget,s;if(n&&r){if(this._scrollLock&&this._scrollLock.source!==i)return;this._clearScrollLock(),this._scrollLock=e.later(300,this,this._clearScrollLock),this._scrollLock.source=i,s=i===n?r:n,s.set("scrollTop",i.get("scrollTop"))}},_syncScrollCaptionUI:function(){var t=this._captionNode,n=this._tableNode,r=this._captionTable,i;t?(i=t.getAttribute("id"),r||(r=this._createScrollCaptionTable(),this.get("contentBox").prepend(r)),t.get("parentNode").compareTo(r)||(r.empty().insert(t),i||(i=e.stamp(t),t.setAttribute("id",i)),n.setAttribute("aria-describedby",i))):r&&this._removeScrollCaptionTable()},_syncScrollColumnWidths:function(){var t=[];this._theadNode&&this._yScrollHeader&&(this._theadNode.all("."+this.getClassName("header")).each(function(n){t.push(e.UA.ie&&e.UA.ie<8?n.get("clientWidth")-u(n,"paddingLeft")-u(n,"paddingRight")+"px":n.getComputedStyle("width"))}),this._yScrollHeader.all("."+this.getClassName("scroll","liner")).each(function(e,n){e.setStyle("width",t[n])}))},_syncScrollHeaders:function(){var t=this._yScrollHeader,n=this._SCROLL_LINER_TEMPLATE,r=this.getClassName("scroll","liner"),i=this.getClassName("header"),s=this._theadNode.all("."+i);this._theadNode&&t&&(t.empty().appendChild(this._theadNode.cloneNode(!0)),t.all("[id]").removeAttribute("id"),t.all("."+i).each(function(t,i){var o=e.Node.create(e.Lang.sub(n,{className:r})),u=s.item(i);o.setStyle("padding",u.getComputedStyle("paddingTop")+" "+u.getComputedStyle("paddingRight")+" "+u.getComputedStyle("paddingBottom")+" "+u.getComputedStyle("paddingLeft")),o.appendChild(t.get("childNodes").toFrag()),t.appendChild(o)},this),this._syncScrollColumnWidths(),this._addScrollbarPadding())},_syncScrollUI:function(){var e=this._xScroll,t=this._yScroll,n=this._xScrollNode,r=this._yScrollNode,i=n&&n.get("scrollLeft"),s=r&&r.get("scrollTop");this._uiSetScrollable(),e||t?((this.get("width")||"").slice(-1)==="%"?this._bindScrollResize():this._unbindScrollResize(),this._syncScrollCaptionUI()):this._disableScrolling(),this._yScrollHeader&&this._yScrollHeader.setStyle("display","none"),e&&(t||this._disableYScrolling(),this._syncXScrollUI(t)),t&&(e||this._disableXScrolling(),this._syncYScrollUI(e)),i&&this._xScrollNode&&this._xScrollNode.set("scrollLeft",i),s&&this._yScrollNode&&this._yScrollNode.set("scrollTop",s)},_syncXScrollUI:function(t){var n=this._xScrollNode,r=this._yScrollContainer,i=this._tableNode,s=this.get("width"),o=this.get("boundingBox").get("offsetWidth"),a=e.DOM.getScrollbarWidth(),f,l;n||(n=this._createXScrollNode(),(r||i).replace(n).appendTo(n)),f=u(n,"borderLeftWidth")+u(n,"borderRightWidth"),n.setStyle("width",""),this._uiSetDim("width",""),t&&this._yScrollContainer&&this._yScrollContainer.setStyle("width",""),e.UA.ie&&e.UA.ie<8&&(i.setStyle("width",s),i.get("offsetWidth")),i.setStyle("width",""),l=i.get("offsetWidth"),i.setStyle("width",l+"px"),this._uiSetDim("width",s),n.setStyle("width",o-f+"px"),n.get("offsetWidth")-f>l&&(t?i.setStyle("width",n.get("offsetWidth")-f-a+"px"):i.setStyle("width","100%"))},_syncYScrollUI:function(t){var n=this._yScrollContainer,r=this._yScrollNode,i=this._xScrollNode,s=this._yScrollHeader,o=this._scrollbarNode,a=this._tableNode,f=this._theadNode,l=this._captionTable,c=this.get("boundingBox"),h=this.get("contentBox"),p=this.get("width"),d=c.get("offsetHeight"),v=e.DOM.getScrollbarWidth(),m;l&&!t&&l.setStyle("width",p||"100%"),n||(n=this._createYScrollNode(),r=this._yScrollNode,a.replace(n).appendTo(r)),m=t?i:n,t||a.setStyle("width",""),t&&(d-=v),r.setStyle("height",d-m.get("offsetTop")-u(m,"borderTopWidth")-u(m,"borderBottomWidth")+"px"),t?n.setStyle("width",a.get("offsetWidth")+v+"px"):this._uiSetYScrollWidth(p),l&&!t&&l.setStyle("width",n.get("offsetWidth")+"px"),f&&!s&&(s=this._createYScrollHeader(),n.prepend(s),this._syncScrollHeaders()),s&&(this._syncScrollColumnWidths(),s.setStyle("display",""),o||(o=this._createScrollbar(),this._bindScrollbar(),h.prepend(o)),this._uiSetScrollbarHeight(),this._uiSetScrollbarPosition(m))},_uiSetScrollable:function(){this.get("boundingBox").toggleClass(this.getClassName("scrollable","x"),this._xScroll).toggleClass(this.getClassName("scrollable","y"),this._yScroll)},_uiSetScrollbarHeight:function(){var e=this._scrollbarNode,t=this._yScrollNode,n=this._yScrollHeader;e&&t&&n&&(e.get("firstChild").setStyle("height",this._tbodyNode.get("scrollHeight")+"px"),e.setStyle("height",parseFloat(t.getComputedStyle("height"))-parseFloat(n.getComputedStyle("height"))+"px"))},_uiSetScrollbarPosition:function(t){var n=this._scrollbarNode,r=this._yScrollHeader;n&&t&&r&&n.setStyles({top:parseFloat(r.getComputedStyle("height"))+u(t,"borderTopWidth")+t.get("offsetTop")+"px",left:t.get("offsetWidth")-e.DOM.getScrollbarWidth()-1-u(t,"borderRightWidth")+"px"})},_uiSetYScrollWidth:function(t){var n=this._yScrollContainer,r=this._tableNode,i,s,o,u;n&&r&&(u=e.DOM.getScrollbarWidth(),t?(s=n.get("offsetWidth")-n.get("clientWidth")+u,n.setStyle("width",t),o=n.get("clientWidth")-s,r.setStyle("width",o+"px"),i=r.get("offsetWidth"),n.setStyle("width",i+u+"px")):(r.setStyle("width",""),n.setStyle("width",""),n.setStyle("width",r.get("offsetWidth")+u+"px")))},_unbindScrollbar:function(){this._scrollbarEventHandle&&this._scrollbarEventHandle.detach()},_unbindScrollResize:function(){this._scrollResizeHandle&&(this._scrollResizeHandle.detach(),delete this._scrollResizeHandle)}},!0),e.Base.mix(e.DataTable,[o])},"@VERSION@",{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0});
View
253 build/datatable-sort/datatable-sort-coverage.js
@@ -26,10 +26,10 @@ _yuitest_coverage["build/datatable-sort/datatable-sort.js"] = {
path: "build/datatable-sort/datatable-sort.js",
code: []
};
-_yuitest_coverage["build/datatable-sort/datatable-sort.js"].code=["YUI.add('datatable-sort', function (Y, NAME) {","","/**","Adds support for sorting the table data by API methods `table.sort(...)` or","`table.toggleSort(...)` or by clicking on column headers in the rendered UI.","","@module datatable","@submodule datatable-sort","@since 3.5.0","**/","var YLang = Y.Lang,"," isBoolean = YLang.isBoolean,"," isString = YLang.isString,"," isArray = YLang.isArray,"," isObject = YLang.isObject,",""," toArray = Y.Array,"," sub = YLang.sub,",""," dirMap = {"," asc : 1,"," desc: -1,"," \"1\" : 1,"," \"-1\": -1"," };","","","/**","_API docs for this extension are included in the DataTable class._","","This DataTable class extension adds support for sorting the table data by API","methods `table.sort(...)` or `table.toggleSort(...)` or by clicking on column","headers in the rendered UI.","","Sorting by the API is enabled automatically when this module is `use()`d. To","enable UI triggered sorting, set the DataTable's `sortable` attribute to","`true`.","","<pre><code>","var table = new Y.DataTable({"," columns: [ 'id', 'username', 'name', 'birthdate' ],"," data: [ ... ],"," sortable: true","});","","table.render('#table');","</code></pre>","","Setting `sortable` to `true` will enable UI sorting for all columns. To enable","UI sorting for certain columns only, set `sortable` to an array of column keys,","or just add `sortable: true` to the respective column configuration objects.","This uses the default setting of `sortable: auto` for the DataTable instance.","","<pre><code>","var table = new Y.DataTable({"," columns: ["," 'id',"," { key: 'username', sortable: true },"," { key: 'name', sortable: true },"," { key: 'birthdate', sortable: true }"," ],"," data: [ ... ]"," // sortable: 'auto' is the default","});","","// OR","var table = new Y.DataTable({"," columns: [ 'id', 'username', 'name', 'birthdate' ],"," data: [ ... ],"," sortable: [ 'username', 'name', 'birthdate' ]","});","</code></pre>","","To disable UI sorting for all columns, set `sortable` to `false`. This still","permits sorting via the API methods.","","As new records are inserted into the table's `data` ModelList, they will be inserted at the correct index to preserve the sort order.","","The current sort order is stored in the `sortBy` attribute. Assigning this value at instantiation will automatically sort your data.","","Sorting is done by a simple value comparison using &lt; and &gt; on the field","value. If you need custom sorting, add a sort function in the column's","`sortFn` property. Columns whose content is generated by formatters, but don't","relate to a single `key`, require a `sortFn` to be sortable.","","<pre><code>","function nameSort(a, b, desc) {"," var aa = a.get('lastName') + a.get('firstName'),"," bb = a.get('lastName') + b.get('firstName'),"," order = (aa > bb) ? 1 : -(aa < bb);",""," return desc ? -order : order;","}","","var table = new Y.DataTable({"," columns: [ 'id', 'username', { key: name, sortFn: nameSort }, 'birthdate' ],"," data: [ ... ],"," sortable: [ 'username', 'name', 'birthdate' ]","});","</code></pre>","","See the user guide for more details.","","@class DataTable.Sortable","@for DataTable","@since 3.5.0","**/","function Sortable() {}","","Sortable.ATTRS = {"," // Which columns in the UI should suggest and respond to sorting interaction"," // pass an empty array if no UI columns should show sortable, but you want the"," // table.sort(...) API"," /**"," Controls which column headers can trigger sorting by user clicks.",""," Acceptable values are:",""," * \"auto\" - (default) looks for `sortable: true` in the column configurations"," * `true` - all columns are enabled"," * `false - no UI sortable is enabled"," * {String[]} - array of key names to give sortable headers",""," @attribute sortable"," @type {String|String[]|Boolean}"," @default \"auto\""," @since 3.5.0"," **/"," sortable: {"," value: 'auto',"," validator: '_validateSortable'"," },",""," /**"," The current sort configuration to maintain in the data.",""," Accepts column `key` strings or objects with a single property, the column"," `key`, with a value of 1, -1, \"asc\", or \"desc\". E.g. `{ username: 'asc'"," }`. String values are assumed to be ascending.",""," Example values would be:",""," * `\"username\"` - sort by the data's `username` field or the `key`"," associated to a column with that `name`."," * `{ username: \"desc\" }` - sort by `username` in descending order."," Alternately, use values \"asc\", 1 (same as \"asc\"), or -1 (same as \"desc\")."," * `[\"lastName\", \"firstName\"]` - ascending sort by `lastName`, but for"," records with the same `lastName`, ascending subsort by `firstName`."," Array can have as many items as you want."," * `[{ lastName: -1 }, \"firstName\"]` - descending sort by `lastName`,"," ascending subsort by `firstName`. Mixed types are ok.",""," @attribute sortBy"," @type {String|String[]|Object|Object[]}"," @since 3.5.0"," **/"," sortBy: {"," validator: '_validateSortBy',"," getter: '_getSortBy'"," },",""," /**"," Strings containing language for sorting tooltips.",""," @attribute strings"," @type {Object}"," @default (strings for current lang configured in the YUI instance config)"," @since 3.5.0"," **/"," strings: {}","};","","Y.mix(Sortable.prototype, {",""," /**"," Sort the data in the `data` ModelList and refresh the table with the new"," order.",""," Acceptable values for `fields` are `key` strings or objects with a single"," property, the column `key`, with a value of 1, -1, \"asc\", or \"desc\". E.g."," `{ username: 'asc' }`. String values are assumed to be ascending.",""," Example values would be:",""," * `\"username\"` - sort by the data's `username` field or the `key`"," associated to a column with that `name`."," * `{ username: \"desc\" }` - sort by `username` in descending order."," Alternately, use values \"asc\", 1 (same as \"asc\"), or -1 (same as \"desc\")."," * `[\"lastName\", \"firstName\"]` - ascending sort by `lastName`, but for"," records with the same `lastName`, ascending subsort by `firstName`."," Array can have as many items as you want."," * `[{ lastName: -1 }, \"firstName\"]` - descending sort by `lastName`,"," ascending subsort by `firstName`. Mixed types are ok.",""," @method sort"," @param {String|String[]|Object|Object[]} fields The field(s) to sort by"," @param {Object} [payload] Extra `sort` event payload you want to send along"," @return {DataTable}"," @chainable"," @since 3.5.0"," **/"," sort: function (fields, payload) {"," /**"," Notifies of an impending sort, either from clicking on a column"," header, or from a call to the `sort` or `toggleSort` method.",""," The requested sort is available in the `sortBy` property of the event.",""," The default behavior of this event sets the table's `sortBy` attribute.",""," @event sort"," @param {String|String[]|Object|Object[]} sortBy The requested sort"," @preventable _defSortFn"," **/"," return this.fire('sort', Y.merge((payload || {}), {"," sortBy: fields || this.get('sortBy')"," }));"," },",""," /**"," Template for the node that will wrap the header content for sortable"," columns.",""," @property SORTABLE_HEADER_TEMPLATE"," @type {HTML}"," @value '<div class=\"{className}\" tabindex=\"0\"><span class=\"{indicatorClass}\"></span></div>'"," @since 3.5.0"," **/"," SORTABLE_HEADER_TEMPLATE: '<div class=\"{className}\" tabindex=\"0\"><span class=\"{indicatorClass}\"></span></div>',",""," /**"," Reverse the current sort direction of one or more fields currently being"," sorted by.",""," Pass the `key` of the column or columns you want the sort order reversed"," for.",""," @method toggleSort"," @param {String|String[]} fields The field(s) to reverse sort order for"," @param {Object} [payload] Extra `sort` event payload you want to send along"," @return {DataTable}"," @chainable"," @since 3.5.0"," **/"," toggleSort: function (columns, payload) {"," var current = this._sortBy,"," sortBy = [],"," i, len, j, col, index;",""," // To avoid updating column configs or sortBy directly"," for (i = 0, len = current.length; i < len; ++i) {"," col = {};"," col[current[i]._id] = current[i].sortDir;"," sortBy.push(col);"," }",""," if (columns) {"," columns = toArray(columns);",""," for (i = 0, len = columns.length; i < len; ++i) {"," col = columns[i];"," index = -1;",""," for (j = sortBy.length - 1; i >= 0; --i) {"," if (sortBy[j][col]) {"," sortBy[j][col] *= -1;"," break;"," }"," }"," }"," } else {"," for (i = 0, len = sortBy.length; i < len; ++i) {"," for (col in sortBy[i]) {"," if (sortBy[i].hasOwnProperty(col)) {"," sortBy[i][col] *= -1;"," break;"," }"," }"," }"," }",""," return this.fire('sort', Y.merge((payload || {}), {"," sortBy: sortBy"," }));"," },",""," //--------------------------------------------------------------------------"," // Protected properties and methods"," //--------------------------------------------------------------------------"," /**"," Sorts the `data` ModelList based on the new `sortBy` configuration.",""," @method _afterSortByChange"," @param {EventFacade} e The `sortByChange` event"," @protected"," @since 3.5.0"," **/"," _afterSortByChange: function (e) {"," // Can't use a setter because it's a chicken and egg problem. The"," // columns need to be set up to translate, but columns are initialized"," // from Core's initializer. So construction-time assignment would"," // fail."," this._setSortBy();",""," // Don't sort unless sortBy has been set"," if (this._sortBy.length) {"," if (!this.data.comparator) {"," this.data.comparator = this._sortComparator;"," }",""," this.data.sort();"," }"," },",""," /**"," Applies the sorting logic to the new ModelList if the `newVal` is a new"," ModelList.",""," @method _afterSortDataChange"," @param {EventFacade} e the `dataChange` event"," @protected"," @since 3.5.0"," **/"," _afterSortDataChange: function (e) {"," // object values always trigger a change event, but we only want to"," // call _initSortFn if the value passed to the `data` attribute was a"," // new ModelList, not a set of new data as an array, or even the same"," // ModelList."," if (e.prevVal !== e.newVal || e.newVal.hasOwnProperty('_compare')) {"," this._initSortFn();"," }"," },",""," /**"," Checks if any of the fields in the modified record are fields that are"," currently being sorted by, and if so, resorts the `data` ModelList.",""," @method _afterSortRecordChange"," @param {EventFacade} e The Model's `change` event"," @protected"," @since 3.5.0"," **/"," _afterSortRecordChange: function (e) {"," var i, len;",""," for (i = 0, len = this._sortBy.length; i < len; ++i) {"," if (e.changed[this._sortBy[i].key]) {"," this.data.sort();"," break;"," }"," }"," },",""," /**"," Subscribes to state changes that warrant updating the UI, and adds the"," click handler for triggering the sort operation from the UI.",""," @method _bindSortUI"," @protected"," @since 3.5.0"," **/"," _bindSortUI: function () {"," var handles = this._eventHandles;",""," if (!handles.sortAttrs) {"," handles.sortAttrs = this.after("," ['sortableChange', 'sortByChange', 'columnsChange'],"," Y.bind('_uiSetSortable', this));"," }",""," if (!handles.sortUITrigger && this._theadNode) {"," handles.sortUITrigger = this.delegate(['click','keydown'],"," Y.rbind('_onUITriggerSort', this),"," '.' + this.getClassName('sortable', 'column'));"," }"," },",""," /**"," Sets the `sortBy` attribute from the `sort` event's `e.sortBy` value.",""," @method _defSortFn"," @param {EventFacade} e The `sort` event"," @protected"," @since 3.5.0"," **/"," _defSortFn: function (e) {"," this.set.apply(this, ['sortBy', e.sortBy].concat(e.details));"," },",""," /**"," Getter for the `sortBy` attribute.",""," Supports the special subattribute \"sortBy.state\" to get a normalized JSON"," version of the current sort state. Otherwise, returns the last assigned"," value.",""," For example:",""," <pre><code>var table = new Y.DataTable({"," columns: [ ... ],"," data: [ ... ],"," sortBy: 'username'"," });",""," table.get('sortBy'); // 'username'"," table.get('sortBy.state'); // { key: 'username', dir: 1 }",""," table.sort(['lastName', { firstName: \"desc\" }]);"," table.get('sortBy'); // ['lastName', { firstName: \"desc\" }]"," table.get('sortBy.state'); // [{ key: \"lastName\", dir: 1 }, { key: \"firstName\", dir: -1 }]"," </code></pre>",""," @method _getSortBy"," @param {String|String[]|Object|Object[]} val The current sortBy value"," @param {String} detail String passed to `get(HERE)`. to parse subattributes"," @protected"," @since 3.5.0"," **/"," _getSortBy: function (val, detail) {"," var state, i, len, col;",""," // \"sortBy.\" is 7 characters. Used to catch"," detail = detail.slice(7);",""," // TODO: table.get('sortBy.asObject')? table.get('sortBy.json')?"," if (detail === 'state') {"," state = [];",""," for (i = 0, len = this._sortBy.length; i < len; ++i) {"," col = this._sortBy[i];"," state.push({"," column: col._id,"," dir: col.sortDir"," });"," }",""," // TODO: Always return an array?"," return { state: (state.length === 1) ? state[0] : state };"," } else {"," return val;"," }"," },",""," /**"," Sets up the initial sort state and instance properties. Publishes events"," and subscribes to attribute change events to maintain internal state.",""," @method initializer"," @protected"," @since 3.5.0"," **/"," initializer: function () {"," var boundParseSortable = Y.bind('_parseSortable', this);",""," this._parseSortable();",""," this._setSortBy();",""," this._initSortFn();",""," this._initSortStrings();",""," this.after({"," 'table:renderHeader': Y.bind('_renderSortable', this),"," dataChange : Y.bind('_afterSortDataChange', this),"," sortByChange : Y.bind('_afterSortByChange', this),"," sortableChange : boundParseSortable,"," columnsChange : boundParseSortable"," });"," this.data.after(this.data.model.NAME + \":change\","," Y.bind('_afterSortRecordChange', this));",""," // TODO: this event needs magic, allowing async remote sorting"," this.publish('sort', {"," defaultFn: Y.bind('_defSortFn', this)"," });"," },",""," /**"," Creates a `_compare` function for the `data` ModelList to allow custom"," sorting by multiple fields.",""," @method _initSortFn"," @protected"," @since 3.5.0"," **/"," _initSortFn: function () {"," var self = this;",""," // TODO: This should be a ModelList extension."," // FIXME: Modifying a component of the host seems a little smelly"," // FIXME: Declaring inline override to leverage closure vs"," // compiling a new function for each column/sortable change or"," // binding the _compare implementation to this, resulting in an"," // extra function hop during sorting. Lesser of three evils?"," this.data._compare = function (a, b) {"," var cmp = 0,"," i, len, col, dir, aa, bb;",""," for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {"," col = self._sortBy[i];"," dir = col.sortDir;",""," if (col.sortFn) {"," cmp = col.sortFn(a, b, (dir === -1));"," } else {"," // FIXME? Requires columns without sortFns to have key"," aa = a.get(col.key) || '';"," bb = b.get(col.key) || '';",""," cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);"," }"," }",""," return cmp;"," };",""," if (this._sortBy.length) {"," this.data.comparator = this._sortComparator;",""," // TODO: is this necessary? Should it be elsewhere?"," this.data.sort();"," } else {"," // Leave the _compare method in place to avoid having to set it"," // up again. Mistake?"," delete this.data.comparator;"," }"," },",""," /**"," Add the sort related strings to the `strings` map.",""," @method _initSortStrings"," @protected"," @since 3.5.0"," **/"," _initSortStrings: function () {"," // Not a valueFn because other class extensions will want to add to it"," this.set('strings', Y.mix((this.get('strings') || {}),"," Y.Intl.get('datatable-sort')));"," },",""," /**"," Fires the `sort` event in response to user clicks on sortable column"," headers.",""," @method _onUITriggerSort"," @param {DOMEventFacade} e The `click` event"," @protected"," @since 3.5.0"," **/"," _onUITriggerSort: function (e) {"," var id = e.currentTarget.getAttribute('data-yui3-col-id'),"," sortBy = e.shiftKey ? this.get('sortBy') : [{}],"," column = id && this.getColumn(id),"," i, len;",""," if (e.type === 'keydown' && e.keyCode !== 32) {"," return;"," }",""," // In case a headerTemplate injected a link"," // TODO: Is this overreaching?"," e.preventDefault();",""," if (column) {"," if (e.shiftKey) {"," for (i = 0, len = sortBy.length; i < len; ++i) {"," if (id === sortBy[i] || Math.abs(sortBy[i][id]) === 1) {"," if (!isObject(sortBy[i])) {"," sortBy[i] = {};"," }",""," sortBy[i][id] = -(column.sortDir|0) || 1;"," break;"," }"," }",""," if (i >= len) {"," sortBy.push(column._id);"," }"," } else {"," sortBy[0][id] = -(column.sortDir|0) || 1;"," }",""," this.fire('sort', {"," originEvent: e,"," sortBy: sortBy"," });"," }"," },",""," /**"," Normalizes the possible input values for the `sortable` attribute, storing"," the results in the `_sortable` property.",""," @method _parseSortable"," @protected"," @since 3.5.0"," **/"," _parseSortable: function () {"," var sortable = this.get('sortable'),"," columns = [],"," i, len, col;",""," if (isArray(sortable)) {"," for (i = 0, len = sortable.length; i < len; ++i) {"," col = sortable[i];",""," // isArray is called because arrays are objects, but will rely"," // on getColumn to nullify them for the subsequent if (col)"," if (!isObject(col, true) || isArray(col)) {"," col = this.getColumn(col);"," }",""," if (col) {"," columns.push(col);"," }"," }"," } else if (sortable) {"," columns = this._displayColumns.slice();",""," if (sortable === 'auto') {"," for (i = columns.length - 1; i >= 0; --i) {"," if (!columns[i].sortable) {"," columns.splice(i, 1);"," }"," }"," }"," }",""," this._sortable = columns;"," },",""," /**"," Initial application of the sortable UI.",""," @method _renderSortable"," @protected"," @since 3.5.0"," **/"," _renderSortable: function () {"," this._uiSetSortable();",""," this._bindSortUI();"," },",""," /**"," Parses the current `sortBy` attribute into a normalized structure for the"," `data` ModelList's `_compare` method. Also updates the column"," configurations' `sortDir` properties.",""," @method _setSortBy"," @protected"," @since 3.5.0"," **/"," _setSortBy: function () {"," var columns = this._displayColumns,"," sortBy = this.get('sortBy') || [],"," sortedClass = ' ' + this.getClassName('sorted'),"," i, len, name, dir, field, column;",""," this._sortBy = [];",""," // Purge current sort state from column configs"," for (i = 0, len = columns.length; i < len; ++i) {"," column = columns[i];",""," delete column.sortDir;",""," if (column.className) {"," // TODO: be more thorough"," column.className = column.className.replace(sortedClass, '');"," }"," }",""," sortBy = toArray(sortBy);",""," for (i = 0, len = sortBy.length; i < len; ++i) {"," name = sortBy[i];"," dir = 1;",""," if (isObject(name)) {"," field = name;"," // Have to use a for-in loop to process sort({ foo: -1 })"," for (name in field) {"," if (field.hasOwnProperty(name)) {"," dir = dirMap[field[name]];"," break;"," }"," }"," }",""," if (name) {"," // Allow sorting of any model field and any column"," // FIXME: this isn't limited to model attributes, but there's no"," // convenient way to get a list of the attributes for a Model"," // subclass *including* the attributes of its superclasses."," column = this.getColumn(name) || { _id: name, key: name };",""," if (column) {"," column.sortDir = dir;",""," if (!column.className) {"," column.className = '';"," }",""," column.className += sortedClass;",""," this._sortBy.push(column);"," }"," }"," }"," },",""," /**"," Array of column configuration objects of those columns that need UI setup"," for user interaction.",""," @property _sortable"," @type {Object[]}"," @protected"," @since 3.5.0"," **/"," //_sortable: null,",""," /**"," Array of column configuration objects for those columns that are currently"," being used to sort the data. Fake column objects are used for fields that"," are not rendered as columns.",""," @property _sortBy"," @type {Object[]}"," @protected"," @since 3.5.0"," **/"," //_sortBy: null,",""," /**"," Replacement `comparator` for the `data` ModelList that defers sorting logic"," to the `_compare` method. The deferral is accomplished by returning `this`.",""," @method _sortComparator"," @param {Model} item The record being evaluated for sort position"," @return {Model} The record"," @protected"," @since 3.5.0"," **/"," _sortComparator: function (item) {"," // Defer sorting to ModelList's _compare"," return item;"," },",""," /**"," Applies the appropriate classes to the `boundingBox` and column headers to"," indicate sort state and sortability.",""," Also currently wraps the header content of sortable columns in a `<div>`"," liner to give a CSS anchor for sort indicators.",""," @method _uiSetSortable"," @protected"," @since 3.5.0"," **/"," _uiSetSortable: function () {"," var columns = this._sortable || [],"," sortableClass = this.getClassName('sortable', 'column'),"," ascClass = this.getClassName('sorted'),"," descClass = this.getClassName('sorted', 'desc'),"," linerClass = this.getClassName('sort', 'liner'),"," indicatorClass= this.getClassName('sort', 'indicator'),"," sortableCols = {},"," i, len, col, node, liner, title, desc;",""," this.get('boundingBox').toggleClass("," this.getClassName('sortable'),"," columns.length);",""," for (i = 0, len = columns.length; i < len; ++i) {"," sortableCols[columns[i].id] = columns[i];"," }",""," // TODO: this.head.render() + decorate cells?"," this._theadNode.all('.' + sortableClass).each(function (node) {"," var col = sortableCols[node.get('id')],"," liner = node.one('.' + linerClass),"," indicator;",""," if (col) {"," if (!col.sortDir) {"," node.removeClass(ascClass)"," .removeClass(descClass);"," }"," } else {"," node.removeClass(sortableClass)"," .removeClass(ascClass)"," .removeClass(descClass);",""," if (liner) {"," liner.replace(liner.get('childNodes').toFrag());"," }",""," indicator = node.one('.' + indicatorClass);",""," if (indicator) {"," indicator.remove().destroy(true);"," }"," }"," });",""," for (i = 0, len = columns.length; i < len; ++i) {"," col = columns[i];"," node = this._theadNode.one('#' + col.id);"," desc = col.sortDir === -1;",""," if (node) {"," liner = node.one('.' + linerClass);",""," node.addClass(sortableClass);",""," if (col.sortDir) {"," node.addClass(ascClass);",""," node.toggleClass(descClass, desc);",""," node.setAttribute('aria-sort', desc ?"," 'descending' : 'ascending');"," }",""," if (!liner) {"," liner = Y.Node.create(Y.Lang.sub("," this.SORTABLE_HEADER_TEMPLATE, {"," className: linerClass,"," indicatorClass: indicatorClass"," }));",""," liner.prepend(node.get('childNodes').toFrag());",""," node.append(liner);"," }",""," title = sub(this.getString("," (col.sortDir === 1) ? 'reverseSortBy' : 'sortBy'), {"," column: col.abbr || col.label ||"," col.key || ('column ' + i)"," });",""," node.setAttribute('title', title);"," // To combat VoiceOver from reading the sort title as the"," // column header"," node.setAttribute('aria-labelledby', col.id);"," }"," }"," },",""," /**"," Allows values `true`, `false`, \"auto\", or arrays of column names through.",""," @method _validateSortable"," @param {Any} val The input value to `set(\"sortable\", VAL)`"," @return {Boolean}"," @protected"," @since 3.5.0"," **/"," _validateSortable: function (val) {"," return val === 'auto' || isBoolean(val) || isArray(val);"," },",""," /**"," Allows strings, arrays of strings, objects, or arrays of objects.",""," @method _validateSortBy"," @param {String|String[]|Object|Object[]} val The new `sortBy` value"," @return {Boolean}"," @protected"," @since 3.5.0"," **/"," _validateSortBy: function (val) {"," return val === null ||"," isString(val) ||"," isObject(val, true) ||"," (isArray(val) && (isString(val[0]) || isObject(val, true)));"," }","","}, true);","","Y.DataTable.Sortable = Sortable;","","Y.Base.mix(Y.DataTable, [Sortable]);","","","}, '@VERSION@', {\"requires\": [\"datatable-base\"], \"lang\": [\"en\"], \"skinnable\": true});"];
-_yuitest_coverage["build/datatable-sort/datatable-sort.js"].lines = {"1":0,"11":0,"108":0,"110":0,"173":0,"215":0,"246":0,"251":0,"252":0,"253":0,"254":0,"257":0,"258":0,"260":0,"261":0,"262":0,"264":0,"265":0,"266":0,"267":0,"272":0,"273":0,"274":0,"275":0,"276":0,"282":0,"303":0,"306":0,"307":0,"308":0,"311":0,"329":0,"330":0,"344":0,"346":0,"347":0,"348":0,"349":0,"363":0,"365":0,"366":0,"371":0,"372":0,"387":0,"420":0,"423":0,"426":0,"427":0,"429":0,"430":0,"431":0,"438":0,"440":0,"453":0,"455":0,"457":0,"459":0,"461":0,"463":0,"470":0,"474":0,"488":0,"496":0,"497":0,"500":0,"501":0,"502":0,"504":0,"505":0,"508":0,"509":0,"511":0,"515":0,"518":0,"519":0,"522":0,"526":0,"539":0,"553":0,"558":0,"559":0,"564":0,"566":0,"567":0,"568":0,"569":0,"570":0,"571":0,"574":0,"575":0,"579":0,"580":0,"583":0,"586":0,"602":0,"606":0,"607":0,"608":0,"612":0,"613":0,"616":0,"617":0,"620":0,"621":0,"623":0,"624":0,"625":0,"626":0,"632":0,"643":0,"645":0,"658":0,"663":0,"666":0,"667":0,"669":0,"671":0,"673":0,"677":0,"679":0,"680":0,"681":0,"683":0,"684":0,"686":0,"687":0,"688":0,"689":0,"694":0,"699":0,"701":0,"702":0,"704":0,"705":0,"708":0,"710":0,"751":0,"766":0,"775":0,"779":0,"780":0,"784":0,"785":0,"789":0,"790":0,"791":0,"795":0,"799":0,"800":0,"803":0,"805":0,"806":0,"811":0,"812":0,"813":0,"814":0,"816":0,"817":0,"819":0,"821":0,"822":0,"824":0,"826":0,"830":0,"831":0,"837":0,"839":0,"842":0,"848":0,"851":0,"866":0,"879":0,"887":0,"889":0};
-_yuitest_coverage["build/datatable-sort/datatable-sort.js"].functions = {"Sortable:108":0,"sort:202":0,"toggleSort:245":0,"_afterSortByChange:298":0,"_afterSortDataChange:324":0,"_afterSortRecordChange:343":0,"_bindSortUI:362":0,"_defSortFn:386":0,"_getSortBy:419":0,"initializer:452":0,"_compare:496":0,"_initSortFn:487":0,"_initSortStrings:537":0,"_onUITriggerSort:552":0,"_parseSortable:601":0,"_renderSortable:642":0,"_setSortBy:657":0,"_sortComparator:749":0,"(anonymous 2):784":0,"_uiSetSortable:765":0,"_validateSortable:865":0,"_validateSortBy:878":0,"(anonymous 1):1":0};
-_yuitest_coverage["build/datatable-sort/datatable-sort.js"].coveredLines = 174;
+_yuitest_coverage["build/datatable-sort/datatable-sort.js"].code=["YUI.add('datatable-sort', function (Y, NAME) {","","/**","Adds support for sorting the table data by API methods `table.sort(...)` or","`table.toggleSort(...)` or by clicking on column headers in the rendered UI.","","@module datatable","@submodule datatable-sort","@since 3.5.0","**/","var YLang = Y.Lang,"," isBoolean = YLang.isBoolean,"," isString = YLang.isString,"," isArray = YLang.isArray,"," isObject = YLang.isObject,",""," toArray = Y.Array,"," sub = YLang.sub,",""," dirMap = {"," asc : 1,"," desc: -1,"," \"1\" : 1,"," \"-1\": -1"," };","","","/**","_API docs for this extension are included in the DataTable class._","","This DataTable class extension adds support for sorting the table data by API","methods `table.sort(...)` or `table.toggleSort(...)` or by clicking on column","headers in the rendered UI.","","Sorting by the API is enabled automatically when this module is `use()`d. To","enable UI triggered sorting, set the DataTable's `sortable` attribute to","`true`.","","<pre><code>","var table = new Y.DataTable({"," columns: [ 'id', 'username', 'name', 'birthdate' ],"," data: [ ... ],"," sortable: true","});","","table.render('#table');","</code></pre>","","Setting `sortable` to `true` will enable UI sorting for all columns. To enable","UI sorting for certain columns only, set `sortable` to an array of column keys,","or just add `sortable: true` to the respective column configuration objects.","This uses the default setting of `sortable: auto` for the DataTable instance.","","<pre><code>","var table = new Y.DataTable({"," columns: ["," 'id',"," { key: 'username', sortable: true },"," { key: 'name', sortable: true },"," { key: 'birthdate', sortable: true }"," ],"," data: [ ... ]"," // sortable: 'auto' is the default","});","","// OR","var table = new Y.DataTable({"," columns: [ 'id', 'username', 'name', 'birthdate' ],"," data: [ ... ],"," sortable: [ 'username', 'name', 'birthdate' ]","});","</code></pre>","","To disable UI sorting for all columns, set `sortable` to `false`. This still","permits sorting via the API methods.","","As new records are inserted into the table's `data` ModelList, they will be inserted at the correct index to preserve the sort order.","","The current sort order is stored in the `sortBy` attribute. Assigning this value at instantiation will automatically sort your data.","","Sorting is done by a simple value comparison using &lt; and &gt; on the field","value. If you need custom sorting, add a sort function in the column's","`sortFn` property. Columns whose content is generated by formatters, but don't","relate to a single `key`, require a `sortFn` to be sortable.","","<pre><code>","function nameSort(a, b, desc) {"," var aa = a.get('lastName') + a.get('firstName'),"," bb = a.get('lastName') + b.get('firstName'),"," order = (aa > bb) ? 1 : -(aa < bb);",""," return desc ? -order : order;","}","","var table = new Y.DataTable({"," columns: [ 'id', 'username', { key: name, sortFn: nameSort }, 'birthdate' ],"," data: [ ... ],"," sortable: [ 'username', 'name', 'birthdate' ]","});","</code></pre>","","See the user guide for more details.","","@class DataTable.Sortable","@for DataTable","@since 3.5.0","**/","function Sortable() {}","","Sortable.ATTRS = {"," // Which columns in the UI should suggest and respond to sorting interaction"," // pass an empty array if no UI columns should show sortable, but you want the"," // table.sort(...) API"," /**"," Controls which column headers can trigger sorting by user clicks.",""," Acceptable values are:",""," * \"auto\" - (default) looks for `sortable: true` in the column configurations"," * `true` - all columns are enabled"," * `false - no UI sortable is enabled"," * {String[]} - array of key names to give sortable headers",""," @attribute sortable"," @type {String|String[]|Boolean}"," @default \"auto\""," @since 3.5.0"," **/"," sortable: {"," value: 'auto',"," validator: '_validateSortable'"," },",""," /**"," The current sort configuration to maintain in the data.",""," Accepts column `key` strings or objects with a single property, the column"," `key`, with a value of 1, -1, \"asc\", or \"desc\". E.g. `{ username: 'asc'"," }`. String values are assumed to be ascending.",""," Example values would be:",""," * `\"username\"` - sort by the data's `username` field or the `key`"," associated to a column with that `name`."," * `{ username: \"desc\" }` - sort by `username` in descending order."," Alternately, use values \"asc\", 1 (same as \"asc\"), or -1 (same as \"desc\")."," * `[\"lastName\", \"firstName\"]` - ascending sort by `lastName`, but for"," records with the same `lastName`, ascending subsort by `firstName`."," Array can have as many items as you want."," * `[{ lastName: -1 }, \"firstName\"]` - descending sort by `lastName`,"," ascending subsort by `firstName`. Mixed types are ok.",""," @attribute sortBy"," @type {String|String[]|Object|Object[]}"," @since 3.5.0"," **/"," sortBy: {"," validator: '_validateSortBy',"," getter: '_getSortBy'"," },",""," /**"," Strings containing language for sorting tooltips.",""," @attribute strings"," @type {Object}"," @default (strings for current lang configured in the YUI instance config)"," @since 3.5.0"," **/"," strings: {}","};","","Y.mix(Sortable.prototype, {",""," /**"," Sort the data in the `data` ModelList and refresh the table with the new"," order.",""," Acceptable values for `fields` are `key` strings or objects with a single"," property, the column `key`, with a value of 1, -1, \"asc\", or \"desc\". E.g."," `{ username: 'asc' }`. String values are assumed to be ascending.",""," Example values would be:",""," * `\"username\"` - sort by the data's `username` field or the `key`"," associated to a column with that `name`."," * `{ username: \"desc\" }` - sort by `username` in descending order."," Alternately, use values \"asc\", 1 (same as \"asc\"), or -1 (same as \"desc\")."," * `[\"lastName\", \"firstName\"]` - ascending sort by `lastName`, but for"," records with the same `lastName`, ascending subsort by `firstName`."," Array can have as many items as you want."," * `[{ lastName: -1 }, \"firstName\"]` - descending sort by `lastName`,"," ascending subsort by `firstName`. Mixed types are ok.",""," @method sort"," @param {String|String[]|Object|Object[]} fields The field(s) to sort by"," @param {Object} [payload] Extra `sort` event payload you want to send along"," @return {DataTable}"," @chainable"," @since 3.5.0"," **/"," sort: function (fields, payload) {"," /**"," Notifies of an impending sort, either from clicking on a column"," header, or from a call to the `sort` or `toggleSort` method.",""," The requested sort is available in the `sortBy` property of the event.",""," The default behavior of this event sets the table's `sortBy` attribute.",""," @event sort"," @param {String|String[]|Object|Object[]} sortBy The requested sort"," @preventable _defSortFn"," **/"," return this.fire('sort', Y.merge((payload || {}), {"," sortBy: fields || this.get('sortBy')"," }));"," },",""," /**"," Template for the node that will wrap the header content for sortable"," columns.",""," @property SORTABLE_HEADER_TEMPLATE"," @type {HTML}"," @value '<div class=\"{className}\" tabindex=\"0\"><span class=\"{indicatorClass}\"></span></div>'"," @since 3.5.0"," **/"," SORTABLE_HEADER_TEMPLATE: '<div class=\"{className}\" tabindex=\"0\"><span class=\"{indicatorClass}\"></span></div>',",""," /**"," Reverse the current sort direction of one or more fields currently being"," sorted by.",""," Pass the `key` of the column or columns you want the sort order reversed"," for.",""," @method toggleSort"," @param {String|String[]} fields The field(s) to reverse sort order for"," @param {Object} [payload] Extra `sort` event payload you want to send along"," @return {DataTable}"," @chainable"," @since 3.5.0"," **/"," toggleSort: function (columns, payload) {"," var current = this._sortBy,"," sortBy = [],"," i, len, j, col, index;",""," // To avoid updating column configs or sortBy directly"," for (i = 0, len = current.length; i < len; ++i) {"," col = {};"," col[current[i]._id] = current[i].sortDir;"," sortBy.push(col);"," }",""," if (columns) {"," columns = toArray(columns);",""," for (i = 0, len = columns.length; i < len; ++i) {"," col = columns[i];"," index = -1;",""," for (j = sortBy.length - 1; i >= 0; --i) {"," if (sortBy[j][col]) {"," sortBy[j][col] *= -1;"," break;"," }"," }"," }"," } else {"," for (i = 0, len = sortBy.length; i < len; ++i) {"," for (col in sortBy[i]) {"," if (sortBy[i].hasOwnProperty(col)) {"," sortBy[i][col] *= -1;"," break;"," }"," }"," }"," }",""," return this.fire('sort', Y.merge((payload || {}), {"," sortBy: sortBy"," }));"," },",""," //--------------------------------------------------------------------------"," // Protected properties and methods"," //--------------------------------------------------------------------------"," /**"," Sorts the `data` ModelList based on the new `sortBy` configuration.",""," @method _afterSortByChange"," @param {EventFacade} e The `sortByChange` event"," @protected"," @since 3.5.0"," **/"," _afterSortByChange: function (e) {"," // Can't use a setter because it's a chicken and egg problem. The"," // columns need to be set up to translate, but columns are initialized"," // from Core's initializer. So construction-time assignment would"," // fail."," this._setSortBy();",""," // Don't sort unless sortBy has been set"," if (this._sortBy.length) {"," if (!this.data.comparator) {"," this.data.comparator = this._sortComparator;"," }",""," this.data.sort();"," }"," },",""," /**"," Applies the sorting logic to the new ModelList if the `newVal` is a new"," ModelList.",""," @method _afterSortDataChange"," @param {EventFacade} e the `dataChange` event"," @protected"," @since 3.5.0"," **/"," _afterSortDataChange: function (e) {"," // object values always trigger a change event, but we only want to"," // call _initSortFn if the value passed to the `data` attribute was a"," // new ModelList, not a set of new data as an array, or even the same"," // ModelList."," if (e.prevVal !== e.newVal || e.newVal.hasOwnProperty('_compare')) {"," this._initSortFn();"," }"," },",""," /**"," Checks if any of the fields in the modified record are fields that are"," currently being sorted by, and if so, resorts the `data` ModelList.",""," @method _afterSortRecordChange"," @param {EventFacade} e The Model's `change` event"," @protected"," @since 3.5.0"," **/"," _afterSortRecordChange: function (e) {"," var i, len;",""," for (i = 0, len = this._sortBy.length; i < len; ++i) {"," if (e.changed[this._sortBy[i].key]) {"," this.data.sort();"," break;"," }"," }"," },",""," /**"," Subscribes to state changes that warrant updating the UI, and adds the"," click handler for triggering the sort operation from the UI.",""," @method _bindSortUI"," @protected"," @since 3.5.0"," **/"," _bindSortUI: function () {"," var handles = this._eventHandles;",""," if (!handles.sortAttrs) {"," handles.sortAttrs = this.after("," ['sortableChange', 'sortByChange', 'columnsChange'],"," Y.bind('_uiSetSortable', this));"," }",""," if (!handles.sortUITrigger && this._theadNode) {"," handles.sortUITrigger = this.delegate(['click','keydown'],"," Y.rbind('_onUITriggerSort', this),"," '.' + this.getClassName('sortable', 'column'));"," }"," },",""," /**"," Sets the `sortBy` attribute from the `sort` event's `e.sortBy` value.",""," @method _defSortFn"," @param {EventFacade} e The `sort` event"," @protected"," @since 3.5.0"," **/"," _defSortFn: function (e) {"," this.set.apply(this, ['sortBy', e.sortBy].concat(e.details));"," },",""," /**"," Getter for the `sortBy` attribute.",""," Supports the special subattribute \"sortBy.state\" to get a normalized JSON"," version of the current sort state. Otherwise, returns the last assigned"," value.",""," For example:",""," <pre><code>var table = new Y.DataTable({"," columns: [ ... ],"," data: [ ... ],"," sortBy: 'username'"," });",""," table.get('sortBy'); // 'username'"," table.get('sortBy.state'); // { key: 'username', dir: 1 }",""," table.sort(['lastName', { firstName: \"desc\" }]);"," table.get('sortBy'); // ['lastName', { firstName: \"desc\" }]"," table.get('sortBy.state'); // [{ key: \"lastName\", dir: 1 }, { key: \"firstName\", dir: -1 }]"," </code></pre>",""," @method _getSortBy"," @param {String|String[]|Object|Object[]} val The current sortBy value"," @param {String} detail String passed to `get(HERE)`. to parse subattributes"," @protected"," @since 3.5.0"," **/"," _getSortBy: function (val, detail) {"," var state, i, len, col;",""," // \"sortBy.\" is 7 characters. Used to catch"," detail = detail.slice(7);",""," // TODO: table.get('sortBy.asObject')? table.get('sortBy.json')?"," if (detail === 'state') {"," state = [];",""," for (i = 0, len = this._sortBy.length; i < len; ++i) {"," col = this._sortBy[i];"," state.push({"," column: col._id,"," dir: col.sortDir"," });"," }",""," // TODO: Always return an array?"," return { state: (state.length === 1) ? state[0] : state };"," } else {"," return val;"," }"," },",""," /**"," Sets up the initial sort state and instance properties. Publishes events"," and subscribes to attribute change events to maintain internal state.",""," @method initializer"," @protected"," @since 3.5.0"," **/"," initializer: function () {"," var boundParseSortable = Y.bind('_parseSortable', this);",""," this._parseSortable();",""," this._setSortBy();",""," this._initSortFn();",""," this._initSortStrings();",""," this.after({"," 'table:renderHeader': Y.bind('_renderSortable', this),"," dataChange : Y.bind('_afterSortDataChange', this),"," sortByChange : Y.bind('_afterSortByChange', this),"," sortableChange : boundParseSortable,"," columnsChange : boundParseSortable"," });"," this.data.after(this.data.model.NAME + \":change\","," Y.bind('_afterSortRecordChange', this));",""," // TODO: this event needs magic, allowing async remote sorting"," this.publish('sort', {"," defaultFn: Y.bind('_defSortFn', this)"," });"," },",""," /**"," Creates a `_compare` function for the `data` ModelList to allow custom"," sorting by multiple fields.",""," @method _initSortFn"," @protected"," @since 3.5.0"," **/"," _initSortFn: function () {"," var self = this;",""," // TODO: This should be a ModelList extension."," // FIXME: Modifying a component of the host seems a little smelly"," // FIXME: Declaring inline override to leverage closure vs"," // compiling a new function for each column/sortable change or"," // binding the _compare implementation to this, resulting in an"," // extra function hop during sorting. Lesser of three evils?"," this.data._compare = function (a, b) {"," var cmp = 0,"," i, len, col, dir, cs, aa, bb;",""," for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {"," col = self._sortBy[i];"," dir = col.sortDir,"," cs = col.caseSensitive;",""," if (col.sortFn) {"," cmp = col.sortFn(a, b, (dir === -1));"," } else {"," // FIXME? Requires columns without sortFns to have key"," aa = a.get(col.key) || '';"," bb = b.get(col.key) || '';"," if (!cs && typeof(aa) === \"string\" && typeof(bb) === \"string\"){// Not case sensitive"," aa = aa.toLowerCase();"," bb = bb.toLowerCase();"," }"," cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);"," }"," }",""," return cmp;"," };",""," if (this._sortBy.length) {"," this.data.comparator = this._sortComparator;",""," // TODO: is this necessary? Should it be elsewhere?"," this.data.sort();"," } else {"," // Leave the _compare method in place to avoid having to set it"," // up again. Mistake?"," delete this.data.comparator;"," }"," },",""," /**"," Add the sort related strings to the `strings` map.",""," @method _initSortStrings"," @protected"," @since 3.5.0"," **/"," _initSortStrings: function () {"," // Not a valueFn because other class extensions will want to add to it"," this.set('strings', Y.mix((this.get('strings') || {}),"," Y.Intl.get('datatable-sort')));"," },",""," /**"," Fires the `sort` event in response to user clicks on sortable column"," headers.",""," @method _onUITriggerSort"," @param {DOMEventFacade} e The `click` event"," @protected"," @since 3.5.0"," **/"," _onUITriggerSort: function (e) {"," var id = e.currentTarget.getAttribute('data-yui3-col-id'),"," sortBy = e.shiftKey ? this.get('sortBy') : [{}],"," column = id && this.getColumn(id),"," i, len;",""," if (e.type === 'keydown' && e.keyCode !== 32) {"," return;"," }",""," // In case a headerTemplate injected a link"," // TODO: Is this overreaching?"," e.preventDefault();",""," if (column) {"," if (e.shiftKey) {"," for (i = 0, len = sortBy.length; i < len; ++i) {"," if (id === sortBy[i] || Math.abs(sortBy[i][id]) === 1) {"," if (!isObject(sortBy[i])) {"," sortBy[i] = {};"," }",""," sortBy[i][id] = -(column.sortDir|0) || 1;"," break;"," }"," }",""," if (i >= len) {"," sortBy.push(column._id);"," }"," } else {"," sortBy[0][id] = -(column.sortDir|0) || 1;"," }",""," this.fire('sort', {"," originEvent: e,"," sortBy: sortBy"," });"," }"," },",""," /**"," Normalizes the possible input values for the `sortable` attribute, storing"," the results in the `_sortable` property.",""," @method _parseSortable"," @protected"," @since 3.5.0"," **/"," _parseSortable: function () {"," var sortable = this.get('sortable'),"," columns = [],"," i, len, col;",""," if (isArray(sortable)) {"," for (i = 0, len = sortable.length; i < len; ++i) {"," col = sortable[i];",""," // isArray is called because arrays are objects, but will rely"," // on getColumn to nullify them for the subsequent if (col)"," if (!isObject(col, true) || isArray(col)) {"," col = this.getColumn(col);"," }",""," if (col) {"," columns.push(col);"," }"," }"," } else if (sortable) {"," columns = this._displayColumns.slice();",""," if (sortable === 'auto') {"," for (i = columns.length - 1; i >= 0; --i) {"," if (!columns[i].sortable) {"," columns.splice(i, 1);"," }"," }"," }"," }",""," this._sortable = columns;"," },",""," /**"," Initial application of the sortable UI.",""," @method _renderSortable"," @protected"," @since 3.5.0"," **/"," _renderSortable: function () {"," this._uiSetSortable();",""," this._bindSortUI();"," },",""," /**"," Parses the current `sortBy` attribute into a normalized structure for the"," `data` ModelList's `_compare` method. Also updates the column"," configurations' `sortDir` properties.",""," @method _setSortBy"," @protected"," @since 3.5.0"," **/"," _setSortBy: function () {"," var columns = this._displayColumns,"," sortBy = this.get('sortBy') || [],"," sortedClass = ' ' + this.getClassName('sorted'),"," i, len, name, dir, field, column;",""," this._sortBy = [];",""," // Purge current sort state from column configs"," for (i = 0, len = columns.length; i < len; ++i) {"," column = columns[i];",""," delete column.sortDir;",""," if (column.className) {"," // TODO: be more thorough"," column.className = column.className.replace(sortedClass, '');"," }"," }",""," sortBy = toArray(sortBy);",""," for (i = 0, len = sortBy.length; i < len; ++i) {"," name = sortBy[i];"," dir = 1;",""," if (isObject(name)) {"," field = name;"," // Have to use a for-in loop to process sort({ foo: -1 })"," for (name in field) {"," if (field.hasOwnProperty(name)) {"," dir = dirMap[field[name]];"," break;"," }"," }"," }",""," if (name) {"," // Allow sorting of any model field and any column"," // FIXME: this isn't limited to model attributes, but there's no"," // convenient way to get a list of the attributes for a Model"," // subclass *including* the attributes of its superclasses."," column = this.getColumn(name) || { _id: name, key: name };",""," if (column) {"," column.sortDir = dir;",""," if (!column.className) {"," column.className = '';"," }",""," column.className += sortedClass;",""," this._sortBy.push(column);"," }"," }"," }"," },",""," /**"," Array of column configuration objects of those columns that need UI setup"," for user interaction.",""," @property _sortable"," @type {Object[]}"," @protected"," @since 3.5.0"," **/"," //_sortable: null,",""," /**"," Array of column configuration objects for those columns that are currently"," being used to sort the data. Fake column objects are used for fields that"," are not rendered as columns.",""," @property _sortBy"," @type {Object[]}"," @protected"," @since 3.5.0"," **/"," //_sortBy: null,",""," /**"," Replacement `comparator` for the `data` ModelList that defers sorting logic"," to the `_compare` method. The deferral is accomplished by returning `this`.",""," @method _sortComparator"," @param {Model} item The record being evaluated for sort position"," @return {Model} The record"," @protected"," @since 3.5.0"," **/"," _sortComparator: function (item) {"," // Defer sorting to ModelList's _compare"," return item;"," },",""," /**"," Applies the appropriate classes to the `boundingBox` and column headers to"," indicate sort state and sortability.",""," Also currently wraps the header content of sortable columns in a `<div>`"," liner to give a CSS anchor for sort indicators.",""," @method _uiSetSortable"," @protected"," @since 3.5.0"," **/"," _uiSetSortable: function () {"," var columns = this._sortable || [],"," sortableClass = this.getClassName('sortable', 'column'),"," ascClass = this.getClassName('sorted'),"," descClass = this.getClassName('sorted', 'desc'),"," linerClass = this.getClassName('sort', 'liner'),"," indicatorClass= this.getClassName('sort', 'indicator'),"," sortableCols = {},"," i, len, col, node, liner, title, desc;",""," this.get('boundingBox').toggleClass("," this.getClassName('sortable'),"," columns.length);",""," for (i = 0, len = columns.length; i < len; ++i) {"," sortableCols[columns[i].id] = columns[i];"," }",""," // TODO: this.head.render() + decorate cells?"," this._theadNode.all('.' + sortableClass).each(function (node) {"," var col = sortableCols[node.get('id')],"," liner = node.one('.' + linerClass),"," indicator;",""," if (col) {"," if (!col.sortDir) {"," node.removeClass(ascClass)"," .removeClass(descClass);"," }"," } else {"," node.removeClass(sortableClass)"," .removeClass(ascClass)"," .removeClass(descClass);",""," if (liner) {"," liner.replace(liner.get('childNodes').toFrag());"," }",""," indicator = node.one('.' + indicatorClass);",""," if (indicator) {"," indicator.remove().destroy(true);"," }"," }"," });",""," for (i = 0, len = columns.length; i < len; ++i) {"," col = columns[i];"," node = this._theadNode.one('#' + col.id);"," desc = col.sortDir === -1;",""," if (node) {"," liner = node.one('.' + linerClass);",""," node.addClass(sortableClass);",""," if (col.sortDir) {"," node.addClass(ascClass);",""," node.toggleClass(descClass, desc);",""," node.setAttribute('aria-sort', desc ?"," 'descending' : 'ascending');"," }",""," if (!liner) {"," liner = Y.Node.create(Y.Lang.sub("," this.SORTABLE_HEADER_TEMPLATE, {"," className: linerClass,"," indicatorClass: indicatorClass"," }));",""," liner.prepend(node.get('childNodes').toFrag());",""," node.append(liner);"," }",""," title = sub(this.getString("," (col.sortDir === 1) ? 'reverseSortBy' : 'sortBy'), {"," column: col.abbr || col.label ||"," col.key || ('column ' + i)"," });",""," node.setAttribute('title', title);"," // To combat VoiceOver from reading the sort title as the"," // column header"," node.setAttribute('aria-labelledby', col.id);"," }"," }"," },",""," /**"," Allows values `true`, `false`, \"auto\", or arrays of column names through.",""," @method _validateSortable"," @param {Any} val The input value to `set(\"sortable\", VAL)`"," @return {Boolean}"," @protected"," @since 3.5.0"," **/"," _validateSortable: function (val) {"," return val === 'auto' || isBoolean(val) || isArray(val);"," },",""," /**"," Allows strings, arrays of strings, objects, or arrays of objects.",""," @method _validateSortBy"," @param {String|String[]|Object|Object[]} val The new `sortBy` value"," @return {Boolean}"," @protected"," @since 3.5.0"," **/"," _validateSortBy: function (val) {"," return val === null ||"," isString(val) ||"," isObject(val, true) ||"," (isArray(val) && (isString(val[0]) || isObject(val, true)));"," }","","}, true);","","Y.DataTable.Sortable = Sortable;","","Y.Base.mix(Y.DataTable, [Sortable]);","","","}, '@VERSION@', {\"requires\": [\"datatable-base\"], \"lang\": [\"en\"], \"skinnable\": true});"];
+_yuitest_coverage["build/datatable-sort/datatable-sort.js"].lines = {"1":0,"11":0,"108":0,"110":0,"173":0,"215":0,"246":0,"251":0,"252":0,"253":0,"254":0,"257":0,"258":0,"260":0,"261":0,"262":0,"264":0,"265":0,"266":0,"267":0,"272":0,"273":0,"274":0,"275":0,"276":0,"282":0,"303":0,"306":0,"307":0,"308":0,"311":0,"329":0,"330":0,"344":0,"346":0,"347":0,"348":0,"349":0,"363":0,"365":0,"366":0,"371":0,"372":0,"387":0,"420":0,"423":0,"426":0,"427":0,"429":0,"430":0,"431":0,"438":0,"440":0,"453":0,"455":0,"457":0,"459":0,"461":0,"463":0,"470":0,"474":0,"488":0,"496":0,"497":0,"500":0,"501":0,"502":0,"505":0,"506":0,"509":0,"510":0,"511":0,"512":0,"513":0,"515":0,"519":0,"522":0,"523":0,"526":0,"530":0,"543":0,"557":0,"562":0,"563":0,"568":0,"570":0,"571":0,"572":0,"573":0,"574":0,"575":0,"578":0,"579":0,"583":0,"584":0,"587":0,"590":0,"606":0,"610":0,"611":0,"612":0,"616":0,"617":0,"620":0,"621":0,"624":0,"625":0,"627":0,"628":0,"629":0,"630":0,"636":0,"647":0,"649":0,"662":0,"667":0,"670":0,"671":0,"673":0,"675":0,"677":0,"681":0,"683":0,"684":0,"685":0,"687":0,"688":0,"690":0,"691":0,"692":0,"693":0,"698":0,"703":0,"705":0,"706":0,"708":0,"709":0,"712":0,"714":0,"755":0,"770":0,"779":0,"783":0,"784":0,"788":0,"789":0,"793":0,"794":0,"795":0,"799":0,"803":0,"804":0,"807":0,"809":0,"810":0,"815":0,"816":0,"817":0,"818":0,"820":0,"821":0,"823":0,"825":0,"826":0,"828":0,"830":0,"834":0,"835":0,"841":0,"843":0,"846":0,"852":0,"855":0,"870":0,"883":0,"891":0,"893":0};
+_yuitest_coverage["build/datatable-sort/datatable-sort.js"].functions = {"Sortable:108":0,"sort:202":0,"toggleSort:245":0,"_afterSortByChange:298":0,"_afterSortDataChange:324":0,"_afterSortRecordChange:343":0,"_bindSortUI:362":0,"_defSortFn:386":0,"_getSortBy:419":0,"initializer:452":0,"_compare:496":0,"_initSortFn:487":0,"_initSortStrings:541":0,"_onUITriggerSort:556":0,"_parseSortable:605":0,"_renderSortable:646":0,"_setSortBy:661":0,"_sortComparator:753":0,"(anonymous 2):788":0,"_uiSetSortable:769":0,"_validateSortable:869":0,"_validateSortBy:882":0,"(anonymous 1):1":0};
+_yuitest_coverage["build/datatable-sort/datatable-sort.js"].coveredLines = 177;
_yuitest_coverage["build/datatable-sort/datatable-sort.js"].coveredFunctions = 23;
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 1);
YUI.add('datatable-sort', function (Y, NAME) {
@@ -604,47 +604,54 @@ this.data._compare = function (a, b) {
_yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_compare", 496);
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 497);
var cmp = 0,
- i, len, col, dir, aa, bb;
+ i, len, col, dir, cs, aa, bb;
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 500);
for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 501);
col = self._sortBy[i];
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 502);
-dir = col.sortDir;
+dir = col.sortDir,
+ cs = col.caseSensitive;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 504);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 505);
if (col.sortFn) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 505);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 506);
cmp = col.sortFn(a, b, (dir === -1));
} else {
// FIXME? Requires columns without sortFns to have key
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 508);
-aa = a.get(col.key) || '';
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 509);
+aa = a.get(col.key) || '';
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 510);
bb = b.get(col.key) || '';
-
_yuitest_coverline("build/datatable-sort/datatable-sort.js", 511);
+if (!cs && typeof(aa) === "string" && typeof(bb) === "string"){// Not case sensitive
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 512);
+aa = aa.toLowerCase();
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 513);
+bb = bb.toLowerCase();
+ }
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 515);
cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
}
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 515);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 519);
return cmp;
};
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 518);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 522);
if (this._sortBy.length) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 519);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 523);
this.data.comparator = this._sortComparator;
// TODO: is this necessary? Should it be elsewhere?
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 522);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 526);
this.data.sort();
} else {
// Leave the _compare method in place to avoid having to set it
// up again. Mistake?
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 526);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 530);
delete this.data.comparator;
}
},
@@ -658,8 +665,8 @@ delete this.data.comparator;
**/
_initSortStrings: function () {
// Not a valueFn because other class extensions will want to add to it
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_initSortStrings", 537);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 539);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_initSortStrings", 541);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 543);
this.set('strings', Y.mix((this.get('strings') || {}),
Y.Intl.get('datatable-sort')));
},
@@ -674,56 +681,56 @@ this.set('strings', Y.mix((this.get('strings') || {}),
@since 3.5.0
**/
_onUITriggerSort: function (e) {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_onUITriggerSort", 552);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 553);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_onUITriggerSort", 556);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 557);
var id = e.currentTarget.getAttribute('data-yui3-col-id'),
sortBy = e.shiftKey ? this.get('sortBy') : [{}],
column = id && this.getColumn(id),
i, len;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 558);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 562);
if (e.type === 'keydown' && e.keyCode !== 32) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 559);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 563);
return;
}
// In case a headerTemplate injected a link
// TODO: Is this overreaching?
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 564);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 568);
e.preventDefault();
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 566);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 570);
if (column) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 567);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 571);
if (e.shiftKey) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 568);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 572);
for (i = 0, len = sortBy.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 569);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 573);
if (id === sortBy[i] || Math.abs(sortBy[i][id]) === 1) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 570);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 574);
if (!isObject(sortBy[i])) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 571);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 575);
sortBy[i] = {};
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 574);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 578);
sortBy[i][id] = -(column.sortDir|0) || 1;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 575);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 579);
break;
}
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 579);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 583);
if (i >= len) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 580);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 584);
sortBy.push(column._id);
}
} else {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 583);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 587);
sortBy[0][id] = -(column.sortDir|0) || 1;
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 586);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 590);
this.fire('sort', {
originEvent: e,
sortBy: sortBy
@@ -740,52 +747,52 @@ this.fire('sort', {
@since 3.5.0
**/
_parseSortable: function () {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_parseSortable", 601);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 602);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_parseSortable", 605);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 606);
var sortable = this.get('sortable'),
columns = [],
i, len, col;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 606);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 610);
if (isArray(sortable)) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 607);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 611);
for (i = 0, len = sortable.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 608);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 612);
col = sortable[i];
// isArray is called because arrays are objects, but will rely
// on getColumn to nullify them for the subsequent if (col)
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 612);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 616);
if (!isObject(col, true) || isArray(col)) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 613);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 617);
col = this.getColumn(col);
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 616);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 620);
if (col) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 617);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 621);
columns.push(col);
}
}
- } else {_yuitest_coverline("build/datatable-sort/datatable-sort.js", 620);
+ } else {_yuitest_coverline("build/datatable-sort/datatable-sort.js", 624);
if (sortable) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 621);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 625);
columns = this._displayColumns.slice();
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 623);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 627);
if (sortable === 'auto') {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 624);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 628);
for (i = columns.length - 1; i >= 0; --i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 625);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 629);
if (!columns[i].sortable) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 626);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 630);
columns.splice(i, 1);
}
}
}
}}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 632);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 636);
this._sortable = columns;
},
@@ -797,11 +804,11 @@ this._sortable = columns;
@since 3.5.0
**/
_renderSortable: function () {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_renderSortable", 642);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 643);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_renderSortable", 646);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 647);
this._uiSetSortable();
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 645);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 649);
this._bindSortUI();
},
@@ -815,84 +822,84 @@ this._bindSortUI();
@since 3.5.0
**/
_setSortBy: function () {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_setSortBy", 657);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 658);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_setSortBy", 661);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 662);
var columns = this._displayColumns,
sortBy = this.get('sortBy') || [],
sortedClass = ' ' + this.getClassName('sorted'),
i, len, name, dir, field, column;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 663);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 667);
this._sortBy = [];
// Purge current sort state from column configs
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 666);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 670);
for (i = 0, len = columns.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 667);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 671);
column = columns[i];
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 669);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 673);
delete column.sortDir;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 671);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 675);
if (column.className) {
// TODO: be more thorough
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 673);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 677);
column.className = column.className.replace(sortedClass, '');
}
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 677);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 681);
sortBy = toArray(sortBy);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 679);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 683);
for (i = 0, len = sortBy.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 680);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 684);
name = sortBy[i];
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 681);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 685);
dir = 1;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 683);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 687);
if (isObject(name)) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 684);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 688);
field = name;
// Have to use a for-in loop to process sort({ foo: -1 })
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 686);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 690);
for (name in field) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 687);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 691);
if (field.hasOwnProperty(name)) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 688);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 692);
dir = dirMap[field[name]];
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 689);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 693);
break;
}
}
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 694);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 698);
if (name) {
// Allow sorting of any model field and any column
// FIXME: this isn't limited to model attributes, but there's no
// convenient way to get a list of the attributes for a Model
// subclass *including* the attributes of its superclasses.
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 699);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 703);
column = this.getColumn(name) || { _id: name, key: name };
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 701);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 705);
if (column) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 702);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 706);
column.sortDir = dir;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 704);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 708);
if (!column.className) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 705);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 709);
column.className = '';
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 708);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 712);
column.className += sortedClass;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 710);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 714);
this._sortBy.push(column);
}
}
@@ -934,8 +941,8 @@ this._sortBy.push(column);
**/
_sortComparator: function (item) {
// Defer sorting to ModelList's _compare
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_sortComparator", 749);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 751);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_sortComparator", 753);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 755);
return item;
},
@@ -951,8 +958,8 @@ return item;
@since 3.5.0
**/
_uiSetSortable: function () {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_uiSetSortable", 765);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 766);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_uiSetSortable", 769);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 770);
var columns = this._sortable || [],
sortableClass = this.getClassName('sortable', 'column'),
ascClass = this.getClassName('sorted'),
@@ -962,115 +969,115 @@ var columns = this._sortable || [],
sortableCols = {},
i, len, col, node, liner, title, desc;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 775);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 779);
this.get('boundingBox').toggleClass(
this.getClassName('sortable'),
columns.length);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 779);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 783);
for (i = 0, len = columns.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 780);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 784);
sortableCols[columns[i].id] = columns[i];
}
// TODO: this.head.render() + decorate cells?
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 784);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 788);
this._theadNode.all('.' + sortableClass).each(function (node) {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "(anonymous 2)", 784);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 785);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "(anonymous 2)", 788);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 789);
var col = sortableCols[node.get('id')],
liner = node.one('.' + linerClass),
indicator;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 789);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 793);
if (col) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 790);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 794);
if (!col.sortDir) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 791);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 795);
node.removeClass(ascClass)
.removeClass(descClass);
}
} else {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 795);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 799);
node.removeClass(sortableClass)
.removeClass(ascClass)
.removeClass(descClass);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 799);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 803);
if (liner) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 800);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 804);
liner.replace(liner.get('childNodes').toFrag());
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 803);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 807);
indicator = node.one('.' + indicatorClass);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 805);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 809);
if (indicator) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 806);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 810);
indicator.remove().destroy(true);
}
}
});
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 811);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 815);
for (i = 0, len = columns.length; i < len; ++i) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 812);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 816);
col = columns[i];
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 813);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 817);
node = this._theadNode.one('#' + col.id);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 814);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 818);
desc = col.sortDir === -1;
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 816);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 820);
if (node) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 817);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 821);
liner = node.one('.' + linerClass);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 819);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 823);
node.addClass(sortableClass);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 821);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 825);
if (col.sortDir) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 822);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 826);
node.addClass(ascClass);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 824);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 828);
node.toggleClass(descClass, desc);
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 826);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 830);
node.setAttribute('aria-sort', desc ?
'descending' : 'ascending');
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 830);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 834);
if (!liner) {
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 831);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 835);
liner = Y.Node.create(Y.Lang.sub(
this.SORTABLE_HEADER_TEMPLATE, {
className: linerClass,
indicatorClass: indicatorClass
}));
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 837);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 841);
liner.prepend(node.get('childNodes').toFrag());
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 839);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 843);
node.append(liner);
}
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 842);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 846);
title = sub(this.getString(
(col.sortDir === 1) ? 'reverseSortBy' : 'sortBy'), {
column: col.abbr || col.label ||
col.key || ('column ' + i)
});
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 848);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 852);
node.setAttribute('title', title);
// To combat VoiceOver from reading the sort title as the
// column header
- _yuitest_coverline("build/datatable-sort/datatable-sort.js", 851);
+ _yuitest_coverline("build/datatable-sort/datatable-sort.js", 855);
node.setAttribute('aria-labelledby', col.id);
}
}
@@ -1086,8 +1093,8 @@ node.setAttribute('aria-labelledby', col.id);
@since 3.5.0
**/
_validateSortable: function (val) {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_validateSortable", 865);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 866);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_validateSortable", 869);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 870);
return val === 'auto' || isBoolean(val) || isArray(val);
},
@@ -1101,8 +1108,8 @@ return val === 'auto' || isBoolean(val) || isArray(val);
@since 3.5.0
**/
_validateSortBy: function (val) {
- _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_validateSortBy", 878);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 879);
+ _yuitest_coverfunc("build/datatable-sort/datatable-sort.js", "_validateSortBy", 882);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 883);
return val === null ||
isString(val) ||
isObject(val, true) ||
@@ -1111,10 +1118,10 @@ return val === null ||
}, true);
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 887);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 891);
Y.DataTable.Sortable = Sortable;
-_yuitest_coverline("build/datatable-sort/datatable-sort.js", 889);
+_yuitest_coverline("build/datatable-sort/datatable-sort.js", 893);
Y.Base.mix(Y.DataTable, [Sortable]);
View
10 build/datatable-sort/datatable-sort-debug.js
@@ -495,19 +495,23 @@ Y.mix(Sortable.prototype, {
// extra function hop during sorting. Lesser of three evils?
this.data._compare = function (a, b) {
var cmp = 0,
- i, len, col, dir, aa, bb;
+ i, len, col, dir, cs, aa, bb;
for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {
col = self._sortBy[i];
- dir = col.sortDir;
+ dir = col.sortDir,
+ cs = col.caseSensitive;
if (col.sortFn) {
cmp = col.sortFn(a, b, (dir === -1));
} else {
// FIXME? Requires columns without sortFns to have key
aa = a.get(col.key) || '';
bb = b.get(col.key) || '';
-
+ if (!cs && typeof(aa) === "string" && typeof(bb) === "string"){// Not case sensitive
+ aa = aa.toLowerCase();
+ bb = bb.toLowerCase();
+ }
cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
}
}
View
2 build/datatable-sort/datatable-sort-min.js
@@ -1 +1 @@
-YUI.add("datatable-sort",function(e,t){function l(){}var n=e.Lang,r=n.isBoolean,i=n.isString,s=n.isArray,o=n.isObject,u=e.Array,a=n.sub,f={asc:1,desc:-1,1:1,"-1":-1};l.ATTRS={sortable:{value:"auto",validator:"_validateSortable"},sortBy:{validator:"_validateSortBy",getter:"_getSortBy"},strings:{}},e.mix(l.prototype,{sort:function(t,n){return this.fire("sort",e.merge(n||{},{sortBy:t||this.get("sortBy")}))},SORTABLE_HEADER_TEMPLATE:'<div class="{className}" tabindex="0"><span class="{indicatorClass}"></span></div>',toggleSort:function(t,n){var r=this._sortBy,i=[],s,o,a,f,l;for(s=0,o=r.length;s<o;++s)f={},f[r[s]._id]=r[s].sortDir,i.push(f);if(t){t=u(t);for(s=0,o=t.length;s<o;++s){f=t[s],l=-1;for(a=i.length-1;s>=0;--s)if(i[a][f]){i[a][f]*=-1;break}}}else for(s=0,o=i.length;s<o;++s)for(f in i[s])if(i[s].hasOwnProperty(f)){i[s][f]*=-1;break}return this.fire("sort",e.merge(n||{},{sortBy:i}))},_afterSortByChange:function(e){this._setSortBy(),this._sortBy.length&&(this.data.comparator||(this.data.comparator=this._sortComparator),this.data.sort())},_afterSortDataChange:function(e){(e.prevVal!==e.newVal||e.newVal.hasOwnProperty("_compare"))&&this._initSortFn()},_afterSortRecordChange:function(e){var t,n;for(t=0,n=this._sortBy.length;t<n;++t)if(e.changed[this._sortBy[t].key]){this.data.sort();break}},_bindSortUI:function(){var t=this._eventHandles;t.sortAttrs||(t.sortAttrs=this.after(["sortableChange","sortByChange","columnsChange"],e.bind("_uiSetSortable",this))),!t.sortUITrigger&&this._theadNode&&(t.sortUITrigger=this.delegate(["click","keydown"],e.rbind("_onUITriggerSort",this),"."+this.getClassName("sortable","column")))},_defSortFn:function(e){this.set.apply(this,["sortBy",e.sortBy].concat(e.details))},_getSortBy:function(e,t){var n,r,i,s;t=t.slice(7);if(t==="state"){n=[];for(r=0,i=this._sortBy.length;r<i;++r)s=this._sortBy[r],n.push({column:s._id,dir:s.sortDir});return{state:n.length===1?n[0]:n}}return e},initializer:function(){var t=e.bind("_parseSortable",this);this._parseSortable(),this._setSortBy(),this._initSortFn(),this._initSortStrings(),this.after({"table:renderHeader":e.bind("_renderSortable",this),dataChange:e.bind("_afterSortDataChange",this),sortByChange:e.bind("_afterSortByChange",this),sortableChange:t,columnsChange:t}),this.data.after(this.data.model.NAME+":change",e.bind("_afterSortRecordChange",this)),this.publish("sort",{defaultFn:e.bind("_defSortFn",this)})},_initSortFn:function(){var e=this;this.data._compare=function(t,n){var r=0,i,s,o,u,a,f;for(i=0,s=e._sortBy.length;!r&&i<s;++i)o=e._sortBy[i],u=o.sortDir,o.sortFn?r=o.sortFn(t,n,u===-1):(a=t.get(o.key)||"",f=n.get(o.key)||"",r=a>f?u:a<f?-u:0);return r},this._sortBy.length?(this.data.comparator=this._sortComparator,this.data.sort()):delete this.data.comparator},_initSortStrings:function(){this.set("strings",e.mix(this.get("strings")||{},e.Intl.get("datatable-sort")))},_onUITriggerSort:function(e){var t=e.currentTarget.getAttribute("data-yui3-col-id"),n=e.shiftKey?this.get("sortBy"):[{}],r=t&&this.getColumn(t),i,s;if(e.type==="keydown"&&e.keyCode!==32)return;e.preventDefault();if(r){if(e.shiftKey){for(i=0,s=n.length;i<s;++i)if(t===n[i]||Math.abs(n[i][t])===1){o(n[i])||(n[i]={}),n[i][t]=-(r.sortDir|0)||1;break}i>=s&&n.push(r._id)}else n[0][t]=-(r.sortDir|0)||1;this.fire("sort",{originEvent:e,sortBy:n})}},_parseSortable:function(){var e=this.get("sortable"),t=[],n,r,i;if(s(e))for(n=0,r=e.length;n<r;++n){i=e[n];if(!o(i,!0)||s(i))i=this.getColumn(i);i&&t.push(i)}else if(e){t=this._displayColumns.slice();if(e==="auto")for(n=t.length-1;n>=0;--n)t[n].sortable||t.splice(n,1)}this._sortable=t},_renderSortable:function(){this._uiSetSortable(),this._bindSortUI()},_setSortBy:function(){var e=this._displayColumns,t=this.get("sortBy")||[],n=" "+this.getClassName("sorted"),r,i,s,a,l,c;this._sortBy=[];for(r=0,i=e.length;r<i;++r)c=e[r],delete c.sortDir,c.className&&(c.className=c.className.replace(n,""));t=u(t);for(r=0,i=t.length;r<i;++r){s=t[r],a=1;if(o(s)){l=s;for(s in l)if(l.hasOwnProperty(s)){a=f[l[s]];break}}s&&(c=this.getColumn(s)||{_id:s,key:s},c&&(c.sortDir=a,c.className||(c.className=""),c.className+=n,this._sortBy.push(c)))}},_sortComparator:function(e){return e},_uiSetSortable:function(){var t=this._sortable||[],n=this.getClassName("sortable","column"),r=this.getClassName("sorted"),i=this.getClassName("sorted","desc"),s=this.getClassName("sort","liner"),o=this.getClassName("sort","indicator"),u={},f,l,c,h,p,d,v;this.get("boundingBox").toggleClass(this.getClassName("sortable"),t.length);for(f=0,l=t.length;f<l;++f)u[t[f].id]=t[f];this._theadNode.all("."+n).each(function(e){var t=u[e.get("id")],a=e.one("."+s),f;t?t.sortDir||e.removeClass(r).removeClass(i):(e.removeClass(n).removeClass(r).removeClass(i),a&&a.replace(a.get("childNodes").toFrag()),f=e.one("."+o),f&&f.remove().destroy(!0))});for(f=0,l=t.length;f<l;++f)c=t[f],h=this._theadNode.one("#"+c.id),v=c.sortDir===-1,h&&(p=h.one("."+s),h.addClass(n),c.sortDir&&(h.addClass(r),h.toggleClass(i,v),h.setAttribute("aria-sort",v?"descending":"ascending")),p||(p=e.Node.create(e.Lang.sub(this.SORTABLE_HEADER_TEMPLATE,{className:s,indicatorClass:o})),p.prepend(h.get("childNodes").toFrag()),h.append(p)),d=a(this.getString(c.sortDir===1?"reverseSortBy":"sortBy"),{column:c.abbr||c.label||c.key||"column "+f}),h.setAttribute("title",d),h.setAttribute("aria-labelledby",c.id))},_validateSortable:function(e){return e==="auto"||r(e)||s(e)},_validateSortBy:function(e){return e===null||i(e)||o(e,!0)||s(e)&&(i(e[0])||o(e,!0))}},!0),e.DataTable.Sortable=l,e.Base.mix(e.DataTable,[l])},"@VERSION@",{requires:["datatable-base"],lang:["en"],skinnable:!0});
+YUI.add("datatable-sort",function(e,t){function l(){}var n=e.Lang,r=n.isBoolean,i=n.isString,s=n.isArray,o=n.isObject,u=e.Array,a=n.sub,f={asc:1,desc:-1,1:1,"-1":-1};l.ATTRS={sortable:{value:"auto",validator:"_validateSortable"},sortBy:{validator:"_validateSortBy",getter:"_getSortBy"},strings:{}},e.mix(l.prototype,{sort:function(t,n){return this.fire("sort",e.merge(n||{},{sortBy:t||this.get("sortBy")}))},SORTABLE_HEADER_TEMPLATE:'<div class="{className}" tabindex="0"><span class="{indicatorClass}"></span></div>',toggleSort:function(t,n){var r=this._sortBy,i=[],s,o,a,f,l;for(s=0,o=r.length;s<o;++s)f={},f[r[s]._id]=r[s].sortDir,i.push(f);if(t){t=u(t);for(s=0,o=t.length;s<o;++s){f=t[s],l=-1;for(a=i.length-1;s>=0;--s)if(i[a][f]){i[a][f]*=-1;break}}}else for(s=0,o=i.length;s<o;++s)for(f in i[s])if(i[s].hasOwnProperty(f)){i[s][f]*=-1;break}return this.fire("sort",e.merge(n||{},{sortBy:i}))},_afterSortByChange:function(e){this._setSortBy(),this._sortBy.length&&(this.data.comparator||(this.data.comparator=this._sortComparator),this.data.sort())},_afterSortDataChange:function(e){(e.prevVal!==e.newVal||e.newVal.hasOwnProperty("_compare"))&&this._initSortFn()},_afterSortRecordChange:function(e){var t,n;for(t=0,n=this._sortBy.length;t<n;++t)if(e.changed[this._sortBy[t].key]){this.data.sort();break}},_bindSortUI:function(){var t=this._eventHandles;t.sortAttrs||(t.sortAttrs=this.after(["sortableChange","sortByChange","columnsChange"],e.bind("_uiSetSortable",this))),!t.sortUITrigger&&this._theadNode&&(t.sortUITrigger=this.delegate(["click","keydown"],e.rbind("_onUITriggerSort",this),"."+this.getClassName("sortable","column")))},_defSortFn:function(e){this.set.apply(this,["sortBy",e.sortBy].concat(e.details))},_getSortBy:function(e,t){var n,r,i,s;t=t.slice(7);if(t==="state"){n=[];for(r=0,i=this._sortBy.length;r<i;++r)s=this._sortBy[r],n.push({column:s._id,dir:s.sortDir});return{state:n.length===1?n[0]:n}}return e},initializer:function(){var t=e.bind("_parseSortable",this);this._parseSortable(),this._setSortBy(),this._initSortFn(),this._initSortStrings(),this.after({"table:renderHeader":e.bind("_renderSortable",this),dataChange:e.bind("_afterSortDataChange",this),sortByChange:e.bind("_afterSortByChange",this),sortableChange:t,columnsChange:t}),this.data.after(this.data.model.NAME+":change",e.bind("_afterSortRecordChange",this)),this.publish("sort",{defaultFn:e.bind("_defSortFn",this)})},_initSortFn:function(){var e=this;this.data._compare=function(t,n){var r=0,i,s,o,u,a,f,l;for(i=0,s=e._sortBy.length;!r&&i<s;++i)o=e._sortBy[i],u=o.sortDir,a=o.caseSensitive,o.sortFn?r=o.sortFn(t,n,u===-1):(f=t.get(o.key)||"",l=n.get(o.key)||"",!a&&typeof f=="string"&&typeof l=="string"&&(f=f.toLowerCase(),l=l.toLowerCase()),r=f>l?u:f<l?-u:0);return r},this._sortBy.length?(this.data.comparator=this._sortComparator,this.data.sort()):delete this.data.comparator},_initSortStrings:function(){this.set("strings",e.mix(this.get("strings")||{},e.Intl.get("datatable-sort")))},_onUITriggerSort:function(e){var t=e.currentTarget.getAttribute("data-yui3-col-id"),n=e.shiftKey?this.get("sortBy"):[{}],r=t&&this.getColumn(t),i,s;if(e.type==="keydown"&&e.keyCode!==32)return;e.preventDefault();if(r){if(e.shiftKey){for(i=0,s=n.length;i<s;++i)if(t===n[i]||Math.abs(n[i][t])===1){o(n[i])||(n[i]={}),n[i][t]=-(r.sortDir|0)||1;break}i>=s&&n.push(r._id)}else n[0][t]=-(r.sortDir|0)||1;this.fire("sort",{originEvent:e,sortBy:n})}},_parseSortable:function(){var e=this.get("sortable"),t=[],n,r,i;if(s(e))for(n=0,r=e.length;n<r;++n){i=e[n];if(!o(i,!0)||s(i))i=this.getColumn(i);i&&t.push(i)}else if(e){t=this._displayColumns.slice();if(e==="auto")for(n=t.length-1;n>=0;--n)t[n].sortable||t.splice(n,1)}this._sortable=t},_renderSortable:function(){this._uiSetSortable(),this._bindSortUI()},_setSortBy:function(){var e=this._displayColumns,t=this.get("sortBy")||[],n=" "+this.getClassName("sorted"),r,i,s,a,l,c;this._sortBy=[];for(r=0,i=e.length;r<i;++r)c=e[r],delete c.sortDir,c.className&&(c.className=c.className.replace(n,""));t=u(t);for(r=0,i=t.length;r<i;++r){s=t[r],a=1;if(o(s)){l=s;for(s in l)if(l.hasOwnProperty(s)){a=f[l[s]];break}}s&&(c=this.getColumn(s)||{_id:s,key:s},c&&(c.sortDir=a,c.className||(c.className=""),c.className+=n,this._sortBy.push(c)))}},_sortComparator:function(e){return e},_uiSetSortable:function(){var t=this._sortable||[],n=this.getClassName("sortable","column"),r=this.getClassName("sorted"),i=this.getClassName("sorted","desc"),s=this.getClassName("sort","liner"),o=this.getClassName("sort","indicator"),u={},f,l,c,h,p,d,v;this.get("boundingBox").toggleClass(this.getClassName("sortable"),t.length);for(f=0,l=t.length;f<l;++f)u[t[f].id]=t[f];this._theadNode.all("."+n).each(function(e){var t=u[e.get("id")],a=e.one("."+s),f;t?t.sortDir||e.removeClass(r).removeClass(i):(e.removeClass(n).removeClass(r).removeClass(i),a&&a.replace(a.get("childNodes").toFrag()),f=e.one("."+o),f&&f.remove().destroy(!0))});for(f=0,l=t.length;f<l;++f)c=t[f],h=this._theadNode.one("#"+c.id),v=c.sortDir===-1,h&&(p=h.one("."+s),h.addClass(n),c.sortDir&&(h.addClass(r),h.toggleClass(i,v),h.setAttribute("aria-sort",v?"descending":"ascending")),p||(p=e.Node.create(e.Lang.sub(this.SORTABLE_HEADER_TEMPLATE,{className:s,indicatorClass:o})),p.prepend(h.get("childNodes").toFrag()),h.append(p)),d=a(this.getString(c.sortDir===1?"reverseSortBy":"sortBy"),{column:c.abbr||c.label||c.key||"column "+f}),h.setAttribute("title",d),h.setAttribute("aria-labelledby",c.id))},_validateSortable:function(e){return e==="auto"||r(e)||s(e)},_validateSortBy:function(e){return e===null||i(e)||o(e,!0)||s(e)&&(i(e[0])||o(e,!0))}},!0),e.DataTable.Sortable=l,e.Base.mix(e.DataTable,[l])},"@VERSION@",{requires:["datatable-base"],lang:["en"],skinnable:!0});
View
10 build/datatable-sort/datatable-sort.js
@@ -495,19 +495,23 @@ Y.mix(Sortable.prototype, {
// extra function hop during sorting. Lesser of three evils?
this.data._compare = function (a, b) {
var cmp = 0,
- i, len, col, dir, aa, bb;
+ i, len, col, dir, cs, aa, bb;
for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {
col = self._sortBy[i];
- dir = col.sortDir;
+ dir = col.sortDir,
+ cs = col.caseSensitive;
if (col.sortFn) {
cmp = col.sortFn(a, b, (dir === -1));
} else {
// FIXME? Requires columns without sortFns to have key
aa = a.get(col.key) || '';
bb = b.get(col.key) || '';
-
+ if (!cs && typeof(aa) === "string" && typeof(bb) === "string"){// Not case sensitive
+ aa = aa.toLowerCase();
+ bb = bb.toLowerCase();
+ }
cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
}
}
View
12 src/datatable/HISTORY.md
@@ -1,10 +1,18 @@
DataTable Change History
========================
+
@VERSION@
----------
+-----
+
+* Avoid processing columns if there aren't any to allow empty tables.
+ [Pull Request #176] [Mark Woon]
-* Pull Req: #176 - Avoid processing columns if there aren't any to allow empty tables [markwoon]
+* Default sort for text columns is now case insensitive. Added `caseSensitive`
+ attribute to table columns config. Setting `caseSensitive` to `true` will
+ bypass the case insensitive sort speeding up sort in large data sets, where
+ case insensitivity is not required. [Ticket #2532134] [Pull Request #281]
+ [clanceyp]
3.8.0
-----
View
59 src/datatable/docs/assets/datatable-sort-tests.js
@@ -46,6 +46,65 @@ YUI.add('datatable-sort-tests', function(Y) {
}
}));
+
+ /* sortable data types test */
+
+ var suiteSortable = new Y.Test.Suite('datatable-sort example test suite'),
+ tableSortableSelector = '#sortSensitive ',
+ ths = Y.all(tableSortableSelector + 'th'),
+ tds = Y.all(tableSortableSelector + 'td'),
+ trs = Y.all(tableSortableSelector + 'tr');
+
+
+
+
+ suiteSortable.add(new Y.Test.Case({
+ name: 'Example sortable tests',
+ 'test click to sort data types': function() {
+ Assert.areEqual('1', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 before sort');
+
+ ths.item(0).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('1', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after Number sort');
+
+ ths.item(0).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('4', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after Number sort');
+
+ ths.item(1).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('1', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after DATE sort');
+
+ ths.item(1).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('4', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after DATE sort');
+
+ // should be AaBbCcZz
+ ths.item(2).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('2', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after String sort');
+
+ ths.item(2).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('4', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after String sort');
+
+ // should be ABCZabcz
+ ths.item(3).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('1', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after String case sensitive sort');
+
+ ths.item(3).simulate('click');
+ tds = Y.all(tableSortableSelector + 'td'); // refresh the nodeList
+ Assert.areEqual('4', tds.item(0).getHTML(), ' - Wrong text in col 1 row 1 after String case sensitive sort');
+
+ ths.item(0).simulate('click');
+ }
+ }));
+
+
+
+
Y.Test.Runner.add(suite);
+ Y.Test.Runner.add(suiteSortable);
}, '', { requires: [ 'node', 'node-event-simulate' ] });
View
24 src/datatable/docs/index.mustache
@@ -1235,6 +1235,10 @@ YUI({ filter: 'raw' }).use('datatable-sort', function (Y) {
<p>
Disable header-click sorting by setting `sortable` to `false`.
</p>
+<p>
+ The default sort order is case insensitive, the sort order can be set to case sensitive
+ by using the `caseSensitive` attribute, see <a href="#column-config">Appendix A</a> below.
+</p>
<h4 id="customsort">Custom Sorting</h4>
@@ -2020,13 +2024,31 @@ pies.on('pie:slicesChange', function (e) {
user sorting by clicking on the header.
</p>
<p>
- If the instance's `sortable` attribute is set, this
+ If the instance's `key` attribute is not set, this
configuration is ignored.
</p>
</td>
<td>`datatable-sort`</td>
</tr>
<tr>
+ <td>caseSensitive</td>
+ <td>
+ ```
+ { key: 'lastLogin', sortable: true, caseSensitive: true }
+ ```
+
+ <p>
+ When the instance's `caseSensitive` attribute is set to
+ "true" the sort order is case sensitive (relevant to string columns only).
+ </p>
+ <p>
+ Case sensitive sort is marginally more efficient and should be considered
+ for large data sets when case insensitive sort is not required.
+ </p>
+ </td>
+ <td>`datatable-sort`</td>
+ </tr>
+ <tr>
<td>sortFn</td>
<td>
```
View
21 src/datatable/docs/partials/datatable-sort-source.mustache
@@ -1,5 +1,7 @@
<div id="sort" class="yui3-skin-sam dt-example"></div>
+<div id="sortSensitive" class="yui3-skin-sam dt-example"></div>
+
<div id="presorted" class="yui3-skin-sam dt-example"></div>
<div id="dblclick" class="yui3-skin-sam dt-example"></div>
@@ -11,6 +13,12 @@ YUI().use("datatable-sort", function (Y) {
{key:"Phone", label:"Not Sortable Column B"},
{key:"Contact", label:"Click to Sort Column C", sortable:true}
],
+ sortableCols = [
+ {key:"Number", label:"Sortable Number", sortable:true},
+ {key:"Date", label:"Sortable Date", sortable:true},
+ {key:"String", label:"Sortable string", sortable:true},
+ {key:"StringSensitive", label:"Sortable string (case sensitive)", sortable:true, caseSensitive:true}
+ ],
/*
dblclickCols = [
{key:"Company", label:"Dblclick to Sort A", sortable:true},
@@ -23,6 +31,12 @@ YUI().use("datatable-sort", function (Y) {
{Company:"Acme Company", Phone:"650-555-4444", Contact:"John Jones"},
{Company:"Industrial Industries", Phone:"408-555-5678", Contact:"Robin Smith"}
],
+ dataSortable = [
+ {Number:1, Date:new Date(2001, 8, 16), String:"A", StringSensitive:"A"},
+ {Number:2, Date:new Date(2003, 8, 16), String:"a", StringSensitive:"a"},
+ {Number:3, Date:new Date(2005, 8, 16), String:"Z", StringSensitive:"Z"},
+ {Number:4, Date:new Date(2007, 8, 16), String:"z", StringSensitive:"z"}
+ ],dt1,dt2;
/*
presortedData = [
{Company:"Acme Company", Phone:"415-555-1234", Contact:"John Jones"},
@@ -37,6 +51,13 @@ YUI().use("datatable-sort", function (Y) {
summary:"Contacts list",
caption:"Table with simple column sorting"
}).render("#sort");
+
+ dt2 = new Y.DataTable({
+ columns:sortableCols,
+ data:dataSortable,
+ summary:"Sortable test data",
+ caption:"Table with column sorting by data type"
+ }).render("#sortSensitive");
/*
dt2 = new Y.DataTable({
View
10 src/datatable/js/sort.js
@@ -493,19 +493,23 @@ Y.mix(Sortable.prototype, {
// extra function hop during sorting. Lesser of three evils?
this.data._compare = function (a, b) {
var cmp = 0,
- i, len, col, dir, aa, bb;
+ i, len, col, dir, cs, aa, bb;
for (i = 0, len = self._sortBy.length; !cmp && i < len; ++i) {
col = self._sortBy[i];
- dir = col.sortDir;
+ dir = col.sortDir,
+ cs = col.caseSensitive;
if (col.sortFn) {
cmp = col.sortFn(a, b, (dir === -1));
} else {
// FIXME? Requires columns without sortFns to have key
aa = a.get(col.key) || '';
bb = b.get(col.key) || '';
-
+ if (!cs && typeof(aa) === "string" && typeof(bb) === "string"){// Not case sensitive
+ aa = aa.toLowerCase();
+ bb = bb.toLowerCase();
+ }
cmp = (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
}
}

0 comments on commit a8cad67

Please sign in to comment.
Something went wrong with that request. Please try again.