|
|
(2 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
− | /** <pre>
| |
− | * highlightTable.js
| |
− | *
| |
− | * Description:
| |
− | * Adds row highlighting to tables
| |
− | *
| |
− | * Version 1.0: Row highlighting - Quarenon
| |
− | * Version 1.1: Update from pengLocations.js v1.0 - Quarenon
| |
− | * Version 2.0: pengLocations v2.1, Granular cookie - Saftzie
| |
− | * Version 2.1: Made compatible with jquery.tablesorter - Cqm
| |
− | */
| |
| | | |
− | ;(function ($, mw) {
| |
− |
| |
− | 'use strict';
| |
− |
| |
− | function highlightTable() {
| |
− |
| |
− | // requires CSS classes named in lightOnClass and mouseOverClass
| |
− | var wgPageName = mw.config.get('wgPageName'),
| |
− | cookiePrefix = 'lightTable',
| |
− | tableClass = 'lighttable',
| |
− | lightOnClass = 'highlight-on',
| |
− | mouseOverClass = 'highlight-over',
| |
− | base64url = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
| |
− | pageSeparator = '!',
| |
− | tableSeparator = '.',
| |
− | hashPageName,
| |
− | rows = [],
| |
− | columns,
| |
− | tables,
| |
− | cookie;
| |
− |
| |
− | // hash a string into a 32-bit hex string, msb first
| |
− | function crc32c(s) {
| |
− | var polynomial = 0x04C11DB7, // Castagnoli polynomial
| |
− | retVal,
| |
− | table = [],
| |
− | i,
| |
− | j,
| |
− | k;
| |
− |
| |
− | // guarantee 8-bit chars
| |
− | s = window.unescape(window.encodeURI(s));
| |
− |
| |
− | // calculate the crc for all 8-bit data
| |
− | // bit-wise operations discard anything left of bit 31
| |
− | for (i = 0; i < 256; i += 1) {
| |
− | k = (i << 24);
| |
− | for (j = 0; j < 8; j += 1) {
| |
− | k = (k << 1) ^ ((k >>> 31) * polynomial);
| |
− | }
| |
− | table[i] = k;
| |
− | }
| |
− |
| |
− | // the actual calculation
| |
− | retVal = 0;
| |
− | for (i = 0; i < s.length; i += 1) {
| |
− | retVal = (retVal << 8) ^ table[(retVal >>> 24) ^ s.charCodeAt(i)];
| |
− | }
| |
− |
| |
− | // make negative numbers unsigned
| |
− | if (retVal < 0) {
| |
− | retVal += 4294967296;
| |
− | }
| |
− | // 32-bit hex string, padded on the left
| |
− | retVal = '0000000' + retVal.toString(16).toUpperCase();
| |
− | retVal = retVal.substr(retVal.length - 8);
| |
− |
| |
− | return retVal;
| |
− | }
| |
− |
| |
− | // change the row bg color based on mouse events
| |
− | function setHighlight(el, val) {
| |
− | $(el).removeClass(mouseOverClass).removeClass(lightOnClass);
| |
− | switch (val) {
| |
− | case 1: // light on
| |
− | $(el).addClass(lightOnClass);
| |
− | break;
| |
− | case 2: // mouse-over
| |
− | $(el).addClass(mouseOverClass);
| |
− | break;
| |
− | default: // same as case 0, light off
| |
− | }
| |
− | }
| |
− |
| |
− | // load the cookie and parse it for the page
| |
− | // cookie info is saved in 1 of 16 browser cookies, based on page name hash
| |
− | // global cookie[][] supports multiple tables and multiple pages
| |
− | // uses global hashPageName
| |
− | function loadCookie(numTables) {
| |
− | var cookieName = cookiePrefix + '-' + hashPageName.charAt(0),
| |
− | pageCookies,
| |
− | tableCookies,
| |
− | iPage,
| |
− | iTable,
| |
− | i,
| |
− | j,
| |
− | k;
| |
− |
| |
− | cookie = [];
| |
− | if ($.cookie(cookieName) !== null) {
| |
− | pageCookies = $.cookie(cookieName).split(pageSeparator);
| |
− | for (iPage = 0; iPage < pageCookies.length; iPage += 1) {
| |
− | if (hashPageName === pageCookies[iPage].substr(0, 8)) {
| |
− | tableCookies = pageCookies[iPage].substr(8).split(tableSeparator);
| |
− | // trim the cookie array of arrays, if needed
| |
− | while (tableCookies.length > numTables) {
| |
− | tableCookies.pop();
| |
− | }
| |
− | // extract the row info per table
| |
− | // use Base64url to compress 6 rows to 1 character
| |
− | for (iTable = 0; iTable < tableCookies.length; iTable += 1) {
| |
− | cookie[iTable] = [];
| |
− | for (i = 0; i < tableCookies[iTable].length; i += 1) {
| |
− | k = base64url.indexOf(tableCookies[iTable].charAt(i));
| |
− | if (k < 0) { // input validation
| |
− | k = 0;
| |
− | }
| |
− | for (j = 5; j >= 0; j -= 1) {
| |
− | cookie[iTable][6 * i + j] = (k & 0x1);
| |
− | k >>= 1;
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // initialize the cookie array of arrays, if needed
| |
− | while (cookie.length < numTables) {
| |
− | cookie.push([]);
| |
− | }
| |
− | }
| |
− |
| |
− | // save/update the cookie for page reloads
| |
− | // cookie info is saved in 1 of 16 browser cookies, based on page name hash
| |
− | // global cookie[][] supports multiple tables and multiple pages
| |
− | // uses global hashPageName
| |
− | function saveCookie() {
| |
− | var cookieName = cookiePrefix + '-' + hashPageName.charAt(0),
| |
− | pageCookies,
| |
− | tableCookies,
| |
− | iPage,
| |
− | iTable,
| |
− | i,
| |
− | j,
| |
− | k,
| |
− | updated;
| |
− |
| |
− | // create the cookie for the tables on the current page
| |
− | // use Base64url to compress 6 rows to 1 character
| |
− | tableCookies = hashPageName;
| |
− | for (iTable = 0; iTable < cookie.length; iTable += 1) {
| |
− | if (iTable > 0) {
| |
− | tableCookies += tableSeparator;
| |
− | }
| |
− | for (i = 0; i < Math.ceil(cookie[iTable].length / 6); i += 1) {
| |
− | k = cookie[iTable][6 * i];
| |
− | for (j = 1; j < 6; j += 1) {
| |
− | k = 2 * k + ((6 * i + j < cookie[iTable].length) ? cookie[iTable][6 * i + j] : 0);
| |
− | }
| |
− | tableCookies += base64url.charAt(k);
| |
− | }
| |
− | }
| |
− |
| |
− | updated = 0;
| |
− | pageCookies = [];
| |
− | if ($.cookie(cookieName) !== null) {
| |
− | // get all the page cookies
| |
− | // another page might have updated them since this page
| |
− | pageCookies = $.cookie(cookieName).split(pageSeparator);
| |
− | // update the page cookie if it already exists
| |
− | for (iPage = 0; iPage < pageCookies.length; iPage += 1) {
| |
− | if (hashPageName === pageCookies[iPage].substr(0, 8)) {
| |
− | updated = 1;
| |
− | pageCookies[iPage] = tableCookies;
| |
− | }
| |
− | }
| |
− | }
| |
− | // add the page cookie if it doesn't exist yet
| |
− | if (updated === 0) {
| |
− | pageCookies.push(tableCookies);
| |
− | }
| |
− |
| |
− | // set path to / so it works for /wiki/, /index.php, etc
| |
− | $.cookie(cookieName, pageCookies.join(pageSeparator), {
| |
− | expires: 7,
| |
− | path: '/'
| |
− | });
| |
− | }
| |
− |
| |
− | tables = $('table.' + tableClass);
| |
− | // don't bother doing anything unless there's really something to do
| |
− | if (tables.length > 0) {
| |
− | // hash the page name to an 8-char hex string
| |
− | hashPageName = crc32c(wgPageName);
| |
− | loadCookie(tables.length);
| |
− |
| |
− | tables.each(function (iTable) {
| |
− | rows[iTable] = $(this).find('tr:has(td)'); // data rows
| |
− |
| |
− | // init or trim the cookie array of rows, if needed
| |
− | while (cookie[iTable].length < rows[iTable].length) {
| |
− | cookie[iTable].push(0);
| |
− | }
| |
− | while (cookie[iTable].length > rows[iTable].length) {
| |
− | cookie[iTable].pop();
| |
− | }
| |
− |
| |
− | // don't rely on headers to find # of columns
| |
− | // count them dynamically
| |
− | columns = 1;
| |
− |
| |
− | rows[iTable].each(function (iRow) {
| |
− | // update column count as we go
| |
− | // a smarter approach would count colspans, but this is good for now
| |
− | columns = Math.max(columns, $(this).children('th,td').length);
| |
− |
| |
− | // initialize highlighting based on the cookie
| |
− | setHighlight(this, cookie[iTable][iRow]);
| |
− |
| |
− | // set mouse events
| |
− | $(this).mouseover(function () {
| |
− | setHighlight(this, 2);
| |
− | }).mouseout(function () {
| |
− | setHighlight(this, cookie[iTable][iRow]);
| |
− | }).click(function (e) {
| |
− | // don't toggle highlight when clicking links
| |
− | if ((e.target.tagName !== 'A') && (e.target.tagName !== 'IMG')) {
| |
− | cookie[iTable][iRow] = 1 - cookie[iTable][iRow];
| |
− | setHighlight(this, cookie[iTable][iRow]);
| |
− | saveCookie();
| |
− | }
| |
− | });
| |
− | });
| |
− |
| |
− | // add a button for reset
| |
− | $(this).append(
| |
− | $('<tfoot/>')
| |
− | .append(
| |
− | $('<tr/>')
| |
− | .append(
| |
− | $('<th/>')
| |
− | .attr('colspan', columns)
| |
− | .append(
| |
− | $('<input>')
| |
− | .attr({
| |
− | 'type': 'button',
| |
− | 'value': 'Reset'
| |
− | })
| |
− | .click(function () {
| |
− | rows[iTable].each(function (iRow) {
| |
− | cookie[iTable][iRow] = 0;
| |
− | setHighlight(this, 0);
| |
− | });
| |
− | saveCookie();
| |
− | })
| |
− | )
| |
− | )
| |
− | )
| |
− | );
| |
− | });
| |
− | }
| |
− | }
| |
− |
| |
− | $(highlightTable);
| |
− |
| |
− | }(this.jQuery, this.mediaWiki));
| |
− |
| |
− | /* </pre> */
| |