User:Chieftain Alex/Wiki javascripts

From Guild Wars 2 Wiki
Jump to navigationJump to search
See also: User:Chieftain Alex/API javascripts
<div id="apidata">[[File:Mediawiki loading animation.gif]]</div>
Mediawiki loading animation.gif (nothing is loading until you paste a script from below into your javascript scratchpad)

Wiki API - All categories[edit]

/* GW2W API query tool for all categories as the generator with additional properties */
console.log('User pressed run. Starting queries for Special:Categories');
var continue_param = '';

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                if (continue_param == data['continue'][config.continue]) {
                  // Quit if its making two queries in a row with the same continue offset... probably indicates wrong limits set.
                  return;
                }
                continue_param = data['continue'][config.continue];
                console.log(continue_param);

                // Make next query
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML(config) {
    var data = config.resultsarray;
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>EN page</th><th>Categories</th></tr>';
    $.each(data, function(index, val) {
        result += '<tr>';
        // Add english page title
        result += '<td>'+val['title']+'</td>';
    
        // Add categories
        if (typeof val['categories'] !== 'undefined'){
            result += '<td>' + $.map(val['categories'], function(v) { return v.title }).join(', ')  + '</td>';
        } else {
            result += '<td>...</td>';
        }
        result += '</tr>\n';
    });
    result += '</table>';
    $('#mw-content-text').html('<pre'+'>' + result + '</'+'pre>');
}

// ------------ Notes -----------------------
// We're using a generator here, so all the parameters usually used from action=query have a "g" on the front of it.
// Generators allow you to extract additional properties not normally available from "list=allpages".
// The output format is dumb from generators, you need to set "formatversion=2" to make it use an array like every other endpoint.
// Generators are dumb; the limits need to be set for each of the individual props too. These limits should be higher than that
//   set for the actual generator. 4x higher seems to be the sweetspot. (e.g. gaplimit=1000, cllimit=4000)
// Admins and bots have limits of 5000 as well as no throttling. Regular users have limits of 500.

// Make the request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&formatversion=2' + '&action=query' + '&generator=allcategories&gaclimit=1000' + '&prop=categories&cllimit=5000',
  output: 'pages',
  continue: 'gaccontinue',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - All pages[edit]

/* GW2W API query tool for all pages */

// Setup
var redirectfilter = 'nonredirects'; // all, redirects
var languagelinkfilter = 'all'; // withlanglinks, withoutlanglinks
var baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&list=allpages&aplimit=500&apfilterredir='+redirectfilter+'&apfilterlanglinks='+languagelinkfilter;
var datadrop = [];

// Function to concatenate all data
function processdata (datadrop) {
    var contribs = [];
    $.each(datadrop, function(k,v){
        $.each(v, function(kk,vv){
            contribs.push(vv);
        });
    });
    $('#mw-content-text').html(makeTableHTML(contribs));
}

// Function to convert an object variable into a table
function makeTableHTML( data ) {
        var result = '<table class="table mech1"><tbody>'
                    +'<tr><th>Pageid</th><th>Name</th></tr>';
        $.each(data, function(k, v) {
                result += '<tr id="'+v['revid']+'">'
                          +'<td>'+v['pageid']+'</td><td>'+v['title']+'</td>'
                         +'</tr>';
        });
        result += "</tbody></table>";
        return result;
}

// Fetch all the pages
function apiQuery (token,startkey) {
    var url = baseurl;
    if (startkey) {
     url += '&apfrom=' + startkey;
    }
    if (token) {
     url += '&apcontinue=' + token;
    }
    // console.log(url);
    $.getJSON(url).done(function(data){
        datadrop.push(data['query']['allpages']);

        if (data['continue']) {
            apiQuery(data['continue']['apcontinue']);
        } else {
            console.log('Query complete.');
            processdata(datadrop);
        }
    });
}

console.log('User pressed run. Starting queries for Special:AllPages');
//apiQuery(null,'Z');
apiQuery();

Wiki API - All pages (v2)[edit]

/* GW2W API query tool for all pages */
console.log('User pressed run. Starting queries for Special:AllPages');

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML (config) {
    var data = config.resultsarray;

    // Generate table html
    var result = '<table class="table mech1"><tbody>';
    if (data.length > 0) {
        var columns = Object.keys(data[0]);
        result += '<tr>' + $.map(columns, function(c) { return '<th>' + c + '</th>'; }).join('') + '</tr>';
        result += $.map(data, function(v) {
            return '<tr>' + $.map(columns, function(c) {
                return '<td>' + v[c] + '</td>';
            }).join('') + '</tr>';
        }).join('\n');
    }
    result += '</tbody></table>';
    $('#mw-content-text').html(result);
}

// Make request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&action=query&list=allpages&aplimit=500&apfilterredir=nonredirects&apfilterlanglinks=all',
  output: 'allpages',
  continue: 'apcontinue',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - Category pages[edit]

/* GW2W API query tool for all pages in a category */
console.log('User pressed run. Starting queries for Special:Category');
var category_page = 'Category:' + 'Bestiary screenshots';

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML (config) {
    var data = config.resultsarray;

    // Generate table html
    var result = '<table class="wikitable"><tbody>';
    if (data.length > 0) {
        var columns = Object.keys(data[0]);
        result += '<tr>' + $.map(columns, function(c) { return '<th>' + c + '</th>'; }).join('') + '</tr>';
        result += $.map(data, function(v) {
            return '<tr>' + $.map(columns, function(c) {
                return '<td>' + v[c] + '</td>';
            }).join('') + '</tr>';
        }).join('\n');
    }
    result += '</tbody></table>';
    $('#mw-content-text').html(result);
}

// Make request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&action=query&list=categorymembers&cmlimit=500&cmtitle=' + category_page,
  output: 'categorymembers',
  continue: 'cmcontinue',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - Generator example (all pages, categories and interwikis)[edit]

/* GW2W API query tool for all pages as the generator with additional properties */
console.log('User pressed run. Starting queries for Special:AllPages');
var continue_param = '';

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                if (continue_param == data['continue'][config.continue]) {
                  // Quit if its making two queries in a row with the same continue offset... probably indicates wrong limits set.
                  return;
                }
                continue_param = data['continue'][config.continue];
                console.log(continue_param);

                // Make next query
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML(config) {
    var data = config.resultsarray;
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>EN page</th><th>DE page</th><th>ES page</th><th>FR page</th><th>Categories</th></tr>';
    $.each(data, function(index, val) {
        result += '<tr>';
        // Add english page title
        result += '<td>'+val['title']+'</td>';
        if (typeof val['langlinks'] !== 'undefined'){
            // Placeholder with all interwiki language keys
            var resultobj = { de: '', es: '', fr: '' };

            // Go through each interwiki on the page and add them into the object
            $.map(val['langlinks'], function(v){
                resultobj[v['lang']] = v['title'];
            });

            // Add to the results
            result += $.map(resultobj, function(v){
                return '<td>' + v + '</td>';
            }).join('');
        } else {
            result += '<td>...</td><td>...</td><td>...</td>';
        }
        if (typeof val['categories'] !== 'undefined'){
            result += '<td>' + $.map(val['categories'], function(v) { return v.title }).join(', ')  + '</td>';
        } else {
            result += '<td>...</td>';
        }
        result += '</tr>\n';
    });
    result += '</table>';
    $('#mw-content-text').html(result);
}

// ------------ Notes -----------------------
// We're using a generator here, so all the parameters usually used from action=query have a "g" on the front of it.
// Generators allow you to extract additional properties not normally available from "list=allpages".
// The output format is dumb from generators, you need to set "formatversion=2" to make it use an array like every other endpoint.
// Generators are dumb; the limits need to be set for each of the individual props too. These limits should be higher than that
//   set for the actual generator. 4x higher seems to be the sweetspot. (e.g. gaplimit=1000, lllimit=4000, cllimit=4000)
// Admins and bots have limits of 5000 as well as no throttling. Regular users have limits of 500.

// Make the request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&formatversion=2' + '&action=query' + '&generator=allpages&gapfilterredir=nonredirects&gapfilterlanglinks=all&gaplimit=1000' + '&prop=categories|langlinks&lllimit=5000&cllimit=5000',
  output: 'pages',
  continue: 'gapcontinue',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - Generator for images[edit]

