Greasy Fork is available in English.

pso2 catalog2table

スク品のメモ蝶とワンクリックでアイテム名コピー

Stan na 2021-01-07 22:46:01 UTC. Zobacz najnowszą wersję.

// ==UserScript==
// @name         pso2 catalog2table
// @name-jp      PSO2 スクラッチカタログのメモシート化
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  スク品のメモ蝶とワンクリックでアイテム名コピー
// @author       You
// @match        http://pso2.jp/players/catalog/scratch/ac/*/
// @match        http://pso2.jp/players/catalog/scratch/gold/*/
// @grant        none
// ==/UserScript==

var isgold = !!~document.URL.indexOf('scratch/gold/');
var keyword = isgold ? 'gold/' : 'ac/';
var catalogid = document.URL.split(keyword)[1].split('/')[0];
if(isgold)catalogid = 'gold'+catalogid;

//build page
//button to toggle table display
var mbtoggletable = createbutton('☨表召喚☨');
mbtoggletable.addEventListener('click',toggletable);
mbtoggletable.style.width = 'auto';
mbtoggletable.style.position = 'fixed';
mbtoggletable.style.top = '0px';
mbtoggletable.style.right = '10px';
mbtoggletable.style.zIndex = '10001';
document.body.appendChild(mbtoggletable);

var mbexport = createbutton('export');
mbexport.addEventListener('click',converttotext);
mbexport.style.width = 'auto';
mbexport.style.position = 'fixed';
mbexport.style.top = '20px';
mbexport.style.right = '10px';
mbexport.style.zIndex = '10001';
document.body.appendChild(mbexport);

var mbclear = createbutton('clear');
mbclear.addEventListener('click',clearprices);
mbclear.style.width = 'auto';
mbclear.style.position = 'fixed';
mbclear.style.top = '40px';
mbclear.style.right = '10px';
mbclear.style.zIndex = '10001';
document.body.appendChild(mbclear);

function clearprices(){
    var alltr = table.querySelectorAll('tr');
    var alltd;
    allstates.forEach(function(item,index){
        if(!item){
            alltd = alltr[index+1].querySelectorAll('td');
            for (let i = 2, end = 12; i<end;i++){
                alltd[i].querySelector('input').value = '';
            }
        }
    });
}

function toggletable(){
    overlay.style.display = overlay.style.display == 'none' ? '' : 'none';
    mbtoggletable.value = overlay.style.display == 'none' ? '☨表召喚☨' : '卍表派遣卍';
}

//table wrapper & extras
var overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = '0px';
overlay.style.right = '0px';
overlay.style.height = '100%';
overlay.style.width = '100%';
overlay.style.zIndex = '9997';
overlay.style.overflow = 'auto';
overlay.style.display = 'none';

var overlaycontents = document.createElement('div');
overlaycontents.style.position = 'absolute';
overlaycontents.style.width = '100%';
overlaycontents.style.margin = 'auto';

var overlaysubcontents = document.createElement('div');
overlaysubcontents.style.textAlign = 'center';
overlaycontents.appendChild(overlaysubcontents);


var optdiv = document.createElement('div');
optdiv.style.align = 'center';
optdiv.style.left = '50%';
optdiv.style.top = '50%';
optdiv.style.display = 'inline-block';

overlaysubcontents.appendChild(optdiv);

var legend = document.createElement('span');
legend.style.backgroundColor = '#333333';
legend.innerHTML = `<font color ='white'>画像左右クリックで色の切替<br>
画像中クリックでプレビュー<br>
名前クリックでクリップボード<br></font>
<b><font color="yellow">購入予定</font>
<font color="green">購入済</font>
<font color="red">予定外</font></b>
`;
legend.style.display = 'inline-block';

overlaysubcontents.appendChild(legend);


overlay.appendChild(overlaycontents);
document.body.appendChild(overlay);

var exporter = overlay.cloneNode();
exporter.style.zIndex = '9998';
exporter.style.width = 'auto';
exporter.style.height = 'auto';
exporter.style.top = '50%';
exporter.style.left = '50%';
exporter.style.overflow = '';
exporter.style.transform = 'translate(-50%,-50%)';

