You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
data-math="ignore" is not ignored (Math Widget) #1526
I'm generating a table with numeric values, but some records don't have any data. In this case, I'm not outputting any value and the TD element is empty. I noticed that the math widget was converting these empty values to "0" when averaging, so I added data-math="ignore" to these empty TD elements. The cells are still being converted to "0" and included in the average.
For example, the mean of non-ignored fields should be "100". The value "60" is returned, so this must mean that it's evaluating ignored cells as "0" instead of ignoring them. (By comparison, if I create 5 cells in Excel and only 3 are populated w/100, the average is "100".)
Yes... ignore a table "TD" cell . Please, please please.
That's what I initially thought it was doing. I didn't realize, even after reviewing the documentation/sample, that it was a row-only attribute.
The reason for it is because I'm averaging some data for a client, but some records don't have any response data. In those cases, I leave the table cell is empty (ie, null) but tablesorter auto-translates the missing value to "0" and then the averages are incorrect & unusable. (By contrast, MS Excel automatically ignores empty cells when performing math functions.)
I just noticed that a new release became available 2 hours ago. I didn't see any change in behavior. In my sample (above), I'm expecting that the result of 3 populated cells w/100 be displayed as "100" instead of "60" as the two empty (non-zero) cells are ignored, . The v2.30.7 release is still including the ignored cells. (I tested count, mean or sum functions.)
Was the enhancement included in the v2.30.7 release? If not, do you have a separate script I could try? Thanks.
I checked v2.31.0 (8/27/2018) and data-math="ignore" is still including the non-existent values in the calculations. Was the enhancement added to v2.31?
A project that I used this widget on just reported calculation errors due to empty non-numeric null-ish values being averaged as "0" and throwing off the final values.
Sorry for the long long delay on this... I modified your changes a bit. It appears to work, please test it out more thoroughly for me. I'll update the repo if it works well.
widget-math.js
/*! Widget: math - updated 11/18/2019 (v2.31.2) *//** Requires tablesorter v2.16+ and jQuery 1.7+* by Rob Garrison*//*jshint browser:true, jquery:true, unused:false *//*global jQuery: false */(function($){"use strict";varts=$.tablesorter,math={error: {0: "Infinity result: Divide by zero",1: "Need more than one element to make this calculation",undef: "No elements found"},// value returned when calculation is not possible, e.g. no values, dividing by zero, etc.invalid: function(c,name,errorIndex){// name = function returning invalid results// errorIndex = math.error index with an explanation of the errorconsole.warn(name,math.error[errorIndex]);return(c&&c.widgetOptions.math_none)||"";// text for cell},events: "tablesorter-initialized update updateAll updateRows addRows updateCell filterReset ".split(" ").join(".tsmath "),processText: function(c,$cell){vartmp,wo=c.widgetOptions,txt=ts.getElementText(c,$cell,math.getCellIndex($cell)),prefix=c.widgetOptions.math_prefix;if(wo.math_textAttr){txt=$cell.attr(wo.math_textAttr)||txt;}if(/</.test(prefix)){// prefix contains HTML; remove it & any text before using formatFloattmp=$("<div>"+prefix+"</div>").text().replace(/\{content\}/g,"").trim();txt=txt.replace(tmp,"");}txt=ts.formatFloat(txt.replace(/[^\w,.\-()]/g,""),c.table)||0;// isNaN('') => falsereturnisNaN(txt) ? 0 : txt;},// get all of the row numerical values in an arrygetRow: function(c,$el,hasFilter){var$cells,wo=c.widgetOptions,arry=[],$row=$el.closest("tr"),isFiltered=$row.hasClass(wo.filter_filteredRow||"filtered");if(hasFilter){$row=$row.filter(hasFilter);}if(hasFilter||!isFiltered){$cells=$row.children().not("["+wo.math_dataAttrib+"=ignore]");if(wo.math_ignore.length){$cells=$cells.filter(function(){// using $.inArray is not optimal (needed for IE8)return($.inArray(math.getCellIndex($(this)),wo.math_ignore)===-1);});}arry=$cells.not($el).map(function(){returnmath.processText(c,$(this));}).get();}returnarry;},// get all of the column numerical values in an arrygetColumn: function(c,$el,type,hasFilter){varindex,$t,$tr,len,$mathRows,mathAbove,wo=c.widgetOptions,arry=[],$row=$el.closest("tr"),mathAttr=wo.math_dataAttrib,mathIgnore="["+mathAttr+"=ignore]",filtered=wo.filter_filteredRow||"filtered",cIndex=math.getCellIndex($el),// get all rows to keep row indexing$rows=c.$table.children("tbody").children(),mathAttrs=["["+mathAttr+"^=above]","["+mathAttr+"^=below]","["+mathAttr+"^=col]","["+mathAttr+"^=all]"];if(type==="above"){len=$rows.index($row);index=len;while(index>=0){$tr=$rows.eq(index);mathAbove=$tr.children().filter(mathAttrs[0]).length;if(hasFilter){$tr=$tr.filter(hasFilter);}$t=$tr.children().filter(function(){returnmath.getCellIndex($(this))===cIndex;});// ignore filtered rows & rows with data-math="ignore" (and starting row)if(((hasFilter||!$tr.hasClass(filtered))&&$tr.not(mathIgnore).length&&index!==len)||(mathAbove&&index!==len)){// stop calculating 'above', when encountering another 'above'if(mathAbove){index=0;}elseif($t.length&&$t.not(mathIgnore).length){arry[arry.length]=math.processText(c,$t);}}index--;}}elseif(type==="below"){len=$rows.length;// index + 1 to ignore starting nodefor(index=$rows.index($row)+1;index<len;index++){$tr=$rows.eq(index);if($tr.children().filter(mathAttrs[1]).length){break;}if(hasFilter){$tr=$tr.filter(hasFilter);}$t=$tr.children().filter(function(){returnmath.getCellIndex($(this))===cIndex;});if((hasFilter||!$tr.hasClass(filtered))&&$tr.not(mathIgnore).length&&$t.length&&$t.not(mathIgnore)){arry[arry.length]=math.processText(c,$t);}}}else{$mathRows=$rows.not(mathIgnore);len=$mathRows.length;for(index=0;index<len;index++){$tr=$mathRows.eq(index);if(hasFilter){$tr=$tr.filter(hasFilter);}$t=$tr.children().filter(function(){returnmath.getCellIndex($(this))===cIndex;});if((hasFilter||!$tr.hasClass(filtered))&&$t.not(mathAttrs.join(",")).length&&!$t.is($el)&&$t.not(mathIgnore).length){arry[arry.length]=math.processText(c,$t);}}}returnarry;},// get all of the column numerical values in an arrygetAll: function(c,hasFilter){var$t,col,$row,rowIndex,rowLen,$cells,cellIndex,cellLen,arry=[],wo=c.widgetOptions,mathAttr=wo.math_dataAttrib,mathIgnore="["+mathAttr+"=ignore]",filtered=wo.filter_filteredRow||"filtered",$rows=c.$table.children("tbody").children().not(mathIgnore);rowLen=$rows.length;for(rowIndex=0;rowIndex<rowLen;rowIndex++){$row=$rows.eq(rowIndex);if(hasFilter){$row=$row.filter(hasFilter);}if(hasFilter||!$row.hasClass(filtered)){$cells=$row.children().not(mathIgnore);cellLen=$cells.length;for(cellIndex=0;cellIndex<cellLen;cellIndex++){$t=$cells.eq(cellIndex);col=math.getCellIndex($t);if(!$t.filter("["+mathAttr+"]").length&&$.inArray(col,wo.math_ignore)<0){arry[arry.length]=math.processText(c,$t);}}}}returnarry;},setColumnIndexes: function(c){var$table=c.$table,last=1,// only target rows with a colspan or rows included in a rowspan$rows=$table.children("tbody").children().filter(function(){varcells,indx,$this=$(this),include=$this.children("[colspan]").length>0;if(last>1){last--;include=true;}elseif(last<1){last=1;}if($this.children("[rowspan]").length>0){cells=this.cells;// find max rowspan (in case more than one cell has a rowspan)for(indx=0;indx<cells.length;indx++){last=Math.max(cells[indx].rowSpan,last);}}returninclude;});// pass `c` (table.config) to computeColumnIndex so it won't add a data-column// to every tbody cell, just the ones where the .cellIndex property doesn't match// the calculated cell index - hopefully fixes the lag issue in #1048ts.computeColumnIndex($rows,c);},getCellIndex: function($cell){varindx=$cell.attr("data-column");returntypeofindx==="undefined"
? $cell[0].cellIndex
: parseInt(indx,10);},recalculate: function(c,wo,init){if(c&&(!wo.math_isUpdating||init)){vartime,mathAttr,$mathCells,indx,len,changed=false,filters={};if(c.debug||wo.math_debug){time=newDate();}// add data-column attributes to all table cellsif(init){math.setColumnIndexes(c);}// data-attribute name (defaults to data-math)wo.math_dataAttrib="data-"+(wo.math_data||"math");// all non-info tbody cellsmathAttr=wo.math_dataAttrib;$mathCells=c.$tbodies.children("tr").children("["+mathAttr+"]");changed=math.mathType(c,$mathCells,wo.math_priority)||changed;// only info tbody cells$mathCells=c.$table.children("."+c.cssInfoBlock+", tfoot").children("tr").children("["+mathAttr+"]");math.mathType(c,$mathCells,wo.math_priority);// find the 'all' total$mathCells=c.$table.children().children("tr").children("["+mathAttr+"^=all]");len=$mathCells.length;// get math filter, if any// hasFilter = $row.attr( mathAttr + '-filter' ) || wo.math_rowFilter;for(indx=0;indx<len;indx++){var$cell=$mathCells.eq(indx),filter=$cell.attr(mathAttr+"-filter")||wo.math_rowFilter;filters[filter]=filters[filter]
? filters[filter].add($cell)
: $cell;}$.each(filters,function(hasFilter,$cells){changed=math.mathType(c,$cells,["all"],hasFilter)||changed;});// trigger an update only if cells inside the tbody changedif(changed){wo.math_isUpdating=true;if(c.debug||wo.math_debug){console[console.group ? "group" : "log"]("Math widget updating the cache after recalculation");}// update internal cache, but ignore "remove-me" rows and do not resortts.updateCache(c,function(){math.updateComplete(c);if(!init&&typeofwo.math_completed==="function"){wo.math_completed(c);}if(c.debug||wo.math_debug){console.log("Math widget update completed"+ts.benchmark(time));}});}else{if(!init&&typeofwo.math_completed==="function"){wo.math_completed(c);}if(c.debug||wo.math_debug){console.log("Math widget found no changes in data"+ts.benchmark(time));}}}},updateComplete: function(c){varwo=c.widgetOptions;if(wo.math_isUpdating&&(c.debug||wo.math_debug)&&console.groupEnd){console.groupEnd();}wo.math_isUpdating=false;},mathType: function(c,$cells,priority,hasFilter){if($cells.length){vargetAll,changed=false,wo=c.widgetOptions,mathAttr=wo.math_dataAttrib,equations=ts.equations;if(priority[0]==="all"){// mathType is called multiple times if more than one "hasFilter" is usedgetAll=math.getAll(c,hasFilter);}if(c.debug||wo.math_debug){console[console.group ? "group" : "log"]("Tablesorter Math widget recalculation");}// $.each is okay here... only 4 priorities$.each(priority,function(i,type){varindex,arry,formula,result,$el,$targetCells=$cells.filter("["+mathAttr+"^="+type+"]"),len=$targetCells.length;if(len){if(c.debug||wo.math_debug){console[console.group ? "group" : "log"](type);}for(index=0;index<len;index++){$el=$targetCells.eq(index);// Row is filtered, no need to do further checkingif($el.parent().hasClass(wo.filter_filteredRow||"filtered")){continue;}hasFilter=$el.attr(mathAttr+"-filter")||wo.math_rowFilter;formula=($el.attr(mathAttr)||"").replace(type+"-","");arry=type==="row"
? math.getRow(c,$el,hasFilter)
: type==="all"
? getAll
: math.getColumn(c,$el,type,hasFilter);if(equations[formula]){if(arry.length){result=equations[formula](arry,c);if(c.debug||wo.math_debug){console.log($el.attr(mathAttr),hasFilter ? '("'+hasFilter+'")' : "",arry,"=",result);}}else{// mean will return a divide by zero error, everything else shows an undefined errorresult=math.invalid(c,formula,formula==="mean" ? 0 : "undef");}changed=math.output($el,c,result,arry)||changed;}}if((c.debug||wo.math_debug)&&console.groupEnd){console.groupEnd();}}});if((c.debug||wo.math_debug)&&console.groupEnd){console.groupEnd();}returnchanged;}returnfalse;},output: function($cell,c,value,arry){// get mask from cell data-attribute: data-math-mask="#,##0.00"var$el,wo=c.widgetOptions,changed=false,prev=$cell.html(),mask=$cell.attr("data-"+wo.math_data+"-mask")||wo.math_mask,target=$cell.attr("data-"+wo.math_data+"-target")||"",result=ts.formatMask(mask,value,wo.math_prefix,wo.math_suffix);if(target){$el=$cell.find(target);if($el.length){$cell=$el;}}if(typeofwo.math_complete==="function"){result=wo.math_complete($cell,wo,result,value,arry);}if(result!==false){changed=prev!==result;$cell.html(result);}// check if in a regular tbody, otherwise don't pass a changed flag// to prevent unnecessary updating of the table cacheif(changed){$el=$cell.closest("tbody");// content was changed in a tfoot, info-only tbody or the resulting tbody is in a nested table// then don't signal a changeif(!$el.length||$el.hasClass(c.cssInfoBlock)||$el.parent()[0]!==c.table){returnfalse;}}returnchanged;}};// Modified from https://code.google.com/p/javascript-number-formatter//** * @preserve IntegraXor Web SCADA - JavaScript Number Formatter * http:// www.integraxor.com/ * author: KPL, KHL * (c)2011 ecava * Dual licensed under the MIT or GPL Version 2 licenses. */ts.formatMask=function(mask,val,tmpPrefix,tmpSuffix){if(!mask||isNaN(+val)){returnval;// return as it is.}varisNegative,result,decimal,group,posLeadZero,posTrailZero,posSeparator,part,szSep,integer,str,offset,index,end,inv,suffix="",// find prefix/suffixlen=mask.length,start=mask.search(/[0-9\-\+#]/),tmp=start>0 ? mask.substring(0,start) : "",prefix=tmp;if(tmpPrefix){if(/\{content\}/.test(tmpPrefix||"")){prefix=(tmpPrefix||"").replace(/\{content\}/g,tmp||"");}else{prefix=(tmpPrefix||"")+tmp;}}// reverse string: not an ideal method if there are surrogate pairsinv=mask.split("").reverse().join("");end=inv.search(/[0-9\-\+#]/);index=len-end;index+=mask.substring(index,index+1)==="." ? 1 : 0;tmp=end>0 ? mask.substring(index,len) : "";suffix=tmp;if(tmpSuffix){if(/\{content\}/.test(tmpSuffix||"")){suffix=(tmpSuffix||"").replace(/\{content\}/g,tmp||"");}else{suffix=tmp+(tmpSuffix||"");}}mask=mask.substring(start,index);// convert any string to number according to formation sign.val=mask.charAt(0)==="-" ? -val : +val;isNegative=val<0 ? (val=-val) : 0;// process only abs(), and turn on flag.// search for separator for grp & decimal, anything not digit, not +/- sign, not #.result=mask.match(/[^\d\-\+#]/g);decimal=(result&&result[result.length-1])||".";// treat the right most symbol as decimalgroup=(result&&result[1]&&result[0])||",";// treat the left most symbol as group separator// split the decimal for the format string if any.mask=mask.split(decimal);// Fix the decimal first, toFixed will auto fill trailing zero.val=val.toFixed(mask[1]&&mask[1].length);val=+val+"";// convert number to string to trim off *all* trailing decimal zero(es)// fill back any trailing zero according to formatposTrailZero=mask[1]&&mask[1].lastIndexOf("0");// look for last zero in formatpart=val.split(".");// integer will get !part[1]if(!part[1]||(part[1]&&part[1].length<=posTrailZero)){val=(+val).toFixed(posTrailZero+1);}szSep=mask[0].split(group);// look for separatormask[0]=szSep.join("");// join back without separator for counting the pos of any leading 0.posLeadZero=mask[0]&&mask[0].indexOf("0");if(posLeadZero>-1){while(part[0].length<mask[0].length-posLeadZero){part[0]="0"+part[0];}}elseif(+part[0]===0){part[0]="";}val=val.split(".");val[0]=part[0];// process the first group separator from decimal (.) only, the rest ignore.// get the length of the last slice of split result.posSeparator=szSep[1]&&szSep[szSep.length-1].length;if(posSeparator){integer=val[0];str="";offset=integer.length%posSeparator;len=integer.length;for(index=0;index<len;index++){str+=integer.charAt(index);// ie6 only support charAt for sz.// -posSeparator so that won't trail separator on full length/*jshint -W018 */if(!((index-offset+1)%posSeparator)&&index<len-posSeparator){str+=group;}}val[0]=str;}val[1]=mask[1]&&val[1] ? decimal+val[1] : "";// put back any negation, combine integer and fraction, and add back prefix & suffixreturnprefix+((isNegative ? "-" : "")+val[0]+val[1])+suffix;};ts.equations={count: function(arry){returnarry.length;},sum: function(arry){varindex,len=arry.length,total=0;for(index=0;index<len;index++){total+=arry[index];}returntotal;},mean: function(arry){vartotal=ts.equations.sum(arry);returntotal/arry.length;},median: function(arry,c){varhalf,len=arry.length;if(len>1){// https://gist.github.com/caseyjustus/1166258arry.sort(function(a,b){returna-b;});half=Math.floor(len/2);returnlen%2 ? arry[half] : (arry[half-1]+arry[half])/2;}returnmath.invalid(c,"median",1);},mode: function(arry){// http://stackoverflow.com/a/3451640/145346varindex,el,m,modeMap={},maxCount=1,modes=[arry[0]];for(index=0;index<arry.length;index++){el=arry[index];modeMap[el]=modeMap[el] ? modeMap[el]+1 : 1;m=modeMap[el];if(m>maxCount){modes=[el];maxCount=m;}elseif(m===maxCount){modes[modes.length]=el;maxCount=m;}}// returns arry of modes if there is a tiereturnmodes.sort(function(a,b){returna-b;});},max: function(arry){returnMath.max.apply(Math,arry);},min: function(arry){returnMath.min.apply(Math,arry);},range: function(arry){varv=arry.sort(function(a,b){returna-b;});returnv[arry.length-1]-v[0];},// common variance equation// (not accessible via data-attribute setting)variance: function(arry,population,c){vardivisor,avg=ts.equations.mean(arry),v=0,i=arry.length;while(i--){v+=Math.pow(arry[i]-avg,2);}divisor=arry.length-(population ? 0 : 1);if(divisor===0){returnmath.invalid(c,"variance",0);}v/=divisor;returnv;},// variance (population)varp: function(arry,c){returnts.equations.variance(arry,true,c);},// variance (sample)vars: function(arry,c){returnts.equations.variance(arry,false,c);},// standard deviation (sample)stdevs: function(arry,c){varvars=ts.equations.variance(arry,false,c);returnMath.sqrt(vars);},// standard deviation (population)stdevp: function(arry,c){varvarp=ts.equations.variance(arry,true,c);returnMath.sqrt(varp);}};// add new widget called repeatHeaders// ************************************ts.addWidget({id: "math",priority: 100,options: {math_data: "math",math_debug: false,// column index to ignoremath_ignore: [],// mask info: https://code.google.com/p/javascript-number-formatter/math_mask: "#,##0.00",// complete executed after each fucntionmath_complete: null,// function($cell, wo, result, value, arry) { return result; },// math_completed called after all math calculations have completedmath_completed: function(/* config */){},// order of calculation; 'all' is lastmath_priority: ["row","above","below","col"],// template for or just prepend the mask prefix & suffix with this HTML// e.g. '<span class="red">{content}</span>'math_prefix: "",math_suffix: "",// cell attribute containing the math value to usemath_textAttr: "",// no matching math elements found (text added to cell)math_none: "N/A",math_event: "recalculate",// use this filter to target specific rows (e.g. ':visible', or ':not(.empty-row)')math_rowFilter: ""},init: function(table,thisWidget,c,wo){// filterEnd fires after updateCompletevarupdate=(ts.hasWidget(table,"filter") ? "filterEnd" : "updateComplete")+".tsmath";// filterEnd is when the pager hides rows... so bind to pagerCompletemath.events+=(ts.hasWidget(table,"pager") ? "pagerComplete" : "filterEnd")+".tsmath ";c.$table.off((math.events+"updateComplete.tsmath "+wo.math_event).replace(/\s+/g," ")).on(math.events+wo.math_event,function(e){if(!this.hasInitialized){return;}varinit=e.type==="tablesorter-initialized";if(!wo.math_isUpdating||init){// don't setColumnIndexes on init here, or it gets done twiceif(!/filter/.test(e.type)&&!init){// redo data-column indexes on updatemath.setColumnIndexes(c);}math.recalculate(c,wo,init);}}).on(update,function(){setTimeout(function(){math.updateComplete(c);},40);});wo.math_isUpdating=false;// math widget initialized after table - see #946if(table.hasInitialized){math.recalculate(c,wo,true);}},// this remove function is called when using the refreshWidgets method or when destroying the tablesorter plugin// this function only applies to tablesorter v2.4+remove: function(table,c,wo,refreshing){if(refreshing){return;}c.$table.off((math.events+" updateComplete.tsmath "+wo.math_event).replace(/\s+/g," ")).children().children("tr").children("[data-"+wo.math_data+"]").empty();}});})(jQuery);
Thanks! This "mathIgnore" update provides me with the correct column-based values when generically tested against count, mean & sum.
I noticed that quotes changed from 'single' to "double". I'm curious... is this a coding practice change or just the effect of using a different IDE/editor?
Hey Mottie, grats on the new baby and job. (though not so new anymore...)
We just ran into this bug, same as OP: some columns have no data, and median and average are affected by the null = 0 in this case. When do you think you'll ship this fix out? I tried to bring your commented file into our system but couldn't get it working. I'm sure it was just something in our system, though.
Activity
Mottie commentedon Mar 14, 2018
Hi @JamoCA!
The
data-math="ignore"is meant to be added to thetr(demo):Is there a case where we'd need data only from specific cells in a row? If so, I'll need to modify the widget.
Sneezeplease commentedon Mar 20, 2018
Hello,
I would very much like to see this added to the widget. I am running into a similar problem.
Mottie commentedon Mar 21, 2018
Hi @Sneezeplease!
Do you mean you want the ability to add
data-math="ignore"to a cell as well as a row? Or something else?JamoCA commentedon Mar 23, 2018
Yes... ignore a table "TD" cell . Please, please please.
That's what I initially thought it was doing. I didn't realize, even after reviewing the documentation/sample, that it was a row-only attribute.
The reason for it is because I'm averaging some data for a client, but some records don't have any response data. In those cases, I leave the table cell is empty (ie, null) but tablesorter auto-translates the missing value to "0" and then the averages are incorrect & unusable. (By contrast, MS Excel automatically ignores empty cells when performing math functions.)
Mottie commentedon Apr 26, 2018
Sorry, I missed adding this enhancement in today's release. I'll make sure to include it in the next one.
JamoCA commentedon Jul 10, 2018
I just noticed that a new release became available 2 hours ago. I didn't see any change in behavior. In my sample (above), I'm expecting that the result of 3 populated cells w/100 be displayed as "100" instead of "60" as the two empty (non-zero) cells are ignored, . The v2.30.7 release is still including the ignored cells. (I tested count, mean or sum functions.)
Was the enhancement included in the v2.30.7 release? If not, do you have a separate script I could try? Thanks.
Mottie commentedon Jul 10, 2018
Sorry, I keep neglecting old issues... I'll really try to include this in the next update.
JamoCA commentedon Oct 23, 2018
I checked v2.31.0 (8/27/2018) and
data-math="ignore"is still including the non-existent values in the calculations. Was the enhancement added to v2.31?Mottie commentedon Oct 23, 2018
Sorry, no this enhancement wasn't included. I've been busy and neglecting work on this repo 😿. It is on my to-do list for the next update though!
JamoCA commentedon Apr 2, 2019
I saw that there's been a 2.31.1 update to the math widget on 11/20/2018. It doesn't look like this enhancement has been added yet. :(
Mottie commentedon Apr 2, 2019
Sorry :(
New baby, new job... I'm a bit overwhelmed.
JamoCA commentedon Nov 18, 2019
A project that I used this widget on just reported calculation errors due to empty non-numeric null-ish values being averaged as "0" and throwing off the final values.
I've attempted to add support for cell-based "ignore", but not sure if it's correct or performant:
https://gist.github.com/JamoCA/72aa5d40af8fa756c55e408674b324c1
compare w/current math widget:
https://github.com/Mottie/tablesorter/blob/master/js/widgets/widget-math.js
Mottie commentedon Nov 19, 2019
Sorry for the long long delay on this... I modified your changes a bit. It appears to work, please test it out more thoroughly for me. I'll update the repo if it works well.
widget-math.js
JamoCA commentedon Nov 19, 2019
Thanks! This "mathIgnore" update provides me with the correct column-based values when generically tested against count, mean & sum.
I noticed that quotes changed from 'single' to "double". I'm curious... is this a coding practice change or just the effect of using a different IDE/editor?
Mottie commentedon Nov 20, 2019
When I post code here in a GitHub comment, prettier-github bot automatically reformats the code to use double quotes.
VaelVictus commentedon Nov 27, 2019
Hey Mottie, grats on the new baby and job. (though not so new anymore...)
We just ran into this bug, same as OP: some columns have no data, and median and average are affected by
the null = 0in this case. When do you think you'll ship this fix out? I tried to bring your commented file into our system but couldn't get it working. I'm sure it was just something in our system, though.Mottie commentedon Nov 27, 2019
Hi @VaelVictus!
Thanks!
I'll try to get a new release out this weekend some time. Happy Thanksgiving!
Mottie commentedon Dec 1, 2019
Sorry for the super-long delay! Version 2.31.2 is now available.
VaelVictus commentedon Dec 2, 2019
Just tested it; works perfectly, thank you very much!
szabizs commentedon Sep 11, 2020
This was what I've been looking for, didn't find it in the docs, only here.
Mottie commentedon Sep 11, 2020
Hi @szabizs!
It's in the docs here - https://mottie.github.io/tablesorter/docs/example-widget-math.html#attribute_settings - under "Ignoring cells". Please let me know if that is what you're referring to, or if there is something missing in that section so I can improve it. Thanks!
szabizs commentedon Sep 14, 2020
@Mottie sorry for the confusion, I've searched for the work skip rather than ignore, that's why I wasn't able to find it 👍