Colour Bag

Lets you colour inventory text in KOL. Click on inventory item text to rotate colours.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name           Colour Bag
// @namespace      kol.interface.unfinished
// @description    Lets you colour inventory text in KOL.  Click on inventory item text to rotate colours.
// @include        https://*kingdomofloathing.com/inventory.php*
// @include        https://*kingdomofloathing.com/storage.php*
// @include        https://*kingdomofloathing.com/managestore.php*
// @include        https://*kingdomofloathing.com/multiuse.php*
// @include        https://*kingdomofloathing.com/managecollection.php*
// @include        https://*kingdomofloathing.com/town_sellflea.php*
// @include        https://*kingdomofloathing.com/wand.php*
// @include        https://*kingdomofloathing.com/familiar.php*
// @include        https://*kingdomofloathing.com/craft.php*
// @include        https://*kingdomofloathing.com/knoll.php*
// @include        https://*kingdomofloathing.com/hiddencity.php*
// @include        https://*kingdomofloathing.com/closet.php*
// @include        https://*kingdomofloathing.com/clan_stash.php*
// @include        https://*kingdomofloathing.com/lair*
// @include        https://*kingdomofloathing.com/fight.php*
// @include        https://*kingdomofloathing.com/town_right.php?place=untinker*
// @include        https://*kingdomofloathing.com/account.php
// @grant          GM_getValue
// @grant          GM_setValue
// @version        2.12
// ==/UserScript==

// Version 2.12
// - switch to https
// Version 2.11
// - add @grant, convert GM_log to console.log
// Version 2.1
// - now allows colours to be set in Hagnk's
// - added a lock option to avoid accidental re-settings
// Version 2.0.1
//  - added fight page so combat items are coloured (old style combat only)
// Version 2.0
//  - major redesign, now based on item id instead of descitem
//  - now applies to many more lists
//  - now applies when extra drop-downs are created (mall, collection, etc)
//  - now applies to recently equipped list
//  - as a tradeoff, colour does not show up in actual equipped items any more
// Version 1.1
//  - now colours items in many lists (Hagnks, mall, zapping, flea market)
// Version 1.0

// Feel free to add or remove colour names.
// (the first entry is special, don't change it.)
var colourarray = ['','red','green','blue','orange', 'brown', 'purple', 'steelblue', 'silver', 'seagreen', 'SandyBrown', 'crimson' ];

// attribute name for storing colour in clickable entries
var tddcolour='colourbagcolour';
// attribute name for storing item id in clickable entries
var tdditemid='colourbagitem';
// id of script holding inserted css text
var finalcssid='colourbagcssid';
// greasemonkey global var for storing colour list
var clist='colourlist2';

// permanent storage, and update the current css
function saveColourlist(cl) {
    var s = '';
    for (var d in cl) {
        if (cl[d])
            s += d+':'+cl[d]+';';
    }
    GM_setValue(clist,s);
    createCss(cl);
}

// load the colourlist; consists of itemid:colour pairs
function loadColourlist() {
    var colourlist={};
    var s = GM_getValue(clist,'');
    if (s!='') {
        var sp = s.split(';');
        for (var i=0;i<sp.length;i++) {
            var r = sp[i].split(':');
            if (r.length==2) {
                colourlist[r[0]]=r[1];
            }
        }
    }
    return colourlist;
}

// main function to add colour toggling links in the inventory pane
function addEditLinks(page,doc) {
    var colourlist=loadColourlist();
    // look for td's with an id attribute consisting of
    // 'i' followed by numbers
    var elts = document.getElementsByTagName('td');
    for (var i=0;i<elts.length;i++)  {
        var tdd = elts[i];
        var tddid = tdd.getAttribute('id');
        if (tddid && tddid.match(/i[0-9]*/)) {
            // found an entry
            tddid=tddid.substr(1);
            // the text is the first bold therein
            var bref = tdd.getElementsByTagName('b');
            if (bref.length>0) {
                // found text
                var t = bref[0];
                t.title='Click to change colour.';
                t.setAttribute(tdditemid,tddid);
                if (colourlist[tddid]) {
                    t.setAttribute(tddcolour,colourlist[tddid]);
                }
                // add up and down event listeners
                t.addEventListener("click", changeColourUp, true);
                t.addEventListener("contextmenu", changeColourDown, true);
            } 
        }
    }
}

// handler for left clicking
function changeColourUp(e) {
    changeColour(this,false);
}

// handler for right clicking
function changeColourDown(e) {
    changeColour(this,true);
    if (e.stopPropagation) 
        e.stopPropagation();
}

// common handler function for changing colour
function changeColour(x,dec) {
    // get original colour
    var orgcolour=x.getAttribute(tddcolour);
    // get item id
    var desc=x.getAttribute(tdditemid);
    var newcolour;
    if (!orgcolour) {
        if (!dec)
            newcolour=colourarray[1];
        else
            newcolour=colourarray[colourarray.length-1];
    } else {
        for (var i=0;i<colourarray.length;i++) {
            if (colourarray[i]==orgcolour) {
                if (!dec)
                    newcolour = colourarray[(i+1)%(colourarray.length)];
                else
                    newcolour = colourarray[((i-1)<0) ? (colourarray.length-1) : i-1];
                break;
            }
        }
    }
    var colourlist=loadColourlist();
    if (newcolour=='') {
        colourlist[desc]=null;
        x.removeAttribute(tddcolour);
    } else if (newcolour) {
        colourlist[desc]=newcolour;
        x.setAttribute(tddcolour,newcolour);
    }
    saveColourlist(colourlist);
}