var exporterfield = document.createElement('textarea');
exporterfield.cols = 96;
exporterfield.rows = 40;
var mbcloseexport = createbutton('close');
mbcloseexport.addEventListener('click', function(){exporter.style.display = 'none';});
exporter.appendChild(mbcloseexport);
var mbtest = createbutton('copy');
mbtest.addEventListener('click', function(){copyelemtext(exporterfield);});
exporter.appendChild(mbtest);
exporter.insertAdjacentHTML('beforeend','<br>');
exporter.appendChild(exporterfield);
document.body.appendChild(exporter);

//script start
var allitems = Array.from(document.querySelectorAll('.item-list-l')); //all item data
var allstates = []; //icon column colors
var allselections = []; //ship column colors

var allimages = []; //item icons
var allnames = []; //item names
var allgenres = []; //item types
var alldansei = []; //filter setting flags
var allcostume = [];
var allnonfashion = [];
var allbought = [];
var allnoplan = [];

var allcheapest = []; //cheapest column entries
var allitemsoriginal = Array.from(allitems);

for (let index = allitems.length-1; index >= 0; index--){
    var item = allitems[index];
    var genre = item.querySelector('dd.detail > table > tbody > tr:nth-child(1) > td').innerText;
    var description = item.querySelector('dd.description > p').innerText;
    var newarray = [];
    let itemclone;
    if (~genre.indexOf('(セット)') || ~description.indexOf('セットを使用すると')){
        var allsubs = item.querySelectorAll('ul.image > li');
        for (let i = 0, iend = allsubs.length; i < iend; i++){
            var children = allsubs[i].children
            for (let j = 0, jend = children.length; j < jend; j++){
                allsubs[i].removeChild(children[j]);
            }
            itemclone = item.cloneNode(true);
            itemclone.querySelector('dl.item-list-l>dt').innerText = allsubs[i].innerText.split('「').pop().split('」').shift();
            newarray.push(itemclone);
        }
        allitems.splice(index,1);
        for(let i = 0, end = newarray.length; i < end; i++){
            allitems.splice(index+i,0,newarray[i]);
            if(i>0)allitemsoriginal.splice(index+i,0,allitemsoriginal[index]);
        }
    }
}

//parse item data to fill up above arrays
allitems.forEach(function(item,index){
    //image
    var image = item.querySelector('dd.detail').querySelector('img');
    if (image) {image = image.src} else {image = ''}
    allimages.push(image);
    //name
    var name = item.querySelector('dt').innerText;
    allnames.push(name);
    //genre
    var genre = item.querySelector('dd.detail > table > tbody > tr:nth-child(1) > td').innerText;
    var genreabbrev = genre.split('\n')[0];
    allgenres.push(genreabbrev);
    //dansei
    var flavor = item.querySelector('dd.description').innerText;
    var cond1 = genre.indexOf('男性') > -1;
    var cond2 = flavor.indexOf('男性のみ使用可能') > -1;
    var dansei = false;
    if (cond1 || cond2) {dansei = true};
    alldansei.push(dansei);
    //costume
    var cond3 = name.indexOf('[Ou]') > -1;
    var cond4 = (genre.indexOf('コスチューム') > -1) || (genre.indexOf('パーツ') > -1);
    var costume = false;
    if (cond3 || cond4) {costume = true};
    allcostume.push(costume);
    //nonfashion
    var nonfashion = containsany(genre,['マグ','アイテム強化']);
    allnonfashion.push(nonfashion);
});

console.log({allimages},{allnames},{allgenres},{alldansei});

//construct table
var table = document.createElement('table');
table.style.tableLayout = 'auto';
table.className = 'pricetable';
table.style.borderSpacing = '0';
table.style.borderCollapse = 'collapse';
//header
var header = document.createElement('tr');
header.innerHTML = '<th>img</th><td>name</td>'
for (let col = 0, colend=10; col < colend; col++){
    var th = document.createElement('th');
    th.innerText = 'ship'+(col+1);
    th.className = 'ship'+(col+1);
    header.appendChild(th);
}
var cheapheader = document.createElement('td');
cheapheader.innerText = 'cheapest';
cheapheader.addEventListener('click',function(){changed = true;autosuggestcheap();});
header.appendChild(cheapheader);
table.appendChild(header);

//generate rows
for (let row = 0, rowend = allitems.length; row < rowend; row++){
    var tr = document.createElement('tr');
    tr.style.whiteSpace = 'nowrap';
    //add image
    var tdimg = document.createElement('td');
    tdimg.className = 'itemimg';
    var tempimg = document.createElement('img');
    tempimg.width = 50;
    tempimg.height = 50;
    tempimg.src = allimages[row];
    //add events on img click
    tdimg.addEventListener('click',function(){ toggleitemstate(row,); });
    tdimg.addEventListener('contextmenu',function(e){ toggleitemstate(row,-1,true,e); });
    tdimg.addEventListener('mousedown',function(e){if(e.which == 2){e.preventDefault();openpreview(row)};});
    tdimg.appendChild(tempimg);
    tr.appendChild(tdimg);
    //add name
    let tdname = document.createElement('td');
    tdname.className = 'itemname';
    tdname.innerHTML = allnames[row];
    tdname.addEventListener('click',function(){ copytoclip(tdname); });
    tr.appendChild(tdname);
    //add ship columns
    for (let col = 0, colend = 10; col < colend; col++){
        let tdprices = document.createElement('td');
        tdprices.className = 'ship'+(col+1);
        let input = document.createElement('input');
        input.size = 4;
        input.maxLength = 8;
        input.addEventListener('input',function(){changed = true; checkcheapest(row); });
        //add events on price click
        tdprices.addEventListener('click',function(){ togglepricestate(row,tdprices); });
        tdprices.addEventListener('contextmenu',function(e){ togglepricestate(row,tdprices,-1,true,e); });
        tdprices.addEventListener('mousedown',function(e){if(e.which == 2){e.preventDefault();focusinside(tdprices);}});
        tdprices.appendChild(input);
        tr.appendChild(tdprices);

    }
    //add cheapest column
    let cheaptd = document.createElement('td');
    cheaptd.className = 'cheapest';
    cheaptd.addEventListener('click',function(){changed = true; autosuggestcheap(row)});
    tr.appendChild(cheaptd);
    table.appendChild(tr);
}

overlaycontents.appendChild(table);

function hideships(targets){
    //loop through designated ships 1-10 columns to toggle their display
    for (let i in targets){
        var target = targets[i];
        var cells = document.querySelectorAll('.ship'+target);
        cells.forEach(function(item,index){
            var currentdisplay = item.style.display;
            item.style.display = (currentdisplay == 'none') ? '' : 'none';
        });
    }
}

function openpreview(row){
    allitemsoriginal[row].querySelector('a').click();
    if(allgenres[row]=='ボイス'){
        allitemsoriginal[row].querySelector('.voice__list li').click();
    }
}

function togglerows(){
    //loop through designated item rows to display according to settings
    var allrows = table.querySelectorAll('tr');
    var conditions = types;
    for (let row = 1, rowend = allrows.length; row < rowend; row++){
        var hidethisrow = false;
        for (let i in conditions){
            var mask = 1 << (i*1);
            if ( (typeoptions & mask) != 0 && conditions[i][row-1] ){
                hidethisrow = true;
                break
            }
        }
        if (hidethisrow) {allrows[row].style.display = 'none';}
        else {allrows[row].style.display = '';}
    }
}

function toggleitemstate(row,direction,disable,e){
    changed = true;
    //wrapper for toggling color when clicking
    direction = direction || 1;
    if (disable) e.preventDefault();
    var curr = allstates[row];
    if (curr === undefined) {curr = 0;}
    allstates[row] = maptorange(curr+direction,3,0,true);
    colorrowbytoggle([row]);
}

function colorrowbytoggle(rows,all){
    //toggle color
    var colors2use = ['white','yellow','green','red'];
    var allrows = table.querySelectorAll('.itemimg');
    if (all){
        for (let i = 0, end = allrows.length-1; i < end; i++){
            var row = i+1;
            colorthis(allrows[row],row);
        }
    } else {
        for (let i in rows){
            var row = rows[i];
            colorthis(allrows[row],row);

        }
    }
    function colorthis(item,index){
        var state = allstates[index];
        item.style.background = colors2use[state];
        allbought[index] = state==2;
        allnoplan[index] = state==3;
    }
}

function togglepricestate(row,cell,direction,disable,e){
    changed = true;
    direction = direction || 1;
    if (event.target.tagName == 'INPUT') return
    if (disable) e.preventDefault();
    var shipnum = cell.className.split('ship')[1]*1;
    var mask0 = 1<<((shipnum-1)*2);
    var mask1 = mask0*2;
    var wholesel = allselections[row] || 0;
    var currsel = ( (wholesel & mask0)+(wholesel & mask1) ) / mask0;
    var newsel = maptorange(currsel+direction,3,0,true);
    allselections[row] = allselections[row] & ~mask0 & ~mask1; //clear both bits before setting
    allselections[row] |= (newsel * mask0);
    //var updatedwholesel = allselections[row];
    //    console.log({shipnum},{wholesel},{mask0},{mask1},{currsel},{newsel},{updatedwholesel});
    //    var colors2use = ['white','yellow','green','red'];
    //    cell.style.background = colors2use[newsel];
    colorpricebytoggle([row+1],false); //+1 to account for header row
}

function forcechangepricestate(row,shipnum,newvalue,reqvalue){
    var mask0 = 1<<((shipnum-1)*2);
    var mask1 = mask0*2;
    var wholesel = allselections[row] || 0;
    var currsel = ( (wholesel & mask0)+(wholesel & mask1) ) / mask0;
    if ((reqvalue != undefined) && (currsel != reqvalue)) return;
    var newsel = maptorange(newvalue,3,0,true);
    allselections[row] = allselections[row] & ~mask0 & ~mask1; //clear both bits before setting
    allselections[row] |= (newsel * mask0);
    colorpricebytoggle([row+1],false);
}

function colorpricebytoggle(rows,all){
    var allrows = table.querySelectorAll('tr');
    var colors2use = ['white','yellow','green','blue'];
    if (all){
        for (let row = 1, rowend = allrows.length; row < rowend; row++){
            colorthis(row);
        }
    } else {
        for (let i in rows){
            var row = rows[i];
            colorthis(row);
        }
    }
    function colorthis(row){
        var rowsel = allselections[row-1] || 0;
        var currcols = allrows[row].querySelectorAll('td');
        for (let col = 2, colend = 12; col < colend; col++){
            var cell = currcols[col];
            var mask = (2<<(col-1)) + (2<<(col-2)); //col 2 = ship1
            var mask0 = 1<<((col-2)*2); //col 2 = ship1 = 0th&1st bits
            var mask1 = mask0 * 2;
            var cellsel = ((rowsel & mask0) + (rowsel & mask1)) / mask0;
            cell.style.background = colors2use[cellsel];
        }
    }
}

function focusinside(elem){
    elem.querySelector('input').focus();
}

function checkcheapest(row){
    row += 1;
    var allrows = table.querySelectorAll('tr');
    var currrow = allrows[row];
    var cheaptd = currrow.querySelector('.cheapest');
    var rowinputs = currrow.querySelectorAll('input');
    var rowprices = [];
    var shipscounted = 0;
    //get all prices and check if completed
    for (let i = 0, end = 10; i<end; i++){
        var parenttd = rowinputs[i].closest('td');
        if (parenttd.style.display == 'none'){
            shipscounted++;
        } else {
            if (rowinputs[i].value != undefined && rowinputs[i].value != 0) {
                shipscounted++;
                rowprices[i] = rowinputs[i].value;
            }
        }
    }
    if (shipscounted >= 10){
        var buyhere = getminindices(rowprices,1);
        cheaptd.innerText = buyhere;
        allcheapest[row-1] = buyhere;
    } else {
        cheaptd.innerText = '';
        allcheapest[row-1] = undefined;
    }
}

function checkallcheapest(){
    var allrows = table.querySelectorAll('tr');
    for (let i = 1, end = allrows.length; i<end; i++){
        checkcheapest(i-1);
    }
}

function autosuggestcheap(row){
    var allrows = table.querySelectorAll('tr');
    let start = row == undefined ? 1 : row+1;
    let end = row == undefined ? allrows.length : start+1;
    for (let i = start; i < end; i++){
        var cheapest = allcheapest[i-1];
        if (!cheapest || (allstates[i-1] >=2)) continue;
        var allcols = allrows[i].querySelectorAll('td');
        for (let j = 0, end = cheapest.length;j<end;j++){
            forcechangepricestate(i-1,cheapest[j],1,0);
        }
    }
}

function converttotext(){
    var allrows = table.querySelectorAll('tr');
    var text ='';
    var boughtmarker = 'x';
    for (let row = 0, rowend = allrows.length; row<rowend; row++){
        //check if item is neither filtered nor unplanned, or is bought
        if((allrows[row].style.display != 'none' || allstates[row-1] == 2) && allstates[row-1] != 3){

            var rowcols = allrows[row].querySelectorAll('td,th');
            if (row == 0){
                text += '        \t\t';
            } else {
                if (text) text += '\n';
                text += rowcols[1].innerText;
                //align names with tab
                for (let i = 0, end = (21 - rowcols[1].innerText.length) / 7 -1; i < end; i++){
                    text += '\t';
                }
            }
            //add x if bought
            if(allstates[row-1]==2) text += boughtmarker;
            for (let col = 2, colend = 12; col < colend; col++){
                if (rowcols[col].style.display != 'none'){
                    if (row ==0){
                        text += '\tship'+(col-1);
                        if(col==11) text += '\n';
                        continue
                    }
                    text += '\t' +rowcols[col].querySelector('input').value;
                    switch (getselectionofcell(row-1,col-1)){
                        case 3:
                            text +=boughtmarker;
                        case 2:
                            text +=boughtmarker;
                    }
                }
            }
        }
    }
    exporterfield.value = text;
    exporter.style.display = exporter.style.display == 'none'? '' : 'none';
}

function getselectionofcell(item,ship){
    var rowsel = allselections[item];
    var mask0 = 1<<((ship-1)*2); //col 2 = ship1 = 0th&1st bits
    var mask1 = mask0 * 2;
    var output = ((rowsel & mask0) + (rowsel & mask1)) / mask0;
    return output;
}

//general functions
function containsany(str, items){
    for(var i in items){
        var item = items[i];
        if (str.indexOf(item) > -1){
            return true;
        }

    }
    return false;
}

function copytoclip(item){
    document.oncopy = function(event) {
        event.clipboardData.setData("Text", item.innerText || item.value);
        event.preventDefault();
    };
    document.execCommand("Copy");
    document.oncopy = undefined;
    selectText(item);
}

function copyelemtext(elem){
    elem.select();
    //    selectText(elem);
    document.execCommand('copy')
}

function selectText(el){
    var sel, range;
    if (window.getSelection && document.createRange) {
        sel = window.getSelection();
        if(sel.toString() == ''){
            window.setTimeout(function(){
                range = document.createRange();
                range.selectNodeContents(el);
                sel.removeAllRanges();
                sel.addRange(range);
            },1);
        }
    }else if (document.selection) {
        sel = document.selection.createRange();
        if(sel.text == ''){
            range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        }
    }
}

function maptorange(value,max,min,wrap){
    value = value || 0;
    max = max || 0;
    min = min || 0;
    wrap = wrap || true;
    console.log("maptorange: ",{wrap},{value},{max},{min});
    if (!wrap) return Math.min(Math.max(value, min), max);
    value = value % (max+1);
    if (value < min) value += max - min + 1;
    console.log({value});
    return value;
}

function createbutton(value,f){
    var tempbutton = document.createElement('input');
    tempbutton.type = 'button';
    tempbutton.value = value;
    tempbutton.style.width = '50px';
    return tempbutton
}

function getminindices(array,offset){
    if (array.length <= 0) return
    offset = offset || 0;
    var indices = [];
    var check = array[0];
    for (let i in array){
        if ((array[i]*1) == check){
            indices.push(i*1+offset);
        }
        if ((array[i]*1) < check){
            check = array[i];
            indices = [i*1+offset]
        }
    }
    return indices
}

//options
//ship display
var shipsbinary = 0;
var shipbuttons = [];
for (let i = 1, end = 10; i<=end; i++){
    if (i == 6){
        optdiv.insertAdjacentHTML('beforeend', '<br>')
    }
    let temp = createbutton('ship'+i);
    temp.addEventListener('click',function(){mbhideship(i,temp);});
    optdiv.appendChild(temp);
    shipbuttons.push(temp);
}

function mbhideship(shipnum,button){
    shipsbinary ^= (1 << shipnum);
    var tempcollection = document.querySelectorAll('.ship'+shipnum);
    tempcollection.forEach(function(item,index){
        item.style.display = item.style.display == 'none'? '' : 'none';
    });
    button.style.color = button.style.color == 'red'? '' : 'red';

}

