// ==UserScript==
// @name BGG Trade Manager
// @namespace http://tampermonkey.net/
// @version 0.2
// @description Modifies the collection view on Board Game Geek to conveniently project shipping costs. Important note: for this script to run you must filter your collection for game with the "For Trade" flag, include the columns "private information" and "title" and then follow the permalink to that view.
// @author Kempeth
// @match https://www.boardgamegeek.com/collection/user/*?*title*ownership*trade=1*
// @icon https://cf.geekdo-static.com/icons/favicon2.ico
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
const KEY_UNIT_CURRENCY = "unit_currency";
const KEY_UNIT_WEIGHT = "unit_weight";
const KEY_UNIT_SIZE = "unit_size";
var units = {
currency: GM_getValue(KEY_UNIT_CURRENCY, "USD"),
weight: GM_getValue(KEY_UNIT_WEIGHT, "kg"),
size: GM_getValue(KEY_UNIT_SIZE, "mm")
};
var packagings = JSON.parse(GM_getValue("packagings", "[]"));
//console.log("loaded packagings: ", packagings);
var shippings = JSON.parse(GM_getValue("shippings", "[]"));
//console.log("loaded shippings: ", shippings);
var username = "";
/**
Wires up an input so it automatically updates the script variable and GreaseMonkey storage
*/
function bindInputToStorage(fieldid, keyid, valueHolder, valueIndex)
{
var input = document.getElementById(fieldid);
input.value = valueHolder[valueIndex];
input.onchange = () => {
//console.log("script value = " + valueHolder[valueIndex]);
//console.log("input value = " + input.value);
GM_setValue(keyid, input.value)
valueHolder[valueIndex] = input.value;
//console.log("script value = " + valueHolder[valueIndex]);
};
}
/**
Wires up an input so it automatically updates the script list variable and GreaseMonkey storage.
Applies data transformations on read and write if specified.
*/
function bindInputToListStorage(fieldid, item, key, onchange, fromstorage = (x) => x, tostorage = (x) => x)
{
var input = document.getElementById(fieldid);
input.value = fromstorage(item[key]);
input.onchange = () => {
//console.log("script value = " + item[key]);
//console.log("input value = " + input.value);
item[key] = tostorage(input.value);
//console.log("script value = " + item[key]);
onchange();
};
}
/**
Converts an array into a comma separated list.
*/
function array2csv(arr)
{
return arr.join(', ');
}
/**
Converts a comma separated list into an array.
*/
function csv2array(txt)
{
return JSON.parse('[' + txt + ']');
}
/**
Evaluates whether a packaging is eligible for shipping at a given rate.
*/
function eligible(package, shipping)
{
return (shipping.maxsum == 0 || shipping.maxsum >= (package.outer.reduce((sum, dim) => dim + sum)))
&& shipping.maxdim[0] >= package.outer[0] && shipping.maxdim[1] >= package.outer[1] && shipping.maxdim[2] >= package.outer[2];
}
function savePackagings()
{
// only save those that are not null
var storing = packagings.filter(p => p != null);
GM_setValue("packagings", JSON.stringify(storing));
}
function makePackagingDeleteHandler(row, id)
{
return () => {
row.parentNode.removeChild(row);
packagings[id] = null;
savePackagings();
};
}
function addPackagesRow(id)
{
var packaging = {
name: "New Packaging",
weight: 0,
cost: 0,
inner: [990, 590, 590],
outer: [1000, 600, 600],
};
if (packagings.length > id) packaging = packagings[id]; // fetch existing packaging
else packagings.push(packaging); // store new packaging
var row = document.createElement('tr');
row.innerHTML = "<td><input type=\"text\" id=\"trade_pack_name" + id + "\" /></td>" +
"<td><input type=\"number\" style=\"text-align: right\" step=\"0.001\" id=\"trade_pack_weight" + id + "\" /></td>"+
"<td><input type=\"number\" style=\"text-align: right\" step=\"0.01\" id=\"trade_pack_cost" + id + "\" /></td>"+
"<td><input type=\"text\" style=\"text-align: center\" id=\"trade_pack_inner" + id + "\" /></td>"+
"<td><input type=\"text\" style=\"text-align: center\" id=\"trade_pack_outer" + id + "\" /></td>"+
"<td><img src=\"https://cf.geekdo-static.com/images/icons/silkicons/delete.png\" title=\"Delete this packaging\" id=\"trade_pack_delete" + id + "\" style=\"bottom:2px; position:relative;\" /></td>";
document.getElementById('trade_packaging').appendChild(row);
bindInputToListStorage("trade_pack_name" + id, packaging, 'name', savePackagings);
bindInputToListStorage("trade_pack_weight" + id, packaging, 'weight', savePackagings, x => parseFloat(x).toFixed(3), txt => parseFloat(txt));
bindInputToListStorage("trade_pack_cost" + id, packaging, 'cost', savePackagings, x => parseFloat(x).toFixed(2), txt => parseFloat(txt));
bindInputToListStorage("trade_pack_inner" + id, packaging, 'inner', savePackagings, array2csv, csv2array);
bindInputToListStorage("trade_pack_outer" + id, packaging, 'outer', savePackagings, array2csv, csv2array);
var btn = document.getElementById("trade_pack_delete" + id);
btn.onclick = makePackagingDeleteHandler(row, id);
}
function saveShippings()
{
// only save those that are not null
var storing = shippings.filter(p => p != null);
storing.forEach(s => { s.tiers = s.tiers.filter(t => t != null); });
//console.log("saving shippings: ", storing);
GM_setValue("shippings", JSON.stringify(storing));
}
function makeShippingDeleteHandler(row, id)
{
return () => {
row.parentNode.removeChild(row);
shippings[id] = null;
saveShippings();
};
}
function makeShippingTierAddHandler(shipping, id)
{
return () => {
addShippingTierRow(shipping, id, shipping.tiers.length);
saveShippings();
};
}
function makeShippingTierDeleteHandler(id, tid)
{
return () => {
var weight = document.getElementById("trade_ship" + id + "_tier_weight" + tid);
weight.parentNode.removeChild(weight);
var cost = document.getElementById("trade_ship" + id + "_tier_cost" + tid);
cost.parentNode.removeChild(cost);
var del = document.getElementById("trade_ship" + id + "_tier_del" + tid);
del.parentNode.removeChild(del);
shippings[id].tiers[tid] = null;
saveShippings();
};
}
function addShippingTierRow(shipping, id, tid)
{
//console.log(shipping, id, tid);
var shippingtier = {
maxweight: 0,
cost: 0,
};
if (shipping.tiers.length > tid) shippingtier = shipping.tiers[tid]; // fetch existing tier
else shipping.tiers.push(shippingtier); // store new tier
var weights = document.getElementById("trade_shiptier_weights" + id);
var weight = document.createElement('input');
weight.type = "number";
weight.step = "0.001";
weight.id = "trade_ship" + id + "_tier_weight" + tid;
weight.style.textAlign = "right";
weight.style.display = "block";
weight.style.width = "100%";
weight.style.marginTop = "3px";
weight.value = shippingtier.maxweight;
weights.appendChild(weight);
var costs = document.getElementById("trade_shiptier_costs" + id);
var cost = document.createElement('input');
cost.type = "number";
cost.step = "0.01";
cost.id = "trade_ship" + id + "_tier_cost" + tid;
cost.style.textAlign = "right";
cost.style.display = "block";
cost.style.width = "100%";
cost.style.marginTop = "3px";
cost.value = shippingtier.cost;
costs.appendChild(cost);
var dels = document.getElementById("trade_shiptier_deletes" + id);
var del = document.createElement('img');
del.id = "trade_ship" + id + "_tier_del" + tid;
del.src = "https://cf.geekdo-static.com/images/icons/silkicons/money_delete.png";
del.title = "Delete this shipping tier";
del.style.display = "block";
del.style.margin = "5px 0 6px 0";
del.onclick = makeShippingTierDeleteHandler(id, tid);
dels.appendChild(del);
bindInputToListStorage("trade_ship" + id + "_tier_weight" + tid, shippingtier, 'maxweight', saveShippings, x => parseFloat(x).toFixed(3), txt => parseFloat(txt));
bindInputToListStorage("trade_ship" + id + "_tier_cost" + tid, shippingtier, 'cost', saveShippings, x => parseFloat(x).toFixed(2), txt => parseFloat(txt));
}
function addShippingRow(id)
{
var shipping = {
name: "New Shipping",
destinations: "",
maxdim: [ 1000, 600, 600 ],
maxsum: 900,
tiers: [
{
maxweight: 0,
cost: 0,
},
],
};
if (shippings.length > id) shipping = shippings[id]; // fetch existing shipping
else shippings.push(shipping); // store new shipping
var row = document.createElement('tr');
row.innerHTML =
"<td valign=\"top\"><input type=\"text\" style=\"width:100%\" id=\"trade_ship_name" + id + "\" /></td>"+
"<td valign=\"top\"><input type=\"text\" style=\"width:100%\" id=\"trade_ship_dest" + id + "\" /></td>"+
"<td valign=\"top\"><input type=\"text\" style=\"width:100%; text-align: center\" id=\"trade_ship_maxdim" + id + "\" /></td>"+
"<td valign=\"top\"><input type=\"number\" style=\"width:100%; text-align: right\" id=\"trade_ship_maxsum" + id + "\" /></td>"+
"<td valign=\"top\" id=\"trade_shiptier_weights" + id + "\"></td>"+
"<td valign=\"top\" id=\"trade_shiptier_costs" + id + "\"></td>"+
"<td valign=\"top\" id=\"trade_shiptier_deletes" + id + "\" width=\"1\"></td>"+
"<td valign=\"top\" width=\"1\">"+
"<img id=\"trade_ship_tier_add" + id + "\" style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/money_add.png\" title=\"Add new shipping tier\" border=\"0\"> "+
"<img id=\"trade_ship_delete" + id + "\" style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/delete.png\" title=\"Delete this shipping\" border=\"0\">"+
"</td>";
document.getElementById('trade_shipping').appendChild(row);
bindInputToListStorage("trade_ship_name" + id, shipping, 'name', saveShippings);
bindInputToListStorage("trade_ship_dest" + id, shipping, 'destinations', saveShippings);
bindInputToListStorage("trade_ship_maxdim" + id, shipping, 'maxdim', saveShippings, array2csv, csv2array);
bindInputToListStorage("trade_ship_maxsum" + id, shipping, 'maxsum', saveShippings, x => parseFloat(x), txt => parseFloat(txt));
var btn = document.getElementById("trade_ship_delete" + id);
btn.onclick = makeShippingDeleteHandler(row, id);
for (var tid = 0; tid < shipping.tiers.length; tid++)
{
addShippingTierRow(shipping, id, tid);
}
var addtier = document.getElementById("trade_ship_tier_add" + id);
addtier.onclick = makeShippingTierAddHandler(shipping, id);
}
function addOutputUI()
{
var parent = document.getElementById('columnfilter').parentNode;
var run = document.createElement('a');
run.href = "javascript://";
//run.innerHTML = "<img alt=\"Trade Display\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/arrow_switch.png\" border=\"0\" align=\"absmiddle\"> Trade Display";
run.innerText = "Trade Output »"
run.title = "Format your items for trade geeklists";
run.setAttribute("onclick", "Toggle( 'trademanager_output' );");
parent.getElementsByTagName('span')[0].appendChild(run);
parent.getElementsByTagName('span')[0].appendChild(document.createTextNode("\u00A0\u00A0\u00A0"));
var config = document.createElement('div');
config.id = "trademanager_output";
config.style.display = "none";
config.className = "collection_filters";
config.innerHTML = "<div class=\"collectionfilter_commandbar\">"+
"<a href=\"javascript://\" onclick=\"$('trademanager_config').style.display='none';\"><img style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/cross.png\" alt=\"Close Trade Manager Output\" border=\"0\"></a> "+
"Kempeth's Trade Manager Output"+
"</div>"+
"<style type=\"text/css\">"+
".markup { display: inline-block; max-width: 0; max-height: 0; overflow:hidden }"+
"</style>"+
"<div class=\"collectionfilter_body\">"+
"<table id=\"tradeoutput_type\" class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td colspan=\"2\"><b>Geeklist</b></td></tr>"+
"<tr><td>Geeklist Type</td><td width=\"100%\"><select id=\"trade_geeklisttype\"><option>Math Trade</option><option>Auction</option></select></td></tr>"+
"<tr><td>Geeklist ID</td><td width=\"100%\"><input id=\"trade_geeklistid\" type=\"number\" title=\"The id of the geeklist you're going to post this to. Optional\"></td></tr>"+
"</tbody></table>"+
"<table id=\"tradeoutput_shipping\" class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td colspan=\"2\"><b>Shipping</b></td></tr>"+
"<tr><td>No Shipping?</td><td width=\"100%\"><input id=\"trade_isnoshipping\" type=\"checkbox\" title=\"Check this if all items are handed over in person instead of being shipped.\"></td></tr>"+
"<tr><td>Your Share</td><td><input id=\"trade_yourshare\" type=\"number\" title=\"This is the amount of shipping you cover. For auctions this is typically zero. But for Math Trades this is usually the equivalent of the cheapest shipping for the eligible trade area.\"></td></tr>"+
"<tr><td>Handover</td><td><textarea id=\"trade_handover\" title=\"This is where you can specify when and where you're available to hand over the games in no shipping exchanges.\"></textarea></td></tr>"+
"</tbody></table>"+
"<table id=\"tradeoutput_auction\" class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td colspan=\"2\"><b>Auction</b></td></tr>"+
"<tr><td>Custom End Date</td><td width=\"100%\"><input id=\"trade_auctionenddate\" type=\"date\" title=\"Some auctions have a predetermined end date. Others leave it up to you. To skip this, set it to a date in the past.\"></td></tr>"+
"<tr><td>Custom End Time</td><td><input id=\"trade_auctionendtime\" type=\"text\" title=\"Most people prefer to say 'random time' because it prevents sniping and leaves them flexible to end the auction when they have time.\"></td></tr>"+
"<tr><td>Payment Types</td><td><input id=\"trade_paymenttypes\" type=\"text\" size=\"100\" title=\"Which kind of payment types you accept.\"></td></tr>"+
"</tbody></table>"+
"</div>" +
"<div id=\"tradeoutput\"></div>";
parent.appendChild(config);
// Wire unit settings
bindInputToStorage('trade_currency', KEY_UNIT_CURRENCY, units, 'currency');
bindInputToStorage('trade_weight', KEY_UNIT_WEIGHT, units, 'weight');
bindInputToStorage('trade_size', KEY_UNIT_SIZE, units, 'size');
// Wire packaging settings
var addpackaging = document.getElementById('trade_addpackaging');
addpackaging.onclick = () => {
addPackagesRow(packagings.length);
};
for (var id = 0; id < packagings.length; id++)
{
addPackagesRow(id);
}
// Wire packaging settings
var addshipping = document.getElementById('trade_addshipping');
addshipping.onclick = () => {
addShippingRow(shippings.length);
};
for (id = 0; id < shippings.length; id++)
{
addShippingRow(id);
}
}
function addConfigUI() {
var parent = document.getElementById('columnfilter').parentNode;
var toggle = document.createElement('a');
toggle.href="javascript://";
toggle.innerText = "Trade Config »";
toggle.title = "Configue Kempeth's Trade Manager";
toggle.setAttribute("onclick", "Toggle( 'trademanager_config' );");
parent.getElementsByTagName('span')[0].appendChild(toggle);
parent.getElementsByTagName('span')[0].appendChild(document.createTextNode("\u00A0\u00A0\u00A0"));
var config = document.createElement('div');
config.id = "trademanager_config";
config.style.display = "none";
config.className = "collection_filters";
config.innerHTML = "<div class=\"collectionfilter_commandbar\">"+
"<a href=\"javascript://\" onclick=\"$('trademanager_config').style.display='none';\"><img style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/cross.png\" alt=\"Close Trade Manager Configuration\" border=\"0\"></a> "+
"Kempeth's Trade Manager"+
"</div>"+
"<style type=\"text/css\">"+
".markup { display: inline-block; max-width: 0; max-height: 0; overflow:hidden }"+
"</style>"+
"<div class=\"collectionfilter_body\">"+
"<table id=\"trade_packaging\" class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td colspan=\"6\"><b>Packaging</b>"+
" <a href=\"javascript://\" id=\"trade_addpackaging\"><img style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/add.png\" title=\"Add new packaging\" border=\"0\"></a>"+
"</td></tr>"+
"<tr><td>Name</td><td>Weight</td><td>Cost</td><td>Internal Size</td><td>External Size</td><td>Commands</td></tr>"+
"</tbody></table>"+
"<table id=\"trade_shipping\" class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td colspan=\"6\">"+
"<b>Shipping</b>"+
" <img id=\"trade_addshipping\" style=\"bottom:2px; position:relative;\" src=\"https://cf.geekdo-static.com/images/icons/silkicons/add.png\" title=\"Add new shipping\" border=\"0\">"+
"</td></tr>"+
"<tr>"+
"<td width=\"200\">Name</td><td>Destinations</td>"+
"<td width=\"100\" title=\"the maximum size a package may have for this shipping rate.\">Max. Dimensions</td>"+
"<td width=\"100\" title=\"if there is a restriction on the sum of all package dimensions. 0 means no restriction.\">Max. Sum</td>"+
"<td width=\"100\">Max. Weight</td><td width=\"100\">Cost</td><td colspan=\"2\">Commands</td></tr>"+
"</tbody></table>"+
"<table class=\"collfilter_table\" style=\"margin-top:5px;\" width=\"100%\"><tbody>"+
"<tr><td><b>Units</b></td></tr>"+
"<tr>"+
"<td width=\"100\"><b><label class=\"fwn\" for=\"trade_currency\">Currency</label></b></td>"+
"<td><input type=\"text\" id=\"trade_currency\" /></td>"+
"</tr>"+
"<tr>"+
"<td width=\"100\"><b><label class=\"fwn\" for=\"trade_weight\">Weight</label></b></td>"+
"<td><input type=\"text\" id=\"trade_weight\" /></td>"+
"</tr>"+
"<tr>"+
"<td width=\"100\"><b><label class=\"fwn\" for=\"trade_size\">Size</label></b></td>"+
"<td><input type=\"text\" id=\"trade_size\" /></td>"+
"</tr>"+
"</tbody></table>"+
"<p>Item parameters need to be included in the private information comment in the following format:<br/><code>${<br/>"+
"\"value\": <i>a value for the item</i>,<br/>"+
"\"dimensions\": [<i>a comma separated list of dimensions, ordered from longest to shortest</i>],<br/>"+
"\"weight\": <i>the physical weight of the game</i>,<br/>"+
"$}</code><br/>"+
"For example <code>${ \"value\": 25, \"dimensions\": [274,190,67], \"weight\":0.59 }$</code> means you value this game at EUR 25, that it is 274x190x67mm in size and weighs 0.59kg (assuming you configured the tool with EUR, mm and kg under <b>Units</b>).</p>"+
"</div>";
parent.appendChild(config);
// Wire unit settings
bindInputToStorage('trade_currency', KEY_UNIT_CURRENCY, units, 'currency');
bindInputToStorage('trade_weight', KEY_UNIT_WEIGHT, units, 'weight');
bindInputToStorage('trade_size', KEY_UNIT_SIZE, units, 'size');
// Wire packaging settings
var addpackaging = document.getElementById('trade_addpackaging');
addpackaging.onclick = () => {
addPackagesRow(packagings.length);
};
for (var id = 0; id < packagings.length; id++)
{
addPackagesRow(id);
}
// Wire packaging settings
var addshipping = document.getElementById('trade_addshipping');
addshipping.onclick = () => {
addShippingRow(shippings.length);
};
for (id = 0; id < shippings.length; id++)
{
addShippingRow(id);
}
}
function createItemOutput(row)
{
}
function fetchForTradeCollection()
{
//https://boardgamegeek.com/xmlapi2/collection?username=Kempeth&trade=1&showprivate=1&version=1
var request = new XMLHttpRequest();
request.open("GET", "https://boardgamegeek.com/xmlapi2/collection?username=" + username + "&trade=1&showprivate=1&version=1", true);
request.send(null);
request.onreadystatechange = function() {
if (request.readyState == 4)
{
//console.log(request.responseText);
createListOutput(request.responseXML);
}
};
}
function xpathToArray(xpathResult)
{
var res = [];
if (xpathResult.resultType == XPathResult.ORDERED_NODE_SNAPSHOT_TYPE || xpathResult.resultType == XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE)
{
for (var r = 0; r < xpathResult.snapshotLength; r++)
{
res.push(xpathResult.snapshotItem(r));
}
}
return res;
}
function createListOutput(xml)
{
//console.log(xml);
var items = xml.documentElement.getElementsByTagName('item');
//console.log(items);
var xpathItems = xml.evaluate( "./item", xml.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
console.log(xpathItems);
for (var i = 0; i < xpathItems.snapshotLength; i++)
{
var item = xpathItems.snapshotItem(i);
if (item.getAttribute('objecttype') == 'thing')
{
//console.log(item.innerHTML);
var bggid = item.getAttribute('objectid');
var name = xml.evaluate( "./name", item, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.innerHTML;
var version = xml.evaluate( "./version/item", item, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
var thumbnail = xml.evaluate( "./thumbnail", item, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.innerHTML;
var thumbnailid = thumbnail.match(/\/pic(\d+)?\./)[1];
if (version != null)
{
var versionid = version?.getAttribute('id');
var versionname = xml.evaluate( "./name", version, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue?.getAttribute('value');
var languages = xpathToArray(xml.evaluate( "./link[@type='language']", version, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null )).map(l => l.getAttribute('value'));
thumbnail = xml.evaluate( "./thumbnail", item, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.innerHTML;
thumbnailid = thumbnail.match(/\/pic(\d+)?\./)[1];
}
//console.log(name, bggid, versionname, versionid, languages);
console.log(name, bggid, thumbnail, thumbnailid);
var row = document.createElement('table');
row.style.padding = "0.5em";
row.style.margin = "0.5em";
row.style.border = "1px solid silver";
row.style.width = "100%";
var html = "<tbody><tr>";
// Floating Image
html += "<td valign=\"top\"><div style=\"width: 100px; height: 100px; text-align: center;\"><img style=\"max-width: 100%; max-height: 100%\" src=\"" + thumbnail + "\"></div></td>";
html += "<td width=\"100%\">";
// Item Title
html += "<div style=\"font-size: 20pt; font-weight: bold\">" + name + "</div>";
// Output condition
if (true)
{
html += "<span style=\"font-size: 15pt\"><b>Condition:</b> " + "Unknown" + "</span>" +
"<img src=\"https://cf.geekdo-static.com/images/star_yellow.gif\">"+
"<img src=\"https://cf.geekdo-static.com/images/star_white.gif\">"+
"<img src=\"https://cf.geekdo-static.com/images/star_yellow.gif\">"+
"<img src=\"https://cf.geekdo-static.com/images/star_white.gif\">"+
"<img src=\"https://cf.geekdo-static.com/images/star_yellow.gif\">"
if (true)
{
html += "(" + "no comment" + ")";
}
html += "<br><br>";
}
// Output version
if (version != null)
{
html += "<b>Version:</b> <a href=\"https://boardgamegeek.com/boardgameversion/" + versionid + "\">" + versionname + "</a><br>";
html += "<b>Languages:</b> " + languages.join(', ') + "<br>";
html += "<b>Language dependency:</b> " + "Unspecified" + "<br>";
html += "<br>";
}
// additional information
// images
// auction parameters
// shipping / handover
html += "</td></tr></tbody>";
row.innerHTML = html;
document.getElementById('tradeoutput').append(row);
}
}
}
(function() {
'use strict';
addConfigUI();
addOutputUI();
// Your code here...
//alert("initializing trade helper");
var list = document.getElementById('collectionitems');
var rows = list.getElementsByTagName('tr');
for (var r = 0; r < rows.length; r++)
{
var row = rows[r];
if (row.id)
{
var privateinfo = row.getElementsByClassName('collectiontable_ownership');
//console.log(privateinfo);
var html = privateinfo.length > 0 ? privateinfo[0].innerHTML : null;
//console.log(html);
var match = html != null ? html.match(/\$\{.+\}\$/) : null;
//console.log(match);
var data = {weight:0, packweight:0, dimensions:[0,0,0]};
if (match)
{
data = match[0];
data = data.substring(1, data.length - 1);
//console.log(data);
data = JSON.parse(data);
//console.log(data);
var objectname = row.getElementsByClassName('collection_objectname')[0].getElementsByTagName('a')[0].innerText;
var possibleParcels = packagings
.filter(p => p.inner[0] > data.dimensions[0] && p.inner[1] > data.dimensions[1] && p.inner[2] > data.dimensions[2])
.sort((a, b) => a.outer[0] + a.outer[1] + a.outer[2] - b.outer[0] - b.outer[1] - b.outer[2]);
if (possibleParcels.length > 0)
{
var packaging = possibleParcels[0];
var totalweight = data.weight + packaging.weight;
var possibleShippings = shippings
.filter(shipping => eligible(packaging, shipping));
//display: inline-block; max-width: 0; max-height: 0; overflow:hidden
var adhtml = "";
adhtml += "<b>" + objectname + "</b><span class=\"markup\">this is hidden</span><br />";
adhtml += "<b>Parcel:</b> " + possibleParcels[0].name + " (" + parseFloat(possibleParcels[0].cost).toFixed(2) + " " + units.currency + ")<br />";
adhtml += "<b>Total weight:</b> " + Math.round(totalweight*1000)/1000 + units.weight + " ... " + Math.round(totalweight*1.25*1000)/1000 + units.weight + "<br/>";
possibleShippings.forEach(shipping => {
var orderedtiers = shipping.tiers.filter(t => t.maxweight > totalweight * 1.25).sort((a, b) => a.maxweight - b.maxweight);
if (orderedtiers.length > 0)
{
var lightesttier = orderedtiers[0];
adhtml += "<b>" + shipping.name + "</b> (" + shipping.destinations + ")<br/>" + lightesttier.cost.toFixed(2) + " " + units.currency + "<br/>";
}
});
}
}
//console.log(adhtml);
row.innerHTML += "<td>" + adhtml + "</td>";
}
else if (row.parentNode == list || row.parentNode.parentNode == list)
{
//row.parentNode.removeChild(row);
}
}
})();
var f_getUsername = function()
{
var el_username = document.getElementsByClassName("mygeek-dropdown-username");
//console.log(el_username);
if (el_username.length < 1)
{
//console.log('.');
window.setTimeout(f_getUsername, 100);
}
else
{
el_username = el_username.item(0);
//console.log(el_username);
//console.log(el_username.innerText);
username = el_username.innerText;
fetchForTradeCollection();
}
}
f_getUsername();