User script: Difference between revisions

From GreaseSpot Wiki
Jump to navigationJump to search
No edit summary
No edit summary
(40 intermediate revisions by 21 users not shown)
Line 1: Line 1:
// ==UserScript==
User scripts are programs which make on-the-fly changes to specific web pages, typically to change their appearance or to add or modify functionality.
// @name          Travian Building Mover
// @namespace      Travian Building Mover
// @description    This repositions the buildings on the dorf2.php page
// @version        1.5.1
// @include        http://*.travian.*/dorf2.php*
// @license        GPL 3 or any later version
// ==/UserScript==


/*****************************************************************************
User scripts for [[Greasemonkey]] and Greasemonkey-compatible alternatives are written in [http://developer.mozilla.org/en/docs/JavaScript JavaScript].
* Copyright (C) 2009 Adriaan Tichler
If you would like to write user scripts yourself, see [[Greasemonkey Manual:Editing]].
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Public License for more details
*
* To obtain a copy of the GNU General Public License, please see
* <http://www.gnu.org.licenses/>
*****************************************************************************/


// First, get the user mappings...
== See Also ==
var mapping = eval(GM_getValue('mapping', '({})'));
* [[wikipedia:Augmented browsing|Augmented browsing at Wikipedia]]
 
function reset_vil(){
    if (!window.confirm("Reset this village's buildings to their original position?")) return;
    delete mapping[did];
    GM_setValue('mapping', uneval(mapping));
    location.reload();
}
 
// Register these first, in case the script fails later and we still want to reset things
GM_registerMenuCommand("BM: Reset this village's buildings", reset_vil);
GM_registerMenuCommand("BM: Reset all buildings", function(){
        if (!window.confirm("Reset all buildings in all villages to their original position?")) return;
        GM_setValue('mapping', '({})');
        location.reload();
    });
 
