Skip to content

Instantly share code, notes, and snippets.

@icodejs
Created August 8, 2012 18:59
Show Gist options
  • Save icodejs/3297586 to your computer and use it in GitHub Desktop.
Save icodejs/3297586 to your computer and use it in GitHub Desktop.
JS: MS global namespace file
var MS = MS || {};
MS.ajaxEventListener = ({
init: function(w, d) {
w.evt = d.createEvent("Event");
w.evt.initEvent("ajaxLoaded", true, true);
return this;
},
dispatchEvent: function(w, d) {
if (w.evt) {
d.dispatchEvent(w.evt);
}
return this;
}
}).init(window, document);
MS.utils = (function () {
return {
canApplySearchPagination: function($, $elem, max, callback) {
var
passCount = 0,
failCount = 0,
rgxIsHtml = /<(.|\n)*?>/g, // matches all HTML tags pairs including attributes in the tags
rgxIsHtmlStTag = /<\s*\w.*?>/g, // match all start tags including attributes in the tags
rgxIsAnchor = /<\s*a.*?>/g, // matches start tag of specific tag (a) including attibutes
$table = $elem.find('table:first');
if (typeof(callback) !== 'function')
throw new TypeError(callback + " is not a function!");
if ($elem.find('#searchPaginate').length || !$table.length)
return callback(false, null); // one searchPaginate control per page only and dont do anything if we dont find a table
if ($table.find('tr').length >= max) {
$table.find('tr td').each(function (i) {
var $this = $(this), tdText = $this.html();
if (passCount >= max && passCount > failCount) {
return callback(true, $table);
} else if (failCount >= max && failCount > passCount) {
return callback(false, $table);
}
if ((!rgxIsHtml.test(tdText) && !rgxIsHtmlStTag.test(tdText)) || rgxIsAnchor.test(tdText)) { //allow anchor tags
passCount += 1;
} else {
failCount += 1;
}
});
} else {
return callback(false, $table);
}
// callback function returns false so returning it will exit the jQuery.each early
}
};
}());
(function () {
/**
* Monkey patch Array object with a custom contains method
*/
if (typeof Array.prototype.contains !== 'function') {
Array.prototype.contains = function (needle, prop) {
var i = this.length;
while (i--) {
if (prop) {
if (this[i][prop] === needle) return true;
} else {
if (this[i] === needle) return true;
}
}
return false;
};
}
}());
;(function($) {
// Pagination and dynamic search
// by Russell Wark and Tahir Joseph
//
// USAGE:
//
// Results table must be in the following format:
// Table ID should be "itemtable" (note: not for the plugin)
// The table should have separate <THEAD> and <TBODY> sections, and <TH> tags should have the "col" scope
// The table <TBODY> should have a separate ID of "itemlist"
// Result TDs should have a class corresponding to the value of each searchable field in the <select> picklist
// An empty DIV with an ID of "holder" should be present to contain the pagination
// Record count is returned in a SPAN with an ID of "resultscount"
// new jQuery expression, "Contains" - works like "contains" but is case-insensitive
$.expr[':'].Contains = function(a, i, m) {
return $(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
$.expr[':'].contains = function(a, i, m) {
return $(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
/**
* Search and Paginate Plugin options
* ==================================
* minSearchTextLength : int,
* searchfilterId : 'string without #',
* searchTextboxId : 'string without #',
* searchpaginateHtml : 'url path to html file',
* excludeColumns : ['lowercase column name with no spaces'],
* jPagesOptions: {
* containerID : 'string without #',
* previous : 'string',
* next : 'string',
* perPage : int,
* delay : int
* }
*/
$.fn.searchPaginate = function(options) {
if (!this.length) return this;
var defaults = {
minSearchTextLength : 3,
searchfilterId : 'searchfilter',
searchTextboxId : 'thesearch',
searchpaginateHtml : '/static/MS/js/html-templates/searchpaginate.html',
excludeColumns : ['options'],
jPagesOptions: {
containerID : 'itemlist',
previous : 'Prev',
next : 'Next',
perPage : 20,
delay : 20
}
}, o = $.extend(defaults, options);
return this.each(function() {
var $table = $(this);
// add search page UI code to the page dynamically via ajax
insertSearchPaginateHTML($table , o.searchpaginateHtml);
var
$searchfilter = $('#' + o.searchfilterId),
$resultscount = $('<span id="resultscount" />').appendTo('#content h1'), // add results count container to h1
$divHolder = $('div.holder'),
$trElements = [],
filterClassNames = {};
if ($table) {
// dynamic page setup - make sure all the conditions set at the top of page are met
filterClassNames = getFilterClassNames($table.find('th')); // class name retrieved from th text
setupFilterOptions($searchfilter, filterClassNames);
//setupTable($table, filterClassNames, o.jPagesOptions.containerID);
$trElements = $table.find('#' + o.jPagesOptions.containerID + ' tr');
addSearchPaginationClasses($trElements, filterClassNames);
setResultsCount(false, $trElements, $resultscount); // update h1 with results count
$divHolder.jPages(o.jPagesOptions); // activate pagination
$('#' + o.searchTextboxId).keyup(function(e) {
var
$this = $(this),
keycode = e.keyCode || e.which,
searchfilter = $searchfilter.val(),
searchText = $this.val(),
showHighlighted = false,
$tdElements = [];
// reset
$table.find("td").removeClass("highlight");
$table.find("tr").show();
if (searchText.length > o.minSearchTextLength) {
$divHolder.jPages("destroy");
showHighlighted = (searchfilter.toLowerCase() === 'all');
if (showHighlighted) {
$trElements.hide();
$trElements.has('td:Contains("' + searchText + '")').show();
$trElements.find('td:Contains("' + searchText + '")').addClass('highlight');
$divHolder.jPages(o.jPagesOptions);
setResultsCount(showHighlighted, $trElements, $resultscount);
} else {
$trElements .hide();
$tdElements = $trElements.find('td:Contains("' + searchText + '")').filter('td.' + searchfilter);
$tdElements.parent('tr').show();
$tdElements.addClass('highlight');
$divHolder.jPages(o.jPagesOptions);
setResultsCount(showHighlighted, $trElements, $resultscount);
}
} else if (searchText.length === 0) { // for when search field is cleared
$divHolder.jPages('destroy');
$divHolder.jPages(o.jPagesOptions);
setResultsCount(showHighlighted, $trElements, $resultscount);
}
}); // end keyup
}
}); // end each
function insertSearchPaginateHTML($tbl, searchpaginateHtml) {
$.ajax({
url: searchpaginateHtml,
type: 'GET',
dataType: 'html',
async: false,
success: function(html, textStatus, xhr) {
$tbl.before(html);
}
});
}
function setupFilterOptions($searchfilter, options) {
var html = '<option value="all">-- all --</option>';
$.each(options, function (i, obj){
html += '<option value="' + obj.className + '">' + obj.heading + '</option>';
});
$searchfilter.html(html);
}
function addSearchPaginationClasses($rows, classes) {
$rows.each(function (i) { // add classes to each td in each row
$(this).find('td').each(function (j) {
if (classes[j])
$(this).addClass(classes[j].className);
});
});
}
function getFilterClassNames($headings) { // add option for excluding columns
var classNames = [];
$headings.each(function (i) {
var
heading = $(this).text(),
className = heading
.toLowerCase()
.replace(' ', '')
.replace(/[,.;:]/g,'') // delete unwanted characters
.replace(/[\n\t]/g,' '); // remove line breaks
if (!o.excludeColumns.contains(className)) {
classNames.push({
index : i,
heading : heading,
className : className
});
}
});
return classNames;
}
function setResultsCount(showHighlighted, $trElems, $targetElem) {
if (showHighlighted) {
count = $trElems.has("td.highlight").size();
} else {
count = $trElems.size();
}
$targetElem.html(' ' + count + ' result' + (count > 1 ? 's' : ''));
}
}; // end searchPaginate plugin
$.fn.setupSearchPaginateTable = function(options) {
if (!this.length) {return this;}
var defaults = {tbodyId: 'itemlist'}, o = $.extend(defaults, options);
return this.each(function() {
setupTable($(this), o.tbodyId);
});
function setupTable($tbl, tbodyId) {
var $html = $tbl
.find('tbody:first tr:first')
.wrapAll('<thead />') // wrap all header tbl rows in a thead
.end()
.find('th')
.attr('scope', 'col') // add option for excluding columns
.end();
$html
.find('tr')
.not('tr:first')
.wrapAll('<tbody id="' + tbodyId + '" />'); // wrap rest of table rows in a tbody with an id of itemlist
$tbl.html($html.find('tbody').html()); // cleanup and remove parent tbody tag and insert
}
}; // end setupSearchPaginateTable plugin
$(window).on('ajaxLoaded', function(e) {
MS.utils.canApplySearchPagination($, $('body'), 20, function (canApply, $tbl) {
if ($tbl) {
if (canApply) {
$tbl
.setupSearchPaginateTable()
.searchPaginate()
.tablesorter();
} else {
$tbl
.setupSearchPaginateTable()
.tablesorter();
}
}
return false;
});
});
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment