User:Lrb/common.js

< User:Lrb
Revision as of 00:01, 8 January 2021 by Lrb (talk | contribs)

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/** <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> */