// Init
var server = location.host;
var uid = document.evaluate("id('side_navi')//a[contains(@href, 'spieler.php')]/@href", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent.match(/uid=(\d+)/)[1];
 
// Add support for the 'toggle building levels' button, so we can make it persistent
// Otherwise, this value keeps getting cleared whenever cookies get cleared, which for the more paranoid of us would be every time the browser restarts ;-)
var toggle = eval(GM_getValue('show_building_level', '({})'));
var button = document.getElementById('lswitch');
if (button != undefined){
    var current_toggle = button.className == "on";
    // If we don't have a saved setting for this server and user, then take the present value of the toggle
    if (toggle[server+'_'+uid] == undefined){
        toggle[server+'_'+uid] = current_toggle;
        GM_setValue('show_building_level', uneval(toggle));
    }
    // Otherwise, correct the value of the toggle to what we have saved
    // *note* calling vil_levels_toggle() in this fashion is safer than using unsafeWindow, because unsafeWindow would elevate the privilege of the function.
    else if (current_toggle != toggle[server+'_'+uid]) location.href = "javascript:void(vil_levels_toggle());";
 
    // Either way, add a listener to update our version of the toggle when it's clicked
    button.addEventListener('click', function(){
            toggle[server+'_'+uid] = !toggle[server+'_'+uid];
            GM_setValue('show_building_level', uneval(toggle));
        }, false);
}
 
// Look at where the original buildings are *first*
var data = [];
var poly = document.getElementById('map2').childNodes;
var img = document.getElementById('map2').nextSibling.nextSibling.childNodes;
 
// Raw_num won't have the right number of elements if there are unused building spots in the village
var num = [];
var raw_num = document.getElementById('village2_levels');
// Some servers use a different ID...
if (raw_num == undefined) raw_num = document.getElementById('levels');
if (raw_num != undefined){
    raw_num = raw_num.childNodes;
    for (var i in raw_num){
        if (raw_num[i].className == undefined || raw_num[i].className.indexOf('level') >= 0) continue; // Don't do walls, closing divs, or the rally point
        num[raw_num[i].className.split('d')[1] - 0] = raw_num[i]; // re-index these nodes so they don't get mistakenly translated by an empty spot
    }
}
 
// Store the current info about all of the buildings...
for (var i=1; i <= 20; i++){
    data[i] = [];
    //GM_log(i + ' ' + img[i].alt + ' | ' + poly[i].title);
 
    data[i]['className'] = img[i].className.split(' ')[2];
    if (num[i] != undefined) data[i]['num'] = num[i].className;
 
    data[i]['title'] = poly[i].title;
    data[i]['href'] = poly[i].href;
}
 
// Get the active village, to store the new mappings
// We don't have to worry about postfixes because we're only running on one page
var did = document.evaluate('//tr[@class="sel"]/td[@class="text"]/a', document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if (did) did = did.href.match('newdid=([0-9]*)')[1];
else {
    // If this fails, there's a possibility that we're just running the other type of travian (??? still 3.5, but with different code...)
    did = document.evaluate('//table[@id="vlist"]/tbody/tr/td[@class="dot hl"]', document, null, XPathResult.ANY_UNORDERED_NODE_TYPE,null).singleNodeValue;
    if (did) did = did.parentNode.innerHTML.match('newdid=([0-9]*)')[1];
}
// Single village support courtesy of Booboo
if (!did) {
    var single_villages = eval(GM_getValue('single_villages', '({})'));
    if (!single_villages[server + "_" + uid]){
GM_xmlhttpRequest({
                method: 'GET',
                url: "http://" + server + "/dorf3.php",
                onload: function(xhr){
                    var did = xhr.responseText.match(/newdid=(\d+)/)[1];
                    single_villages[server + "_" + uid] = did;
                    GM_setValue('single_villages', uneval(single_villages));
                    window.location.reload();
                }
            });
        return;
    }
    else did = single_villages[server + "_" + uid];
}
 
if (mapping[did] == undefined) mapping[did] = {};
 
// This moves a building from src to dest.
function move(dest, src){
    //GM_log('Moving '+src+' to '+dest);
    var base = img[dest].className.split(' '); // We only change the last part of the class name
    img[dest].className = base[0]+' '+base[1]+' '+data[src].className;
 
    if (num[src] != undefined) num[src].className = 'd'+dest; // Move the building numbers. This goes backwards from everything else...
 
    poly[dest].title = data[src].title;
    poly[dest].href = data[src].href;
}
 
// The index is the destination, the value the source
for (var i in mapping[did]) move(i, mapping[did][i]);
 
// Get input from the user... add the moving truck.
var div = document.createElement('div');
div.setAttribute('style', 'position:absolute; top:489px; left:163px; padding:2px; z-index:100; border:none; cursor:pointer');
div.innerHTML = '<img title="Swap Buildings" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QCURXhpZgAASUkqAAgAAAABAGmHBAABAAAAGgAAAAAAAAABAIaSBwBgAAAALAAAAAAAAABBU0NJSQAAAFdpbmRvd0V4dDogMzAzNSwgMjY3NA1XaW5kb3dPcmc6IDAsIDANQ29udGVudDogMTAsIDI2LCAzMDEyLCAyNjcyDUlnbm9yZWQgT3Bjb2RlczoNJDEwNQD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAcACEDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAcIBgED/8QAMRAAAgIBAwMCAwUJAAAAAAAAAQIDBAUGERIABxMhMQgVFxQiMmGUIzRRUlNWcZHS/8QAGAEBAAMBAAAAAAAAAAAAAAAABQAEBgH/xAAkEQABAwMDBAMAAAAAAAAAAAABAAIDBBExEiEiBRRRYUFSwf/aAAwDAQACEQMRAD8AoP4khmPoxqF8FlbmJvRRxSpbqTtDLEqTxtIVdSCPuBh+e/UNyYPW8unY83FqS/NesTeCpG1mQ2rTjcSEFSTupjb3A9Nt2I2DXN3uzWLl7Sa2px2uVk4G+EVY2P3xBJt7D+PUZZm/Rg7lYiOu9z5LirMzJY8TVuAmaWWX9oxU7gsoB5KNh6b9F175w5ojxuceFcpGsJ5Khuxd7WmE0hJmEzGd1VjPmVmGShkyzXEhifxcq7OeXNWjfeF2Kt6cSjDZ35iMlQzGMr5PHTpYqWI/JFIu+zL/AIPqD+R9R0kex+pdOVu2tQ2M5jqvK/kZeNi+hYK96wykuWPL0P4tzv779ZrSmu27e5HIaiuajqZTT2dyd94MYbpHgX7XMyzQMzuhaVWJEYESMCrEjg7HL9F6/UPrZ6asHFruBsd/WLbeVJ4m5Yqe4j+dv99HWJ+o+nP6l79M/wD10dbfu4fsqtnrHfEm+PuURpDGN5NT5pAVroRwirhwWsTggjx7rwCkHy7lOLDmVUGL7ZrrCtFofQjY6pisFMnzPMT0o53uWVIYxBSNnCkqWDNsAVADbb9eT53J2e8Wd00bLRS5vUjUrWXT9+WE2jCqo53RQkahVHDYe+2/r1V2h9M4XSWHjweCpitSqjxxruWYj8RLMfUks7Ek+5Y9IEiOK4y5BxskrKxz3u4RYHk/JP4oqxvw0d6slnaz5VcNQr17CFZRPD4I039WjhjHEbbctuI3J3I39enlW+FrSlqtTj1RqDMZZqcgKGAmBZYw0hIlVjJzdg4VnUo2yLx4kEmhB109HljL3tum9RS/+jHa3+wdO/oV6Ot90dTX6XdRX//Z">';
document.body.appendChild(div);
 
function notify(msg){
    var div = document.createElement('div');
    div.setAttribute('style', 'position:absolute; top:350px; left:400px; padding:2px; z-index:160; border:solid black 1px; background:#fff; -moz-border-radius:5px;');
    div.innerHTML = msg;
    document.body.appendChild(div);
 
    window.setTimeout(function(){div.parentNode.removeChild(div);}, 2000);
}
 
var truck_stage = 0;
div.addEventListener('click', function(){
        // If the truck gets clicked a second time...
        if (truck_stage == 1){
            reset_vil();
            return;
        }
        truck_stage++;
        div.childNodes[0].title = 'Restore building positions';
 
        // Add listeners to all of the objects
        var stage = 0;
        var src;
 
        // Cut all of the village links, so clicking on the villages no longer redirects
        // Also, store index info in here - it's the easiest way I can think of getting this info to the click listener routine
        for (var i in poly)
            if (poly[i].href != undefined)
                poly[i].href = '#'+(poly[i].href.split('id=')[1] - 18);
        var wall = document.getElementById('map1').childNodes;
        for (var i in wall)
            if (wall[i].href != undefined)
                wall[i].href = '#22';
 
        // Listen for a click on each building
        for (var i in poly) poly[i].addEventListener('click', function(e){
                var dest = e.target.href.split('#')[1]; // Extract the index info from above
 
                // Error conditions
                if (dest == '21'){
                    notify('<b>You cannot move the rally point</b>');
                    return;
                }
                if (dest == '22'){
                    notify('<b>You cannot move the walls</b>');
                    return;
                }
 
                // This is the first click
                if (stage == 0){
                    src = dest; // actually...
 
                    notify('<b>Click on the second one</b>');
                    stage++;
                } else { // Now we have to save said data
                    var m = mapping[did];
 
                    //GM_log('src='+src+' dest='+dest);
                    // First, find who *holds* src right now
                    var temp = src;
                    while (m[temp] != undefined && m[temp] != src) temp = m[temp];
                    // Find who *holds* dest right now
                    var temp2 = dest;
                    while (m[temp2] != undefined && m[temp2] != dest) temp2 = m[temp2];
                    //GM_log('m['+temp+']='+dest);
                    //GM_log('m['+temp2+']='+src);
                    m[temp] = parseInt(dest);
                    m[temp2] = parseInt(src);
 
                    GM_setValue('mapping', uneval(mapping));
                    window.location.reload();
                }
            }, false);
 
        notify('<b>Click on the first building</b>');
    }, false);

Revision as of 16:37, 3 November 2017

User scripts are programs which make on-the-fly changes to specific web pages, typically to change their appearance or to add or modify functionality.

User scripts for Greasemonkey and Greasemonkey-compatible alternatives are written in JavaScript. If you would like to write user scripts yourself, see Greasemonkey Manual:Editing.

See Also