/* GW2W API query tool for all pages as the generator with additional properties */
console.log('User pressed run. Starting queries for Special:AllPages');
var continue_param = '';

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        } else {
            // for testing with a large offset
            // url += '&' + config.continue + '=' + 'Zaan_Ruinbringer.jpg';
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                if (continue_param == data['continue'][config.continue]) {
                  // Quit if its making two queries in a row with the same continue offset... probably indicates wrong limits set.
                  return;
                }
                continue_param = data['continue'][config.continue];
                console.log(continue_param);

                // Make next query
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML(config) {
    var data = config.resultsarray;
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>Title</th><th>Height (px)</th><th>Width (px)</th><th>Size (Kb)</th><th>Uploader</th><th>Timestamp</th><th>Categories</th></tr>';
    $.each(data, function(index, val) {
        result += '<tr>';
        // Add english page title
        result += '<td>'+val['title']+'</td>';

        // Add image metadata
        if (typeof val['imageinfo'] !== 'undefined' && val.imageinfo.length > 0){
            var h = val.imageinfo[0].height || 0, w = val.imageinfo[0].width || 0, s = val.imageinfo[0].size || 0, u = val.imageinfo[0].user || '', t = val.imageinfo[0].timestamp || '';
            result += '<td>'+h+'</td><td>'+w+'</td><td>'+(s/1024).toFixed(1)+'</td><td>'+u+'</td><td>'+t.replace('Z','').replace('T',' ') +'</td>';
        } else {
            result += '<td>...</td><td>...</td><td>...</td><td>...</td><td>...</td>';
        }

        // Add categories
        if (typeof val['categories'] !== 'undefined'){
            result += '<td>' + $.map(val['categories'], function(v) { return v.title }).join(', ')  + '</td>';
        } else {
            result += '<td>...</td>';
        }
        result += '</tr>\n';
    });
    result += '</table>';
    $('#mw-content-text').html(result);
}

// Make the request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&formatversion=2' + '&action=query' + '&generator=allpages&gapfilterredir=nonredirects&gapfilterlanglinks=all&gapnamespace=6&gaplimit=1000' + '&prop=categories|imageinfo&iiprop=size|user|timestamp&iilimit=5000&cllimit=5000',
  output: 'pages',
  continue: 'gapcontinue',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - Generator for images with fileusage[edit]

/* GW2W API query tool for FILES in a given CATEGORY (as the generator) returning additional image properties via prop=fileusage */
console.log('User pressed run. Starting queries for Special:CategoryMembers');
var cat = 'Category:Screenshots';

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if ('continue' in data) {
                var continue_suffix = $.map(data['continue'], function(v,k){
                    return k + '=' + v;
                }).join('&');
                console.log(continue_suffix); // debugging

                // Make next query
                apiQuery(config, continue_suffix);
                
            } else if ('batchcomplete' in data && data.batchcomplete == true){
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            } else {
                console.log('Error - landed on an API query without a batchcomplete or continue.');
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML(config) {
    var data = config.resultsarray;
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>file page id</th><th>file page title</th><th>index</th><th>Page title</th></tr>';
    $.each(data, function(index, val) {
        if (typeof val['fileusage'] !== 'undefined'){
            $.each(val['fileusage'], function(i,v){
                result += '<tr>';
                    result += '<td>'+val['pageid']+'</td>' + '<td>'+val['title']+'</td>';
                    result += '<td>' + i + '</td>' + '<td>' + v.title + '</td>'
                result += '</tr>\n';
            });
        } else {
                result += '<tr>';
                    result += '<td>'+val['pageid']+'</td><td>'+val['title']+'</td><td>...</td><td>...</td>';
                result += '</tr>\n';
        }

    });
    result += '</table>';
    $('#mw-content-text').html(result);
}

// Make the request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&formatversion=2' + '&action=query' + '&generator=categorymembers&gcmtitle=' + cat + '&gcmlimit=1000' + '&prop=fileusage&funamespace=0&fulimit=5000', // always leave the generator limit (5000) much higher than the page limit (1000)
  output: 'pages',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - Image metadata[edit]

/* GW2W API query tool for image metadata. You're supposed to be able to query not using names, but I dunno how to convert filenames to page numbers. */
// Function to convert an object variable into a table
function makeTableHTML(data) {
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>Image title</th><th>Size</th><th>Width</th><th>Height</th><th>User</th></tr>';
    $.each(data, function(index, val) {
        if (typeof val['imageinfo'] !== 'undefined'){
            result += '<tr><td>'+val['title']+'</td>'
                +'<td>'+val['imageinfo'][0]['size']+'</td>'
                +'<td>'+val['imageinfo'][0]['width']+'</td>'
                +'<td>'+val['imageinfo'][0]['height']+'</td>'
                +'<td>'+val['imageinfo'][0]['user']+'</td>'
              +'</tr>';
        }
    });
    result += '</table>';
    return result;
}

// Fetch all the possible itemsIDs
(function fetchAPIData() {

var ids = ["File:Master Blaster.jpg","File:Master Blaster.png","File:Moonshank.jpg"];

        console.log('Number of items: ' + ids.length);

        // Query API until all the ids have been requested
        var promises = [], baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&prop=imageinfo&iiprop=size|user&titles=';
        var lines = [[]], maxlength = 1800, j = 0, running_total = 0;
        for (var i=0; i<ids.length; i++) {
            if ((running_total + ids[i].length) >= maxlength) {
                j += 1;
                lines.push([]);
                running_total = 0;
            }
            running_total += 1 + ids[i].length;
            lines[j].push(ids[i]);
        }
        for (var k=0; k<lines.length; k++) {
            var promise = $.getJSON(baseurl + lines[k].join('|') );
            promises.push(promise);
        }

        // Wait until all the GET requests have finished
        $.when.apply($,promises).done(function() {
            var newarguments = {};
            if ( promises.length > 1 ) { newarguments = arguments; } else { newarguments[0] = arguments; }

            console.log(newarguments);
            var alldata = [];
            $.each(newarguments, function(i,v){
              $.each(v[0]['query']['pages'], function(ii,vv){
                alldata.push(vv);
              });
            });

            // Write to document
            $('#apidata').html(makeTableHTML(alldata));
        });

})();

Wiki API - Interwikis[edit]

/* GW2W API query tool for language links. */
// Function to convert an object variable into a table
function makeTableHTML(data) {
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>EN page</th><th>DE page</th><th>ES page</th><th>FR page</th></tr>';
    $.each(data, function(index, val) {
        if (typeof val['langlinks'] !== 'undefined'){
            // Add english page title
            result += '<tr>' + '<td>'+val['title']+'</td>';

            // Placeholder with all interwiki language keys
            var resultobj = { de: '', es: '', fr: '' };

            // Go through each interwiki on the page and add them into the object
            $.map(val['langlinks'], function(v){
                resultobj[v['lang']] = v['*'];
            });

            // Add to the results
            result += $.map(resultobj, function(v){
                return '<td>' + v + '</td>';
            }).join('\n');
            result += '</tr>';
        } else {
            result += '<tr>' + '<td>'+val['title']+'</td><td>...</td><td>...</td><td>...</td></tr>';
        }
    });
    result += '</table>';
    return result;
}

// Fetch all the possible itemsIDs
(function fetchAPIData() {

var ids = ["Main Page","Charr","Asura"];

        console.log('Number of pages: ' + ids.length);

        // Query API until all the page ids have been requested
        var promises = [], baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&prop=langlinks&lllimit=500&titles=';
        var lines = [[]], maxlength = 1500, j = 0, running_count = 0, running_total = 0;
        for (var i=0; i<ids.length; i++) {
            if ((running_total + ids[i].length) >= maxlength || running_count > 500) {
                j += 1;
                lines.push([]);
                running_count = 0;
                running_total = 0;
            }
            running_count += 1;
            running_total += 1 + ids[i].length;
            lines[j].push(ids[i]);
        }
        for (var k=0; k<lines.length; k++) {
            var promise = $.getJSON(baseurl + lines[k].join('|') );
            promises.push(promise);
        }

        // Wait until all the GET requests have finished
        $.when.apply($,promises).done(function() {
            var newarguments = {};
            if ( promises.length > 1 ) { newarguments = arguments; } else { newarguments[0] = arguments; }

            console.log(newarguments);
            var alldata = [];
            $.each(newarguments, function(i,v){
              $.each(v[0]['query']['pages'], function(ii,vv){
                alldata.push(vv);
              });
            });

            // Write to document
            $('#apidata').html(makeTableHTML(alldata));
        });

})();

Wiki API - Log entries[edit]

/* GW2W API query tool for log entries */
// Useful reference link: "https://www.mediawiki.org/wiki/API:Lists/All#Logevents"

// Setup
var loguser = 'Chieftain Alex';
var logtype = 'delete/delete';
var baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&list=logevents&lelimit=500&leaction=' + logtype + '&leuser=' + loguser;
var datadrop = [];

// Function to concatenate all data
function processdata (datadrop) {
    var contribs = [];
    $.each(datadrop, function(k,v){
        $.each(v, function(kk,vv){
            contribs.push(vv);
        });
    });
    $('#mw-content-text').html(makeTableHTML(contribs));
}

// Function to convert an object variable into a table
function makeTableHTML( data ) {
        var result = '<table class="table mech1"><tbody>'
                    +'<tr><th>Namespace</th><th>Timestamp</th><th>Title</th></tr>';
        $.each(data, function(k, v) {
                result += '<tr id="'+v['revid']+'">'
                          +'<td>'+v['ns']+'</td><td>'+v['timestamp']+'</td><td>'+v['title']+'</td>'
                         +'</tr>';
        });
        result += "</tbody></table>";
        return result;
}

// Fetch all the log entries
function apiQuery (token) {
    var url = baseurl;
    if (token) {
     url += '&lecontinue=' + token
    }
    // console.log(url);
    $.getJSON(url).done(function(data){
        datadrop.push(data['query']['logevents']);

        if (data['continue']) {
            apiQuery(data['continue']['lecontinue']);
        } else {
            console.log('Query complete.');
            processdata(datadrop);
        }
    });
}

console.log('User pressed run. Starting deletion log queries for User:' + user + '...');
apiQuery();

Wiki API - Namespaces[edit]

/* GW2W API query tool for Mediawiki namespaces statistics */

// Function to convert an object variable into a table
function makeTableHTML( data ) {
        var result = '<table class="table mech1"><tbody>'+'<tr><th>Namespace ID</th><th>Name</th></tr>';
        $.each(data, function(k, v) {
            result += '<tr>'+'<td>'+v['id']+'</td><td>'+v['canonical']+'</td>'+'</tr>';
        });
        result += "</tbody></table>";
        return result;
}

// Fetch all the namespaces
function apiQuery () {
    // console.log(url);
    $.getJSON('https://wiki.guildwars2.com/api.php?action=query&format=json&meta=siteinfo&siprop=namespaces').done(function(data){
        $('#mw-content-text').html(makeTableHTML(data['query']['namespaces']));
    });
}
apiQuery();

Wiki API - Redirect resolving[edit]

/* GW2W API query tool for finding where redirects go. */
// https://www.mediawiki.org/wiki/API:Query#Resolving_redirects

// Function to convert an object variable into a table
function makeTableHTML(data) {
    console.log(data);
    var result = '<table class="table mech1" style="margin-bottom:0px;"><tr><th>Redirect from</th><th>Redirect to</th><th>Fragment</th></tr>';
    $.each(data, function(index, val) {
        result += '<tr><td>'+val['from']+'</td><td>'+val['to']+'</td><td>'+ ('tofragment' in val ? val['tofragment'] : '') +'</td></tr>';
    });
    result += '</table>';
    return result;
}

// Fetch all the possible redirects for the given pages
(function fetchAPIData() {

var ids = [
"Ascended Flanged Mace",
"Bluebriar Emergency Waypoint"
];

    console.log('Number of items: ' + ids.length);

    // Query API until all the ids have been requested
    var promises = [], baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&formatversion=2&prop=redirects&rdprop=pageid|title|fragment&rdnamespace=0|6|10&rdlimit=500&redirects&titles=';
    var lines = [[]], maxlength = 1200, j = 0, running_total = 0;
    for (var i=0; i<ids.length; i++) {
        if ((running_total + ids[i].length) >= maxlength) {
            j += 1;
            lines.push([]);
            running_total = 0;
        }
        running_total += 1 + ids[i].length;
        lines[j].push(ids[i]);
    }
    for (var k=0; k<lines.length; k++) {
        var promise = $.getJSON(baseurl + lines[k].join('|') );
        promises.push(promise);
    }

    // Wait until all the GET requests have finished
    $.when.apply($,promises).done(function() {
        var newarguments = {};
        if ( promises.length > 1 ) { newarguments = arguments; } else { newarguments[0] = arguments; }

        //console.log(newarguments);
        var alldata = [];
        $.each(newarguments, function(i,v){
          $.each(v[0]['query']['redirects'], function(ii,vv){
            alldata.push(vv);
          });
        });

        // Write to document
        $('#apidata').html(makeTableHTML(alldata));
    });
})();

Wiki API - SMW single result (via template)[edit]

/* GW2W API query tool for SMW results */
function apiQuery () {
    mw.loader.using('mediawiki.api.parse', function () {
        var query = '[[Has equipment supertype::Weapon]] [[Has appearance::+]]';
        var parameters = 'Has weapon type';
        var firstquery = '{{User:Chieftain Alex/Templates/SMW query|mode=1|query='+query+'}}';

        var api = new mw.Api();
        api.parse(firstquery).done(function (resulttext) {

            // Find the output token
            var pattern = /\<div class\="apiresults"\>(\d+)\<\/div\>/;
            var m = resulttext.match(pattern);
            console.log('regexp', m);

            // Check something matched
            if (!m) {
                console.log('No regular expression matched, quitting.')
                return;
            }

            // Convert match from text into a number.
            var n = Number(m[1]);
            if (n == 0) {
                console.log('Zero results found, quitting.');
            } else {
                console.log(n, ' results found, querying...');

                // Check if n > 5000 -- SMW bug won't let us get more results than this
                if (n > 5000) {
                  console.log('Truncating results to 5000 (SMW bug)');
                  n = 5000;
                }

                // Repeat query n/500 times until done
                var promises = [];
                for (var i=0; i<n; i+=500) {
                    var furtherquery = '{{User:Chieftain Alex/Templates/SMW query|mode=2|query='+query+'|parameters='+parameters+'|offset='+i+'}}';
                    promises.push(api.parse(furtherquery));
                }

                // Wait until all the GET requests have finished
                $.when.apply($,promises).done(function() {
                    // Concatenate the api results
                    var table = $.map(arguments, function(v) { return v; }).join('\n');

                    // Write to document
                    $('#apidata').html(table);

                    // Now copy the output to excel, then remove duplicates including table headings.
                    console.log('Batch query complete.');
                });
            }
        });
    });
}
apiQuery();

Wiki API - SMW result misc inputs (via template)[edit]

/* GW2W API query tool for SMW results for miscellaneous page inputs */
function apiQuery () {
    mw.loader.using('mediawiki.api.parse', function () {
        var parameters = 'Has game id#;Has context';
        var pages = ["Precise Strike","Tail Wind","Loud Whistle"];

        var api = new mw.Api();

        // Break the list of pages down into a url almost 2000 characters long.
        var lines = [[]], maxlength = 1800, j = 0, running_count = 0, running_total = 0;
        for (var i=0; i<pages.length; i++) {
            if ((running_total + pages[i].length) >= maxlength || running_count > 200) {
                j += 1;
                lines.push([]);
                running_count = 0;
                running_total = 0;
            }
            running_count += 1;
            running_total += 3 + pages[i].length;
            lines[j].push(pages[i]);
        }
        // Submit each request, result is returned as a table.
        var promises = [];
        for (var k=0; k<lines.length; k++) {
            var current_pages = lines[k].join(';');
            var parsetext = '{{User:Chieftain Alex/Templates/SMW query misc|pages='+current_pages+'|parameters='+parameters+'}}';
            promises.push(api.parse(parsetext));
        }

        // Wait until all the GET requests have finished
        $.when.apply($,promises).done(function() {
            // Concatenate the api results
            var table = $.map(arguments, function(v) { return v; }).join('\n');

            // Write to document
            $('#apidata').html(table);

            // Now copy the output to excel, then remove duplicates including table headings.
            console.log('Batch query complete.');
        });
    });
}
apiQuery();

Wiki API - SMW recipes[edit]

/* GW2W API SMW query tool for recipes */

// Setup\
var baseurl = 'https://wiki.guildwars2.com/api.php?action=ask&format=json&query='
var query = encodeURIComponent('[[Requires discipline::Chef]][[Has item data object::+]]|?Has recipe id|?Has output quantity|?Has item data object|?Has output game id|?Has ingredient with id|limit=500|link=none');
var datadrop = [];

// Function to concatenate all data
function processdata (datadrop) {
    var a = $.map(datadrop, function(v){ return v; });
    $('#apidata').html('<pre'+'></pre'+'>');
    $('#apidata pre').text(JSON.stringify(a, null, 2)
                          .replace(new RegExp("\n(  ){4}", "g")," ")
                          .replace(new RegExp("\n(  ){3}\}", "g")," }")
                         );
    console.log('Query and formatting complete.');
}

// Fetch all the recipes
function apiQuery (token) {
    var url = baseurl+query;
    if (token) {
     url += encodeURIComponent('|offset=') + token
    }
    // console.log(url);
    $.getJSON(url).done(function(rawdata){
        // Streamline results prior to storage
        var data = $.map(rawdata['query']['results'], function(v){
            var w = v.printouts;
            return {
                'wiki_page': v.fulltext, // only available if '|mainlabel=-' is not added.
                'recipe_id': w['Has recipe id'][0],
                'output_item_id': (w['Has output game id'].length > 0 ? w['Has output game id'][0] : null),
                'output_item_count': w['Has output quantity'][0],
                'output_item_wikiname': w['Has item data object'][0]['fulltext'],
                'ingredients': $.map(w['Has ingredient with id'], function(x){
                    return {
                        'item_id': (x['Has ingredient id']['item'].length > 0 ? x['Has ingredient id']['item'][0] : null),
                        'count': (x['Has ingredient quantity']['item'].length > 0 ? x['Has ingredient quantity']['item'][0] : null ),
                        'wikiname': (x['Has ingredient name']['item'].length > 0 ? x['Has ingredient name']['item'][0]['fulltext'] : null )
                    }
                })
            }
        });
        datadrop.push(data);

        if (rawdata['query-continue-offset']) {
            apiQuery(rawdata['query-continue-offset']);
        } else {
            processdata(datadrop);
        }
    });
}

console.log('User pressed run. Starting SMW queries...');
apiQuery();

Wiki API - Template parameter check[edit]

/* GW2W API query tool for Template parameters */
function apiQuery () {
    mw.loader.using('mediawiki.api.parse', function () {
        var template = 'ArenaNet image';
        var category = 'Guild emblems';
        var parameters = '1:2:id';
        var firstquery = '{{User:Chieftain Alex/Templates/Parameter check|mode=1|template='+template+( category != '' ? ('|category=' + category) : '' )+'}}';

        var api = new mw.Api();
        api.parse(firstquery).done(function (resulttext) {

            // Find the output token
            var pattern = /\<div class\="apiresults"\>(\d+)\<\/div\>/;
            var m = resulttext.match(pattern);
            console.log('regexp', m);

            // Check something matched
            if (!m) {
                console.log('No regular expression matched, quitting.')
                return;
            }

            // Convert match from text into a number.
            var n = Number(m[1]);
            if (n == 0) {
                console.log('Zero results found, quitting.');
            } else {
                console.log(n, ' results found, querying...');

                // Repeat query n/500 times until done
                var promises = [];
                for (var i=0; i<n; i+=500) {
                    var furtherquery = '{{User:Chieftain Alex/Templates/Parameter check|mode=2|template='+template+( category != '' ? ('|category=' + category) : '' )+'|parameters='+parameters+'|offset='+i+'}}';
                    promises.push(api.parse(furtherquery));
                }

                // Wait until all the GET requests have finished
                $.when.apply($,promises).done(function() {
                    // Concatenate the api results
                    var table = $.map(arguments, function(v) { return v; }).join('\n');

                    // Write to document
                    $('#apidata').html(table);

                    // Replace first column PAGENAME with FULLPAGENAME (i.e. add namespace)
                    $.map($('#apidata td:first-child a') ,function(v,i){ $(v).text( v.title ); });

                    // Now copy the output to excel, then remove duplicates including table headings.
                    console.log('Batch query complete.');
                });
            }
        });
    });
}
apiQuery();

Wiki API - Unused images[edit]

/* GW2W API query tool for Special pages such as Unused images - see https://www.mediawiki.org/wiki/API:Querypage */
console.log('User pressed run. Starting queries for Special page.');
var special_page = 'Unusedimages'; // Ancientpages, BrokenRedirects, Deadendpages, DisambiguationPageLinks, DisambiguationPages, DoubleRedirects, Fewestrevisions, GadgetUsage, GloballyWantedFiles, ListDuplicatedFiles, Listredirects, Lonelypages, Longpages, MediaStatistics, MostGloballyLinkedFiles, Mostcategories, Mostimages, Mostinterwikis, Mostlinked, Mostlinkedcategories, Mostlinkedtemplates, Mostrevisions, Shortpages, Uncategorizedcategories, Uncategorizedimages, Uncategorizedpages, Uncategorizedtemplates, UnconnectedPages, Unusedcategories, Unusedimages, Unusedtemplates, Unwatchedpages, Wantedcategories, Wantedfiles, Wantedpages, Wantedtemplates, Withoutinterwiki

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query']['querypage']['results']);

            // Get further results if available
            if ('continue' in data) {
                var continue_suffix = $.map(data['continue'], function(v,k){
                    return k + '=' + v;
                }).join('&');
                // console.log(continue_suffix); // debugging

                // Make next query
                apiQuery(config, continue_suffix);
                
            } else if ('batchcomplete' in data && data.batchcomplete == true){
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            } else {
                console.log('Error - landed on an API query without a batchcomplete or continue. Trying to finish anyway.');
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });
                console.log(config.resultsarray);
                callbackfunction(config);
            }

        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML (config) {
    var data = config.resultsarray;

    // Generate table html
    var result = '<table class="wikitable"><tbody>';
    if (data.length > 0) {
        var columns = Object.keys(data[0]);
        result += '<tr>' + $.map(columns, function(c) { return '<th>' + c + '</th>'; }).join('') + '</tr>';
        result += $.map(data, function(v) {
            return '<tr>' + $.map(columns, function(c) {
                return '<td>' + v[c] + '</td>';
            }).join('') + '</tr>';
        }).join('\n');
    }
    result += '</tbody></table>';
    $('#mw-content-text').html(result);
}

