Skip to content

Instantly share code, notes, and snippets.

@mohitmayank
Last active December 31, 2015 20:49
Show Gist options
  • Save mohitmayank/8043113 to your computer and use it in GitHub Desktop.
Save mohitmayank/8043113 to your computer and use it in GitHub Desktop.
/*global define:false */
define([
'underscore',
'jquery',
'backbone',
'marionette',
'./templates/TableViewTmpl',
'./templates/TableRowTmpl',
'vendor/downloadify/swfobject',
'vendor/downloadify/downloadify',
'Timer'
'plugin/jquery/tablesorter',
'plugin/jquery/tablesorter.widgets',
//'plugin/jquery/tablesorter.widgets-filter-formatter',
'plugin/jquery/jquery.iframe-transport',
'plugin/jquery/jquery.fileupload',
//'jquery.ui.widget',
'vendor/bootstrap/plugins/bootstrap-datetimepicker'
], function(_, $, Backbone, Marionette, TableViewTmpl, TableRowTmpl, swfobject, Downloadify, Timer) {
'use strict';
var tagsToReplace = {
'&': '&',
'<': '&lt;',
'>': '&gt;'
};
var replaceTag = function(tag) {
return tagsToReplace[tag] || tag;
};
var safe_tags_replace = function(str) {
str = str.replace(/[<>]/g, replaceTag);
return str;
};
var noop = function(){};
var noopFalse = function(){return false;};
/*************************\
UI Datepicker (2 inputs)
\*************************/
var uiDatepicker = function($cell) {
var $minDateField = $('<div class="input-prepend minDateFilterField"><span class="add-on"><i data-time-icon="icon-chevron-right" data-date-icon="icon-chevron-right"></i></span><input class="forceHide" type="text"></div>').appendTo($cell);
$minDateField.datetimepicker({
pickDate: true,
pickTime: false,
format : "dd-MM-yyyy"
});
var minDatePicker = $minDateField.find('input');
var $input = $('<input type="text" class="dateFilterField"/>').appendTo($cell);
var $maxDateField = $('<div class="input-append maxDateFilterField"><input class="forceHide" type="text"><span class="add-on"><i data-time-icon="icon-chevron-left" data-date-icon="icon-chevron-left"></i></span></div>').appendTo($cell);
$maxDateField.datetimepicker({
pickDate: true,
pickTime: false,
format : "dd-MM-yyyy"
});
var maxDatePicker = $maxDateField.find('input');
$minDateField.on('changeDate', function(){
if(maxDatePicker.val() !== '') {
$input.val(minDatePicker.val() + ' - ' + maxDatePicker.val());
} else {
$input.val('>= ' + minDatePicker.val());
}
$input.trigger('search');
});
$maxDateField.on('changeDate', function(){
if(minDatePicker.val() !== '') {
$input.val(minDatePicker.val() + ' - ' + maxDatePicker.val());
} else {
$input.val('<= ' + maxDatePicker.val());
}
$input.trigger('search');
});
$input.change(function(){
if($input.val() === '') {
minDatePicker.val('');
maxDatePicker.val('');
}
return false;
});
return $input;
};
// var select2Picker = function($cell, index) {
// return $input;
// };
return Marionette.ItemView.extend({
template : TableViewTmpl,
constructor: function(options){
Marionette.ItemView.prototype.constructor.apply(this, _.toArray(arguments));
options = options || {};
_.bindAll(this,
'renderUploader',
'renderDownloader',
'startTableSorter',
'addModel',
'removeModel',
'addRows',
'removeRow'
);
_.extend(this, _.pick(options, [
'columns',
'strikeRow',
'colorRow',
'gridName',
'uploadUrl',
'autoFilter',
'enableUpload',
'title'
]));
if(_.isFunction(this.columns)) {
this.columns = this.columns.call(this);
}
_.each(this.columns, function(item){
item.fieldEscaped = item.field.replace('.', '_dc_');
item.colVals = [];
});
this.csvColumns = _.pluck(this.csv, 'field');
this.csvHeaders = _.pluck(this.csv, 'title');
this.rows = {};
},
enableUpload : false,
autoFilter : false,
columns : [],
gridName : 'download',
title : function(){
return this.gridName;
},
uploadUrl : function(){
if(this.collection) {
return this.collection.uploadUrl();
} else {
return '';
}
},
ui : {
'buttonOnfiltersort' : 'button.onfiltersort',
'columnMenuInput' : '.columnMenuInput',
'buttonTablePrint' : 'button.tablePrint',
'buttonFilterReset' : 'button.filterReset',
'buttonDownloadify' : 'button.downloadifyButton',
'tableGrid' : '.tableGrid',
'gridRecordCountEl' : '.gridRecordCount',
'table' : 'table',
'tbody' : 'tbody',
'gridSortingInfo' : '.gridSortingInfo'
},
events: {
'click tr.tableDataRow' : 'onRowClick',
'dblclick tr.tableDataRow' : 'onRowDblClick',
'click @ui.buttonOnfiltersort' : 'startTableSorter',
'click @ui.columnMenuInput' : 'columnMenuEvent',
'click @ui.buttonTablePrint' : 'printTable',
'click @ui.buttonFilterReset' : 'filterReset',
'click @ui.buttonDownloadify' : 'uriDownload'
},
onRowClick: function(e) {
this.trigger('onRowClick', e.currentTarget.id);
},
onRowDblClick: function(e) {
this.trigger('onRowDblClick', e.currentTarget.id);
},
printTable : function(){
var title = _.result(this, 'title');
var printWindow = window.open('', title, 'height=400,width=600');
printWindow.document.write('<html><head><title>'+title+'</title>');
printWindow.document.write('<style>.columnHide, .filtered, .tablesorter-filter-row {display: none} table, tr, td, th {border : solid 1px black; border-collapse : collapse} td, th {padding: 2px;}</style>');
printWindow.document.write('</head><body>');
printWindow.document.write('<h4>' + title + '</h4>');
printWindow.document.write(this.ui.tableGrid.html());
printWindow.document.write(this.ui.gridRecordCountEl.html());
printWindow.document.write('</body></html>');
printWindow.print();
printWindow.close();
return true;
},
filterReset : function(){
this.ui.table.trigger('filterReset');
},
columnMenuEvent : function(e){
var colClass = e.currentTarget.value;
var hide = true;
if (e.currentTarget.checked) {
self.$('.'+colClass).removeClass('columnHide');
hide = false;
} else {
self.$('.'+colClass).addClass('columnHide');
}
_.each(this.columns, function(col){
if(col.fieldEscaped === colClass)
{
col.hidden = hide;
}
});
},
uriDownload : function(){
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(this.toCSV());
window.open(uri);
},
strikeRow : noopFalse,
colorRow : noopFalse,
sortOn : false,
lineCount : 0,
collectionEvents : {
'add' : 'addModel',
'remove' : 'removeModel'
},
addModel : function(model){
var rows = {};
rows[model.get('_id')] = model;
this.addRows(rows);
},
removeModel : function(model){
this.removeRow(model.get('_id'));
},
fetchColVal : function (model, key) {
try{
var n=key.split(".");
var test = model;
var schema = this._args.schema;
if(!test)
{
return '';
}
for (var i=0;i<n.length;i++)
{
if(test[n[i]])
{
test = test[n[i]];
} else if (test.get) {
test = test.get(n[i]);
}
else
{
return '';
}
}
if(!_.isString(test) && test.toString) {
test = test.toString();
}
return safe_tags_replace(test);
}
catch(err){
return '';
}
},
addRows : function(rows){
_.each(rows, function(row, id){
var style = this.colorRow(row);
if(style) {
style = 'style="background-color:' + style + '"';
} else {
style = '';
}
var values = {};
_.each(this.columns, function(item){
var v = this.fetchColVal(row, item.field);
item.colVals.push(v);
values[item.field] = v;
}, this);
// console.log(values);
this.ui.tbody.append(TableRowTmpl({
_id : id,
columns : this.columns,
values : values,
strikeRow : this.strikeRow(row),
style : style
}));
this.lineCount++;
this.rows[id] = values;
}, this);
this._updateTimer.reset();
},
removeRow : function(id) {
this.$('#'+id).remove();
this.lineCount--;
if(this.lineCount < 0)
{
this.lineCount = 0;
}
this._updateTimer.reset();
},
startTableSorter : function(){
if(!this.sortOn)
{
var that = this;
_.defer(function(){
var filterFormatter = {};
//var filterFunctions = {};
_.each(that.columns, function(item, index){
if(item.schema.type === 'Date') {
filterFormatter[index] = uiDatepicker;
}
// else {
//filterFunctions[index] = true;
// }
});
that.ui.table.tablesorter({
dateFormat : 'ddmmyyyy',
theme: 'bootstrap',
widthFixed: false,
headerTemplate: '{content} {icon}',
// cssAsc : 'tableViewSortedCol',
// cssDesc : 'tableViewSortedCol',
headers: {
/*
0: {
sorter: false,
filter: false
}
*/
},
widgets: [
//'reorder',
'resizable',
'uitheme',
'filter',
//'zebra',
'stickyHeaders'
],
widgetOptions: {
filter_liveSearch : true,
filter_searchDelay : 800,
// // reorder_axis: 'xy',
// // reorder_complete: function() {
// // that.filterPatch();
// // },
// // zebra: [
// 'even',
// 'odd'
// ]
filter_formatter : filterFormatter,
//filter_functions : filterFunctions
}
});
that.sortOn = true;
that.ui.table.bind('filterEnd', function() {
that.patchLineNumbers();
});
that.ui.table.bind('sortStart', function() {
that.ui.gridSortingInfo.show();
});
that.ui.table.bind('sortEnd', function() {
that.ui.gridSortingInfo.hide();
});
_.each(that.columns, function(item, index) {
var _classes = item.fieldEscaped + ' ' + (item.hidden ? 'columnHide' : '');
that.$('.tablesorter-filter-row td:eq(' + index + ')').addClass(_classes);
});
});
this.ui.buttonOnfiltersort.hide();
this.ui.buttonFilterReset.show();
}
},
patchLineNumbers: function(length) {
var that = this;
_.defer(function(){
try {
var length = that.lineCount;
var suffix = '';
if(that.sortOn)
{
that.ui.table.trigger('update');
that.ui.table.trigger('appendCache');
length = that.$('tr.tableDataRow:not(.filtered)').size();
if(length != that.lineCount)
{
if(that.lineCount <= 0) {
suffix = '';
}else if(that.lineCount === 1){
suffix = ' / ' + NSpace.Language.Generic.OneRecord;
}else{
suffix = ' / ' + that.lineCount + ' ' + NSpace.Language.Generic.Records;
}
}
}
if(length <= 0)
{
that.ui.gridRecordCountEl.removeClass('label-warning').removeClass('label-success').html(NSpace.Language.Generic.NoRecord + suffix);
}
else if(length === 1)
{
that.ui.gridRecordCountEl.removeClass('label-warning').addClass('label-success').html(NSpace.Language.Generic.OneRecord + suffix);
}
else
{
that.ui.gridRecordCountEl.removeClass('label-warning').addClass('label-success').html(length + ' ' + NSpace.Language.Generic.Records + suffix);
}
} catch(e){
}
});
_.defer(function(){
_.each(that.columns, function(item, index){
item.colVals = _.unique(item.colVals);
}, that);
});
},
serializeData : function(){
return {
columns : this.columns
};
},
render : function(){
Marionette.ItemView.prototype.render.apply(this, _.toArray(arguments));
this.ui.gridSortingInfo.hide();
this._updateTimer = new Timer(1000, this.patchLineNumbers, function(){
this.ui.gridRecordCountEl.addClass('label-warning').removeClass('label-success').html('Loading ...');
},this);
this._updateTimer.reset();
// if(this.collection) {
// var self = this;
// this.collection.fetch();
// }
if(this.autoFilter) {
_.defer(this.startTableSorter);
}
_.defer(this.renderDownloader);
_.defer(this.renderUploader);
},
renderUploader : function(){
var self = this;
if (self.enableUpload) {
self.$('.fileupload').fileupload({
url: _.result(self, 'uploadUrl'),
dataType: 'json',
formData: {
source: self.gridName
},
start: function() {
self.$('.fileUploadModal').modal('show');
},
cache: false,
done: function(e, data) {
self.collection.fetch();
if (data.result.success) {
self.$('.fileUploadDonelabel').removeClass('label-important').addClass('label-success').html('Success');
} else {
self.$('.fileUploadDonelabel').removeClass('label-success').addClass('label-important').html('Error');
}
self.$('.modal-body').html('<p>' + data.result.msg + '</p>');
if (data.result.dirty) {
var dirty = '<dl class="dl-horizontal">';
_.each(data.result.dirty, function(val, key) {
dirty += '<dt>Row ' + key + '</dt>';
dirty += '<dd>' + val + '</dd>';
});
self.$('.modal-body').append(dirty);
}
self.triggerMethod('upload:done', self);
},
progressall: function(e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
self.$('.bar').css('width', progress + '%');
}
}).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');
} else {
self.$('.fileinput-button').hide();
}
},
renderDownloader : function(){
var self = this;
self.$('.downloadifyTarget').downloadify({
filename: function() {
return self.gridName + '.csv';
},
data: function() {
return self.toCSV();
},
onComplete: noop,
onCancel: noop,
onError: noop,
swf: 'public/media/downloadify.swf',
downloadImage: 'public/images/download_small.png',
width: 40,
height: 30,
transparent: true,
append: true
});
self.$('.downloadifyTarget object').css('display', 'block');
if (swfobject.hasFlashPlayerVersion('10')) {
self.ui.buttonDownloadify.hide();
} else {
self.ui.buttonDownloadify.show();
}
},
toCSV: function() {
var self = this;
var dataView = [];
this.$('tr.tableDataRow:not(.filtered)').each(function(){
dataView.push(self.rows[$(this).attr('id')]);
});
var ar = _.map(dataView, function(value) {
return _.pick(value, self.csvColumns);
});
var l = self.csvColumns.length;
var csvArray = [];
csvArray.push(_.map(self.csvHeaders, function(val) {
return '"' + val.replace(/"/g, '""') + '"';
}).join(','));
_.each(ar, function(line) {
var tmp = [];
console.log(line);
for (var i = 0; i < l; i++) {
if(line[self.csvColumns[i]])
{
if(line[self.csvColumns[i]].replace) {
tmp.push('"' + line[self.csvColumns[i]].replace(/"/g, '""') + '"');
} else {
tmp.push('"' + line[self.csvColumns[i]].toString().replace(/"/g, '""') + '"');
}
}
else
{
tmp.push("");
}
}
csvArray.push(tmp.join(','));
});
return csvArray.join('\n');
}
});
});
<tr id='<%=_id %>' class='tableDataRow <%= strikeRow ? "strikeRow" : ""%>' <%=style%>>
<% _.each(columns, function(item){ %>
<td <%=style%> class='<%= item.fieldEscaped %> <%=item.hidden ? "columnHide" : "" %>'><%=values[item.field] %></td>
<% }); %>
</tr>
<div class='tableToolBar'>
<span class="gridRecordCount label">...</span>
<span class="gridSortingInfo label label-inverse"><i class='icon-refresh'></i> ...</span>
<div class="btn-group pull-right columnMenuButton">
<a class="btn btn-info dropdown-toggle" data-toggle="dropdown" href="#">
<i class='icon-check icon-white'></i>
<span class="caret"></span>
</a>
<ul class="dropdown-menu columnMenu">
<% _.each(columns, function(item){ %>
<li>
<label class="checkbox">
<input class='columnMenuInput' type="checkbox" value="<%= item.fieldEscaped %>" <%=item.hidden ? "" : "checked" %>>
<%=item.title %>
</label>
</li>
<% }); %>
</ul>
</div>
<button class="pull-right btn btn-info onfiltersort"><i class='icon-filter icon-white'></i></button>
<button class="pull-right btn btn-info filterReset" style='display:none'><i class='icon-refresh icon-white'></i></button>
<button class='pull-right btn btn-info tablePrint'><i class='icon-print icon-white'></i></button>
<div class='pull-right downloadifyTarget'></div>
<button class='btn btn-info downloadifyButton pull-right'><i class='icon-arrow-down icon-white'></i></button>
<div class='pull-right'>
<span class='btn btn-info fileinput-button'>
<i class='icon-arrow-up icon-white'></i>
<span></span>
<!-- The file input field used as target for the file upload widget -->
<input class='fileupload' type='file' name='files'>
</span>
</div>
</div>
<div class='clearfix'></div>
<div class='tableGrid'>
<table class='table table-striped table-condensed table-bordered'>
<thead>
<tr>
<% _.each(columns, function(item){ %>
<th class='<%= item.fieldEscaped %> <%=item.hidden ? "columnHide" : "" %>'><%=item.title %></th>
<% }); %>
</tr>
</thead>
<tbody>
</tbody>
<!--tfoot>
<tr>
<% _.each(columns, function(item){ %>
<th class='<%= item.fieldEscaped %> <%=item.hidden ? "columnHide" : "" %>'><%=item.title %></th>
<% }); %>
</tr>
</tfoot-->
</table>
</div>
<div class="fileUploadModal modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3><i class='icon-arrow-up'></i> <span class="fileUploadDonelabel label label-important"></span></h3>
</div>
<div class="modal-body">
<p></p>
</div>
<div class="modal-footer">
<div class='pull-right' style='margin-left: 15px; margin-top:-6px;'>
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
<div class='progress progress-striped'>
<div class='bar'></div>
</div>
</div>
</div>
function(_delay, _callback, _onStart, _context) {
var args = arguments,
_timerId, _start = 0,
_remaining = _delay,
_running = false;
if (!_onStart) {
_onStart = function(){};
}
if (!_context) {
_context = this;
}
this.start = function(delay) {
if (!_running) {
if (delay) {
_delay = delay;
}
if(!_running)
{
_onStart.apply(_context, Array.prototype.slice.call(args, 3, args.length));
}
_running = true;
_start = new Date();
_timerId = window.setTimeout(function() {
_callback.apply(_context, Array.prototype.slice.call(args, 3, args.length));
}, _delay);
}
};
this.stop = function() {
if (_running) {
window.clearTimeout(_timerId);
}
_running = false;
_remaining = _delay;
};
this.pause = function() {
this.stop();
_remaining -= new Date() - _start;
};
this.resume = function() {
this.start(_remaining);
};
this.reset = function(delay) {
this.stop();
this.start(delay);
};
this.setTime = function(delay) {
if (delay) {
_delay = delay;
}
};
this.set = this.start;
this.clear = this.stop;
this.remaining = function() {
return new Date() - _start;
};
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment