From 9fd7af7733833644fef331802f34847ce5dc9710 Mon Sep 17 00:00:00 2001 From: Anton Bagliy <taccessviolation@gmail.com> Date: Thu, 14 Nov 2019 20:33:34 +0300 Subject: [PATCH] ADD: example of download widget for discipline tablesorter #519 --- .../jquery.tablesorter.widget-output.min.js | 4 + media/js/office/disciplines.js | 76 ++++++++++++++++++- .../views/office/disciplines/index.twig | 4 +- 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 media/js/libs/jquery.tablesorter.widget-output.min.js diff --git a/media/js/libs/jquery.tablesorter.widget-output.min.js b/media/js/libs/jquery.tablesorter.widget-output.min.js new file mode 100644 index 000000000..5c9dde2a8 --- /dev/null +++ b/media/js/libs/jquery.tablesorter.widget-output.min.js @@ -0,0 +1,4 @@ +(function(factory){if (typeof define === 'function' && define.amd){define(['jquery'], factory);} else if (typeof module === 'object' && typeof module.exports === 'object'){module.exports = factory(require('jquery'));} else {factory(jQuery);}}(function(jQuery){ + +/*! Widget: output - updated 9/27/2017 (v2.29.0) */ +!function(b){"use strict";var y=b.tablesorter,S=y.output={event:"outputTable",noDblClick:600,lastEvent:0,busy:!1,regexQuote:/([\n\t\x09\x0d\x0a]|<[^<]+>)/,regexBR:/(<br([\s\/])?>|\n)/g,regexIMG:/<img[^>]+alt\s*=\s*['"]([^'"]+)['"][^>]*>/i,regexHTML:/<[^<]+>/g,replaceCR:"\r\n",replaceTab:"\t",popupTitle:"Output",popupStyle:"width:100%;height:100%;margin:0;resize:none;",message:"Your device does not support downloading. Please try again in desktop browser.",init:function(e){e.$table.off(S.event).on(S.event,function(t){t.stopPropagation(),!S.busy&&t.timeStamp-S.lastEvent>S.noDblClick&&(S.lastEvent=t.timeStamp,S.busy=!0,S.process(e,e.widgetOptions))})},processRow:function(t,e,o,u){var n,r,a,p,i,l,s,c,d,f,_=t.widgetOptions,w=[],m=_.output_duplicateSpans,g=o&&u&&_.output_headerRows&&b.isFunction(_.output_callbackJSON),h=0,v=e.length;for(p=0;p<v;p++)for(w[p]||(w[p]=[]),h=0,a=(r=e.eq(p).children()).length,s=0;s<a;s++){if((n=r.eq(s)).filter("[rowspan]").length)for(c=parseInt(n.attr("rowspan"),10)-1,f=S.formatData(t,_,n,o,s),i=1;i<=c;i++)w[p+i]||(w[p+i]=[]),w[p+i][h]=o?f:m?f:"";if(n.filter("[colspan]").length)for(d=parseInt(n.attr("colspan"),10)-1,f=S.formatData(t,_,n,o,s),l=0;l<d;l++)if(n.filter("[rowspan]").length)for(c=parseInt(n.attr("rowspan"),10),i=0;i<c;i++)w[p+i]||(w[p+i]=[]),w[p+i][h+l]=g?_.output_callbackJSON(n,f,h+l)||f+"("+(h+l)+")":o?f:m?f:"";else w[p][h+l]=g?_.output_callbackJSON(n,f,h+l)||f+"("+(h+l)+")":o?f:m?f:"";for(;void 0!==w[p][h];)h++;w[p][h]=w[p][h]||S.formatData(t,_,n,o,h),h++}return y.output.removeColumns(t,_,w)},removeColumns:function(t,e,o){var u,n,r,a=[],p=o.length;for(u=0;u<p;u++)for(n=o[u],a[u]=[],r=0;r<t.columns;r++)e.output_hiddenColumnArray[r]||a[u].push(n[r]);return a},process:function(t,e,o,u){var n,r,a,p,i,l,s,c=window.JSON&&JSON.hasOwnProperty("stringify"),d=0,f=(e.output_separator||",").toLowerCase(),_="json"===f,w="array"===f,m=_||w?",":e.output_separator,g=e.output_saveRows,h=t.$table;for(e.output_regex=new RegExp("("+(/\\/.test(m)?"\\":"")+m+")"),e.output_hiddenColumnArray=[],d=0;d<t.columns;d++)e.output_hiddenColumnArray[d]=-1<b.inArray(d,e.output_ignoreColumns)||!e.output_hiddenColumns&&"none"===t.$headerIndexed[d].css("display")&&!t.$headerIndexed[d].hasClass("tablesorter-scroller-hidden-column");if(r=h.children("thead").children("tr").not("."+(y.css.filterRow||"tablesorter-filter-row")).filter(function(){return e.output_hiddenColumns||"none"!==b(this).css("display")}),a=S.processRow(t,r,!0,_),o||(o=h.children("tbody").children("tr").not(t.selectorRemove)),o="function"==typeof g?o.filter(g):/^f/.test(g)?o.not("."+(e.filter_filteredRow||"filtered")):/^v/.test(g)?o.filter(":visible"):/^[.#:\[]/.test(g)?o.filter(g):o,p=S.processRow(t,o),e.output_includeFooter&&(p=p.concat(S.processRow(t,h.children("tfoot").children("tr:visible")))),i=a.length,_){for(f=[],l=p.length,d=0;d<l;d++)s=a[1<i&&e.output_headerRows?d%i:i-1],f.push(S.row2Hash(s,p[d]));n=c?JSON.stringify(f):f}else f=e.output_includeHeader?(s=[a[1<i&&e.output_headerRows?d%i:i-1]],S.row2CSV(e,e.output_headerRows?a:s,w).concat(S.row2CSV(e,p,w))):S.row2CSV(e,p,w),n=w&&c?JSON.stringify(f):f.join("\n");if(u)return n;if(b.isFunction(e.output_callback)){if(!1===(s=e.output_callback(t,n,t.pager&&t.pager.ajaxObject.url||null)))return void(S.busy=!1);"string"==typeof s&&(n=s)}/p/i.test(e.output_delivery||"")?S.popup(n,e.output_popupStyle,_||w):S.download(t,e,n),S.busy=!1},row2CSV:function(t,e,o){var u,n,r=[],a=e.length;for(n=0;n<a;n++)u=(e[n]||[]).join("").replace(/\"/g,""),0<(e[n]||[]).length&&""!==u&&(r[r.length]=o?e[n]:e[n].join(t.output_separator));return r},row2Hash:function(t,e){var o,u={},n=e.length;for(o=0;o<n;o++)o<t.length&&(u[t[o]]=e[o]);return u},formatData:function(t,e,o,u,n){var r=o.attr(e.output_dataAttrib),a=void 0!==r?r:o.html(),p=(e.output_separator||",").toLowerCase(),i="json"===p||"array"===p,l=a.replace(/\"/g,e.output_replaceQuote||"“");return a=(l=e.output_trimSpaces?l.replace(S.regexBR,""):l.replace(S.regexBR,S.replaceCR).replace(/\t/g,S.replaceTab)).match(S.regexIMG),e.output_includeHTML||null===a||(l=a[1]),l=e.output_includeHTML&&!u?l:l.replace(S.regexHTML,""),l=e.output_trimSpaces||u?b.trim(l):l,l=(p=!i&&(e.output_wrapQuotes||e.output_regex.test(l)||S.regexQuote.test(l)))?'"'+l+'"':l,"function"==typeof e.output_formatContent?e.output_formatContent(t,e,{isHeader:u||!1,$cell:o,content:l,columnIndex:n,parsed:t.parsers[n].format(l,t.table,o[0],n)}):l},popup:function(e,o,u){var n=window.open("",S.popupTitle,o);try{n.document.write("<html><head><title>"+S.popupTitle+'</title></head><body><textarea wrap="'+(u?"on":"off")+'" style="'+S.popupStyle+'">'+e+"\n</textarea></body></html>"),n.document.close(),n.focus()}catch(t){return n.close(),S.popup(e,o,u)}return!0},download:function(t,e,o){if("function"==typeof e.output_savePlugin)return e.output_savePlugin(t,e,o);var u,n,r,a,p=window.navigator,i=document.createElement("a");if(/(iP)/g.test(p.userAgent))return alert(S.message),!1;try{r=!!new Blob}catch(t){r=!1}return r?(window.URL=window.URL||window.webkitURL,a=/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.output_encoding)?["\ufeff",o]:[o],n=new Blob(a,{type:e.output_encoding}),p.msSaveBlob?p.msSaveBlob(n,e.output_saveFileName):(i.href=window.URL.createObjectURL(n),i.download=e.output_saveFileName,document.createEvent&&((u=document.createEvent("MouseEvents")).initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),i.dispatchEvent(u))),!1):(window.open(e.output_encoding+encodeURIComponent(o)+"?download","_self"),!0)},remove:function(t){t.$table.off(S.event)}};y.addWidget({id:"output",options:{output_separator:",",output_ignoreColumns:[],output_hiddenColumns:!1,output_includeFooter:!1,output_includeHeader:!0,output_headerRows:!1,output_dataAttrib:"data-name",output_delivery:"popup",output_saveRows:"filtered",output_duplicateSpans:!0,output_replaceQuote:"“;",output_includeHTML:!1,output_trimSpaces:!0,output_wrapQuotes:!1,output_popupStyle:"width=500,height=300",output_saveFileName:"mytable.csv",output_formatContent:null,output_callback:function(){return!0},output_callbackJSON:function(t,e,o){return e+"("+o+")"},output_encoding:"data:application/octet-stream;charset=utf8,",output_savePlugin:null},init:function(t,e,o){S.init(o)},remove:function(t,e){S.remove(e)}})}(jQuery);return jQuery;})); diff --git a/media/js/office/disciplines.js b/media/js/office/disciplines.js index f931b7f5a..f215258d0 100644 --- a/media/js/office/disciplines.js +++ b/media/js/office/disciplines.js @@ -41,7 +41,7 @@ $(() => { // table class name template to match to include a widget widgetClass: 'widget-{name}', // initialize zebra striping and column styling of the table - widgets : ["zebra", "filter"], + widgets : ["zebra", "filter", "output"], // использование фильтров в tablesorter // https://mottie.github.io/tablesorter/docs/example-widget-filter.html widgetOptions: { @@ -59,11 +59,85 @@ $(() => { // disabled by using -> headers: { 1: { filter: false } } OR add class="filter-false" // if you set this to false, make sure you perform a search using the second method below filter_columnFilters : true, + output_separator : ',', // ',' 'json', 'array' or separator (e.g. ';') + output_ignoreColumns : [0], // columns to ignore [0, 1,... ] (zero-based index) + output_hiddenColumns : false, // include hidden columns in the output + output_includeFooter : true, // include footer rows in the output + output_includeHeader : true, // include header rows in the output + output_headerRows : false, // output all header rows (if multiple rows) + output_dataAttrib : 'data-name', // data-attribute containing alternate cell text + output_delivery : 'd', // (p)opup, (d)ownload + output_saveRows : 'f', // (a)ll, (v)isible, (f)iltered, jQuery filter selector (string only) or filter function + output_duplicateSpans: true, // duplicate output data in tbody colspan/rowspan + output_replaceQuote : '\u201c;', // change quote to left double quote + output_includeHTML : true, // output includes all cell HTML (except the header cells) + output_trimSpaces : false, // remove extra white-space characters from beginning & end + output_wrapQuotes : false, // wrap every cell output in quotes + output_popupStyle : 'width=580,height=310', + output_saveFileName : 'disciplines.csv', + // callback executed after the content of the table has been processed + output_formatContent : function(config, widgetOptions, data) { + // data.isHeader (boolean) = true if processing a header cell + // data.$cell = jQuery object of the cell currently being processed + // data.content = processed cell content (spaces trimmed, quotes added/replaced, etc) + // data.columnIndex = column in which the cell is contained + // data.parsed = cell content parsed by the associated column parser + return data.content; + }, + // callback executed when processing completes + output_callback : function(config, data, url) { + // return false to stop delivery & do something else with the data + // return true OR modified data (v2.25.1) to continue download/output + return true; + }, + // callbackJSON used when outputting JSON & any header cells has a colspan - unique names required + output_callbackJSON : function($cell, txt, cellIndex) { + return txt + '(' + cellIndex + ')'; + }, + // the need to modify this for Excel no longer exists + output_encoding : 'data:application/octet-stream;charset=utf8,', + // override internal save file code and use an external plugin such as + // https://github.com/eligrey/FileSaver.js + output_savePlugin : null /* function(config, widgetOptions, data) { + var blob = new Blob([data], {type: widgetOptions.output_encoding}); + saveAs(blob, widgetOptions.output_saveFileName); + } */ } }); + // taken from https://mottie.github.io/tablesorter/docs/example-widget-output.html + $("#tableGroup").find('.download').click(function() { + $this = $("#tableGroup"); + var typ, + $table = $this.find('table'), + wo = $table[0].config.widgetOptions, + val = $this.find('.output-filter-all :checked').attr('class'); + wo.output_saveRows = val === 'output-filter' ? 'f' : + val === 'output-visible' ? 'v' : + // checked class name, see table.config.checkboxClass + val === 'output-selected' ? '.checked' : + val === 'output-sel-vis' ? '.checked:visible' : + 'a'; + val = $this.find('.output-download-popup :checked').attr('class'); + wo.output_delivery = val === 'output-download' ? 'd' : 'p'; + wo.output_separator = $this.find('.output-separator-input').val(); + wo.output_replaceQuote = $this.find('.output-replacequotes').val(); + wo.output_trimSpaces = $this.find('.output-trim').is(':checked'); + wo.output_includeHTML = $this.find('.output-html').is(':checked'); + wo.output_wrapQuotes = $this.find('.output-wrap').is(':checked'); + wo.output_saveFileName = $this.find('.output-filename').val(); + + // first example buttons, second has radio buttons + wo.output_includeHeader = $this.find('button.output-header').is(".active"); + // footer not included in second example + wo.output_includeFooter = $this.find('.output-footer').is(".active"); + + $table.trigger('outputTable'); + return false; + }); + $('.disciplineInactiveSwitch').click(function () { let idString = $(this).attr('id'); diff --git a/~dev_rating/application/views/office/disciplines/index.twig b/~dev_rating/application/views/office/disciplines/index.twig index 0b73f08e6..3ae76b51c 100644 --- a/~dev_rating/application/views/office/disciplines/index.twig +++ b/~dev_rating/application/views/office/disciplines/index.twig @@ -7,6 +7,7 @@ {{ HTML.script('static/js/libs/jquery.tablesorter.min.js')|raw }} {{ HTML.script('static/js/libs/jquery.tablesorter.widgets.min.js')|raw }} + {{ HTML.script('static/js/libs/jquery.tablesorter.widget-output.min.js')|raw }} {{ HTML.script('static/js/office/disciplines.js')|raw }} @@ -16,7 +17,8 @@ <p>Всего: {{ Disciplines | length }}</p> - <div class="officeList"> + <div id="tableGroup" class="officeList"> + <button type="button" class="btn btn-default download">Output</button> <table id="disciplineTable" class="tablesorter" style="table-layout: fixed; width: 100%;"> <thead> <tr> -- GitLab