// Make request
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&action=query&list=querypage&qplimit=500&qppage=' + special_page,
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - User contributions[edit]

/* GW2W API query tool for contribution statistics */
// Useful reference link: https://wiki.guildwars2.com/api.php?action=query&meta=siteinfo&siprop=namespaces

// Setup
var user = 'Darqbot';
var baseurl = 'https://wiki.guildwars2.com/api.php?action=query&format=json&list=usercontribs&uclimit=500&ucdir=newer&ucuser=' + user;
var datadrop = [];

// Function to concatenate all data
function processdata (datadrop) {
    var contribs = [];
    $.each(datadrop, function(k,v){
        $.each(v, function(kk,vv){
            contribs.push(vv);
        });
    });
    $('#mw-content-text').html(makeTableHTML(contribs));
}

// Function to convert an object variable into a table
function makeTableHTML( data ) {
        var result = '<table class="table mech1"><tbody>'
                    +'<tr><th>Namespace</th><th>Timestamp</th><th>Size</th><th>Title</th></tr>';
        $.each(data, function(k, v) {
                result += '<tr id="'+v['revid']+'">'
                          +'<td>'+v['ns']+'</td><td>'+v['timestamp']+'</td><td>'+v['size']+'</td><td>'+v['title']+'</td>'
                         +'</tr>';
        });
        result += "</tbody></table>";
        return result;
}

