Tablesorter custom equations on calculated data - tablesorter

I need to sum two columns, then find the difference between those two. The use case is simple: in one column I have all the purchases and the second one contains all the transactions, the user will see the difference.
Here is the relevant code for the calculation:
<tfoot>
<tr>
<th>Total</th>
<th data-math="col-sum"></th>
<th data-math="col-sum"></th>
<th data-math="row-difference"></th>
</tr>
</tfoot>
And the formula can be something really simple like
$.tablesorter.equations['difference'] = function(arry) {
return arry[1] - arry[2];
};
How would you make it work?

The way the math widget is set up, it prioritizes rows calculations before column calculations. So in this case, the footer row will try to calculate the row difference before calculating the column sum.
To fix this, change the math_priority widget option so that the 'col' comes before 'row' (demo):
$(function() {
$.tablesorter.equations.difference = function(arry) {
return arry[1] - arry[2];
};
$("table").tablesorter({
theme: 'blue',
widgets: ['math', 'zebra'],
widgetOptions: {
// default [ 'row', 'above', 'below', 'col' ]
// move 'col' first in this case
math_priority: ['col', 'row', 'above', 'below']
}
});
});

Related

Enabling jQueryUI tooltips for disabled fields and buttons

I would like to have the jQueryUI tooltip work on disabled Buttons and Inputs as well. How can I make this happen?
Included is a sample showing various inputs and buttons, both enabled and disabled and how the jQueryUI tooltip seems to skip evaluation of the disabled elements.
Please click on the field/button labels to open the tooltips. My users don't like hover based tooltips on INPUTs and hover does not work on mobile.
If you hover over the disabled INPUT and BUTTON the browser tooltip will appear but not the jQueryUI version. This is obvious because the browser version does not evaluate the HTML but shows it raw.
Note: This question is NOT a duplicate of Show tooltip for disabled items, because that question does not ask about actual disabled tags (buttons or inputs)
// Disable HOVER tooltips for input elements since they are just annoying.
$("input[title]").tooltip({
disabled: true,
content: function() {
// Allows the tooltip text to be treated as raw HTML.
return $(this).prop('title');
},
close: function(event, ui) {
// Disable the Tooltip once closed to ensure it can only open via click.
$(this).tooltip('disable');
}
});
// Basic tooltips for the Buttons only but format HTML.
$("button[title]").tooltip({
content: function() {
// Allows the tooltip text to be treated as raw HTML.
return $(this).prop('title');
}
});
/* Manually Open the Tooltips */
$(".ui-field-help").click(function(e) {
var forId = e.target.getAttribute('for');
if (forId) {
var $forEl = $("#" + forId);
if ($forEl.length)
$forEl.tooltip('enable').tooltip('open');
}
});
// The following is only to load the CSS....
function loadCSS(filename) {
var file = document.createElement("link");
file.setAttribute("rel", "stylesheet");
file.setAttribute("type", "text/css");
file.setAttribute("href", filename);
document.head.appendChild(file);
}
loadCSS("https://code.jquery.com/ui/1.12.1/themes/start/jquery-ui.css");
.ui-field-help {
text-decoration: underline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<table width=100%>
<tr>
<td><label for="A000" class="ui-field-help">Enabled Input</label></td>
<td><input type="Text" id="A000" title="title #A000<hr>Fancy <i>HTML</i>..."></td>
</tr>
<tr>
<td><label for="B000" class="ui-field-help">Disabled Input</label></td>
<td><input disabled=disabled type="Text" id="B000" title="title #B000<hr>Fancy <i>HTML</i>..."></td>
</tr>
<tr>
<td><label for="E000" class="ui-field-help">Enabled Button</label></td>
<td><button id="E000" title="title #E000<hr>Fancy <i>HTML</i>...">Enabled Button</button></td>
</tr>
<tr>
<td><label for="D000" class="ui-field-help">Disabled Button</label></td>
<td><button disabled=disabled type="Text" id="D000" title="title #D000<hr>Fancy <i>HTML</i>...">Disabled Button</button></td>
</tr>
</table>
After not finding the answer I resolved the problem by looping through all disabled items with a [title] and processing them individually to move the tooltip to the label for that input element.
$("[title]:disabled", $container).each(function (ix, el) {
// Since the jQueryUI tooltips don't work on disabled controls we remove them
// and then attempt to add them to the elements label.
var title = el.title;
el.title = ''; // Clear the title to avoid the browser tooltip
// Look for a Label attached to the element and add the tooltip there.
$('label[for=' + el.id + ']').attr('title', title).tooltip({
content: function () {
// Allows the tooltip text to be treated as raw HTML.
return $(this).prop('title');
}
});
});

Generate a column dynamically with JQuery DataTables where table is based on a model

In an ASP.Net MVC application I have a table that's based on a model passed to the view. For this reason, the table is not based on a Json and the fields have no column names that I can reference in the 'columns'[] section of the script (or at least I don't know how!...). Still, the table works fine except that I can't manage to generate a calculated field. In all the various experiments I keep getting a NaN or undefined result, depending on the various attempts, and I understand this is because evidently I'm not referencing the proper data value, but how can I do that if I don't have column names?
The table is properly structured, thead, tbody and tfoot have the same number of columns. This is the html for the table:
<table id="mainTable" class="table table-hover">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.Value1)</th>
<th>#Html.DisplayNameFor(model => model.Value2)</th>
<th>test</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Value1)</td>
<td>#Html.DisplayFor(modelItem => item.Value2)</td>
<td></td>
</tr>
}
</tbody>
<tfoot><tr><th></th><th></th><th></th></tr></tfoot>
</table>
The render function on first and second columns works just fine. The third column is where I am trying to calculate and display the difference between first and second column, and that's where I get NaN or undefined. This is the script:
<script>
$(document).ready(function () {
// DataTable
var table = $('#mainTable').DataTable({
responsive: true,
columns: [
{ render: function (data, type, row) { return data + '$' } },
{ render: function (data, type, row) { return data + '$' } },
{ render: function (data, type, row) { return (row.Value1 - row.Value2) + '$' }}]
});
});
</script>
This is the result I'm getting on this particular attempt. I've tried other versions, unfortunately with similar disappointing results:
Value 1 Value 2 test
200.00$ 100.00$ NaN$
etc...
I have also tried this:
columns: [ { data: 'Value1', render: function (data, type, row) { return data + '$' } } ]
and this
columns: [ { name: 'Value1', render: function (data, type, row) { return data + '$' } } ]
and this
columns: [ { data: 'Value1', name: 'Value1', render: function (data, type, row) { return data + '$' } } ]
but in all cases the entire script fails.
I also tried to assign names with columnDefs [...] but no luck.
Would someone be so kind to tell me what I'm doing wrong, or what I should do to make this work?
Thank you!

