1/*! 2 * jQuery fancyTable plugin 3 * https://github.com/myspace-nu 4 * 5 * Copyright 2018 Johan Johansson 6 * Released under the MIT license 7 */ 8(function($) { 9 $.fn.fancyTable = function(options) { 10 var settings = $.extend({ 11 inputStyle: "", 12 inputPlaceholder: "Search...", 13 pagination: false, 14 paginationClass: "btn btn-light", 15 paginationClassActive: "active", 16 pagClosest: 3, 17 perPage: 10, 18 sortable: true, 19 searchable: true, 20 matchCase: false, 21 exactMatch: false, 22 onInit: function(){ }, 23 onUpdate: function(){ }, 24 sortFunction: function(a, b, fancyTableObject, rowA, rowB){ 25 if(a==b && rowA && rowB){ 26 // If sort values are of equal priority, sort by last order 27 return(fancyTableObject.rowSortOrder[$(rowA).data("rowid")] > fancyTableObject.rowSortOrder[$(rowB).data("rowid")]); 28 } 29 if(fancyTableObject.sortAs[fancyTableObject.sortColumn] == 'numeric'){ 30 return( 31 (fancyTableObject.sortOrder>0) ? parseFloat(a)-parseFloat(b) : parseFloat(b)-parseFloat(a) 32 ); 33 } else { 34 return((a<b)?-fancyTableObject.sortOrder:(a>b)?fancyTableObject.sortOrder:0); 35 } 36 }, 37 testing: false 38 }, options); 39 var instance = this; 40 this.settings = settings; 41 this.tableUpdate = function (elm) { 42 elm.fancyTable.matches = 0; 43 $(elm).find("tbody tr").each(function() { 44 var n=0; 45 var match = true; 46 var globalMatch = false; 47 $(this).find("td").each(function() { 48 if(!settings.globalSearch && elm.fancyTable.searchArr[n] && !(instance.isSearchMatch($(this).html(),elm.fancyTable.searchArr[n]) )){ 49 match = false; 50 } else if(settings.globalSearch && (!elm.fancyTable.search || (instance.isSearchMatch($(this).html(),elm.fancyTable.search) ))){ 51 if(!Array.isArray(settings.globalSearchExcludeColumns) || !settings.globalSearchExcludeColumns.includes(n+1)){ 52 globalMatch = true; 53 } 54 } 55 n++; 56 }); 57 if((settings.globalSearch && globalMatch) || (!settings.globalSearch && match)){ 58 elm.fancyTable.matches++ 59 if(!settings.pagination || (elm.fancyTable.matches>(elm.fancyTable.perPage*(elm.fancyTable.page-1)) && elm.fancyTable.matches<=(elm.fancyTable.perPage*elm.fancyTable.page))){ 60 $(this).show(); 61 } else { 62 $(this).hide(); 63 } 64 } else { 65 $(this).hide(); 66 } 67 }); 68 elm.fancyTable.pages = Math.ceil(elm.fancyTable.matches/elm.fancyTable.perPage); 69 if(settings.pagination){ 70 var paginationElement = (elm.fancyTable.paginationElement) ? $(elm.fancyTable.paginationElement) : $(elm).find(".pag"); 71 paginationElement.empty(); 72 for(var n=1; n<=elm.fancyTable.pages; n++){ 73 if(n==1 || (n>(elm.fancyTable.page-(settings.pagClosest+1)) && n<(elm.fancyTable.page+(settings.pagClosest+1))) || n==elm.fancyTable.pages){ 74 var a = $("<a>",{ 75 html:n, 76 "data-n": n, 77 style:"margin:0.2em", 78 class:settings.paginationClass+" "+((n==elm.fancyTable.page)?settings.paginationClassActive:"") 79 }).css("cursor","pointer").bind("click",function(){ 80 elm.fancyTable.page = $(this).data("n"); 81 instance.tableUpdate(elm); 82 }); 83 if(n==elm.fancyTable.pages && elm.fancyTable.page<(elm.fancyTable.pages-settings.pagClosest-1)){ 84 paginationElement.append($("<span>...</span>")); 85 } 86 paginationElement.append(a); 87 if(n==1 && elm.fancyTable.page>settings.pagClosest+2){ 88 paginationElement.append($("<span>...</span>")); 89 } 90 } 91 } 92 } 93 settings.onUpdate.call(this,elm); 94 }; 95 this.isSearchMatch = function(data, search){ 96 if(!settings.matchCase){ data=data.toUpperCase(); search = search.toUpperCase(); } 97 if(settings.exactMatch == "auto" && search.match(/^".*?"$/)){ 98 // Exact match due to "quoted" value 99 search = search.substring(1,search.length-1); 100 return (data==search); 101 } else if(settings.exactMatch == "auto" && search.replace(/\s+/g,"").match(/^[<>]=?/)){ 102 // Less < or greater > than 103 var comp = search.replace(/\s+/g,"").match(/^[<>]=?/)[0]; 104 var val = search.replace(/\s+/g,"").substring(comp.length); 105 return ((comp == '>' && data*1 > val*1) || (comp == '<' && data*1 < val*1) || (comp == '>=' && data*1 >= val*1) || (comp == '<=' && data*1 <= val*1)) 106 } else if(settings.exactMatch == "auto" && search.replace(/\s+/g,"").match(/^.+(\.\.|-).+$/)){ 107 // Intervall 10..20 or 10-20 108 var arr = search.replace(/\s+/g,"").split(/\.\.|-/); 109 return (data*1 >= arr[0]*1 && data*1 <= arr[1]*1); 110 } 111 try { 112 return (settings.exactMatch === true) ? (data==search) : (ne
112w RegExp(search).test(data)); 113 } 114 catch { 115 return false; 116 } 117 }; 118 this.reinit = function(){ 119 $(this).each(function(){ 120 $(this).find("th a").contents().unwrap(); 121 $(this).find("tr.fancySearchRow").remove(); 122 }); 123 $(this).fancyTable(this.settings); 124 }; 125 this.tableSort = function (elm) { 126 if(typeof elm.fancyTable.sortColumn !== "undefined" && elm.fancyTable.sortColumn < elm.fancyTable.nColumns){ 127 var iElm = 0; 128 $(elm).find("thead th").each(function(){ 129 $(this).attr("aria-sort", 130 (iElm == elm.fancyTable.sortColumn) ? 131 ( (elm.fancyTable.sortOrder == 1) ? "ascending" : (elm.fancyTable.sortOrder == -1) ? "descending" : "other" ) 132 : null // "none" // Remove the attribute instead of setting to "none" to avoid spamming screen readers. 133 ); 134 iElm++; 135 }); 136 $(elm).find("thead th div.sortArrow").each(function(){ 137 $(this).remove(); 138 }); 139 var sortArrow = $("<div>",{"class":"sortArrow"}).css({"margin":"0.1em","display":"inline-block","width":0,"height":0,"border-left":"0.4em solid transparent","border-right":"0.4em solid transparent"}); 140 sortArrow.css( 141 (elm.fancyTable.sortOrder>0) ? 142 {"border-top":"0.4em solid #000"} : 143 {"border-bottom":"0.4em solid #000"} 144 ); 145 $(elm).find("thead th a").eq(elm.fancyTable.sortColumn).append(sortArrow); 146 var rows = $(elm).find("tbody tr").toArray().sort( 147 function(a, b) { 148 var elma = $(a).find("td").eq(elm.fancyTable.sortColumn); 149 var elmb = $(b).find("td").eq(elm.fancyTable.sortColumn); 150 var cmpa = $(elma).attr("data-sortvalue") ? $(elma).data("sortvalue") : elma.html(); 151 var cmpb = $(elmb).attr("data-sortvalue") ? $(elmb).data("sortvalue") : elmb.html(); 152 if(elm.fancyTable.sortAs[elm.fancyTable.sortColumn] == 'case-insensitive') { 153 cmpa = cmpa.toLowerCase(); 154 cmpb = cmpb.toLowerCase(); 155 } 156 return settings.sortFunction.call(this,cmpa,cmpb,elm.fancyTable,a,b); 157 } 158 ); 159 $(rows).each(function(index) { 160 elm.fancyTable.rowSortOrder[$(this).data("rowid")] = index; 161 }); 162 $(elm).find("tbody").empty().append(rows); 163 } 164 }; 165 this.each(function() { 166 if($(this).prop("tagName")!=="TABLE"){ 167 console.warn("fancyTable: Element is not a table."); 168 return true; 169 } 170 var elm = this; 171 elm.fancyTable = { 172 nColumns: $(elm).find("td").first().parent().find("td").length, 173 nRows : $(this).find("tbody tr").length, 174 perPage : settings.perPage, 175 page : 1, 176 pages : 0, 177 matches : 0, 178 searchArr : [], 179 search : "", 180 sortColumn : settings.sortColumn, 181 sortOrder : (typeof settings.sortOrder === "undefined") ? 1 : (new RegExp("desc","i").test(settings.sortOrder) || settings.sortOrder == -1) ? -1 : 1, 182 sortAs:[], // null, numeric or case-insensitive 183 paginationElement : settings.paginationElement 184 }; 185 elm.fancyTable.rowSortOrder = new Array(elm.fancyTable.nRows); 186 if($(elm).find("tbody").length==0){ 187 var content = $(elm).html(); 188 $(elm).empty(); 189 $(elm).append("<tbody>").append($(content)); 190 } 191 if($(elm).find("thead").length==0){ 192 $(elm).prepend($("<thead>")); 193 // Maybe add generated headers at some point 194 //var c=$(elm).find("tr").first().find("td").length; 195 //for(var n=0; n<c; n++){ 196 // $(elm).find("thead").append($("<th></th>")); 197 //} 198 } 199 $(elm).find("tbody tr").each(function(index) { 200 // $(this).attr("data-rowid", index); 201 $(this).data("rowid", index); 202 }); 203 if(settings.sortable){ 204 var nAElm=0; 205 $(elm).find("thead th").each(function() { 206 elm.fancyTable.sortAs.push( 207 ($(this).data('sortas')=='numeric') ? 'numeric' : 208 ($(this).data('sortas')=='case-insensitive') ? 'case-insensitive' : 209 null 210 ); 211 var content = $(this).html(); 212 var a = $("<a>",{ 213 href: "#", 214 "aria-label": "Sort by " + $(this).text(), 215 html:content, 216 "data-n": nAElm, 217 class:"" 218 }).css({"cursor":"pointer","color":"inherit","text-decoration":"none","white-space":"nowrap"}).bind("click",function(){ 219 if(elm.fancyTable.sortColumn == $(this).data("n")){ 220 elm.fancyTable.sortOrder=-elm.fancyTable.sortOrder; 221 } else { 222 elm.fancyTable.sortOrder=1; 223 } 224 elm.fancyTable.sortColumn = $(this).data("n"); 225 instance.tableSort(elm); 226 instance.tableUpdate(elm); 227 return false;
228 }); 229 $(this).empty(); 230 $(this).append(a); 231 nAElm++; 232 }); 233 } 234 if(settings.searchable){ 235 var searchHeader = $("<tr>").addClass("fancySearchRow"); 236 if(settings.globalSearch){ 237 var searchField = $("<input>",{ 238 "aria-label": "Search table", 239 "placeholder": settings.inputPlaceholder, 240 style:"width:100%;box-sizing:border-box;"+settings.inputStyle 241 }).bind("change paste keyup",function(){ 242 elm.fancyTable.search = $(this).val(); 243 elm.fancyTable.page = 1; 244 instance.tableUpdate(elm); 245 }); 246 var th = $("<th>",{ style:"padding:2px;" }).attr("colspan",elm.fancyTable.nColumns); 247 $(searchField).appendTo($(th)); 248 $(th).appendTo($(searchHeader)); 249 } else { 250 var nInputElm=0; 251 $(elm).find("td").first().parent().find("td").each(function() { 252 elm.fancyTable.searchArr.push(""); 253 var searchField = $("<input>",{ 254 "aria-label": "Search column", 255 "data-n": nInputElm, 256 "placeholder": settings.inputPlaceholder, 257 style:"width:100%;box-sizing:border-box;"+settings.inputStyle 258 }).bind("change paste keyup",function(){ 259 elm.fancyTable.searchArr[$(this).data("n")] = $(this).val(); 260 elm.fancyTable.page = 1; 261 instance.tableUpdate(elm); 262 }); 263 var th = $("<th>",{ style:"padding:2px;" }); 264 $(searchField).appendTo($(th)); 265 $(th).appendTo($(searchHeader)); 266 nInputElm++; 267 }); 268 } 269 searchHeader.appendTo($(elm).find("thead")); 270 } 271 // Sort 272 instance.tableSort(elm); 273 if(settings.pagination && !settings.paginationElement){ 274 $(elm).find("tfoot").remove(); 275 $(elm).append($("<tfoot><tr></tr></tfoot>")); 276 $(elm).find("tfoot tr").append($("<td class='pag'></td>",{ }).attr("colspan",elm.fancyTable.nColumns)); 277 } 278 instance.tableUpdate(elm); 279 settings.onInit.call(this,elm); 280 }); 281 return this; 282 }; 283}(jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.