// Fetch all the contributions
function apiQuery (token) {
    var url = baseurl;
    if (token) {
     url += '&uccontinue=' + token
    }
    // console.log(url);
    $.getJSON(url).done(function(data){
        datadrop.push(data['query']['usercontribs']);

        if (data['continue']) {
            apiQuery(data['continue']['uccontinue']);
        } else {
            console.log('Query complete.');
            processdata(datadrop);
        }
    });
}

console.log('User pressed run. Starting queries for User:' + user + '...');
apiQuery();

Wiki API - User groups[edit]

https://wiki.guildwars2.com/api.php?action=query&list=users&usprop=editcount|groups|rights&ususers=Chieftain_Alex

Wiki API - Users who are autoconfirmed[edit]

/* GW2W API query tool for all autoconfirmed users */
console.log('User pressed run. Starting queries for Special:AllUsers');

// Wrapper function to return the results once complete
function apiWrapper (config, callbackfunction) {
    // Fetch all the pages
    function apiQuery (config, token) {
        var url = config.baseurl;
        if (token) {
            url += '&' + config.continue + '=' + token;
        }
        $.getJSON(url).done(function(data){
            // Add results to stack
            config.tempresultsarray.push(data['query'][config.output]);

            // Get further results if available
            if (data['continue']) {
                apiQuery(config, data['continue'][config.continue]);
            } else {
                // Flatten data from nested arrays to one array of result objects
                config.resultsarray = $.map(config.tempresultsarray, function(v) {
                    return v;
                });

                // Modification 1 - filter for only autoconfirmed users
                function onlyIfAutoconfirmed(e){
                    return e.implicitgroups.indexOf('autoconfirmed') > -1;
                }
                config.resultsarray = config.resultsarray.filter(onlyIfAutoconfirmed);

                // Modification 2 - filter for only names shorter than 50 characters
                function onlyAcceptableNames(e){
                    return e.name.length < 50;
                }
                config.resultsarray = config.resultsarray.filter(onlyAcceptableNames);
                console.log('Query complete.');

                // Call the next function
                callbackfunction(config);
            }
        });
    }
    apiQuery(config);
}

// Function to convert an object variable into a table
function makeTableHTML (config) {
    var data = config.resultsarray;

    // Generate table html
    var result = '<table class="wikitable"><tbody>';
    if (data.length > 0) {
        var columns = Object.keys(data[0]);
        result += '<tr>' + $.map(columns, function(c) { return '<th>' + c + '</th>'; }).join('') + '</tr>';
        result += $.map(data, function(v) {
            return '<tr>' + $.map(columns, function(c) {
                return '<td>' + v[c] + '</td>';
            }).join('') + '</tr>';
        }).join('\n');
    }
    result += '</tbody></table>';
    $('#mw-content-text').html(result);
}

// Make request
// https://www.mediawiki.org/w/api.php?action=help&modules=query%2Ballusers
// Initial filters: Only users with Edits
// Post filters: Autoconfirmed Users, Users with usernames shorter than 50 characters (probably gww vandals)
apiWrapper({
  baseurl: 'https://wiki.guildwars2.com/api.php?format=json&action=query&list=allusers&aulimit=500' + '&auwitheditsonly=true' + '&auprop=implicitgroups|editcount|registration',
  output: 'allusers',
  continue: 'aufrom',
  tempresultsarray: [],
  resultsarray: []
}, makeTableHTML);

Wiki API - WhatLinksHere misc inputs using DPL (via template)[edit]