jsPDF Table Width & Font Size

I thought this would be relatively simple but I cannot find an answer anywhere, I have had a good hunt in Stack Overflow. Apologies if I have missed something obvious!
How on earth do you set the table width in jsPDF? I simply want my table to stretch to 100% of the page width. Here is the code I am using:
<script>
function demoFromHTML() {
var pdf = new jsPDF('p', 'pt', 'a4');
source = $('#pdf')[0];
specialElementHandlers = {
'#bypassme': function (element, renderer) {
return true
}
};
margins = {
top: 80,
bottom: 40,
left: 40,
width: 600
};
pdf.fromHTML(
source,
margins.left,
margins.top, {
'width': margins.width,
'elementHandlers': specialElementHandlers
},
function (dispose) {
pdf.output('datauri');
}, margins);
}
</script>
I am using standard, unformatted HTML table.
<table class="reference">
<tbody><tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Points</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
<tr>
<td>Adam</td>
<td>Johnson</td>
<td>67</td>
</tr>
</tbody></table>
The table only stretches about 60% across the PDF, which just seems to be a random amount. In addition the text inside the table is a different font and size to the text outside the table.
Any help would be greatly appreciated.

one idea for jqgrid print view

I would like to have two views in jqgrid:
1) the regular grid view with sortable columns, pagination, etc (It's great and works really well...love it!).
2) a "print view" which can easily be styled with css and customized for print. The class structure should not be too complicated because I want to easily make my own style sheet. One important thing is to be able to repeat the column headers on each printed page. (I do not like to print from a jqgrid. Even when I add the jqgrid stylesheet with "media=print", the printed results are very hard to control.)
So, what I did was to first create a jqGrid. Then, using it's data, create my own table and print from that. It's a bit of a hack. But it works.
1- Create the grid and insert it into a div. Note I called "build_print_view" in the "loadComplete" function, based on the presence of a variable. This allows me to control whether I want to show "print view" or a "grid view" first:
function classGrid(select_val, showgrid){
jQuery.get('/lookupgrid/lookupgrid/get_grid', function(data) {
var _html= jQuery(data);
jQuery('#resultdiv').html(_html);
var gridtable = jQuery("#list");
var formdata = new Array();
formdata.push({
name: "var1",
value: "whatever"
});
formdata.push({
name: "var2",
value: "whateverelse"
});
var lastsel;
console_log("in classGrid");
gridtable.jqGrid({
url:'/lookupgrid/lookupgrid/class_grid',
colNames:['var1','var2'],
colModel :[
{
name:'var1',
index:'var1',
width:95
},
{
name:'var2',
index:'var2',
width:95
}],
datatype: 'json',
mtype: 'POST',
pager: '#pager',
rowList:[10,20,30],
loadComplete: function() {
if(!showgrid){
build_print_view();
}
},
onSelectRow: function(id){
var rowdata = gridtable.jqGrid('getRowData',id);
alert('Selected row ID ' + id + " var1 is " + rowdata.var1);
},
loadonce: true,
postData:formdata,
width: 800,
height: 300,
pgtext:"Page {0}",
viewrecords: true,
gridview: true,
caption: 'Class Results'
});
gridtable.jqGrid('navGrid','#pager',{
edit:false,
add:false,
del:false
});
});
}
2 - In build_print_view() you can extract the data from the jqgrid and put it into a table, which can be styled however you like with your own stylesheets.
function build_print_view(){
var gridtable = jQuery("#list");
var lista = gridtable.jqGrid('getGridParam','data');
var tablestr = "";
for(var i=0;i<lista.length;i++){
var rowData = lista[i];
tablestr += "<tr>"
tablestr += "<td class=\"wide cycle\" style=\"width:50px;\" id=\"sku\">"+rowData.var1+"</td>";
tablestr += "<td class=\"wide cycle\" style=\"width:300px;\" id=\"skudesc\">"+rowData.var2+"</td>";
tablestr += "</tr>";
}
jQuery.get('/lookupgrid/lookupgrid/get_print_view', function(data) {
var _html= jQuery(data);
_html.find('#printresults').append(tablestr);
jQuery('#resultdiv').html(_html);
});
}
3 - The rest of the table, and etc tags are returned by the ajax "get" call to "/lookupgrid/lookupgrid/get_print_view" and I just plop tablestr into "#printresults" div, i.e.:
<div id="printview">
<table id="clsitems" class="wide">
<thead>
<tr>
<th colspan="10" class="wide" id="label">
</th>
</tr>
<tr>
<td class="wide label">
var1:
</td>
<td class="wide label">
var2:
</td>
</tr>
</thead>
<tbody id="printresults">
</tbody>
</table>
</div>
4 - The only weirdness is that if "print view" is requested, the jqGrid gets created and flashes on the screen for a second, and then the print view table replaces it in its div.
Actually, if there were a good way to just construct the jqGrid without displaying it, I would prefer that. I could then display the jqGrid later if "screen view" were requested.

