Ahab / City lists

// ==UserScript==
// @name         City lists
// @namespace    torn.com
// @version      1.7
// @author       Ahab [1735214]
// @license      MIT
// @updateURL    https://openuserjs.org/meta/Ahab/City_lists.meta.js
// @match        https://www.torn.com/city.php
// @run-at       document-body
// @grant        GM_addStyle
// @grant        GM.xmlHttpRequest
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @require      https://gist.githubusercontent.com/BrockA/2625891/raw/9c97aa67ff9c5d56be34a55ad6c18a314e5eb548/waitForKeyElements.js
// @require      https://raw.githubusercontent.com/lostandconfused/test/master/count.js
// @require      https://jpillora.com/xhook/dist/xhook.js
// ==/UserScript==


GM_addStyle(`
table {
  text-align: center;
  width: 100%;
  table-layout: auto;
  border-style: hidden;
}

tbody:not(#idata).tab tr:nth-child(odd) {
  background-color: var(--default-bg-panel-active-color);
}

thead{
  font-size: 130%;
  font-weight: bold;
}

.tab tr, .tab td, .tab th, .cell {
  border: 1px solid var(--default-panel-divider-outer-side-color)!important;
  vertical-align: middle!important;
  padding: 5px!important;
  color: var(--default-qlinks-color);
}

#wdata tr td:nth-child(1) {
    width: 100px;
}

#wdata tr td:nth-child(3) {
    width: 206px;
}

.tab a:hover, #listSelections span:hover, thead.tab th:hover, .symPane:hover, .cell:hover, #warProgress:hover{
  color: var(--default-blue-hover-color)!important
}

#listSelections span, thead.tab, .symPane, .cell, #warProgress{
  cursor: pointer
}

.tab a, #warProgress{
  color:var(--default-blue-color);
  text-decoration: none;
  margin-top: 1px
}

.activetab{
  display: inline-table
}

.inactive{
  display: none
}

.selectedtab{
  color: #5f9ea0
}

.addTime{
  padding: 3px;
  width: 100%
}

.wImg{
    align-items: center;
    justify-content: center;
    display: flex;
    left: 15px;
    position: relative
}

#rImg{
  margin-top: 1px;
  width: 25px;
  padding-left: 5px;
  left: 3px;
  position: relative
}

.advantage-bar {
    width: 100%;
    height: 5px;
    display: table;
    border-radius: 100px;
    margin-bottom: 4px;
    margin-top: 5px
}

.advantage-bar .your {
    display: table-cell;
    background: #a3d900;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2EzZDkwMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM2OThjMDAiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    background: -webkit-linear-gradient(top,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    background: linear-gradient(to bottom,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    border-radius: 100px 0 0 100px;
    position: relative
}

.advantage-bar .your:nth-child(2) {
    border-radius: 0 100px 100px 0
}

.advantage-bar .enemy {
    display: table-cell;
    background: #ff7a4d;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmN2E0ZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNkOTM2MDAiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    background: -webkit-linear-gradient(top,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    background: linear-gradient(to bottom,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    border-radius: 0 100px 100px 0;
    position: relative
}

.advantage-bar .enemy:nth-child(1) {
    border-radius: 100px 0 0 100px
}

.advantage-bar .your .animation, .advantage-bar .enemy .animation {
    height: 5px;
    width: 100%;
    position: relative;
    top: 0;
    left: 0;
    overflow: hidden
}

.advantage-bar .your .animation .arrows, .advantage-bar .enemy .animation .arrows {
    height: 5px;
    width: auto;
    position: relative;
    top: 0;
    left: -5px;
    background: url(/images/v2/faction/wars/progress_bar_arrows.png) 0 -30px repeat-x;
    -webkit-animation: advantage-bar-animation 30s linear .1s infinite normal;
    animation: advantage-bar-animation 30s linear .1s infinite normal;
    z-index: 8
}

.advantage-bar .enemy .animation .arrows {
    left: -5px
}

.advantage-bar .your:nth-child(2) .animation .arrows {
    left: 5px;
    background-position-y: -10px;
    -webkit-animation-direction: reverse;
    animation-direction: reverse;
    z-index: 8
}

.advantage-bar .enemy:nth-child(1) .animation .arrows {
    left: 5px;
    background-position-y: -20px;
    -webkit-animation-direction: normal;
    animation-direction: normal;
    z-index: 8
}

.advantage-bar .your .animation:before, .advantage-bar .your .animation:after {
    content: "";
    display: block;
    position: absolute;
    left: auto;
    right: 0;
    top: 0;
    height: 5px;
    width: 15px;
    background: url(/images/v2/faction/wars/progress_bar_pointer.png) 0 -15px no-repeat
}

.advantage-bar .your .animation:after {
    background: #ff7a4d;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmN2E0ZCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNkOTM2MDAiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    background: -webkit-linear-gradient(top,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    background: linear-gradient(to bottom,rgba(255,122,77,1) 0%,rgba(217,54,0,1) 100%);
    z-index: 5
}

.advantage-bar .your .animation:before {
    z-index: 6
}

.advantage-bar .your:nth-child(2) .animation:before {
    right: auto;
    left: 0;
    background: url(/images/v2/faction/wars/progress_bar_pointer_2.png) 0 -15px no-repeat
}

.advantage-bar .your:nth-child(2) .animation:after {
    right: auto;
    left: 0
}

.advantage-bar .enemy .animation .arrows {
    background-position-y: 0;
    -webkit-animation: advantage-bar-animation 30s linear .1s infinite reverse;
    animation: advantage-bar-animation 30s linear .1s infinite reverse;
    z-index: 7
}

.advantage-bar .enemy .animation:before, .advantage-bar .enemy .animation:after {
    content: "";
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    height: 5px;
    width: 15px;
    background: url(/images/v2/faction/wars/progress_bar_pointer.png) 0 0 no-repeat
}

.advantage-bar .enemy .animation:after {
    background: #a3d900;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2EzZDkwMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM2OThjMDAiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    background: -webkit-linear-gradient(top,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    background: linear-gradient(to bottom,rgba(163,217,0,1) 0%,rgba(105,140,0,1) 100%);
    z-index: 5
}

.advantage-bar .enemy .animation:before {
    z-index: 6
}

.advantage-bar .enemy:nth-child(1) .animation:before {
    right: 0;
    left: auto;
    background: url(/images/v2/faction/wars/progress_bar_pointer_2.png) 0 0 no-repeat
}

.advantage-bar .enemy:nth-child(1) .animation:after {
    right: 0;
    left: auto
}

.advantage-bar .enemy:nth-child(1) .animation .arrows {
    left: -5px
}

@-webkit-keyframes advantage-bar-animation {
    0% {
        background-position-x: 0
    }

    100% {
        background-position-x: 1000px
    }
}

@keyframes advantage-bar-animation {
    0% {
        background-position-x: 0
    }

    100% {
        background-position-x: 1000px
    }
}
@keyframes advantage-bar-animation {
    0% {
        background-position-x: 0
    }

    100% {
        background-position-x: 1000px
    }
}
`)