/* GW2W API query tool for SMW results for miscellaneous page inputs */
function apiQuery () {
    mw.loader.using('mediawiki.api.parse', function () {
        var pages = ["Precise Strike","Tail Wind","Loud Whistle"];

        var api = new mw.Api();

        // Break the list of pages down into a url almost 2000 characters long.
        var lines = [[]], maxlength = 1800, j = 0, running_count = 0, running_total = 0;
        for (var i=0; i<pages.length; i++) {
            if ((running_total + pages[i].length) >= maxlength || running_count > 100) {
                j += 1;
                lines.push([]);
                running_count = 0;
                running_total = 0;
            }
            running_count += 1;
            running_total += 3 + pages[i].length;
            lines[j].push(pages[i]);
        }
        // Submit each request, result is returned as a table.
        var promises = [];
        for (var k=0; k<lines.length; k++) {
            var current_pages = lines[k].join('\n');
            var parsetext = '{{User:Chieftain Alex/Templates/WhatLinksHere query|1='+current_pages+'}}';
            promises.push(api.parse(parsetext));
        }

        // Wait until all the GET requests have finished
        $.when.apply($,promises).done(function() {
            // Concatenate the api results
            var table = $.map(arguments, function(v) { return v; }).join('\n');

            // Write to document
            $('#apidata').html(table);

            // Now copy the output to excel, then remove duplicates including table headings.
            console.log('Batch query complete.');
        });
    });
}
apiQuery();

Wiki API - WhatLinksfrom via DPL[edit]

/* GW2W API query tool for DPL linksfrom results for miscellaneous page inputs */
function nextQuery(stringstackarray) {
    // Get the next chunk
    var current_pages = stringstackarray.shift();
    
    // Wrap in the wikitext, and join the chunk's array elements with a semi-colon.
    var direction = 'linksfrom'; // 'linksto' = same as Special:WhatLinksHere. 'linksfrom' = a DPL special.
    var uses = ''; // including "Template:" prefix
    var parsetext = '{{User:Chieftain Alex/Templates/DPL query links|direction='+direction+'|pages='+current_pages.join(';')+'|uses='+uses+'}}';
    
    // Make the request
    var api = new mw.Api();
    api.parse(parsetext)
    .done(function (result) {
        // Write to document
        $('#apidata').append(result);
    })
    .fail( function(code, result) {
        console.log('Batch query failed.');
        console.log(parsetext);
        if ( code === "http" ) {
            console.log( "HTTP error: " + result.textStatus );
        } else if ( code === "ok-but-empty" ) {
            console.log( "Got an empty response from the server" );
        } else {
            console.log( "API error: " + code );
        }
    })
    .always( function (){
        // Check if any chunks left
        if (stringstackarray.length > 0) {
            nextQuery(stringstackarray);
        } else {
            // Done
            $('#apidata').append('<p>Batch query complete</p>');
            console.log('Batch query complete.');
        }
    });
}

function apiQuery () {
    mw.loader.using('mediawiki.api.parse', function () {
        var pages = ["Aspect Arena","Basket Brawl","Bell Choir Ensemble"];

        // Break the list of pages down into a url almost 2000 characters long.
        // but actually limit it to bunches of 25 pages (depending on the popularity/density, each page could have upwards of 250+ links from each page)
        var lines = [[]], maxlength = 1800, j = 0, running_count = 0, running_total = 0;
        for (var i=0; i<pages.length; i++) {
            if ((running_total + pages[i].length) >= maxlength || running_count >= 25) {
                j += 1;
                lines.push([]);
                running_count = 0;
                running_total = 0;
            }
            running_count += 1;
            running_total += 3 + pages[i].length;
            lines[j].push(pages[i]);
        }
        
        // For each line, parse the text and append the results into the page.
        $('#apidata').html('');
        nextQuery(lines);
    });
}
apiQuery();

Wiki - Whatlinkshere arraymap[edit]

