/* =============================== | TABLESORT.JS | Copyright, Andy Croxall (mitya@mitya.co.uk) | For documentation and demo see http://mitya.co.uk/scripts/Animated-table-sort-REGEXP-friendly-111 | | USAGE | This script may be used, distributed and modified freely but this header must remain in tact. | For usage info and demo, including info on args and params, see www.mitya.co.uk/scripts =============================== */ jQuery.fn.sortTable = function(params) { /*----------- | STOP right now if anim already in progress -----------*/ if ($(this).find(':animated').length > 0) return; /*----------- | VALIDATE TABLE & PARAMS | - if no col to sort on passed, complain and return | - if table doesn't contain requested col, complain and return | If !sortType or invalid sortType, assume ascii sort -----------*/ var error = null; var complain = null; if (!params.onCol) { error = "No column specified to search on"; complain = true; } else if ($(this).find('td:nth-child('+params.onCol+')').length == 0) { error = "The requested column wasn't found in the table"; complain = true; } if (error) { if (complain) alert(error); return; } if (!params.sortType || params.sortType != 'numeric') params.sortType = 'ascii'; /*----------- | PREP | - declare array to store the contents of each , or, if sorting on regexp, the pattern match of the regexp in each | - Give the position: relative to aid animation | - Mark the col we're sorting on with an identifier class -----------*/ var valuesToSort = []; $(this).css('position', 'relative'); var doneAnimating = 0; var tdSelectorText = 'td'+(!params.onCol ? '' : ':nth-child('+params.onCol+')'); $(this).find('td:nth-child('+params.onCol+')').addClass('sortOnThisCol'); var thiss = this; /*----------- | Iterate over table and. For each: | - append its content / regexp match (see above) to valuesToSort[] | - create a new
, give it position: absolute and copy over the
's content into it | - fix the 's width/height to its offset width/height so that, when we remove its html, it won't change shape | - clear the 's content | - clear the 's content | There is no visual effect in this. But it means each 's content is now 'animatable', since it's position: absolute. -----------*/ var counter = 0; $(this).find('td').each(function() { if ($(this).is('.sortOnThisCol') || (!params.onCol && !params.keepRelationships)) { var valForSort = !params.child ? $(this).text() : (params.child != 'input' ? $(this).find(params.child).text() : $(this).find(params.child).val()); if (params.regexp) { valForSort = valForSort.match(new RegExp(params.regexp))[!params.regexpIndex ? 0 : params.regexpIndex]; } valuesToSort.push(valForSort); } var thisTDHTMLHolder = document.createElement('div'); with($(thisTDHTMLHolder)) { html($(this).html()); if (params.child && params.child == 'input') html(html().replace(/=0) valuesToSort_tempCopy.push(valuesToSort[u]); valuesToSort = valuesToSort_tempCopy; delete(valuesToSort_tempCopy) } /*----------- | Now, for each: -----------*/ for(var k in valuesToSort) { //establish current relating to this value of the array var currTD = $($(this).find(tdSelectorText).filter(function() { return ( ( !params.regexp && ( ( params.child && ( ( params.child != 'input' && valuesToSort[k] == $(this).find(params.child).text() ) || params.child == 'input' && valuesToSort[k] == $(this).find(params.child).val() ) ) || ( !params.child && valuesToSort[k] == $(this).children('div').html() ) ) ) || ( params.regexp && $(this).children('div').html().match(new RegExp(params.regexp))[!params.regexpIndex ? 0 : params.regexpIndex] == valuesToSort[k] ) ) && !$(this).hasClass('tableSort_TDRepopulated'); }).get(0)); //give current a class to mark it as having been used, so we don't get confused with duplicate values currTD.addClass('tableSort_TDRepopulated'); //establish target for this value and store as a node reference on this var targetTD = $($(this).find(tdSelectorText).get(k)); currTD.get(0).toTD = targetTD; //if we're sorting on a particular column and maintaining relationships, also give the other s in rows a node reference //denoting ITS target, so they move with their lead siibling if (params.keepRelationships) { var counter = 0; $(currTD).parent().children('td').each(function() { $(this).get(0).toTD = $(targetTD.parent().children().get(counter)); counter++; }); } //establish current relative positions for the current and target s and use this to calculate how far each
needs to move var currPos = currTD.position(); var targetPos = targetTD.position(); var moveBy_top = targetPos.top - currPos.top; //invert values if going backwards/upwards if (targetPos.top > currPos.top) moveBy_top = Math.abs(moveBy_top); /*----------- | ANIMATE | - work out what to animate on. | - if !keepRelationships, animate only
s in the col we're sorting on (identified by .sortOnThisCol) | - if keepRelationships, animate all cols but s that aren't .sortOnThisCol follow lead sibiling with .sortOnThisCol | - run animation. On callback, update each with content of
that just moved into it and remove
s | - If noAnim, we'll still run aniamte() but give it a low duration so it appears instant -----------*/ var animateOn = params.keepRelationships ? currTD.add(currTD.siblings()) : currTD; var done = 0; animateOn.children('div').animate({top: moveBy_top}, !params.noAnim ? 500 : 0, null, function() { if ($(this).parent().is('.sortOnThisCol') || !params.keepRelationships) { done++; if (done == valuesToSort.length-1) thiss.tableSort_cleanUp(); } }); } }; jQuery.fn.tableSort_cleanUp = function() { /*----------- | AFTER ANIM | - assign each
its new content as property of it (DON'T populate it yet - this may still need to be read by | other s' toTD node references | - once new contents for each gathered, populate | - remove some identifier classes and properties -----------*/ $(this).find('td').each(function() { if($(this).get(0).toTD) $($(this).get(0).toTD).get(0).newHTML = $(this).children('div').html(); }); $(this).find('td').each(function() { $(this).html($(this).get(0).newHTML); }); $('td.tableSort_TDRepopulated').removeClass('tableSort_TDRepopulated'); $(this).find('.sortOnThisCol').removeClass('sortOnThisCol'); $(this).find('td[newHTML]').attr('newHTML', ''); $(this).find('td[toTD]').attr('toTD', ''); };