// ==UserScript==
// @name [TORN] OC 2.0 Helper
// @namespace Violentmonkey Scripts
// @match https://www.torn.com/*
// @version 5
// @author callmericky [3299880] / whatdoesthespacebardo
// @description Adds a list of members available for OC2.0, and adds a notifier to the sidebar if you are not in an OC.
// @require http://code.jquery.com/jquery-3.6.0.min.js
// @grant GM_registerMenuCommand
// @grant GM.setValue
// @grant GM.getValue
// @license GNU GPLv3
// ==/UserScript==
/*
* All edits can be done from the dropdown menu from your userscript extension
*/
//IF DROPDOWN MENU DOESN'T WORK, MANUALLY ADD YOUR API KEY HERE
var APIKey = "";
const PDA_APIKey = "###PDA-APIKEY###"
/*
* STOP CHANGING THINGS FROM HERE
*/
//fix for tampermonkey
var $ = window.jQuery;
let memberInfo = {};
let pageURL = $(location).attr("href");
let totalMembers = 0;
let availableMembers = 0;
let activeMembers = 0;
let userInfo = {};
let crimeListUninitiated = []
let crimeListRecruiting = []
let crimeListPlanning = []
let crimeList = []
let availMemberList = []
let myAPIData = null
let itemIDObj = {}
let containerMaxWidth = "784px"
let containerBigMaxWidth = "976px"
let userSettings = {}
let displayIgnoreList = [ ]
var alreadyLoading = false
var OC2_timerID = null
var membersButtonShowText = (`⏵`) //⏵ ⏵
var membersButtonHideText = (`⏷`) //⏷ ⏷
if (isPDA()) {
membersButtonShowText = (`▶`) //▶ ▶
membersButtonHideText = (`▼`) //▼ ▼
}
const crimeButtonShowText = (`Show Crimes`)
const crimeButtonHideText = (`Hide Crimes`)
const lazyMembersButtonShowText = (`Show Members`)
const lazyMembersButtonHideText = (`Hide Members`)
const settingsButtonAscText = (`▴`) //▴ ▴
const settingsButtonDescText = (`▾`) // ▾ ▾
const defaultUserSettings = {
"memberShow": "member-show",
"crimesShow": "crimes-hide",
"sortType": "time-asc", //time-asc / time-desc / level-asc / level-desc
"memberSort": "OC-desc", //OC-asc / OC-desc / active-asc / active-desc
"lastOC_yellow": 24,
"lastOC_red": 48,
"lastActivity": 96,
"memberIgnoreList": [ ]
}
let _isWindowNormal = window.matchMedia("(min-width: 1000px)")
let _isWindowSmallish = window.matchMedia("(min-width: 785px)")
let _isWindowSmall = window.matchMedia("(max-width: 784px) and (min-width: 387px)")
let _isWindowTiny = window.matchMedia("(max-width: 386px)")
let colorObj = {
"dark_bg_link": {
"darkmode": "rgb(116, 192, 252)",
"lightmode": "rgb(116, 192, 252)"
},
"link": {
"darkmode": "rgb(116, 192, 252)",
"lightmode": "#006699"
},
"recolor": {
"green": {
"darkmode": "rgb(130, 201, 30)",
"lightmode": "rgb(92, 148, 13)"
},
"yellow": {
"darkmode": "rgb(252, 196, 25)",
"lightmode": "rgb(252, 196, 25)"
},
"red": {
"darkmode": "rgb(255, 135, 135)",
"lightmode": "rgb(224, 49, 49)"
},
"blue": {
"darkmode": "rgb(59, 201, 219)",
"lightmode": "rgb(12, 133, 153)"
}
},
"userindicatorbg": {
"darkmode": "rgb(63, 68, 45)",
"lightmode": "rgb(238, 241, 228)"
},
"footerbg": {
"darkmode": "rgb(51, 51, 51)",
"lightmode": "rgb(242, 242, 242)"
},
"crimeselectbg": {
"darkmode": "rgba(0,0,0,0.2)",
"lightmode": "rgba(150,150,150,0.1)"
},
"fancyBg": {
"darkmode": "inherit",
"lightmode": "#fff"
},
"inactiveIcon": {
"default": {
"lightmode": "rgba(100, 100, 100, 0.5)",
"darkmode": "rgba(221, 221, 221, 0.5)"
},
"highlightRed": {
"lightmode": "rgba(255, 135, 135, 0.8)",
"darkmode": "rgba(255, 135, 135, 0.8)"
}
},
"crimeIcon": {
"default": {
"lightmode": "rgba(100, 100, 100, 0.5)",
"darkmode": "rgba(221, 221, 221, 0.5)"
},
"highlightYellow": {
"lightmode": "rgb(230, 180, 0)",
"darkmode": "rgba(252, 196, 25, 0.8)"
},
"highlightRed": {
"lightmode": "rgba(255, 135, 135, 1)",
"darkmode": "rgba(255, 135, 135, 0.8)"
},
"highlightVeryRed": {
"lightmode": "rgba(200, 33, 33, 1)",
"darkmode": "rgba(200, 33, 33, 1)"
}
},
"buttons": {
"background": {
"lightmode": "linear-gradient(rgb(255, 255, 255) 0%, rgb(221, 221, 221) 100%)",
"darkmode": "linear-gradient(rgb(85, 85, 85) 0%, rgb(51, 51, 51) 100%)"
},
"textcolor": {
"lightmode": "rgb(102, 102, 102)",
"darkmode": "rgb(221, 221, 221)"
},
"hovercolor": {
"lightmode": "rgb(200,200,200)",
"darkmode": "rgb(28,28,28)"
}
}
}
let colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode"
function getUserID() {
let _profileLink = $(".settings-menu > .link > a")[0]
let _matchregex = /profiles\.php.+XID=(\d+)/i
let _userID = _matchregex.exec(_profileLink)
userInfo.id = _userID[1]
return _userID[1]
}
//user settings functions
if (!isPDA()) {
const menu_command_1 = GM_registerMenuCommand("Open Settings Page", showSettingsPage)
}
function showSettingsPage() {
window.open("https://www.torn.com/OC2_Settings_Page", "_blank")
}
async function getAPIKey() {
if (isPDA()) {
APIKey = PDA_APIKey
return PDA_APIKey
} else if (APIKey != null && APIKey.length > 0) {
return APIKey
} else {
return await GM.getValue("CMR_OC2_APIKey", null)
.then(function(data) {
APIKey = data
return data
})
}
}
async function setUserSettings(_settings) {
if (!_settings) {
return
}
if (isPDA()) {
localStorage.setItem("CMR_OC2_userSettings", JSON.stringify(_settings))
if ( $("#OC2-APIInput").val().length > 5 && $("#OC2-APITestResult-Final").hasClass("color-green") ) {
localStorage.setItem("CMR_OC2_APIKey", $("#OC2-APIInput").val())
}
return
} else {
await GM.setValue("CMR_OC2_userSettings", JSON.stringify(_settings))
}
if ( $("#OC2-APIInput").val().length > 5 && $("#OC2-APITestResult-Final").hasClass("color-green") ) {
await GM.setValue("CMR_OC2_APIKey", $("#OC2-APIInput").val())
}
}
async function getUserSettings(event) {
if (isPDA()) {
if (!localStorage.getItem("CMR_OC2_userSettings")) {
userSettings = defaultUserSettings
} else {
userSettings = JSON.parse(localStorage.getItem("CMR_OC2_userSettings"))
}
return
}
return await GM.getValue("CMR_OC2_userSettings", JSON.stringify(defaultUserSettings))
.then( (data) => {
userSettings = JSON.parse(data)
})
}
//boolean logic functions
function isPDA() {
const PDATestRegex = !/^(###).+(###)$/.test(PDA_APIKey);
return PDATestRegex;
}
function checkCrimesPage() {
let pageURL = $(location).attr("href")
return ((pageURL.search("step=your") >= 0) && (pageURL.search("tab=crimes") >= 0))
}
async function checkTravelFactionPage() {
let pageURL = $(location).attr("href")
if ( ($('body').attr("data-traveling") == "true") || ($('body').attr("data-traveling") == true) || ($('body').attr("data-abroad") == "true") || ($('body').attr("data-abroad") == true) ) {
if (!myAPIData) {
await getAndAnalyzeAPIData()
}
if (pageURL.search("ID="+myAPIData.basic.id) >= 0) {
return true;
}
}
return false;
}
//API call functions
async function getAndAnalyzeAPIData() {
return await $.ajax({
dataType: "json",
url: (`https://api.torn.com/v2/faction/basic,crimes,members?cat=available,completed&offset=0&striptags=true&comment=OC2-helper`),
headers: {
Authorization: (`ApiKey ${APIKey}`)
}
}).done( data => {
if (data.error) {
return data
}
checkMembersInCrimes(data)
myAPIData = data
return data
}).fail( (error) => {
return error
})
}
async function getItemNamesFromID(_arrayOfIds) {
return await $.getJSON(`https://api.torn.com/torn/${_arrayOfIds.toString()}?selections=items&key=${APIKey}&comment=OC2-helper`)
}
//calculations and conversions
async function convertItemIDArrayToItems() {
let _arrayOfIDs = []
let _matchregex = /<\#(\d+)>/i
for (var _key of Object.keys(itemIDObj)) {
_arrayOfIDs.push(_key)
}
await getItemNamesFromID(_arrayOfIDs)
.then( (_data) => {
for (var _itemID of Object.keys(_data.items)) {
itemIDObj[_itemID].name = _data.items[_itemID].name
}
})
for (let i = 0; i < $(".OC2-tableCrimeMemberItem:has(*)").length; i++) {
let _oldTitle = $(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title")
let _regexResult = _matchregex.exec($(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title"))
let _newTitle = _oldTitle.replace(_matchregex, `${itemIDObj[_regexResult[1]].name} <$1>`)
$(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title", _newTitle)
}
}
function timestampDiff(laterTimestamp) {
var currentTimestamp = Math.floor(Date.now()/1000)
var _returnString = ""
var timeDiff = 0
var _highlightClass = ""
if (laterTimestamp > currentTimestamp) {
timeDiff = laterTimestamp - currentTimestamp
}
if (timeDiff < 43200) { //12 hours = 12 * 60 * 60 = 43200
_highlightClass = "OC2-highlightText"
}
let _d = timeDiff < 86400 ? 0 : Math.floor(timeDiff/86400)
let _h = timeDiff < 3600 ? 0 : Math.floor(timeDiff/3600) - _d*24 //24h in 1d
let _m = timeDiff < 60 ? 0 : Math.floor(timeDiff/60) - _h*60 - _d*1440 //60m in 1h, 1440m in 1d
let _s = timeDiff - _m*60 - _h*3600 - _d*86400 //60s in 1m, 3600s in 1h, 86400s in 1d
_returnString += `<span class="${_highlightClass}">${_d.toString().padStart(2,'0')}:${_h.toString().padStart(2,'0')}:${_m.toString().padStart(2,'0')}:${_s.toString().padStart(2,'0')}</span>`
return _returnString
}
function stringifyTimestampOld(_timeDiff) {
var currentTimestamp = Math.floor(Date.now()/1000)
var _returnString = ""
var _highlightClass = ""
if (_timeDiff == -1) {
return (`User has not joined the last ${myAPIData.crimes.length} OCs`)
}
let _d = _timeDiff < 86400 ? 0 : Math.floor(_timeDiff/86400)
let _h = _timeDiff < 3600 ? 0 : Math.floor(_timeDiff/3600) - _d*24 //24h in 1d
let _m = _timeDiff < 60 ? 0 : Math.floor(_timeDiff/60) - _h*60 - _d*1440 //60m in 1h, 1440m in 1d
let _s = _timeDiff - _m*60 - _h*3600 - _d*86400 //60s in 1m, 3600s in 1h, 86400s in 1d
_returnString = (`Last OC Joined:<br />`)
if (_d > 0) {
_returnString += (`${_d.toString().padStart(1,'0')}d `)
}
if (_d > 0 || _h > 0) {
_returnString += (`${_h.toString().padStart(2,'0')}h `)
}
if (_d > 0 || _h > 0 || _m > 0) {
_returnString += (`${_m.toString().padStart(2,'0')}m `)
}
_returnString += (`ago`)
return _returnString
}
function timestampOldDiff(olderTimestamp) {
var currentTimestamp = Math.floor(Date.now()/1000)
if (olderTimestamp == 0) {
return -1
}
return currentTimestamp - olderTimestamp //time since last OC in seconds
}
const timerTick = () => {
let _timeList = $("span.OC2-countdown")
for (let i = 0; i < _timeList.length; i++) {
$(_timeList[i]).html(timestampDiff(parseInt($(_timeList[i]).attr("data-countdown"))))
}
OC2_timerID = setTimeout(timerTick, 1000)
$(".OC2-highlightText").css({
"color": "rgb(252, 196, 25)",
"font-weight": "bold"
})
if ($("body").css("background-color") == "rgb(204, 204, 204)") {
$(".OC2-highlightText").css({
"color": "rgb(230, 119, 0)"
})
}
}
//the nitty gritty functions
function checkMembersInCrimes(_data) {
//put all member ids into a list
for (let i = 0; i < (_data.members).length; i++) {
if (_data.members[i].status.state == "Fallen") {
//skip fallen members
} else if (_data.members[i].position == "Recruit") {
//skip recruits since they can't join OC
} else {
memberInfo[_data.members[i].id] = {
"id": _data.members[i].id,
"name": _data.members[i].name,
"last_action": _data.members[i].last_action,
"statusDesc": _data.members[i].status.description,
"status": _data.members[i].status.state,
"lastCrime": 0
}
}
}
totalMembers = (_data.members).length;
activeMembers = 0 //if this doesn't reset, hashchange will cause the following part to re-fire and get activemembers count wrong.
//go through crime list
for (let i = 0; i < (_data.crimes).length; i++) {
if (_data.crimes[i].status == 'Expired') {
continue; //skip all expired crimes
}
//sort members into objects
if ((_data.crimes[i].status == 'Successful' || _data.crimes[i].status == 'Failure')) { //for crimes that were complete, put info into member's last crime completed section
for (let j=0; j<(_data.crimes[i].slots).length; j++) {
if (_data.crimes[i].slots[j].user_id) {
//ignore members that left the faction
if (!memberInfo[_data.crimes[i].slots[j].user_id]) {
continue
}
let _lastCrimeTime = _data.crimes[i].ready_at
if (_data.crimes[i].executed_at) { //take into account executed at, for crimes that were stalled
_lastCrimeTime = _data.crimes[i].executed_at
}
if (memberInfo[_data.crimes[i].slots[j].user_id].lastCrime < _lastCrimeTime) { //if the user's last crime completed is more recent than this crime's ready_at
memberInfo[_data.crimes[i].slots[j].user_id].lastCrime = _lastCrimeTime
}
}
}
}
if ((_data.crimes[i].status == 'Recruiting' || _data.crimes[i].status == 'Planning')) { //only
if (_data.crimes[i].planning_at) { //if crime is not initiated, it will be null for planning_at. No point looking for members because there won't be any.
for (let j=0; j<(_data.crimes[i].slots).length; j++) {
if (_data.crimes[i].slots[j].user_id) {
//ignore members that left the faction
if (!memberInfo[_data.crimes[i].slots[j].user_id]) {
continue
}
memberInfo[_data.crimes[i].slots[j].user_id].crimeInfo = {
"crimeName": _data.crimes[i].name,
"crimeDifficulty": _data.crimes[i].difficulty,
"crimeId": _data.crimes[i].id,
"crimePosition": _data.crimes[i].slots[j].position,
"crimeSuccess": _data.crimes[i].slots[j].success_chance,
}
activeMembers = activeMembers + 1;
if ((_data.crimes[i].slots[j].user_id) == getUserID()) {
userInfo = memberInfo[_data.crimes[i].slots[j].user_id]
userInfo.crimeInfo.crimeTime = _data.crimes[i].slots[j].ready_at
}
}
}
}
}
//sort crimes into arrays
//crimes in recruiting include both crimes with members (has planning_at and with no members (don't have planning_at)
if (_data.crimes[i].status == "Recruiting") {
//get crimes with no members
if (_data.crimes[i].planning_at == null) {
crimeListUninitiated.push(_data.crimes[i])
} else {
crimeListRecruiting.push(_data.crimes[i])
}
}
//crimes filled with members move to status = planning
if (_data.crimes[i].status == "Planning") {
crimeListPlanning.push(_data.crimes[i])
}
}
availableMembers = totalMembers - activeMembers;
}
function sortCrimeInfo() {
//remove all crime Lis
$(".OC2-memberViewer li.OC2-crimeLi").not(".OC2-memberViewer li[class*='OC2-titleLi']").remove()
$("li.OC2-crimeMemberLi").remove()
if (userSettings.sortType == "level-desc") {
crimeListUninitiated.sort( (a,b) => a.difficulty - b.difficulty)
crimeListRecruiting.sort( (a,b) => a.difficulty - b.difficulty)
crimeListPlanning.sort( (a,b) => a.difficulty - b.difficulty)
} else if (userSettings.sortType == "level-asc") {
crimeListUninitiated.sort( (a,b) => b.difficulty - a.difficulty)
crimeListRecruiting.sort( (a,b) => b.difficulty - a.difficulty)
crimeListPlanning.sort( (a,b) => b.difficulty - a.difficulty)
} else if (userSettings.sortType == "time-desc") { //asc and desc are swapped around. I don't know why but it works. Some math thing. I need to think about it.
crimeListUninitiated.sort( (a,b) => a.expired_at - b.expired_at)
crimeListRecruiting.sort( (a,b) => a.ready_at - b.ready_at)
crimeListPlanning.sort( (a,b) => a.ready_at - b.ready_at)
} else if (userSettings.sortType == "time-asc") {
crimeListUninitiated.sort( (a,b) => b.expired_at - a.expired_at)
crimeListRecruiting.sort( (a,b) => b.ready_at - a.ready_at)
crimeListPlanning.sort( (a,b) => b.ready_at - a.ready_at)
}
}
function sortAvailMembers() {
$("li.OC2-memberAvailable").remove()
if (userSettings.memberSort == "OC-asc") {
availMemberList.sort( (a,b) => b.lastCrime - a.lastCrime )
}
if (userSettings.memberSort == "OC-desc") {
availMemberList.sort( (a,b) => a.lastCrime - b.lastCrime )
}
if (userSettings.memberSort == "active-asc") {
availMemberList.sort( (a,b) => a.last_action.timestamp - b.last_action.timestamp )
}
if (userSettings.memberSort == "active-desc") {
availMemberList.sort( (a,b) => b.last_action.timestamp - a.last_action.timestamp )
}
}
function putAvailMembersIntoTable(_memberArray, _afterElm) {
if (_memberArray.length < 1) {
return //don't do anything if there are no members
}
let _ignoreTitleText = ""
_memberArray.forEach( (_member) => {
if (userSettings.memberIgnoreList) {
if (userSettings.memberIgnoreList.includes((_member.id).toString())) {
if (_ignoreTitleText == "") {
_ignoreTitleText = "Ignored members:"
}
_ignoreTitleText += `<br />${_member.name} [${_member.id}]`
return //skip member to be ignored
}
}
let _outputHTML = ""
let _memberHighlight = "OC2-memberAvailable"
let _memberInactiveTitle = `Last Action: ${_member.last_action.relative}`
let _memberInactiveFill = colorObj.inactiveIcon.default[colorDisplayMode]
let _memberCrimeFill = colorObj.crimeIcon.default[colorDisplayMode]
if (_member.id == userInfo.id) {
_memberHighlight += " OC2-userIndicator"
}
if (_member.lastCrime == 0) { //user is not found in the crimes obtained from the API
_memberCrimeFill = colorObj.crimeIcon.highlightVeryRed[colorDisplayMode]
}
if (timestampOldDiff(_member.lastCrime) > parseInt(userSettings.lastOC_yellow) * 60 * 60) {
_memberCrimeFill = colorObj.crimeIcon.highlightYellow[colorDisplayMode]
}
if (timestampOldDiff(_member.lastCrime) > parseInt(userSettings.lastOC_red) * 60 * 60) {
_memberCrimeFill = colorObj.crimeIcon.highlightRed[colorDisplayMode]
}
if ( (Math.floor(Date.now()/1000) - _member.last_action.timestamp) > parseInt(userSettings.lastActivity) * 60 * 60) {
_memberInactiveFill = colorObj.inactiveIcon.highlightRed[colorDisplayMode]
}
let _lastOnlineIcon = (`<svg xmlns="http://www.w3.org/2000/svg" stroke="transparent" stroke-width="0" width="11" height="11" viewBox="0 1 16 16"><g><path fill="${_memberInactiveFill}" d="M13.88,13.06c-2.29-.53-4.43-1-3.39-2.94C13.63,4.18,11.32,1,8,1S2.36,4.3,5.51,10.12c1.07,2-1.15,2.43-3.39,2.94C.13,13.52,0,14.49,0,16.17V17H16v-.83C16,14.49,15.87,13.52,13.88,13.06Z"></path></g></svg>`)
let _lastCrimeIcon = (`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11" height="11" viewBox="0 0 30 40"><path fill="${_memberCrimeFill} "d="M397,168c-7.573,0-15,5.76-15,13.333,0,4.589,3.375,10.129,6.512,14.524a10.05,10.05,0,0,1,16.935-.067c3.22-4.457,6.553-9.865,6.553-14.457C412,173.76,404.573,168,397,168Zm-5.83,18.333a4.166,4.166,0,1,1,4.167-4.166A4.167,4.167,0,0,1,391.17,186.333Zm11.667,0A4.166,4.166,0,1,1,407,182.167,4.166,4.166,0,0,1,402.837,186.333ZM397,194.52a6.74,6.74,0,1,0,6.74,6.74A6.741,6.741,0,0,0,397,194.52Zm1.752,2.458a1.07,1.07,0,1,1-1.07,1.07A1.071,1.071,0,0,1,398.752,196.978Zm-3.574,0a1.07,1.07,0,1,1-1.068,1.07A1.071,1.071,0,0,1,395.178,196.978Zm-1.918,5.35a1.07,1.07,0,1,1,1.07-1.07A1.071,1.071,0,0,1,393.26,202.328Zm1.918,3.212a1.069,1.069,0,1,1,1.07-1.07A1.07,1.07,0,0,1,395.178,205.54Zm.752-4.28a1.07,1.07,0,1,1,1.07,1.07A1.071,1.071,0,0,1,395.93,201.26Zm2.822,4.28a1.069,1.069,0,1,1,1.07-1.07A1.071,1.071,0,0,1,398.752,205.54Zm1.988-3.212a1.07,1.07,0,1,1,1.07-1.07A1.069,1.069,0,0,1,400.74,202.328Z" transform="translate(-382 -168)"></path></svg>`)
_outputHTML = (`<li class="table-cell ${_memberHighlight}">
<div class="OC2-tableCell OC2-tableLastCrime OC2-lazyCountup" title="${stringifyTimestampOld(timestampOldDiff(_member.lastCrime))}" data-countup="${timestampOldDiff(_member.lastCrime)}"><span>${_lastCrimeIcon}</span></div>
<div class="OC2-tableCell OC2-tableLastActive" title="${_memberInactiveTitle}"><span class="">${_lastOnlineIcon}</span></div>
<div class="OC2-tableCell OC2-tableMember" title="MemberName<br />Last OC joined: xd xxh xxm ago<br />Last online: xx minutes ago"><a href="https://www.torn.com/profiles.php?XID=${_member.id}"><span>${_member.name}</span></a></div>
<div class="OC2-tableCell OC2-tableStatus">${styleMemberStatus(_member.status,_member.statusDesc)}</div>
</li>`)
_afterElm.after(_outputHTML)
})
$(".OC2-memberTableFooter").not(".OC2-settingsFooter").html(`${availableMembers} / ${totalMembers} members available <span title="${_ignoreTitleText}">(${userSettings.memberIgnoreList.length} member${userSettings.memberIgnoreList.length == 1 ? "":"s"} manually ignored)</span>`)
}
function putMemberInfoIntoTable() {
//fix for tornPDA, idk why but checking the li.tablecell works but checking the ul.table doesn't
if ($(".OC2-memberTable .OC2-tableCell")[0]) {
return
}
availMemberList = []
for (var _key of Object.keys(memberInfo)) {
if (memberInfo[_key].crimeInfo) {
continue //skip all members in crimes
}
availMemberList.push(memberInfo[_key])
}
sortAvailMembers()
putAvailMembersIntoTable(availMemberList, $(".OC2-memberTable li.OC2-titleLiAvailableMembers"))
sortCrimeInfo()
putCrimeInfoIntoTable(crimeListUninitiated, $(".OC2-memberTable li.OC2-titleLiUninitiated").eq(0))
putCrimeInfoIntoTable(crimeListRecruiting, $(".OC2-memberTable li.OC2-titleLiRecruiting").eq(0))
putCrimeInfoIntoTable(crimeListPlanning, $(".OC2-memberTable li.OC2-titleLiPlanning").eq(0))
convertItemIDArrayToItems()
styleTable()
checkDefaultHideState()
if (OC2_timerID) {
clearTimeout(OC2_timerID)
}
timerTick()
}
function putCrimeInfoIntoTable(_crimeArray, _afterElm) {
let _countdownText = ""
let _countdownToTimestamp = ""
let _countdownMouseover = ""
let _memberOutputHTML = ""
let _userIndicatorClass = ""
let _userIndicatorCrimeClass = ""
if (_crimeArray.length > 0) {
for (let i = 0; i < _crimeArray.length; i++) {
//crimes in recruiting include both crimes with members (has planning_at) and with no members (don't have planning_at)
if (_crimeArray[i].status == "Recruiting") {
//get crimes with no members
if (_crimeArray[i].planning_at == null) {
_countdownText = "Expires: "
_countdownToTimestamp = _crimeArray[i].expired_at
_countdownMouseover = "Time until this crime is no longer be available"
} else {
_countdownText = "Join in:"
_countdownToTimestamp = _crimeArray[i].ready_at
_countdownMouseover = "Time until this crime needs a new member to join to continue planning"
}
}
//crimes filled with members move to status = planning
if (_crimeArray[i].status == "Planning") {
_countdownText = "Ready in:"
_countdownToTimestamp = _crimeArray[i].ready_at
_countdownMouseover = "Time until this crime is ready to start"
}
_memberOutputHTML = ""
_userIndicatorCrimeClass = ""
let _memberCount = 0
//count number of slots filled
for (let j = 0; j < (_crimeArray[i].slots).length; j++) {
let _crimeSlotMemberName = `<span class="OC2-textGray"> N/A</span>`
let _crimeSlotMemberID = ""
let _crimeSlotMemberStatus = ""
let _crimeSlotPosition = ""
let _crimeItem = ""
let _crimeItemMouseover = ""
let _crimeItemIcon = (`🛠`) //🛠 🛠
if (isPDA()) {
_crimeItemIcon = (`⚒`) // ⚒ $#9874;
}
let _crimeSuccess = ""
let _crimeSuccessWrapper = ""
_userIndicatorClass = ""
if (_crimeArray[i].slots[j].item_requirement) {
if(!(_crimeArray[i].slots[j].item_requirement.id in itemIDObj)) {
itemIDObj[_crimeArray[i].slots[j].item_requirement.id] = {
"name": ""
};
}
_crimeItemMouseover = (`Required item: <#${_crimeArray[i].slots[j].item_requirement.id}>`)
if (_crimeArray[i].slots[j].item_requirement.is_reusable) {
_crimeItemMouseover += (` (reusable)`)
_crimeItemIcon += (`<span style="vertical-align:top">∞</span>`)
}
if (_crimeArray[i].slots[j].item_requirement.is_available) {
_crimeItemMouseover += (`<br />Item is owned by member`)
}
_crimeItem = (`<span class="OC2-itemHave${_crimeArray[i].slots[j].item_requirement.is_available}">${_crimeItemIcon}</span>`)
}
if (_crimeArray[i].slots[j].user_id) {
if (_crimeArray[i].slots[j].user_id == userInfo.id) {
_userIndicatorClass = "OC2-userIndicator"
_userIndicatorCrimeClass = "OC2-userIndicator"
}
_memberCount = _memberCount + 1
_crimeSlotMemberName = `<a href="https://www.torn.com/profiles.php?XID=${_crimeArray[i].slots[j].user_id}">${memberInfo[_crimeArray[i].slots[j].user_id].name}</a>`
_crimeSlotMemberStatus = styleMemberStatus(memberInfo[_crimeArray[i].slots[j].user_id].status, memberInfo[_crimeArray[i].slots[j].user_id].statusDesc)
if (_crimeArray[i].slots[j].success_chance > 75) {
_crimeSuccessWrapper = "OC2-highSuccess"
} else if (_crimeArray[i].slots[j].success_chance > 50) {
_crimeSuccessWrapper = "OC2-midSuccess"
} else {
_crimeSuccessWrapper = "OC2-lowSuccess"
}
_crimeSuccess = (`<span class="${_crimeSuccessWrapper}">${_crimeArray[i].slots[j].success_chance}</span>`)
} else {
_crimeSuccess = (`<span class="OC2-textGray">-</span>`)
}
_memberOutputHTML += (`<li class="table-cell OC2-crimeMemberLi OC2-crimeID_${_crimeArray[i].id} ${_userIndicatorClass}">
<div class="OC2-tableCell OC2-tableCrimeMemberSuccess">${_crimeSuccess}</div>
<div class="OC2-tableCell OC2-tableCrimeMemberItem" title="${_crimeItemMouseover}" >${_crimeItem}</div>
<div class="OC2-tableCell OC2-hideSmall OC2-tableCrimePosition">${_crimeArray[i].slots[j].position}</div>
<div class="OC2-tableCell OC2-tableCrimeMemberName">${_crimeSlotMemberName}</div>
<div class="OC2-tableCell OC2-tableCrimeMemberStatus">${_crimeSlotMemberStatus}</div>
</li>`)
}
let _outputHTML = (`<li class="table-cell OC2-crimeLi OC2-crimeID_${_crimeArray[i].id} ${_userIndicatorCrimeClass}">
<div class="OC2-tableCell OC2-tableCrimeMemberCount OC2-crimeID_${_crimeArray[i].id}">${_memberCount} / ${(_crimeArray[i].slots).length} <span class="hideMembersButton">${membersButtonShowText}</span></div>
<div class="OC2-tableCell OC2-tableCrime"><a href="https://www.torn.com/factions.php?step=your&type=12#/tab=crimes&crimeId=${_crimeArray[i].id}">Lv${_crimeArray[i].difficulty} ${_crimeArray[i].name}</a></div>
<div class="OC2-tableCell OC2-tableCountdown OC2-crimeID_${_crimeArray[i].id}" title="${_countdownMouseover}"><span class="OC2-countdownText OC2-hideSmall">${_countdownText}</span> <span class="OC2-countdown" data-countdown="${_countdownToTimestamp}">${_countdownToTimestamp}</span></div>
</li>`)
_afterElm.after(_outputHTML)
$("li.OC2-crimeID_"+_crimeArray[i].id).after(_memberOutputHTML)
$("div.OC2-crimeID_"+_crimeArray[i].id).off().on("click", (event) => {
toggleMemberView(((event.currentTarget.attributes.class.value).split("OC2-crimeID_"))[1])
if ($(event.currentTarget).parent(".OC2-crimeLi").hasClass("OC2-crimeLiActive")) {
$(event.currentTarget).parent(".OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive")
} else {
$(event.currentTarget).parent(".OC2-crimeLi").not(".OC2-crimeLiActive").addClass("OC2-crimeLiActive")
}
styleCrimeLiActive()
}).css({"cursor": "pointer"})
}
} else {
_afterElm.after(`<li class="table-cell OC2-crimeLi"><div class="OC2-tableCell OC2-tableCrime">None</div></li>`)
}
}
//templating functions
async function generateInsertHTML() {
if ($(".OC2-memberViewer .OC2-memberTable")[0]) {
return
}
let _insertHTML = (`
<div class="category-wrap OC2-memberViewer m-top10">
<div class="title-black top-round t-overflow">OC 2.0 Overview <a href="https://www.torn.com/OC2_Settings_Page" target="_new"><span title="Go to Settings Page" class="extraSettingsButton">⚙</span></a><span class="hideLazyMembersButton">${lazyMembersButtonShowText}</span><span class="hideCrimesButton">${crimeButtonShowText}</span></div>
<div class="cont-gray OC2-memberTableErrorDisplay" style="display:none; padding: 5px 0"></div>
<div class="cont-gray OC2-memberTable" style="display:none"><ul class="table-body">
<li class="table-cell OC2-availableMembers OC2-titleLiAvailableMembers"><div class="OC2-titleCell OC2-fancyBg">Members not in an OC<div class="OC2-sortTypeMember">Sort: <div id="sortOCButton">OC</div><div id="sortActiveButton">active</div></div></div></li>
<li class="table-cell OC2-crimeLi OC2-titleLiCrimeSeciton"><div class="OC2-titleCell OC2-fancyBg">Crimes<div class="OC2-sortType">Sort: <div id="sortLevelButton">level</div><div id="sortTimeButton">time</div></div></div></li>
<li class="table-cell OC2-crimeLi OC2-titleLiUninitiated"><div class="OC2-titleCell">Uninitiated Crimes</div></li>
<li class="table-cell OC2-crimeLi OC2-horizLine"></li>
<li class="table-cell OC2-crimeLi OC2-titleLiRecruiting"><div class="OC2-titleCell">Recruiting Crimes</div></li>
<li class="table-cell OC2-crimeLi OC2-horizLine"></li>
<li class="table-cell OC2-crimeLi OC2-titleLiPlanning"><div class="OC2-titleCell">Full Crimes</div></li>
</ul></div>
<div class="OC2-memberTableFooter"></div>
</div>`)
//what to do in normal crimes2.0 page
if (checkCrimesPage()) {
$("div#faction-crimes").before(_insertHTML)
checkDefaultSortState()
styleTable()
$(".hideCrimesButton").off().on("click", event => {
toggleCrimeView()
})
$(".OC2-sortType div").off().on("click", event => {
resortCrimeTable(event.currentTarget)
})
$(".OC2-sortTypeMember div").off().on("click", event => {
resortAvailMemberTable(event.currentTarget)
})
$(".hideLazyMembersButton").off().on("click", event => {
toggleLazyMembersView()
})
} else //this "else" is important to like the two if statements. Without it, it won't load on the faction -> crimes OC page because the second if statement takes precidence due to await
//what to do if traveling AND on faction page
if (await checkTravelFactionPage()) {
waitForElm('div#react-root').then((elm) => {
$(elm).before(_insertHTML)
checkDefaultSortState()
styleTable()
$(".hideCrimesButton").off().on("click", event => {
toggleCrimeView()
})
$(".OC2-sortType div").off().on("click", event => {
resortCrimeTable(event.currentTarget)
})
$(".OC2-sortTypeMember div").off().on("click", event => {
resortAvailMemberTable(event.currentTarget)
})
$(".hideLazyMembersButton").off().on("click", event => {
toggleLazyMembersView()
})
})
}
}
function checkDefaultHideState() {
$(".OC2-memberTable").show()
if (userSettings.memberShow == "member-hide") {
$(".hideLazyMembersButton").html(lazyMembersButtonShowText)
$(".OC2-availableMembers").hide()
$(".OC2-memberAvailable").hide()
} else {
$(".hideLazyMembersButton").addClass("text-hide")
$(".hideLazyMembersButton").html(lazyMembersButtonHideText)
}
if (userSettings.crimesShow == "crimes-hide") {
$(".hideCrimesButton").html(crimeButtonShowText)
$(".OC2-crimeMemberLi").hide()
$(".OC2-crimeLi").hide()
} else {
$(".hideCrimesButton").addClass("text-hide")
$(".hideCrimesButton").html(crimeButtonHideText)
$(".OC2-crimeMemberLi").hide();
}
}
function checkDefaultSortState() {
//userSettings.memberSort "OC-desc", //OC-asc / OC-desc / active-asc / active-desc
//userSettings.sortType "time-asc", //time-asc / time-desc / level-asc / level-desc
let _memberTarget = userSettings.memberSort.split("-")[0]
let _memberDirection = userSettings.memberSort.split("-")[1]
let _crimeTarget = userSettings.sortType.split("-")[0]
let _crimeDirection = userSettings.sortType.split("-")[1]
_memberTarget = _memberTarget[0].toUpperCase() + _memberTarget.slice(1)
_crimeTarget = _crimeTarget[0].toUpperCase() + _crimeTarget.slice(1)
let _arrowDisplayMember = settingsButtonAscText
let _arrowDisplayCrime = settingsButtonAscText
if (_memberDirection == "desc") {
_arrowDisplayMember = settingsButtonDescText
}
if (_crimeDirection == "desc") {
_arrowDisplayCrime= settingsButtonDescText
}
$(`.OC2-sortTypeMember div[id=sort${_memberTarget}Button]`).addClass("text-underline")
$(`.OC2-sortTypeMember div[id=sort${_memberTarget}Button]`).html(`${_memberTarget.toLowerCase()}${_arrowDisplayMember}`)
$(`.OC2-sortType div[id=sort${_crimeTarget}Button]`).addClass("text-underline")
$(`.OC2-sortType div[id=sort${_crimeTarget}Button]`).html(`${_crimeTarget.toLowerCase()}${_arrowDisplayCrime}`)
}
function insertOCNotifier() {
let _userNotice = (`<a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span class="OC2-redtext">No active OC.</span></a>`)
let _userMouseover = (`You are not currently participating in an OC.`)
if (userInfo.crimeInfo) {
_userNotice = (`<span class="OC2-normaltext"><a href="https://www.torn.com/factions.php?step=your&type=5#/tab=crimes&crimeId=${userInfo.crimeInfo.crimeId}">Lv ${userInfo.crimeInfo.crimeDifficulty} ${userInfo.crimeInfo.crimeName}</a></span>`)
_userMouseover = (`${userInfo.crimeInfo.crimePosition} (${userInfo.crimeInfo.crimeSuccess}%)`)
}
let _insertHTML = (`<div class="OC2-sidebarNotice" title="${_userMouseover}"><a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span style="font-weight: bold">OC 2.0:</span></a>
${_userNotice}
</div>`)
$('div[class^="sidebar_"] div[class^="user-information_"] div[class^="toggle-block_"] div[class^="toggle-content_"] div[class^="content_"]').append(_insertHTML)
styleOCNotifier()
}
//on click functions
function toggleCrimeView() {
if ($(".hideCrimesButton").hasClass("text-hide")) {
$(".hideCrimesButton").html(crimeButtonShowText)
$(".hideCrimesButton").removeClass("text-hide")
$(".OC2-crimeLi").slideUp()
} else {
$(".hideCrimesButton").html(crimeButtonHideText)
$(".hideCrimesButton").addClass("text-hide")
$(".OC2-crimeLi").slideDown()
}
$(".hideMembersButton").html(membersButtonShowText)
$(".hideMembersButton").removeClass("text-hide")
$(".OC2-crimeMemberLi").hide()
$(".OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive")
styleCrimeLiActive()
}
function toggleMemberView(_crimeID) {
if ($(".OC2-crimeID_"+_crimeID+" .hideMembersButton").hasClass("text-hide")) {
$(".OC2-crimeID_"+_crimeID+" .hideMembersButton").html(membersButtonShowText)
$(".OC2-crimeID_"+_crimeID+" .hideMembersButton").removeClass("text-hide")
$(".OC2-crimeMemberLi.OC2-crimeID_"+_crimeID).slideUp()
} else {
$(".OC2-crimeID_"+_crimeID+" .hideMembersButton").html(membersButtonHideText)
$(".OC2-crimeID_"+_crimeID+" .hideMembersButton").addClass("text-hide")
$(".OC2-crimeMemberLi.OC2-crimeID_"+_crimeID).slideDown()
}
}
//OC2-availableMembers
function toggleLazyMembersView() {
if ($(".hideLazyMembersButton").hasClass("text-hide")) {
$(".hideLazyMembersButton").html(lazyMembersButtonShowText)
$(".hideLazyMembersButton").removeClass("text-hide")
$(".OC2-availableMembers").slideUp()
$(".OC2-memberAvailable").slideUp()
} else {
$(".hideLazyMembersButton").html(lazyMembersButtonHideText)
$(".hideLazyMembersButton").addClass("text-hide")
$(".OC2-availableMembers").slideDown()
$(".OC2-memberAvailable").slideDown()
}
}
//<div class="OC2-sortType">Sort: <span id="sortLevelButton">level</span><span id="sortTimeButton">time</span></div>
function resortCrimeTable(_target) {
$(".OC2-sortType div").removeClass("text-underline")
$(".OC2-sortType div#sortLevelButton").html("level")
$(".OC2-sortType div#sortTimeButton").html("time")
$(_target).addClass("text-underline")
if ($(_target).attr("id") == "sortLevelButton") {
if (userSettings.sortType == "level-asc") {
userSettings.sortType = "level-desc"
$(_target).html(`level${settingsButtonDescText}`)
} else {
userSettings.sortType = "level-asc"
$(_target).html(`level${settingsButtonAscText}`)
}
}
if ($(_target).attr("id") == "sortTimeButton") {
if (userSettings.sortType == "time-asc") {
userSettings.sortType = "time-desc"
$(_target).html(`time${settingsButtonDescText}`)
} else {
userSettings.sortType = "time-asc"
$(_target).html(`time${settingsButtonAscText}`)
}
}
sortCrimeInfo()
putCrimeInfoIntoTable(crimeListUninitiated, $(".OC2-memberTable li.OC2-titleLiUninitiated").eq(0))
putCrimeInfoIntoTable(crimeListRecruiting, $(".OC2-memberTable li.OC2-titleLiRecruiting").eq(0))
putCrimeInfoIntoTable(crimeListPlanning, $(".OC2-memberTable li.OC2-titleLiPlanning").eq(0))
convertItemIDArrayToItems()
styleTable()
timerTick()
$("li.OC2-crimeLi .hideMembersButton").removeClass("text-hide")
$("li.OC2-crimeMemberLi").hide()
if ( !$(".hideLazyMembersButton").eq(0).hasClass("text-hide") ) {
$("li.OC2-availableMembers").hide()
$("li.OC2-memberAvailable").hide()
}
}
//<div class="OC2-sortTypeMember">Sort: <div id="sortOCButton">last OC</div><div id="sortActiveButton">last active</div></div>
function resortAvailMemberTable(_target) {
$(".OC2-sortTypeMember div").removeClass("text-underline")
$(".OC2-sortTypeMember div#sortOCButton").html("OC")
$(".OC2-sortTypeMember div#sortActiveButton").html("active")
$(_target).addClass("text-underline")
if ($(_target).attr("id") == "sortOCButton") {
if (userSettings.memberSort == "OC-asc") {
userSettings.memberSort = "OC-desc"
$(_target).html(`OC${settingsButtonAscText}`)
} else {
userSettings.memberSort = "OC-asc"
$(_target).html(`OC${settingsButtonDescText}`)
}
}
if ($(_target).attr("id") == "sortActiveButton") {
if (userSettings.memberSort == "active-desc") {
userSettings.memberSort = "active-asc"
$(_target).html(`active${settingsButtonAscText}`)
} else {
userSettings.memberSort = "active-desc"
$(_target).html(`active${settingsButtonDescText}`)
}
}
sortAvailMembers()
putAvailMembersIntoTable(availMemberList, $(".OC2-memberTable li.OC2-titleLiAvailableMembers"))
styleTable()
$("li.OC2-crimeLi .hideMembersButton").removeClass("text-hide")
$("li.OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive")
styleCrimeLiActive()
$("li.OC2-crimeMemberLi").hide()
if ( !$(".hideCrimesButton").eq(0).hasClass("text-hide") ) {
$("li.OC2-crimeLi").hide()
}
}
//prettifying functions
function styleCrimeLiActive() {
$(".OC2-crimeLi.OC2-crimeLiActive").not(".OC2-userIndicator").css({
"background-color": "rgba(150,150,150,0.2)"
})
$(".OC2-crimeLi").not(".OC2-crimeLiActive").not(".OC2-userIndicator").css({
"background-color": "transparent"
})
if ($("#dark-mode-state").prop("checked")) {
$(".OC2-crimeLi.OC2-crimeLiActive").not(".OC2-userIndicator").css({
"background-color": "rgba(0,0,0,0.3)"
})
}
}
function styleMemberStatus(_statusState, _statusDesc) {
return (`<span title="${_statusDesc}" class="OC2-statusText ${_statusState.toLowerCase()}">${_statusState}</span><span title="${_statusDesc}" class="OC2-statusText OC2-hideSmall ${_statusState.toLowerCase()}">${_statusDesc}</span>`)
}
function styleTable() {
/* notes to self
* Small: 386px
* Tiny: 320px
* Normal: 784px
*/
$(".OC2-memberTable ul.table-body").css({
"display": "flex",
"flex-direction": "row",
"flex-wrap": "wrap"
})
$(".OC2-memberTable a").css({
"color": colorObj.link[colorDisplayMode],
"text-decoration": "none"
})
$(".extraSettingsButton").css({
"color": colorObj.dark_bg_link[colorDisplayMode],
"text-decoration": "none"
})
$(".extraSettingsButton").on("mouseenter", function(event) {
$(event.currentTarget).css({
"color": colorObj.recolor.yellow[colorDisplayMode]
})
})
$(".extraSettingsButton").on("mouseleave", function(event) {
$(event.currentTarget).css({
"color": colorObj.dark_bg_link[colorDisplayMode]
})
})
$(".OC2-memberTable a").hover(
function() {
$(this).css({
"text-decoration": "underline"
})
},
function() {
$(this).css({
"text-decoration": "none"
})
})
$(".OC2-memberTable div.OC2-tableCrimeMemberName a").css({
"color": "inherit",
})
$(".OC2-memberTable div.OC2-tableMember a").css({
"color": "inherit",
})
$(".OC2-memberTable li.table-cell").css({
"display": "flex",
"flex-direction": "row",
})
$(".OC2-memberTable li.OC2-memberAvailable").css({
"font-weight": "normal",
})
$(".OC2-memberTable .OC2-textGray").css({
"color": "rgb(153, 153, 153)",
})
$(".OC2-memberTable div").css({
"font-size": "11px",
"line-height": "12px",
"padding": "5px 0"
})
$(".OC2-memberTable div.OC2-titleCell").css({
"display": "inline",
"font-family": "Fjalla One",
"padding-left": "10px",
"width": containerMaxWidth,
"box-sizing": "border-box",
})
$(".OC2-memberTable div.OC2-titleCell.OC2-fancyBg").css({
"background": "repeating-linear-gradient(90deg, #2e2e2e, #2e2e2e 2px, #282828 0, #282828 4px)",
"color": colorObj.fancyBg[colorDisplayMode]
})
$(".OC2-horizLine").css({
"border-bottom": "1px solid rgb(34,34,34)",
"width": containerMaxWidth,
"box-sizing": "border-box",
"height": "3px",
})
$(".OC2-memberTable div.OC2-tableLastCrime").css({
"width": "13px",
})
$(".OC2-memberTable div.OC2-tableLastActive").css({
"width": "15px",
})
$(".OC2-memberTable div.OC2-tableMember").css({
"width": "120px",
})
$(".OC2-memberTable div.OC2-tableStatus").css({
"width": "222px",
"text-align": "left"
})
//compact mode - COMING SOON
$(".OC2-memberTable div.OC2-tableMember.compact").css({
"width": "150px",
})
$(".OC2-memberTable div.OC2-tableStatus.compact").css({
"width": "150px",
"text-align": "center"
})
$(".OC2-statusText.okay").css({
"color": colorObj.recolor.green[colorDisplayMode]
})
$(".OC2-statusText.abroad, .OC2-statusText.traveling").css({
"color": colorObj.recolor.blue[colorDisplayMode]
})
$(".OC2-statusText.hospital").css({
"color": colorObj.recolor.red[colorDisplayMode]
})
$(".OC2-statusText.jail").css({
"color": colorObj.recolor.red[colorDisplayMode]
})
$(".OC2-memberTable div.OC2-tableStatus img").css({
"height": "11px"
})
$(".OC2-memberTable div.OC2-tableCrimeMemberCount").css({
"width": "50px",
})
$(".OC2-memberTable div.OC2-tableCrimePosition").css({
"width": "100px",
"font-size": "10px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberName").css({
"width": "230px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberStatus").css({
"width": "auto",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberSuccess").css({
"width": "25px",
"text-align": "center"
})
$(".OC2-memberTable div.OC2-tableCrimeMemberItem").css({
"width": "40px",
"text-align": "center"
})
$(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-highSuccess").css({
"color": colorObj.recolor.green[colorDisplayMode]
})
$(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-midSuccess").css({
"color": colorObj.recolor.yellow[colorDisplayMode]
})
$(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-lowSuccess").css({
"color": colorObj.recolor.red[colorDisplayMode]
})
$(".OC2-memberTable .OC2-itemHavetrue").css({
"color": colorObj.recolor.green[colorDisplayMode]
})
$(".OC2-memberTable .OC2-itemHavefalse").css({
"color": colorObj.recolor.red[colorDisplayMode]
})
$(".OC2-memberTable div.OC2-tableCrime").css({
"width": "337px",
})
$(".OC2-memberTable div.OC2-tableCountdown").css({
"width": "auto"
})
$(".OC2-memberTableFooter").css({
"border-radius": "0 0 5px 5px",
"background-color": colorObj.footerbg[colorDisplayMode],
"padding": "5px 5px 5px 10px",
"text-align": "center"
})
$(".hideCrimesButton").css({
"position": "absolute",
"right": "10px",
"cursor": "pointer"
})
$(".hideLazyMembersButton").css({
"position": "absolute",
"right": "100px",
"cursor": "pointer"
})
$(".OC2-memberTable li.OC2-memberAvailable").css({
"padding-left": "20px"
})
$(".OC2-memberTable li.OC2-crimeMemberLi").css({
"padding-left": "25px",
"background-color": colorObj.crimeselectbg[colorDisplayMode],
"width": containerMaxWidth
})
$(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({
"padding-left": "20px",
"width": containerMaxWidth
})
$(".OC2-crimeLi").prev(".OC2-crimeMemberLi").css({
"border-radius": "0 0 15px 15px"
})
$(".OC2-sortType").css({
"display": "inline-block",
"padding-left": parseInt(containerMaxWidth) - 158 + "px",
})
$(".OC2-sortType div").css({
"display": "inline-block",
"font-family": "Arial",
"padding": "0 0 0 5px",
"width": "35px"
})
$(".OC2-memberTable .OC2-sortType div").css({
"text-decoration": "none"
})
$(".OC2-memberTable .OC2-sortType div.text-underline").css({
"text-decoration": "underline"
})
$(".OC2-sortTypeMember").css({
"display": "inline",
"padding-left": parseInt(containerMaxWidth) - 220 + "px",
})
$(".OC2-sortTypeMember div").css({
"display": "inline-block",
"font-family": "Arial",
"padding": "0 0 0 5px",
"width": "35px"
})
$(".OC2-memberTable .OC2-sortTypeMember div").css({
"text-decoration": "none"
})
$(".OC2-memberTable .OC2-sortTypeMember div.text-underline").css({
"text-decoration": "underline"
})
$(".OC2-userIndicator").css({
"background-color": colorObj.userindicatorbg[colorDisplayMode]
})
if (_isWindowTiny.matches) {
styleTableTinyScreen()
} else if (_isWindowSmall.matches) {
styleTableSmallScreen()
} else {
styleTableBigScreen()
}
if (($(".OC2-crimeMemberLi").last().next()).length < 1) {
$(".OC2-crimeMemberLi").last().css({
"border-radius": "0 0 15px 15px",
})
}
}
function styleTableSmallScreen() {
//console.log("Smallscreen!")
//total row length: 386
//margins: 20px <item> 10px
//OC2-tableMember 260px
$(".OC2-memberTable li.OC2-memberAvailable").css({
"padding-left": "15px"
})
$(".OC2-hideSmall").css({
"display": "none"
})
$(".OC2-memberTable div.OC2-tableStatus").css({
"width": "55px",
"text-align": "left"
})
$(".OC2-memberTable div.OC2-tableMember").css({
"width": "120px",
})
$(".OC2-memberTable div.OC2-tableCrime").css({
"width": "210px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberName").css({
"width": "220px",
})
$(".OC2-statusText").not(".OC2-hideSmall").css({
"display": ""
})
$(".OC2-memberTable div.OC2-tableCrimePosition").css({
"width": "70px",
"font-size": "10px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberName").css({
"width": "220px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberStatus").css({
"width": "90px",
"text-align": "left"
})
$(".OC2-memberTable div.OC2-tableCrimeMemberSuccess").css({
"width": "18px",
"text-align": "center"
})
$(".OC2-memberTable div.OC2-tableCrimeMemberItem").css({
"width": "30px",
"text-align": "center"
})
}
function styleTableTinyScreen() {
//console.log("Tinyscreen!")
$(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({
"padding-left": "15px",
"width": containerMaxWidth
})
$(".OC2-hideSmall").css({
"display": "none"
})
$(".OC2-tableCrimeMemberCount").css({
"width": "40px"
})
$(".OC2-memberTable div.OC2-tableStatus").css({
"width": "90px",
"text-align": "left"
})
$(".OC2-memberTable div.OC2-tableCrime").css({
"width": "190px",
})
$(".OC2-memberTable div.OC2-tableCrimeMemberName").css({
"width": "165px",
})
$(".OC2-statusText").not(".OC2-hideSmall").css({
"display": ""
})
$(".OC2-memberTable li.OC2-crimeMemberLi").css({
"padding-left": "18px",
})
$(".OC2-memberTable li.OC2-memberAvailable").css({
"padding-left": "12px"
})
$(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({
"padding-left": "12px"
})
}
function styleTableBigScreen() {
$(".OC2-hideSmall").css({
"display": ""
})
$(".OC2-statusText").not(".OC2-hideSmall").css({
"display": "none"
})
}
function styleOCNotifier() {
$(".OC2-sidebarNotice a").css({
"text-decoration": "none",
"color": "inherit"
})
$(".OC2-sidebarNotice .OC2-redtext").css({
"text-decoration": "none",
"color": "rgb(255, 121, 76)"
})
}
//main functions
/* if page is the crimes 2.0 page
* -> if memberViewer table does NOT exist, get data and fill table
* -> otherwise, show the table
* -> otherwise, hide the table
*/
async function hashChangeFunction() {
if (checkCrimesPage()) {
if (!$(".OC2-memberViewer .OC2-memberTable")[0]) {
generateInsertHTML();
if (!myAPIData) {
try {
let _successfulGetAPIData = await getAndAnalyzeAPIData()
if (_successfulGetAPIData.error) {
$(".OC2-memberTable").hide()
$(".OC2-memberTableErrorDisplay").html(`<span style="margin-left: 20px">Error occured: ${_successfulGetAPIData.error.error}. Please visit the <a href="https://www.torn.com/OC2_Settings_Page" target="_new" style="color: inherit; font-weight: bold; text-decoration: underline">Settings Page</a> to set up an API key</span>`)
$(".OC2-memberTableErrorDisplay").show()
} else {
putMemberInfoIntoTable()
}
} catch(_err) {
console.log("hashchangefunction caught error:", _err)
return
}
} else {
if (alreadyLoading == false) {
putMemberInfoIntoTable()
}
}
} else {
$(".OC2-memberViewer").show()
}
} else {
if ($(".OC2-memberViewer .OC2-memberTable")[0]) {
$(".OC2-memberViewer").hide();
}
}
}
async function runOnceFunction() {
//load saved data
await getUserSettings()
await getAPIKey()
//prepare settings page if on correct URL
if ($(location).attr("pathname").search("OC2_Settings_Page") >= 0) {
$(document).prop('title', 'OC2 Overview - Settings | TORN');
$("div.main-wrap").removeClass("error-404")
$("div.content-title #skip-to-content").text("OC 2.0 Overview: Settings")
prepareSettingsPage()
getSavedValues()
settingsFillSelect()
}
//insert member overview
if (checkCrimesPage() || await checkTravelFactionPage()) {
if (!$(".OC2-memberViewer .OC2-memberTable")[0]) {
alreadyLoading = true;
generateInsertHTML()
if (!myAPIData) {
try {
let _successfulGetAPIData = await getAndAnalyzeAPIData()
if (_successfulGetAPIData.error) {
$(".OC2-memberTable").hide()
$(".OC2-memberTableErrorDisplay").html(`<span style="margin-left: 20px">Error occured: ${_successfulGetAPIData.error.error}. Please visit the <a href="https://www.torn.com/OC2_Settings_Page" target="_new" style="color: inherit; font-weight: bold; text-decoration: underline">Settings Page</a> to set up an API key</span>`)
$(".OC2-memberTableErrorDisplay").show()
} else {
putMemberInfoIntoTable()
}
} catch(_err) {
console.log("runOnceFunction caught error:", _err)
return
}
}
} else {
$(".OC2-memberViewer").show()
}
}
//sidebar notifier, but not if the sidebar doesn't exist
if ( ($("div[class*='sidebar_'][class*='desktop_']")[0]) && (!isPDA()) ) {
if (!myAPIData) {
let _successfulGetAPIData = await getAndAnalyzeAPIData()
if (_successfulGetAPIData.error) {
return
}
}
insertOCNotifier()
}
}
//taken from stackoverflow https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists because mutation observer confuses me
//needed because the faction page info only loads after the document is ready
function waitForElm(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
// If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
function checkWindowWidth() {
if (_isWindowNormal.matches) {
containerMaxWidth = "784px"
containerBigMaxWidth = "976px"
} else if (_isWindowSmallish.matches) {
containerMaxWidth = "784px"
containerBigMaxWidth = "578px"
}else if (_isWindowSmall.matches) {
containerMaxWidth = "386px"
containerBigMaxWidth = "578px"
} else if (_isWindowTiny.matches) {
containerMaxWidth = "320px"
containerBigMaxWidth = "320px"
}
if (!isPDA()) {
styleTable()
}
}
_isWindowNormal.addEventListener("change", function() {
checkWindowWidth()
});
_isWindowSmallish.addEventListener("change", function() {
checkWindowWidth()
});
_isWindowSmall.addEventListener("change", function() {
checkWindowWidth()
});
_isWindowTiny.addEventListener("change", function() {
checkWindowWidth()
});
checkWindowWidth()
runOnceFunction()
$(window).on('hashchange', hashChangeFunction)
$("#dark-mode-state").on('change', modeChangeFunction)
function modeChangeFunction() {
colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode"
styleTable()
checkDefaultHideState()
styleSettings()
}
/* ====
* Settings page stuff
* ====
*/
async function testAPIKey(_APIKey) {
$(".OC2-APITestResults div[id^=OC2-APITestResult-]").remove()
$(".OC2-APITestResults").append(`<div>Testing...</div>`)
let _insertHTML = ""
return await $.ajax({
dataType: "json",
url: (`https://api.torn.com/key/?selections=info&key=${_APIKey}`)
}).then( data => {
try {
let _testResults = {
"limited": data.access_level >= 2,
"basic": data.selections.faction.includes("basic"),
"crimes": data.selections.faction.includes("crimes"),
"members": data.selections.faction.includes("members"),
"items": data.selections.torn.includes("items"),
"final": false
}
_testResults.final = (_testResults.limited && _testResults.basic && _testResults.crimes && _testResults.members && _testResults.items)
let _insertHTML = (`
<div id="OC2-APITestResult-Limited" class="${_testResults.limited ? "color-green" : "color-red"}">Minimal Key (or higher) ${_testResults.limited ? "OK" : "X"}</div>
<div id="OC2-APITestResult-Basic" class="${_testResults.basic ? "color-green" : "color-red"}">/v2/factions/basic ${_testResults.basic ? "OK" : "X"}</div>
<div id="OC2-APITestResult-Crimes" class="${_testResults.crimes ? "color-green" : "color-red"}">/v2/factions/crimes ${_testResults.crimes ? "OK" : "X"}</div>
<div id="OC2-APITestResult-Members" class="${_testResults.members ? "color-green" : "color-red"}">/v2/factions/members ${_testResults.members ? "OK" : "X"}</div>
<div id="OC2-APITestResult-Items" class="${_testResults.items ? "color-green" : "color-red"}">/v1/torn/items ${_testResults.items ? "OK" : "X"}</div>
<div id="OC2-APITestResult-Final" class="${_testResults.final ? "color-green" : "color-red"}">${_testResults.final ? "API Key good to go! Save settings to enable Member Ignore List" : "API Key not usable!"}</div>
`)
$(".OC2-APITestResults div").remove()
$(".OC2-APITestResults").append(_insertHTML)
} catch(err) {
$(".OC2-APITestResults div").remove()
$(".OC2-APITestResults").append(`<div id="OC2-APITestResult-Fail" class="color-red">Error: API Key not valid</div>`)
}
$(".OC2-APITestResults div[id^=OC2-APITestResult-]").css({
"margin-left": "15px"
})
$("div[id^=OC2-APITestResult-].color-green").css({
"color": colorObj.recolor.green[colorDisplayMode]
})
$("div[id^=OC2-APITestResult-].color-red").css({
"color": colorObj.recolor.red[colorDisplayMode]
})
$(".OC2-APITestButton").off().on("click", (event) => {
APITestClickEvent(event)
})
})
}
async function setSavedValues() {
let _userValues = {
"memberShow": $("input[name=OC2-display-choice-availMembers]:checked")[0].value,
"crimesShow": $("input[name=OC2-display-choice-crimes]:checked")[0].value, //crimes-hide / crimes-show
"sortType": $("input[name=OC2-display-choice-crimes-sort]:checked")[0].value, //time-asc / time-desc / level-asc / level-desc
"memberSort": $("input[name=OC2-display-choice-availMembers-sort]:checked")[0].value, //OC-asc / OC-desc / active-asc / active-desc
"lastOC_yellow": $(`input[id=OC-indicator-yellow]`).val(),
"lastOC_red": $(`input[id=OC-indicator-red]`).val(),
"lastActivity": $(`input[id=activity-indicator]`).val(),
"memberIgnoreList": displayIgnoreList
}
await setUserSettings(_userValues)
await getUserSettings()
if ( $("#OC2-APITestResult-Final").hasClass("color-green") ) {
await saveAPIKey()
$("#OC2-addToIgnoreButton").show()
$("#OC2-ignoreMemberInput").prop("disabled", false)
$("#OC2-ignoreMemberSelect").prop("disabled", false)
$(".OC2-errorAPIKey").remove()
settingsFillSelect()
}
getSavedValues()
}
async function saveAPIKey() {
let _userKey = $("#OC2-APIInput").val()
await GM.setValue("CMR_OC2_APIKey", _userKey)
await getAPIKey()
}
async function replaceSavedValues() {
displayIgnoreList = []
userSettings = defaultUserSettings
getSavedValues()
}
function getSavedValues() {
$(`input[name=OC2-display-choice-availMembers][id=${userSettings.memberShow}]`).prop("checked", true)
$(`input[name=OC2-display-choice-crimes][id=${userSettings.crimesShow}]`).prop("checked", true)
$(`input[name=OC2-display-choice-crimes-sort][id=${userSettings.sortType}]`).prop("checked", true)
$(`input[name=OC2-display-choice-availMembers-sort][id=${userSettings.memberSort}]`).prop("checked", true)
$(`input[id=OC-indicator-yellow]`).val(userSettings.lastOC_yellow)
$(`input[id=OC-indicator-red]`).val(userSettings.lastOC_red)
$(`input[id=activity-indicator]`).val(userSettings.lastActivity)
fillMemberIgnoreList()
}
function APITestClickEvent(_event) {
$("#OC2-APIInput").val( $("#OC2-APIInput").val().trim() ) //trim trailing spaces
let _testKey = $("#OC2-APIInput").val()
testAPIKey(_testKey)
}
async function deleteAPIKey() {
$(".OC2-errorAPIKey").remove()
$(".OC2-APITestResults div").remove()
if (isPDA()) {
$(".OC2-APITestResults").append(`<div class="color-yellow">TornPDA: Unable to remove API Key via script because it's saved on TornPDA itself.</div>`)
return
}
GM.setValue("CMR_OC2_APIKey", null)
APIKey = null
$(".OC2-APITestResults").append(`<div class="color-red">API Key removed from script memory. If you wish to be sure that your API key is secure, delete the provided key from torn's settings page.</div>`)
$("#OC2-APIInput").val(APIKey? APIKey : "")
settingsFillSelect()
}
function prepareSettingsPage() {
let _displayAPIKey = "API Key saved in TornPDA"
if (!isPDA()) {
_displayAPIKey = APIKey? APIKey : ""
}
let _injectHTML = (`
<div id="OC2-Settings" class="category-wrap m-top10">
<div class="title-black top-round t-overflow">OC 2.0 Settings</div>
<div class="cont-gray OC2-settingsTable"><ul class="table-body">
<li class="table-cell OC2-settingsTitle"><div class="OC2-titleCell OC2-fancyBg">API Key</div></li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell"><input id="OC2-APIInput" type="textbox" style="line-height: 14px; padding: 10px 8px" value="${_displayAPIKey}" /><div id="OC2-APITestButton" class="OC2-button">Test API Key</div></div>
</li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell"><div id="OC2-deleteAPIKeyButton" class="OC2-button">Delete API Key</div></div>
</li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell OC2-APITestResults">
</div>
</li>
<li class="table-cell OC2-horizLine"></li>
<li class="table-cell OC2-memberAvailable OC2-settingsTitle"><div class="OC2-titleCell OC2-fancyBg">Preferences</div></li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell">
<div class="OC2-settingsSubTitle">Default View</div>
<fieldset class="OC2-choice">
<legend>Show "Members not in an OC" section?</legend>
<div class="OC2-choice-buttons">
<input type="radio" name="OC2-display-choice-availMembers" id="member-show" value="member-show" /><label for="member-show">Yes</label>
<input type="radio" name="OC2-display-choice-availMembers" id="member-hide" value="member-hide" /><label for="member-hide">No</label>
</div>
</fieldset>
<fieldset class="OC2-choice">
<legend>Default sort for "Members not in an OC"?</legend>
<div class="OC2-choice-buttons">
<input type="radio" name="OC2-display-choice-availMembers-sort" id="OC-desc" value="OC-desc" /><label for="OC-desc">OC: Asc </label>
<input type="radio" name="OC2-display-choice-availMembers-sort" id="OC-asc" value="OC-asc" /><label for="OC-asc">OC: Desc</label>
<input type="radio" name="OC2-display-choice-availMembers-sort" id="active-asc" value="active-asc" /><label for="active-asc">Active: Asc</label>
<input type="radio" name="OC2-display-choice-availMembers-sort" id="active-desc" value="active-desc" /><label for="active-desc">Active: Desc</label>
</div>
</fieldset>
<fieldset class="OC2-choice">
<legend>Show "Crimes" section?</legend>
<div class="OC2-choice-buttons">
<input type="radio" name="OC2-display-choice-crimes" id="crimes-show" value="crimes-show" /><label for="crimes-show">Yes</label>
<input type="radio" name="OC2-display-choice-crimes" id="crimes-hide" value="crimes-hide" /><label for="crimes-hide">No</label>
</div>
</fieldset>
<fieldset class="OC2-choice">
<legend>Default sort for "Crimes"?</legend>
<div class="OC2-choice-buttons">
<input type="radio" name="OC2-display-choice-crimes-sort" id="time-asc" value="time-asc" /><label for="time-asc">Time: Asc</label>
<input type="radio" name="OC2-display-choice-crimes-sort" id="time-desc" value="time-desc" /><label for="time-desc">Time: Desc</label>
<input type="radio" name="OC2-display-choice-crimes-sort" id="level-asc" value="level-asc" /><label for="level-asc">Level: Asc</label>
<input type="radio" name="OC2-display-choice-crimes-sort" id="level-desc" value="level-desc" /><label for="level-desc">Level: Desc</label>
</div>
</fieldset>
</div>
</li>
<li class="table-cell OC2-horizLine"></li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell">
<div class="OC2-settingsSubTitle">Highlight & Indicator settings</div>
<ul>
<li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last OC for 'yellow' highlight:</div><input id="OC-indicator-yellow" type="textbox" style="line-height: 12px; padding: 5px" placeholder="24" size="10" /> hours</div></li>
<li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last OC for 'red' highlight:</div><input id="OC-indicator-red" type="textbox" style="line-height: 12px; padding: 5px" placeholder="48" size="10" /> hours</div></li>
<li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last activity for 'inactive' indicator:</div><input id="activity-indicator" type="textbox" style="line-height: 12px; padding: 5px" palceholder="96" size="10" /> hours</div></li>
</ul>
</div>
</li>
<li class="table-cell OC2-horizLine"></li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell">
<div class="OC2-settingsSubTitle">Member Ignore List</div>
<div class="OC2-settingsText">
<div class="OC2-memberIgnoreWrapper">Add member:
<input id="OC2-ignoreMemberInput" type="textbox" />
<select id="OC2-ignoreMemberSelect">
<option class="default-option" value="" selected></option>
</select>
<div id="OC2-addToIgnoreButton" class="OC2-button">Add</div>
</div>
</div>
<div class="OC2-settingsText">Ignored Members:
<ul class="OC2-memberIgnoreList">
<li class="OC2-ignoreTitles" style="font-weight: bold; margin-bottom: 5px"><div class="OC2-ignoreName">Member Name [id]</div> <div class="OC2-ignoreTime">Last Active Time</div><div class="OC2-ignoreButtons">Action</div></li>
</ul>
</div>
</div>
</li>
<li class="table-cell OC2-horizLine"></li>
<li class="table-cell OC2-settingsSection">
<div class="OC2-settingsCell">
<div id="OC2-buttonResult"></div>
<div class="OC2-buttonDiv">
<div id="OC2-APIResetButton" class="OC2-button">Reset to Default</div><div id="OC2-APISaveButton" class="OC2-button">Save Changes</div>
</div>
</div>
</li>
</ul></div>
<div class="OC2-memberTableFooter OC2-settingsFooter"></div>
</div>
`)
$("div.main-wrap").html(_injectHTML)
//onclick functions
$("#OC2-APITestButton").off().on("click", (event) => {
APITestClickEvent(event)
})
$("#OC2-APISaveButton").off().on("click", (event) => {
setSavedValues()
.then( () => {
$("#OC2-buttonResult").html("Settings saved!")
if ($("#OC2-buttonResult").is(":visible")) {
$("#OC2-buttonResult").slideUp("fast")
}
$("#OC2-buttonResult").slideDown("slow")
})
})
$("#OC2-APIResetButton").off().on("click", (event) => {
replaceSavedValues()
.then( () => {
$("#OC2-buttonResult").html("Settings reset to default")
if ($("#OC2-buttonResult").is(":visible")) {
$("#OC2-buttonResult").slideUp("fast")
}
$("#OC2-buttonResult").slideDown("slow")
})
})
$("#OC2-deleteAPIKeyButton").off().on("click", (event) => {
deleteAPIKey()
})
if (isPDA()) {
$("#OC2-APIInput").prop("disabled", true)
$("#OC2-APITestButton").off()
$("#OC2-deleteAPIKeyButton").off()
}
$("#OC2-ignoreMemberInput").off()
$("#OC2-ignoreMemberSelect").off()
$("#OC2-ignoreMemberInput").on("keyup", (event) => {
$("#OC2-ignoreMemberSelect option").not(".default-option").remove()
let _insertOption = ""
let _displayMemberList = myAPIData.members.filter((member) => (member.name.toLowerCase()).search(event.currentTarget.value.toLowerCase()) > -1)
_displayMemberList.forEach( (member) => {
_insertOption += (`<option value="${member.id}">${member.name} [${member.id}]</option>`)
})
$("#OC2-ignoreMemberSelect").append(_insertOption)
$("#OC2-ignoreMemberSelect").attr("size", Math.min(7,_displayMemberList.length+1))
})
$("#OC2-ignoreMemberInput").on("focus", (event) => {
$("#OC2-ignoreMemberSelect").attr("size", 7)
})
$("#OC2-ignoreMemberInput").on("blur", (event) => {
if (event.relatedTarget != $("#OC2-ignoreMemberSelect")[0]) {
$("#OC2-ignoreMemberSelect").attr("size", 0)
}
})
$("#OC2-ignoreMemberSelect").on("change", (event) => {
$("#OC2-ignoreMemberInput").val($("#OC2-ignoreMemberSelect :selected").text())
$("#OC2-ignoreMemberSelect").attr("size", 0)
})
$("#OC2-addToIgnoreButton").off().on("click", (event) => {
let _memberToIgnore = $("#OC2-ignoreMemberSelect :selected").val().toString()
if (displayIgnoreList.includes(_memberToIgnore)) {
return //do nothing
} else {
displayIgnoreList.push(_memberToIgnore)
fillMemberIgnoreList()
}
})
styleSettings()
}
function styleSettings() {
colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode"
$(".OC2-horizLine").css({
"border-bottom": "1px solid rgb(34,34,34)",
"width": containerBigMaxWidth,
"box-sizing": "border-box",
"height": "3px",
})
$(".OC2-buttonDiv").css({
"display": "flex",
"flex-direction": "row",
"justify-content": "flex-end",
"width": parseInt(containerBigMaxWidth) - 30 + "px"
})
$("#OC2-buttonResult").css({
"margin": "3px auto 8px -8px",
"text-align": "center",
"padding": "5px 0",
"background-color": colorObj.userindicatorbg[colorDisplayMode],
"display": "none",
"width": "100%"
})
$(".OC2-APITestResults").css({
"display": "flex",
"flex-direction": "row",
"flex-wrap": "wrap"
})
$(".OC2-choice").css({
"display": "flex",
"flex-direction": "row",
"flex-wrap": "wrap"
})
$(".OC2-settingsSubTitle").css({
"margin-bottom": "10px",
"font-weight": "bold"
})
$(".OC2-settingsLabel").css({
"width": "300px",
"display": "inline-block"
})
$("fieldset.OC2-choice").css({
"display": "inline-block",
"width": "100%",
"margin": "5px 0 5px 10px"
})
$("fieldset.OC2-choice .OC2-choice-buttons").css({
"display": "flex",
"flex-direction": "row",
})
$("fieldset.OC2-choice legend").css({
"float": "left",
"width": "300px"
})
$("fieldset.OC2-choice label").css({
"display": "inline-block",
"margin": "0 10px 0 5px"
})
$(".OC2-settingsText").css({
"margin-left": "11px",
})
$("#OC2-Settings ul.table-body").css({
"display": "flex",
"flex-direction": "row",
"flex-wrap": "wrap"
})
$("#OC2-Settings li.table-cell").css({
"display": "flex",
"flex-direction": "row",
"width": "100%",
"font-size": "12px",
})
$("#OC2-Settings .OC2-titleCell.OC2-fancyBg").css({
"width": "100%",
"background": "repeating-linear-gradient(90deg, #2e2e2e, #2e2e2e 2px, #282828 0, #282828 4px)",
"padding": "5px 0",
"padding-left": "10px",
"font-weight": "bold",
"color": colorObj.fancyBg[colorDisplayMode]
})
$("#OC2-Settings .OC2-settingsCell").css({
"padding": "5px 0",
"margin-left": "15px",
"font-weight": "normal",
"width": "100%"
})
$(".OC2-button").css({
"margin-left": "5px",
"padding": "5px 10px",
"text-align": "center",
"display": "inline-block",
"background": colorObj.buttons.background[colorDisplayMode],
"cursor": "pointer",
"color": colorObj.buttons.textcolor[colorDisplayMode]
})
$(".OC2-button").on("mouseenter", function(event) {
$(event.currentTarget).css({
"background": colorObj.buttons.hovercolor[colorDisplayMode]
})
})
$(".OC2-button").on("mouseleave", function(event) {
$(event.currentTarget).css({
"background": colorObj.buttons.background[colorDisplayMode]
})
})
$(".OC2-memberIgnoreWrapper").css({
"position": "relative",
"margin-bottom": "15px",
"margin-top": "10px",
"display": "inline-block"
})
$("#OC2-addToIgnoreButton").css({
"position": "absolute",
"left": "310px",
"top": "-4px"
})
$("#OC2-ignoreMemberSelect").css({
"position": "absolute",
"top": "0px",
"left": "105px",
"width": "200px",
})
$("#OC2-ignoreMemberInput").css({
"position": "absolute",
"top": "-7px",
"left": "100px",
"width": "200px",
"padding": "5px",
"z-index": "10"
})
styleMemberIgnoreList()
if (_isWindowTiny.matches || _isWindowSmall.matches ) {
styleSettingsTiny()
} else if (_isWindowSmallish.matches) {
styleSettingsMiddle()
}
if (isPDA()) {
$("#OC2-ignoreMemberInput").off()
$("#OC2-ignoreMemberInput").css({
"display": "none"
})
$("#OC2-APITestButton").hide()
$("#OC2-deleteAPIKeyButton").hide()
}
}
function styleSettingsMiddle() {
$("fieldset.OC2-choice legend").css({
"float": "left",
"width": "240px"
})
}
function styleSettingsTiny() {
$(".OC2-settingsCell").css({
"margin-left": "10px"
})
$("fieldset.OC2-choice").css({
"margin": "5px 0 5px 5px",
})
$("fieldset.OC2-choice legend").css({
"float": "none",
"margin-bottom": "5px",
})
$("fieldset.OC2-choice .OC2-choice-buttons").css({
"margin-left": "10px",
})
$("fieldset.OC2-choice label").css({
"margin": "0 3px 0 3px",
"width": "50px"
})
$(".OC2-settingsText").css({
"margin-left": "5px",
"margin-bottom": "5px"
})
$("#OC2-addToIgnoreButton").css({
"left": "240px",
"top": "-4px"
})
$("#OC2-ignoreMemberSelect").css({
"top": "0px",
"left": "85px",
"width": "150px",
})
$("#OC2-ignoreMemberInput").css({
"top": "-7px",
"left": "80px",
"width": "150px",
"padding": "5px",
"z-index": "10"
})
$(".OC2-memberIgnoreList").css({
"margin": "5px 0 0 0",
})
$(".OC2-memberIgnoreList li").not("li.OC2-ignoreTitles").css({
"align-items": "center"
})
$(".OC2-ignoreName").css({
"width": "120px"
})
$(".OC2-ignoreTime").css({
"width": "120px",
})
$(".OC2-buttonDiv").css({
"justify-content": "center",
"padding-bottom": "50px"
})
}
function styleMemberIgnoreList() {
colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode"
$(".OC2-memberIgnoreList a").css({
"color": "inherit"
})
$(".OC2-memberIgnoreList").css({
"display": "flex",
"flex-direction": "row",
"margin": "5px 0 0 10px",
"flex-wrap": "wrap"
})
$(".OC2-memberIgnoreList li").css({
"display": "flex",
"flex-direction": "row",
"width": parseInt(containerBigMaxWidth) + "px",
"padding": "3px 0",
"align-items": "center"
})
$(".OC2-ignoreName").css({
"width": "200px"
})
$(".OC2-ignoreTime").css({
"width": "200px"
})
$(".OC2-ignoreButtons .OC2-button").css({
"margin-top": "3px",
"margin-left": "-10px",
"padding": "5px 10px",
"text-align": "center",
"display": "inline-block",
"background": colorObj.buttons.background[colorDisplayMode],
"cursor": "pointer",
"color": colorObj.buttons.textcolor[colorDisplayMode]
})
$(".OC2-button").on("mouseenter", function(event) {
$(event.currentTarget).css({
"background": colorObj.buttons.hovercolor[colorDisplayMode]
})
})
$(".OC2-button").on("mouseleave", function(event) {
$(event.currentTarget).css({
"background": colorObj.buttons.background[colorDisplayMode]
})
})
if (_isWindowSmall.matches || _isWindowTiny.matches ) {
styleSettingsTiny()
}
}
function fillMemberIgnoreList() {
$(".OC2-memberIgnoreList li").not("li.OC2-ignoreTitles").remove()
//this breaks easily lol
if (!userSettings.memberIgnoreList) {
return
}
if (!displayIgnoreList) {
return
}
if (displayIgnoreList.length == 0) {
return
}
displayIgnoreList.forEach( (_id) => {
_id = _id.toString()
if (!memberInfo[_id]) {
return
}
$(".OC2-memberIgnoreList").append(`<li data-memberid="${_id}">
<div class="OC2-ignoreName">${memberInfo[_id].name} [${_id}]</div>
<div class="OC2-ignoreTime">${memberInfo[_id].last_action.relative}</div>
<div class="OC2-ignoreButtons"><div class="OC2-button">Remove</div></div>
</li>`)
$(`li[data-memberid=${_id}] div.OC2-button`).off().on("click", (event) => {
displayIgnoreList = displayIgnoreList.filter(item => item !== _id)
fillMemberIgnoreList()
})
})
styleMemberIgnoreList()
}
async function settingsFillSelect() {
if (!myAPIData) {
let _APITest = await getAndAnalyzeAPIData()
if (_APITest.error) {
$("#OC2-addToIgnoreButton").hide()
$("#OC2-ignoreMemberInput").prop("disabled", true)
$("#OC2-ignoreMemberSelect").prop("disabled", true)
$(".OC2-memberIgnoreWrapper").parent().prepend(`<div class="color-red OC2-errorAPIKey">This function requires an API key to be registered</div>`)
return
}
}
let _insertOption = ""
let _displayMemberList = myAPIData.members
_displayMemberList.sort( (a,b) => (a.name).localeCompare(b.name))
_displayMemberList.forEach( (member) => {
_insertOption += (`<option value="${member.id}">${member.name} [${member.id}]</option>`)
})
$("#OC2-ignoreMemberSelect").append(_insertOption)
//fill up displayIgnoreList, also syntax is like this as a PDA fix
if (userSettings.memberIgnoreList) {
displayIgnoreList = userSettings.memberIgnoreList
} else {
displayIgnoreList = [ ]
}
fillMemberIgnoreList()
}