{| class="wikitable"
{{#arraymap:

Acolyte Boots (PvP)
Acolyte Coat (PvP)

|\n|@@@|
{{#vardefine:title|@@@}}{{#arraymap:{{#dpl: | linksto = @@@ | mode = userformat | format = ,,%PAGE%;, }}|;|$$$|
{{!}}-
{{!}} {{#var:title}} {{!!}} $$$|\n}}
|\n}}
|}

Wiki - Tools[edit]

Wiki - enumerate achievement page[edit]

var a = $.map( $('.widget-account-achievement.line'), function(v){
  return $(v).find('th:first-child').text().trim();
});
console.log(JSON.stringify(a,null,2));

Wiki - ChatLinkSearch tabler (for Special:Search)[edit]

/* GW2W tool to turn the verbose output of the chatlinksearch script into something you can copy into excel */
var listitems = $('.gw2w-chat-link-search ul li');
var tabletext = '<table><tr><th>id</th></tr>';
$.each(listitems, function(k,v){
  tabletext += '<tr>' + '<td>' + v.attributes['data-gameid']['nodeValue'] + '</td>' + '</tr>';
});
tabletext += '</table>';
$('.gw2w-chat-link-search').html(tabletext);

Wiki - Diff changes only[edit]

var rows = [];
rows.push( $('tr.diff-title').outerHTML );
$.map( $('td.diff-marker:first-child') , function(v,i){
    if (i < 5) { console.log(v); console.log(v.hasAttribute('data-marker')); }
    if ( v.hasAttribute('data-marker') ) {
        rows.push( v.parentElement.outerHTML );
    }
});
$('table.diff tbody').html( rows.join('') );

Wiki - Drop rate research[edit]

// Input
var item_ids = [698,758,761,1032,1297,1309,1594,1594,1605,1625,1834,1842,1849,1849,2088,2088,2096,2110,2115,2355,2360,2360,2363,23175,23194,24995,25435,25715,25930,25941,25944,25947,25949,25949,26125,26127,26128,26496,26521,26521,26818,26826,26826,26874,27131,27153,27160,27160,27588,27610,27610,27610,27610,27610,27622,27919,27937,28224,28243,28245,28245,28249,28251,28405,28414,28546,28780,28793,28796,28797,32958,32966,32998,34137,34809,34825,34825,34845,34853,34861,34881,45084,45090,45092,45092,47218,47442,47442,47442,47474,47482,47490,47502,47753,47753,47753,47769,47813,47825,47825];
var opener = '{{en}} Adeira Beta';
var signature = '[[User:Adeira Tasharo]]';


// --------------------------------------------------------
var inputs = {
    item_ids: item_ids,
    opener: opener,
    signature: signature
}

// Helper function to remove duplicates. Usage: a.unique()
Array.prototype.unique = function() {
    return this.filter(function (el, i, self) {
        return self.indexOf(el) === i;
    });
};

// Helper function to find elements in A which are not in B. Usage: a.diff(b)
Array.prototype.diff = function(a) {
    return this.filter(function(el) {
        return a.indexOf(el) < 0;
    });
};

function makeTableHTML (inputs, reference_data, ref) {
    console.log(inputs, reference_data);
    var column_titles = ['Rarity','Supertype','Type','Level','ID','Name','Suffix','Prefix','Opened on','Signature'];
    
    // Construct array with values to print to page
    var rows = [];
    $.map(inputs.item_ids, function(item_id){
        var row = [];
        
        if (item_id in reference_data.items) {
            // Rarity
            row.push(reference_data.items[item_id].rarity);
            // Supertype
            row.push(reference_data.items[item_id].type);
            // Type
            var t = reference_data.items[item_id].details.type || '';
            row.push(t);
            // Level
            row.push(reference_data.items[item_id].level);
            // ID
            row.push(item_id);
            // Name
            row.push(reference_data.items[item_id].name);
            // Suffix
            var s_id = reference_data.items[item_id].details.suffix_item_id || 0;
            if (s_id == 0) {
                row.push('None');
            } else if (s_id in reference_data.items) {
                row.push(reference_data.items[s_id].name);
            } else {
                row.push('not in the api');
            }
            // Prefix
            var p_id = reference_data.items[item_id].details.infix_upgrade.id || 0;
            if (p_id == 0) {
                row.push('None');
            } else if (p_id in reference_data.itemstats) {
                row.push(reference_data.itemstats[p_id].name);
            } else {
                row.push('not in the api');
            }
        } else {
            // Rarity
            row.push('not in the api');
            // Supertype
            row.push('not in the api');
            // Type
            row.push('not in the api');
            // Level
            row.push('not in the api');
            // ID
            row.push(item_id);
            // Name
            row.push('not in the api');
            // Suffix
            row.push('not in the api');
            // Prefix
            row.push('not in the api');
        }
        // Opened on character
        row.push(inputs.opener);
        
        // Signature
        row.push(inputs.signature);
        
        rows.push(row);
    });
    
    // Sort array logically: supertype, type, rarity, id
    rows = rows.sort(function(a,b){
        var rarity_num = ['Basic','Fine','Masterwork','Rare','Exotic','Ascended','Legendary'];
        return a[1].localeCompare(b[1]) || a[2].localeCompare(b[2]) || rarity_num.indexOf(a[0]) > rarity_num.indexOf(b[0]) || a[4] - b[4];
    });
    
    // Print to page as html table
    var h = '<table class="table mech1"><tbody>';
    h += '<tr>' + $.map(column_titles, function(x) { return '<th>' + x + '</th>' }).join('') + '</tr>\n';
    h += $.map(rows, function(r) {
        return '<tr>' + $.map(r, function(x) { return '<td>' + x + '</td>' }).join('') + '</tr>';
    }).join('\n') + '\n';
    h += '</tbody></table>';
    
    // Print to page as wikicode
    var w = '{| {{STDT|mech1}}';
    w += '\n! ' + $.map(column_titles, function(x) { return x }).join(' !! ');
    w += '\n' + $.map(rows, function(r) {
        return '|-\n| ' + $.map(r, function(x) { return x }).join(' || ');
    }).join('\n') + '\n';
    w += '|}';
    
    $(ref).html(h);
    $(ref).after('<pre' + '>' + w + '</' + 'pre>');
}

// Main function
function dropResearch (inputs) {
    var item_ids = inputs.item_ids.unique();
    
    var promises = [], maxsize = 200, ids, typearray = [];

    // Items
    ids = item_ids;
    for (var i=0; i<ids.length; i+=maxsize) {
        var current_ids = ids.slice(i,i+maxsize).join(',');
        var promise = $.getJSON('https://api.guildwars2.com/v2/items?ids='+current_ids+'&lang=en');
        promises.push(promise);
        typearray.push('items');
    }
        
    // Itemstats (just get all of them)
        var promise = $.getJSON('https://api.guildwars2.com/v2/itemstats?ids=all'+'&lang=en');
        promises.push(promise);
        typearray.push('itemstats');

    $.when.apply($,promises)
    .done(function() {
        // Collate data by type and id
        var reference_data = { 'items': {}, 'itemstats': {} };

        // Ensure data is an object
        var response = arguments;
        $.each(response, function(i,e){
            $.each(e[0], function(k,v){
                reference_data[typearray[i]][v.id] = v;
            });
        });

        // Obtain upgrade item ids
        var item_ids2 = $.map(reference_data.items, function(v){
            if ('details' in v && 'suffix_item_id' in v.details) {
                return v.details.suffix_item_id;
            }
        });
        item_ids2 = item_ids2.diff(item_ids);

        // Further API queries
        // Request upgrade item ids
        var promises2 = [], typearray2 = [];
        ids = item_ids2;
        for (var i=0; i<ids.length; i+=maxsize) {
            var current_ids = ids.slice(i,i+maxsize).join(',');
            var promise = $.getJSON('https://api.guildwars2.com/v2/items?ids='+current_ids+'&lang=en');
            promises2.push(promise);
            typearray2.push('items');
        }

        $.when.apply($,promises2)
        .done(function() {
            // Ensure data is an object
            var response2 = [];
            if ( promises2.length > 1 ) {
                response2 = arguments;
            } else {
                response2[0] = arguments;
            }

            $.each(response2, function(i,e){
                $.each(e[0], function(k,v){
                    reference_data[typearray2[i]][v.id] = v;
                });
            });
            
            // Send to printer
            makeTableHTML(inputs, reference_data, '#apidata');
        });
    });
}
dropResearch(inputs);

Wiki - Redirect and new page markup in a list[edit]

$.map( $('.mw-redirect'), function(v){
    $(v).text( $(v).text() + '¦REDIRECT' );
});
$.map( $('.new'), function(v){
    $(v).text( $(v).text() + '¦NEW' );
});

Wiki - Special:Version[edit]

// Script to run whilst on [[Special:Version]]
function jsonVersion() {
    // Remove table colspan headings
    $('#mw-content-text [colspan]').remove();
    
    // In each table, remove license (col 3), description (col 4) and authors (col 5)
    $('table td:nth-child(5), table th:nth-child(5), table td:nth-child(4), table th:nth-child(4), table td:nth-child(3), table th:nth-child(3)').remove();
    
    // Add final heading
    $('#mw-content-text').append('<h2 id="endofpage">End of page</h2>');
    
    // Remove invisible stuff
    $('#mw-content-text > div, #mw-content-text > span').remove();
    
    // Put all the dumb text nodes into a div
    var e1 = getTextInbetween($('#mw-version-parser-extensiontags')[0], $('#mw-version-parser-function-hooks')[0]);
    $('#mw-version-parser-extensiontags').after('<div id="insert1" class="retain" data-title="Extension tags"></div>');
    $('#insert1').text(e1);
  
    var e2 = getTextInbetween($('#mw-version-parser-function-hooks')[0], $('#endofpage')[0]);
    $('#mw-version-parser-function-hooks').after('<div id="insert2" class="retain" data-title="Parser function hooks">' + e2 + '</div>');
    $('#insert2').text(e2);
    
    // Replace all of the .retain content with tables
    var r = $('.retain');
    $.each(r, function(i,v) {
        var title = $(v).attr('data-title');
        var tx = $(v).text();
        var tx_array = tx.replace(' and ',', ').split(',');
        tx_array = $.map(tx_array, function(x) { return x.trim().replace('<','').replace('>','') });
        
        var tb = $('<table class="wikitable"><tbody><tr><th>' + title + '</th></tr>'+
          $.map(tx_array, function(x) { return '<tr><td>' + x + '</td></tr>' }).join('')
        +'</tbody></table>');
        
        $(v).replaceWith(tb);
    });
    
    // Remove h2
    $('h2').remove();
    
    // Get remaining tables and JSON them.
    var version = {};
    var tables = $('#mw-content-text table');
    $.each(tables, function(i,table) {
        var table_title = $(table).find('th')[0].textContent;
        var table_data_array = $('tr', table).get().map(function(row) {
            return $(row).find('td').get().map(function(cell) {
                return $(cell).text();
            });
        });
      
        var table_data_obj = {};
        $.map(table_data_array, function(x){
            if (typeof x !== 'undefined' && x.length != 0) {
                table_data_obj[x[0]] = x[1] || true;
            }
        });
      
        version[table_title] = table_data_obj;
      
    });
    $('#mw-content-text').html('<pre' + '></' + 'pre>');
    $('#mw-content-text pre').text(JSON.stringify(version, null, 2));
}

function getTextInbetween(startNode, stopNode) {
    if (startNode.parentElement != stopNode.parentElement) return;

    var elements = startNode.parentElement.childNodes;
    var startPos = [].indexOf.call(elements, startNode);
  
    // Get all the text from start to stop
    var text = [];
    var i_arr = [];
    for (var i = startPos; i < elements.length; ++i) {
        if (elements[i].nodeType == 3 || elements[i].nodeType == 1) {
            text.push(elements[i].textContent);
            i_arr.push(i);
        }
        if (elements[i] == stopNode) {
            break;
        }
    }
  
    // Remove first and last (don't need contents of the h2)
    text.pop();
    text.shift();
  
    // Go back and remove all the garbage
    i_arr.pop();
    i_arr.shift();
    i_arr = i_arr.reverse();
    for (var i = 0; i < i_arr.length; i++) {
      elements[i_arr[i]].remove();
    }
  
    // remove lines and spaces as HTML does
    text = text.join('').trim();
    text = text.replace(/\s+/g, " ");

    return text;
}
jsonVersion();

Wiki - Whatlinkshere alphabetical[edit]

// https://stackoverflow.com/questions/1134976
var list = $('#mw-whatlinkshere-list');
var listitems = list.children('li').get();
listitems.sort(function(a, b) {
   return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
})
$.each(listitems, function(idx, itm) { list.append(itm); });

Wiki - Whitespace hunting[edit]

Option 1 - NBSP only[edit]

var a = $('#wpTextbox1').val();
var position = a.indexOf(String.fromCharCode(160));
if ( position !== -1 ) {
    console.log('Position of non-breaking space character: ', position);
    console.log( a.substr(0,position), '<<<nbsp>>>' );
} else {
    console.log('Did not find non-breaking space')
}

Option 2 - Tabulate data[edit]

Array.prototype.unique = function() {
    return this.filter(function (el, i, self) {
        return self.indexOf(el) === i;
    });
};

/* Acquire data */
var nodename = 'wpTextbox1'
var textareanode = $('#' + nodename);
var str = textareanode.val();

/* Note: Selection/highlight only appears when its the active window, so remember to alt+tab after running this script! */
const highlightnode = document.getElementById(nodename);
highlightnode.focus();

/* Highlight the adjacent characters (note, this moves the selection so if there's more than one baddie, it'll highlight only the last one */
var j;
var results = [];
for (var i = 0; i < str.length; i++) {
  j = str.charCodeAt(i);
  results.push(j);
  if (j > 255) {
      highlightnode.setSelectionRange(i-1, i + 2);
  }
}
results_unique = results.unique().sort();

/* Construct a frequency table */
var freq_table = {};
$.map(results_unique, function(v){ freq_table[v] = 0; });
$.map(results, function(v) { freq_table[v] += 1; });
var c = $.map(freq_table, function(v, k){
    return String.fromCharCode(k) + ' ==> code ' + k + ' (' + v + ' occurrences)';
});
console.log(JSON.stringify(c,null,2));

Option 3 - Just remove it[edit]

Array.prototype.unique = function() {
    return this.filter(function (el, i, self) {
        return self.indexOf(el) === i;
    });
};

var whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/*-+=,.?<>;#:@~[]{}`¦¬!\"£$%^&*()_,²«»¶¦|—";
var str = $('#wpTextbox1').val();
var N, L, textoutput = '', removed = [];
for (var i = 0; i < str.length; i++) {
  L = str.charAt(i);
  N = str.charCodeAt(i);
   
    /* 160 is nbsp */
    if (N > 159) {
        /* beyond 160 (nbsp) we're going to check if its in our whitelist above */
        if (whitelist.includes(L)) {
            textoutput = textoutput + L;
        } else {
            removed.push(N);
        }
    } else {
        textoutput = textoutput + L;
    }
}
$('#wpTextbox1').val(textoutput);

if (removed.length > 0) {
    var results_unique = removed.unique().sort();
    var freq_table = {};
    $.map(results_unique, function(v){ freq_table[v] = 0; });
    $.map(removed, function(v) { freq_table[v] += 1; });
    var c = $.map(freq_table, function(v, k){
        return k + ' ==> "' + String.fromCharCode(k) + '" ' + '(x' + v + ')';
    });
    $('#wpSummary').val( $('#wpSummary').val() + ' Removed special character codes: ' + c.join(', '));
}

Reddit - API - Weekly questions thread statistics[edit]

/* Reddit API query tool for post count */
// Setup
var baseurl = 'https://www.reddit.com/r/Guildwars2/search.json?q=question+thread+author%3AAutoModerator+OR+author%3AIntigo&sort=new&restrict_sr=on&t=all';
var datadrop = [];

// Function to concatenate all data
function processdata (datadrop) {
    console.log('datadrop',datadrop);
    var dump = [];
    $.each(datadrop, function(kk,vv){
        $.each(vv, function(k,v){
            if (  (v.data.title.indexOf('Weekly') > -1 ) && (v.data.title.indexOf('Question') > -1)  ) {
                var date = new Date(v.data.created_utc*1000);
                dump.push({ title: v.data.title, count: v.data.num_comments, date: date });
            }
        });
    });
    console.log('dump',dump);
    $('#apidata').html(makeTableHTML(dump));
}

// Function to convert an object variable into a table
function makeTableHTML ( data ) {
        var result = '<table class="table mech1"><tbody>'
                    +'<tr><th>Date</th><th>Title</th><th>Comment count</th></tr>';
        $.each(data, function(k, v) {
            result += '<tr>'
                       +'<td>'+ pad(v['date'].getUTCDate()) + '/' + pad(v['date'].getUTCMonth()+1) + '/' + v['date'].getUTCFullYear() + '</td>'
                       +'<td>'+v['title']+'</td>'
                       +'<td>'+v['count']+'</td>'
                     +'</tr>';
        });
        result += "</tbody></table>";
        return result;
}

// Function to pad numbers into character strings with leading zeroes
function pad (s) {
    return (s < 10 ? '0' : '') + s;
}

// Fetch all the threads
function apiQuery (qc, token) {
    qc = qc + 1;
    var url = baseurl;
    if (token) {
     url += '&after=' + token
    }
    $.getJSON(url).done(function(data){
        datadrop.push(data['data']['children']);

        if (qc > 8) {
                console.log('Query max count reached.');
                processdata(datadrop);
        } else {
            if ('after' in data['data'] && data['data']['after'] !== null) {
                apiQuery(qc, data['data']['after']);
            } else {
                console.log('Query complete.');
                processdata(datadrop);
            }
        }
    });
}

console.log('User pressed run. Starting queries.');
apiQuery(0);

Miscellaneous - Build CSS from table[edit]

Guild Wars 2 Wiki:Projects/CSS documentation/table
var mode = 'common'; // 'common', 'monobook', 'mobile', 'minerva', 'vector'

// Lookup object
var delete_columns = {
  'common':      [  3,4,5,6],
  'monobook':    [2,  4,5,6],
  'mobile':      [2,3,  5,6],
  'minerva':     [2,3,4,  6],
  'vector':      [2,3,4,5  ],
}

// Remove irrelevant columns
$('small').remove();
$('#csstable tr:nth-child(1)').remove();
$.each(delete_columns[mode].reverse(), function(i,v) {
  $('#csstable tr td:nth-child(' + v + '), #csstable tr th:nth-child(' + v + ')').remove();
});

// Remove excessive newlines and empty headings
var t = $('#csstable').text()
  .replace(/\n(\n\n+)/g,'\n\n')
  .replace(/(-------- \*\*\/)(\n+)/g,'$1\n')
  .replace(/(\/\*\* -------- )(.*?)( -------- \*\*\/)\n(\/\*\* -------- )/g,'$4')
  .replace(/(\/\*\* -------- )(.*?)( -------- \*\*\/)\n(\/\*\* -------- )/g,'$4')
  .replace(/^( {4})/gm,'  ')
  .trim();

// Replace content
$('#cssoutput').text(t);

Miscellaneous - Chatlinks to IDs[edit]

/** window.atob & window.btoa polyfill
 * WTFPLv2 – https://github.com/davidchambers/Base64.js
 */
!function(){function t(t){this.message=t}var e=this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=new Error,t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-a%1*8)){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),e.length%4==1)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(-2*a&6)):0)n=r.indexOf(n);return c})}();

