Changes

no edit summary
Line 3: Line 3:  
  *
 
  *
 
  * Description:
 
  * Description:
  * Adds row highlighting to tables
+
  * Adds highlighting to tables
 
  *
 
  *
  * Version 1.0: Row highlighting                        - Quarenon
+
  * History:
  * Version 1.1: Update from pengLocations.js v1.0      - Quarenon
+
* - 1.0: Row highlighting                        - Quarenon
  * Version 2.0: pengLocations v2.1, Granular cookie    - Saftzie
+
  * - 1.1: Update from pengLocations.js v1.0      - Quarenon
  * Version 2.1: Made compatible with jquery.tablesorter - Cqm
+
  * - 2.0: pengLocations v2.1, Granular cookie    - Saftzie
 +
  * - 2.1: Made compatible with jquery.tablesorter - Cqm
 +
* - 2.2: Switch to localStorage                  - Cqm
 +
* - 3.0: Allow cell highlighting                - mejrs
 +
*
 +
* @todo Allow the stored data to be coupled to the table in question. Currently the data is stored
 +
*      on the page itself, so if any tables are shuffled, the highlighting doesn't follow. For
 +
*      the same reason tables hosted on other pages are not synchronized.
 +
*/
 +
 
 +
/**
 +
* DATA STORAGE STRUCTURE
 +
* ----------------------
 +
*
 +
* In its raw, uncompressed format, the stored data is as follows:
 +
* {
 +
*    hashedPageName1: [
 +
*        [0, 1, 0, 1, 0, 1],
 +
*        [1, 0, 1, 0, 1, 0],
 +
*        [0, 0, 0, 0, 0, 0]
 +
*    ],
 +
*    hashedPageName2: [
 +
*        [0, 1, 0, 1, 0, 1],
 +
*        [1, 0, 1, 0, 1, 0],
 +
*        [0, 0, 0, 0, 0, 0]
 +
*    ]
 +
* }
 +
*
 +
* Where `hashedPageNameX` is the value of wgPageName passed through our `hashString` function,
 +
* the arrays of numbers representing tables on a page (from top to bottom) and the numbers
 +
* representing whether a row is highlighted or not, depending on if it is 1 or 0 respectively.
 +
*
 +
* During compression, these numbers are collected into groups of 6 and converted to base64.
 +
* For example:
 +
*
 +
*  1. [0, 1, 0, 1, 0, 1]
 +
*  2. 0x010101            (1 + 4 + 16 = 21)
 +
*  3. BASE_64_URL[21]      (U)
 +
*
 +
* Once each table's rows have been compressed into strings, they are concatenated using `.` as a
 +
* delimiter. The hashed page name (which is guaranteed to be 8 characters long) is then prepended
 +
* to this string to look something like the following:
 +
*
 +
*  XXXXXXXXab.dc.ef
 +
*
 +
*
 +
* The first character of a hashed page name is then used to form the object that is actually
 +
* stored. As the hashing function uses hexadecimal, this gives us 16 possible characters (0-9A-Z).
 +
*
 +
* {
 +
*    A: ...
 +
*    B: ...
 +
*    C: ...
 +
*    // etc.
 +
* }
 +
*
 +
* The final step of compression is to merge each page's data together under it's respective top
 +
* level key. this is done by concatenation again, separated by a `!`.
 +
*
 +
* The resulting object is then converted to a string and persisted in local storage. When
 +
* uncompressing data, simply perform the following steps in reverse.
 +
*
 +
* For the implementation of this algorithm, see:
 +
* - `compress`
 +
* - `parse`
 +
* - `hashString`
 +
*
 +
* Note that while rows could theoretically be compressed further by using all ASCII characters,
 +
* eventually we'd start using characters outside printable ASCII which makes debugging painful.
 
  */
 
  */
   −
