From 7d7b199dff29f071b2890992670b327a1c957fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Kov=C3=A1cs?= Date: Tue, 7 Jun 2016 20:59:06 +0200 Subject: [PATCH 1/3] Enables multisorting New property `multiSort` added. If it's false (default), everything works like before However when it's set to true, you can sort data by several selected columns. The most recent selected column has the smallest precedence. The generated request looks like this: `?sort=id|desc,name|asc,email|asc` Of course to get this working, you'll need a backend which is able to parse the above format. Please note that this commit breaks backwards compatibility *a bit*. Now if you want to initialise the sort-order property, it should be done with an array like this. Just wrap your previous object in an array. ``` [{ field: 'name', direction: 'asc' }] ``` --- dist/vue-table.js | 103 +++++++++++++++++++++++++++------- dist/vue-table.min.js | 2 +- examples/bootstrap.html | 6 +- examples/semantic.html | 6 +- src/components/Vuetable.vue | 108 +++++++++++++++++++++++++++++------- 5 files changed, 180 insertions(+), 45 deletions(-) diff --git a/dist/vue-table.js b/dist/vue-table.js index b8594dd..c02a452 100644 --- a/dist/vue-table.js +++ b/dist/vue-table.js @@ -373,12 +373,21 @@ exports.default = { required: true }, 'sortOrder': { - type: Object, + type: Array, default: function _default() { - return { - field: '', - direction: 'asc' - }; + return []; + /* array of + { + field: '', + direction: 'asc' + } + objects */ + } + }, + 'multiSort': { + type: Boolean, + default: function _default() { + return false; } }, 'perPage': { @@ -516,9 +525,6 @@ exports.default = { } }, computed: { - sortIcon: function sortIcon() { - return this.sortOrder.direction == 'asc' ? this.ascendingIcon : this.descendingIcon; - }, paginationInfo: function paginationInfo() { if (this.tablePagination == null || this.tablePagination.total == 0) { return this.paginationInfoNoDataTemplate; @@ -619,9 +625,15 @@ exports.default = { return ''; } - var fieldName = typeof this.sortOrder.sortField === 'undefined' ? this.sortOrder.field : this.sortOrder.sortField; + var result = ''; - return fieldName + '|' + this.sortOrder.direction; + for (var i = 0; i < this.sortOrder.length; i++) { + var fieldName = typeof this.sortOrder[i].sortField === 'undefined' ? this.sortOrder[i].field : this.sortOrder[i].sortField; + + result += fieldName + '|' + this.sortOrder[i].direction + (i + 1 < this.sortOrder.length ? ',' : ''); + } + + return result; }, addClass: function addClass(el, className) { if (el.classList) el.classList.add(className);else el.className += ' ' + className; @@ -640,15 +652,43 @@ exports.default = { return; } - if (this.sortOrder.field == field.name) { - // change sort direction - this.sortOrder.direction = this.sortOrder.direction == 'asc' ? 'desc' : 'asc'; + if (this.multiSort) { + var i = this.currentSortOrder(field); + + if (i === false) { + //this field is not in the sort array yet + this.sortOrder.push({ + field: field.name, + direction: 'asc' + }); + } else { + //this field is in the sort array, now we change its state + if (this.sortOrder[i].direction == 'asc') { + // switch direction + this.sortOrder[i].direction = 'desc'; + } else { + //remove sort condition + this.sortOrder.splice(i, 1); + } + } } else { - // reset sort direction - this.sortOrder.direction = 'asc'; + if (this.sortOrder.length == 0) { + this.sortOrder.push({ + field: '', + direction: 'asc' + }); + } + if (this.sortOrder[0].field == field.name) { + // change sort direction + this.sortOrder[0].direction = this.sortOrder[0].direction == 'asc' ? 'desc' : 'asc'; + } else { + // reset sort direction + this.sortOrder[0].direction = 'asc'; + } + this.sortOrder[0].field = field.name; + this.sortOrder[0].sortField = field.sortField; } - this.sortOrder.field = field.name; - this.sortOrder.sortField = field.sortField; + this.currentPage = 1; // reset page index this.loadData(); }, @@ -656,11 +696,28 @@ exports.default = { return !(typeof field.sortField == 'undefined'); }, isCurrentSortField: function isCurrentSortField(field) { + return this.currentSortOrder(field) !== false; + }, + currentSortOrder: function currentSortOrder(field) { if (!this.isSortable(field)) { return false; } - return this.sortOrder.field == field.name; + for (var i = 0; i < this.sortOrder.length; i++) { + if (this.sortOrder[i].field == field.name) { + return i; + } + } + + return false; + }, + sortIcon: function sortIcon(field) { + var i = this.currentSortOrder(field); + if (i !== false) { + return this.sortOrder[i].direction == 'asc' ? this.ascendingIcon : this.descendingIcon; + } else { + return ''; + } }, gotoPreviousPage: function gotoPreviousPage() { if (this.currentPage > 1) { @@ -775,6 +832,14 @@ exports.default = { } } }, + watch: { + 'multiSort': function multiSort(newVal, oldVal) { + if (newVal === false && this.sortOrder.length > 1) { + this.sortOrder.splice(1); + this.loadData(); + } + } + }, events: { 'vuetable-pagination:change-page': function vuetablePaginationChangePage(page) { if (page == 'prev') { @@ -812,7 +877,7 @@ exports.default = { } }; if (module.exports.__esModule) module.exports = module.exports.default -;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n
\n
1\" class=\"vuetable-pagination-component {{paginationComponentClass}}\">\n \n
\n
\n
\n" +;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n
\n
1\" class=\"vuetable-pagination-component {{paginationComponentClass}}\">\n \n
\n
\n
\n" if (module.hot) {(function () { module.hot.accept() var hotAPI = require("vue-hot-reload-api") hotAPI.install(require("vue"), true) diff --git a/dist/vue-table.min.js b/dist/vue-table.min.js index 2d1c2f2..37f1712 100644 --- a/dist/vue-table.min.js +++ b/dist/vue-table.min.js @@ -1 +1 @@ -!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o0&&(url+="&"+this.appendParams.join("&"));var self=this;this.$http.get(url,this.httpData,this.httpOptions).then(function(response){self.tableData=self.getObjectValue(response.data,self.dataPath,null),self.tablePagination=self.getObjectValue(response.data,self.paginationPath,null),null===self.tablePagination&&console.warn('vuetable: pagination-path "'+self.paginationPath+'"" not found. It looks like the data returned from the sever does not have pagination information.'),self.dispatchEvent("load-success",response),self.broadcastEvent("load-success",self.tablePagination),self.hideLoadingAnimation(wrapper)},function(response){self.dispatchEvent("load-error",response),self.broadcastEvent("load-error",response),self.hideLoadingAnimation(wrapper)})},showLoadingAnimation:function(wrapper){null!==wrapper&&this.addClass(wrapper,this.loadingClass),this.dispatchEvent("loading")},hideLoadingAnimation:function(wrapper){null!==wrapper&&this.removeClass(wrapper,this.loadingClass),this.dispatchEvent("loaded")},getTitle:function(field){return"undefined"==typeof field.title?field.name.replace("."," "):field.title},getSortParam:function(){if(!this.sortOrder||""==this.sortOrder.field)return"";var fieldName="undefined"==typeof this.sortOrder.sortField?this.sortOrder.field:this.sortOrder.sortField;return fieldName+"|"+this.sortOrder.direction},addClass:function(el,className){el.classList?el.classList.add(className):el.className+=" "+className},removeClass:function(el,className){el.classList?el.classList.remove(className):el.className=el.className.replace(new RegExp("(^|\\b)"+className.split(" ").join("|")+"(\\b|$)","gi")," ")},dispatchEvent:function(eventName,args){this.$dispatch(this.eventPrefix+eventName,args)},broadcastEvent:function(eventName,args){this.$broadcast(this.eventPrefix+eventName,args)},orderBy:function(field){this.isSortable(field)&&(this.sortOrder.field==field.name?this.sortOrder.direction="asc"==this.sortOrder.direction?"desc":"asc":this.sortOrder.direction="asc",this.sortOrder.field=field.name,this.sortOrder.sortField=field.sortField,this.currentPage=1,this.loadData())},isSortable:function(field){return!("undefined"==typeof field.sortField)},isCurrentSortField:function(field){return this.isSortable(field)?this.sortOrder.field==field.name:!1},gotoPreviousPage:function(){this.currentPage>1&&(this.currentPage--,this.loadData())},gotoNextPage:function(){this.currentPage0&&page<=this.tablePagination.last_page&&(this.currentPage=page,this.loadData())},isSpecialField:function(fieldName){return fieldName.startsWith("__")},hasCallback:function(item){return!!item.callback},callCallback:function(field,item){if(this.hasCallback(field)){var args=field.callback.split("|"),func=args.shift();return"function"==typeof this.$parent[func]?args.length>0?this.$parent[func].apply(this.$parent,[this.getObjectValue(item,field.name)].concat(args)):this.$parent[func].call(this.$parent,this.getObjectValue(item,field.name)):null}},getObjectValue:function(object,path,defaultValue){defaultValue="undefined"==typeof defaultValue?null:defaultValue;var obj=object;if(""!=path.trim()){var keys=path.split(".");keys.forEach(function(key){return"undefined"==typeof obj[key]||null===obj[key]?void(obj=defaultValue):void(obj=obj[key])})}return obj},callAction:function(action,data){this.$dispatch(this.eventPrefix+"action",action,data)},addParam:function(param){this.appendParams.push(param)},toggleCheckbox:function(isChecked,dataItem,fieldName){var idColumn=this.extractArgs(fieldName);return void 0===idColumn?void console.warn('You did not provide reference id column with "__checkbox:" field!'):void(isChecked?this.selectedTo.push(dataItem[idColumn]):this.selectedTo.$remove(dataItem[idColumn]))},toggleAllCheckboxes:function(isChecked,fieldName){var self=this,idColumn=this.extractArgs(fieldName);isChecked?this.tableData.forEach(function(dataItem){self.isSelectedRow(dataItem,fieldName)||self.selectedTo.push(dataItem[idColumn])}):this.tableData.forEach(function(dataItem){self.selectedTo.$remove(dataItem[idColumn])})},isSelectedRow:function(dataItem,fieldName){return this.selectedTo.indexOf(dataItem[this.extractArgs(fieldName)])>=0},extractName:function(string){return string.split(":")[0].trim()},extractArgs:function(string){return string.split(":")[1]},onRowChanged:function(dataItem){return this.dispatchEvent("row-changed",dataItem),!0},onRowClicked:function(dataItem,event){return this.$dispatch(this.eventPrefix+"row-clicked",dataItem,event),!0},onCellDoubleClicked:function(dataItem,field,event){this.$dispatch(this.eventPrefix+"cell-dblclicked",dataItem,field,event)},callPaginationConfig:function(){"function"==typeof this.$parent[this.paginationConfig]&&this.$parent[this.paginationConfig].call(this.$parent,this.$refs.pagination.$options.name)}},events:{"vuetable-pagination:change-page":function(page){"prev"==page?this.gotoPreviousPage():"next"==page?this.gotoNextPage():this.gotoPage(page)},"vuetable:reload":function(){this.loadData()},"vuetable:refresh":function(){this.currentPage=1,this.loadData()},"vuetable:goto-page":function(page){this.$emit("vuetable-pagination:change-page",page)},"vuetable:set-options":function(options){for(var n in options)this.$set(n,options[n])}},created:function(){this.normalizeFields(),this.loadOnStart&&this.loadData(),this.$nextTick(function(){this.callPaginationConfig()})}},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template='
'},{"vueify/lib/insert-css":1}],3:[function(require,module,exports){"use strict";function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(exports,"__esModule",{value:!0});var _VuetablePaginationMixin=require("./VuetablePaginationMixin.vue"),_VuetablePaginationMixin2=_interopRequireDefault(_VuetablePaginationMixin);exports.default={mixins:[_VuetablePaginationMixin2.default]},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template=''},{"./VuetablePaginationMixin.vue":5}],4:[function(require,module,exports){"use strict";function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(exports,"__esModule",{value:!0});var _VuetablePaginationMixin=require("./VuetablePaginationMixin.vue"),_VuetablePaginationMixin2=_interopRequireDefault(_VuetablePaginationMixin);exports.default={mixins:[_VuetablePaginationMixin2.default],props:{dropdownClass:{type:String,default:function(){return"ui search dropdown"}},pageText:{type:String,default:function(){return"Page"}}},methods:{loadPage:function(page){"prev"!=page||this.isOnFirstPage?"next"!=page||this.isOnLastPage||this.setDropdownToPage(this.tablePagination.current_page+1):this.setDropdownToPage(this.tablePagination.current_page-1),this.$dispatch("vuetable-pagination:change-page",page)},setDropdownToPage:function(page){this.$nextTick(function(){document.getElementById("vuetable-pagination-dropdown").value=page})},selectPage:function(event){this.$dispatch("vuetable-pagination:change-page",event.target.selectedIndex+1)}},events:{"vuetable:load-success":function(tablePagination){this.tablePagination=tablePagination,this.setDropdownToPage(tablePagination.current_page)}}},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template='
'},{"./VuetablePaginationMixin.vue":5}],5:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default={props:{wrapperClass:{type:String,default:function(){return"ui right floated pagination menu"}},activeClass:{type:String,default:function(){return"active large"}},disabledClass:{type:String,default:function(){return"disabled"}},pageClass:{type:String,default:function(){return"item"}},linkClass:{type:String,default:function(){return"icon item"}},icons:{type:Object,default:function(){return{first:"angle double left icon",prev:"left chevron icon",next:"right chevron icon",last:"angle double right icon"}}},onEachSide:{type:Number,coerce:function(value){return parseInt(value)},default:function(){return 2}}},data:function(){return{tablePagination:null}},computed:{totalPage:function(){return null==this.tablePagination?0:this.tablePagination.last_page},isOnFirstPage:function(){return null==this.tablePagination?!1:1==this.tablePagination.current_page},isOnLastPage:function(){return null==this.tablePagination?!1:this.tablePagination.current_page==this.tablePagination.last_page},notEnoughPages:function(){return this.totalPage<2*this.onEachSide+4},windowSize:function(){return 2*this.onEachSide+1},windowStart:function(){return this.tablePagination.current_page<=this.onEachSide?1:this.tablePagination.current_page>=this.totalPage-this.onEachSide?this.totalPage-2*this.onEachSide:this.tablePagination.current_page-this.onEachSide}},methods:{loadPage:function(page){this.$dispatch("vuetable-pagination:change-page",page)},isCurrentPage:function(page){return page==this.tablePagination.current_page}},events:{"vuetable:load-success":function(tablePagination){this.tablePagination=tablePagination},"vuetable-pagination:set-options":function(options){for(var n in options)this.$set(n,options[n])}}},module.exports.__esModule&&(module.exports=module.exports.default)},{}],6:[function(require,module,exports){Vue.component("vuetable-pagination",require("./components/VuetablePagination.vue")),Vue.component("vuetable-pagination-dropdown",require("./components/VuetablePaginationDropdown.vue")),Vue.component("vuetable",require("./components/Vuetable.vue"))},{"./components/Vuetable.vue":2,"./components/VuetablePagination.vue":3,"./components/VuetablePaginationDropdown.vue":4}]},{},[6]); +!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o0&&(url+="&"+this.appendParams.join("&"));var self=this;this.$http.get(url,this.httpData,this.httpOptions).then(function(response){self.tableData=self.getObjectValue(response.data,self.dataPath,null),self.tablePagination=self.getObjectValue(response.data,self.paginationPath,null),null===self.tablePagination&&console.warn('vuetable: pagination-path "'+self.paginationPath+'"" not found. It looks like the data returned from the sever does not have pagination information.'),self.dispatchEvent("load-success",response),self.broadcastEvent("load-success",self.tablePagination),self.hideLoadingAnimation(wrapper)},function(response){self.dispatchEvent("load-error",response),self.broadcastEvent("load-error",response),self.hideLoadingAnimation(wrapper)})},showLoadingAnimation:function(wrapper){null!==wrapper&&this.addClass(wrapper,this.loadingClass),this.dispatchEvent("loading")},hideLoadingAnimation:function(wrapper){null!==wrapper&&this.removeClass(wrapper,this.loadingClass),this.dispatchEvent("loaded")},getTitle:function(field){return"undefined"==typeof field.title?field.name.replace("."," "):field.title},getSortParam:function(){if(!this.sortOrder||""==this.sortOrder.field)return"";for(var result="",i=0;i1&&(this.currentPage--,this.loadData())},gotoNextPage:function(){this.currentPage0&&page<=this.tablePagination.last_page&&(this.currentPage=page,this.loadData())},isSpecialField:function(fieldName){return fieldName.startsWith("__")},hasCallback:function(item){return!!item.callback},callCallback:function(field,item){if(this.hasCallback(field)){var args=field.callback.split("|"),func=args.shift();return"function"==typeof this.$parent[func]?args.length>0?this.$parent[func].apply(this.$parent,[this.getObjectValue(item,field.name)].concat(args)):this.$parent[func].call(this.$parent,this.getObjectValue(item,field.name)):null}},getObjectValue:function(object,path,defaultValue){defaultValue="undefined"==typeof defaultValue?null:defaultValue;var obj=object;if(""!=path.trim()){var keys=path.split(".");keys.forEach(function(key){return"undefined"==typeof obj[key]||null===obj[key]?void(obj=defaultValue):void(obj=obj[key])})}return obj},callAction:function(action,data){this.$dispatch(this.eventPrefix+"action",action,data)},addParam:function(param){this.appendParams.push(param)},toggleCheckbox:function(isChecked,dataItem,fieldName){var idColumn=this.extractArgs(fieldName);return void 0===idColumn?void console.warn('You did not provide reference id column with "__checkbox:" field!'):void(isChecked?this.selectedTo.push(dataItem[idColumn]):this.selectedTo.$remove(dataItem[idColumn]))},toggleAllCheckboxes:function(isChecked,fieldName){var self=this,idColumn=this.extractArgs(fieldName);isChecked?this.tableData.forEach(function(dataItem){self.isSelectedRow(dataItem,fieldName)||self.selectedTo.push(dataItem[idColumn])}):this.tableData.forEach(function(dataItem){self.selectedTo.$remove(dataItem[idColumn])})},isSelectedRow:function(dataItem,fieldName){return this.selectedTo.indexOf(dataItem[this.extractArgs(fieldName)])>=0},extractName:function(string){return string.split(":")[0].trim()},extractArgs:function(string){return string.split(":")[1]},onRowChanged:function(dataItem){return this.dispatchEvent("row-changed",dataItem),!0},onRowClicked:function(dataItem,event){return this.$dispatch(this.eventPrefix+"row-clicked",dataItem,event),!0},onCellDoubleClicked:function(dataItem,field,event){this.$dispatch(this.eventPrefix+"cell-dblclicked",dataItem,field,event)},callPaginationConfig:function(){"function"==typeof this.$parent[this.paginationConfig]&&this.$parent[this.paginationConfig].call(this.$parent,this.$refs.pagination.$options.name)}},watch:{multiSort:function(newVal,oldVal){newVal===!1&&this.sortOrder.length>1&&(this.sortOrder.splice(1),this.loadData())}},events:{"vuetable-pagination:change-page":function(page){"prev"==page?this.gotoPreviousPage():"next"==page?this.gotoNextPage():this.gotoPage(page)},"vuetable:reload":function(){this.loadData()},"vuetable:refresh":function(){this.currentPage=1,this.loadData()},"vuetable:goto-page":function(page){this.$emit("vuetable-pagination:change-page",page)},"vuetable:set-options":function(options){for(var n in options)this.$set(n,options[n])}},created:function(){this.normalizeFields(),this.loadOnStart&&this.loadData(),this.$nextTick(function(){this.callPaginationConfig()})}},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template='
'},{"vueify/lib/insert-css":1}],3:[function(require,module,exports){"use strict";function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(exports,"__esModule",{value:!0});var _VuetablePaginationMixin=require("./VuetablePaginationMixin.vue"),_VuetablePaginationMixin2=_interopRequireDefault(_VuetablePaginationMixin);exports.default={mixins:[_VuetablePaginationMixin2.default]},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template=''},{"./VuetablePaginationMixin.vue":5}],4:[function(require,module,exports){"use strict";function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(exports,"__esModule",{value:!0});var _VuetablePaginationMixin=require("./VuetablePaginationMixin.vue"),_VuetablePaginationMixin2=_interopRequireDefault(_VuetablePaginationMixin);exports.default={mixins:[_VuetablePaginationMixin2.default],props:{dropdownClass:{type:String,default:function(){return"ui search dropdown"}},pageText:{type:String,default:function(){return"Page"}}},methods:{loadPage:function(page){"prev"!=page||this.isOnFirstPage?"next"!=page||this.isOnLastPage||this.setDropdownToPage(this.tablePagination.current_page+1):this.setDropdownToPage(this.tablePagination.current_page-1),this.$dispatch("vuetable-pagination:change-page",page)},setDropdownToPage:function(page){this.$nextTick(function(){document.getElementById("vuetable-pagination-dropdown").value=page})},selectPage:function(event){this.$dispatch("vuetable-pagination:change-page",event.target.selectedIndex+1)}},events:{"vuetable:load-success":function(tablePagination){this.tablePagination=tablePagination,this.setDropdownToPage(tablePagination.current_page)}}},module.exports.__esModule&&(module.exports=module.exports.default),("function"==typeof module.exports?module.exports.options:module.exports).template='
'},{"./VuetablePaginationMixin.vue":5}],5:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default={props:{wrapperClass:{type:String,default:function(){return"ui right floated pagination menu"}},activeClass:{type:String,default:function(){return"active large"}},disabledClass:{type:String,default:function(){return"disabled"}},pageClass:{type:String,default:function(){return"item"}},linkClass:{type:String,default:function(){return"icon item"}},icons:{type:Object,default:function(){return{first:"angle double left icon",prev:"left chevron icon",next:"right chevron icon",last:"angle double right icon"}}},onEachSide:{type:Number,coerce:function(value){return parseInt(value)},default:function(){return 2}}},data:function(){return{tablePagination:null}},computed:{totalPage:function(){return null==this.tablePagination?0:this.tablePagination.last_page},isOnFirstPage:function(){return null==this.tablePagination?!1:1==this.tablePagination.current_page},isOnLastPage:function(){return null==this.tablePagination?!1:this.tablePagination.current_page==this.tablePagination.last_page},notEnoughPages:function(){return this.totalPage<2*this.onEachSide+4},windowSize:function(){return 2*this.onEachSide+1},windowStart:function(){return this.tablePagination.current_page<=this.onEachSide?1:this.tablePagination.current_page>=this.totalPage-this.onEachSide?this.totalPage-2*this.onEachSide:this.tablePagination.current_page-this.onEachSide}},methods:{loadPage:function(page){this.$dispatch("vuetable-pagination:change-page",page)},isCurrentPage:function(page){return page==this.tablePagination.current_page}},events:{"vuetable:load-success":function(tablePagination){this.tablePagination=tablePagination},"vuetable-pagination:set-options":function(options){for(var n in options)this.$set(n,options[n])}}},module.exports.__esModule&&(module.exports=module.exports.default)},{}],6:[function(require,module,exports){Vue.component("vuetable-pagination",require("./components/VuetablePagination.vue")),Vue.component("vuetable-pagination-dropdown",require("./components/VuetablePaginationDropdown.vue")),Vue.component("vuetable",require("./components/Vuetable.vue"))},{"./components/Vuetable.vue":2,"./components/VuetablePagination.vue":3,"./components/VuetablePaginationDropdown.vue":4}]},{},[6]); diff --git a/examples/bootstrap.html b/examples/bootstrap.html index 1741628..25a9793 100644 --- a/examples/bootstrap.html +++ b/examples/bootstrap.html @@ -184,6 +184,7 @@