// Decode chatlinks into type and ids
function decodeChatLink(code) {
    var binary = window.atob(code);
    var octets = new Array(binary.length);
    for (var i = 0; i < binary.length; i++) {
        octets[i] = binary.charCodeAt(i);
    }
    var type;
    var id = octets[2] << 8 | octets[1];
    if (octets[0] == 2) {
        type = 'item';
        id = octets[3] << 8 | octets[2];
        id = (octets.length > 4 ? octets[4] << 16 : 0) | id;
    }
    else if (octets[0] == 4 ) { type = 'location'; }
    else if (octets[0] == 6 ) { type = 'skill';    }
    else if (octets[0] == 7 ) { type = 'trait';    }
    else if (octets[0] == 9 ) { type = 'recipe';   }
    else if (octets[0] == 10) { type = 'skin';     }
    else if (octets[0] == 11) { type = 'outfit';   }
    else                      { type = 'unknown'   }
    var outputobject = {
        code: code,
        octets: octets,
        binary: binary,
        type: type,
        id: id
    };
    return outputobject;
}

//
(function chatlinksToIDs () {
    var rawtext = $('#inputrawtext');
    rawtext = rawtext.html().replace("&","&");

    // Regular expression matching
    var expr = /\[&([A-Za-z0-9+/]+=*)\]/g;
    var match, onlychatlinks = [], internalchatlinks = [], internalIDs = [], outputIDs = [];
    while ((match = expr.exec(rawtext))) {
        onlychatlinks.push(match[0]);
        internalchatlinks.push(match[1]);
    }

    // Take each matched expression, and decode it
    $.each(internalchatlinks, function(i,v){
        internalIDs.push(decodeChatLink(v));
    });

    // Only interested in the ids here
    $.each(internalIDs, function(i,v){
        outputIDs.push(v.id);
    });

    // Print results
    $('#outputchatlinks').html(JSON.stringify(onlychatlinks));
    $('#outputids').html(outputIDs.length + ' ids found.<br>' + JSON.stringify(outputIDs));
})();

Miscellaneous - Compare Silver Mirror with Gemstore[edit]

<div id="apidata1">[[File:Mediawiki loading animation.gif]] 1</div>
<div id="apidata2">[[File:Mediawiki loading animation.gif]] 2</div>
/* GW2 API query tool for comparing Silver's Mirror (static address) with the ArenaNet page (moves around) */
var url1 = 'https://api.datawars2.ie/gw2/v1/gemstore/catalogue/json';
var url2 = 'https://2gemstore.staticwars.com/const/gw2/build116703/GemStore/en/catalog.a856377d.js'; // amend when comparing - take the value within the source of https://gemstore-live.ncplatform.net/?buildid=999999&language=en&gamecode=gw2

$.loadScript = function (url, callback, callbackerror) {
    $.ajax({
        url: url,
        dataType: 'script',
        success: callback,
        error: callbackerror,
        async: true
    });
};

function makeTableHTML(dataUnsorted,prefix) {
    var data = $.map(dataUnsorted, function(v,k){ v.uuid = k; return v; });
    data = data.sort(function(a,b) { return a.uuid > b.uuid; });
  
    var result = '<h2>' + prefix + '</h2>';
    result += '<table class="table mech1" style="margin-bottom:0px;"><tr><th>Gemstore GUID</th><th>Name</th><th>Item id</th></tr>';
    $.each(data, function(k, v) {
        result += '<tr><td>'+v.uuid+'</td><td>'+v.name+'</td><td>'+v.dataId+'</td></tr>';
    });
    result += '</table>';
    return result;
}

// Fetch all the possible achievement IDs
(function fetchAPIData() {
    $.getJSON(url1).done(function (data) {
        var data2 = {}, uuid;
        $.each(data, function(k,v) {
            // Copy
            uuid = data[k].uuid;

            // Remove things that will be different
            delete data[k].categoriesOld;
            delete data[k].categoryLifespans;
            delete data[k].categoryLifespansOld;
            delete data[k].firstAdded;
            delete data[k].gemPrice;
            delete data[k].latestEndDate;
            delete data[k].latestStartDate;
            delete data[k].uuid;

            // Paste into new object
            data2[uuid] = data[k];
        });
        $('#apidata1').html(makeTableHTML(data2,"Silver's Mirror"));
    });
    $.loadScript(url2, function () {
        $('#apidata2').html(makeTableHTML(gemstoreCatalog,"ArenaNet's Hidden Catalogue"));
    }, function(jqxhr, textStatus, error) {
        console.log("Request to the gemstore failed.", jqxhr, textStatus, error);
    });
})();