var city = {}

xhook.after(function(request, response) {
    if(request.url.match(/&step=mapData/)){
        city = JSON.parse(response.data);
        waitForKeyElements(".leaflet-layer", build)
    }
})

function build(){
    if(!localStorage.hasOwnProperty("mapApi")){
        $($('ul[class*="map-symbols"]')[0].previousElementSibling).append('<span id=apiAsk class="symPane" data-att=0 style="float:right; margin-right:10px;">Add api key</span>')
        $($('ul[class*="map-symbols"]')[0].previousElementSibling).append('<span id=apiAsk class="symPane" style="display:none; float:right; margin-right:10px;">Change api key</span>')
    }else{
        $($('ul[class*="map-symbols"]')[0].previousElementSibling).append('<span id=apiAsk class="symPane" style="float:right; margin-right:10px;">Change api key</span>')
    }
    $('span[id*="apiAsk"]').on('click', function(){
        var apiKey = localStorage.setItem("mapApi", prompt("Enter api key"))
        if(this.attributes[2].nodeValue == 0){
            $('span[id*="apiAsk"]').toggle()
        }
    })
    $($('ul[class*="map-symbols"]')[0].previousElementSibling).append(' - <span id="hideLeaf" class="symPane">Hide all</span>')
    $($('ul[class*="map-symbols"]')[0].previousElementSibling).append('<span id="hideLeaf" class="symPane" style="display:none">Show all</span>')
    if($('input[id*="view-switcher"]')[0].checked == true){
        var racket = {}
        var territories = {}
        var items = sorti('title',JSON.parse(atob(city.territoryUserItems)))
        $('div[class*="territory-info-toggle"]').before('<div id=listcont><div id=listSelections class="title-black top-round m-top10"><span id=select name=items class="selectedtab">Items </span> / <span id=select name=rackets>Rackets </span> / <span id=select name=wars>Wars</span></div><table id=items name=table class="cont-gray10 bottom-round activetab"><thead class="tab"><tr><th id=type colspan=6>Items</th></tr><tbody id=idata class="tab" style="display:block;"></tbody></table><table id=rackets name=table class="cont-gray10 bottom-round inactive"><thead class="tab"><tr><th id=type>Type</th><th id=level>Level</th><th id=description>Description</th><th id=ter>Territory</th><th id=owner>Owner</th></tr></thead><tbody id=rdata class="tab"></tbody></table><table id=wars name=table class="cont-gray10 bottom-round inactive"><thead class="tab"><tr><th id=territory>Territory</th><th id=attacker>Attacker</th><th>Progress</th><th id=defender>Defender</th></tr></thead><tbody id=wdata class="tab"></tbody></table></div>')
        $.each(torn.get('collection'), function(i, v){
            if(this.factionID){
                racket[parseInt(this.path.attributes[0].nodeValue)] = [this.factionID]
            }
            else{
                racket[parseInt(this.path.attributes[0].nodeValue)] = ['na']
            }
        })
        $.each(territories_shapes, function(i, v){
            territories[this[4]] = this[9]
        })
        $.each(standard_shapes, function(i, v){
            territories[this[4]] = this[9]
        })
        $.each(city.rackets, function(i, v){
            racket[city.rackets[i].territoryID].push('true',city.rackets[i].typeName,city.rackets[i].level,city.rackets[i].description)
            $('tbody[id*="rdata"]').append('<tr><td>'+city.rackets[i].typeName+'</td><td>'+city.rackets[i].level+'</td><td>'+city.rackets[i].description+'</td><td><a id="flink" href="https://www.torn.com/city.php#terrName='+territories[city.rackets[i].territoryID]+'">'+territories[city.rackets[i].territoryID]+'</td><td>'+torn.getFactionName(racket[city.rackets[i].territoryID][0])+'</td></tr>')
        })
        if(items.length > 0){
            $.each(items, function(i, v){
                $('tbody[id*="idata"]').append('<tr style="display:inline-block; border:none!important"><td class="cell" data-id='+[i]+' style="border: none!important">'+items[i].title+'</td></tr>')
            })
        }
        if(localStorage.hasOwnProperty("mapApi") && localStorage.getItem("mapApi").length > 0 ){
            var getapiData = new Promise((resolve, reject) => {
                var apiData = getAction({
                    type: "GET",
                    action: "https://api.torn.com/torn/?selections=territorywars&key="+localStorage.getItem("mapApi"),
                })
                resolve(apiData)
            })
            Promise.all([getapiData]).then(([apiData]) => {
                if(apiData.hasOwnProperty("error")){
                    alert('Error code - '+apiData.error.code+"  | "+apiData.error.error)
                }else{
                    $.each(city.factionOwnTerritories.terrInWars, function(i, v){
                        if(localStorage.getItem("mapApi").length > 0 && !apiData.hasOwnProperty("error")){
                            var cdt = new Date(JSON.parse(apiData)['territorywars'][territories[city.factionOwnTerritories.terrInWars[i].territoryID]].ends*1000).toLocaleString("en-US", {timeZone: 'UTC'})
                            $($('td[data-ids*="'+city.factionOwnTerritories.terrInWars[i].territoryID+'"]')).prepend('<div class="addTime" data-countdown="'+cdt+'"></div>')
                        }
                    })
                }
                $('[data-countdown]').each(function() {
                    var $this = $(this), finalDate = $(this).data('countdown');
                    $this.countd(finalDate, function(event) {
                        $this.html(event.strftime('%D:%H:%M:%S'));
                    })
                })
            })
        }
        $.each(city.factionOwnTerritories.terrInWars, function(i, v){
            if(racket[city.factionOwnTerritories.terrInWars[i].territoryID][1] == 'true'){
                $('tbody[id*="wdata"]').append('<tr><td><span class=wImg><a id="flink" href="https://www.torn.com/city.php#terrName='+territories[city.factionOwnTerritories.terrInWars[i].territoryID]+'">'+territories[city.factionOwnTerritories.terrInWars[i].territoryID]+'</a><img id=rImg src="images/v2/city/citymap/rackets/street_surgeon_level_5.svg" title="<b>'+racket[city.factionOwnTerritories.terrInWars[i].territoryID][2]+' '+racket[city.factionOwnTerritories.terrInWars[i].territoryID][3]+'</b><br>'+racket[city.factionOwnTerritories.terrInWars[i].territoryID][4]+'"><td>'+torn.getFactionName(city.factionOwnTerritories.terrInWars[i].attackFaction)+'</td><td data-ids='+city.factionOwnTerritories.terrInWars[i].territoryID+'><div id=warProgress data-id='+city.factionOwnTerritories.terrInWars[i].territoryID+' style="margin-bottom: 1px">Show progress bar</div></td><td>'+torn.getFactionName(city.factionOwnTerritories.terrInWars[i].defendFaction)+'</span></td></tr>')
            }else{
                $('tbody[id*="wdata"]').append('<tr><td><a id="flink" href="https://www.torn.com/city.php#terrName='+territories[city.factionOwnTerritories.terrInWars[i].territoryID]+'">'+territories[city.factionOwnTerritories.terrInWars[i].territoryID]+'</a><td>'+torn.getFactionName(city.factionOwnTerritories.terrInWars[i].attackFaction)+'</td><td data-ids='+city.factionOwnTerritories.terrInWars[i].territoryID+'><div id=warProgress data-id='+city.factionOwnTerritories.terrInWars[i].territoryID+' style="margin-bottom: 1px">Show progress bar</div></td><td>'+torn.getFactionName(city.factionOwnTerritories.terrInWars[i].defendFaction)+'</td></tr>')
            }
        })
        $('div[id*="warProgress"]').on('click', function(){
            var getUpdate = new Promise((resolve, reject) => {
                var update = getAction({
                    type: "POST",
                    action: "war.php",
                    data: {
                        step: 'getWarInfo',
                        terr: $(this)[0].attributes[1].nodeValue
                    }
                })
                resolve(update)
            })
            Promise.all([getUpdate]).then(([update]) => {
                if($($(this)[0].parentNode).find('.addTime').length == 1){
                    $($(this)[0].parentNode).find('.addTime').wrap('<div id="terrIcons" style="display: flex; align-items: center"></div>')
                    $($(this)[0].parentNode).find('#terrIcons').prepend('<div style="display: inline-flex; align-items: center; min-width: 37px"><i class="faction-attacking"></i>'+JSON.parse(update).count1+'</div>')
                    $($(this)[0].parentNode).find('#terrIcons').append('<div style="display: inline-flex; align-items: center; min-width: 37px; justify-content: flex-end">'+JSON.parse(update).count2+'<i class="faction-defending" style="background-position-y: -9px;"></i></div>')
                }else{
                    $($(this)[0].parentNode).prepend('<div id="terrIcons" style="display: flex; align-items: center"><div style="display: inline-flex; align-items: center; min-width: 37px"><i class="faction-attacking"></i>'+JSON.parse(update).count1+'</div><div class="addTime"></div><div style="display: inline-flex; align-items: center; min-width: 37px; justify-content: flex-end">'+JSON.parse(update).count2+'<i class="faction-defending" style="background-position-y: -9px;"></i></div></div>')
                }
                var diff = Math.abs(JSON.parse(update).count1 - JSON.parse(update).count2);
                var arrowSpeed = (diff >= 5 ? 'fast' : (diff >= 3 ? 'medium' : (diff >= 1 ? 'slow' : '')))
                $($(this)[0].parentNode).append('<div class="advantage-bar" data-terrId='+$(this)[0].attributes[1].nodeValue+'><div id=eAdd class="enemy" style="width: '+JSON.parse(update).scorePercent+'%"></div><div id=yAdd class="your"></div></div>')
                if(JSON.parse(update).count1 > JSON.parse(update).count2){
                    $($('div[data-terrId*="'+$(this)[0].attributes[1].nodeValue+'"]')[0].children[0]).append('<div class="animation '+arrowSpeed+'"><div class="arrows"></div></div>')
                }else{
                    $($('div[data-terrId*="'+$(this)[0].attributes[1].nodeValue+'"]')[0].children[1]).append('<div class="animation '+arrowSpeed+'"><div class="arrows"></div></div>')
                }
                $(this).remove()
            })
        })
        $('span[id*="select"]').on('click', function(){
            $('span[id*="select"]').removeClass('selectedtab')
            $(this).addClass('selectedtab')
            $('table[name*="table"]').removeClass('activetab').addClass('inactive');
            $('table[id*="'+$(this)[0].attributes[1].nodeValue+'"]').addClass('activetab').removeClass('inactive')
        })
        document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
            sort(th)
        })))
        $('a[id*="flink"]').on('click', function(){
            document.documentElement.scrollTop = 0
        })
        $('tbody[id*="idata"]').find('td').on('click', function(){
            var td = $(this)
            const XHR = new XMLHttpRequest(),
                  data = new FormData();
            data.append('td', btoa(items[$(this)[0].attributes[1].nodeValue].c['x']+'O'+items[$(this)[0].attributes[1].nodeValue].c['y']+'O'+items[$(this)[0].attributes[1].nodeValue].id+'O'+items[$(this)[0].attributes[1].nodeValue].ts));
            data.append('step', 'uif');
            XHR.addEventListener('load', function(event) {
                if(JSON.parse(event.target.response)['success'] == true){
                    td[0].textContent = td[0].textContent+' Picked Up'
                    td.css("color","#008000")
                    setTimeout(() => {td[0].parentElement.remove(); }, 2000);
                }
            });
            XHR.addEventListener('error', function(event) {
                console.log(event);
            });
            XHR.open('POST', 'https://www.torn.com/city.php?rfcv=undefined');
            XHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
            XHR.send(data);
        })
        sort(document.querySelector("#level"))
    }else{
        $('div[class*="territory-info-toggle"]').before('<div id=alert><div class="white-grad border-round m-top10 p10">Enable full map and refresh for lists</div>')
    }
    $('span[id*="hideLeaf"]').on('click', function(){
        $('img[class*="standard-object-marker"]').toggle();
        $('span[id*="hideLeaf"]').toggle()
    })
}

function sorti (prop, arr) {
    prop = prop.split('.');
    var len = prop.length;

    arr.sort(function (a, b) {
        var i = 0;
        while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });
    return arr;
};

function sort(th){
    const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
    const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2))(getCellValue(asc ? b : a, idx), getCellValue(asc ? a : b, idx));
    const table = th.closest('table');
    const tbody = table.querySelector('tbody');
    Array.from(tbody.querySelectorAll('tr'))
        .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
        .forEach(tr => tbody.appendChild(tr) );
}