List of Users

pagination-path="" :fields="fields" :sort-order="sortOrder" + :multi-sort="multiSort" table-class="table table-bordered table-striped table-hover" ascending-icon="glyphicon glyphicon-chevron-up" descending-icon="glyphicon glyphicon-chevron-down" @@ -261,10 +262,11 @@

List of Users

data: { searchFor: '', fields: tableColumns, - sortOrder: { + sortOrder: [{ field: 'name', direction: 'asc' - }, + }], + multiSort: false, perPage: 10, paginationComponent: 'vuetable-pagination', paginationInfoTemplate: 'แสดง {from} ถึง {to} จากทั้งหมด {total} รายการ', diff --git a/examples/semantic.html b/examples/semantic.html index 56dcbad..e6c9a57 100644 --- a/examples/semantic.html +++ b/examples/semantic.html @@ -143,6 +143,7 @@

List of Users

table-wrapper=".vuetable-wrapper" :fields="fields" :sort-order="sortOrder" + :multi-sort="multiSort" :item-actions="itemActions" :per-page="perPage" :append-params="moreParams" @@ -203,10 +204,11 @@

List of Users

searchFor: '', moreParams: [], fields: tableColumns, - sortOrder: { + sortOrder: [{ field: 'name', direction: 'asc', - }, + }], + multiSort: false, paginationComponent: 'vuetable-pagination', perPage: 10, paginationInfoTemplate: 'แสดง {from} ถึง {to} จากทั้งหมด {total} รายการ', diff --git a/src/components/Vuetable.vue b/src/components/Vuetable.vue index cc5460e..bb8ee0f 100644 --- a/src/components/Vuetable.vue +++ b/src/components/Vuetable.vue @@ -18,7 +18,7 @@ id="_{{field.name}}" class="{{field.titleClass || ''}} {{isSortable(field) ? 'sortable' : ''}}"> {{getTitle(field) | capitalize}}  - + @@ -120,12 +120,21 @@ export default { required: true }, 'sortOrder': { - type: Object, + type: Array, default: function() { - return { - field: '', - direction: 'asc' - } + return []; + /* array of + { + field: '', + direction: 'asc' + } + objects */ + } + }, + 'multiSort' : { + type: Boolean, + default: function() { + return false } }, 'perPage': { @@ -263,9 +272,6 @@ export default { }, }, computed: { - sortIcon: function() { - return this.sortOrder.direction == 'asc' ? this.ascendingIcon : this.descendingIcon - }, paginationInfo: function() { if (this.tablePagination == null || this.tablePagination.total == 0) { return this.paginationInfoNoDataTemplate @@ -377,11 +383,17 @@ export default { return '' } - var fieldName = (typeof this.sortOrder.sortField === 'undefined') - ? this.sortOrder.field - : this.sortOrder.sortField + var result = ''; + + for(var i=0; i 1) { @@ -544,6 +602,14 @@ export default { } }, }, + watch: { + 'multiSort': function(newVal, oldVal){ + if (newVal === false && this.sortOrder.length > 1) { + this.sortOrder.splice(1); + this.loadData(); + } + } + }, events: { 'vuetable-pagination:change-page': function(page) { if (page == 'prev') { From cbf3c667a21772317853c184dfc04b95093b5659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Kov=C3=A1cs?= Date: Sat, 18 Jun 2016 13:43:54 +0200 Subject: [PATCH 2/3] Multisort now works with ctrl key --- dist/vue-table.js | 11 ++++++++--- src/components/Vuetable.vue | 11 +++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/dist/vue-table.js b/dist/vue-table.js index c02a452..2555c20 100644 --- a/dist/vue-table.js +++ b/dist/vue-table.js @@ -647,12 +647,13 @@ exports.default = { broadcastEvent: function broadcastEvent(eventName, args) { this.$broadcast(this.eventPrefix + eventName, args); }, - orderBy: function orderBy(field) { + orderBy: function orderBy(field, event) { if (!this.isSortable(field)) { return; } - if (this.multiSort) { + if (this.multiSort && event.ctrlKey) { + //adding column to multisort var i = this.currentSortOrder(field); if (i === false) { @@ -672,12 +673,16 @@ exports.default = { } } } else { + //no multisort, or resetting sort if (this.sortOrder.length == 0) { this.sortOrder.push({ field: '', direction: 'asc' }); } + + this.sortOrder.splice(1); //removes additional columns + if (this.sortOrder[0].field == field.name) { // change sort direction this.sortOrder[0].direction = this.sortOrder[0].direction == 'asc' ? 'desc' : 'asc'; @@ -877,7 +882,7 @@ exports.default = { } }; if (module.exports.__esModule) module.exports = module.exports.default -;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n
\n
1\" class=\"vuetable-pagination-component {{paginationComponentClass}}\">\n \n
\n
\n
\n" +;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n
\n
1\" class=\"vuetable-pagination-component {{paginationComponentClass}}\">\n \n
\n
\n
\n" if (module.hot) {(function () { module.hot.accept() var hotAPI = require("vue-hot-reload-api") hotAPI.install(require("vue"), true) diff --git a/src/components/Vuetable.vue b/src/components/Vuetable.vue index bb8ee0f..afe5c2d 100644 --- a/src/components/Vuetable.vue +++ b/src/components/Vuetable.vue @@ -14,7 +14,7 @@ @@ -489,6 +489,31 @@ export default { return ''; } }, + sortIconOpacity: function(field) { + //fields with stronger precedence have darker color + + //if there are few fields, we go down by 0.3 + //ex. 2 fields are selected: 1.0, 0.7 + + //if there are more we go down evenly on the given spectrum + //ex. 6 fields are selected: 1.0, 0.86, 0.72, 0.58, 0.44, 0.3 + + var max = 1.0; + var min = 0.3; + var step = 0.3; + + var count = this.sortOrder.length; + var current = this.currentSortOrder(field); + + + if(max - count*step < min){ + step = (max - min) / (count-1); + } + + var opacity = max - current*step; + + return opacity; + }, gotoPreviousPage: function() { if (this.currentPage > 1) { this.currentPage--