;(function ($, mw) {
+
/*jshint bitwise:false, camelcase:true, curly:true, eqeqeq:true, es3:false,
 +
    forin:true, immed:true, indent:4, latedef:true, newcap:true,
 +
    noarg:true, noempty:true, nonew:true, plusplus:true, quotmark:single,
 +
    undef:true, unused:true, strict:true, trailing:true,
 +
    browser:true, devel:false, jquery:true,
 +
    onevar:true
 +
*/
    +
(function($, mw, OO, rs) {
 
     'use strict';
 
     'use strict';
   −
     function highlightTable() {
+
     // constants
 +
    var STORAGE_KEY = 'rs:lightTable',
 +
        TABLE_CLASS = 'lighttable',
 +
        LIGHT_ON_CLASS = 'highlight-on',
 +
        MOUSE_OVER_CLASS = 'highlight-over',
 +
        BASE_64_URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
 +
        PAGE_SEPARATOR = '!',
 +
        TABLE_SEPARATOR = '.',
 +
        CASTAGNOLI_POLYNOMIAL = 0x04c11db7,
 +
        UINT32_MAX = 0xffffffff,
 +
 
 +
        self = {
 +
            /*
 +
            * Stores the current uncompressed data for the current page.
 +
            */
 +
            data: null,
 +
 
 +
            /*
 +
            * Perform initial checks on the page and browser.
 +
            */
 +
            init: function() {
 +
                var $tables = $('table.' + TABLE_CLASS),
 +
                    hashedPageName = self.hashString(mw.config.get('wgPageName'));
 +
 
 +
                // check we have some tables to interact with
 +
                if (!$tables.length) {
 +
                    return;
 +
                }
 +
                // check the browser supports local storage
 +
                if (!rs.hasLocalStorage()) {
 +
                    return;
 +
                }
 +
 
 +
                self.data = self.load(hashedPageName, $tables.length);
 +
                self.initTables(hashedPageName, $tables);
 +
            },
   −
        // requires CSS classes named in lightOnClass and mouseOverClass
+
            /*
        var wgPageName = mw.config.get('wgPageName'),
+
            * Initialise table highlighting.
            cookiePrefix = 'lightTable',
+
            *
            tableClass = 'lighttable',
+
            * @param hashedPageName The current page name as a hash.
            lightOnClass = 'highlight-on',
+
            * @param $tables A list of highlightable tables on the current page.
            mouseOverClass = 'highlight-over',
+
            */
            base64url = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
+
            initTables: function(hashedPageName, $tables) {
            pageSeparator = '!',
+
                $tables.each(function(tIndex) {
            tableSeparator = '.',
+
                    var $this = $(this),
            hashPageName,
+
                        // data cells
            rows = [],
+
                        $cells = $this.find('td'),
            columns,
+
                        $rows = $this.find('tr:has(td)'),
            tables,
+
                        // don't rely on headers to find number of columns     
            cookie;
+
                        // count them dynamically
 +
                        columns = 1,
 +
                        tableData = self.data[tIndex],
 +
                        mode = 'cells';
   −
        // hash a string into a 32-bit hex string, msb first
+
                    // Switching between either highlighting rows or cells
        function crc32c(s) {
+
                    if (!$this.hasClass('individual')) {
            var polynomial = 0x04C11DB7, // Castagnoli polynomial
+
                        mode = 'rows';
                retVal,
+
                        $cells = $rows;
                table = [],
+
                    }
                i,
  −
                j,
  −
                k;
     −
            // guarantee 8-bit chars
+
                    // initialise rows if necessary
            s = window.unescape(window.encodeURI(s));
+
                    while ($cells.length > tableData.length) {
 +
                        tableData.push(0);
 +
                    }
   −
            // calculate the crc for all 8-bit data
+
                    // counting the column count
            // bit-wise operations discard anything left of bit 31
+
                    // necessary to determine colspan of reset button
            for (i = 0; i < 256; i += 1) {
+
                    $rows.each(function() {
                k = (i << 24);
+
                        var $this = $(this);
                for (j = 0; j < 8; j += 1) {
+
                        columns = Math.max(columns, $this.children('th,td').length);
                     k = (k << 1) ^ ((k >>> 31) * polynomial);
+
                    });
 +
 
 +
                    $cells.each(function(cIndex) {
 +
                        var $this = $(this),
 +
                            cellData = tableData[cIndex];
 +
 
 +
                        // forbid highlighting any cells/rows that have class nohighlight
 +
                        if (!$this.hasClass('nohighlight')) {
 +
                            // initialize highlighting based on the cookie
 +
                            self.setHighlight($this, cellData);
 +
 
 +
                            // set mouse events
 +
                            $this
 +
                                .mouseover(function() {
 +
                                    self.setHighlight($this, 2);
 +
                                })
 +
                                .mouseout(function() {
 +
                                    self.setHighlight($this, tableData[cIndex]);
 +
                                })
 +
                                .click(function(e) {
 +
                                    // don't toggle highlight when clicking links
 +
                                    if ((e.target.tagName !== 'A') && (e.target.tagName !== 'IMG')) {
 +
                                        // 1 -> 0
 +
                                        // 0 -> 1
 +
                                        tableData[cIndex] = 1 - tableData[cIndex];
 +
 
 +
                                        self.setHighlight($this, tableData[cIndex]);
 +
                                        self.save(hashedPageName);
 +
                                    }
 +
                                });
 +
                        }
 +
                    });
 +
 
 +
                    // add a button for reset
 +
                    var button = new OO.ui.ButtonWidget({
 +
                        label: (mode === 'rows') ?
 +
                      'Clear highlighted rows' :
 +
                            'Clear highlighted cells',
 +
                        icon: 'clear',
 +
                        title: 'Removes all highlights from the table',
 +
                        classes: ['ht-reset'] // this class is targeted by other gadgets, be careful removing it
 +
                    });
 +
 
 +
 
 +
                    button.$element.click(function() {
 +
                        $cells.each(function(cIndex) {
 +
                            tableData[cIndex] = 0;
 +
                            self.setHighlight($(this), 0);
 +
                        });
 +
 
 +
                        self.save(hashedPageName, $tables.length);
 +
                    });
 +
 
 +
                     $this.append(
 +
                        $('<tfoot>')
 +
                            .append(
 +
                                $('<tr>')
 +
                                    .append(
 +
                                        $('<th>')
 +
                                            .attr('colspan', columns)
 +
                                            .append(button.$element)
 +
                                    )
 +
                            )
 +
                    );
 +
                });
 +
            },
 +
 
 +
            /*
 +
            * Change the cell background color based on mouse events.
 +
            *
 +
            * @param $cell The cell element.
 +
            * @param val The value to control what class to add (if any).
 +
            *            0 -> light off (no class)
 +
            *            1 -> light on
 +
            *            2 -> mouse over
 +
            */
 +
            setHighlight: function($cell, val) {
 +
                $cell.removeClass(MOUSE_OVER_CLASS);
 +
                $cell.removeClass(LIGHT_ON_CLASS);
 +
 
 +
                switch (val) {
 +
                    // light on
 +
                    case 1:
 +
                        $cell.addClass(LIGHT_ON_CLASS);
 +
                        break;
 +
 
 +
                    // mouse-over
 +
                    case 2:
 +
                        $cell.addClass(MOUSE_OVER_CLASS);
 +
                        break;
 +
                }
 +
            },
 +
 
 +
            /*
 +
            * Merge the updated data for the current page into the data for other pages into local storage.
 +
            *
 +
            * @param hashedPageName A hash of the current page name.
 +
            */
 +
            save: function(hashedPageName) {
 +
                // load the existing data so we know where to save it
 +
                var curData = localStorage.getItem(STORAGE_KEY),
 +
                    compressedData;
 +
 
 +
                if (curData === null) {
 +
                    curData = {};
 +
                } else {
 +
                    curData = JSON.parse(curData);
 +
                    curData = self.parse(curData);
 
                 }
 
                 }
                table[i] = k;
  −
            }
     −
            // the actual calculation
+
                // merge in our updated data and compress it
            retVal = 0;
+
                curData[hashedPageName] = self.data;
            for (i = 0; i < s.length; i += 1) {
+
                compressedData = self.compress(curData);
                 retVal = (retVal << 8) ^ table[(retVal >>> 24) ^ s.charCodeAt(i)];
+
 
            }
+
                // convert to a string and save to localStorage
 +
                compressedData = JSON.stringify(compressedData);
 +
                localStorage.setItem(STORAGE_KEY, compressedData);
 +
            },
 +
 
 +
            /*
 +
            * Compress the entire data set using tha algoritm documented at the top of the page.
 +
            *
 +
            * @param data The data to compress.
 +
            *
 +
            * @return the compressed data.
 +
            */
 +
            compress: function(data) {
 +
                 var ret = {};
 +
 
 +
                Object.keys(data).forEach(function(hashedPageName) {
 +
                    var pageData = data[hashedPageName],
 +
                        pageKey = hashedPageName.charAt(0);
 +
 
 +
                    if (!ret.hasOwnProperty(pageKey)) {
 +
                        ret[pageKey] = {};
 +
                    }
   −
            // make negative numbers unsigned
+
                    ret[pageKey][hashedPageName] = [];
            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;
+
                    pageData.forEach(function(tableData) {
        }
+
                        var compressedTableData = '',
 +
                            i, j, k;
   −
        // change the row bg color based on mouse events
+
                        for (i = 0; i < Math.ceil(tableData.length / 6); i += 1) {
        function setHighlight(el, val) {
+
                            k = tableData[6 * i];
            $(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
+
                            for (j = 1; j < 6; j += 1) {
        // cookie info is saved in 1 of 16 browser cookies, based on page name hash
+
                                k = 2 * k + ((6 * i + j < tableData.length) ? tableData[6 * i + j] : 0);
        // 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 = [];
+
                            compressedTableData += BASE_64_URL.charAt(k);
            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
+
                        ret[pageKey][hashedPageName].push(compressedTableData);
                         for (iTable = 0; iTable < tableCookies.length; iTable += 1) {
+
                    });
                             cookie[iTable] = [];
+
 
                             for (i = 0; i < tableCookies[iTable].length; i += 1) {
+
                    ret[pageKey][hashedPageName] = ret[pageKey][hashedPageName].join(TABLE_SEPARATOR);
                                 k = base64url.indexOf(tableCookies[iTable].charAt(i));
+
                });
                                 if (k < 0) { // input validation
+
 
 +
                Object.keys(ret).forEach(function(pageKey) {
 +
                    var hashKeys = Object.keys(ret[pageKey]),
 +
                        hashedData = [];
 +
 
 +
                    hashKeys.forEach(function(key) {
 +
                        var pageData = ret[pageKey][key];
 +
                        hashedData.push(key + pageData);
 +
                    });
 +
 
 +
                    hashedData = hashedData.join(PAGE_SEPARATOR);
 +
                    ret[pageKey] = hashedData;
 +
                });
 +
 
 +
                return ret;
 +
            },
 +
 
 +
            /*
 +
            * Get the existing data for the current page.
 +
            *
 +
            * @param hashedPageName A hash of the current page name.
 +
            * @param numTables The number of tables on the current page. Used to ensure the loaded
 +
            *                  data matches the number of tables on the page thus handling cases
 +
            *                  where tables have been added or removed. This does not check the
 +
            *                  amount of rows in the given tables.
 +
            *
 +
            * @return The data for the current page.
 +
            */
 +
            load: function(hashedPageName, numTables) {
 +
                var data = localStorage.getItem(STORAGE_KEY),
 +
                    pageData;
 +
 
 +
                if (data === null) {
 +
                    pageData = [];
 +
                } else {
 +
                    data = JSON.parse(data);
 +
                    data = self.parse(data);
 +
 
 +
                    if (data.hasOwnProperty(hashedPageName)) {
 +
                        pageData = data[hashedPageName];
 +
                    } else {
 +
                         pageData = [];
 +
                    }
 +
                }
 +
 
 +
                // if more tables were added
 +
                // add extra arrays to store the data in
 +
                // also populates if no existing data was found
 +
                while (numTables > pageData.length) {
 +
                    pageData.push([]);
 +
                }
 +
 
 +
                // if tables were removed, remove data from the end of the list
 +
                // as there's no way to tell which was removed
 +
                while (numTables < pageData.length) {
 +
                    pageData.pop();
 +
                }
 +
 
 +
                return pageData;
 +
            },
 +
 
 +
            /*
 +
            * Parse the compressed data as loaded from local storage using the algorithm desribed
 +
            * at the top of the page.
 +
            *
 +
            * @param data The data to parse.
 +
            *
 +
            * @return the parsed data.
 +
            */
 +
            parse: function(data) {
 +
                var ret = {};
 +
 
 +
                Object.keys(data).forEach(function(pageKey) {
 +
                    var pageData = data[pageKey].split(PAGE_SEPARATOR);
 +
 
 +
                    pageData.forEach(function(tableData) {
 +
                         var hashedPageName = tableData.substr(0, 8);
 +
 
 +
                        tableData = tableData.substr(8).split(TABLE_SEPARATOR);
 +
                        ret[hashedPageName] = [];
 +
 
 +
                        tableData.forEach(function(rowData, index) {
 +
                             var i, j, k;
 +
 
 +
                            ret[hashedPageName].push([]);
 +
 
 +
                             for (i = 0; i < rowData.length; i += 1) {
 +
                                 k = BASE_64_URL.indexOf(rowData.charAt(i));
 +
 
 +
                                // input validation
 +
                                 if (k < 0) {
 
                                     k = 0;
 
                                     k = 0;
 
                                 }
 
                                 }
 +
 
                                 for (j = 5; j >= 0; j -= 1) {
 
                                 for (j = 5; j >= 0; j -= 1) {
                                     cookie[iTable][6 * i + j] = (k & 0x1);
+
                                     ret[hashedPageName][index][6 * i + j] = (k & 0x1);
 
                                     k >>= 1;
 
                                     k >>= 1;
 
                                 }
 
                                 }
 
                             }
 
                             }
                         }
+
                         });
                     }
+
                     });
                 }
+
 
             }
+
                 });
 +
 
 +
                return ret;
 +
             },
 +
 
 +
            /*
 +
            * Hash a string into a big endian 32 bit hex string. Used to hash page names.
 +
            *
 +
            * @param input The string to hash.
 +
            *
 +
            * @return the result of the hash.
 +
            */
 +
            hashString: function(input) {
 +
                var ret = 0,
 +
                    table = [],
 +
                    i, j, k;
   −
            // initialize the cookie array of arrays, if needed
+
                // guarantee 8-bit chars
            while (cookie.length < numTables) {
+
                input = window.unescape(window.encodeURI(input));
                cookie.push([]);
  −
            }
  −
        }
     −
        // save/update the cookie for page reloads
+
                // calculate the crc (cyclic redundancy check) for all 8-bit data
        // cookie info is saved in 1 of 16 browser cookies, based on page name hash
+
                // bit-wise operations discard anything left of bit 31
        // global cookie[][] supports multiple tables and multiple pages
+
                for (i = 0; i < 256; i += 1) {
        // uses global hashPageName
+
                    k = (i << 24);
        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
+
                     for (j = 0; j < 8; j += 1) {
            // use Base64url to compress 6 rows to 1 character
+
                        k = (k << 1) ^ ((k >>> 31) * CASTAGNOLI_POLYNOMIAL);
            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);
+
                     table[i] = k;
 
                 }
 
                 }
            }
     −
            updated = 0;
+
                 // the actual calculation
            pageCookies = [];
+
                 for (i = 0; i < input.length; i += 1) {
            if ($.cookie(cookieName) !== null) {
+
                     ret = (ret << 8) ^ table[(ret >>> 24) ^ input.charCodeAt(i)];
                 // 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
+
                // make negative numbers unsigned
            $.cookie(cookieName, pageCookies.join(pageSeparator), {
+
                if (ret < 0) {
                expires: 7,
+
                    ret += UINT32_MAX;
                 path: '/'
+
                 }
            });
  −
        }
     −
        tables = $('table.' + tableClass);
+
                // 32-bit hex string, padded on the left
        // don't bother doing anything unless there's really something to do
+
                ret = '0000000' + ret.toString(16).toUpperCase();
        if (tables.length > 0) {
+
                ret = ret.substr(ret.length - 8);
            // hash the page name to an 8-char hex string
  −
            hashPageName = crc32c(wgPageName);
  −
            loadCookie(tables.length);
     −
             tables.each(function (iTable) {
+
                return ret;
                rows[iTable] = $(this).find('tr:has(td)'); // data rows
+
             }
 +
        };
   −
                // init or trim the cookie array of rows, if needed
+
    $(self.init);
                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
+
    // sample data for testing the algorithm used
                columns = 1;
+
    var data = {
 +
        // page1
 +
        '0FF47C63': [
 +
            [0, 1, 1, 0, 1, 0],
 +
            [0, 1, 1, 0, 1, 0, 1, 1, 1],
 +
            [0, 0, 0, 0, 1, 1, 0, 0]
 +
        ],
 +
        // page2
 +
        '02B75ABA': [
 +
            [0, 1, 0, 1, 1, 0],
 +
            [1, 1, 1, 0, 1, 0, 1, 1, 0],
 +
            [0, 0, 1, 1, 0, 0, 0, 0]
 +
        ],
 +
        // page3
 +
        '0676470D': [
 +
            [1, 0, 0, 1, 0, 1],
 +
            [1, 0, 0, 1, 0, 1, 0, 0, 0],
 +
            [1, 1, 1, 1, 0, 0, 1, 1]
 +
        ]
 +
    };
   −
                rows[iTable].each(function (iRow) {
+
    console.log('input', data);
                    // 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
+
    var compressedData = self.compress(data);
                    setHighlight(this, cookie[iTable][iRow]);
+
    console.log('compressed', compressedData);
 
  −
                    // 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);
+
     var parsedData = self.parse(compressedData);
 +
    console.log(parsedData);
 +
    */
   −
}(this.jQuery, this.mediaWiki));
+
}(this.jQuery, this.mediaWiki, this.OO, this.rswiki));
   −
/* </pre> */
+
// </pre>
52

edits