Miscellaneous - Decimal, Hex and Charcode table[edit]

var a = [];
for (var i = 0; i < 256; i++){
  a.push('<tr><th>'+i+'</th><td>'+i.toString(16)+'</td><td>'+String.fromCharCode(i)+'</td></tr>');
}
$('#apidata').html('<table class="wikitable"><tr><th>decimal value</th><th>hex value</th><th>fromCharCode character equivalent</th></tr>'+a.join('\n')+'</table>');

Miscellaneous - Remove newlines from tables[edit]

// Remove <br> tags
$('table br').remove();

// Remove p tags (and possibly newlines?) by converting html to raw text
$('table td, table th').each(function(){
  $(this).html( $(this).text() );
});

Miscellaneous - Remove dead files from galleries[edit]

// Use this whilst using "show preview" on [[User:Darqam/Dat_Icons]]

// Find all gallery elements
var gallery_elements = $('.gallerybox .thumb');

// Gather elements with no child elements (i.e. text only with no images)
var empty_gallery_elements = $.map(gallery_elements, function(v){
  if (v.childElementCount == 0) {
    return v;
  }
});

// Collate the moved file names
var moved_file_names = $.map(empty_gallery_elements, function(v){
  return v.childNodes[0].textContent;
});

// Get the editing box text content
var editing_box_text_lines = $('#wpTextbox1').text().split('\n');

// Scan through editing box lines for moved files
var editing_box_text_lines_new = $.map(editing_box_text_lines, function(v){
  // Compare left-hand side of any pipe elements with the whole array of moved file names
  var lhs = v.split('|')[0].trim().replace('File:','');
  if (moved_file_names.indexOf( lhs ) == -1 ) {
    return v;
  }
});

// Update text-box content without moved files
$('#wpTextbox1').text( editing_box_text_lines_new.join('\n') );
$("#wpTextbox1").fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100);

console.log('Files removed from textbox: ', moved_file_names.length );

Miscellaneous - Template wikicode to html table[edit]

// For use when the edit box of a page calling a template is being viewed
function wikiTemplateToTable(){
    var config = {
        inputselector: '#wpTextbox1',
        templatename: 'Gem store entry',
        fieldnames: ['item', 'availability', 'cost', 'discounted', 'qty', 'section', 'subsection']
    };
    var template_array_object = wikitextToObject($(config.inputselector).val(), config);
    $('#mw-content-text').before( makeTableHTML(template_array_object, config.fieldnames) );
}

function wikitextToObject(wikitext, config){
    // Remove excess whitespace
    wikitext = wikitext.trim().replace(/\n\n/g,'\n');

    // Remove first line ("{{templatename") and remove last line ("}}")
    var wikitextlines = wikitext.split('\n');
    wikitextlines.shift();
    wikitextlines.pop();
    wikitext = '\n' + wikitextlines.join('\n');
    
    // Split by template name
    var templatewikitextlines = wikitext.split('\n}}\n{{' + config.templatename + '');
    
    var temp_by_line, temp_obj, param;
    var outputarr = $.map(templatewikitextlines, function(v,i){
        // Split by newline and template parameter delimiter
        temp_by_line = v.split('\n| ');
        
        // Remove first empty element
        temp_by_line.shift();

        // Loop through each template parameter, check if whitelisted, then add to array
        temp_obj = {};
        $.map(temp_by_line, function(vv){
            param = vv.split(' = ');
            if (config.fieldnames.indexOf(param[0]) != -1) {
                temp_obj[param[0]] = param[1];
            }
        });
        return temp_obj;
    });
    return outputarr;
}


// Function to convert an array object variable into a table
function makeTableHTML(data, fieldnames) {
    // Remove any previous tables
    $('#temptable').remove();
    
    // Generate new one
    var result = '<table id="temptable" class="wikitable"><tbody>';
    if (data.length > 0) {
        var columns = fieldnames; // Object.keys(data[0]);
        result += '<tr>' + $.map(columns, function(c) { return '<th>' + c + '</th>'; }).join('') + '</tr>';
        result += $.map(data, function(v) {
            return '<tr>' + $.map(columns, function(c) {
                return '<td>' + v[c] + '</td>';
            }).join('') + '</tr>';
        }).join('\n');
    }
    result += '</tbody></table>';
    return result;
}

wikiTemplateToTable();

Miscellaneous - Unique keys in object[edit]

// Find all possible keys for an object of depth 1
var obj = {};

var uniquekeys = [];
$.each(obj, function(i, v){
  $.each(Object.keys(v), function(ii, vv){
    if (uniquekeys.indexOf(vv) == -1) {
      uniquekeys.push(vv);
    }
  });
});
console.log(JSON.stringify(uniquekeys));

Miscellaneous - World link history (via werdes.net)[edit]

var continentFilter = 'EU';
var worldFilter = 'Fort Ranik';
var uniqueLinkFilter = false;

function makeTableHTML(data) {
    // First pass
    var output_arr_full = [];
    $.each(data, function(k, v) {
        // Collate team names
        var teams = [];
        $.map(["red", "green", "blue"], function(c){
            var this_team = [];
            this_team.push(v.worlds[c].name);
            $.map(v.worlds[c].additional_worlds, function(ac){
                this_team.push(ac.name);
            });
            teams.push( this_team.join(', ') );
        });

        var continent = (v.arenanet_id[0] == '1' ? 'NA' : 'EU');

        var filter_match_continent = true;
        if (continentFilter && continentFilter.length > 0) {
            filter_match_continent = false;
            if (continent === continentFilter) {
                filter_match_continent = true;
            }
        }

        var teams_smushed = teams.join(', ');
        var filter_match_world = true;
        if (worldFilter && worldFilter.length > 0) {
            filter_match_world = false;
            if (teams_smushed.indexOf(worldFilter) !== -1) {
                filter_match_world = true;
            }
        }
        
        var filter_match_only = '';
        if (uniqueLinkFilter) {
            $.map(teams, function(t){
                if (t.indexOf(worldFilter) !== -1) {
                    filter_match_only = t;
                }
            });
        }

        // Array of objects output
        output_arr_full.push({
            flag: filter_match_world && filter_match_continent,
            start_date: v.start.replace('T18:00:00',''),
            continent: continent,
            match_tier: v.arenanet_id[2],
            red: teams[0],
            green: teams[1],
            blue: teams[2],
            server_choice: (uniqueLinkFilter ? filter_match_only : '' )
        });
    });

    Array.prototype.wvwfilter = function(continent) {
        return this.filter(function (el, i, self) {
            return (el.continent == continent) && (el.flag);
        });
    };

    // Second pass
    var output_arr_filtered = output_arr_full.wvwfilter(continentFilter).sort(function(a,b){
        return Date.parse(b.start_date) < Date.parse(a.start_date);
    });

    // Check all results didn't get removed
    if (output_arr_filtered.length == 0) {
        return;
    }
    
    var columns;
    var output_arr_final = [];
    if (uniqueLinkFilter) {
        var prev_world_choice = '';
        $.map(output_arr_filtered, function(a) {
            if (a.server_choice !== prev_world_choice) {
                output_arr_final.push(a);
            }
            prev_world_choice = a.server_choice;
        });
        columns = ["start_date", "server_choice"];
    } else {
        output_arr_final = output_arr_filtered;
        columns = Object.keys(output_arr_final[0]);
    }

    // Convert to output result
    if (output_arr_final.length == 0) {
        return;
    }
    
    // Headers
    var result = '<table class="table mech1">';
    $.each(columns, function(i,v) { result += '<th class="header-' + v + '">' + v + '</th>' });
    result += '</tr>';
    
    // Rows
    $.each(output_arr_final, function(i,v) {
        result += '<tr>';
        $.each(columns, function(ii,vv){
            if (typeof v[vv] == 'object') {
                result += '<td>' + JSON.stringify(v[vv]) + '</td>';
            } else {
                if (vv == 'red' || vv == 'green' || vv == 'blue') {
                    result += '<td class="cell-worlds cell-' + v[vv].replace(/ /g,'').replace(/,/g,' cell-') + '">' + v[vv] + '</td>';
                } else {
                    result += '<td class="cell-other">' + v[vv] + '</td>';
                }
            }
        });
        result += '</tr>';
    });
    result += '</table>';
    return result;
}

// Main function
$.getJSON('https://api.kills.werdes.net/api/matchlist/all?ts=1700848232594', function(matches) {
    $('#apidata').html(makeTableHTML(matches));
});

Miscellaneous - CSS for tables in gw2efficiency[edit]

table.c-table { width: auto; }
.eff-margin-top-s { margin: 0; }

table.account-overview tr td,
table.account-overview tr th { border: 1px solid black; }

.eff-font-size-xs div { display: none; }
.eff-font-size-xs :nth-child(4),
.eff-font-size-xs :nth-child(6),
.eff-font-size-xs :nth-child(7) { display: block; }

table.account-overview tr > :nth-child(2),
table.account-overview tr > :nth-child(3),
table.account-overview tr > :nth-child(5) { display:none; }

table.account-overview tr td:nth-child(1) div:nth-child(2) { display:none; }