/* ---------------------------------------------------------------------------------
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);