Changes

no edit summary
Line 1: Line 1: −
// <nowiki>
+
/** <pre>
if ($("table.lighttable").length) {
+
* highlightTable.js
mw.loader.load( 'ext.gadget.highlightTable-core' );
+
*
}
+
* Description:
// </nowiki>
+
* 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> */
52

edits