//type display
var typeoptions = 0;
var types = [alldansei, allcostume, allnonfashion,allbought,allnoplan];
var typenames = ['男性','コスチュム','非ファッション','購入済','予定外'];
var typebuttons = [];
optdiv.insertAdjacentHTML('beforeend', '<br>')
for (let i = 0, end = types.length; i < end; i++){
    let temp = createbutton(typenames[i]);
    temp.addEventListener('click',function(){mbtoggletype(i,temp);});
    optdiv.appendChild(temp);
    typebuttons.push(temp);
}

function mbtoggletype(type,button){
    typeoptions ^= (1 << type);
    togglerows();
    button.style.color = button.style.color == 'red'? '' : 'red';
}


//save function
//load from storage to rebuild table prices and display states
save2table();
save2option();

//save to storage on exit
window.onbeforeunload = function() {
    table2save();
    option2save();
}

//autosave every 5 minutes if change has been made to table
var changed = false;
var autosave = setInterval(autosavewrapper,1000*60*5);

function autosavewrapper(){
    if (changed) {
        all2save()
        changed = false;
        console.log('autosaved');
    };
}

function all2save(){
    table2save();
    option2save();
}

function table2save(){
    var prices = [];
    var tablerows = table.querySelectorAll('tr');
    //loop through rows, skipping header
    for (let row = 1, rowend = tablerows.length; row < rowend; row++){
        var tablecols = tablerows[row].querySelectorAll('td');
        var temparray = [];
        var itemname = tablecols[1].innerText;
        temparray.push(itemname);
        //loop through cols, skipping img and name
        for (let col = 2, colend = 12; col < colend; col++){
            var currprice = tablecols[col].querySelector('input').value;
            temparray.push(currprice);
        }
        prices.push(temparray);
    }
    console.log({prices});
    //var catalogid = document.URL.split('ac/')[1].split('/')[0];

    localStorage.setItem(catalogid, JSON.stringify(prices) );
    //save states
    localStorage.setItem(catalogid+'states', JSON.stringify(allstates));
    //save selections
    localStorage.setItem(catalogid+'selections', JSON.stringify(allselections));
}

function option2save(){
    localStorage.setItem('shipoptions',shipsbinary);
    localStorage.setItem('typeoptions',typeoptions);
}

function save2table(){
    var temp = localStorage.getItem(catalogid);
    if (!temp) return
    var prices = JSON.parse( localStorage.getItem(catalogid) );
    var tablerows = table.querySelectorAll('tr');
    //loop through rows, skipping header
    for (let row = 1, rowend = tablerows.length; row < rowend; row++){
        var tablecols = tablerows[row].querySelectorAll('td');
        var itemname = tablecols[1].innerText;
        if (itemname != prices[row-1][0]) continue
        //loop through cols, skipping img and name
        for (let col = 2, colend = 12; col < colend; col++){
            var currprice = prices[row-1][col-1];
            var currinput = tablecols[col].querySelector('input');
            currinput.value = currprice;
        }
    }
    console.log({prices});
    setTimeout(function(){checkallcheapest();},1000);
    //load states
    temp = localStorage.getItem(catalogid+'states');
    if (temp) allstates = JSON.parse(temp);
    console.log({allstates});
    colorrowbytoggle('',true);
    //load selections
    temp = localStorage.getItem(catalogid+'selections');
    console.log('load selections: ',{temp});
    if (temp) allselections = JSON.parse(temp);
    console.log({allselections});
    colorpricebytoggle('',true);
}

function save2option(){
    //ship display
    var temp = localStorage.getItem('shipoptions');
    if (!temp) return
    shipsbinary = temp * 1;
    console.log({shipsbinary});
    var hidetargets = [];
    for (let i = 1, end = 10; i <= end; i++){
        var mask = 1 << i;
        if ((shipsbinary & mask) != 0){
            hidetargets.push(i);
            shipbuttons[i-1].style.color = shipbuttons[i-1].style.color == 'red' ? '' : 'red';
        }
    }
    hideships(hidetargets);
    console.log({hidetargets});

    //type diplay
    temp = localStorage.getItem('typeoptions');
    //    if(!temp) return
    typeoptions = temp * 1;
    console.log({typeoptions});
    togglerows();
    for (let i = 0, end = types.length; i < end; i++){
        var typemask = 1 << i;
        if ( (typeoptions & typemask) != 0){
            typebuttons[i].style.color = 'red';
        }

    }

}