/* --------------------------------------------------------------------------------- Component: Table grid Input Options for gridOptions: - id: id of grid wrapper - dataSource: array of objects to be shown in grid - pageable: wehter to use paging - pageSize: page size in int - searchModel: field by which to filter by grid - columns: definition for columns to be shown in grid Example of grid options: gridOptions: { serverFiltering: true, dataSource: { remoteUrl:'/api/documents/GetDocumentsList', remoteparams:{}, remoteMethod: 'POST', pageIndex:0, total: 13, data: [] }, pageable: true, pageSize: 5, height: 120, searchModel: '', noDataMessage: 'No rows to show', sortBy: { column:'name', orderBy: 1 // 1- asc, 0 - default, -1 - desc }, columns: [ { title: '', type: 'index', sorting: false, style: { width: '50px' } }, { title:'Ime', field: 'name', type 'string', // available: string, numeric, date, boolean template: '{{name}} - {{power}}' }, { title: 'Active', field: 'active', type: 'boolean', style: { textAlign: 'center', width:'95px' }, template: '' }, { title: 'Snaga', field: 'power', type: 'numeric', }, { title: 'Datum', field: 'datum', type: 'date', dateFormat: 'dd/mm/yyyy' }, { title: '', template: '
', sorting: false, style: { 'text-align':'center', width: '80px' } }, ] } Usage: */ Vue.component('data-grid', { props: { id: String, gridOptions: Object }, data: function() { var self = this; var sortKey = ''; var sortOrders = {} this.gridOptions.columns.forEach(function (column) { // if sorting for column is not wanted if(column.sorting != undefined && column.sorting == false) { return; } if(self.gridOptions.sortBy != undefined && self.gridOptions.sortBy.column == column.field ) { sortOrders[column.field] = self.gridOptions.sortBy.orderBy; sortKey = self.gridOptions.sortBy.column; } else { sortOrders[column.field] = 0; } }); return { $eel: null, sortKey: sortKey, sortOrders: sortOrders, showPagination: false, searchModelValue: '', gridRowCount: 0, gotoPage: null, // input for go to page defaultOptions: { serverFiltering: false, dataSource: { pageIndex: 0, total: 0, data: [] }, pageable: true, pageSize: 15, searchModel: '', columns: [] } }; }, computed: { filteredData: function() { return this.ProcessGridData(this.gridOptions.dataSource.data); } }, filters: { capitalize: function(str) { return str.charAt(0).toUpperCase() + str.slice(1) }, }, mounted: function () { var self = this; $(window).on('resize', function(e) { self.CheckForScroll(); }); // Ukoliko ne postoji definisan height, zakucaj ga na velicinu inicijalnog tbody scrollheighta // setTimeout(function() // { // if (self.gridOptions.height == undefined) // { // $(self.$el).find('tbody').css('height', $(self.$el).find('tbody')[0].scrollHeight + 1); // } // },100); }, methods: { // ------------------------------------------------------------------ // Process grid data filtering, sorting and pagination ProcessGridData: function() { var self = this; var sortKey = this.sortKey; var order = this.sortOrders[sortKey]; var filterKey = this.searchModelValue.toLowerCase();//this.gridOptions.searchModel && this.gridOptions.searchModel.toLowerCase(); var gridData = this.gridOptions.dataSource.data; this.showPagination = this.gridOptions.pageable != undefined && this.gridOptions.pageable && this.gridOptions.pageSize != undefined && gridData.length > 0; if(gridData.length == 0) { this.gridRowCount = 0; return []; } // Search - if defined if (filterKey != '') { //this.gridOptions.dataSource.pageIndex = 0; // reset page to zero gridData = gridData.filter(function(row) { return Object.keys(row).some(function(key) { // Uzmi u obzir tip kolone i probaj da shvatis sta sta ostaje to to filtriraj var columnOptions = $.grep(self.gridOptions.columns, function(e){return e.field==key}); if(columnOptions.length > 0)// && columnOptions[0].type != undefined) { if(columnOptions[0].template != undefined) { return self.ParseTemplate(columnOptions[0].template, row).toLowerCase().indexOf(filterKey) > -1; } else if(columnOptions[0].type == 'date' && columnOptions[0].dateFormat != undefined && row[key] != null && row[key] != '') { return self.ParseDate(row[key], columnOptions[0].dateFormat).indexOf(filterKey) > -1; } else { return String(row[key]).toLowerCase().indexOf(filterKey) > -1; } } return false; }); }); } this.gridRowCount = gridData.length; // Sort - if defined if (sortKey && order != 0) { gridData = this.SortBy(sortKey, order, gridData); } // Ukoliko treba da se pokaze paginacija, ali broj rredova je manji od pageSizea ne prikazuj this.showPagination = this.showPagination == true && gridData.length > this.gridOptions.pageSize && gridData.length > 0; // if pageable if(this.gridOptions.pageable) { this.gridOptions.dataSource.totalPages = Math.ceil(gridData.length / this.gridOptions.pageSize); // Check pageIndex range if(this.gridOptions.dataSource.pageIndex < 0) { this.gridOptions.dataSource.pageIndex = 0; } else if (this.gridOptions.dataSource.pageIndex > this.gridOptions.dataSource.totalPages - 1) { this.gridOptions.dataSource.pageIndex = this.gridOptions.dataSource.totalPages - 1; } var startIndex = this.gridOptions.dataSource.pageIndex * this.gridOptions.pageSize; var endIndex = startIndex + this.gridOptions.pageSize; gridData = gridData.slice(startIndex,endIndex); } // Proveri da li je visina tbody kontejnera manja od visine elemenata unutra this.CheckForScroll(true); return gridData; }, CheckForScroll: function(withTimeout) { // ovde ce trebati timeout zbog iscrtavanja grida pre pocetka, // i cilj je da se u thead-u smanji/poveca sirina u zavisnosti ako ima/nema scrolla var self = this; setTimeout(function() { if(self.$el == undefined) { return false; } else if($(self.$el).find('tbody').height() < $(self.$el).find('tbody')[0].scrollHeight) { $(self.$el).find('th.last').show(); } else { $(self.$el).find('th.last').hide(); } }, withTimeout != undefined && withTimeout ? 500 : 0); }, RenderTableCellContent: function(column, entry, index) { if(column.template) { return this.ParseTemplate(column.template, entry); } else if(column.type == 'date' && column.dateFormat != undefined) { return this.ParseDate(entry[column.field],column.dateFormat); } else if(column.type == 'index') { return ((this.gridOptions.dataSource.pageIndex)*this.gridOptions.pageSize + index + 1) + '.'; } else { return entry[column.field]; } }, // ------------------------------------------------------------------ // Sorting SetSortByColumn: function(key) { // OVDE TREBA SERVERSI KOZIV // if sorting in grifOptions set to false, then there is no sorting via this column if(this.sortOrders[key] == undefined) { return; } this.sortKey = key; if(this.sortOrders[key] == 0) { this.sortOrders[key] = 1; } else if(this.sortOrders[key] == 1) { this.sortOrders[key] = -1; } else { this.sortOrders[key] = 0; } // reset current page in paginator to first this.gridOptions.dataSource.pageIndex = 0; }, SortBy: function(sortKey, order, gridData) { var sortFieldType = 'string'; var column = $.grep(this.gridOptions.columns, function(e) { return e.field == sortKey; }); if(column.length > 0 && column[0].type != undefined) { sortFieldType = column[0].type; } switch(sortFieldType) { case 'boolean': gridData = gridData.slice().sort(function (a, b) { a = a[sortKey]; b = b[sortKey]; if(a == null || b == null) { return -1; } return (a === b ? 0 : a > b ? 1 : -1) * order * -1 }); break; case 'date': gridData = gridData.slice().sort(function (a, b) { a = a[sortKey]; b = b[sortKey]; if(a == null || b == null) { return -1; } return (a.getTime() === b.getTime() ? 0 : a.getTime() > b.getTime() ? 1 : -1) * order }); break; case 'numeric': gridData = gridData.slice().sort(function (a, b) { a = a[sortKey]; b = b[sortKey]; if(a == null) { a = 100000 * order; } if(b == null) { b = 100000 * order; } return (a === b ? 0 : a > b ? 1 : -1) * order }); break; default: case 'string': case 'numeric': gridData = gridData.slice().sort(function (a, b) { a = a[sortKey]; b = b[sortKey]; return (a === b ? 0 : a > b ? 1 : -1) * order }); break; } return gridData; }, // ------------------------------------------------------------------ // Template parsing ParseTemplate: function(template, data) { var self = this; $.each( template.match(/\{\{(.*?)\}\}/g), function(i,item) { var item_stripped = item.replace('{{','').replace('}}',''); if (data[item_stripped]) { template = template.replace(item, data[item_stripped]); } else { try { // Expresion - ideja je da napravimo sve promenjive i na kraju dodamo izraz koji zelimo da evauliramo var forEval = ''; $.each(data, function(i,item) { forEval += 'var '+ i +' = `'+ self.replaceAll(item, '"','"') +'`;'; }); forEval += item_stripped +';'; template = template.replace(item, eval(forEval)); } catch(err) { console.log('Error parsing grid template.\n' +err); template = template.replace(item, '-!-'); } } }); return template; }, ParseDate: function(date, format) { if(date == null) { return null; } return dateFormat(date,format); }, replaceAll: function(item, search, replacement) { if(typeof item !== 'string') { return item; } return item.replace(new RegExp(search, 'g'), replacement); }, // ------------------------------------------------------------------ // Pagination PaginationClick: function(pageIndex) { console.log(pageIndex); // OVDE TREBA SERVERSI KOZIV // NIJE GOTOVO // if(this.gridOptions.serverFiltering != undefined && this.gridOptions.serverFiltering) // { // $.ajax( // { // type: this.gridOptions.dataSource.remoteMethod, // url: this.gridOptions.dataSource.remoteUrl, // dataType: "json", // context: this, // data:{}, // success: function(wsResult) // { // this.gridOptions.dataSource.data = wsResult; // this.gridOptions.dataSource.pageIndex = pageIndex; // }, // error: function(data) // { // console.error('Error while getting server data'); // } // }); // } // else // { this.gridOptions.dataSource.pageIndex = pageIndex; // } }, CreateRange: function(from,to,tttt) { if(this.gridOptions.dataSource.data.length == 0) { return []; } var ttt = (new Array(to - from + 1)).fill(undefined).map((_, i) => i + from); return ttt; }, }, watch: { 'gridOptions.searchModel': function(val) { // OVDE TREBA SERVERSI KOZIV // reset current page in paginator to first this.gridOptions.dataSource.pageIndex = 0; this.searchModelValue = val; }, gotoPage: function(val) { if(val != null && val != '') { console.log(val); this.gridOptions.dataSource.pageIndex = val - 1; } } }, template: `
{{ column.title | capitalize }}
{{gridOptions.noDataMessage != undefined ? gridOptions.noDataMessage : 'No results. Please try another term.'}}
Showing page {{gridOptions.dataSource.pageIndex+1}} of {{gridOptions.dataSource.totalPages}} ({{gridRowCount}} {{searchModelValue == null || searchModelValue == '' ? 'total' : ''}} entries)
  • {{i}}
  • ...
  • {{j}}
  • ...
  • {{k}}
Go to page:
` }); /* * Date Format 1.2.3 * (c) 2007-2009 Steven Levithan * MIT license * * Includes enhancements by Scott Trenda * and Kris Kowal * * Accepts a date, a mask, or a date and a mask. * Returns a formatted version of the given date. * The date defaults to the current date/time. * The mask defaults to dateFormat.masks.default. */ (function(global) { 'use strict'; var dateFormat = (function() { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWN]|"[^"]*"|'[^']*'/g; var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g; var timezoneClip = /[^-+\dA-Z]/g; // Regexes and supporting functions are cached through closure return function (date, mask, utc, gmt) { // You can't provide utc if you skip other args (use the 'UTC:' mask prefix) if (arguments.length === 1 && kindOf(date) === 'string' && !/\d/.test(date)) { mask = date; date = undefined; } date = date || new Date; if(!(date instanceof Date)) { date = new Date(date); } if (isNaN(date)) { throw TypeError('Invalid date'); } mask = String(dateFormat.masks[mask] || mask || dateFormat.masks['default']); // Allow setting the utc/gmt argument via the mask var maskSlice = mask.slice(0, 4); if (maskSlice === 'UTC:' || maskSlice === 'GMT:') { mask = mask.slice(4); utc = true; if (maskSlice === 'GMT:') { gmt = true; } } var _ = utc ? 'getUTC' : 'get'; var d = date[_ + 'Date'](); var D = date[_ + 'Day'](); var m = date[_ + 'Month'](); var y = date[_ + 'FullYear'](); var H = date[_ + 'Hours'](); var M = date[_ + 'Minutes'](); var s = date[_ + 'Seconds'](); var L = date[_ + 'Milliseconds'](); var o = utc ? 0 : date.getTimezoneOffset(); var W = getWeek(date); var N = getDayOfWeek(date); var flags = { d: d, dd: pad(d), ddd: dateFormat.i18n.dayNames[D], dddd: dateFormat.i18n.dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: dateFormat.i18n.monthNames[m], mmmm: dateFormat.i18n.monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(Math.round(L / 10)), t: H < 12 ? dateFormat.i18n.timeNames[0] : dateFormat.i18n.timeNames[1], tt: H < 12 ? dateFormat.i18n.timeNames[2] : dateFormat.i18n.timeNames[3], T: H < 12 ? dateFormat.i18n.timeNames[4] : dateFormat.i18n.timeNames[5], TT: H < 12 ? dateFormat.i18n.timeNames[6] : dateFormat.i18n.timeNames[7], Z: gmt ? 'GMT' : utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''), o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10], W: W, N: N }; return mask.replace(token, function (match) { if (match in flags) { return flags[match]; } return match.slice(1, match.length - 1); }); }; })(); dateFormat.masks = { 'default': 'ddd mmm dd yyyy HH:MM:ss', 'shortDate': 'm/d/yy', 'mediumDate': 'mmm d, yyyy', 'longDate': 'mmmm d, yyyy', 'fullDate': 'dddd, mmmm d, yyyy', 'shortTime': 'h:MM TT', 'mediumTime': 'h:MM:ss TT', 'longTime': 'h:MM:ss TT Z', 'isoDate': 'yyyy-mm-dd', 'isoTime': 'HH:MM:ss', 'isoDateTime': 'yyyy-mm-dd\'T\'HH:MM:sso', 'isoUtcDateTime': 'UTC:yyyy-mm-dd\'T\'HH:MM:ss\'Z\'', 'expiresHeaderFormat': 'ddd, dd mmm yyyy HH:MM:ss Z' }; // Internationalization strings dateFormat.i18n = { dayNames: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ], monthNames: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], timeNames: [ 'a', 'p', 'am', 'pm', 'A', 'P', 'AM', 'PM' ] }; function pad(val, len) { val = String(val); len = len || 2; while (val.length < len) { val = '0' + val; } return val; } /** * Get the ISO 8601 week number * Based on comments from * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html * * @param {Object} `date` * @return {Number} */ function getWeek(date) { // Remove time components of date var targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate()); // Change date to Thursday same week targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3); // Take January 4th as it is always in week 1 (see ISO 8601) var firstThursday = new Date(targetThursday.getFullYear(), 0, 4); // Change date to Thursday same week firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3); // Check if daylight-saving-time-switch occurred and correct for it var ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset(); targetThursday.setHours(targetThursday.getHours() - ds); // Number of weeks between target Thursday and first Thursday var weekDiff = (targetThursday - firstThursday) / (86400000*7); return 1 + Math.floor(weekDiff); } /** * Get ISO-8601 numeric representation of the day of the week * 1 (for Monday) through 7 (for Sunday) * * @param {Object} `date` * @return {Number} */ function getDayOfWeek(date) { var dow = date.getDay(); if(dow === 0) { dow = 7; } return dow; } /** * kind-of shortcut * @param {*} val * @return {String} */ function kindOf(val) { if (val === null) { return 'null'; } if (val === undefined) { return 'undefined'; } if (typeof val !== 'object') { return typeof val; } if (Array.isArray(val)) { return 'array'; } return {}.toString.call(val) .slice(8, -1).toLowerCase(); }; if (typeof define === 'function' && define.amd) { define(function () { return dateFormat; }); } else if (typeof exports === 'object') { module.exports = dateFormat; } else { global.dateFormat = dateFormat; } })(this);