jquery - tablesort only works in one direction

This sorts in one direction, but not the other. Is there something wrong with the table specifications. It wold be great if someone could post an HTML sample that has sorting working in both directions on a column with dollar values that include commas in them.
// create sorter
<script type="text/javascript" id="js">
$(document).ready(function() {
// call the tablesorter plugin
$("table.tablesorter").tablesorter({
// enable debug mode
debug: false
});
});
</script>
Not sure if a prefix is needed here (table.tablesorter):
// add parser through the tablesorter addParser method
<script type="text/javascript" id="js">
$.tablesorter.addParser({
// set a unique id
id: 'money',
is: function(s) {
// return false so this parser is not auto detected
return false;
},
format: function(s) {
return s.toLowerCase().replace("\$","").replace(",","");
},
// set type, either numeric or text
type: 'numeric'
});
Not sure if table.tablesorter is needed here:
// specify column
$(function() {
$("table.tablesorter").tablesorter({
headers: {
// column to be handled specially
7: {
sorter:'money'
}
}
});
});
</script>
The following is the top of the table:
<table cellspacing="1" class="tablesorter">
<thead>
<tr>
<th>Name</th>
<th>Major</th>
<th>Gender</th>
<th>English</th>
<th>Japanese</th>
<th>Calculus</th>
<th>Overall grades</th>
<th>Money</th>
</tr>
</thead>
<tbody>
<tr>
<td>Student01</td>
<td>Languages</td>
<td>male</td>
<td>80</td>
<td>70</td>
<td>75</td>
<td>bad</td>
<td>$1.00</td>
</tr>
Since you are working with numbers, you'll need to parse the string into a real number. Change this line in your parser:
format: function(s) {
return parseFloat( s.toLowerCase().replace("\$","").replace(",","") );
}

Resources