// routine to add or modify our css; heavily modified from Dive Into Greasemonkey
function addGlobalStyle(css,id) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.getElementById(id);
    if (!style) {
        //console.log("Creating first css");
        style = document.createElement('style');
        style.type = 'text/css';
        style.setAttribute('id',id);
        style.innerHTML = css;
        head.appendChild(style);
    } else {
        //console.log("Replacing existing css");
        style.innerHTML = css;
    }
}

// main function to create or modify the css for our colours
// idea: have a rule for each colour
// with a big selector, choosing 
//  1) bold elements as first children of a td with the corresponding item id
//  2) option elements with a value of the id
function createCss(cl) {
    var icl={};
    for (var d in cl) {
        var c = cl[d];
        if (!c)
            continue;
        if (icl[c])
            icl[c]=icl[c]+', td[id="i'+d+'"]>b, option[value="'+d+'"]';
        else
            icl[c]='td[id="i'+d+'"]>b, option[value="'+d+'"]';
    }
    var finalcss='';
    for (var c in icl) {
        if (icl[c])
            finalcss += icl[c]+' { color:'+c+'; } ';
    }
    //console.log("finalcss="+finalcss);
    addGlobalStyle(finalcss,finalcssid);
}


// --------------------------------------------
// ---------- account menu option -------------
// --------------------------------------------


// Charon's code
function buildPrefs() {
    if (!document.querySelector('#privacy'))
        return;
    if (!document.querySelector('#scripts')) {
        //scripts tab is not built, do it here
        var scripts = document.querySelector('ul').appendChild(document.createElement('li'));
        scripts.id = 'scripts';
        var a = scripts.appendChild(document.createElement('a'));
        a.href = '#';
        var img = a.appendChild(document.createElement('img'));
        img.src = 'http://images.kingdomofloathing.com/itemimages/cmonkey1.gif';
        img.align = 'absmiddle';
        img.border = '0';
        img.style.paddingRight = '10px';
        a.appendChild(document.createTextNode('Scripts'));
        a.addEventListener('click', function (e) {
                //make our new tab active when clicked, clear out the #guts div and add our settings to it
                e.stopPropagation();
                document.querySelector('.active').className = '';
                document.querySelector('#scripts').className = 'active';
                document.querySelector('#guts').innerHTML = '<div class="scaffold"></div>';
                document.querySelector('#guts').appendChild(getSettings());
            }, false);
    } else {
        //script tab already exists
         document.querySelector('#scripts').firstChild.addEventListener('click', function (e) {
                //some other script is doing the activation work, just add our settings
                e.stopPropagation();
                document.querySelector('#guts').appendChild(getSettings());
            }, false);
    }
}

function getSettings() {
    //build our settings and return them for appending
    var contents = document.createElement('div');
    contents.id = 'recipecounterprefs';
    var fieldset = contents.appendChild(document.createElement('fieldset'));
    fieldset.setAttribute('style', 'width:33%; margin-top:20px');
    var legend = fieldset.appendChild(document.createElement('legend'));
    legend.className = 'subhead';
    legend.textContent = 'Colour Bag';
    var section = fieldset.appendChild(document.createElement('div'));
    section.className = 'indent';
    section.appendChild(buildSettings());
    return contents;
}

function buildSettings() {
    var d = document.createElement('div');
    d.appendChild(document.createTextNode('Lock colour settings: '));
    var ar = document.createElement('a');
    ar.setAttribute('href','#');
    if (GM_getValue('locked',false)) {
        ar.appendChild(document.createTextNode('now locked'));
        ar.setAttribute('title','Changing text colours is now prevented.  Click to toggle.');
    } else {
        ar.appendChild(document.createTextNode('now unlocked'));
        ar.setAttribute('title','Changing text colours is now allowed.  Click to toggle.');
    }
    ar.addEventListener('click',toggleLock,false);
    ar.setAttribute('id','colourbaglock');
    //li.appendChild(ar);
    //ul.appendChild(li);
    d.appendChild(ar);
    return d;
}

function toggleLock() {
    var ar = document.getElementById('colourbaglock');
    if (GM_getValue('locked',false)) {
        GM_setValue('locked','');
        ar.replaceChild(document.createTextNode('now unlocked'),ar.firstChild);
        ar.setAttribute('title','Changing text colours is now allowed.  Click to toggle.');
    } else {
        GM_setValue('locked','true');
        ar.replaceChild(document.createTextNode('now locked'),ar.firstChild);
        ar.setAttribute('title','Changing text colours is now prevented.  Click to toggle.');
    }
}

// grab the stored colour list
var firstcl = loadColourlist();
// create the css
createCss(firstcl);

// if in inventory frame, add edit links too
if (window.location.pathname.indexOf('/inventory.php')>=0 || window.location.pathname.indexOf('/storage.php')>=0) {
    if (!GM_getValue('locked',false))
        addEditLinks();
} else if (window.location.pathname.indexOf('/account.php')==0) {
    buildPrefs();
}