MediaWiki:Common.js/highlight.js

/** * Taken from: https://runescape.fandom.com/wiki/MediaWiki:Common.js/highlightTable.js * * 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: "/"            }); }

// This hook forces it to apply script even in TabViews mw.hook("wikipage.content").add(function (pSection) {           tables = $(pSection[0]).find("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(                       $(" ")                        .append( $(" ")                           .append(                                $(" ")                                .attr("colspan", columns)                                .append( $(" ")                                   .attr({                                        "class": "button"                                    }) .text("Reset") .click(function {                                        rows[iTable].each(function (iRow) { cookie[iTable][iRow] = 0; setHighlight(this, 0); });                                       saveCookie;                                    }) )                           )                        )                    );                });            }        });    }

$(highlightTable);

}(this.jQuery, this.mediaWiki));

/* */