Tidy up your Dashboard

Tidy Up Your Dashboard is a Userscript which brings along a lot of features for improving the user experience on Warzone.

当前为 2018-09-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Tidy up your Dashboard
  3. // @namespace https://gf.qytechs.cn/users/10154
  4. // @grant none
  5. // @run-at document-start
  6. // @match https://www.warzone.com/*
  7. // @description Tidy Up Your Dashboard is a Userscript which brings along a lot of features for improving the user experience on Warzone.
  8. // @version 3.0.3
  9. // @icon http://i.imgur.com/XzA5qMO.png
  10. // @require https://code.jquery.com/jquery-1.11.2.min.js
  11. // @require https://code.jquery.com/ui/1.11.3/jquery-ui.min.js
  12. // @require https://cdn.bootcss.com/datatables/1.10.10/js/jquery.dataTables.min.js
  13. // @require https://cdn.bootcss.com/datatables/1.10.10/js/dataTables.bootstrap.js
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js
  15. // ==/UserScript==
  16. window.timeUserscriptStart = new Date().getTime();
  17. window.MULIS_USERSCRIPT = true;
  18. var version = GM_info.script.version;
  19. this.$$$ = jQuery.noConflict(true);
  20. window.wlerror = function(){}
  21. setupImages();
  22. console.log("Running Muli's userscript");
  23. if(pageIsDashboard()) {
  24. createSelector(".container-fluid", "display: none")
  25. createSelector("body", "overflow: hidden")
  26. }
  27.  
  28. setupDatabase()
  29. log("indexedDB setup complete")
  30.  
  31. if (document.readyState == 'complete' || document.readyState == 'interactive') {
  32. log("Readystate complete|interactive")
  33. DOM_ContentReady();
  34. } else {
  35. window.document.addEventListener("DOMContentLoaded", DOM_ContentReady);
  36. log("Readystate loading")
  37. }
  38. var logData = "";
  39. function log(entry) {
  40. var time = moment(new Date()).format('h:mm:ss');
  41. logData += `\n${time} | ${entry}`;
  42. }
  43. function logError(entry) {
  44. var time = moment(new Date()).format('h:mm:ss');
  45. logData += `\n${time} | ${entry}`;
  46. }
  47. //ctrl+shift+2
  48. $$$(document).keydown(function(e){
  49. if( e.which === 50 && e.ctrlKey && e.shiftKey ){
  50. getLog()
  51. }
  52. });
  53.  
  54. window.logDialog = undefined;
  55. window.getLog = function() {
  56. if(logDialog) {
  57. logDialog.html(`<textarea style="height:100%;width:100%">${logData}</textarea>`)
  58. logDialog.dialog('open')
  59. } else {
  60. logDialog = $$$(`<div style="overflow:hidden"><textarea style="height:100%;width:100%">${logData}</textarea></div>`).dialog({
  61. width: 800,
  62. title: "Userscript log",
  63. height: 400});
  64. }
  65. }
  66. window.onerror = windowError
  67.  
  68. function windowError(message, source, lineno, colno, error) {
  69. logError(`Error on line ${lineno} col ${colno} in ${source}`)
  70. logError(`${JSON.stringify(error)} ${message}`)
  71. if(typeof $().dialog == "function") {
  72. window.wlerror(message, source, lineno, colno, error)
  73. }
  74. }
  75. function setupAWPWorldTour() {
  76. if($("title").text().toLowerCase().indexOf("awp world tour") != -1) {
  77. setupAWPRanking();
  78. setupAWPEvents();
  79. setupBottomForumContainer("awp")
  80. addCSS(`
  81. .AWPRanking {
  82. margin-bottom: 20px;
  83. width: 100%;
  84. }
  85. .awpUpdated {
  86. color: gray;
  87. float: right;
  88. font-size: 11px;
  89. `)
  90. }
  91. }
  92.  
  93. function setupAWPRanking() {
  94. var minRow = 12;
  95. var maxRow = 30;
  96. var minCol = 1;
  97. var maxCol = 25;
  98. var url = `https://spreadsheets.google.com/feeds/cells/1YuV5WqthgmYsZqv4rFVSE1xhM0BKVrcbkivRZ8ht6-E/1/public/values?min-row=${minRow}&max-row=${maxRow}&min-col=${minCol}&max-col=${maxCol}&alt=json-in-script&callback=parseAWPRankingData`
  99. console.log(url)
  100. $.ajax({
  101. url: url,
  102. dataType: "script",
  103. });
  104. }
  105.  
  106. function setupAWPEvents() {
  107. var minRow = 10;
  108. var minCol = 1;
  109. var maxCol = 6;
  110. var url = `https://spreadsheets.google.com/feeds/cells/1YuV5WqthgmYsZqv4rFVSE1xhM0BKVrcbkivRZ8ht6-E/2/public/values?min-row=${minRow}&min-col=${minCol}&max-col=${maxCol}&alt=json-in-script&callback=parseAWPEventData`
  111. $.ajax({
  112. url: url,
  113. dataType: "script",
  114. });
  115. }
  116.  
  117. window.parseAWPEventData = function(data) {
  118. var entries = data.feed.entry
  119. var lastUpdated = moment(data.feed.updated.$t)
  120. var content = $("<div>");
  121. content.prepend('<h4 class="text-medium card-title px-4 mb-0 py-3"><a href="https://www.warzone.com/Forum/156042-awp-world-tour">AWP World Tour</a>: Events</h4>')
  122. var table = $('<table class="AWPRanking table table-striped mb-0"><thead><tr><td>Week</td><td>Name</td><td>Champion</td></tr></thead><tbody></tbody></table>')
  123. var tbody = $("<tbody></tbody>")
  124. var tr = $("<tr></tr>");
  125. var events = [];
  126. var event = {finished: true};
  127. var currentRow = entries[0].gs$cell.row
  128. try {
  129. $.each(entries, function(key, entry){
  130. var col = entry.gs$cell.col
  131. var row = entry.gs$cell.row
  132.  
  133. if((row - currentRow) >= 3) {
  134. currentRow = row;
  135. events.push(event)
  136. if(event.url.match(/forum/i)) {
  137. return;
  138. }
  139. event = {finished: true}
  140. }
  141.  
  142. if(col == 1 && entry.content.$t) {
  143. event.url = entry.content.$t.match(/docs.google.com/i) ? undefined : entry.content.$t
  144. } else if(col == 3) {
  145. event.date = entry.content.$t
  146. } else if(col == 4) {
  147. if(event.name == undefined) {
  148. event.name = entry.content.$t
  149. } else if(event.series == undefined) {
  150. event.series = entry.content.$t
  151. }
  152. } else if(col == 5) {
  153. event.champion = entry.content.$t
  154. } else if(col == 6) {
  155. event.finished = false
  156. }
  157. })
  158. } catch(e) {
  159. log("error parsing awp event data")
  160. log(e)
  161. }
  162. var eventRows = events.filter(function(e){
  163. return e.url && Math.abs(moment().diff(moment(e.date), 'days')) < 150
  164. }).map(function(e){
  165. return `<tr>
  166. <td>${moment(e.date).format('DD/MMM')}</td>
  167. <td><a href="${e.url}">${e.name}</a><br>${e.series}</td>
  168. <td>${e.finished ? e.champion : (e.url.match(/tournament/i) ? "in progress" : "not started")}</td>
  169. </tr>`
  170. }).join("")
  171. tbody.append(eventRows)
  172. tbody.append(`<tr class="lastRow"><td colspan="3"><span><a target="_blank" href="https://docs.google.com/spreadsheets/d/1Ao0SlM6Kv6CE1-Ha5mBIrI6nj4Uft2lMaE25qbXxWHs/pub?gid=648212339&output=html">Show All</a></span><span class="awpUpdated">Updated ${lastUpdated.from()}</span></td></tr>`)
  173. table.append(tbody);
  174. content.append($("<div class='scroller'>").append(table))
  175. $(".awp").append(content);
  176. }
  177. window.parseAWPRankingData = function(data) {
  178. var entries = data.feed.entry
  179. var lastUpdated = moment(data.feed.updated.$t)
  180. var content = $("<div>");
  181. content.prepend('<h4 class="text-medium card-title px-4 mb-0 py-3"><a href="https://www.warzone.com/Forum/156042-awp-world-tour">AWP World Tour</a>: Rankings</h4>')
  182. var table = $('<table class="AWPRanking table table-striped mb-0"><thead><tr><td>Rank</td><td>Name</td><td>Points</td></tr></thead><tbody></tbody></table>')
  183. var tbody = $("<tbody></tbody>")
  184. var tr = $("<tr></tr>");
  185. var url;
  186. try {
  187. $.each(entries, function(key, entry){
  188. var col = entry.gs$cell.col
  189. var row = entry.gs$cell.row
  190. if(col == 1) {
  191. url = entry.content.$t;
  192. } else if(col == 3) {
  193. //rank
  194. tr.append($(`<td>${entry.content.$t}</td>`))
  195. } else if(col == 5) {
  196. //name
  197. tr.append($(`<td><a href="${url}">${entry.content.$t}</a></td>`))
  198. } else if(col == 25) {
  199. //points
  200. tr.append($(`<td>${entry.content.$t}</td>`))
  201. tbody.append(tr)
  202. tr = $("<tr></tr>");
  203. }
  204. })
  205. } catch(e) {
  206. log("error parsing awp event data")
  207. log(JSON.parse(e))
  208. }
  209. table.append(tbody);
  210. tbody.append(`<tr class="lastRow"><td colspan="3"><span><a target="_blank" href="https://docs.google.com/spreadsheets/d/1Ao0SlM6Kv6CE1-Ha5mBIrI6nj4Uft2lMaE25qbXxWHs/pubhtml">Show All</a></span><span class="awpUpdated">Updated ${lastUpdated.from()}</span></td></tr>`)
  211.  
  212. content.append(table)
  213. $(".awp").prepend(content);
  214. }
  215. function setupMDLProfile() {
  216. var id = location.href.match(/([0-9]*)$/i)[1]
  217. var urlParam = "http://md-ladder.cloudapp.net/api/v1.0/players/" + id;
  218. var url = "https://w115l144.hoststar.ch/wl/httpTohttps.php?url=" + encodeURI(urlParam)
  219. $.ajax({
  220. type: 'GET',
  221. url: url,
  222. dataType: 'jsonp',
  223. crossDomain: true,
  224. }).done(function (response) {
  225. var data = JSON.parse(response.data);
  226. var player = data.player;
  227.  
  228. if(player) {
  229. var mdlStats = '<a target="_blank" href="http://md-ladder.cloudapp.net/player?playerId=' + id +'">Multi-day ladder</a>'
  230. if(player.rank) {
  231. mdlStats += '<span>: Ranked ' + getRankText(player.rank) + ' with a rating of ' + player.displayed_rating + '. Best rating ever: ' + player.best_displayed_rating + ', best rank ever: ' + getRankText(player.best_rank) + '</span>'
  232. } else if(player.best_displayed_rating) {
  233. mdlStats += '<span>: Not Ranked with a rating of ' + player.displayed_rating + '. Best rating ever: ' + player.best_displayed_rating + ', best rank ever: ' + getRankText(player.best_rank) + '</span>'
  234. } else if(player.displayed_rating) {
  235. mdlStats += '<span>: Not Ranked with a rating of ' + player.displayed_rating
  236. }
  237. } else {
  238. var mdlStats = '<a target="_blank" href="http://md-ladder.cloudapp.net/">Multi-day ladder</a>'
  239. mdlStats += '<span>: Currently not participating in the ladder.</span>'
  240. }
  241.  
  242. mdlStats += '<br>'
  243. mdlStats += '<br>'
  244. $("h3:contains('Ladder Statistics')").next().prepend(mdlStats)
  245. })
  246. }
  247.  
  248. function setupMDLLadderTable() {
  249. addCSS(`
  250. .spinner {
  251. margin: 100px auto 0;
  252. width: 70px;
  253. text-align: center;
  254. }
  255.  
  256. .spinner > div {
  257. width: 18px;
  258. height: 18px;
  259. background-color: #333;
  260.  
  261. border-radius: 100%;
  262. display: inline-block;
  263. -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
  264. animation: sk-bouncedelay 1.4s infinite ease-in-out both;
  265. }
  266.  
  267. .spinner .bounce1 {
  268. -webkit-animation-delay: -0.32s;
  269. animation-delay: -0.32s;
  270. }
  271.  
  272. .spinner .bounce2 {
  273. -webkit-animation-delay: -0.16s;
  274. animation-delay: -0.16s;
  275. }
  276.  
  277. @-webkit-keyframes sk-bouncedelay {
  278. 0%, 80%, 100% { -webkit-transform: scale(0) }
  279. 40% { -webkit-transform: scale(1.0) }
  280. }
  281.  
  282. @keyframes sk-bouncedelay {
  283. 0%, 80%, 100% {
  284. -webkit-transform: scale(0);
  285. transform: scale(0);
  286. } 40% {
  287. -webkit-transform: scale(1.0);
  288. transform: scale(1.0);
  289. }
  290. }
  291. `)
  292. var mdlTab = '<li class="nav-item"><a href="#MDLTab" data-toggle="tab" style="cursor: pointer" class="nav-link">Multi-day ladder</a></li>'
  293. $("#CommunityLadderTabs").append(mdlTab);
  294. var mdlData = `
  295. <div id="MDLTab" class="tab-pane" role="tabpanel" aria-hidden="false" style="height:400px">
  296. <div class="mdl-data">
  297. <div class="mdlPlayers" style="float:left">
  298. <div class="spinner mdlPlayerTable-loading" style="min-width:265px">
  299. <div class="bounce1"></div>
  300. <div class="bounce2"></div>
  301. <div class="bounce3"></div>
  302. </div>
  303. <div class="mdl-content" style="display:none">
  304. <a href="http://md-ladder.cloudapp.net/allplayers" style="float:right;margin-top:5px">Show All</a>
  305. </div>
  306. </div>
  307. <div class="mdlGames" style="float:left; margin-left:10px">
  308. <div class="spinner mdlGamesTable-loading">
  309. <div class="bounce1"></div>
  310. <div class="bounce2"></div>
  311. <div class="bounce3"></div>
  312. </div>
  313. </div>
  314. </div>
  315. </div>`
  316. $("#myTabContent").append(mdlData);
  317. getMDLPlayerTable(function(table) {
  318. $(".mdlPlayers .mdl-content").prepend(table);
  319. $(".mdlPlayerTable-loading").remove();
  320. $(".mdlPlayers .mdl-content").show();
  321. })
  322. getMDLGamesTable(10, function(table) {
  323. $(".mdlGames").prepend(table);
  324. $(".mdlGamesTable-loading").remove();
  325. $("#DashboardLadderTabs-6 .mdlGames table").show();
  326. })
  327. $('#DashboardLadderTabs').tabs('destroy').tabs({ event: 'mouseover' });
  328. }
  329.  
  330. function getMDLGamesTable(numOfGames, cb) {
  331. var content = $("<div>");
  332. content.prepend('<h4 class="text-medium card-title px-4 mb-0 py-3"><a href="http://md-ladder.cloudapp.net/">Multi-day ladder</a>: Recent Games</h4>')
  333. var table = $("<table>").attr("cellpadding", 2).attr("cellspacing", 0).css("width", "100%").addClass("table table-striped mb-0")
  334. table.append(`
  335. <thead>
  336. <tr>
  337. <td>Game</td>
  338. <td>Link</td>
  339. <td>Date</td>
  340. </tr>
  341. </thead>
  342. `)
  343. table.append("<tbody></table>")
  344. var urlParam = "http://md-ladder.cloudapp.net/api/v1.0/games/?topk=" + numOfGames;
  345. var url = "https://w115l144.hoststar.ch/wl/httpTohttps.php?url=" + encodeURI(urlParam)
  346. $.ajax({
  347. type: 'GET',
  348. url: url,
  349. dataType: 'jsonp',
  350. crossDomain: true,
  351. }).done(function (response) {
  352. var data = JSON.parse(response.data);
  353. var games = data.games;
  354.  
  355. $.each(games, function(key, game) {
  356. var p1 = game.players[0];
  357. var p2 = game.players[1]
  358. var winner = game.winner_id;
  359. var ended = moment(game.finish_date+"Z")
  360. var rowData = "<td>" + getPlayerGameString(p1, p2, winner) + "</td>"
  361. if(game.is_game_deleted) {
  362. rowData += "<td>DELETED</td>"
  363. } else {
  364. rowData += "<td><a href='https://www.warlight.net/MultiPlayer?GameID=" + game.game_id + "'>" + game.game_id + "</a></td>"
  365. }
  366. rowData += "<td>" + ended.from() + "</td>"
  367. table.append("<tr>" + rowData + "</tr>")
  368. })
  369. content.append(table)
  370. if(cb) {
  371. cb(content)
  372. }
  373. })
  374. }
  375.  
  376. function getMDLPlayerTable(cb) {
  377. var content = $("<div>");
  378. content.prepend('<h4 class="text-medium card-title px-4 mb-0 py-3"><a href="http://md-ladder.cloudapp.net/">Multi-day ladder</a>: Rankings</h4>')
  379. var table = $("<table>").attr("cellpadding", 2).attr("cellspacing", 0).css("width", "100%").addClass("table table-striped mb-0")
  380. table.append(`
  381. <thead>
  382. <tr>
  383. <td>Rank</td>
  384. <td>Name</td>
  385. <td>Rating</td>
  386. </tr>
  387. </thead>`)
  388. table.append("<tbody></table>")
  389. var urlParam = "http://md-ladder.cloudapp.net/api/v1.0/players/?topk=10";
  390. var url = "https://w115l144.hoststar.ch/wl/httpTohttps.php?url=" + encodeURI(urlParam)
  391. $.ajax({
  392. type: 'GET',
  393. url: url,
  394. dataType: 'jsonp',
  395. crossDomain: true,
  396. }).done(function (response) {
  397. var data = JSON.parse(response.data);
  398. var players = data.players;
  399.  
  400. players = players.filter(function(p){
  401. return p.rank <= 10
  402. }).sort(function(p1, p2){
  403. return p1.rank - p2.rank
  404. })
  405. $.each(players, function(key, player) {
  406. var rowData = "<td>" + player.rank + "</td>"
  407. var playerLink = getPlayerLink(player);
  408. var clanIcon = getClanIcon(player);
  409. rowData += "<td>" + clanIcon + playerLink + "</td>"
  410. rowData += "<td>" + player.displayed_rating + "</td>"
  411. $(table).find("tbody").append("<tr>" + rowData + "</tr>")
  412. })
  413. if(cb) {
  414. content.append(table)
  415. cb(content)
  416. }
  417. })
  418. }
  419.  
  420. function setupMDLForumTable() {
  421. if($("title").text().toLowerCase().indexOf("multi-day ladder") != -1) {
  422. var mdlContainer = setupBottomForumContainer("mdl")
  423. getMDLPlayerTable(function(table) {
  424. mdlContainer.prepend(table)
  425. })
  426. getMDLGamesTable(10, function(table) {
  427. mdlContainer.append(table);
  428. })
  429. }
  430. }
  431.  
  432. function getPlayerGameString(p1, p2, winnerId) {
  433. var c1 = getClanIcon(p1)
  434. var c2 = getClanIcon(p2)
  435. var p1s = c1 + "<a target='_blank' href='http://md-ladder.cloudapp.net/player?playerId=" + p1.player_id + "'> " + p1.player_name + "</a>"
  436. var p2s = c2 + "<a target='_blank' href='http://md-ladder.cloudapp.net/player?playerId=" + p2.player_id + "'> " + p2.player_name + "</a>"
  437. if(p1.player_id == winnerId) {
  438. return p1s + " defeated " + p2s
  439. } else {
  440. return p2s + " defeated " + p1s
  441. }
  442. }
  443.  
  444. function getPlayerLink(player) {
  445. return "<a href='http://md-ladder.cloudapp.net/player?playerId=" + player.player_id + "'> " + player.player_name + "</a>"
  446. }
  447.  
  448. function getClanIcon(player) {
  449. if(player.clan_id) {
  450. return '<a href="http://md-ladder.cloudapp.net/clan?clanId=' + player.clan_id + '" title="' + player.clan + '"><img border="0" style="vertical-align: middle" src="' + player.clan_icon + '"></a>'
  451. } else {
  452. return ""
  453. }
  454. }
  455.  
  456. function getRankText(n) {
  457. var s=["th","st","nd","rd"]
  458. var v=n%100;
  459. return n+(s[(v-20)%10]||s[v]||s[0]);
  460. }
  461.  
  462. function setupBottomForumContainer(className) {
  463. $("#ReplyDiv").after("<div class='" + className + "'></div>")
  464. addCSS(`
  465. .` + className + ` {
  466. padding: 20px;
  467. display: flex;
  468. justify-content: space-between;
  469. }
  470. .` + className + ` > * {
  471. flex: 0.47;
  472. }
  473. .` + className + ` .scroller {
  474. max-height: 750px;
  475. display: block;
  476. overflow-y: auto;
  477. }
  478. `)
  479. return $("."+className);
  480. }
  481. function setupExtendedTwitch() {
  482. $.getJSON('https://api.twitch.tv/kraken/streams?client_id=m2cojjidnvim6g0go9g2epmafcpv14&game=WarLight', function(data) {
  483. $(".streamBox").remove();
  484. if(data && data.streams.length > 1) {
  485. var last = $("body > div:nth-of-type(1) > div > div:last");
  486. var offset = last.offset().left + last.width();
  487. var container = $("<div/>");
  488. container.css("left", 0)
  489. container.css("position", "absolute")
  490. container.css("top", "42px")
  491. container.css("display", "none")
  492. container.css("background", "black")
  493. container.css("padding", "10px")
  494. container.css("width", "200px")
  495. container.css("z-index", "100")
  496. container.css("border", "1px gray solid")
  497. container.addClass("streamContainer")
  498. var box = $("<div/>")
  499. box.html("<a>View all " + data.streams.length + " streams »</a>")
  500. box.css("position", "relative")
  501. box.css("display", "inline")
  502. box.css("padding", "15px 120px 15px 10px")
  503. box.css("left", offset)
  504. box.addClass("streamBox")
  505. var streams = data.streams;
  506. var html = "";
  507. $.each(streams, function (key, stream) {
  508. var streamHTML = getStreamHtml(stream);
  509. html += streamHTML
  510. console.log(stream)
  511. })
  512. container.html(html)
  513. box.append(container)
  514. $("body > div:nth-of-type(1) > div").append(box)
  515. // $("body").append(container)
  516. // $(".streamBox").on("mouseover", function() {
  517. // $(".streamContainer").css("display", "inline");
  518. // })
  519. }
  520.  
  521. });
  522. }
  523.  
  524. function getStreamHtml(stream) {
  525. var name = stream.channel.display_name;
  526. var title = stream.channel.status;
  527. var url = stream.channel.url;
  528. var viewers = stream.viewers;
  529. var startingTime = new Date(stream.created_at).getTime();
  530. return '<div class="LivestreamInner" title="Streaming now on Twitch.tv by ' + name + '" data-started="' + startingTime + '"><a target="_blank" href="' + url + '"><img src="https://d2wcw7vp66n8b3.cloudfront.net/Images/LiveIcon.jpg" width="29" height="8"> <span class="LivestreamTimer">time</span> <img src="https://d2wcw7vp66n8b3.cloudfront.net/Images/FollowerIcon.png" width="10" height="10"> <span id="LivestreamViewers">' + viewers + '</span><br>' + title + '<br>by ' + name+'</a></div>'
  531. }
  532.  
  533. function StartLivestream() {
  534. $(".LivestreamInner").tooltip();
  535. window.setInterval(function() {
  536. LivestreamTick()
  537. }, 1000)
  538. addCSS(`
  539. .LivestreamTimer {
  540. color: gray;
  541. }
  542. .LivestreamInner {
  543. font-size: 9px;
  544. padding-bottom: 5px;
  545. border-bottom: 1px #222 solid;
  546. margin-top: 5px;
  547. }
  548. .streamBox:hover > .streamContainer, .streamContainer:hover {
  549. display: inline!important
  550. }
  551. .streamBox > a {
  552. font-size: 9px;
  553. position: absolute;
  554. margin-top: 13px;
  555. cursor:pointer;
  556. }
  557. `)
  558. }
  559.  
  560. function LivestreamTick() {
  561. $.each($(".LivestreamInner"), function(key, elem) {
  562. var timer = $(elem).find(".LivestreamTimer")
  563. $(timer).text(GetHMS((new Date).getTime() - parseInt($(elem).attr("data-started"))))
  564. })
  565. // var a = $(".LivestreamTimer"),
  566. // b = $(".LivestreamInner");
  567. // a.text(GetHMS((new Date).getTime() - parseInt(b.attr("data-started"))))
  568. }
  569.  
  570. function Pad0sTo2(a) {
  571. return 0 == a.length ? "00" : 1 == a.length ? "0" + a : a
  572. }
  573.  
  574. function GetHMS(a) {
  575. var b = a / 1E3,
  576. c = b / 60;
  577. a = c / 60;
  578. c = Math.floor(c % 60).toString();
  579. b = Math.floor(b % 60).toString();
  580. return 1 <= a ? Math.floor(a) + ":" + Pad0sTo2(c) + ":" + Pad0sTo2(b) : c + ":" + Pad0sTo2(b)
  581. };
  582.  
  583. function setupDatabase() {
  584. log("indexedDB start setup")
  585. window.Database = {
  586. db: null,
  587. Table: {
  588. Bookmarks: "Bookmarks",
  589. Settings: "Settings",
  590. BlacklistedForumThreads: "BlacklistedForumThreads",
  591. TournamentData: "TournamentData"
  592. },
  593. Exports: {
  594. Bookmarks: "Bookmarks",
  595. Settings: "Settings",
  596. BlacklistedForumThreads: "BlacklistedForumThreads"
  597. },
  598. Row: {
  599. BlacklistedForumThreads: {
  600. ThreadId: "threadId",
  601. Date: "date"
  602. },
  603. Bookmarks: {
  604. Order: "order"
  605. },
  606. Settings: {
  607. Name: "name"
  608. },
  609. TournamentData: {
  610. Id: "tournamentId",
  611. }
  612. },
  613. init: function(callback) {
  614. log("indexedDB start init")
  615. if(!"indexedDB" in window) {
  616. log("IndexedDB not supported")
  617. return;
  618. }
  619. var openRequest = indexedDB.open("TidyUpYourDashboard_v3", 3);
  620. openRequest.onupgradeneeded = function(e) {
  621. var thisDB = e.target.result;
  622. if(!thisDB.objectStoreNames.contains("Bookmarks")) {
  623. var objectStore = thisDB.createObjectStore("Bookmarks", {autoIncrement:true});
  624. objectStore.createIndex("order", "order", {unique:true});
  625. }
  626. if(!thisDB.objectStoreNames.contains("Settings")) {
  627. var objectStore = thisDB.createObjectStore("Settings", { keyPath: "name" });
  628. objectStore.createIndex("name", "name", {unique: true});
  629. objectStore.createIndex("value", "value", {unique: false});
  630. }
  631. if(!thisDB.objectStoreNames.contains("BlacklistedForumThreads")) {
  632. var objectStore = thisDB.createObjectStore("BlacklistedForumThreads", {autoIncrement:true});
  633. objectStore.createIndex("threadId", "threadId", {unique:true});
  634. objectStore.createIndex("date", "date", {unique:false});
  635. }
  636. if(!thisDB.objectStoreNames.contains("TournamentData")) {
  637. var objectStore = thisDB.createObjectStore("TournamentData",{ keyPath: "tournamentId" });
  638. objectStore.createIndex("tournamentId", "tournamentId", {unique:true});
  639. objectStore.createIndex("value", "value", {unique: false});
  640. }
  641. }
  642.  
  643. openRequest.onsuccess = function(e) {
  644. log("indexedDB init sucessful");
  645. db = e.target.result;
  646. callback()
  647. }
  648.  
  649. openRequest.onerror = function(e) {
  650. log("Error Init IndexedDB")
  651. log(e.target.error)
  652. // alert("Sorry, Tidy Up Your Dashboard is not supported")
  653. $("<div>Sorry,<br> Tidy Up Your Dashboard is not supported.</div>").dialog();
  654. }
  655. },
  656. update: function(table, value, key, callback) {
  657. var transaction = db.transaction([table],"readwrite");
  658. var store = transaction.objectStore(table);
  659.  
  660.  
  661. //Perform the add
  662. try {
  663. var request = store.put(value, key != undefined ? Number(key) : undefined);
  664. request.onerror = function(e) {
  665. log(`Error saving ${JSON.stringify(value)} in ${table}`)
  666. log(JSON.stringify(e));
  667. }
  668.  
  669. request.onsuccess = function(e) {
  670. log(`Saved ${JSON.stringify(value)} in ${table}`)
  671. callback()
  672. }
  673. } catch(e) {
  674. log(`Error saving ${JSON.stringify(value)} in ${table}`)
  675. log(JSON.stringify(e));
  676. }
  677.  
  678. },
  679. read: function(table, key, callback) {
  680. var transaction = db.transaction([table], "readonly");
  681. var objectStore = transaction.objectStore(table);
  682.  
  683. var ob = objectStore.get(Number(key));
  684.  
  685. ob.onsuccess = function(e) {
  686. var result = e.target.result;
  687. callback(result)
  688. }
  689. },
  690. readIndex: function(table, row, value, callback) {
  691. var transaction = db.transaction([table], "readonly");
  692. var objectStore = transaction.objectStore(table);
  693.  
  694. var index = objectStore.index(row);
  695. //name is some value
  696. var ob = index.get(value);
  697.  
  698. ob.onsuccess = function(e) {
  699. var result = e.target.result;
  700. callback(result)
  701. }
  702. },
  703. readAll: function(table, callback) {
  704. var transaction = db.transaction([table], "readonly");
  705. var objectStore = transaction.objectStore(table);
  706. var items = []
  707.  
  708. var ob = objectStore.openCursor()
  709.  
  710. ob.onsuccess = function(e) {
  711. var cursor = e.target.result;
  712. if (cursor) {
  713. var item = cursor.value;
  714. item.id = cursor.primaryKey;
  715. items.push(item);
  716. cursor.continue();
  717. } else {
  718. callback(items)
  719. }
  720. }
  721. },
  722. add: function(table, value, callback) {
  723. var transaction = db.transaction([table],"readwrite");
  724. var store = transaction.objectStore(table);
  725.  
  726. try {
  727. var request = store.add(value);
  728. request.onerror = function(e) {
  729. log(`Error saving ${JSON.stringify(value)} in ${table}`)
  730. log(JSON.stringify(e));
  731. }
  732.  
  733. request.onsuccess = function(e) {
  734. log(`Saved ${JSON.stringify(value)} in ${table}`)
  735. callback()
  736. }
  737. } catch(e) {
  738. log(`Error saving ${JSON.stringify(value)} in ${table}`)
  739. log(JSON.stringify(e));
  740. }
  741. },
  742. delete: function(table, key, callback) {
  743. var transaction = db.transaction([table],"readwrite");
  744. var store = transaction.objectStore(table);
  745.  
  746.  
  747. //Perform the add
  748. var request = store.delete(key)
  749.  
  750. request.onerror = function(e) {
  751. log("Error deleting in " + table)
  752. log(e.target.error);
  753. //some type of error handler
  754. }
  755.  
  756. request.onsuccess = function(e) {
  757. log("Deleted in " + table)
  758. callback()
  759. }
  760. },
  761. clear: function(table, callback) {
  762. var transaction = db.transaction([table],"readwrite");
  763. var store = transaction.objectStore(table);
  764.  
  765.  
  766. //Perform the add
  767. var request = store.clear();
  768.  
  769. request.onerror = function(e) {
  770. log("Error clearing " + table)
  771. log(e.target.error);
  772. //some type of error handler
  773. }
  774.  
  775. request.onsuccess = function(e) {
  776. log("Cleared " + table)
  777. callback()
  778. }
  779. },
  780.  
  781. }
  782.  
  783. }
  784. function setupDashboardSearch() {
  785. loadDataTableCSS();
  786. $(".navbar-nav .nav-item:first").before('<li class="nav-item"><a class="nav-link" data-toggle="modal" data-target="#userscriptSearch" style="cursor:pointer">Search</a></li>')
  787. $("body").append(`
  788. <div class="modal modal-1000 fade" id="userscriptSearch" tabindex="-1" role="dialog">
  789. <div class="modal-dialog" role="document">
  790. <div class="modal-content">
  791. <div class="modal-header">
  792. <h5 class="modal-title" id="exampleModalLongTitle">Search</h5>
  793. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  794. <span aria-hidden="true">&times;</span>
  795. </button>
  796. </div>
  797. <div class="modal-body">
  798. <div id="searchTabs">
  799. <ul class="nav nav-tabs" role="tablist">
  800. <li class="nav-item">
  801. <a class="nav-link active" data-toggle="tab" href="#tab_player" role="tab">Player</a> </li>
  802. <li class="nav-item"><a class="nav-link" id="tab_clan_header" data-toggle="tab" href="#tab_clan" role="tab">Clan</a> </li>
  803. </ul>
  804. <div class="tab-content" style="padding:20px;">
  805. <div class="tab-pane active" id="tab_player" role="tabpanel">
  806. <div class="form-group">
  807. <div class="form-inline">
  808. <input placeholder='Player name' id='playerSearchQuery' class="form-control">
  809. <button id="searchPlayerBtn" class="btn btn-primary">Search</button>
  810. </div>
  811. <div id='foundPlayers'></div>
  812. </div>
  813. </div>
  814. <div class="tab-pane active" id="tab_clan" role="tabpanel">
  815. <div id='foundClans'></div>
  816. </div>
  817. </div>
  818. </div>
  819. </div>
  820. <div class="modal-footer">
  821. <button type="button" class="btn btn-primary" class="close" data-dismiss="modal" >Close</button>
  822. </div>
  823. </div>
  824. </div>
  825. </div>
  826. `)
  827. $('#userscriptSearch').on('shown.bs.modal', function () {
  828. $('#playerSearchQuery').focus();
  829. })
  830. window.tabsInit = false;
  831. $("#tab_clan_header").on("click", function (event, ui) {
  832. if (!tabsInit) {
  833. initClanSearch();
  834. tabsInit = true;
  835. }
  836. });
  837. createSelector("#searchTabs", "background: none;border: none;")
  838. $("#searchPlayerLink").on("click", function () {
  839. showPopup(".playersearch-show")
  840. $("#playerSearchQuery").val("")
  841. $("#playerSearchQuery").focus()
  842. })
  843. $("#searchPlayerBtn").on("click", function () {
  844. searchPlayer()
  845. })
  846. $("#findPlayerExtra").on("click", function (event) {
  847. $(".playersearch-context").finish().toggle(100).
  848. css({
  849. top: event.pageY + "px",
  850. left: event.pageX + "px"
  851. });
  852. })
  853. $('#playerSearchQuery').keyup(function (e) {
  854. if (e.keyCode == 13) {
  855. searchPlayer()
  856. }
  857. });
  858. createSelector(".SubTabCell", "cursor: pointer")
  859. createSelector(".foundPlayer", "display: block; height: 25px; padding: 2px; clear:both")
  860. createSelector(".foundPlayer a", "line-height: 25px; float: left")
  861. createSelector(".foundPlayer img", "height: 15px; display: block; float: left; margin: 5px")
  862. createSelector(".notFound", "clear: both; display: block; color: gray;")
  863. createSelector("#foundPlayers span", "color: gray; padding: 0 5px; line-height: 25px")
  864. createSelector("#foundPlayers > span", "display: block; clear: both; margin: 0px; padding: 10px 0")
  865. createSelector(".playerSearchName", "float: left")
  866. createSelector("#foundClansTable", "float: left; table-layout: fixed;width: 100%")
  867. createSelector("#foundClansTable thead", "text-align: left")
  868. createSelector("#foundClansTable td a", "display: block; width: 100%;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;")
  869. createSelector("#foundClansTable img", "margin-right: 5px;")
  870. }
  871.  
  872. function initClanSearch() {
  873. warlight_shared_viewmodels_WaitDialogVM.Start("Setting up clans...")
  874. warlight_shared_messages_Message.GetClansAsync(null, null, function (a, b, clans) {
  875. parseFoundClans(clans)
  876. warlight_shared_viewmodels_WaitDialogVM.Stop();
  877. })
  878. }
  879. window.blockSearch = false;
  880.  
  881. function searchPlayer() {
  882. if (blockSearch) {
  883. return;
  884. }
  885. blockSearch = true;
  886. window.setTimeout(function () {
  887. blockSearch = false;
  888. }, 3000)
  889. $("#foundPlayers").empty()
  890. var query = $("#playerSearchQuery").val().toLowerCase()
  891. if (query.length < 3) {
  892. warlight_shared_viewmodels_AlertVM.DoPopup("Please enter at least 3 characters to search for");
  893. return
  894. }
  895. warlight_shared_viewmodels_main_manageplayers_ManagePlayersVM.SearchPlayers(query, function (players) {
  896. players = players.Results
  897. if (players.length >= 25) {
  898. $("#foundPlayers").append("<span>This query found more than 25 results. Only the first 25 results are shown below.</span>")
  899. }
  900. parseFoundGlobalPlayers(players)
  901. $("#playerSearchQuery").focus()
  902. $("#playerSearchQuery").select()
  903. })
  904. }
  905.  
  906.  
  907. function parseFoundClans(clans) {
  908. clans.sort(function (c1, c2) {
  909. return (c2.TotalPointsInThousands - c1.TotalPointsInThousands)
  910. });
  911. var clanTableHTML = '<table class="table table-striped mb-0" id="foundClansTable"><thead><tr><th width="50">#</th><th width="250">Name</th><th width="194">Created By</th><th width="110">Total Points</th><th width="110">Created On</th></tr></thead>'
  912. for (var i = 0; i < clans.length; i++) {
  913. var clan = clans[i];
  914. var name = clan.Name;
  915. var id = clan.ID;
  916. var createdBy = clan.CreatedBy;
  917. var iconId = clan.IconIncre;
  918. var imgTag = iconId == 0 ? "" : `<img src="https://d32kaghj56y4ei.cloudfront.net/Data/Clans/${id}/Icon/${iconId}.png">`;
  919. var totalpoints = (clan.TotalPointsInThousands * 1000).toLocaleString("en")
  920. var createdDate = moment(clan.CreatedDate.date).format('MM/DD/YYYY')
  921. var nameHTML = `<a target="_blank" href="https://www.warzone.com/Clans/?ID=${id}">${imgTag}${name}</a>`;
  922. clanTableHTML += `<tr><td>${i+1}</td><td>${nameHTML}</td><td class="data-player" data-player-id="${createdBy}">Checking..</td><td>${totalpoints}</td><td data-order="${id}">${createdDate}</td></tr>`
  923. }
  924. clanTableHTML += "</table>"
  925. $("#foundClans").append(clanTableHTML)
  926. var dataTable = $$$("#foundClansTable").DataTable({
  927. "order": [],
  928. paging: true,
  929. "pageLength": 10,
  930. "bLengthChange": false,
  931. "autoWidth": false,
  932. columnDefs: [{
  933. targets: [0],
  934. searchable: false
  935. }, {
  936. targets: [1],
  937. orderData: [1, 0],
  938. sortable: false
  939. }, {
  940. targets: [2],
  941. orderData: [2, 1, 0],
  942. sortable: false,
  943. searchable: false
  944. }, {
  945. targets: [3],
  946. orderData: [3, 1, 0],
  947. type: "numeric-comma"
  948. }, {
  949. targets: [4],
  950. orderData: [4, 1]
  951. }],
  952. "aoColumns": [
  953. {
  954. "orderSequence": ["desc", "asc"]
  955. },
  956. {
  957. "orderSequence": ["asc", "desc"]
  958. },
  959. {
  960. "orderSequence": ["asc", "desc"]
  961. },
  962. {
  963. "orderSequence": ["asc", "desc"]
  964. },
  965. {
  966. "orderSequence": ["desc", "asc"]
  967. },
  968. ],
  969. initComplete: function () {
  970. window.setTimeout(loadClanCreators, 200);
  971. $("#foundClansTable").removeClass("dataTable")
  972. },
  973. "language": {
  974. "zeroRecords": "No matching clans found",
  975. "info": "Showing _START_ to _END_ of _TOTAL_ clans",
  976. "infoEmpty": "Showing 0 to 0 of 0 clans",
  977. "infoFiltered": "(filtered from _MAX_ total clans)",
  978. }
  979. });
  980. dataTable.on('draw.dt', function () {
  981. loadClanCreators()
  982. })
  983. }
  984.  
  985. function loadClanCreators() {
  986. $.each($(".data-player"), function (k, cell) {
  987. if ($(cell).hasClass("data-player") && $(cell).is(":visible")) {
  988. var id = $(cell).attr("data-player-id")
  989. $.ajax({
  990. type: 'GET',
  991. url: `https://w115l144.hoststar.ch/wl/wl_profile.php?p=${id}`,
  992. dataType: 'jsonp',
  993. crossDomain: true,
  994. }).done(function (response) {
  995. if (isFinite(response.data)) {
  996. $(`[data-player-id="${id}"]`).html(`<a target="_blank" href="https://www.warzone.com/Profile?p=${response.data}">${decodeURI(atob(response.name)) || "Unknown"}</a>`)
  997. }
  998. else {
  999. $(`[data-player-id="${id}"]`).html(`Unknown`)
  1000. }
  1001. if ($(cell).is(":visible")) {
  1002. $(cell).removeClass("data-player");
  1003. }
  1004. });
  1005. }
  1006. });
  1007. }
  1008.  
  1009. function parseFoundGlobalPlayers(players) {
  1010. if (!players || players.length == 0) {
  1011. $("#foundPlayers").append("<span class='notFound'>No Players found.</span>");
  1012. return;
  1013. }
  1014. players.sort(function (p1, p2) {
  1015. return (p2.Level - p1.Level != 0) ? p2.Level - p1.Level : p1.Name > p2.Name
  1016. });
  1017. for (var i = 0; i < players.length; i++) {
  1018. var player = players[i];
  1019. var id = String(player.ProfileToken).substr(0, 2) + String(player.PlayerID) + String(player.ProfileToken).substr(2, 2);
  1020. var nameLink = '<a href="/Profile?p=' + id + '">' + player.Name + '</a>'
  1021. var clan = player.ClanOpt != null ? '<a href="https://www.warzone.com/Clans/?ID=' + player.ClanOpt.ClanID + '"><img onError="this.onError=null;$(this).remove()" class="playerSearchClan" src="https://d32kaghj56y4ei.cloudfront.net/Data/Clans/' + player.ClanOpt.ClanID + '/Icon/' + player.ClanOpt.IconIncre + '.png"></a>' : "";
  1022. var member = player.IsMember ? '<img class="playerSearchMember" src="https://d2wcw7vp66n8b3.cloudfront.net/Images/MemberIcon.png">' : "";
  1023. var name = '<div class="playerSearchName">' + nameLink + "<span>(" + player.Level + ")</span></div>";
  1024. $("#foundPlayers").append('<div class="foundPlayer">' + clan + name + member + '</div>');
  1025. }
  1026. }
  1027. var mapData;
  1028. function setupMapSearch() {
  1029. $("#PerPageBox").closest("tr").after('<tr><td></td><td><input id="mapSearchQuery" placeholder="Map Name"><br><button id="mapSearchBtn">Search</button><button style="margin: 4px" id="mapSearchResetBtn">Reset</button></td></tr>')
  1030. $('#mapSearchQuery').on('keypress', function (event) {
  1031. if(event.which === 13){
  1032. searchMaps();
  1033. }
  1034. });
  1035. $("#mapSearchBtn").on("click", function() {
  1036. searchMaps();
  1037. })
  1038. $("#FilterBox, #SortBox, #PerPageBox").on("change", function() {
  1039. $("#mapSearchQuery").val("")
  1040. $("#searchResultsTitle").remove()
  1041. })
  1042.  
  1043. }
  1044.  
  1045. function searchMaps() {
  1046. if(mapData == undefined) {
  1047. $("<div />").load('Ajax/EnumerateMaps?Filter=' + 1 + '&Sort=' + 1 + "&PerPage=" + 2147483647 + "&Offset=" + 0, function(data) {
  1048. mapData = data;
  1049. filterMaps(this);
  1050. })
  1051. } else {
  1052. var maps = $("<div />").html(mapData)
  1053. filterMaps(maps);
  1054. }
  1055. }
  1056.  
  1057. function filterMaps(selector) {
  1058. var query = $("#mapSearchQuery").val()
  1059. $.each($(selector).find("div"), function(key, div) {
  1060. if($(div).text().trim().toLowerCase().replace(/(rated.*$)/, "").indexOf(query.toLowerCase()) == -1) {
  1061. $(div).remove()
  1062. }
  1063. })
  1064. var count = $(selector).find("div").length
  1065. $('#MapsContainer').empty()
  1066. $(selector).detach().appendTo('#MapsContainer')
  1067. $("#MapsContainer tr:last-of-type").html("Showing maps 1 - " + count + " of " + count);
  1068. $("#ReceivePager").html("Showing maps 1 - " + count + " of " + count);
  1069. $("#searchResultsTitle").length > 0 ? $("#searchResultsTitle").html("Searchresults for <i>" + query +"</i>") : $("#ReceivePager").after("<h2 id='searchResultsTitle'>Searchresults for <i>" + query +"</i></h2>")
  1070. }
  1071. function setupTournamentDecline() {
  1072. $.each($(".TournamentRow"), function (key, val) {
  1073. //Waiting for accept / decline
  1074. if ($(val).find("[style='color: red']:not(.BootTimeLabel)").length > 0) {
  1075. $(val).find("td:last-of-type").append('<button style="float: right;" class="DeclineBtn btn btn-primary" role="button">Decline</button>')
  1076. $(val).find("td:last-of-type").attr("colspan", "2")
  1077. }
  1078. })
  1079. $(".DeclineBtn").on("click", function (e) {
  1080. var id = $(e.target).closest(".TournamentRow").attr("data-tournamentid")
  1081. warlight_shared_messages_Message.DeclineTournamentAsync(null, warlight_shared_viewmodels_SignIn.Auth, id, null, function (b, c) {
  1082. warlight_shared_viewmodels_WaitDialogVM.Stop();
  1083. if (null != c && 129 != c.ErrorType) {
  1084. if (135 == c.ErrorType) {
  1085. warlight_shared_viewmodels_AlertVM.DoPopup("The tournament has been deleted");
  1086. }
  1087. else {
  1088. throw c;
  1089. }
  1090. }
  1091. var btn = $(e.target).closest(".DeclineBtn")
  1092. $(e.target).text("Declined")
  1093. btn.attr("disabled", true).addClass("ui-state-disabled");
  1094. btn.closest(".TournamentRow").find("[style='color: red']:not(.BootTimeLabel)").remove()
  1095. Database.update(Database.Table.TournamentData, {
  1096. tournamentId: Number(id),
  1097. value: false,
  1098. name: false
  1099. }, undefined, function () {})
  1100. })
  1101. })
  1102. }
  1103.  
  1104. function setupTournamentTableStyles() {
  1105. createSelector("body", "overflow: hidden")
  1106. $("#MyTournamentsTable").parent().css({
  1107. "display": "block",
  1108. "overflow-y": "scroll",
  1109. "border-bottom": "1px solid #444444",
  1110. "border-top": "1px solid #444444"
  1111. })
  1112. setTournamentTableHeight();
  1113. }
  1114.  
  1115. function updateCurrentTournamentData() {
  1116. var tournament = WL_Tournament.Tourn
  1117. var players = WL_Tournament.Players._players
  1118. var name = WL_Tournament.Tourn.Settings.Name
  1119. var id = tournament.ID
  1120. try {
  1121. Database.readIndex(Database.Table.TournamentData, Database.Row.TournamentData.Id, id, function (tourn) {
  1122. if (tourn && tourn.value) {
  1123. var details = getTournamentPlayerInfo(tournament, players, warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID)
  1124. Database.update(Database.Table.TournamentData, {
  1125. tournamentId: Number(id),
  1126. value: details,
  1127. name: name
  1128. }, undefined, function () {})
  1129. }
  1130. })
  1131. }
  1132. catch (e) {
  1133. log("Bad tournament")
  1134. log(e)
  1135. }
  1136. }
  1137.  
  1138. function setDefaultElimnatedTournamentStatus() {
  1139. ifSettingIsEnabled('hideEliminatedTournaments', function () {
  1140. $('#hideElimnatedTournaments').prop('checked', true);
  1141. }, undefined, function () {
  1142. showHideEliminatedTournaments();
  1143. })
  1144. }
  1145.  
  1146. function setupTournamentDataCheck() {
  1147. log("setting up tournament data check")
  1148. addCSS(`
  1149. .hideEliminatedTournmanets {
  1150. display: inline-block;
  1151. float: right;
  1152. margin-top: 6px;
  1153. }
  1154. .hideEliminatedTournmanets span {
  1155. margin-right: 10px;
  1156. }
  1157. `)
  1158. // $("#MyTournamentsTable h2").after('<label id="showHideTournaments"><input id="hideElimnatedTournaments" type="checkbox" >Hide tournaments where I am eliminated</input></label>');
  1159. $("#MyTournamentsTable h2").after('<div class="hideEliminatedTournmanets"><label class="switch" for="hideElimnatedTournaments"><input type="checkbox" id="hideElimnatedTournaments"><div class="slider round"></div></label><span>Hide tournaments where I am eliminated </span></div>');
  1160. $("#MyTournamentsTable h2").after('<button class="btn btn-primary" id="dataTournamanetButton" onclick="updateAllTournamentData()">Update data</button>');
  1161. $("body").append("<div style='display:none'><div id='ShowAllBtn'></div><div id='PlayersContainer'></div></div>")
  1162. $("#MyTournamentsTable thead td").attr("colspan", 3)
  1163. $("#MyTournamentsTable tr:last td").attr("colspan", 3)
  1164. addCSS(`
  1165. #showHideTournaments, #dataTournamanetButton {
  1166. float: right;
  1167. margin: 0 10px;
  1168. }
  1169. `)
  1170. addCSS(`
  1171. .TournamentRow.eliminated {
  1172. background: rgba(255,0,0,0.05);
  1173. }
  1174. .TournamentRow {
  1175. transition: all 1s ease-in;
  1176. }
  1177. `)
  1178. showHideEliminatedTournaments();
  1179. $('#hideElimnatedTournaments').change(function () {
  1180. var hideEliminatedTournaments = {
  1181. name: "hideEliminatedTournaments",
  1182. value: this.checked
  1183. }
  1184. Database.update(Database.Table.Settings, hideEliminatedTournaments, undefined, function () {})
  1185. showHideEliminatedTournaments()
  1186. });
  1187. }
  1188.  
  1189. function showHideEliminatedTournaments() {
  1190. var hide = $("#hideElimnatedTournaments").prop("checked");
  1191. markEliminatedTournaments();
  1192. if (hide) {
  1193. hideElimatedTournaments();
  1194. }
  1195. else {
  1196. showElimnatedTournaments();
  1197. }
  1198. }
  1199.  
  1200. function markEliminatedTournaments() {
  1201. $(".eliminated").removeClass("eliminated")
  1202. $.each($("#MyTournamentsTable [data-tournamentid]"), function (key, row) {
  1203. var text = $(row).find(".tournamentData").text();
  1204. if (text.indexOf("None") != -1 && text.indexOf("Playing") == -1) {
  1205. $(row).addClass("eliminated");
  1206. }
  1207. });
  1208. }
  1209.  
  1210. function updateAllTournamentData() {
  1211. $.each($("#MyTournamentsTable [data-tournamentid]"), function (key, row) {
  1212. if (!$(row).find("[style='color: red']:not(.BootTimeLabel)").length > 0) {
  1213. var id = $(row).attr("data-tournamentid")
  1214. Database.readIndex(Database.Table.TournamentData, Database.Row.TournamentData.Id, Number(id), function (tourn) {
  1215. if (!tourn) {
  1216. Database.update(Database.Table.TournamentData, {
  1217. tournamentId: Number(id),
  1218. value: "-",
  1219. name: "-"
  1220. }, undefined, function () {})
  1221. }
  1222. })
  1223. }
  1224. })
  1225. Database.readAll(Database.Table.TournamentData, function (tournamentDatas) {
  1226. $.each(tournamentDatas, function (key, tournamentData) {
  1227. if ($(`#MyTournamentsTable [data-tournamentid='${tournamentData.tournamentId}']`).length) {
  1228. $(`#MyTournamentsTable [data-tournamentid='${tournamentData.tournamentId}']`).find("td:last-of-type").attr("colspan", "1")
  1229. $(`#MyTournamentsTable [data-tournamentid='${tournamentData.tournamentId}']`).append(`<td class="tournamentData">${tournamentData.value ? tournamentData.value : "-"}</td>`)
  1230. }
  1231. else if (tournamentData.value && tournamentData.name) {
  1232. $("#MyTournamentsTable").prepend(`<tr class="TournamentRow" data-tournament="${tournamentData.tournamentId}"><td></td><td><a style="font-size: 17px; color: white" href="https://www.warzone.com/MultiPlayer/Tournament?ID=${tournamentData.tournamentId}"> ${tournamentData.name} (finished)</a></td><td><a><button class="removeTournament btn btn-primary" role="button">Remove</button></a></td></tr>`);
  1233. }
  1234. })
  1235. $(".removeTournament").on("click", function () {
  1236. var row = $(this).closest("tr");
  1237. var id = row.attr("data-tournament")
  1238. Database.update(Database.Table.TournamentData, {
  1239. tournamentId: Number(id),
  1240. value: false,
  1241. name: false
  1242. }, undefined, function () {
  1243. row.remove();
  1244. })
  1245. })
  1246. setDefaultElimnatedTournamentStatus();
  1247. })
  1248. }
  1249.  
  1250. function showElimnatedTournaments() {
  1251. $(".TournamentRow").show();
  1252. updateTournamentCounter();
  1253. }
  1254.  
  1255. function hideElimatedTournaments() {
  1256. $(".TournamentRow.eliminated").hide()
  1257. updateTournamentCounter();
  1258. }
  1259.  
  1260. function updateTournamentCounter() {
  1261. var total = $("#MyTournamentsTable .TournamentRow").length;
  1262. var visible = $("#MyTournamentsTable .TournamentRow:visible").length;
  1263. if (total > visible) {
  1264. $("#MyTournamentsTable h2").text("My Tournaments (" + visible + "/" + total + ")")
  1265. }
  1266. else {
  1267. $("#MyTournamentsTable h2").text("My Tournaments (" + total + ")")
  1268. }
  1269. };
  1270. window.updateAllTournamentData = function () {
  1271. addCSS(`
  1272. .progress {
  1273. width: 269px;
  1274. float: right;
  1275. margin-top: 6px;
  1276. }
  1277. .progress-bar {
  1278. transition-duration: 0.1s;
  1279. }
  1280. `)
  1281. $("#dataTournamanetButton").replaceWith(`
  1282. <div class="progress" >
  1283. <div class="progress-bar"></div>
  1284. </div>
  1285. `)
  1286. var numOfMyTournaments = $("#MyTournamentsTable [data-tournamentid]").length;
  1287. $.each($("#MyTournamentsTable [data-tournamentid]"), function (key, row) {
  1288. var id = $(row).attr("data-tournamentid")
  1289. loadTournamentDetails(id, function () {
  1290. progressTournamentData(numOfMyTournaments)
  1291. showHideEliminatedTournaments()
  1292. updateTournamentCounter();
  1293. })
  1294. })
  1295. }
  1296.  
  1297. function showInfo(text, x, y) {
  1298. window.setTimeout(function () {
  1299. if (!$(".custom-menu").is(':visible')) {
  1300. $(".custom-menu .content").html(text);
  1301. $(".custom-menu").finish().toggle(100).
  1302. // In the right position (the mouse)
  1303. css({
  1304. top: x + "px",
  1305. left: y + "px"
  1306. });
  1307. }
  1308. }, 10);
  1309. }
  1310. var counter = 0;
  1311.  
  1312. function progressTournamentData(max) {
  1313. if (max >= ++counter) {
  1314. $(".progress-bar").text(++counter + "/" + max)
  1315. }
  1316. else {
  1317. $(".progress-bar").text("Done")
  1318. }
  1319. $(".progress-bar").css("width", counter / max * 100 + "%")
  1320. }
  1321.  
  1322. function loadTournamentDetails(id, cb) {
  1323. $(".tournamentData").remove();
  1324. warlight_shared_messages_Message.GetTournamentDetailsAsync(null, warlight_shared_viewmodels_SignIn.Auth, id, new system_Nullable_$Float(999999999), null, function (a, b, c) {
  1325. var tournament = c["Tournament"]
  1326. var name = tournament.Settings.Name
  1327. var players = new wljs_multiplayer_tournaments_display_Players(tournament)["_players"];
  1328. var details = getTournamentPlayerInfo(tournament, players, warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID)
  1329. $(`[data-tournamentid='${id}']`).append(`<td class="tournamentData">${details}</td>`)
  1330. Database.update(Database.Table.TournamentData, {
  1331. tournamentId: Number(id),
  1332. value: details,
  1333. name: name
  1334. }, undefined, function () {})
  1335. if (cb) {
  1336. cb();
  1337. }
  1338. })
  1339. }
  1340. window.getTournamentPlayerInfo = function (tournament, players, id) {
  1341. var playerInfo = players["store"]["h"][id]
  1342. var playing = playerInfo.NumInProgress
  1343. var won = playerInfo.NumWins
  1344. var lost = playerInfo.NumLosses
  1345. var myGames = playing + won + lost
  1346. var allowVacations = tournament.Settings.AllowVacations
  1347. // 0 -> Single Elimination, 1 -> Double Elimination, 2 -> Robin Round
  1348. var tournamentType = tournament.Type
  1349. var myMaxGames;
  1350. var tournamentTotalGames;
  1351. var tournamentGamesStarted = tournament.Games.length
  1352. var teamsPerGame = tournament.TeamsPerGame.val;
  1353. var joker = 0;
  1354. //Single Elimination
  1355. if (tournamentType == 0) {
  1356. tournamentTotalGames = (Math.pow(teamsPerGame, tournament.NumberOfRoundsOrNumberOfTeams) - 1) / (teamsPerGame - 1);
  1357. if (lost == 1) {
  1358. myMaxGames = undefined;
  1359. }
  1360. else {
  1361. myMaxGames = [0, tournament.NumberOfRoundsOrNumberOfTeams]
  1362. }
  1363. }
  1364. //Double Eliminiation
  1365. else if (tournamentType == 1) {
  1366. tournamentTotalGames = 2 * Math.pow(2, tournament.NumberOfRoundsOrNumberOfTeams) - 1;
  1367. if (lost == 0) {
  1368. joker = 1;
  1369. }
  1370. if (lost == 2) {
  1371. myMaxGames = undefined;
  1372. }
  1373. else {
  1374. myMaxGames = [0, tournament.NumberOfRoundsOrNumberOfTeams * 2]
  1375. }
  1376. }
  1377. //Robin round
  1378. else if (tournamentType == 2) {
  1379. joker = 0;
  1380. var teams = [];
  1381. $.each(players.store.h, function (index, player) {
  1382. if (player.TP.State == 1) {
  1383. if (tournament.TeamSize > 1) {
  1384. teams.push(player.TP.TeamID)
  1385. }
  1386. else {
  1387. teams.push(Math.random())
  1388. }
  1389. }
  1390. });
  1391. var numOfTeams = teams.unique().length
  1392. myMaxGames = numOfTeams - 1;
  1393. tournamentTotalGames = ((numOfTeams - 1) * numOfTeams) / 2
  1394. }
  1395. else {
  1396. myMaxGames = undefined;
  1397. tournamentTotalGames = undefined;
  1398. }
  1399. var details;
  1400. if (myMaxGames == undefined) {
  1401. details = `
  1402. <font color="#858585">Won:</font> ${won} <br>
  1403. <font color="#858585">Lost:</font> ${lost} <br>
  1404. <font color="#858585">Games left:</font> None <br>
  1405. <font color="#858585">Progress: </font>${getTournamentProgress(tournamentGamesStarted, tournamentTotalGames)} <br>`
  1406. }
  1407. else if (tournamentGamesStarted == 0) {
  1408. details = `
  1409. <font color="#858585">Games left:</font> ${getGamesLeftString(myGames, myMaxGames, playing, joker)} <br>
  1410. <font color="#858585">Progress: </font>Not started`
  1411. }
  1412. else {
  1413. details = `
  1414. <font color="#858585">Playing:</font> ${playing} <br>
  1415. <font color="#858585">Won:</font> ${won} <br>
  1416. <font color="#858585">Lost:</font> ${lost} <br>
  1417. <font color="#858585">Games left:</font> ${getGamesLeftString(myGames, myMaxGames, playing, joker)} <br>
  1418. <font color="#858585">Progress: </font>${getTournamentProgress(tournamentGamesStarted, tournamentTotalGames)} <br>`
  1419. }
  1420. log(details)
  1421. return details;
  1422. }
  1423.  
  1424. function getTournamentProgress(tournamentGamesStarted, tournamentTotalGames) {
  1425. var progress = Math.round(tournamentGamesStarted / tournamentTotalGames * 100, 0)
  1426. if (progress == 100) {
  1427. return "Almost done"
  1428. }
  1429. else {
  1430. return progress + "%"
  1431. }
  1432. }
  1433.  
  1434. function getGamesLeftString(myGames, myMaxGames, playing, joker) {
  1435. if (typeof myMaxGames == "number") {
  1436. return (myMaxGames - myGames == 0 ? "None" : (myMaxGames - myGames))
  1437. }
  1438. else if (typeof myMaxGames == "object") {
  1439. if (playing == 1) {
  1440. if (myMaxGames[1] - myGames == 0) {
  1441. return "None"
  1442. }
  1443. else {
  1444. return (Math.max(joker, myMaxGames[0] - myGames)) + " - " + (myMaxGames[1] - myGames)
  1445. }
  1446. }
  1447. else {
  1448. return (Math.max(joker + 1, myMaxGames[0] - myGames)) + " - " + (myMaxGames[1] - myGames)
  1449. }
  1450. }
  1451. else {
  1452. return "undefined"
  1453. }
  1454. }
  1455.  
  1456. function setTournamentTableHeight() {
  1457. $("#MyTournamentsTable").parent().height(window.innerHeight - 100);
  1458. }
  1459. window.findMeIndex = -1;
  1460. window.findNextInTournament = function () {
  1461. var boxes = getPlayerBoxes();
  1462. var max = boxes.length - 1;
  1463. findMeIndex = findMeIndex == max ? 0 : findMeIndex + 1;
  1464. panzoomMatrix = undefined;
  1465. findInTournament();
  1466. }
  1467.  
  1468. function setupPlayerDataTable() {
  1469. var dataTable = $$$("#PlayersContainer > table").DataTable({
  1470. "order": [[4, "asc"], [3, "desc"]],
  1471. paging: false,
  1472. sDom: 't',
  1473. columnDefs: [{
  1474. targets: [0],
  1475. orderData: [0, 3]
  1476. }, {
  1477. targets: [1],
  1478. orderData: [1, 0]
  1479. }, {
  1480. targets: [2],
  1481. orderData: [2, 1, 0],
  1482. type: "rank"
  1483. }, {
  1484. targets: [3],
  1485. orderData: [3, ]
  1486. }, {
  1487. targets: [4],
  1488. orderData: [4]
  1489. }, {
  1490. targets: [5],
  1491. orderData: [5, 1, 0]
  1492. }],
  1493. "aoColumns": [
  1494. {
  1495. "orderSequence": ["asc", "desc"]
  1496. },
  1497. {
  1498. "orderSequence": ["asc", "desc"]
  1499. },
  1500. {
  1501. "orderSequence": ["asc", "desc"]
  1502. },
  1503. {
  1504. "orderSequence": ["desc", "asc"]
  1505. },
  1506. {
  1507. "orderSequence": ["desc", "asc"]
  1508. },
  1509. {
  1510. "orderSequence": ["desc", "asc"]
  1511. },
  1512. ]
  1513. });
  1514. loadDataTableCSS();
  1515. }
  1516. window.setCurrentplayer = function (player, noSearch) {
  1517. window.currentPlayer = {
  1518. id: player.id,
  1519. name: player.name,
  1520. fullID: player.fullID,
  1521. team: player.team
  1522. };
  1523. $("#selectContainer").toggle(100);
  1524. $("#activePlayer").html(htmlEscape(player.name == self.name ? "Me" : player.name));
  1525. $("#playerSelectInput").val("");
  1526. panzoomMatrix = undefined;
  1527. findMeIndex = 0;
  1528. $(".gold").removeClass("gold")
  1529. $("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "']").addClass("gold")
  1530. $("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "'] a").addClass("gold")
  1531. if (window.WL_Tournament.Tourn.Type == 2) { //Robin Round
  1532. $(".TeamTip_" + (window.currentPlayer.team == "" ? window.currentPlayer.id : window.currentPlayer.team.replace("Team ", "").charCodeAt(0) - 65)).addClass("gold")
  1533. }
  1534. else { //Elimination Tournament
  1535. getPlayerBoxes().find("a").addClass("gold")
  1536. }
  1537. if (noSearch != true) {
  1538. window.findInTournament();
  1539. }
  1540. }
  1541.  
  1542. function setupTournamentFindMe() {
  1543. $("body").keyup(function (event) {
  1544. // "Left" is pressed
  1545. var boxes = getPlayerBoxes();
  1546. var max = boxes.length - 1;
  1547. if (event.which == 37) {
  1548. findMeIndex = findMeIndex == 0 ? max : findMeIndex - 1;
  1549. panzoomMatrix = undefined;
  1550. findInTournament();
  1551. }
  1552. // "Right" is pressed
  1553. else if (event.which == 39) {
  1554. findMeIndex = findMeIndex == max ? 0 : findMeIndex + 1;
  1555. panzoomMatrix = undefined;
  1556. findInTournament();
  1557. }
  1558. // "Home" is pressed
  1559. else if (event.which == 36) {
  1560. findMeIndex = 0;
  1561. panzoomMatrix = undefined;
  1562. findInTournament();
  1563. }
  1564. // "End" is pressed
  1565. else if (event.which == 35) {
  1566. findMeIndex = boxes.length - 1;
  1567. panzoomMatrix = undefined;
  1568. findInTournament();
  1569. }
  1570. });
  1571. window.players = []
  1572. $("[href='#SettingsTab']").parent().after('<li id="findMe" class="ui-state-default ui-corner-top"><div style="cursor: pointer" class="ui-tabs-anchor" onclick="window.findNextInTournament()">Find <label id="activePlayer"></label></div><a id="showPlayerSelect">▼</a></li>');
  1573. createSelector('#findMe:hover', 'border: 1px solid #59b4d4;background: #0078a3 url("https://d2wcw7vp66n8b3.cloudfront.net/jui4/images/ui-bg_glass_40_0078a3_1x400.png") 50% 50% repeat-x;font-weight: bold;color: #ffffff;border-bottom-width: 0')
  1574. createSelector('#findMe', 'border: 1px solid #666666;border-bottom-width: 0')
  1575. var css = '-webkit-keyframes pulsate{ 0% { background-color: rgba(0,0,0,0); } 50% { background-color: olive; } 100% { background-color: rgba(0,0,0,0); }}@keyframes pulsate { 0% { background-color: rgba(0,0,0,0); } 50% { background-color: olive; } 100% { background-color: rgba(0,0,0,0); }}.pulsate { -webkit-animation: pulsate 1s ease-in 1; -moz-animation: pulsate 1s ease-in 1; -ms-animation: pulsate 1s ease-in 1; -o-animation: pulsate 1s ease-in 1; animation: pulsate 1s ease-in 1;}-webkit-keyframes pulsate-border{ 0% { border: 3px solid #c4c2c4; } 25% { border: 3px solid red; } 50% { border: 3px solid red; } 100% { border: 3px solid #c4c2c4; }}@keyframes pulsate-border { 0% { border: 3px solid #c4c2c4; } 25% { border: 3px solid red; }50% { border: 3px solid red; } 100% { border: 3px solid #c4c2c4; }}.pulsate-border { -webkit-animation: pulsate-border 2s ease-in 1; -moz-animation: pulsate-border 2s ease-in 1; -ms-animation: pulsate-border 2s ease-in 1; -o-animation: pulsate-border 2s ease-in 1; animation: pulsate-border 2s ease-in 1;}'
  1576. addCSS(css)
  1577. $("#findMe").append('<div id="selectContainer"><div id="playerSelectInputContainer"><input placeholder="Search a Player" type="text" id="playerSelectInput"></input></div><div id="playerContainer"></div></div>');
  1578. addCSS(`
  1579. .TeamBox a {
  1580. color: azure;
  1581. }
  1582. `)
  1583. self = {
  1584. id: warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID,
  1585. name: warlight_shared_viewmodels_SignIn.get_CurrentPlayer().Name,
  1586. fullID: String(warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ProfileToken).substring(0, 2) + warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID + String(warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ProfileToken).substring(2, 4),
  1587. team: $("[data-playerid='" + warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID + "'] td:nth-of-type(2)").text()
  1588. };
  1589. window.setCurrentplayer(self, true);
  1590. $.each($("#PlayingPlayers tr"), function (key, playerRow) {
  1591. var id = $(playerRow).attr("data-playerid");
  1592. var fullID = $(playerRow).find("a").get($(playerRow).find("a").length - 1).href.replace(/.*warzone.com\/Profile\?p=/, "");
  1593. var name = $(playerRow).find("td a").text();
  1594. var img = $(playerRow).find("td img").attr("src");
  1595. var team = $("[data-playerid='" + id + "'] td:nth-of-type(2)").text();
  1596. if (img && img.indexOf("MemberIcon") > -1) {
  1597. img = "";
  1598. }
  1599. window.players.push({
  1600. id: id,
  1601. fullID: fullID,
  1602. name: name,
  1603. img: img,
  1604. team: team
  1605. });
  1606. });
  1607. $("#playerSelectInput").on('input', function (data) {
  1608. $(".playerElement").remove();
  1609. var search = $(this).val().toLowerCase();
  1610. $("#playerContainer").append("<div class='playerElement' onclick='setCurrentplayer(self)'>" + self.name + " (Me)</div>")
  1611. $.each(window.players, function (key, player) {
  1612. if (player.name.toLowerCase().indexOf(search) > -1 && self.name != player.name) {
  1613. var img = player.img ? "<img src='" + player.img + "'>" : "";
  1614. $("#playerContainer").append("<div onclick='setCurrentplayer(players[" + key + "])' class='playerElement'>" + img + "<span>" + htmlEscape(player.name) + "</span>" + "</div>")
  1615. }
  1616. });
  1617. $("#activePlayer").html(window.currentPlayer.name == self.name ? "Me" : window.currentPlayer.name);
  1618. $("#playerContainer").scrollTop(0)
  1619. });
  1620. $("#playerSelectInput").trigger("input");
  1621. $("#showPlayerSelect").on("click", function () {
  1622. $("#selectContainer").toggle(100);
  1623. $("#playerContainer").scrollTop(0);
  1624. $("#playerSelectInput").trigger("input");
  1625. $("#playerSelectInput").focus();
  1626. });
  1627. createSelector("#playerSelectInputContainer", "height: 28px; ");
  1628. createSelector(".border-red", "border: 3px red solid !important; ");
  1629. createSelector(".playerElement span, .playerElement img", "display:inline-block; margin-right: 10px");
  1630. createSelector("#showPlayerSelect", "color: #DDDDDD;font-size: 14px;margin: 8px 10px 0px -3px;;cursor: pointer; display: inline-block;");
  1631. createSelector("#playerSelectInput", "display: block;margin: 5px 3%;width: 93%;");
  1632. createSelector("#activePlayer", "cursor:pointer; margin: 0");
  1633. createSelector(".playerElement", "border-bottom: 1px gray solid;padding: 7px;color: white; clear:both; height: 30px; font-weight: normal;");
  1634. createSelector(".playerElement:hover", "background: rgb(102, 102, 102);");
  1635. createSelector("#playerContainer", "border: 2px gray solid; overflow-y: auto; overflow-x: hidden;max-height: 275px; min-width: 175px; ");
  1636. createSelector(".gold", "color: gold!important")
  1637. createSelector("#selectContainer", "cursor: pointer; background:rgb(23, 23, 23);position: fixed; z-index: 10;border: 2px gray solid;border-radius: 5px;box-shadow: 0 20px 50px 3px black;margin-top: 16px;display: none");
  1638. }
  1639. window.panzoomMatrix;
  1640. window.findInTournament = function () {
  1641. var id;
  1642. $("#selectContainer").hide(100);
  1643. if ($("[href='#PlayersTab']").parent().hasClass("ui-state-active")) {
  1644. id = window.currentPlayer.id;
  1645. if ($("#PlayingPlayers [data-playerid='" + id + "']").length > 0) {
  1646. var player = $("#PlayingPlayers [data-playerid='" + id + "']");
  1647. var box = $("#CenterTabs").parent()
  1648. var offset = player.offset().top - box.offset().top - box.height() / 2
  1649. box.stop().animate({
  1650. scrollTop: offset
  1651. }, '500', 'swing');
  1652. window.setTimeout(function () {
  1653. $("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "']").addClass("pulsate");
  1654. window.setTimeout(function () {
  1655. $(".pulsate").removeClass("pulsate");
  1656. }, 1000);
  1657. }, 250);
  1658. }
  1659. else {
  1660. showInfo("You didn't join this tournament.", $("#findMe").offset().top + 25, $("#findMe").offset().left + 25);
  1661. }
  1662. // Elimination Tournament
  1663. }
  1664. else if ($("[href='#BracketTab']").parent().hasClass("ui-state-active") && window.WL_Tournament.Tourn.Type != 2) {
  1665. id = window.currentPlayer.fullID;
  1666. //Started
  1667. if (window.WL_Tournament.Tourn.State >= 1 && $("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "']").length > 0) {
  1668. if (!panzoomMatrix) {
  1669. var currentMatrix = $("#Visualize").panzoom("getMatrix");
  1670. $("#Visualize").panzoom("reset", {
  1671. animate: false
  1672. });
  1673. VisualizePanzoom.panzoom("zoom", {
  1674. increment: 0.75,
  1675. animate: false
  1676. })
  1677. var boxes = getPlayerBoxes();
  1678. $(".TeamBoxHighlighted").removeClass("TeamBoxHighlighted");
  1679. boxes.addClass("TeamBoxHighlighted");
  1680. console.log("ttt")
  1681. console.log(boxes.get(findMeIndex))
  1682. console.log(getPlayerBoxes())
  1683. console.log(findMeIndex)
  1684. var offsetTop = $(boxes.get(findMeIndex)).offset().top - $("#VisualizeContainer").offset().top - $("#VisualizeContainer").height() / 4;
  1685. var offsetLeft = $(boxes.get(findMeIndex)).offset().left - $("#VisualizeContainer").offset().left - $("#VisualizeContainer").width() / 2;
  1686. $(".border-red").removeClass("border-red");
  1687. $(boxes.get(findMeIndex)).addClass("border-red");
  1688. $("#Visualize").panzoom("pan", 0 - offsetLeft, 100 - offsetTop, {
  1689. relative: true,
  1690. animate: false
  1691. });
  1692. panzoomMatrix = $("#Visualize").panzoom("getMatrix");
  1693. $("#Visualize").panzoom("setMatrix", currentMatrix, {
  1694. animate: false
  1695. });
  1696. }
  1697. window.setTimeout(function () {
  1698. $("#Visualize").panzoom("setMatrix", panzoomMatrix, {
  1699. animate: true
  1700. })
  1701. window.setTimeout(function () {
  1702. //getPlayerBoxes().addClass("pulsate-border");
  1703. window.setTimeout(function () {
  1704. $(".pulsate-border").removeClass("pulsate-border");
  1705. }, 2000)
  1706. }, 400);
  1707. }, 10)
  1708. }
  1709. else {
  1710. showFindMeError();
  1711. }
  1712. // Robin Round Tournament
  1713. }
  1714. else if ($("[href='#BracketTab']").parent().hasClass("ui-state-active") && window.WL_Tournament.Tourn.Type == 2) {
  1715. //Started
  1716. if ($("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "']").length > 0) {
  1717. $(".TeamTip_" + (window.WL_Tournament.Tourn.TeamSize == 1 ? window.currentPlayer.id : window.currentPlayer.team.replace("Team ", "").charCodeAt(0) - 65)).addClass("pulsate")
  1718. window.setTimeout(function () {
  1719. $(".pulsate").removeClass("pulsate")
  1720. }, 2000)
  1721. }
  1722. else {
  1723. showFindMeError()
  1724. }
  1725. }
  1726. }
  1727.  
  1728. function showFindMeError() {
  1729. if ($("#PlayingPlayers [data-playerid='" + window.currentPlayer.id + "']").length == 0) {
  1730. showInfo("You didn't join this tournament.", $("#findMe").offset().top + 25, $("#findMe").offset().left + 25);
  1731. }
  1732. else {
  1733. showInfo("This tournament didn't start yet.", $("#findMe").offset().top + 25, $("#findMe").offset().left + 25);
  1734. }
  1735. }
  1736.  
  1737. function getPlayerBoxes() {
  1738. var boxes = $(".GameBox [href='/Profile?p=" + window.currentPlayer.fullID + "']").closest(".TeamBox");
  1739. if (boxes.length == 0) {
  1740. boxes = $("a:contains('" + window.currentPlayer.team + "')").closest(".TeamBox");
  1741. }
  1742. return boxes;
  1743. }
  1744.  
  1745. function colorTournamentCreatorInChat() {
  1746. var creatorLink = $("#HostLabel a:last").attr("href")
  1747. addCSS(`
  1748. #ChatContainer a[href='` + creatorLink + `'] {
  1749. color: cornflowerblue
  1750. }
  1751. `)
  1752. }
  1753.  
  1754. function highlightEliminatedPlayers() {
  1755. addCSS(`
  1756. .eliminated {
  1757. color: crimson;
  1758. background: rgba(255,0,0,0.03);
  1759. }
  1760. `)
  1761. var players = WL_Tournament.Players._players.store.h;
  1762. var maxLosses;
  1763. var tournamentType = WL_Tournament.Tourn.Type;
  1764. if (tournamentType == 0 || tournamentType == 1) {
  1765. if (tournamentType == 0) {
  1766. //single elimination
  1767. maxLosses = 1;
  1768. }
  1769. else if (tournamentType == 1) {
  1770. //double elimination
  1771. maxLosses = 2;
  1772. }
  1773. $.each(players, function (key, player) {
  1774. if (player.NumLosses >= maxLosses) {
  1775. //player is eliminated
  1776. $("[data-playerid='" + key + "']").closest("tr").addClass("eliminated")
  1777. }
  1778. })
  1779. }
  1780. }
  1781.  
  1782. function setupWhoInvitedMe() {
  1783. console.log("running this");
  1784. addCSS(`
  1785. .whoInvited {
  1786. font-size: 11px;
  1787. color: gray!important;
  1788. cursor: pointer;
  1789. margin-bottom: 25px;
  1790. display: inline-block;
  1791. }
  1792. `)
  1793. window.setTimeout(function () {
  1794. var id = $(".navbar a[href*='Profile']").attr("href").match(/[\/a-zA-Z\?=]*([0-9]*)/)[1].slice(2, -2);
  1795. var invitedById = WL_Tournament.Players._players.store["h"][id].TP.InvitedBy.val;
  1796. if (invitedById > 0) {
  1797. var invitingPlayer = WL_Tournament.Players._players.store["h"][invitedById].TP.Player;
  1798. var url = "/Profile?p=" + [String(invitingPlayer.ProfileToken).slice(0, 2), invitedById, String(invitingPlayer.ProfileToken).slice(-2)].join("");
  1799. var a = $("<a>");
  1800. a.addClass("whoInvited");
  1801. a.attr("target", "_blank");
  1802. a.text("Invited by " + invitingPlayer.DisplayName);
  1803. console.log(("#DataTables_Table_0").length)
  1804. a.attr("href", url);
  1805. $("#ShowAllBtn").prev().before(a)
  1806. console.log(invitingPlayer)
  1807. }
  1808. }, 1500)
  1809. }
  1810. function setupRealTimeLadderTable() {
  1811. if($("#RealTimeLadderTable").length == 0) {
  1812. return;
  1813. }
  1814. if( $(".extendedRTLadderRow").length == 0) {
  1815. createSelector(".extendedRTLadderRow .rtBox", "width: calc(100%/2);");
  1816. createSelector(".extendedRTLadderRow span", "");
  1817. createSelector(".rtLeft", "float:left");
  1818. createSelector(".rtRight", "float:Right");
  1819. createSelector(".rtRight a", " padding: 10px 30px;position: absolute;margin-left: -75px;");
  1820. createSelector(".newGamesRT", "display:block");
  1821. createSelector(".rtLabelBig", "font-size: 18px; margin: 5px");
  1822. }
  1823. var joinLeaveText = $(".rtRight a").text()
  1824. var joinLeaveLink = $(".rtRight a").attr("href")
  1825. $(".extendedRTLadderRow").remove();
  1826. $("#RealTimeLadderTable").append('<tr class="extendedRTLadderRow"><td colspan="2"><div class="rtLeft rtBox"><span class="newGamesRT">New Games in<br></span><div class="rtLabelBig">' + getRealTimeLadderTimerHTML() + '<a href="' + joinLeaveLink + '" class="rtLabelBig">' + joinLeaveText + '</a></div></td></tr>')
  1827. $("[href='/LadderSeason?ID=3']").text("Ladder Page")
  1828. WLPost("/LadderSeason?ID=3", "WaiterData=1", function(data) {
  1829. if(JSON.parse(data).length > 0) {
  1830. $(".rtRight a").attr("href", "https://www.warlight.net/LadderLeave?Ladder=RealTime")
  1831. $(".rtRight a").text("Leave!")
  1832. } else {
  1833. $(".rtRight a").attr("href", "https://www.warlight.net/LadderJoin?Ladder=RealTime")
  1834. $(".rtRight a").text("Join!")
  1835. }
  1836. });
  1837. setRTLadderTime()
  1838. }
  1839.  
  1840. function setupRealTimeLadderPageTimer() {
  1841. $("#LadderJoinBtn").after("<div>New Games in " + getRealTimeLadderTimerHTML() +"</div>")
  1842. $("#LeaveLadderBtn").after("<div>New Games in " + getRealTimeLadderTimerHTML() +"</div>")
  1843. setRTLadderTime()
  1844. }
  1845.  
  1846. function getRealTimeLadderTimerHTML() {
  1847. return '<span class="rtMin">00</span>:<span class="rtSec">00</span></div></div><div class="rtRight rtBox">'
  1848. }
  1849.  
  1850.  
  1851. function setRTLadderTime() {
  1852. var date = new Date()
  1853. date.setMinutes(Math.ceil((new Date().getMinutes() + date.getSeconds() / 60) / 5) * 5)
  1854. date.setSeconds(0)
  1855. var diff = (date - new Date()) / 1000
  1856. var min = Math.floor(diff / 60) % 60
  1857. diff -= min * 60
  1858. var sec = diff % 60
  1859. $(".rtMin").text(padLeft(min))
  1860. $(".rtSec").text(padLeft(sec))
  1861. }
  1862.  
  1863. function padLeft(str) {
  1864. str = Math.round(str)
  1865. len = 2
  1866. symbol = '0'
  1867. while(String(str).length < len) {
  1868. str = symbol + str;
  1869. }
  1870. return str
  1871. }
  1872. function setupBookmarkMenu() {
  1873. bookmarkBody = "<label for='bookmarkName'>Name</label><input style='width:100%;color: lightgray;text-align: left;' type='text' id='bookmarkName'><br><br><label for='bookmarkURL'>Url</label><input style='width:100%; text-align: left; color: lightgray' id='bookmarkURL' type='text'><br><br><label for='bookmarkNewWindow'>Open in new Window</label><input style='float:left;' id='bookmarkNewWindow' type='checkbox'>";
  1874.  
  1875. $("body").append(`
  1876. <div class="modal modal-500 fade" id="bookmarkMenu" tabindex="-1" role="dialog">
  1877. <div class="modal-dialog" role="document">
  1878. <div class="modal-content">
  1879. <div class="modal-header">
  1880. <h5 class="modal-title" id="exampleModalLongTitle">Add Bookmark</h5>
  1881. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  1882. <span aria-hidden="true">&times;</span>
  1883. </button>
  1884. </div>
  1885. <div class="modal-body">
  1886. <div class="d-flex flex-column">
  1887. <div style="padding:10px" class="d-flex flex-column">
  1888. <label for='bookmarkName'>Name</label>
  1889. <input type='text' id='bookmarkName'>
  1890. <label for='bookmarkURL'>Url</label>
  1891. <input id='bookmarkURL' type='text'>
  1892. </div>
  1893. <div class="form-check">
  1894. <label class="form-check-label">
  1895. <input id='bookmarkNewWindow' type='checkbox'>
  1896. Open in new Window
  1897. </label>
  1898. </div>
  1899. </div>
  1900. </div>
  1901. <div class="modal-footer">
  1902. <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
  1903. <button type="button" class="btn btn-success" data-dismiss="modal" onclick='saveBookmark()'>Save</button>
  1904. </div>
  1905. </div>
  1906. </div>
  1907. </div>
  1908. `)
  1909.  
  1910. createSelector(".highlightedBookmark", "background-color:rgb(50, 50, 50);cursor:pointer;");
  1911. $("body").append("<ul class='context-menu bookmark-context'><li onclick='editBookmark()'>Edit</li><li onclick='moveBookmarkUp()'>Move up</li><li onclick='moveBookmarkDown()'>Move Down</li></ul>")
  1912. $("body").append("<ul class='context-menu thread-context'><li onclick='hideThread()'>Hide</li></ul>")
  1913. bindCustomContextMenu()
  1914.  
  1915. }
  1916.  
  1917. function setupBookmarkTable() {
  1918. $(".SideColumn").prepend('<table class="dataTable" cellspacing="0" width="100%" id="BookmarkTable" style="text-align: left;"><thead><tr><td style="text-align: center">Bookmarks<img src="' + IMAGES.PLUS + '" width="15" height="15" onclick="showAddBookmark()"style="display:inline-block;float:right; opacity: 0.6; margin-right:15px; cursor: pointer"></td></tr></thead></table><br>');
  1919.  
  1920. refreshBookmarks();
  1921. bindBookmarkTable();
  1922. }
  1923.  
  1924. function refreshBookmarks() {
  1925. Database.readAll(Database.Table.Bookmarks, function(bookmarks) {
  1926. $("#BookmarkTable tbody").remove();
  1927. bookmarks.sort(function(a, b) {return a.order - b.order})
  1928. var data = "<tbody>";
  1929. $.each(bookmarks, function (key, bookmark) {
  1930. data += '<tr data-bookmarkId="' + bookmark.id + '" data-order="' + bookmark.order + '"><td><a ' + (bookmark.newWindow ? 'target="_blank"' : "") + ' href="' + bookmark.url + '">' + bookmark.name + '</a>';
  1931. data += '<a onclick="deleteBookmark(' + bookmark.id + ')" style="display:inline-block;float:right; opacity: 0.6;cursor: pointer;margin-right:5px">';
  1932. data += '<span class="ui-icon ui-icon-trash"></span></a></td></tr>';
  1933. })
  1934.  
  1935. $("#BookmarkTable").append(data + '</tbody>');
  1936. warlight_shared_viewmodels_WaitDialogVM.Stop()
  1937. $(".loader").fadeOut("fast", function() {
  1938. if($(".loader")) {
  1939. $(".loader").remove();
  1940. window.timeUserscriptReady = new Date().getTime();
  1941. log("Time userscript ready " + (timeUserscriptReady - timeUserscriptStart) / 1000)
  1942. }
  1943. })
  1944. })
  1945.  
  1946. }
  1947.  
  1948. window.bookmarkOrder;
  1949. window.bookmarkId;
  1950. window.showAddBookmark = function () {
  1951. $("#bookmarkMenu").modal("show")
  1952. bookmarkId = undefined
  1953. bookmarkOrder = undefined
  1954. $("#bookmarkURL").val("");
  1955. $("#bookmarkName").val("");
  1956. $("#bookmarkNewWindow").prop("checked", false);
  1957. }
  1958.  
  1959. window.editBookmark = function () {
  1960. Database.read(Database.Table.Bookmarks, bookmarkId, function(bookmark) {
  1961. $("#bookmarkURL").val(bookmark.url);
  1962. $("#bookmarkName").val(bookmark.name);
  1963. $("#bookmarkNewWindow").prop("checked", bookmark.newWindow);
  1964. $("#bookmarkMenu").modal("show")
  1965. })
  1966. }
  1967.  
  1968. window.moveBookmarkUp = function() {
  1969. Database.readAll(Database.Table.Bookmarks, function(bookmarks) {
  1970. var bookmark;
  1971. var newIdx = -1
  1972. $.each(bookmarks, function (key, bm) {
  1973. if (bookmarkId == bm.id) {
  1974. bookmark = bm
  1975. }
  1976. })
  1977. bookmarks.sort(function(a,b){return a.order - b.order});
  1978. var previousBookmark1 = bookmarks[bookmarks.indexOf(bookmark) - 1]
  1979. var previousBookmark2 = bookmarks[bookmarks.indexOf(bookmark) - 2] || {order: 0}
  1980. if(previousBookmark1) {
  1981. bookmark.order = (previousBookmark1.order + previousBookmark2.order) / 2
  1982.  
  1983. Database.update(Database.Table.Bookmarks, bookmark, bookmark.id, function() {
  1984. $("#bookmarkURL").val('');
  1985. $("#bookmarkName").val('');
  1986. $("#bookmarkNewWindow").prop('checked', false);
  1987. $(".overlay").fadeOut();
  1988. refreshBookmarks();
  1989. })
  1990. }
  1991. })
  1992. }
  1993.  
  1994. window.moveBookmarkDown = function() {
  1995. Database.readAll(Database.Table.Bookmarks, function(bookmarks) {
  1996. var bookmark;
  1997. var newIdx = -1
  1998. $.each(bookmarks, function (key, bm) {
  1999. if (bookmarkId == bm.id) {
  2000. bookmark = bm
  2001. }
  2002. })
  2003. bookmarks.sort(function(a,b){return a.order - b.order});
  2004. var nextBookmark1 = bookmarks[bookmarks.indexOf(bookmark) + 1]
  2005. var nextBookmark2 = bookmarks[bookmarks.indexOf(bookmark) + 2] || {order: 100000}
  2006. if(nextBookmark1) {
  2007. bookmark.order = (nextBookmark1.order + nextBookmark2.order) / 2
  2008. Database.update(Database.Table.Bookmarks, bookmark, bookmark.id, function() {
  2009. $("#bookmarkURL").val('');
  2010. $("#bookmarkName").val('');
  2011. $("#bookmarkNewWindow").prop('checked', false);
  2012. $(".overlay").fadeOut();
  2013. refreshBookmarks();
  2014. })
  2015. }
  2016. })
  2017. }
  2018.  
  2019.  
  2020. window.deleteBookmark = function (id) {
  2021. Database.delete(Database.Table.Bookmarks, id, function() {
  2022. refreshBookmarks();
  2023. })
  2024. }
  2025.  
  2026. window.saveBookmark = function () {
  2027. $("#bookmarkMenu").hide();
  2028. var url = $("#bookmarkURL").val().trim();
  2029. url = (url.lastIndexOf('http', 0) != 0) && (url.lastIndexOf('javascript', 0) != 0) ? "http://" + url : url;
  2030. var name = $("#bookmarkName").val().trim();
  2031. var newWindow = $("#bookmarkNewWindow").prop("checked");
  2032. if(bookmarkId == undefined) {
  2033. Database.readAll(Database.Table.Bookmarks, function(bookmarks) {
  2034. bookmarks.sort(function(a, b) {return a.order - b.order})
  2035. var bookmark = {
  2036. name: name,
  2037. url: url,
  2038. newWindow: newWindow,
  2039. order: (bookmarks.length > 0) ? bookmarks[bookmarks.length - 1].order + 1 : 1
  2040. }
  2041. Database.add(Database.Table.Bookmarks, bookmark, function() {
  2042. showBookmarkTable();
  2043. refreshBookmarks();
  2044. })
  2045. })
  2046. } else {
  2047. var bookmark = {
  2048. name: name,
  2049. url: url,
  2050. newWindow: newWindow,
  2051. order: bookmarkOrder
  2052. }
  2053. Database.update(Database.Table.Bookmarks, bookmark, bookmarkId, function() {
  2054. showBookmarkTable();
  2055. refreshBookmarks();
  2056. })
  2057. }
  2058. $("#bookmarkURL").val('');
  2059. $("#bookmarkName").val('');
  2060. $("#bookmarkNewWindow").prop('checked', false);
  2061. $(".overlay").fadeOut();
  2062. }
  2063.  
  2064. function hideBookmarkTable() {
  2065. $("#BookmarkTable").hide();
  2066. if ($("#BookmarkTable").prev().hasClass("followWrap")) {
  2067. $("#BookmarkTable").prev().hide();
  2068. }
  2069. if ($("#BookmarkTable").next().is('br')) {
  2070. $("#BookmarkTable").next().hide();
  2071. }
  2072. }
  2073.  
  2074. function showBookmarkTable() {
  2075. $("#BookmarkTable").show();
  2076. if ($("#BookmarkTable").prev().hasClass("followWrap")) {
  2077. $("#BookmarkTable").prev().show();
  2078. }
  2079. if ($("#BookmarkTable").next().is('br')) {
  2080. $("#BookmarkTable").next().show();
  2081. }
  2082. }
  2083.  
  2084. window.bookmarkForumThread = function () {
  2085. var title = $("title").text().replace(' - Play Risk Online Free - WarLight', '');
  2086. var url = window.location.href;
  2087.  
  2088. $("#bookmarkURL").val(url);
  2089. $("#bookmarkName").val(title);
  2090. showAddBookmark();
  2091.  
  2092. }
  2093. window.bookmarkTournament = function () {
  2094. var title = $("#TournamentName").text().replace("Tournament: ", "").trim();
  2095. var url = window.location.href;
  2096.  
  2097. $("#bookmarkURL").val(url);
  2098. $("#bookmarkName").val(title);
  2099. showAddBookmark();
  2100.  
  2101. }
  2102.  
  2103. window.bookmarkLevel = function () {
  2104. var title = $("h1").text()
  2105. var url = window.location.href;
  2106.  
  2107. $("#bookmarkURL").val(url);
  2108. $("#bookmarkName").val(title);
  2109. showAddBookmark();
  2110.  
  2111. }
  2112.  
  2113. function addDefaultBookmark() {
  2114. var bookmark = {
  2115. name: "Muli's userscript (Tidy up Your Dashboard)",
  2116. url: "https://www.warlight.net/Forum/106092-tidy-up-dashboard-2",
  2117. newWindow: false,
  2118. order: 0
  2119. }
  2120. Database.add(Database.Table.Bookmarks, bookmark, function() {
  2121. showBookmarkTable();
  2122. refreshBookmarks();
  2123. })
  2124. }
  2125.  
  2126. function bindBookmarkTable() {
  2127. $("#BookmarkTable").bind("contextmenu", function (event) {
  2128. $(".highlightedBookmark").removeClass("highlightedBookmark")
  2129. var row = $(event.target).closest("tr");
  2130. bookmarkId = row.attr("data-bookmarkid")
  2131. bookmarkOrder = row.attr("data-order")
  2132. if(bookmarkId && bookmarkOrder) {
  2133. event.preventDefault();
  2134. row.addClass("highlightedBookmark")
  2135. // Show contextmenu
  2136. $(".bookmark-context").finish().toggle(100).
  2137. css({
  2138. top: event.pageY + "px",
  2139. left: event.pageX + "px"
  2140. });
  2141. }
  2142. });
  2143. }
  2144.  
  2145. function setupLevelBookmark() {
  2146. $("h1").after(`
  2147. <a style="cursor:pointer" onclick="bookmarkLevel()">Bookmark</a><br>
  2148. `)
  2149. }
  2150. function setupLadderClotOverview() {
  2151. console.log("setupLadderClotOverview")
  2152. $("h1").text($("h1").text() + " & Community Events")
  2153. loadClots(function(clotInfo) {
  2154. console.log("clotInfo")
  2155. console.log(clotInfo)
  2156. if(!clotInfo) {
  2157. return
  2158. }
  2159. var clots = clotInfo
  2160.  
  2161. var ladders = clots['leagues']
  2162. var md = ""
  2163. var rt = ""
  2164. var leagues = ""
  2165. var counter = 0
  2166. $.each(ladders, function (key, val) {
  2167. if (val.type == "realtime") {
  2168. rt += "<li><big><a target='_blank' href=" + val.url + ">" + val.name + "</a> using Real-Time boot times</big></li><br><br>"
  2169. counter++
  2170. } else if (val.type == "multiday") {
  2171. md += "<li><big><a target='_blank' href = " + val.url + ">" + val.name + "</a> using Multi-Day boot times</big></li><br><br>"
  2172. counter++
  2173. } else {
  2174. leagues += `<li><big><a target='_blank' href="${val.url}">${val.name}</a> ${getPlayerString(val.players)}</big></li><br><br>`
  2175. counter++
  2176. }
  2177.  
  2178. })
  2179. $("#MainSiteContent > div").append("Warlight currently has " + toWords(counter) + " Community Events:<br><br>")
  2180.  
  2181. $("#MainSiteContent > div").append("<ul id='clotInfo'></ul>")
  2182. $("#clotInfo").append(rt)
  2183. $("#clotInfo").append(md)
  2184. $("#clotInfo").append(leagues)
  2185. });
  2186. }
  2187.  
  2188. function getPlayerString(players) {
  2189. if(players) {
  2190. return `<span class='clotPlayers'>${players} players participating</span>`
  2191. }
  2192. return ""
  2193. }
  2194.  
  2195. function loadClots(cb) {
  2196. log("loading clots");
  2197. $.ajax({
  2198. type: 'GET',
  2199. url: 'https://raw.githubusercontent.com/psenough/wl_clot/master/hub/list.jsonp',
  2200. dataType: 'text',
  2201. crossDomain: true,
  2202. }).done(function(response){
  2203. try {
  2204. var response = eval(response);
  2205. console.log(response.data)
  2206. var json = response.data
  2207. var clotInfo = JSON.stringify(json)
  2208. sessionStorage.setItem('clots', clotInfo);
  2209. if(cb) {
  2210. cb(json)
  2211. }
  2212. var datetime = json.datetime
  2213. log("clot update " + datetime)
  2214. } catch (e) {
  2215. log("Error parsing CLOTs")
  2216. log(e)
  2217. }
  2218. }).fail(function(e){
  2219. log("Error loading CLOTs")
  2220. log(e);
  2221. });
  2222. }
  2223.  
  2224. function toWords(number) {
  2225. var NS = [
  2226. {value: 1000000000000000000000, str: "sextillion"},
  2227. {value: 1000000000000000000, str: "quintillion"},
  2228. {value: 1000000000000000, str: "quadrillion"},
  2229. {value: 1000000000000, str: "trillion"},
  2230. {value: 1000000000, str: "billion"},
  2231. {value: 1000000, str: "million"},
  2232. {value: 1000, str: "thousand"},
  2233. {value: 100, str: "hundred"},
  2234. {value: 90, str: "ninety"},
  2235. {value: 80, str: "eighty"},
  2236. {value: 70, str: "seventy"},
  2237. {value: 60, str: "sixty"},
  2238. {value: 50, str: "fifty"},
  2239. {value: 40, str: "forty"},
  2240. {value: 30, str: "thirty"},
  2241. {value: 20, str: "twenty"},
  2242. {value: 19, str: "nineteen"},
  2243. {value: 18, str: "eighteen"},
  2244. {value: 17, str: "seventeen"},
  2245. {value: 16, str: "sixteen"},
  2246. {value: 15, str: "fifteen"},
  2247. {value: 14, str: "fourteen"},
  2248. {value: 13, str: "thirteen"},
  2249. {value: 12, str: "twelve"},
  2250. {value: 11, str: "eleven"},
  2251. {value: 10, str: "ten"},
  2252. {value: 9, str: "nine"},
  2253. {value: 8, str: "eight"},
  2254. {value: 7, str: "seven"},
  2255. {value: 6, str: "six"},
  2256. {value: 5, str: "five"},
  2257. {value: 4, str: "four"},
  2258. {value: 3, str: "three"},
  2259. {value: 2, str: "two"},
  2260. {value: 1, str: "one"}
  2261. ];
  2262.  
  2263. var result = '';
  2264. for (var n of NS) {
  2265. if(number>=n.value){
  2266. if(number<=20){
  2267. result += n.str;
  2268. number -= n.value;
  2269. if(number>0) result += ' ';
  2270. }else{
  2271. var t = Math.floor(number / n.value);
  2272. var d = number % n.value;
  2273. if(d>0){
  2274. return intToEnglish(t) + ' ' + n.str +' ' + intToEnglish(d);
  2275. }else{
  2276. return intToEnglish(t) + ' ' + n.str;
  2277. }
  2278.  
  2279. }
  2280. }
  2281. }
  2282. return result;
  2283. }
  2284. window.userscriptSettings = [
  2285. {
  2286. id: 'scrollGames',
  2287. text: 'Fixed Window with scrollable Games',
  2288. selected: true,
  2289. title: 'Dashboard',
  2290. addBreak: false,
  2291. help: 'This option displays My-, Open-, Coin-Games in a scrollable box, which removes a lot of unesessary scrolling. You can find tabs to switch between the different type of games. '
  2292. },
  2293. {
  2294. id: 'hideMyGamesIcons',
  2295. text: 'Hide Icons in "My Games"',
  2296. selected: false,
  2297. title: '',
  2298. addBreak: false,
  2299. help: 'This option hides game icons for My Games on the dashboard'
  2300. },
  2301. {
  2302. id: 'autoRefreshOnFocus',
  2303. text: 'Automatically refresh Games on Tab-Focus',
  2304. selected: true,
  2305. title: '',
  2306. addBreak: false,
  2307. help: 'This option automatically refreshes your games after switching back to WarLight from a different tab / program. This only applies if WarLight was idle for 30 or more seconds.'
  2308. },
  2309. {
  2310. id: 'highlightTournaments',
  2311. text: 'Highlight Tournament invites',
  2312. selected: false,
  2313. title: '',
  2314. addBreak: false,
  2315. },
  2316. {
  2317. id: 'hideRightColumn',
  2318. text: 'Hide Right Column',
  2319. selected: false,
  2320. title: '',
  2321. addBreak: false,
  2322. help: 'This option hides the right column completely and leaves you alone with My-, Open- and Coin-Games.'
  2323. },
  2324. {
  2325. id: 'hidePromotedGames',
  2326. text: 'Hide Promoted Games',
  2327. selected: false,
  2328. title: '',
  2329. addBreak: false,
  2330. help: 'This option hides the promoted (coin) games on the dashboard'
  2331. },
  2332. {
  2333. id: 'hideCoinsGlobally',
  2334. text: 'Hide Coins Globally',
  2335. selected: false,
  2336. title: '',
  2337. addBreak: false,
  2338. help: 'This option removes everything from Warlight related to Coins'
  2339. },
  2340. {
  2341. id: 'showPrivateNotesOnProfile',
  2342. text: 'Show Private Notes on Profile',
  2343. selected: true,
  2344. title: '',
  2345. addBreak: false,
  2346. help: 'This option will show you your private notes which you made on a player directly on their profile page. You can find them on the left side under the profile picture.'
  2347. },
  2348. {
  2349. id: 'useDefaultBootLabel',
  2350. text: 'Use the Default Boot Time Label',
  2351. selected: false,
  2352. title: 'Advanced',
  2353. addBreak: false
  2354. },
  2355. {
  2356. id: 'hideRefreshButton',
  2357. text: 'Hide Refresh Button',
  2358. selected: false,
  2359. title: '',
  2360. addBreak: false,
  2361. help: 'Hide the refresh button. You can still refresh with R'
  2362. },
  2363. {
  2364. id: 'hideOffTopic',
  2365. text: 'Automatically hide Off-topic threads',
  2366. selected: false,
  2367. title: '',
  2368. addBreak: false,
  2369. help: 'This option automatically hides all off-topic threads everytime you visit the All Forum Posts page'
  2370. },
  2371. {
  2372. id: 'disableHideThreadOnDashboard',
  2373. text: 'Disable right-click on the forum table',
  2374. selected: false,
  2375. title: '',
  2376. addBreak: false,
  2377. help: 'This option will allow you to right-click forum thread on the dashboard and use the default browser options.'
  2378. }
  2379. ];
  2380. /**
  2381. * Creates the Userscript-Menu
  2382. */
  2383. function setupUserscriptMenu() {
  2384. addCSS(`
  2385. /* The switch - the box around the slider */
  2386. .switch {
  2387. position: relative;
  2388. width: 50px;
  2389. height: 24px;
  2390. margin-right: 30px;
  2391. float: right;
  2392. }
  2393.  
  2394. /* Hide default HTML checkbox */
  2395. .switch input {display:none;}
  2396.  
  2397. /* The slider */
  2398. .slider {
  2399. position: absolute;
  2400. cursor: pointer;
  2401. top: 0;
  2402. left: 0;
  2403. right: 0;
  2404. bottom: 0;
  2405. background-color: #ccc;
  2406. -webkit-transition: .4s;
  2407. transition: .4s;
  2408. }
  2409.  
  2410. .slider:before {
  2411. position: absolute;
  2412. content: "";
  2413. height: 20px;
  2414. width: 20px;
  2415. left: 2px;
  2416. bottom: 2px;
  2417. background-color: white;
  2418. -webkit-transition: .4s;
  2419. transition: .4s;
  2420. }
  2421.  
  2422. input:checked + .slider {
  2423. background-color: #0E5C83;
  2424. }
  2425.  
  2426. input:focus + .slider {
  2427. box-shadow: 0 0 1px crimson;
  2428. }
  2429.  
  2430. input:checked + .slider:before {
  2431. -webkit-transform: translateX(26px);
  2432. -ms-transform: translateX(26px);
  2433. transform: translateX(26px);
  2434. }
  2435.  
  2436. /* Rounded sliders */
  2437. .slider.round {
  2438. border-radius: 34px;
  2439. }
  2440.  
  2441. .slider.round:before {
  2442. border-radius: 50%;
  2443. }
  2444. .settingsListItem {
  2445. padding-top: 25px;
  2446. font-size: 15px;
  2447. }
  2448. `)
  2449. var inputs = '';
  2450. $.each(userscriptSettings, function (key, setting) {
  2451. if (setting.title != '') {
  2452. inputs += `<div class="title">${setting.title}</div>`;
  2453. }
  2454. var help = setting.help != undefined ? `<img tabindex="0" class="help-icon" src="${IMAGES.QUESTION}" data-content="${getSettingInfo(setting.id)}" data-toggle="popover">` : ''
  2455. inputs += '<div class="settingsListItem">' + setting.text + help + '<label class="switch"><input id="' + setting.id + '" type="checkbox"><div class="slider round"></div></label></div>';
  2456. if (setting.addBreak) {
  2457. inputs += '<hr>';
  2458. }
  2459. });
  2460. $("body").append(`
  2461. <div class="modal modal-750 fade" id="userscriptMenu" tabindex="-1" role="dialog">
  2462. <div class="modal-dialog" role="document">
  2463. <div class="modal-content">
  2464. <div class="modal-header">
  2465. <h5 class="modal-title" id="exampleModalLongTitle">Muli's Userscript ${GM_info.script.version}</h5>
  2466. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  2467. <span aria-hidden="true">&times;</span>
  2468. </button>
  2469. </div>
  2470. <div class="modal-body">
  2471. ${inputs}
  2472. </div>
  2473. <div class="modal-footer">
  2474. <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
  2475. <button type="button" class="btn btn-primary close-userscript" data-dismiss="modal">Close & Refresh</button>
  2476. </div>
  2477. </div>
  2478. </div>
  2479. </div>
  2480. `)
  2481. $("body").append('<ul class="custom-menu"><div class="content"></div></ul>');
  2482. $("[data-toggle=popover]").popover({
  2483. trigger: 'focus'
  2484. })
  2485. $("#userscriptMenu").on("change", function () {
  2486. console.log("storing settings")
  2487. storeSettingsVariables();
  2488. });
  2489. $("#AccountDropDown").next(".dropdown-menu").append('<div class="dropdown-divider"></div><a class="dropdown-item " href="#" data-toggle="modal" data-target="#userscriptMenu">Muli\'s Userscript</a>')
  2490. $(".close-userscript").on("click", function () {
  2491. $(".userscript-show").fadeOut();
  2492. $(".overlay").fadeOut();
  2493. location.reload();
  2494. });
  2495. $(".close-popup-img").on("click", function () {
  2496. $(".userscript-show").fadeOut();
  2497. $(".overlay").fadeOut();
  2498. $("embed#main").css('opacity', '1');
  2499. });
  2500. $("#hideRightColumn").parent().parent().after('<button class="btn btn-primary" data-toggle="modal" data-target="#dashboardTableSortMenu">Sort Right Column Tables</button><br>')
  2501. createSelector("#sortTables", "margin-top: 5px")
  2502. addCSS(`
  2503. .userscriptSettingsButtons {
  2504. display: flex;
  2505. justify-content: space-between;
  2506. margin-top: 25px;
  2507. }
  2508. `)
  2509. $("#userscriptMenu .modal-body").append("<div class='userscriptSettingsButtons'></div>")
  2510. //Export settings button
  2511. $(".userscriptSettingsButtons").append('<button data-target="#userscriptExportSettings" data-toggle="modal" id="exportSettings" class="btn btn-primary">Export Settings</button>')
  2512. //Import settings button
  2513. $(".userscriptSettingsButtons").append('<button data-toggle="modal" data-target="#userscriptImportSettings" class="btn btn-primary">Import Settings</button>')
  2514. //Reset hidden threads button
  2515. $(".userscriptSettingsButtons").append('<button id="resetHiddenThreads" class="btn btn-primary">Reset Hidden Threads</button>')
  2516. $("body").append(`
  2517. <div class="modal fade" id="userscriptExportSettings" tabindex="-1" role="dialog">
  2518. <div class="modal-dialog" role="document">
  2519. <div class="modal-content">
  2520. <div class="modal-header">
  2521. <h5 class="modal-title" id="exampleModalLongTitle">Export Settings</h5>
  2522. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  2523. <span aria-hidden="true">&times;</span>
  2524. </button>
  2525. </div>
  2526. <div class="modal-body">
  2527. Copy or download this text and save it somewhere on your computer!
  2528. <textarea id='exportSettingsBox'></textarea>
  2529. <a id='downloadExportSettingsFile' href='' download='tuyd_settings.txt'>Download Text-File</a>
  2530. </div>
  2531. <div class="modal-footer">
  2532. <button type="button" data-dismiss="modal" class="btn btn-primary close-userscript">Close</button>
  2533. </div>
  2534. </div>
  2535. </div>
  2536. </div>
  2537. `)
  2538. $("body").append(`
  2539. <div class="modal fade" id="userscriptImportSettings" tabindex="-1" role="dialog">
  2540. <div class="modal-dialog" role="document">
  2541. <div class="modal-content">
  2542. <div class="modal-header">
  2543. <h5 class="modal-title" id="exampleModalLongTitle">Import Settings</h5>
  2544. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  2545. <span aria-hidden="true">&times;</span>
  2546. </button>
  2547. </div>
  2548. <div class="modal-body">
  2549. <textarea id='importSettingsBox' placeholder='Copy settings here'></textarea><button id='importSettings' class="btn btn-primary">Import Settings</button>
  2550. </div>
  2551. <div class="modal-footer">
  2552. <button type="button" data-dismiss="modal" class="btn btn-primary close-userscript">Close</button>
  2553. </div>
  2554. </div>
  2555. </div>
  2556. </div>
  2557. `)
  2558. createSelector("#exportSettingsBox, #importSettingsBox", "width:100%; height: 300px")
  2559. $("#exportSettings").on("click", function () {
  2560. exportSettings();
  2561. })
  2562. $("#importSettings").on("click", function () {
  2563. importSettings();
  2564. })
  2565. $("#resetHiddenThreads").on("click", function () {
  2566. window.undoIgnore();
  2567. })
  2568. getSortTables(function (tables) {
  2569. var tableCode = ''
  2570. $.each(tables, function (key, table) {
  2571. tableCode += '<div class="sortableLadder ' + (table.hidden ? 'tableSortHidden' : '') + '" data-name="' + table.name + '" data-tableId="' + table.id + '">' + table.name + '<div class="tableSortNavigation"><span class="tableSortUp">▲</span><span class="tableSortDown">▼</span><span class="tableSortHideShow"><img src="' + IMAGES.EYE + '"></span></div></div>'
  2572. })
  2573. createSelector(".sortableLadder", "border: 1px gray solid;margin: 5px;padding: 5px;background-color:rgb(25, 25, 25);")
  2574. createSelector(".tableSortNavigation", "display: inline-block;float: right;margin-top: -2px;")
  2575. createSelector(".tableSortNavigation span", "padding: 3px 10px; cursor: pointer")
  2576. createSelector(".tableSortNavigation span:hover", "color: #C0D0FF")
  2577. createSelector(".sortTableHighlight", "background-color: rgb(60, 60, 60)")
  2578. createSelector(".tableSortHideShow img", "height: 10px")
  2579. createSelector(".tableSortHidden", "opacity: 0.2;")
  2580. $("body").append(`
  2581. <div class="modal modal-500 fade" id="dashboardTableSortMenu" tabindex="-1" role="dialog">
  2582. <div class="modal-dialog" role="document">
  2583. <div class="modal-content">
  2584. <div class="modal-header">
  2585. <h5 class="modal-title" id="exampleModalLongTitle">Sort dashboard tables</h5>
  2586. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  2587. <span aria-hidden="true">&times;</span>
  2588. </button>
  2589. </div>
  2590. <div class="modal-body">
  2591. ${tableCode}
  2592. </div>
  2593. <div class="modal-footer">
  2594. <button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
  2595. <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="window.saveTableSort()">Save</button>
  2596. </div>
  2597. </div>
  2598. </div>
  2599. </div>
  2600. `)
  2601. // $("body").append(' <div class="popup popup600" id="sortTablePopup" style="display:none;margin-top: 150px; width: 500px; margin-left: -282px;"><div class="head" style=" margin-top: 152px;width:500px;right:62px">Sort Tables<img class="close-popup-img" src="' + IMAGES.CROSS + '" height="25" width="25"></div>' + tableCode + ' <button class="close-userscript" onclick="window.saveTableSort()">Save & Refresh</button></div>')
  2602. $(".close-popup-img").unbind();
  2603. $(".close-popup-img").on("click", function () {
  2604. $(".popup").fadeOut();
  2605. $(".overlay").fadeOut();
  2606. });
  2607. $(".tableSortUp").on("click", function () {
  2608. $(".sortTableHighlight").removeClass("sortTableHighlight")
  2609. var table = $(this).closest(".sortableLadder")
  2610. table.addClass("sortTableHighlight")
  2611. var prev = table.prev()
  2612. table = table.detach()
  2613. prev.before(table)
  2614. })
  2615. $(".tableSortDown").on("click", function () {
  2616. $(".sortTableHighlight").removeClass("sortTableHighlight")
  2617. var table = $(this).closest(".sortableLadder")
  2618. table.addClass("sortTableHighlight")
  2619. var next = table.next()
  2620. table = table.detach()
  2621. next.after(table)
  2622. })
  2623. $(".tableSortHideShow").on("click", function () {
  2624. $(".sortTableHighlight").removeClass("sortTableHighlight")
  2625. var table = $(this).closest(".sortableLadder")
  2626. table.addClass("sortTableHighlight")
  2627. table.toggleClass("tableSortHidden")
  2628. })
  2629. checkUserscriptMenuButtons();
  2630. })
  2631. }
  2632.  
  2633. function importSettings() {
  2634. var deferredCount = 0;
  2635. var resolvedCount = 0;
  2636. var clearPromises = [];
  2637. $.each(Database.Table, function (key, table) {
  2638. clearPromises[deferredCount++] = $.Deferred();
  2639. Database.clear(table, function () {
  2640. clearPromises[resolvedCount++].resolve();
  2641. })
  2642. })
  2643. if (WLJSDefined()) {
  2644. warlight_shared_viewmodels_WaitDialogVM.Start("Importing Settings...")
  2645. }
  2646. $('.modal').modal("hide");
  2647. var settings = $("#importSettingsBox").val().trim();
  2648. $.when.apply($, clearPromises).done(function () {
  2649. var deferredCount = 0;
  2650. var resolvedCount = 0;
  2651. var promises = [];
  2652. try {
  2653. settings = JSON.parse(atob(settings))
  2654. $.each(settings, function (key, data) {
  2655. var table = data.table
  2656. var content = data.data
  2657. $.each(content, function (key, value) {
  2658. promises[deferredCount++] = $.Deferred();
  2659. Database.add(table, value, function () {
  2660. promises[resolvedCount++].resolve();
  2661. })
  2662. })
  2663. })
  2664. $.when.apply($, promises).done(function () {
  2665. window.location.reload();
  2666. })
  2667. }
  2668. catch (e) {
  2669. log(e)
  2670. if (WLJSDefined()) {
  2671. warlight_shared_viewmodels_WaitDialogVM.Stop();
  2672. warlight_shared_viewmodels_AlertVM.DoPopup("There was an error importing the settings.");
  2673. }
  2674. $(".overlay").fadeOut();
  2675. }
  2676. });
  2677. }
  2678.  
  2679. function exportSettings() {
  2680. var settings = [];
  2681. var deferredCount = 0;
  2682. var resolvedCount = 0;
  2683. var promises = [];
  2684. $.each(Database.Exports, function (key, table) {
  2685. promises[deferredCount++] = $.Deferred();
  2686. Database.readAll(table, function (data) {
  2687. settings.push({
  2688. table: table,
  2689. data: data
  2690. })
  2691. promises[resolvedCount++].resolve();
  2692. })
  2693. })
  2694. $.when.apply($, promises).done(function () {
  2695. var settingsString = btoa(JSON.stringify(settings))
  2696. $("#exportSettingsBox").html(settingsString)
  2697. showPopup(".exportSettings-show");
  2698. $("#downloadExportSettingsFile").click(function () {
  2699. this.href = "data:text/plain;charset=UTF-8," + settingsString;
  2700. });
  2701. });
  2702. }
  2703.  
  2704. function showPopup(selector) {
  2705. if ($(selector).length > 0) {
  2706. $(".popup").fadeOut();
  2707. $(selector).fadeIn();
  2708. $(".overlay").fadeIn();
  2709. makePopupVisible();
  2710. }
  2711. }
  2712.  
  2713. function makePopupVisible() {
  2714. if ($(".popup600:visible").offset() && $(".popup600:visible").offset().top + $(".popup600:visible").height() + 150 > $(window).height() || ($(".popup600:visible").offset() && $(".popup600:visible").offset().top < 100)) {
  2715. $(".popup600:visible").css("margin-top", $(window).height() - 250 - $(".popup600:visible").height())
  2716. $(".popup600:visible .head").css("margin-top", $(window).height() - 250 - $(".popup600:visible").height() + 2)
  2717. }
  2718. }
  2719.  
  2720. function getSortTables(callback) {
  2721. var defaultTables = [
  2722. {
  2723. id: "#BookmarkTable",
  2724. name: "Bookmarks",
  2725. hidden: false,
  2726. order: 0
  2727. },
  2728. {
  2729. id: "#MyTournamentsTable",
  2730. name: "Tournaments",
  2731. hidden: false,
  2732. order: 2
  2733. },
  2734. {
  2735. id: "#RealTimeLadderTable",
  2736. name: "Real-Time Ladder",
  2737. hidden: false,
  2738. order: 3
  2739. },
  2740. {
  2741. id: "#MapOfTheWeekTable",
  2742. name: "Map of the Week",
  2743. hidden: false,
  2744. order: 4
  2745. },
  2746. {
  2747. id: "#ForumTable",
  2748. name: "Forum Posts",
  2749. hidden: false,
  2750. order: 5
  2751. },
  2752. {
  2753. id: "#ClanForumTable",
  2754. name: "Clan Forum Posts",
  2755. hidden: false,
  2756. order: 6
  2757. },
  2758. {
  2759. id: "#BlogTable",
  2760. name: "Recent Blog Posts",
  2761. hidden: false,
  2762. order: 7
  2763. },
  2764. {
  2765. id: "#LeaderboardTable",
  2766. name: "Coin Leaderboard",
  2767. hidden: false,
  2768. order: 8
  2769. }
  2770. ]
  2771. if ($("#ShopTable").length > 0) {
  2772. defaultTables.push({
  2773. id: "#ShopTable",
  2774. name: "WarLight Shop",
  2775. hidden: false,
  2776. order: -1
  2777. })
  2778. } if ($(".dataTable:contains('Quickmatch')").length > 0) {
  2779. defaultTables.push({
  2780. id: ".dataTable:contains('Quickmatch')",
  2781. name: "Quickmatch",
  2782. hidden: false,
  2783. order: 1
  2784. },)
  2785. }
  2786. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "tableSort", function (tableData) {
  2787. if (tableData && tableData.value.length > 3) {
  2788. var tables = tableData.value;
  2789. if ($("#ShopTable").length > 0 && !arrayHasObjWithId(tables, "#ShopTable")) {
  2790. tables.push({
  2791. id: "#ShopTable",
  2792. name: "WarLight Shop",
  2793. hidden: false,
  2794. order: -1
  2795. })
  2796. }
  2797. callback($(tables).sort(compareTable));
  2798. }
  2799. else {
  2800. callback($(defaultTables).sort(compareTable))
  2801. }
  2802. })
  2803. }
  2804.  
  2805. function arrayHasObjWithId(arr, id) {
  2806. var found = false;
  2807. $.each(arr, function (key, val) {
  2808. if (val.id == id) {
  2809. found = true;
  2810. }
  2811. })
  2812. return found;
  2813. }
  2814. window.saveTableSort = function () {
  2815. var tables = []
  2816. $.each($("#dashboardTableSortMenu div.sortableLadder"), function (key, table) {
  2817. var order = key
  2818. var id = $(table).attr('data-tableId')
  2819. var hidden = $(table).hasClass("tableSortHidden")
  2820. var name = $(table).attr('data-name')
  2821. tables.push({
  2822. id: id,
  2823. name: name,
  2824. hidden: hidden,
  2825. order: order
  2826. })
  2827. })
  2828. var tableSort = {
  2829. name: "tableSort",
  2830. value: tables
  2831. }
  2832. Database.update(Database.Table.Settings, tableSort, undefined, function () {
  2833. $("#sortTablePopup").fadeOut();
  2834. $(".overlay").fadeOut();
  2835. refreshOpenGames();
  2836. })
  2837. }
  2838.  
  2839. function compareTable(a, b) {
  2840. if (a.order < b.order) return -1;
  2841. if (a.order > b.order) return 1;
  2842. return 0;
  2843. }
  2844. window.getSettingInfo = function (id) {
  2845. var info = "";
  2846. $.each(userscriptSettings, function (key, setting) {
  2847. if (setting.id == id) {
  2848. help = setting.help;
  2849. }
  2850. });
  2851. return help;
  2852. }
  2853.  
  2854. function checkUserscriptMenuButtons() {
  2855. $.each(userscriptSettings, function (key, set) {
  2856. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, set.id, function (setting) {
  2857. if (setting) {
  2858. $("#" + setting.name).prop("checked", setting.value);
  2859. }
  2860. else {
  2861. $("#" + set.id).prop("checked", set.selected);
  2862. }
  2863. })
  2864. });
  2865. }
  2866. /**
  2867. * Stores User-Settings to local Storage
  2868. */
  2869. function storeSettingsVariables() {
  2870. $.each(userscriptSettings, function (key, set) {
  2871. var isEnabled = $("#" + set.id).prop("checked");
  2872. var setting = {
  2873. name: set.id,
  2874. value: isEnabled
  2875. }
  2876. Database.update(Database.Table.Settings, setting, undefined, function () {})
  2877. });
  2878. }
  2879.  
  2880. function setupSettingsDatabase() {
  2881. if (WLJSDefined()) {
  2882. warlight_shared_viewmodels_WaitDialogVM.Start("Setting up Muli's Userscript...")
  2883. }
  2884. var promises = [];
  2885. $.each(userscriptSettings, function (key, set) {
  2886. promises[key] = $.Deferred();
  2887. var setting = {
  2888. name: set.id,
  2889. value: set.selected
  2890. }
  2891. Database.update(Database.Table.Settings, setting, undefined, function () {
  2892. promises[key].resolve();
  2893. })
  2894. })
  2895. $.when.apply($, promises).done(function () {
  2896. sessionStorage.setItem("showUserscriptMenu", true)
  2897. window.setTimeout(window.location.reload(), 2000)
  2898. })
  2899. }
  2900.  
  2901. function ifSettingIsEnabled(setting, positive, negative, cb) {
  2902. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, setting, function (setting) {
  2903. if (setting && setting.value) {
  2904. positive();
  2905. if (typeof cb == "function") {
  2906. cb();
  2907. }
  2908. }
  2909. else {
  2910. if (typeof negative == 'function') {
  2911. negative();
  2912. }
  2913. if (typeof cb == 'function') {
  2914. cb();
  2915. }
  2916. }
  2917. })
  2918. }
  2919.  
  2920. function ifSettingIsNotEnabled(setting, callback) {
  2921. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, setting, function (setting) {
  2922. if (!setting.value) {
  2923. callback();
  2924. }
  2925. })
  2926. }
  2927.  
  2928. function ifAllAreEnabled(settings, positive, negative) {
  2929. var promises = [];
  2930. var allAreEnabled = true;
  2931. $.each(settings, function (key, setting) {
  2932. promises[key] = $.Deferred();
  2933. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, setting, function (set) {
  2934. if (!set || !set.value) {
  2935. allAreEnabled = false;
  2936. }
  2937. promises[key].resolve();
  2938. })
  2939. })
  2940. $.when.apply($, promises).done(function () {
  2941. if (allAreEnabled) {
  2942. positive()
  2943. }
  2944. else {
  2945. if (typeof negative == "function") {
  2946. negative();
  2947. }
  2948. }
  2949. })
  2950. }
  2951.  
  2952. function ifOneOrMoreIsEnabled(settings, positive, negative) {
  2953. var promises = [];
  2954. var isEnabled = false;
  2955. $.each(settings, function (key, setting) {
  2956. promises[key] = $.Deferred();
  2957. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, setting, function (set) {
  2958. if (set && set.value) {
  2959. isEnabled = true;
  2960. }
  2961. promises[key].resolve();
  2962. })
  2963. })
  2964. $.when.apply($, promises).done(function () {
  2965. if (isEnabled) {
  2966. positive()
  2967. }
  2968. else {
  2969. if (typeof negative == "function") {
  2970. negative();
  2971. }
  2972. }
  2973. })
  2974. }
  2975. function pageIsMultiplayer() {
  2976. return location.href.match(/.*warzone[.]com\/MultiPlayer.*/i);
  2977. }
  2978.  
  2979. function pageIsPointsPage() {
  2980. return location.href.match(/.*warzone[.]com\/Points.*/i);
  2981. }
  2982.  
  2983. function pageIsDashboard() {
  2984. return location.href.match(/.*warzone[.]com\/MultiPlayer\/(?:#|\?|$).*$/i);
  2985. }
  2986.  
  2987. function pageIsRealTimeLadder() {
  2988. return location.href.match(/.*warzone[.]com\/LadderSeason\?ID=3.*$/i);
  2989. }
  2990.  
  2991. function pageIsProfile() {
  2992. return location.href.match(/.*warzone[.]com\/profile\?p=[0-9]+$/i);
  2993. }
  2994.  
  2995. function pageIsClanPage() {
  2996. return location.href.match(/.*warzone[.]com\/Clans\/\?ID=[0-9]+$/i);
  2997. }
  2998.  
  2999. function pageIsLevelOverview() {
  3000. return location.href.match(/.*warzone[.]com\/SinglePlayer\/Level\?ID=[0-9]+$/i);
  3001. }
  3002.  
  3003. function pageIsLevelPlayLog() {
  3004. return location.href.match(/.*warzone[.]com\/SinglePlayer\/PlayLog\?ID=[0-9]+$/i);
  3005. }
  3006.  
  3007. function pageIsMapsPage() {
  3008. return location.href.match(/.*warzone[.]com\/maps/i);
  3009. }
  3010.  
  3011. function pageIsClanThread() {
  3012. return location.href.match(/.*warzone[.]com\/Discussion/i);
  3013. }
  3014.  
  3015. function pageIsNewThread() {
  3016. return location.href.match(/.*warzone[.]com\/Forum\/NewThread.*/i);
  3017. }
  3018.  
  3019. function pageIsForumThread() {
  3020. return location.href.match(/.*warzone[.]com\/Forum\/[0-9]+.*/i);
  3021. }
  3022.  
  3023. function pageIsForumOverview() {
  3024. return location.href.match(/.*warzone[.]com\/Forum\/Forum.*/i);
  3025. }
  3026.  
  3027. function pageIsThread() {
  3028. return location.href.match(/.*warzone[.]com\/(Forum|Discussion|Clans\/CreateThread).*/i);
  3029. }
  3030.  
  3031. function pageIsSubForum() {
  3032. return location.href.match(/.*warzone[.]com\/Forum\/[A-Z]+.*/i);
  3033. }
  3034.  
  3035. function pageIsForum() {
  3036. return location.href.match(/.*warzone[.]com\/Forum\/.*/);
  3037. }
  3038.  
  3039. function pageIsLadderOverview() {
  3040. return location.href.match(/.*warzone[.]com\/Ladders/);
  3041. }
  3042.  
  3043. function pageIsLogin() {
  3044. return location.href.match(/.*warzone[.]com\/LogIn.*/);
  3045. }
  3046.  
  3047. function pageIsClanForumThread() {
  3048. return location.href.match(/.*warzone[.]com\/Discussion\/\?ID=[0-9]+.*/);
  3049. }
  3050.  
  3051. function pageIsTournament() {
  3052. return location.href.match(/.*warzone[.]com\/MultiPlayer\/Tournament\?ID=[0-9]+/i);
  3053. }
  3054.  
  3055. function pageIsTournamentOverview() {
  3056. return location.href.match(/.*warzone[.]com\/MultiPlayer\/Tournaments\/$/i);
  3057. }
  3058.  
  3059. function pageIsGame() {
  3060. return location.href.match(/.*warzone[.]com\/MultiPlayer\?GameID=[0-9]+/i);
  3061. }
  3062.  
  3063. function pageIsExamineMap() {
  3064. return location.href.match(/.*warzone[.]com\/SinglePlayer\?PreviewMap.*/i);
  3065. }
  3066.  
  3067. function pageIsDesignMap() {
  3068. return location.href.match(/.*warzone[.]com\/MultiPlayer\?DesignMaps.*/i);
  3069. }
  3070.  
  3071. function pageIsCommonGames() {
  3072. return location.href.match(/.*warzone[.]com\/CommonGames\?p=[0-9]+$/i);
  3073. }
  3074.  
  3075. function pageIsCommunityLevels() {
  3076. return location.href.match(/.*warzone[.]com\/SinglePlayer\/CommunityLevels/i);
  3077. }
  3078.  
  3079. function pageIsCommunity() {
  3080. return location.href.match(/.*warzone[.]com\/Community/i);
  3081. }
  3082.  
  3083. function pageIsMapOfTheWeek() {
  3084. return location.href.match(/.*warzone[.]com\/MapOfTheWeek.*/i);
  3085. }
  3086.  
  3087. function pageIsBlacklistPage() {
  3088. return location.href.match(/.*warzone[.]com\/ManageBlackList.*/i);
  3089. }
  3090.  
  3091. function pageIsMapPage() {
  3092. return location.href.match(/.*warzone[.]com\/Map.*/i);
  3093. }
  3094.  
  3095. function pageIsMyAccount() {
  3096. return location.href.match(/.*warzone[.]com\/MyAccount.*/i);
  3097. }
  3098.  
  3099. function mapIsPublic() {
  3100. return $("a:contains('Start a')").length > 0;
  3101. }
  3102. function addCSS(css) {
  3103. var head = document.head || document.getElementsByTagName('head')[0]
  3104. var style = document.createElement('style');
  3105. style.type = 'text/css';
  3106. if (head) {
  3107. if (style.styleSheet) {
  3108. style.styleSheet.cssText = css;
  3109. }
  3110. else {
  3111. style.appendChild(document.createTextNode(css));
  3112. }
  3113. head.appendChild(style);
  3114. }
  3115. else {
  3116. $$$(document).ready(function () {
  3117. addCSS(css)
  3118. })
  3119. }
  3120. }
  3121. /**
  3122. * Create a CSS selector
  3123. * @param name The name of the object, which the rules are applied to
  3124. * @param rules The CSS rules
  3125. */
  3126. function createSelector(name, rules) {
  3127. var head = document.head || document.getElementsByTagName('head')[0]
  3128. var style = document.createElement('style');
  3129. style.type = 'text/css';
  3130. if (head) {
  3131. head.appendChild(style);
  3132. if (!(style.sheet || {}).insertRule) {
  3133. (style.styleSheet || style.sheet).addRule(name, rules);
  3134. }
  3135. else {
  3136. style.sheet.insertRule(name + "{" + rules + "}", 0);
  3137. }
  3138. }
  3139. else {
  3140. $$$(document).ready(function () {
  3141. createSelector(name, rules)
  3142. })
  3143. }
  3144. }
  3145.  
  3146. function setGlobalStyles() {
  3147. /** Warzone **/
  3148. addCSS(`
  3149. body > .container-fluid {
  3150. font-size: 15px;
  3151. }
  3152. .modal-1000 .modal-dialog {
  3153. max-width: 1000px;
  3154. }
  3155. .modal-750 .modal-dialog {
  3156. max-width: 750px;
  3157. }
  3158. .modal-500 .modal-dialog {
  3159. max-width: 500px;
  3160. }
  3161. .modal-header {
  3162. background-color: #132913;
  3163. background-image: url(/Images/Warzone/MainNavBacking.jpg);
  3164. background-size: cover;
  3165. border: none;
  3166. }
  3167. .modal-content {
  3168. background-image: url(/Images/Warzone/Arrows.jpg);
  3169. background-repeat: repeat;
  3170. color: grey;
  3171. }
  3172. .modal-content a {
  3173. color: burlywood;
  3174. }
  3175. .modal-content .title {
  3176. border-bottom: 1px solid #928f59;
  3177. margin-top: 25px;
  3178. }
  3179. .p-4 table {
  3180. width: 100%;
  3181. }
  3182. .GameRow p {
  3183. margin: 0 !important;
  3184. }
  3185. h2, h3 {
  3186. font-size: 25px;
  3187. }
  3188. img[src*='/Images/X.png'] {
  3189. width: 100%;
  3190. height: 100%;
  3191. }
  3192. `)
  3193. /** Warlight **/
  3194. $("tr:contains('WarLight Shop')").closest(".dataTable").attr("id", "ShopTable");
  3195. createSelector('.help-icon', 'display:inline-block;position:absolute; margin-left:10px;margin-top: 2px;cursor:pointer; height: 15px; width: 15px;')
  3196. var winHeight = $(window).height();
  3197. createSelector(".popup", "position: fixed;;left: 50%;background: #171717;top: 100px;z-index: 9999; color:white;padding:60px 30px 30px 30px;border: 2px solid gray;border-radius:8px;max-height:" + (winHeight - 200) + "px;overflow-y:auto");
  3198. createSelector(".close-popup-img", "float:right;margin:5px;cursor:pointer;margin-right: 20px");
  3199. addCSS(`.popup .title {
  3200. color: crimson;
  3201. font-size: 15px;
  3202. margin-top: 10px;
  3203. display: inline-block;
  3204. width: 95%;
  3205. padding-bottom: 3px;
  3206. border-bottom: 1px solid crimson;
  3207. }`)
  3208. createSelector(".popup input[type='checkbox']", "width: 20px;height: 20px;margin-left:30px;margin: 5px;");
  3209. createSelector(".overlay", "position: absolute;background: white;top: 0;left: 0;right: 0;bottom: 0;z-index: 98;opacity: 0.5;width: 100%;height: 100%;position: fixed;");
  3210. createSelector(".popup .head", "position: fixed;height: 40px;background: #330000;width: 660px;left: 0;right: 0;top: 100px;color: white;font-size: 15px;text-align: center;line-height: 40px;border-top-left-radius:8px;border-top-right-radius:8px;margin:auto;z-index:10000;");
  3211. createSelector(".userscript-show", "display:none");
  3212. createSelector("#MorePromotedGamesHorizontalRow", "display:none");
  3213. createSelector(".newSetting", "color: gold;font-weight: bold;");
  3214. createSelector(".userscript-menu img", "height: 18px;display: inline-block;position: relative;margin-bottom: -5px;margin-right: 7px;");
  3215. createSelector(".custom-menu", "display: none;z-index: 98;position: absolute;overflow: hidden;border: 1px solid #CCC;white-space: nowrap;font-family: sans-serif;background: #FFF;color: #333;border-radius:5px;padding: 10px;z-index:100000000; cursor:pointer");
  3216. createSelector(".custom-menu .content", "width: 300px;white-space: pre-wrap;");
  3217. createSelector('.popup input[type="text"]', 'display: inline-block;background: none;border-top: none;border-left: none;border-right: none;color: green;font-size: 15px;border-bottom: 1px white dashed;font-family: Verdana;padding: 0 5px 0 5px;text-align: center;margin-right: 5px');
  3218. createSelector(".popup840", "width: 840px;margin-left: -452px");
  3219. createSelector(".popup600", "width: 600px;margin-left: -332px");
  3220. createSelector(".popup840 .head", "width: 900px");
  3221. createSelector(".popup600 .head", "width: 660px");
  3222. createSelector(".context-menu", "display: none;z-index: 100;position: absolute;overflow: hidden;border: 1px solid #CCC;white-space: nowrap;font-family: sans-serif;background: #FFF;color: #333;border-radius: 5px;padding: 0;");
  3223. createSelector(".context-menu li", "padding: 8px 12px;cursor: pointer;list-style-type: none;");
  3224. createSelector(".context-menu li:hover", "background-color: #DEF;");
  3225. createSelector("#MyGamesTable select", "margin: 0 10px 0 5px; width: 125px")
  3226. createSelector("#MyGamesFilter", "float:right")
  3227. createSelector("#MyGamesTable thead tr", "text-align: right")
  3228. $("body").on("click", function (e) {
  3229. if ($(".custom-menu").is(':visible')) {
  3230. $(".custom-menu").hide(100);
  3231. }
  3232. });
  3233. }
  3234.  
  3235. function loadDataTableCSS() {
  3236. var styles = document.createElement("style");
  3237. styles.type = "text/css";
  3238. styles.innerHTML = getDataTableCSS();
  3239. document.body.appendChild(styles);
  3240. }
  3241.  
  3242. function getDataTableCSS() {
  3243. return `table.dataTable thead td,table.dataTable thead th{padding:6px 18px 6px 6px}table.dataTable tfoot td,table.dataTable tfoot th{padding:10px 18px 6px;border-top:1px solid #111}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc{cursor:pointer}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_desc_disabled{background-repeat:no-repeat;background-position:center right}table.dataTable thead .sorting{background-image:url(https://cdn.datatables.net/1.10.10/images/sort_both.png)}table.dataTable thead .sorting_asc{background-image:url(https://cdn.datatables.net/1.10.10/images/sort_asc.png)}table.dataTable thead .sorting_desc{background-image:url(https://cdn.datatables.net/1.10.10/images/sort_desc.png)}table.dataTable thead .sorting_asc_disabled{background-image:url(https://cdn.datatables.net/1.10.10/images/sort_asc_disabled.png)}table.dataTable thead .sorting_desc_disabled{background-image:url(https://cdn.datatables.net/1.10.10/images/sort_desc_disabled.png)}.dataTables_wrapper{position:relative;clear:both;zoom:1}#PlayersContainer td{white-space:nowrap}
  3244.  
  3245. .dataTables_filter {
  3246. float: right;
  3247. }
  3248.  
  3249. .dataTables_filter label {
  3250. display: inline!important;
  3251. }
  3252.  
  3253. .dataTables_filter input {
  3254. padding: 3px;
  3255. border-radius: 5px;
  3256. margin: 5px;
  3257. }
  3258.  
  3259. .dataTables_info {
  3260. clear: both;
  3261. padding-top: 10px;
  3262. }
  3263.  
  3264. .pagination {
  3265. display: inline-block;
  3266. float: right;
  3267.  
  3268. }
  3269. #foundClansTable_wrapper .row {
  3270. width: 100%;
  3271. }
  3272. .paginate_button {
  3273. display: inline;
  3274. padding: 5px;
  3275. }.paginate_button.active {
  3276. text-decoration: underline;
  3277. }`
  3278. }
  3279. function domRefresh() {
  3280. $("body").hide(0).show(0);
  3281. $(window).trigger('resize')
  3282. }
  3283.  
  3284. function htmlEscape(str) {
  3285. return String(str)
  3286. .replace(/&/g, '&amp;')
  3287. .replace(/"/g, '&quot;')
  3288. .replace(/'/g, '&#39;')
  3289. .replace(/</g, '&lt;')
  3290. .replace(/>/g, '&gt;');
  3291. }
  3292. function isJson(str) {
  3293. try {
  3294. JSON.parse(str);
  3295. } catch (e) {
  3296. log(e)
  3297. return false;
  3298. }
  3299. return true;
  3300. }
  3301.  
  3302. function hideTable(seletor) {
  3303. if( $(seletor).prev().hasClass("followWrap")) {
  3304. $(seletor).prev().remove()
  3305. }
  3306. $(seletor).remove()
  3307. }
  3308.  
  3309. function getParameterByName(name, url) {
  3310. url = url || location.search
  3311. name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  3312. var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
  3313. results = regex.exec(url);
  3314. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  3315. }
  3316.  
  3317. function browserIsFirefox() {
  3318. return navigator.userAgent.toLowerCase().indexOf('firefox') > -1
  3319. }
  3320.  
  3321. function WLJSDefined() {
  3322. return (typeof WLJSLoaded) != "undefined" && WLJSLoaded();
  3323. }
  3324.  
  3325. function setupImages() {
  3326. window.IMAGES = {
  3327. EYE: 'https://i.imgur.com/kekYrsO.png',
  3328. CROSS: 'https://i.imgur.com/RItbpDS.png',
  3329. QUESTION: 'https://i.imgur.com/TUyoZOP.png',
  3330. PLUS: 'https://i.imgur.com/lT6SvSY.png',
  3331. SAVE: 'https://i.imgur.com/Ze4h3NQ.png',
  3332. FILTER: 'https://i.imgur.com/Q5Jq3EX.png?1',
  3333. BOOKMARK: 'https://i.imgur.com/c6IxAql.png'
  3334.  
  3335. }
  3336. }
  3337.  
  3338. Array.prototype.unique = function() {
  3339. var n = {},r=[];
  3340. for(var i = 0; i < this.length; i++) {
  3341. if (!n[this[i]]) {
  3342. n[this[i]] = true;
  3343. r.push(this[i]);
  3344. }
  3345. }
  3346. return r;
  3347. }
  3348.  
  3349. function addslashes( str ) {
  3350. return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0');
  3351. }
  3352. function setupWLError() {
  3353. window.wlerror = window.onerror
  3354. window.onerror = windowError
  3355. window.timeDomContentReady = new Date().getTime();
  3356. log("Time DOM content ready " + (timeDomContentReady - timeUserscriptStart) / 1000)
  3357. log("DOM content ready")
  3358. window.WLError = function(a, b) {
  3359. logError(a)
  3360. null == a && (a = "");
  3361. console.log("WLError: " + a + ", silent=" + b); - 1 != a.indexOf("NotAuth") ? location.reload() : -1 != a.indexOf("WarLight Server returned CouldNotConnect") ? CNCDialog() : -1 == a.indexOf("TopLine is not defined") && -1 == a.indexOf("_TPIHelper") && -1 == a.indexOf("Syntax error, unrecognized expression: a[href^=http://]:not([href*=") && -1 == a.indexOf("y2_cc2242") && -1 == a.indexOf("Error calling method on NPObject") && (-1 != a.indexOf("WARLIGHTERROR48348927984712893471394") ? a = "ServerError" : -1 !=
  3362. a.indexOf("WARLIGHTHEAVYLOAD48348927984712893471394") && (a = "HeavyLoad"), ReportError(a), b || PopErrorDialog(a))
  3363. }
  3364. }
  3365. function hideCoinsGlobally() {
  3366. $("#LeaderboardTable").prev().remove();
  3367. $("#LeaderboardTable").css({
  3368. opacity: 0,
  3369. cursor: 'default'
  3370. });
  3371. $("#LeaderboardTable a").css('display', 'none');
  3372. $("body").find("a[href='/Coins/']").css('display', 'none');
  3373. $("a[href='/Win-Money']").css('display', 'none');
  3374. $("#OpenTournamentsTable").css('display', 'none');
  3375. }
  3376.  
  3377. function updateTotalPointsEarned() {
  3378. var pointsEarned = {
  3379. name: "totalPoints",
  3380. value: warlight_shared_points_PointValues.Get(warlight_shared_viewmodels_SignIn.get_CurrentPlayer().Level).RawPoints + warlight_shared_viewmodels_SignIn.get_CurrentPlayer().PointsThisLevel
  3381. }
  3382. Database.update(Database.Table.Settings, pointsEarned, undefined, function() {
  3383. })
  3384. }
  3385. function hideExtraBlanks() {
  3386. var content = $(".container .my-2:first-of-type div.p-3");
  3387. var replacement = '<br><br>';
  3388. content.html(content.html().replace(/(<br\s*\/?>){3,}/gi, replacement))
  3389. }
  3390.  
  3391. function foldProfileStats() {
  3392. addCSS(`
  3393. h3.expander {
  3394. cursor: pointer;
  3395. `)
  3396. $.each($("big").parent().contents(), function(key, val) {
  3397. if(val.nodeType == 3) {
  3398. $(val).replaceWith(`<span>${val.data}</span>`)
  3399. }
  3400. })
  3401. $.each($(".container .my-2:first-of-type div.p-3 h3"), function(key, val){
  3402. $(val).addClass("expander");
  3403. $(val).nextUntil("h3").wrapAll("<div class='exp'></div>")
  3404. })
  3405. $('h3.expander').click(function(e){
  3406. $(this).next().slideToggle();
  3407. });
  3408. }
  3409.  
  3410.  
  3411. function loadPrivateNotes() {
  3412. log("Loading private notes")
  3413. $("#FeedbackMsg").after('<div class="profileBox" id="privateNotes"><h3>Private Notes</h3><p style="width: 285px;overflow:hidden" class="content">Loading Privates Notes..</p></div>');
  3414. var url = $("img[alt='Private Notes']").parent()[0].href;
  3415. var page = $('<div />').load(url, function () {
  3416. var notes = page.find('#PostForDisplay_0').html().trim();
  3417. if (notes) {
  3418. $('#privateNotes .content').html(notes);
  3419. } else {
  3420. $('#privateNotes .content').html('You don\'t have any Private Notes.');
  3421. }
  3422.  
  3423. });
  3424. }
  3425. function databaseReady() {
  3426. log("Running main")
  3427. if (pageIsForumOverview()) {
  3428. ifSettingIsEnabled("hideOffTopic", function () {
  3429. hideOffTopicThreads()
  3430. })
  3431. formatHiddenThreads();
  3432. }
  3433. if (pageIsCommunityLevels()) {
  3434. setupCommunityLevels()
  3435. }
  3436. if (pageIsForumOverview() || pageIsSubForum()) {
  3437. setupSpammersBeGone()
  3438. addCSS(`
  3439. #MainSiteContent > table table tr td:nth-of-type(4), #MainSiteContent > table table tr td:nth-of-type(5) {
  3440. max-width: 200px;
  3441. overflow: hidden;
  3442. text-overflow: ellipsis;
  3443. }
  3444. `)
  3445. }
  3446. if (pageIsProfile() && $("#BlackListImage").length > 0) {
  3447. ifSettingIsEnabled('showPrivateNotesOnProfile', function () {
  3448. loadPrivateNotes();
  3449. })
  3450. }
  3451. if (pageIsTournamentOverview()) {
  3452. log("loading tournament data")
  3453. updateAllTournamentData();
  3454. }
  3455. if (pageIsCommunity()) {
  3456. hideIgnoredForumThreadsFromCommnuityList();
  3457. }
  3458. if (pageIsTournament()) {
  3459. updateCurrentTournamentData()
  3460. $("#JoinBtn").on("click", updateCurrentTournamentData)
  3461. }
  3462. if (pageIsBlacklistPage()) {
  3463. $("#MainSiteContent ul").before(`<span id="numBlacklisted">You have <b>${$("#MainSiteContent ul li:visible").length}</b> players on your blacklist.</span>`)
  3464. window.setInterval(function () {
  3465. $("#numBlacklisted").replaceWith(`<span id="numBlacklisted">You have <b>${$("#MainSiteContent ul li:visible").length}</b> players on your blacklist.</span>`)
  3466. }, 500)
  3467. }
  3468. if (pageIsPointsPage()) {
  3469. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "totalPoints", function (res) {
  3470. if (res) {
  3471. $("#AutoContainer table:first").before(`<br><span>In total, you've earned <b>${res.value.toLocaleString("en")}</b> points.</span>`)
  3472. }
  3473. else {
  3474. $("#AutoContainer table:first").before(`<br><span>Visit the Dashboard once to see how many points you've earned in total.</span>`)
  3475. }
  3476. })
  3477. }
  3478. if (pageIsDashboard()) {
  3479. setupVacationAlert();
  3480.  
  3481. window.StringTools.htmlEscape = function (a) {
  3482. if (a.indexOf("##joined##") >= 0) {
  3483. a = a.replace("##joined##", "");
  3484. return htmlEscape(a) + '<img style="display:inline-block;height:16px;width:16px;margin-left:10px;z-index:10;cursor:default" src="https://i.imgur.com/6akgXa7.png" title="You already joined this game">';
  3485. }
  3486. else {
  3487. return htmlEscape(a);
  3488. }
  3489. }
  3490. hideBlacklistedThreads();
  3491. setupBasicDashboardStyles();
  3492. setupCustomSort(function () {
  3493. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "customFilter", function (f) {
  3494. var filter = (f && f.value) ? f.value : 4;
  3495. $("#MyGamesFilter").val(filter)
  3496. refreshMyGames();
  3497. })
  3498. });
  3499. ifSettingIsEnabled('hideCoinsGlobally', function () {
  3500. hideCoinsGlobally()
  3501. })
  3502. ifSettingIsEnabled('useDefaultBootLabel', function () {
  3503. createSelector(".BootTimeLabel", "z-index:50;");
  3504. }, function () {
  3505. createSelector(".BootTimeLabel", "color:white !important;font-weight:normal!important;font-style:italic;font-size:13px!important;z-index:50;");
  3506. })
  3507. ifSettingIsEnabled("hideRefreshButton", function () {
  3508. createSelector("#refreshAll", "display: none");
  3509. })
  3510. ifSettingIsEnabled("highlightTournaments", function () {
  3511. createSelector("#MyTournamentsTable tbody", "background:#4C4C33;");
  3512. })
  3513. ifOneOrMoreIsEnabled(["hidePromotedGames", "hideCoinsGlobally"], function () {
  3514. createSelector("#PromotedGamesTable", "display:none");
  3515. })
  3516. ifSettingIsEnabled("hideMyGamesIcons", function () {
  3517. createSelector("#MyGamesTable td div > img, #MyGamesTable td div a > img", "display:none;");
  3518. })
  3519. ifSettingIsEnabled("scrollGames", function () {
  3520. setupFixedWindowWithScrollableGames();
  3521. }, function () {
  3522. ifSettingIsEnabled("hideRefreshButton", function () {
  3523. }, function() {
  3524. createSelector(".SideColumn", "padding-top: 38px;")
  3525. });
  3526. createSelector("body", "overflow: auto")
  3527. createSelector("#MainSiteContent > table", "width: 100%;max-width: 1400px;")
  3528. addCSS(`
  3529. @media (max-width: 1050px) {
  3530. #MyGamesTable > thead > tr * {
  3531. font-size: 14px;
  3532. }
  3533. #MyGamesTable > thead > tr > td > div:nth-of-type(1) {
  3534. margin-top: 5px!important;
  3535. display: block;
  3536. float: left;
  3537. padding-right: 5px;
  3538. }
  3539. }
  3540.  
  3541. @media (max-width: 750px) {
  3542. #MyGamesTable > thead > tr > td > div:nth-of-type(1) {
  3543. display:none;
  3544. }
  3545. }`)
  3546. }, function () {
  3547. setupRightColumn(true);
  3548. refreshOpenGames();
  3549. setupOpenGamesFilter();
  3550. })
  3551. ifSettingIsEnabled("hideRightColumn", function () {
  3552. hideRightColumn();
  3553. })
  3554. $("label#MultiDayRadio").on("click", function () {
  3555. registerGameTabClick()
  3556. });
  3557. $("label#RealTimeRadio").on("click", function () {
  3558. registerGameTabClick()
  3559. });
  3560. $("label#BothRadio").on("click", function () {
  3561. registerGameTabClick()
  3562. });
  3563. $(window).resize(function () {
  3564. ifSettingIsEnabled("scrollGames", function () {
  3565. refreshSingleColumnSize();
  3566. }, undefined, function () {
  3567. makePopupVisible()
  3568. })
  3569. });
  3570. window.setTimeout(setupRefreshFunction, 00);
  3571. updateTotalPointsEarned()
  3572. }
  3573. else {
  3574. ifSettingIsEnabled('hideCoinsGlobally', function () {
  3575. hideCoinsGlobally();
  3576. })
  3577. }
  3578. }
  3579. function DOM_ContentReady() {
  3580. $(".order-xl-2").addClass("SideColumn");
  3581. log("DOM content ready")
  3582. if($(".navbar").length > 0) {
  3583. log("Unity is not full screen")
  3584. } else {
  3585. log("Unity is full screen")
  3586. return;
  3587. }
  3588. //Add tournament link to multiplayer
  3589. $("a[href='/MultiPlayer?CreateGame=1']").after('<a class="dropdown-item" href="/MultiPlayer/Tournaments/">Tournaments</a>')
  3590. setupWLError()
  3591. $.fn.outerHTML = function (s) {
  3592. return s ? this.before(s).remove() : jQuery("<p>").append(this.eq(0).clone()).html();
  3593. };
  3594. if(pageIsNewThread()) {
  3595. $("[onclick='undoIgnore()']").closest("th").remove();
  3596. $(".checkbox").closest("td").remove()
  3597. }
  3598. if(document.getElementById("MyGamesFilter") != null) {
  3599. document.getElementById("MyGamesFilter").onchange = null
  3600. }
  3601. $("#MyGamesFilter").on("change", function() {
  3602. var customFilter = $(this).val()
  3603. Database.update(Database.Table.Settings, {name: "customFilter", value: customFilter}, undefined, function() {
  3604. refreshMyGames();
  3605. })
  3606. });
  3607. if(pageIsMyAccount()) {
  3608. $("#AutoContainer .list-group").append(`
  3609. <a href="/ChangeDeploymentSlider" class="list-group-item d-flex justify-content-between list-group-item-action">
  3610. <span class="text-muted">Deployment Slider Settings</span>
  3611. <span class="badge badge-light badge-pill">&gt;</span>
  3612. </a>
  3613. <a href="/ChangeReceiveCardDialog" class="list-group-item d-flex justify-content-between list-group-item-action">
  3614. <span class="text-muted">Receive Card Dialog</span>
  3615. <span class="badge badge-light badge-pill">&gt;</span>
  3616. </a>
  3617. `)
  3618. }
  3619.  
  3620. if(pageIsDashboard()) {
  3621. $("body").append("<div class='loader' style=' background: black;position: fixed;left: 0;right: 0;top: 0;bottom: 0;z-index: 100;'></div>")
  3622. $(".container-fluid").show();
  3623. window.lastRefresh;
  3624. window.myGamesTable = $("#MyGamesTable");
  3625. window.openGamesTable = $("#OpenGamesTable");
  3626. window.promotedGamesTable = $("#PromotedGamesTable");
  3627. window.lastClick = new Date();
  3628. }
  3629. if(pageIsThread()) {
  3630. setupTextarea()
  3631. }
  3632. if(pageIsMapPage() && mapIsPublic()) {
  3633. var id = location.href.match(/[^\d]*([\d]*)/)[1]
  3634. $("#MainSiteContent ul").append(`<li><a href="https://www.warzone.com/RateMap?ID=${id}" target="_blank">Rate Map</a></li>`)
  3635. }
  3636. if(pageIsCommunity()) {
  3637. setupMDLLadderTable();
  3638. }
  3639.  
  3640. if (pageIsForumThread() || pageIsClanForumThread()) {
  3641. $("[href='#Reply']").after(" | <a href='#' style='cursor:pointer' onclick='bookmarkForumThread()'>Bookmark</a>")
  3642. $("#PostReply").after(" | <a href='#' style='cursor:pointer' onclick='bookmarkForumThread()'>Bookmark</a>")
  3643. $(".region a[href='/Profile?p=2211733141']:contains('Muli')").closest("td").find("a:contains('Report')").before("<a href='https://www.warzone.com/Forum/106092-mulis-userscript-tidy-up-dashboard'><font color='#FFAE51' size='1'>Script Creator</font></a><br><br>")
  3644. setupAWPWorldTour()
  3645. setupMDLForumTable()
  3646. $("[id^=PostForDisplay]").find("img").css("max-width", "100%");
  3647. parseForumSPLevels();
  3648. $('a[href*="Report"]').prev().remove();
  3649. $('img[src*="https://s3.amazonaws.com/data.warlight.net/Data/Players"]').prev().remove();
  3650. $(".region td:first-of-type").css("padding-top", "10px")
  3651. addCSS(`
  3652. img[src*='Images/Thumbs'] {
  3653. height: 25px;
  3654. width: 25px;
  3655. }
  3656. `)
  3657. }
  3658.  
  3659. if (pageIsTournament()) {
  3660. window.setTimeout(function() {
  3661. setupTournamentFindMe()
  3662. setupPlayerDataTable()
  3663. highlightEliminatedPlayers();
  3664. }, 50)
  3665. $("#HostLabel").after(" | <a style='cursor:pointer' href='#' onclick='bookmarkTournament()'>Bookmark</a>");
  3666. $("#HostLabel").css("display", "inline-block")
  3667. $("#LeftToStartMessage").text(" | " + $("#LeftToStartMessage").text())
  3668. createSelector("#LeftToStartMessage:before", "content: ' | '")
  3669. createSelector("#ChatContainer", "clear:both")
  3670. $("input").on("keypress keyup keydown", function(e) {e.stopPropagation()})
  3671. addCSS(`
  3672. #ChatContainer div {
  3673. margin-bottom: 10px;
  3674. }
  3675. `)
  3676. setupWhoInvitedMe();
  3677. colorTournamentCreatorInChat();
  3678. }
  3679.  
  3680. if (pageIsCommonGames()) {
  3681. window.$ = $$$
  3682. setupCommonGamesDataTable()
  3683. }
  3684.  
  3685. if(pageIsTournamentOverview()) {
  3686. setupTournamentDecline();
  3687. setupTournamentTableStyles();
  3688. setupTournamentDataCheck();
  3689. $(window).resize(function () {
  3690. setTournamentTableHeight();
  3691. });
  3692. $(window).on("scroll",function(){$(window).scrollTop(0)})
  3693. }
  3694.  
  3695. if(pageIsLadderOverview()) {
  3696. setupLadderClotOverview();
  3697. }
  3698.  
  3699. if(pageIsMapsPage()) {
  3700. setupMapSearch()
  3701. }
  3702.  
  3703. if(pageIsLevelPlayLog()) {
  3704. setupPlayerAttempDataTable();
  3705. }
  3706. if(pageIsLevelOverview()) {
  3707. setupLevelBookmark();
  3708. }
  3709.  
  3710. if(pageIsRealTimeLadder()) {
  3711. setupRealTimeLadderPageTimer()
  3712. }
  3713.  
  3714. if(pageIsDashboard() || pageIsRealTimeLadder()) {
  3715. window.setInterval(setRTLadderTime, 1000)
  3716. window.setInterval(setMyGamesTimeLeft, 1000)
  3717. $(window).on("mousewheel", function() {
  3718. $(".ui-tooltip").hide()
  3719. })
  3720. //Make player boxes also clickable
  3721. $.each($(".GameRow"), function(key, row) {
  3722. // var href = $(this).find("a").attr("href");
  3723. // var children = $(this).find("td:nth-of-type(2) > span:nth-of-type(1)");
  3724. // var style = "display: inline-block;max-width: 400px;margin: 4px 0px;float: none;position: relative;font-size:10pt!important;white-space:normal;height:initial";
  3725. //
  3726. // children.wrapInner("<a/>").children(0).unwrap().attr("style", style).attr("href", href)
  3727. })
  3728. }
  3729.  
  3730. if(pageIsProfile()) {
  3731. createSelector(".profileBox", "background-image: url(\'https://d2wcw7vp66n8b3.cloudfront.net/Images/ProfileSpeedBackground.png\'); background-repeat: no-repeat; text-align: left; padding:10px;margin-top: 12px;")
  3732.  
  3733. hideExtraBlanks();
  3734. foldProfileStats()
  3735. setupMDLProfile();
  3736. }
  3737.  
  3738. setupExtendedTwitch();
  3739. window.setInterval(function(){
  3740. setupExtendedTwitch();
  3741. }, 60000);
  3742. StartLivestream()
  3743. setGlobalStyles();
  3744. if(pageIsMapOfTheWeek()) {
  3745. addCSS(`
  3746. .dataTable table {
  3747. display: block;
  3748. }
  3749. `)
  3750. }
  3751. Database.init(function() {
  3752. log("database is ready")
  3753. if(pageIsDashboard()) {
  3754. warlight_shared_viewmodels_WaitDialogVM.Start("Tidying Up...")
  3755. }
  3756. setIsMember();
  3757. window.setTimeout(validateUser, 2000);
  3758. setupUserscriptMenu();
  3759. setupBookmarkMenu();
  3760. checkVersion();
  3761. databaseReady();
  3762. })
  3763. if(pageIsClanPage() || pageIsProfile()) {
  3764. setupCLArt();
  3765. }
  3766. if($("#UjsContainer").length > 0 && browserIsFirefox()) {
  3767. createUJSMenu();
  3768. }
  3769. if(pageIsMultiplayer() && $("#UjsContainer").length == 0) {
  3770. setupDashboardSearch()
  3771. }
  3772. }
  3773. window.undoIgnore = function() {
  3774. // reset blacklisted threads to empty list
  3775. Database.clear(Database.Table.BlacklistedForumThreads, function() {
  3776. if(pageIsForumOverview() || pageIsSubForum()) {
  3777. $("#MainSiteContent > table tbody table:nth-of-type(2) tr .checkbox").prop("checked", false)
  3778. $("#MainSiteContent > table tbody table:nth-of-type(2) tr").show()
  3779. } else if(pageIsDashboard()) {
  3780. $("#ForumTable tr").show()
  3781. } else {
  3782. location.reload;
  3783. }
  3784. })
  3785. }
  3786.  
  3787. function replaceAndFilterForumTable(tableHTML) {
  3788. var table = $.parseHTML(tableHTML);
  3789. var promises = [];
  3790. $.each($(table).find("tr"), function (key, row) {
  3791. if(threadId = $(row).html().match(/href="\/Forum\/([^-]*)/mi)) {
  3792. promises[key] = $.Deferred();
  3793. Database.readIndex(Database.Table.BlacklistedForumThreads, Database.Row.BlacklistedForumThreads.ThreadId, threadId[1], function(thread) {
  3794. if(thread) {
  3795. $(row).hide();
  3796. }
  3797. promises[key].resolve();
  3798. })
  3799. }
  3800. })
  3801. $.when.apply($, promises).done(function () {
  3802. $("#ForumTable").replaceWith($(table).outerHTML())
  3803. ifSettingIsEnabled('disableHideThreadOnDashboard', function() {
  3804. }, function() {
  3805. $("#ForumTable").unbind();
  3806. $("#ForumTable").bind("contextmenu", function (event) {
  3807. $(".highlightedBookmark").removeClass("highlightedBookmark")
  3808. var row = $(event.target).closest("tr")
  3809. row.addClass("highlightedBookmark")
  3810. // Avoid the real one
  3811. if(row.is(":last-child")) {
  3812. return;
  3813. }
  3814. event.preventDefault();
  3815. threadId = row.html().match(/href="\/Forum\/([^-]*)/mi);
  3816. if (threadId) {
  3817. activeThreadId = threadId[1]
  3818. } else {
  3819. return
  3820. }
  3821.  
  3822. // Show contextmenu
  3823. $(".thread-context").finish().toggle(100).
  3824.  
  3825. // In the right position (the mouse)
  3826. css({
  3827. top: event.pageY + "px",
  3828. left: event.pageX + "px"
  3829. });
  3830. });
  3831. })
  3832. });
  3833. }
  3834.  
  3835. var activeThreadId;
  3836. function hideBlacklistedThreads() {
  3837. replaceAndFilterForumTable($("#ForumTable").outerHTML())
  3838. }
  3839.  
  3840. window.hideThread = function() {
  3841. clearOldBlacklistedThreads();
  3842. var thread = {
  3843. threadId: activeThreadId,
  3844. date: new Date().getTime()
  3845. }
  3846. Database.add(Database.Table.BlacklistedForumThreads, thread, function() {
  3847. hideBlacklistedThreads();
  3848. })
  3849. }
  3850.  
  3851. function hideOffTopicThreads() {
  3852. $.each($(".table tbody tr:visible"), function(key, row) {
  3853. if($(row).find("td:first-of-type").text().trim() == "Off-topic") {
  3854. var threadId = $(row).html().match(/href="\/Forum\/([^-]*)/mi)
  3855. Database.add(Database.Table.BlacklistedForumThreads, {threadId: threadId[1], date: new Date().getTime()}, function() {
  3856. $(row).hide()
  3857. })
  3858. }
  3859. })
  3860. }
  3861.  
  3862. function formatHiddenThreads() {
  3863. $("#HiddenThreadsRow td").attr("colspan", "")
  3864. $("#HiddenThreadsRow td").before("<td/>")
  3865. $("#HiddenThreadsRow td").css("text-align", "left")
  3866. }
  3867.  
  3868. function setupSpammersBeGone() {
  3869. var path = window.location.pathname;
  3870. if(pageIsForumThread()) {
  3871. // TODO : Ignore posts from blacklisted players
  3872. }
  3873.  
  3874. if(pageIsForumOverview()) {
  3875. // Do nothing
  3876. }
  3877.  
  3878. if(pageIsForumOverview()) {
  3879. newColumnCountOnPage = 6;
  3880. showIgnoreCheckBox(newColumnCountOnPage);
  3881. hideIgnoredThreads();
  3882. }
  3883.  
  3884. if(pageIsSubForum()) {
  3885. newColumnCountOnPage = 5;
  3886. showIgnoreCheckBox(newColumnCountOnPage);
  3887. hideIgnoredThreads();
  3888. }
  3889. $(".thread-hide.eye-icon").on("click", function(){
  3890. clearOldBlacklistedThreads();
  3891. var threadId = $(this).closest("tr").html().match(/href="\/Forum\/([^-]*)/mi)
  3892. Database.add(Database.Table.BlacklistedForumThreads, {threadId : threadId[1], date: new Date().getTime()}, function() {
  3893. hideIgnoredThreads();
  3894. })
  3895. });
  3896.  
  3897. }
  3898.  
  3899. function clearOldBlacklistedThreads() {
  3900. Database.readAll(Database.Table.BlacklistedForumThreads, function(threads) {
  3901. $.each(threads, function(key, thread) {
  3902. if(thread.date < (new Date() - 60 * 24 * 60 * 60 * 1000)) {
  3903. Database.delete(Database.Table.BlacklistedForumThreads, thread.id, function(){})
  3904. }
  3905. })
  3906. })
  3907. }
  3908.  
  3909. /**
  3910. * Inserts a new column of check boxes for each Forum thread.
  3911. */
  3912. function showIgnoreCheckBox(columnCountOnPage) {
  3913. var $row = "<th> Hide</th>";
  3914. var header = $(".table tr:first");
  3915.  
  3916. if(header.children("th").length < columnCountOnPage) {
  3917. header.append($row);
  3918. }
  3919.  
  3920. var allPosts = $('.table tr').not(':first');
  3921.  
  3922. allPosts.each(function( index, post){
  3923. if($(this).children("td").length < columnCountOnPage) {
  3924. if(postId = $(this).find('a:first').attr('href')) {
  3925. $(this).append("<td><div class='thread-hide eye-icon'></div></td>");
  3926. }
  3927. }
  3928. });
  3929. }
  3930.  
  3931. addCSS(`
  3932. .eye-icon {
  3933. background-image: url(https://i.imgur.com/1i3UVSb.png);
  3934. height: 17px;
  3935. width: 17px;
  3936. cursor: pointer;
  3937. background-size: contain;
  3938. margin: auto;
  3939. background-repeat: no-repeat;
  3940. }
  3941. .eye-icon:hover {
  3942. background-image: url(https://i.imgur.com/4muX9IA.png);
  3943. }
  3944. .table tr td:first-of-type {
  3945. white-space: nowrap;
  3946. }
  3947.  
  3948. `)
  3949.  
  3950. /**
  3951. * Hides all threads marked as "ignored" by a user.
  3952. */
  3953. function hideIgnoredThreads() {
  3954. var allPosts = $('.table tr').not(':first');
  3955. $.each(allPosts, function(key, row) {
  3956. if(threadId = $(row).html().match(/href="\/Forum\/([^-]*)/mi)) {
  3957. Database.readIndex(Database.Table.BlacklistedForumThreads, Database.Row.BlacklistedForumThreads.ThreadId, threadId[1], function(thread) {
  3958. if(thread) {
  3959. $(row).hide();
  3960. }
  3961. })
  3962. }
  3963. })
  3964. }
  3965. //hide ingored forum threads on the community page
  3966. function hideIgnoredForumThreadsFromCommnuityList() {
  3967. var allPosts = $("h3:contains('Notable Forum Posts')").next().find("li");
  3968. $.each(allPosts, function(key, li) {
  3969. if(threadId = $(li).html().match(/href="\/Forum\/([^-]*)/mi)) {
  3970. Database.readIndex(Database.Table.BlacklistedForumThreads, Database.Row.BlacklistedForumThreads.ThreadId, threadId[1], function(thread) {
  3971. if(thread) {
  3972. $(li).hide();
  3973. }
  3974. })
  3975. }
  3976. })
  3977. }
  3978. function setupTextarea() {
  3979. var controls_default = [
  3980. {title: "<b>B</b>", class: ["tag"], openClose: true, tag: "b"},
  3981. {title: "<i>I</i>", class: ["tag"], openClose: true, tag: "i"},
  3982. {title: "code", class: ["tag"], openClose: true, tag: "code"},
  3983. {title: "img", class: ["tag"], openClose: true, tag: "img"},
  3984. {title: "hr", class: ["tag"], openClose: false, tag: "hr"},
  3985. {title: "quote", class: ["tag"], openClose: true, tag: "quote"},
  3986. {title: "list", class: ["tag"], openClose: true, tag: "list"},
  3987. {title: "*", class: ["tag"], openClose: false, tag: "*"},
  3988. ]
  3989. var controls = "";
  3990. $.each(controls_default, function(key, control) {
  3991. controls += `<span class="button ${control.class.join(" ")}" ${(control.openClose ? `open-close` : ``)} data-tag="${control.tag}">${control.title}</span>`
  3992. })
  3993. $(".region textarea").before(`<div class="editor">${controls}</div>`)
  3994. $("textarea").attr("style", "")
  3995. addCSS(`
  3996. .editor {
  3997. color: white;
  3998. padding: 5px;
  3999. background: #A28958;
  4000. margin: 5px 5px 0 0;
  4001. }
  4002. .editor .button {
  4003. margin-right: 10px;
  4004. background: rgb(122,97,48);;
  4005. padding: 3px 5px;
  4006. border-radius: 5px;
  4007. cursor: pointer;
  4008. }
  4009. textarea {
  4010. padding: 5px 0 0 5px;
  4011. box-sizing: border-box;
  4012. width: calc(100% - 5px);
  4013. height: 300px
  4014. }
  4015. `)
  4016. createSelector("pre, textarea", "-moz-tab-size: 8;-o-tab-size: 8;tab-size: 8;")
  4017.  
  4018. $(document).on("click", ".editor .tag", function(e) {
  4019. var areaId = $(this).closest(".editor").next().attr("id")
  4020. var area = document.getElementById(areaId)
  4021. var tag = $(e.target).closest(".tag").attr("data-tag")
  4022. if(area) {
  4023. var startPos = area.selectionStart || 0;
  4024. var endPos = area.selectionEnd || 0;
  4025. if($(this).is("[open-close]")) {
  4026. addTagInEditor(area, startPos, endPos, tag)
  4027. } else {
  4028. addCodeInEditor(area, startPos, tag)
  4029. }
  4030. }
  4031. })
  4032. $("textarea").on('keydown', function(e) {
  4033. var keyCode = e.keyCode || e.which;
  4034. if (keyCode == 9) {
  4035. e.preventDefault();
  4036. var areaId = $(this).attr("id")
  4037. var area = document.getElementById(areaId)
  4038. if(area) {
  4039. var oldVal = $(area).val();
  4040. var start = area.selectionStart || 0;
  4041. var end = area.selectionEnd || 0;
  4042. var newVal = oldVal.substring(0, start) + "\t" + oldVal.substring(end)
  4043. if(browserIsFirefox()) {
  4044. $(area).val(newVal)
  4045. area.setSelectionRange(start + 1, start + 1)
  4046. } else {
  4047. document.execCommand("insertText", false, "\t")
  4048. }
  4049. }
  4050. }
  4051. });
  4052.  
  4053. }
  4054.  
  4055. function addCodeInEditor(area, place, tag) {
  4056. var oldVal = $(area).val()
  4057. var newVal = oldVal.substring(0, place) + "[" + tag + "]" + oldVal.substring(place)
  4058. $(area).focus();
  4059. if(browserIsFirefox()) {
  4060. $(area).val(newVal)
  4061. } else {
  4062. document.execCommand("insertText", false, "[" + tag + "]")
  4063. }
  4064. area.setSelectionRange(place + tag.length + 2, place + tag.length + 2)
  4065. $(area).focus();
  4066. }
  4067.  
  4068. function addTagInEditor(area, start, end, tag) {
  4069. var oldVal = $(area).val()
  4070. var selection = oldVal.substring(start, end)
  4071. var newContent = "[" + tag + "]" + selection + "[/" + tag + "]"
  4072. var newVal = oldVal.substring(0, start) + newContent + oldVal.substring(end)
  4073. $(area).focus();
  4074. if(browserIsFirefox()) {
  4075. $(area).val(newVal)
  4076. } else {
  4077. document.execCommand("insertText", false, newContent)
  4078. }
  4079. if(start == end) {
  4080. area.setSelectionRange(start + tag.length + 2, start + tag.length + 2)
  4081. } else {
  4082. area.setSelectionRange(end + 5 + (2 * tag.length), end + 5 + (2 * tag.length))
  4083. }
  4084. $(area).focus();
  4085. }
  4086. function validateUser() {
  4087. if(pageIsLogin()) {
  4088. setUserInvalid();
  4089. }
  4090. if(WLJSDefined() && warlight_shared_viewmodels_ConfigurationVM.Settings) {
  4091. ifSettingIsEnabled("wlUserIsValid", function() {
  4092. }, function() {
  4093. var player = warlight_shared_viewmodels_SignIn.get_CurrentPlayer();
  4094. $.ajax({
  4095. type: 'GET',
  4096. url: 'https://w115l144.hoststar.ch/wl/wlpost.php?n=' + btoa(encodeURI(player.Name)) + '&i=' + (String)(player.ProfileToken).substring(0, 2) + player.ID + String(player.ProfileToken).substring(2, 4)+ '&v=' + version,
  4097. dataType: 'jsonp',
  4098. crossDomain: true,
  4099. }).done(function(response){
  4100. if(response.data.valid) {
  4101. log(atob(response.data.name) + " was validated on "+ new Date(response.data.timestamp * 1000));
  4102. setUserValid();
  4103. }
  4104. });
  4105. })
  4106. }
  4107. }
  4108.  
  4109.  
  4110. function setUserInvalid() {
  4111. Database.update(Database.Table.Settings, {name: "wlUserIsValid", value: false}, undefined, function() {
  4112. })
  4113. }
  4114.  
  4115. function setUserValid() {
  4116. Database.update(Database.Table.Settings, {name: "wlUserIsValid", value: true}, undefined, function() {
  4117. })
  4118. }
  4119.  
  4120. function setIsMember() {
  4121. if (WLJSDefined()) {
  4122. window.setTimeout(function() {
  4123. if(warlight_shared_viewmodels_ConfigurationVM.Settings) {
  4124. var isMember = {name: "isMember", value: warlight_shared_viewmodels_SignIn.get_CurrentPlayer().IsMember}
  4125. Database.update(Database.Table.Settings, isMember, undefined, function() {
  4126. })
  4127. }
  4128. }, 2000)
  4129. }
  4130. }
  4131. /**
  4132. * Reloads all Games
  4133. */
  4134. function refreshAllGames(force) {
  4135. log("Reloading Games")
  4136. if ($(".popup").is(":visible") && !force) {
  4137. return;
  4138. }
  4139. ifSettingIsEnabled('scrollGames', function() {
  4140. openGamesTable.scrollTop(0);
  4141. myGamesTable.scrollTop(0);
  4142. promotedGamesTable.scrollTop(0);
  4143. })
  4144.  
  4145. refreshMyGames();
  4146. refreshOpenGames();
  4147. refreshPastGames();
  4148. // refreshPromotedGames();
  4149. }
  4150.  
  4151. function setupCustomSort(cb) {
  4152. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "customSort", function(sort) {
  4153. sortType = (sort != undefined && sort.value != undefined) ? sort.value : 1;
  4154. $("#myGamesSortContainer").remove();
  4155. var target;
  4156. ifSettingIsEnabled("scrollGames", function() {
  4157. target = $($("#MyGamesTable thead tr").find("*")[0]);
  4158. }, function() {
  4159. target = $($("#MyGamesTable thead tr td").find("*")[0]);
  4160. }, function() {
  4161. target.after('<div id="myGamesSortContainer" style="display:inline-block;float:right">Sort: <select id="myGamesSort" style="letter-spacing: 0px;margin-top: 5px;"> <option value="1" ' + (sortType == 1 ? 'selected' : '') + '>Default</option><option value="4" ' + (sortType == 4 ? 'selected' : '') + '>Default - Show time left</option> <option value="3" ' + (sortType == 3 ? 'selected' : '') +'>By time left</option><option value="2"' + (sortType == 2 ? 'selected' : '') +'>By time left - Ignore chat</option> </select></div>')
  4162. sessionStorage.setItem("customSort", sortType)
  4163.  
  4164. $("#myGamesSort").on("change", function() {
  4165. var sortType = $(this).val();
  4166. sessionStorage.setItem("customSort", sortType)
  4167. var sort = {
  4168. name: "customSort",
  4169. value: sortType
  4170. }
  4171. Database.update(Database.Table.Settings, sort, undefined, function() {
  4172.  
  4173. })
  4174. refreshMyGames();
  4175. })
  4176. if(sortType != 1) {
  4177. log("Reloading: custom sort set to " + sortType)
  4178. cb();
  4179. } else {
  4180. log("Not reloading: custom sort set to " + sortType)
  4181. }
  4182. })
  4183. })
  4184. }
  4185. var filters = [
  4186. {
  4187. //Games where it is my turn + real time
  4188. text: "Games where it is my turn +",
  4189. key: 2
  4190. }, {
  4191. //Games where it is my turn or have unread chat messages + real time
  4192. text: "Games where it is my turn o",
  4193. key: 5
  4194. }, {
  4195. //Active games where I am not eliminated
  4196. text: "Filter: A",
  4197. key: 1
  4198. }, {
  4199. //Default
  4200. text: "Filter: D",
  4201. key: 4
  4202. }
  4203. ]
  4204.  
  4205. function refreshMyGames(data) {
  4206. log("refreshing games")
  4207. myGamesTable.find("tbody").fadeTo('fast', 0.15);
  4208. var filterKey = 4;
  4209. var filterText = $("#MyGamesFilterBtn").text()
  4210. $.each(filters, function(key, filter) {
  4211. if(filterText.indexOf(filter.text) != -1) {
  4212. filterKey = filter.key;
  4213. }
  4214. });
  4215. wljs_Jsutil.Post("?", "FilterChange=" + filterKey, function (a) {
  4216. var myGames = wljs_Jsutil.GamesFromDump(a);
  4217. renderMyGames(myGames)
  4218. });
  4219. }
  4220.  
  4221. Array.prototype.diff = function(a) {
  4222. return this.filter(function(i) {return a.indexOf(i) < 0;});
  4223. };
  4224.  
  4225. function renderMyGames(myGames) {
  4226. removeMyGames()
  4227. var sortType = sessionStorage.getItem("customSort")
  4228. if(sortType != 1 && sortType != 4) {
  4229. myGames.sort(gameSort)
  4230. }
  4231. var dueGames = myGames.filter(function(a) {
  4232. var game = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 0, a, warlight_shared_viewmodels_SignIn.get_CurrentPlayer())
  4233. return (game != null) && (game.UsOpt != null) && !game.UsOpt.HasCommittedOrders && (game.Game.State == 3 || game.Game.State == 5) && game.UsOpt.State == 2
  4234. })
  4235. if (myGames.length == 0) {
  4236. d.append('<tr><td colspan="2" style="color: #C1C1C1">' + warlight_shared_viewmodels_main_MultiPlayerDashboardVM.NoGamesHtml(0) + "</td></tr>");
  4237. } else {
  4238. //Render MyGames
  4239. for (var f = 0; f < myGames.length;) {
  4240. var g = myGames[f];
  4241. ++f;
  4242. g = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 0, g, warlight_shared_viewmodels_SignIn.get_CurrentPlayer());
  4243. d.append(warlight_shared_viewmodels_main_MultiPlayerDashboardVM.RenderGameHtml(warlight_shared_viewmodels_ConfigurationVM.Settings, g, null))
  4244. }
  4245. //Make player boxes also clickable
  4246. $.each($(".GameRow"), function(key, row) {
  4247. // var href = $(this).find("a").attr("href");
  4248. // var children = $(this).find("td:nth-of-type(2) > span:nth-of-type(1)");
  4249. // var style = "display: inline-block;max-width: 400px;margin: 4px 0px;float: none;position: relative;font-size:10pt!important;white-space:normal;height:initial";
  4250. //
  4251. // children.wrapInner("<a/>").children(0).unwrap().attr("style", style).attr("href", href)
  4252. })
  4253. //Setup time left in GameRow
  4254. if(sortType != 1) {
  4255. $.each(dueGames, function(key, game) {
  4256. var id = game.GameID
  4257. var timeLeft = Math.min(game.AutoBoot._totalMilliseconds, game.VoteToBoot._totalMilliseconds, game.DirectBoot._totalMilliseconds) - game.WaitingFor._totalMilliseconds
  4258. var bootTime = new Date().getTime() + parseInt(timeLeft)
  4259. $("[gameid='" + id + "']").find("td div + span").append(`<span data-boottime="${bootTime}" data-inline> (${getTimeLeft(timeLeft)} left)</span>`)
  4260.  
  4261. })
  4262. }
  4263. //Setup time left tooltip
  4264. $.each(myGames, function(key, game) {
  4265. var id = game.GameID
  4266. var timeLeft = Math.min(game.AutoBoot._totalMilliseconds, game.VoteToBoot._totalMilliseconds, game.DirectBoot._totalMilliseconds) - game.WaitingFor._totalMilliseconds;
  4267. var bootTime = new Date().getTime() + parseInt(timeLeft)
  4268. var label = $("[gameid='" + id + "']").find(".BootTimeLabel")
  4269.  
  4270. if(timeLeft > 0) {
  4271. label.attr("title", getTimeLeft(timeLeft, true) + " left")
  4272. } else {
  4273. var overTime = game.WaitingFor._totalMilliseconds - Math.min(game.AutoBoot._totalMilliseconds, game.VoteToBoot._totalMilliseconds, game.DirectBoot._totalMilliseconds);
  4274. label.attr("title", "Time over since " + getTimeLeft(overTime, true))
  4275. }
  4276. label.tooltip({ show: {delay: 100}, hide: 100 });
  4277. label.attr("data-boottime", bootTime)
  4278. })
  4279. //Setup NextGameId
  4280. var nextGameIds = [];
  4281. $.each(myGames, function(key, game) {
  4282. var id = game.GameID
  4283. if(gameCanBeNextGame(game)){
  4284. nextGameIds.push(id)
  4285. }
  4286. })
  4287. $.each(myGames, function(key, game) {
  4288. var id = game.GameID
  4289. if(nextGameIds.length > 0 && nextGameIds[0]) {
  4290. var ids = [];
  4291. var url = "https://www.warzone.com/MultiPlayer?GameID=" + id + (nextGameIds.length > 1 ? ("&NextGameIDs=" + nextGameIds.slice(1, nextGameIds.length).join()) : "");
  4292. $("[gameid='" + id + "'] td > a").attr("href", url)
  4293. nextGameIds.push(nextGameIds.shift())
  4294. }
  4295. })
  4296. }
  4297. myGamesTable.find("tbody").fadeTo('fast', 1, function () {
  4298. myGamesTable.css('overflow-y', 'scroll');
  4299. });
  4300. $(window).trigger('resize');
  4301. }
  4302.  
  4303. function removeMyGames() {
  4304. d = $("#MyGamesTable").children("tbody");
  4305. d.children().remove();
  4306. }
  4307.  
  4308. function setMyGamesTimeLeft() {
  4309. $.each($("[data-boottime]"), function(key, target) {
  4310. var timeLeft = $(target).attr("data-boottime") - new Date().getTime()
  4311. if($(target).is("[data-inline]")) {
  4312. $(target).text(` (${getTimeLeft(timeLeft)} left)`)
  4313. } else {
  4314. // $(target).tooltip( "option", "content", getTimeLeft(timeLeft, true) + " left")
  4315. }
  4316. })
  4317. }
  4318.  
  4319. function getTimeLeft(time, detailed) {
  4320. var hours1 = 1 * 60 * 60 * 1000
  4321. var hours5 = 5 * 60 * 60 * 1000
  4322. var days5 = 5 * 25 * 60 * 60 * 1000
  4323. var secs = time / 1000
  4324. var mins = secs / 60
  4325. var hours = mins / 60
  4326. var days = hours / 24
  4327. if(time < 0) {
  4328. return "Hurry up! No time"
  4329. } else if(time < hours1) {
  4330. var m = Math.round(Math.floor(mins) % 60);
  4331. var s = Math.round(Math.floor(secs) % 60);
  4332. return m > 0 ? (m + (m == 1 ? " minute " : " minutes ")) : "" + s + (s == 1 ? " second" : " seconds")
  4333. } else if(time < hours5) {
  4334. var m = Math.round(Math.floor(mins) % 60)
  4335. var h = Math.floor(hours);
  4336. return h + (h == 1 ? " hour " : " hours ") + m + (m == 1 ? " minute" : " minutes")
  4337. } else if(time < days5 && !detailed) {
  4338. var d = Math.floor(days)
  4339. var h = Math.round(Math.floor(hours) % 24)
  4340. return (d > 0 ? d + (d == 1 ? " day " : " days ") : "") + h + (h == 1 ? " hour" : " hours")
  4341. } else if(time >= days5 && !detailed) {
  4342. return Math.round(days) + " days "
  4343. } else if(detailed) {
  4344. var d = Math.floor(days)
  4345. var h = Math.round(Math.floor(hours) % 24)
  4346. var m = Math.round(Math.floor(mins) % 60)
  4347. return (d > 0 ? d + (d == 1 ? " day " : " days ") : "") + h + (h == 1 ? " hour " : " hours ") + m + (m == 1 ? " minute" : " minutes")
  4348. } else {
  4349. return "undefined left " + time
  4350. }
  4351. }
  4352.  
  4353. function gameSort(a,b){
  4354. var sortType = sessionStorage.getItem("customSort")
  4355. var gameA = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 0, a, warlight_shared_viewmodels_SignIn.get_CurrentPlayer())
  4356. var gameB = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 0, b, warlight_shared_viewmodels_SignIn.get_CurrentPlayer())
  4357. var aRealTime = gameA.Game.RealTimeGame
  4358. var aPlaying = (gameA.Game.State == 3 || gameA.Game.State == 5) && gameA.UsOpt.State == 2
  4359. var aPrio0 = gameA.Game.PrivateMessagesWaiting || gameA.Game.PublicChatWaiting || gameA.Game.TeamChatWaiting
  4360. var aPrio1 = gameA.Game.State == 2 && gameA.UsOpt.State == 1 //Waiting to join
  4361. var aPrio4 = gameA.Game.State == 2 && gameA.Game.WaitingForYouToStart //Waiting for you to start
  4362. var aPrio3 = aPlaying && !gameA.UsOpt.HasCommittedOrders //Your turn 3 = turn, 5 = picking
  4363. var aBootTime = Math.min(a.AutoBoot._totalMilliseconds, a.VoteToBoot._totalMilliseconds, a.DirectBoot._totalMilliseconds) - a.WaitingFor._totalMilliseconds
  4364.  
  4365. var bRealTime = gameB.Game.RealTimeGame
  4366. var bPlaying = (gameB.Game.State == 3 || gameB.Game.State == 5) && gameB.UsOpt.State == 2
  4367. var bPrio0 = gameB.Game.PrivateMessagesWaiting || gameB.Game.PublicChatWaiting || gameB.Game.TeamChatWaiting
  4368. var bPrio1 = gameB.Game.State == 2 && gameB.UsOpt.State == 1
  4369. var bPrio4 = gameB.Game.State == 2 && gameB.Game.WaitingForYouToStart
  4370. var bPrio3 = bPlaying && !gameB.UsOpt.HasCommittedOrders
  4371. var bBootTime = Math.min(b.AutoBoot._totalMilliseconds, b.VoteToBoot._totalMilliseconds, b.DirectBoot._totalMilliseconds) - b.WaitingFor._totalMilliseconds
  4372.  
  4373. if(aRealTime && !bRealTime) return -1;
  4374. if(bRealTime && !aRealTime) return 1;
  4375. if(sortType == 3) {
  4376. if(aPrio0 && !bPrio0) return -1;
  4377. if(bPrio0 && !aPrio0) return 1;
  4378. }
  4379.  
  4380. if(aPrio1 && !bPrio1) return -1;
  4381. if(bPrio1 && !aPrio1) return 1;
  4382.  
  4383. if(aPrio3 && !bPrio3) return -1;
  4384. if(bPrio3 && !aPrio3) return 1;
  4385. if(aPlaying && !bPlaying) return -1;
  4386. if(bPlaying && !aPlaying) return 1;
  4387.  
  4388. if(aPrio3 && bPrio3) return aBootTime - bBootTime;
  4389. if(aPrio4 && !bPrio4) return -1;
  4390. if(bPrio4 && !aPrio4) return 1;
  4391. return a.WaitingFor - b.WaitingFor
  4392. }
  4393.  
  4394. function gameCanBeNextGame(g) {
  4395. var game = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 0, g, warlight_shared_viewmodels_SignIn.get_CurrentPlayer())
  4396.  
  4397. if(game != null && game.Game != null && game.UsOpt != null) {
  4398. var playing = (game.Game.State == 3 || game.Game.State == 5) && game.UsOpt.State == 2
  4399. var prio0 = game.Game.PrivateMessagesWaiting || game.Game.PublicChatWaiting || game.Game.TeamChatWaiting
  4400. var prio1 = game.Game.State == 2 && game.UsOpt.State == 1 //Waiting to join
  4401. var prio3 = playing && !game.UsOpt.HasCommittedOrders //Your turn 3 = turn, 5 = picking
  4402. var prio4 = game.Game.State == 2 && game.Game.WaitingForYouToStart //Waiting for you to start
  4403.  
  4404. return prio0 || prio1 || prio3 || prio4
  4405. } else {
  4406. return false;
  4407. }
  4408. }
  4409.  
  4410.  
  4411. function refreshOpenGames() {
  4412. deletedMD = deletedRT = 0;
  4413. openGamesTable.find("tbody").fadeTo('fast', 0.15);
  4414. var page = $('<div />').load('https://www.warzone.com/MultiPlayer/ ', function () {
  4415. var data = page.find('#AllOpenGamesData').html();
  4416. $('#AllOpenGamesData').html(data);
  4417. WL_MPDash.OpenGamesCtrl.AllOpenGamesData = data
  4418. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "openGamesFilters", function(filters) {
  4419. var openGamesFilters;
  4420. if(filters) {
  4421. openGamesFilters = filters.value;
  4422. }
  4423. var games;
  4424. if (openGamesFilters && openGamesFilters["disableAll"] != true) {
  4425. games = filterGames(wljs_Jsutil.GamesFromDump(data), openGamesFilters);
  4426. } else {
  4427. games = wljs_Jsutil.GamesFromDump(data);
  4428. }
  4429. $.each(games, function (key, game) {
  4430. if ($$$(game).playerJoined()) {
  4431. games[key] = $$$(game).markJoined();
  4432. }
  4433. });
  4434.  
  4435.  
  4436. wljs_AllOpenGames = WL_MPDash.OpenGamesCtrl.AllOpenGames = games;
  4437.  
  4438. var RealTimeLadderTable = page.find("#RealTimeLadderTable tbody tr:first-of-type").outerHTML();
  4439. $("#RealTimeLadderTable tbody tr:first-of-type")
  4440. $("#RealTimeLadderTable tbody tr:first-of-type").replaceWith(RealTimeLadderTable)
  4441.  
  4442. replaceAndFilterForumTable(page.find("#ForumTable").outerHTML());
  4443. $("#ClanForumTable").replaceWith(page.find("#ClanForumTable").outerHTML())
  4444. setupRightColumn()
  4445.  
  4446. updateOpenGamesCounter();
  4447.  
  4448. wljs_AllOpenGamesData = wljs_multiplayer_Ctrl_AllOpenGamesData = data;
  4449. var player = warlight_shared_viewmodels_SignIn.get_CurrentPlayer();
  4450. if (($(this.BothRadio)).is(":checked")) {
  4451. player.OpenGamePreference = 1;
  4452. } else if (($(this.MultiDayRadio)).is(":checked")) {
  4453. player.OpenGamePreference = 2;
  4454. } else if (($(this.RealTimeRadio)).is(":checked")) {
  4455. player.OpenGamePreference = 3;
  4456. }
  4457. wljs_Jsutil.Post("/MultiPlayer/", "ChangePace=" + player.OpenGamePreference, function (a) {});
  4458.  
  4459.  
  4460. var a = $("#OpenGamesTable").children("tbody");
  4461. a.children().remove();
  4462.  
  4463. var gamesToShow = warlight_shared_viewmodels_main_MultiPlayerDashboardVM.GamesToShow(wljs_AllOpenGames, player.OpenGamePreference, 0 == this.ShowingAllOpenGames)
  4464. var gamesToShow = warlight_shared_viewmodels_main_MultiPlayerDashboardVM.GamesToShow(wljs_AllOpenGames, player.OpenGamePreference, 0 == this.ShowingAllOpenGames)
  4465. for (var b = 0; b < gamesToShow.length;) {
  4466. var game = gamesToShow[b];
  4467. b++;
  4468. game.get_IsLottery() && warlight_shared_viewmodels_main_MultiPlayerDashboardVM.get_HideLotteryGames() ||
  4469. (game = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 2, game, warlight_shared_viewmodels_SignIn.get_CurrentPlayer()), a.append(warlight_shared_viewmodels_main_MultiPlayerDashboardVM.RenderGameHtml(warlight_shared_viewmodels_ConfigurationVM.Settings, game, null)))
  4470. }
  4471. openGamesTable.find("tbody").fadeTo('fast', 1, function () {
  4472. openGamesTable.css('overflow-y', 'scroll');
  4473. });
  4474. addOpenGamesSuffix();
  4475. domRefresh();
  4476. })
  4477. });
  4478. }
  4479. var refreshingPromotedGames = false;
  4480. function refreshPromotedGames() {
  4481. if(!refreshingPromotedGames) {
  4482. refreshingPromotedGames = true;
  4483. promotedGamesTable.find("tbody").fadeTo('fast', 0.15);
  4484. var page = $('<div />').load('https://www.warzone.com/MultiPlayer/ ', function () {
  4485. var data = page.find('#MorePromotedGamesData').html();
  4486. $('#MorePromotedGamesData').html(data);
  4487. wljs_PromotedGames = wljs_Jsutil.GamesFromDump(data);
  4488. refreshingPromotedGames = false;
  4489. var a = $("#PromotedGamesTable").children("tbody");
  4490. a.children().remove();
  4491. for (var b = 0; b < wljs_PromotedGames.length;) {
  4492. var game = wljs_PromotedGames[b];
  4493. b++;
  4494. (game = (new warlight_shared_viewmodels_main_MyGamesGameVM).Init(warlight_shared_viewmodels_ConfigurationVM.Settings, 2, game, warlight_shared_viewmodels_SignIn.get_CurrentPlayer()), a.append(warlight_shared_viewmodels_main_MultiPlayerDashboardVM.RenderGameHtml(warlight_shared_viewmodels_ConfigurationVM.Settings, game, null)))
  4495. }
  4496. domRefresh();
  4497. promotedGamesTable.find("tbody").fadeTo('fast', 1, function () {
  4498. promotedGamesTable.css('overflow-y', 'scroll');
  4499. });
  4500.  
  4501. });
  4502. } else {
  4503. log("refreshing promoted blocked")
  4504. }
  4505. }
  4506.  
  4507.  
  4508. /**
  4509. * Setups the refresh functionality
  4510. */
  4511. function setupRefreshFunction() {
  4512. lastRefresh = new Date();
  4513. $("a:contains('Refresh (F5)')").text("Refresh (R)")
  4514. var oldRefreshBtn = $("#RefreshBtn");
  4515. var oldRefreshBtn2 = $("#RefreshBtn2");
  4516. if (oldRefreshBtn.length) {
  4517. var newRefreshBtn = $("#refreshAll");
  4518. oldRefreshBtn.replaceWith(oldRefreshBtn.clone().removeAttr("id").attr("id", "refreshAll").attr("value", "Refresh (R)"));
  4519. newRefreshBtn.appendTo("body");
  4520. $("#refreshAll").on("click", function () {
  4521. if (new Date() - lastRefresh > 3000) {
  4522. lastRefresh = new Date();
  4523. log("Refresh by click")
  4524. refreshAllGames();
  4525. }
  4526. });
  4527. } else if (oldRefreshBtn2.length) {
  4528. var newRefreshBtn = $("#refreshAll");
  4529. oldRefreshBtn2.replaceWith(oldRefreshBtn2.clone().removeAttr("id").attr("id", "refreshAll").attr("value", "Refresh (R)"));
  4530. newRefreshBtn.appendTo("body");
  4531. $("#refreshAll").on("click", function () {
  4532. if (new Date() - lastRefresh > 3000) {
  4533. lastRefresh = new Date();
  4534. log("Refresh by click")
  4535. refreshAllGames();
  4536. }
  4537. });
  4538. }
  4539.  
  4540. $(".MainColumn").prepend($('#refreshAll'))
  4541.  
  4542. ifSettingIsEnabled('autoRefreshOnFocus', function() {
  4543. $(window).on('focus', function () {
  4544. if (new Date() - lastRefresh > 30000) {
  4545. lastRefresh = new Date();
  4546. log("Refresh by focus")
  4547. refreshAllGames();
  4548. }
  4549. });
  4550. })
  4551.  
  4552. $("body").keyup(function (event) {
  4553. // "R" is pressed
  4554. if (event.which == 82) {
  4555. if (new Date() - lastRefresh > 3000) {
  4556. lastRefresh = new Date();
  4557. log("Refresh by key r")
  4558. refreshAllGames();
  4559. }
  4560. }
  4561. });
  4562. }
  4563.  
  4564.  
  4565. function getDate(text) {
  4566. var date;
  4567.  
  4568. if (text.match(/[0-9]+ second/)) {
  4569. date = new Date() - 1000;
  4570.  
  4571. } else if (text.match(/[0-9]+ seconds/)) {
  4572. date = new Date() - text.match(/[0-9]+/) * 1000;
  4573.  
  4574. } else if (text.match(/[0-9]+ minute/)) {
  4575. date = new Date() - text.match(/[0-9]+/) * 1000 * 60;
  4576.  
  4577. } else if (text.match(/[0-9]+ minutes/)) {
  4578. date = new Date() - text.match(/[0-9]+/) * 1000 * 60;
  4579.  
  4580. } else if (text.match(/[0-9]+ hour/)) {
  4581. date = new Date() - text.match(/[0-9]+/) * 1000 * 60 * 59;
  4582.  
  4583. } else if (text.match(/[0-9]+ hours/)) {
  4584. date = new Date() - text.match(/[0-9]+/) * 1000 * 60 * 60;
  4585.  
  4586. } else if (text.match(/[0-9]+ day/)) {
  4587. date = new Date() - text.match(/[0-9]+/) * 1000 * 60 * 60 * 36;
  4588.  
  4589. } else if (text.match(/[0-9]+ days/)) {
  4590. date = new Date() - text.match(/[0-9]+/) * 1000 * 60 * 60 * 24;
  4591.  
  4592. } else if (text.match(/[0-9]+[\/][0-9]+[\/][0-9]+/)) {
  4593. var split = text.split('/');
  4594. date = new Date(split[2], split[0] - 1, split[1]);
  4595. date.setHours(0, 0, 0, 0);
  4596. }
  4597. return date;
  4598. }
  4599. /**
  4600. * Refreshes Width & Height of Columns
  4601. */
  4602. function refreshSingleColumnSize() {
  4603. var showSide = $(".showSide");
  4604. var showGames = $(".showGames");
  4605. showSide.scrollTop(0);
  4606. var width = $("#ForumTable").width();
  4607. createSelector(".followMeBar", "width:" + width + "px;");
  4608. createSelector(".followMeBar:not(.fixed)", "width:100%");
  4609. /**
  4610. * Sticky Titles
  4611. */
  4612. $(".followMeBar").each(function () {
  4613. $(this).removeClass("fixed");
  4614. if ($(this).parent().hasClass("followWrap")) {
  4615. $(this).unwrap();
  4616. }
  4617. var thisSticky = $(this).wrap('<div class="followWrap" />');
  4618. thisSticky.parent().height(thisSticky.outerHeight());
  4619. var pos = parseInt(thisSticky.offset().top) - parseInt(showSide.offset().top);
  4620. $.data(thisSticky[0], 'pos', pos);
  4621. });
  4622.  
  4623.  
  4624. var vacationHeight = $(".vacation").height() ? $(".vacation").height() + 15 : 0;
  4625. var columnHeight = window.innerHeight - 150 - vacationHeight;
  4626. showGames.find("table").css({
  4627. height: columnHeight
  4628. });
  4629.  
  4630. //var height = showGames.find("table thead tr").height() + 30;
  4631. var height = 58;
  4632. createSelector(".showGames table tbody tr:first-of-type td", "padding-top:" + height + "px");
  4633.  
  4634.  
  4635. showSide.css({
  4636. height: columnHeight
  4637. });
  4638. showGames.find("table tbody tr:first-of-type td").css("padding-top", height);
  4639. $(".showGames thead tr").width($(".showGames thead tr").closest("table").width()-30)
  4640. $(".showGames thead tr td div").unwrap();
  4641. }
  4642.  
  4643. function refreshPastGames() {
  4644. if($("#pastGamesContainer").length) {
  4645. var div = $("<div>")
  4646. div.load("/MultiPlayer/PastGames #MyGamesTable", function(data) {
  4647. div.find("#MyGamesTable").attr("id", "PastGamesTable")
  4648. div.find("#PastGamesTable thead tr td").html('<h2 style="margin: 0px">Past Games</h2>')
  4649. div.find("#PastGamesTable thead tr td").css("border", "none")
  4650. $("#pastGamesContainer").html("")
  4651. $("#pastGamesContainer").append(div)
  4652. refreshSingleColumnSize()
  4653. });
  4654. }
  4655. }
  4656. window.showGamesActive = "ShowMyGames";
  4657. window.openGames = [];
  4658.  
  4659. function setupBasicDashboardStyles() {
  4660. createSelector(".GameRow a", "font-size:16px !important;");
  4661. createSelector(".GameRow", "font-size:15px");
  4662. createSelector("a", "outline: none");
  4663. createSelector('#PromotedGamesTable td:last-of-type a img', 'display:none');
  4664. createSelector("#MyGamesTable td > a > img", 'display:none');
  4665. createSelector(".GameRow td:last-of-type span,#OpenGamesTable .GameRow td:last-of-type span:first-child, #PromotedGamesTable .GameRow td:last-of-type span:first-child", "margin:5px 0px;position:relative !important;z-index:10;");
  4666. createSelector("#MyGamesTable td span a img, #MyGamesTable td span a img", "display:inherit;");
  4667. createSelector(".GameRow:hover", "background-color:rgb(50, 50, 50);cursor:pointer;");
  4668. createSelector(".GameRow a:hover", "text-decoration:none;");
  4669. createSelector(".TournamentRow a:hover", "text-decoration:none;");
  4670. createSelector(".TournamentRow:hover", "background-color:rgb(50, 50, 50);cursor:pointer;");
  4671. createSelector(".ui-buttonset label", "font-size:11px;");
  4672. createSelector("#OpenGamesTable label:hover", " border: 1px solid #59b4d4;background: #0078a3 50% 50% repeat-x;font-weight: bold;color: #ffffff;");
  4673. createSelector("#OpenGamesTable td:last-child,#MyGamesTable td:last-child, #PromotedGamesTable td:last-child", "position: relative;");
  4674. createSelector("#OpenGamesTable td:nth-child(2) > a,#MyGamesTable td:nth-child(2) > a, #PromotedGamesTable td:nth-child(2) > a", " display: block;width: 100%;height: 100%;float: left;position: absolute;margin-top: -5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;");
  4675. createSelector(".loading", "position: absolute;height: 100%;width: 100%;background-color: rgba(255, 255, 255, 0.2);text-align: center;z-index: 12;margin-top: 34px;display:none;");
  4676. createSelector(".loading img", "position: absolute;top: 50%;left: 50%;margin-left: -16px;margin-top: -16px;");
  4677. createSelector("img", "position: relative;z-index:50;");
  4678. createSelector("input", "z-index: 98;position: relative;");
  4679. createSelector(".showGames thead tr", "background: #1d0f04 none repeat scroll 0% 0%;z-index: 98;position: fixed;padding: 5px;border-bottom: 1px solid rgb(68, 68, 68);border-top-left-radius: 8px;letter-spacing: 1px;");
  4680. createSelector(".showGames table tbody", "display:table;width:100%;");
  4681. createSelector(".showGames table thead", "position:inherit;");
  4682. createSelector(".ui-tooltip", "background: #EBEBEB;padding: 4px;font-style: italic;");
  4683. addCSS(`
  4684. .MyGamesGameBoxOpenSeat {
  4685. font-size:11px;
  4686. }
  4687. `)
  4688. $.each($(".TournamentRow td"), function () {
  4689. $(this).find("font:first-of-type").appendTo($(this).find("a")).css("font-size", "10px");
  4690. });
  4691. createSelector("#refreshAll", "margin-top: -50px;");
  4692. }
  4693.  
  4694. function setupFixedWindowStyles() {
  4695. createSelector('html', 'width: 100%; position:fixed')
  4696. createSelector(".followMeBar", "background: rgb(29, 15, 4);padding: 5px 0px;position: relative;z-index: 1;color: #fff;border: 1px solid gray;border-bottom:none");
  4697. // var top = parseInt($(".showSide").offset().top) + parseInt(43);
  4698. createSelector(".followMeBar.fixed", "position: fixed;top: " + top + "px;z-index: 0;z-index:98;");
  4699. createSelector(".followMeBar.fixed.absolute", "position: absolute;");
  4700. createSelector(".showSide thead", "display:none");
  4701. createSelector(".showGames table", "display:block !important");
  4702. createSelector("#switchGameRadio label:hover", "border: 1px solid rgb(89, 180, 212);border-image-source: initial;border-image-slice: initial;border-image-width: initial;border-image-outset: initial;border-image-repeat: initial;background:rgb(0, 120, 163);font-weight: bold;color: rgb(255, 255, 255);");
  4703. createSelector("#MyGamesTable, #PromotedGamesTable, #OpenGamesTable", "display:none");
  4704. createSelector("#MainSiteContent > table > tbody > tr > td", "width:100%");
  4705. createSelector(".MainColumn", "width: calc(60% - 20px)!important;max-width: 800px;min-width:1px");
  4706. createSelector(".SideColumn", "float:left !important");
  4707. createSelector("h2 + span", "margin-right: 50px;");
  4708. createSelector("body", "overflow:hidden");
  4709. createSelector(".SideColumn", "width: 100% !important;");
  4710. createSelector("#MyGamesFilter", "width:200px");
  4711. createSelector(".showGames table", "display:block; overflow-y:scroll; overflow-x:hidden; border:1px gray solid;");
  4712. createSelector(".adsbygoogle", "margin-top: 25px;");
  4713. createSelector(".showSide", "overflow-y:scroll;float: left;margin-top: 43px;padding-right: 6px;width:39%; min-width:1px;max-width:615px;margin-left: 20px;");
  4714. createSelector("#refreshAll", "width: 140px;float: right;");
  4715. createSelector("#fakeOpenGameMenu label", "margin-right:2px");
  4716. createSelector("#RestoreLotteryGamesBtn", "display:none");
  4717. createSelector('#ForumTable tbody tr td, #ClanForumTable tbody tr td', 'overflow:hidden;position:relative');
  4718. createSelector('#ForumTable tbody tr td > a, #ClanForumTable tbody tr td > a', 'width: 100%;display: block;height: 100%;float: left;position: absolute;overflow: hidden;z-index: 1;');
  4719. createSelector('#ForumTable tbody tr td span, #ClanForumTable tbody tr td span', 'display: inline-block;z-index: 1;float: left;position: relative;');
  4720. createSelector('#ForumTable tbody tr:not(:last-child):hover, #ClanForumTable tbody tr:hover', 'background-color:rgb(50, 50, 50)');
  4721. createSelector('#ForumTable tbody tr td a[href="/Forum/Forum"]', 'position: relative;');
  4722. createSelector('#ClanForumTable tbody tr td a[href="/Clans/Forum"]', 'position: relative;');
  4723. $("body").scrollTop(0)
  4724. addCSS(`
  4725. @media (max-width: 1400px) {
  4726. .showSide {
  4727. //min-width: 380px;
  4728. //width: 40%;
  4729. }
  4730. h2 + span {
  4731. margin-right: 10px!important;
  4732. }
  4733. }
  4734.  
  4735. @media (max-width: 1300px) {
  4736. #MyGamesTable > thead > tr * {
  4737. font-size: 14px;
  4738. }
  4739. #MyGamesTable > thead > tr > div:nth-of-type(1) {
  4740. margin-top: 5px!important;
  4741. display: block;
  4742. float: left;
  4743. padding-right: 5px;
  4744. }
  4745. #MyGamesTable select {
  4746. width: 110px;
  4747. }
  4748.  
  4749. }
  4750.  
  4751. @media (max-width: 1205px) {
  4752. .MainColumn {
  4753. width: 60% ;
  4754. min-width: 0;
  4755. }
  4756. #MyGamesTable select {
  4757. width: 75px;
  4758. }
  4759.  
  4760. }
  4761.  
  4762. @media (max-width: 1100px) {
  4763. #refreshAll {
  4764. width: 85px!important;
  4765. }
  4766. #MyGamesTable > thead > tr > div:nth-of-type(1) {
  4767. display: none;
  4768. }
  4769. }
  4770.  
  4771. @media (max-width: 1100px) {
  4772. .MainColumn {
  4773. float: left;
  4774. }
  4775. }
  4776. @media (max-width: 1000px) {
  4777. .showSide {
  4778. min-width:0px;
  4779. }
  4780. }
  4781. `);
  4782. }
  4783.  
  4784. function setupFixedTitlesInSideColumn() {
  4785. var blogTable = $("#BlogTable");
  4786. var realTimeLadderTable = $("#RealTimeLadderTable");
  4787. var forumTable = $("#ForumTable");
  4788. var clanForumTable = $("#ClanForumTable");
  4789. var mapOfTheWeekTable = $("#MapOfTheWeekTable");
  4790. var leaderboardTable = $("#LeaderboardTable");
  4791. var myTournamentsTable = $("#MyTournamentsTable");
  4792. var bookmarkTable = $("#BookmarkTable");
  4793. var shopTable = $("#ShopTable")
  4794. blogTable.before("<div class='followMeBar'>" + blogTable.find("thead > tr > td").html() + "</div>");
  4795. realTimeLadderTable.before("<div class='followMeBar'>" + realTimeLadderTable.find("thead > tr > td").html() + "</div>");
  4796. forumTable.before("<div class='followMeBar'>" + forumTable.find("thead > tr > td").html() + "</div>");
  4797. clanForumTable.before("<div class='followMeBar'>" + clanForumTable.find("thead > tr > td").html() + "</div>");
  4798. mapOfTheWeekTable.before("<div class='followMeBar'>" + mapOfTheWeekTable.find("thead > tr > td").html() + "</div>");
  4799. ifSettingIsEnabled("hideCoinsGlobally", function () {}, function () {
  4800. leaderboardTable.before("<div class='followMeBar'>" + leaderboardTable.find("thead > tr > td").html() + "</div>");
  4801. }, function () {
  4802. myTournamentsTable.before("<div class='followMeBar'>" + myTournamentsTable.find("thead > tr > td").html() + "</div>");
  4803. bookmarkTable.before("<div class='followMeBar'>" + bookmarkTable.find("thead > tr > td").html() + "</div>");
  4804. shopTable.before("<div class='followMeBar'>" + shopTable.find("thead > tr > td").html() + "</div>");
  4805. new StickyTitles(jQuery(".followMeBar")).load();
  4806. })
  4807. }
  4808.  
  4809. function setupFixedWindowWithScrollableGames() {
  4810. var gameButtons = '<div style="margin: 5px;" id="switchGameRadio" class="btn-group">';
  4811. gameButtons += '<label for="ShowMyGames" class="active btn btn-primary" role="button"><input type="radio" id="ShowMyGames" name="switchGames" checked="checked" class="ui-helper-hidden-accessible">';
  4812. gameButtons += 'My Games</label>';
  4813. ifOneOrMoreIsEnabled(["hidePromotedGames", "hideCoinsGlobally"], function () {
  4814. gameButtons += `
  4815. <label for="ShowOpenGames" class="btn btn-primary" role="button">
  4816. <input type="radio" id="ShowOpenGames" name="switchGames" class="ui-helper-hidden-accessible">Open Games
  4817. </label>
  4818. <label for="ShowPastGames" class="btn btn-primary" role="button">
  4819. <input type="radio" id="ShowPastGames" name="switchGames" class="ui-helper-hidden-accessible">Past Games
  4820. </label>
  4821. </div>
  4822. `
  4823. setupMainColumn(gameButtons)
  4824. }, function () {
  4825. gameButtons += `
  4826. <label for="ShowOpenGames" class="btn btn-primary" role="button">
  4827. <input type="radio" id="ShowOpenGames" name="switchGames" class="ui-helper-hidden-accessible">Open Games
  4828. </label>
  4829. <label for="ShowCoinGames" class="btn btn-primary" role="button">
  4830. <input type="radio" id="ShowCoinGames" name="switchGames" class="ui-helper-hidden-accessible">Coin Games
  4831. </label>
  4832. <label for="ShowPastGames" class="btn btn-primary" role="button">
  4833. <input type="radio" id="ShowPastGames" name="switchGames" class="ui-helper-hidden-accessible">Past Games
  4834. </label>
  4835. </div>
  4836. `
  4837. setupMainColumn(gameButtons)
  4838. })
  4839. addCSS(`
  4840. table#MyGamesTable > tbody tr:last-of-type td {
  4841. padding-bottom: 10px;
  4842. }
  4843. .btn-group .btn {
  4844. font-size: 13px;
  4845. }`)
  4846. }
  4847.  
  4848. function setupMainColumn(gameButtons) {
  4849. var mainColumn = $(".MainColumn ");
  4850. mainColumn.prepend('<div class="showGamesContainer">' + gameButtons + '<div class="showGames"></div></div>');
  4851. mainColumn.prepend($('#refreshAll').detach())
  4852. myGamesTable.appendTo(".showGames");
  4853. mainColumn.after('<div class="showSide"></div>');
  4854. $(".SideColumn").appendTo(".showSide");
  4855. setupFixedWindowStyles();
  4856. refreshSingleColumnSize();
  4857. $("#switchGameRadio").find("label").on("click", function () {
  4858. var newShowGames = $(this).attr("for");
  4859. if (newShowGames != showGamesActive) {
  4860. $.each($("#switchGameRadio").find("label"), function () {
  4861. $(this).removeClass("active");
  4862. });
  4863. $(this).addClass("active");
  4864. if (newShowGames == "ShowMyGames") {
  4865. showGamesActive = newShowGames;
  4866. promotedGamesTable.appendTo("body");
  4867. openGamesTable.appendTo("body");
  4868. myGamesTable.appendTo(".showGames");
  4869. $("#pastGamesContainer").appendTo("body")
  4870. }
  4871. else if (newShowGames == "ShowCoinGames") {
  4872. showGamesActive = newShowGames;
  4873. myGamesTable.appendTo("body");
  4874. openGamesTable.appendTo("body");
  4875. promotedGamesTable.appendTo(".showGames");
  4876. $("#pastGamesContainer").appendTo("body")
  4877. }
  4878. else if (newShowGames == "ShowOpenGames") {
  4879. showGamesActive = newShowGames;
  4880. myGamesTable.appendTo("body");
  4881. promotedGamesTable.appendTo("body");
  4882. openGamesTable.appendTo(".showGames");
  4883. $("#pastGamesContainer").appendTo("body")
  4884. }
  4885. else if (newShowGames == "ShowPastGames") {
  4886. showGamesActive = newShowGames;
  4887. myGamesTable.appendTo("body");
  4888. promotedGamesTable.appendTo("body");
  4889. openGamesTable.appendTo("body");
  4890. if ($("#pastGamesContainer").length) {
  4891. $("#pastGamesContainer").appendTo(".showGames")
  4892. }
  4893. else {
  4894. $(".showGames").append("<div id='pastGamesContainer'></div>");
  4895. var div = $("<div>")
  4896. div.load("/MultiPlayer/PastGames #MyGamesTable", function (data) {
  4897. div.find("#MyGamesTable").attr("id", "PastGamesTable")
  4898. div.find("#PastGamesTable thead tr td").html('<h2 style="margin: 0px">Past Games</h2>')
  4899. div.find("#PastGamesTable thead tr td").css("border", "none")
  4900. $("#pastGamesContainer").append(div)
  4901. refreshSingleColumnSize()
  4902. });
  4903. }
  4904. }
  4905. refreshSingleColumnSize()
  4906. }
  4907. });
  4908. }
  4909.  
  4910. function hideRightColumn() {
  4911. ifSettingIsEnabled('scrollGames', function () {
  4912. $(".showSide").css("display", "none");
  4913. createSelector(".MainColumn", "margin: auto;max-width: 800px;width: 60%!important;float: none !important;min-width: 600px !important;");
  4914. $('.MainColumn').closest('table').css("width", "100%");
  4915. }, function () {
  4916. $(".SideColumn").css("display", "none");
  4917. $(".MainColumn").css("width", "100%");
  4918. $(".MainColumn").css("max-width", "800px");
  4919. })
  4920. }
  4921.  
  4922. function registerGameTabClick() {
  4923. if (lastClick - new Date() > 2000) {
  4924. openGamesTable.scrollTop(0);
  4925. lastClick = new Date();
  4926. }
  4927. window.setTimeout(function () {
  4928. domRefresh();
  4929. addOpenGamesSuffix();
  4930. }, 1);
  4931. }
  4932.  
  4933. function updateOpenGamesCounter() {
  4934. var numMD = countGames(wljs_AllOpenGames, 1);
  4935. var numRT = countGames(wljs_AllOpenGames, 2);
  4936. var numBoth = parseInt(numMD) + parseInt(numRT)
  4937. //Both
  4938. $("#OpenGamesTable [for='BothRadio'] span").text('Both (' + numBoth + ')')
  4939. //Real
  4940. $("#OpenGamesTable [for='RealTimeRadio'] span").text('Real-Time (' + numRT + ')')
  4941. //Multi-Day
  4942. $("#OpenGamesTable [for='MultiDayRadio'] span").text('Multi-Day (' + numMD + ')')
  4943. }
  4944. // Type 1 : Multiday
  4945. // Type 2 : Realtime
  4946. function countGames(games, type) {
  4947. games = system_linq_Enumerable.Where(games, function (a) {
  4948. if (type == 1) return !a.RealTimeGame;
  4949. if (type == 2) return a.RealTimeGame;
  4950. });
  4951. return system_linq_Enumerable.ToArray(games).length
  4952. }
  4953.  
  4954. function StickyTitles(stickies) {
  4955. var thisObj = this;
  4956. thisObj.load = function () {
  4957. stickies.each(function () {
  4958. var thisSticky = $(this).wrap('<div class="followWrap" />');
  4959. thisSticky.parent().height(thisSticky.outerHeight());
  4960. var pos = parseInt(thisSticky.offset().top, 10) - parseInt($(".showSide").offset().top, 10);
  4961. $.data(thisSticky[0], 'pos', pos);
  4962. });
  4963. $(".showSide").off("scroll.stickies").on("scroll.stickies", function () {
  4964. thisObj.scroll();
  4965. });
  4966. };
  4967. thisObj.scroll = function () {
  4968. stickies.each(function (i) {
  4969. var thisSticky = $(this),
  4970. nextSticky = stickies.eq(i + 1),
  4971. prevSticky = stickies.eq(i - 1),
  4972. pos = $.data(thisSticky[0], 'pos');
  4973. var showSide = $(".showSide");
  4974. if (pos <= showSide.scrollTop()) {
  4975. thisSticky.addClass("fixed");
  4976. if (nextSticky.length > 0 && thisSticky.offset().top >= $.data(nextSticky[0], 'pos') - thisSticky.outerHeight()) {
  4977. thisSticky.addClass("absolute").css("top", jQuery.data(nextSticky[0], 'pos') - thisSticky.outerHeight());
  4978. }
  4979. }
  4980. else {
  4981. thisSticky.removeClass("fixed");
  4982. if (prevSticky.length > 0 && showSide.scrollTop() <= $.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
  4983. prevSticky.removeClass("absolute").removeAttr("style");
  4984. }
  4985. }
  4986. });
  4987. }
  4988. }
  4989.  
  4990. function bindCustomContextMenu() {
  4991. // If the document is clicked somewhere
  4992. $(document).bind("mousedown", function (e) {
  4993. // If the clicked element is not the menu
  4994. if (!$(e.target).parents(".context-menu").length > 0) {
  4995. // Hide it
  4996. $(".context-menu").hide(100);
  4997. $(".highlightedBookmark").removeClass("highlightedBookmark")
  4998. }
  4999. });
  5000. // If the menu element is clicked
  5001. $(".context-menu li").click(function () {
  5002. // This is the triggered action name
  5003. switch ($(this).attr("data-action")) {
  5004. // A case for each action. Your actions here
  5005. case "first":
  5006. alert("first");
  5007. break;
  5008. case "second":
  5009. alert("second");
  5010. break;
  5011. case "third":
  5012. alert("third");
  5013. break;
  5014. }
  5015. // Hide it AFTER the action was triggered
  5016. $(".context-menu").hide(100);
  5017. });
  5018. }
  5019.  
  5020. function setupRightColumn(isInit) {
  5021. if (isInit) {
  5022. createSelector(".SideColumn > table", "margin-bottom: 17px;")
  5023. }
  5024. //Bookmarks
  5025. if (isInit) {
  5026. setupBookmarkTable()
  5027. }
  5028. else {
  5029. refreshBookmarks()
  5030. }
  5031. setupRealTimeLadderTable()
  5032. sortRightColumnTables(function () {
  5033. if (isInit) {
  5034. ifSettingIsEnabled('scrollGames', function () {
  5035. setupFixedTitlesInSideColumn();
  5036. })
  5037. }
  5038. })
  5039. }
  5040.  
  5041. function setupVacationAlert() {
  5042. var vacationEnd = warlight_shared_viewmodels_SignIn.get_CurrentPlayer().OnVacationUntil;
  5043. if (vacationEnd.date > new Date()) {
  5044. $(".MainColumn").before("<div class='vacation'></div>");
  5045. $(".vacation").html('<div class="alert alert-warning">You are on vacation until <strong class="vacationUntil"></strong></div>');
  5046. $(".vacationUntil").text(vacationEnd);
  5047. }
  5048. addCSS(`
  5049. .vacation {
  5050. width: 100%;
  5051. }
  5052. .vacation .alert-warning {
  5053. border: none;
  5054. background: rgba(255,200,180,0.1);
  5055. }
  5056. `)
  5057. }
  5058.  
  5059. function sortRightColumnTables(callback) {
  5060. var sideColumn = $(".SideColumn")
  5061. getSortTables(function (tables) {
  5062. $.each(tables, function (key, table) {
  5063. if (table.hidden == true) {
  5064. hideTable(table.id)
  5065. }
  5066. else {
  5067. var table = $(table.id)
  5068. if (table.prev().hasClass("followWrap")) {
  5069. var wrap = table.prev().remove()
  5070. sideColumn.append(wrap)
  5071. }
  5072. table = table.detach()
  5073. sideColumn.append(table)
  5074. }
  5075. })
  5076. $(".SideColumn > br").remove()
  5077. callback();
  5078. })
  5079. }
  5080. function checkVersion() {
  5081. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "version", function(v) {
  5082. var currentVersion = v != undefined ? v.value: undefined
  5083. log("Current version " + currentVersion)
  5084. if (currentVersion == version) {
  5085. //Script Up to date
  5086.  
  5087. } else if (currentVersion == undefined) {
  5088. //Script new installed
  5089. addDefaultBookmark();
  5090. setupSettingsDatabase();
  5091. } else {
  5092. setUserInvalid()
  5093. //Script Updated
  5094.  
  5095. // $("label[for='showPrivateNotesOnProfile']").addClass('newSetting');
  5096.  
  5097. // showPopup(".userscript-show");
  5098.  
  5099. // window.setTimeout(function() {
  5100. // CreateModal("Alert", "", "Tidy up Your Dashboard was sucessfully updated to version " + version + "! Check out the forum thread to see what changed.", false)
  5101. // }, 2000)
  5102. //
  5103. Database.delete(Database.Table.Settings, "tableSort", function() {
  5104. location.reload();
  5105. });
  5106. }
  5107.  
  5108. addVersionLabel()
  5109. if(sessionStorage.getItem("showUserscriptMenu")) {
  5110. $('#userscriptMenu').modal('show');
  5111. sessionStorage.removeItem("showUserscriptMenu")
  5112. }
  5113. })
  5114. Database.update(Database.Table.Settings, {name: "version", value: version}, undefined, function() {
  5115. })
  5116. }
  5117.  
  5118. function addVersionLabel() {
  5119. if(!pageIsGame() && !pageIsExamineMap() && !pageIsDesignMap()) {
  5120. $("body").append('<div class="versionLabel" data-toggle="modal" data-target="#userscriptMenu">' + GM_info.script.version +'</div>')
  5121. createSelector(".versionLabel", "position:fixed; right:0; bottom: 0; padding: 5px; color: bisque; font-size: 10px; cursor:pointer")
  5122. }
  5123. }
  5124. window.filters = [
  5125. {
  5126. id: "disableAll",
  5127. text: "Disable All Filters",
  5128. selected: false,
  5129. type: "checkbox"
  5130. },
  5131. {
  5132. id: "",
  5133. text: "<div style='display:inline-block;height:30px; width: 10px'> </div>",
  5134. selected: false,
  5135. type: "custom"
  5136. },
  5137. {
  5138. id: "hideTeam",
  5139. text: "Hide Team Games",
  5140. selected: false,
  5141. type: "checkbox"
  5142. },
  5143. {
  5144. id: "hideCommanderGames",
  5145. text: "Hide Games with Commanders",
  5146. selected: false,
  5147. type: "checkbox"
  5148. },
  5149. {
  5150. id: "hideFFA",
  5151. text: "Hide FFA Games",
  5152. selected: false,
  5153. type: "checkbox"
  5154. },
  5155. {
  5156. id: "hideNoneCommanderGames",
  5157. text: "Hide Games without Commanders",
  5158. selected: false,
  5159. type: "checkbox"
  5160. },
  5161. {
  5162. id: "hide1v1",
  5163. text: "Hide 1 v 1 Games",
  5164. selected: false,
  5165. type: "checkbox"
  5166. },
  5167. {
  5168. id: "hideManualDistribution",
  5169. text: "Hide Manual Distribution Games",
  5170. selected: false,
  5171. type: "checkbox"
  5172. },
  5173. {
  5174. id: "hideNoSplit",
  5175. text: "Hide No-Split Games",
  5176. selected: false,
  5177. type: "checkbox"
  5178. },
  5179. {
  5180. id: "hideAutoDistribution",
  5181. text: "Hide Auto Distribution Games",
  5182. selected: false,
  5183. type: "checkbox"
  5184. },
  5185. {
  5186. id: "hideLocalDeployments",
  5187. text: "Hide Local Deployment Games",
  5188. selected: false,
  5189. type: "checkbox"
  5190. },
  5191. {
  5192. id: "hideCustomScenario",
  5193. text: "Hide Custom Scenario Games",
  5194. selected: false,
  5195. type: "checkbox"
  5196. },
  5197. {
  5198. id: "hideLuck",
  5199. text: "<label for='hideLuck' style='width:169px'>Hide Luck greater than</label><input type='text' id='hideLuck' class='number'>",
  5200. selected: false,
  5201. type: "custom"
  5202. },
  5203. {
  5204. id: "hideNonCustomScenario",
  5205. text: "Hide Non-Custom Scenario Games",
  5206. selected: false,
  5207. type: "checkbox"
  5208. },
  5209. {
  5210. id: "hideKeyword",
  5211. text: '<label for="hideKeyword" style="width:115px">Hide Keywords<img src="' + IMAGES.QUESTION + '" class="help-icon" onclick="showFilterHelp(\'You can separate multiple Keywords with a comma. Each keyword must have 3 or more letters. The Keyword-Filter searches for case insensitive matches in the complete game title.<br>Example: The keyword ´Rop´ removes the game ´Europe 3v3´\', this)"></label><br><input type="text" id="hideKeyword" style="width: 95%;margin-left: 6px;"><hr>',
  5212. selected: false,
  5213. type: "custom",
  5214. },
  5215. {
  5216. id: "hidePractice",
  5217. text: "Hide Practice Games",
  5218. selected: false,
  5219. type: "checkbox"
  5220. },
  5221. {
  5222. id: "hideNonPractice",
  5223. text: "Hide Non-Practice Games",
  5224. selected: false,
  5225. type: "checkbox"
  5226. },
  5227. {
  5228. id: "limitPlayers",
  5229. text: '<label>Limit Amount of Players</label><br><div class="filter-small"><label for="hideMinPlayers" style="width:25px">Min </label><input class="number" type="text" id="hideMinPlayers">Players<br><label for="hideMaxPlayers" style="width:25px">Max </label><input class="number" type="text" id="hideMaxPlayers">Players</div>',
  5230. selected: false,
  5231. type: "custom"
  5232. },
  5233. {
  5234. id: "hideBootTime",
  5235. text: '<label>Hide Boot Time lower than</label><br><div class="filter-small"><label for="hideRealTimeBootTime" style="width:100px">Realtime: </label><input class="number" type="text" id="hideRealTimeBootTime">minute(s)<br><label for="hideMinPlayers" style="width:100px">Multiday: </label><input class="number" type="text" id="hideMultiDayBootTimeDays"> day(s) and <input class="number" type="text" id="hideMultiDayBootTimeHours"> hour(s)</div>',
  5236. selected: false,
  5237. type: "custom"
  5238. }
  5239. ];
  5240. window.deletedRT = 0;
  5241. window.deletedMD = 0;
  5242.  
  5243. function filterGames(games, openGamesFilters) {
  5244. var filteredGames = [];
  5245. var deletedGames = [];
  5246. $.each(games, function (key, game) {
  5247. if (!$$$(game).getsFiltered(openGamesFilters)) {
  5248. filteredGames.push(game);
  5249. }
  5250. else {
  5251. if (game.RealTimeGame) {
  5252. deletedRT++;
  5253. }
  5254. else {
  5255. deletedMD++;
  5256. }
  5257. }
  5258. });
  5259. return filteredGames;
  5260. }
  5261.  
  5262. function storeFilterVariables() {
  5263. openGamesFilters = {};
  5264. $.each(window.filters, function (key, filter) {
  5265. if (filter.type == "checkbox") {
  5266. openGamesFilters[filter.id] = $("#" + filter.id).prop("checked");
  5267. }
  5268. });
  5269. openGamesFilters["hideKeyword"] = $("#hideKeyword").val()
  5270. openGamesFilters["hideRealTimeBootTime"] = $("#hideRealTimeBootTime").val()
  5271. openGamesFilters["hideMultiDayBootTimeDays"] = $("#hideMultiDayBootTimeDays").val()
  5272. openGamesFilters["hideMultiDayBootTimeHours"] = $("#hideMultiDayBootTimeHours").val()
  5273. var luck = $("#hideLuck").val();
  5274. openGamesFilters["hideLuck"] = ($.isNumeric(luck) && luck <= 100 && luck >= 0) ? luck : 100;
  5275. var minPlayers = $("#hideMinPlayers").val();
  5276. openGamesFilters["hideMinPlayers"] = ($.isNumeric(minPlayers) && minPlayers <= 100 && minPlayers >= 2) ? minPlayers : 2;
  5277. var maxPlayers = $("#hideMaxPlayers").val();
  5278. openGamesFilters["hideMaxPlayers"] = ($.isNumeric(maxPlayers) && maxPlayers <= 100 && maxPlayers >= 2) ? maxPlayers : 100;
  5279. if (parseFloat(openGamesFilters["hideMinPlayers"]) > parseFloat(openGamesFilters["hideMaxPlayers"])) {
  5280. openGamesFilters["hideMaxPlayers"] = openGamesFilters["hideMinPlayers"]
  5281. }
  5282. var rtBoot = $("#hideRealTimeBootTime").val();
  5283. openGamesFilters["hideRealTimeBootTime"] = $.isNumeric(rtBoot) ? rtBoot * 60 * 1000 : 0;
  5284. var mdBoot = calculateMDBoot($("#hideMultiDayBootTimeHours").val(), $("#hideMultiDayBootTimeDays").val());
  5285. openGamesFilters["hideMultiDayBootTimeDays"] = mdBoot.days;
  5286. openGamesFilters["hideMultiDayBootTimeHours"] = mdBoot.hours;
  5287. openGamesFilters["hideMultiDayBootTimeInMs"] = (parseInt(mdBoot.days) * 24 + parseInt(mdBoot.hours)) * 60 * 60 * 1000;
  5288. var gameFilters = {
  5289. name: "openGamesFilters",
  5290. value: openGamesFilters
  5291. }
  5292. Database.update(Database.Table.Settings, gameFilters, undefined, function () {
  5293. updateFilterSettings()
  5294. })
  5295. }
  5296.  
  5297. function calculateMDBoot(hours, days) {
  5298. hours = $.isNumeric(hours) ? hours : 0;
  5299. days = $.isNumeric(days) ? days : 0;
  5300. if (hours >= 24) {
  5301. days = parseFloat(days) + parseInt(hours / 24);
  5302. hours -= parseInt(hours / 24) * 24
  5303. }
  5304. return {
  5305. hours: hours,
  5306. days: days
  5307. }
  5308. }
  5309.  
  5310. function updateFilterSettings() {
  5311. Database.readIndex(Database.Table.Settings, Database.Row.Settings.Name, "openGamesFilters", function (gameFilters) {
  5312. if (!gameFilters || !gameFilters.value) {
  5313. return;
  5314. }
  5315. var openGamesFilters = gameFilters.value;
  5316. $.each(window.filters, function (key, filter) {
  5317. if (filter.type == "checkbox") {
  5318. $("#" + filter.id).prop("checked", openGamesFilters[filter.id]);
  5319. }
  5320. });
  5321. $("#hideLuck").val(openGamesFilters["hideLuck"] || 100);
  5322. $("#hideMinPlayers").val(openGamesFilters["hideMinPlayers"] || 0);
  5323. $("#hideMaxPlayers").val(openGamesFilters["hideMaxPlayers"] || 100);
  5324. $("#hideKeyword").val(openGamesFilters["hideKeyword"] || "");
  5325. $("#hideRealTimeBootTime").val(openGamesFilters["hideRealTimeBootTime"] / 1000 / 60 || 0);
  5326. $("#hideMultiDayBootTimeDays").val(openGamesFilters["hideMultiDayBootTimeDays"] || 0);
  5327. $("#hideMultiDayBootTimeHours").val(openGamesFilters["hideMultiDayBootTimeHours"] || 0);
  5328. })
  5329. }
  5330.  
  5331. function setupOpenGamesFilter() {
  5332. $("#OpenGamesTable thead tr td").prepend('<a id="editFilters" style="color:#DDDDDD;font-size: 14px;float: right;"><img src="' + IMAGES.FILTER + '" class="filter-img"></a>');
  5333. var filtersHTML = "<hr>";
  5334. $.each(window.filters, function (key, filter) {
  5335. if (filter.type == "checkbox") {
  5336. filtersHTML += '<div class="filterOption settingsListItem">' + filter.text + '<label class="switch" for="' + filter.id + '"><input type="checkbox" id="' + filter.id + '"><div class="slider round"></div></label></div>';
  5337. }
  5338. else if (filter.type == "custom") {
  5339. filtersHTML += '<div class="filterOption settingsListItem">' + filter.text + '</div>';
  5340. }
  5341. });
  5342. addCSS(`
  5343. .filter-img {
  5344. height: 20px;
  5345. margin: 7px;
  5346. }
  5347.  
  5348. #gamesAreHidden {
  5349. height: 50px;
  5350. vertical-align: top;
  5351. }
  5352. `);
  5353. $("body").append(`
  5354. <div class="modal modal-1000 fade" id="openGamesFilter" tabindex="-1" role="dialog">
  5355. <div class="modal-dialog" role="document">
  5356. <div class="modal-content">
  5357. <div class="modal-header">
  5358. <h5 class="modal-title" id="exampleModalLongTitle">Filter Open Games</h5>
  5359. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  5360. <span aria-hidden="true">&times;</span>
  5361. </button>
  5362. </div>
  5363. <div class="modal-body">
  5364. ${filtersHTML}
  5365. </div>
  5366. <div class="modal-footer">
  5367. <button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
  5368. <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="window.closeOpenGamesFilter()">Save</button>
  5369. </div>
  5370. </div>
  5371. </div>
  5372. </div>
  5373. `)
  5374. createSelector('hr', 'height: 1px;border: none;background-color: gray;opacity:0.5;');
  5375. createSelector('.number', 'width: 31px');
  5376. createSelector('.filterOption', 'width: 400px;float: left;margin: 5px;');
  5377. createSelector('.info', 'font-size: 12px;color: gray;border: 1px gray solid;padding: 5px;display: block;margin: 8px 0 8px 0;line-height: 20px;overflow: hidden; max-height:18px;transition:max-height 2s;-webkit-transition:max-height 2s;');
  5378. createSelector('.info:hover', 'max-height:500px');
  5379. createSelector('#hideKeyword', 'text-align: left;');
  5380. createSelector('.filter-small, .filter-small label', 'font-size: 12px!important;color: #aaa;');
  5381. $("#hideLuck").after("%");
  5382. createSelector('.ui-button-text-only .ui-button-text', 'padding: .4em 0.6em;');
  5383. createSelector('#editFilters:hover', 'cursor:pointer');
  5384. $("#openGamesFilter").on("change", function () {
  5385. storeFilterVariables();
  5386. });
  5387. $("#editFilters").on("click", function () {
  5388. window.showFilterOptions();
  5389. });
  5390. updateFilterSettings();
  5391. }
  5392. window.closeOpenGamesFilter = function () {
  5393. log("Refresh by userscript settings close")
  5394. refreshAllGames(true);
  5395. }
  5396. window.showFilterHelp = function (text, obj) {
  5397. window.setTimeout(function () {
  5398. if (!$(".custom-menu").is(':visible')) {
  5399. $(".custom-menu .content").html(text);
  5400. $(".custom-menu").finish().toggle(100).
  5401. // In the right position (the mouse)
  5402. css({
  5403. top: $(obj).offset().top + "px",
  5404. left: $(obj).offset().left + "px"
  5405. });
  5406. }
  5407. }, 10);
  5408. }
  5409.  
  5410. function getNumHiddenLabelText(num) {
  5411. return num == 1 ? "1 Game is hidden" : (num + " Games are hidden");
  5412. }
  5413. window.showFilterOptions = function () {
  5414. $("#openGamesFilter").modal("show")
  5415. }
  5416. $$$.fn.getsFiltered = function (openGamesFilters) {
  5417. var game = this[0];
  5418. if (game) {
  5419. if (openGamesFilters["hideMaxPlayers"] <= 100 && $$$(game).numOfPlayers() > openGamesFilters["hideMaxPlayers"]) return true;
  5420. if (openGamesFilters["hideMinPlayers"] <= 100 && $$$(game).numOfPlayers() < openGamesFilters["hideMinPlayers"]) return true;
  5421. if (openGamesFilters["hideLuck"] < 100 && game.SettingsOpt.LuckModifier * 100 > openGamesFilters["hideLuck"]) return true;
  5422. if (openGamesFilters["hideFFA"] && $$$(game).numOfTeams() == 0 && $$$(game).numOfPlayers() > 2) return true;
  5423. if (openGamesFilters["hideTeam"] && $$$(game).numOfTeams() > 0) return true;
  5424. if (openGamesFilters["hide1v1"] && $$$(game).numOfPlayers() == 2) return true;
  5425. if (openGamesFilters["hideCustomScenario"] && game.SettingsOpt.DistributionMode === -3) return true;
  5426. if (openGamesFilters["hideNonCustomScenario"] && game.SettingsOpt.DistributionMode !== -3) return true;
  5427. if (openGamesFilters["hideCommanderGames"] && game.SettingsOpt.HasCommanders) return true;
  5428. if (openGamesFilters["hideNoneCommanderGames"] && !game.SettingsOpt.HasCommanders) return true;
  5429. if (openGamesFilters["hidePractice"] && !game.SettingsOpt.RankedGame) return true;
  5430. if (openGamesFilters["hideNoSplit"] && game.SettingsOpt.NoSplit) return true;
  5431. if (openGamesFilters["hideLocalDeployments"] && game.SettingsOpt.LocalDeployments) return true;
  5432. if (openGamesFilters["hideNonPractice"] && game.SettingsOpt.RankedGame) return true;
  5433. if (openGamesFilters["hideManualDistribution"] && !game.SettingsOpt.AutoDistribution) return true;
  5434. if (openGamesFilters["hideAutoDistribution"] && game.SettingsOpt.AutoDistribution) return true;
  5435. if (openGamesFilters["hideKeyword"] && openGamesFilters["hideKeyword"].length > 0 && $$$(game).containsKeyword(openGamesFilters)) return true;
  5436. if (openGamesFilters["hideRealTimeBootTime"] > 0 && game.RealTimeGame && game.DirectBoot._totalMilliseconds < openGamesFilters["hideRealTimeBootTime"]) return true;
  5437. if (openGamesFilters["hideMultiDayBootTimeInMs"] > 0 && !game.RealTimeGame && game.DirectBoot._totalMilliseconds < openGamesFilters["hideMultiDayBootTimeInMs"]) return true;
  5438. }
  5439. return false;
  5440. };
  5441. $$$.fn.numOfPlayers = function () {
  5442. var game = this[0];
  5443. return game.Players.length + game.OpenSeats.length;
  5444. };
  5445. $$$.fn.playerJoined = function () {
  5446. var game = this[0];
  5447. var playerJoined = false;
  5448. var id = warlight_shared_viewmodels_SignIn.get_CurrentPlayer().ID;
  5449. $.each(game.Players, function (key, player) {
  5450. if (player.PlayerID == id) {
  5451. playerJoined = true;
  5452. }
  5453. });
  5454. return playerJoined;
  5455. };
  5456. $$$.fn.markJoined = function () {
  5457. var game = this[0];
  5458. game.Name += '##joined##';
  5459. return game;
  5460. };
  5461. $$$.fn.numOfTeams = function () {
  5462. var game = this[0];
  5463. var teams = 0;
  5464. if (game.AtStartDivideIntoTeamsOfIfOpenGame > 0) return $$$(game).numOfPlayers() / game.AtStartDivideIntoTeamsOfIfOpenGame;
  5465. if (Math.max.apply(Math, game.OpenSeats) == -1) return 0;
  5466. var maxTeam = Math.max.apply(Math, game.OpenSeats);
  5467. $.each(game.Players, function (key, player) {
  5468. if (player.Team > maxTeam) {
  5469. maxTeam = player.Team;
  5470. };
  5471. });
  5472. return maxTeam + 1;
  5473. }
  5474. $$$.fn.containsKeyword = function (openGamesFilters) {
  5475. var game = this[0];
  5476. var keywords = openGamesFilters["hideKeyword"].split(",");
  5477. var title = game._nameLowered || game.Name.toLowerCase();
  5478. var filtered = false;
  5479. $.each(keywords, function (key, keyword) {
  5480. if (title.indexOf(keyword.trim().toLowerCase()) >= 0) {
  5481. filtered = true;
  5482. }
  5483. })
  5484. return filtered;
  5485. };
  5486. try {
  5487. $.extend($$$.fn.dataTableExt.oSort, {
  5488. "rank-pre": function (a) {
  5489. return a.match(/([0-9]*)/)[1] || 9999;
  5490. },
  5491. "rank-asc": function (a, b) {
  5492. return a < b;
  5493. },
  5494. "rank-desc": function (a, b) {
  5495. return a > b;
  5496. }
  5497. });
  5498. $.extend($$$.fn.dataTableExt.oSort, {
  5499. "numeric-comma-pre": function (a) {
  5500. return Number(a.replace(/,/g, ""))
  5501. },
  5502. "numeric-comma-asc": function (a, b) {
  5503. return a < b;
  5504. },
  5505. "numeric-comma-desc": function (a, b) {
  5506. return a > b;
  5507. }
  5508. });
  5509. }
  5510. catch (e) {
  5511. log(e)
  5512. }
  5513.  
  5514. function addOpenGamesSuffix() {
  5515. var deletedBoth = parseInt(deletedMD) + parseInt(deletedRT);
  5516. $("#OpenGamesTable tbody tr:not(.GameRow)").remove();
  5517. var active = $("#OpenGamesTable .btn-group .active").text();
  5518.  
  5519. if (active.indexOf('Both') > -1 && deletedBoth > 0) {
  5520. //Both
  5521. $("#OpenGamesTable tbody").append("<tr id='gamesAreHidden' style='color: gray;font-style: italic;'><td colspan='2'>" + getNumHiddenLabelText(deletedBoth) + " <span style='float: right;cursor: pointer;font-size: 11px;margin-left: 10px;display: inline-block;margin-top: 2px;margin-right: 20px;' onclick='showFilterOptions()'>Change Filter Options</span</td></tr>");
  5522. } else if (active.indexOf('Real') > -1 && deletedRT > 0) {
  5523. //Real
  5524. $("#OpenGamesTable tbody").append("<tr id='gamesAreHidden' style='color: gray;font-style: italic;'><td colspan='2'>" + getNumHiddenLabelText(deletedRT) + " <span style='float: right;cursor: pointer;font-size: 11px;margin-left: 10px;display: inline-block;margin-top: 2px;margin-right: 20px;' onclick='showFilterOptions()'>Change Filter Options</span</td></tr>");
  5525. } else if (active.indexOf('Multi') > -1 && deletedMD > 0) {
  5526. //Multi-Day
  5527. $("#OpenGamesTable tbody").append("<tr id='gamesAreHidden' style='color: gray;font-style: italic;'><td colspan='2'>" + getNumHiddenLabelText(deletedMD) + " <span style='float: right;cursor: pointer;font-size: 11px;margin-left: 10px;display: inline-block;margin-top: 2px;margin-right: 20px;' onclick='showFilterOptions()'>Change Filter Options</span</td></tr>");
  5528. }
  5529.  
  5530. }
  5531. function setupCommunityLevels() {
  5532. var fonts = $("#LevelsTable tr td:nth-of-type(2) font:nth-of-type(1)")
  5533. $.each(fonts, function (key, font) {
  5534. $(font).html($(font).html().replace(" 0 wins", "<span style='color: khaki'> 0 wins</span>"))
  5535. })
  5536. $("#AutoContainer").wrapInner("<div id='newestLevels' class='tab-pane active'></div>")
  5537. $("#AutoContainer").wrapInner("<div id='content'></div>")
  5538. $("#content").append(`
  5539. <div class="tab-content">
  5540. <div class="tab-pane" id='tab_hot'>
  5541. <h2>Popular New Levels</h2>
  5542. </div>
  5543. <div class="tab-pane" id='tab_liked'>
  5544. <h2>Most Liked Levels</h2>
  5545. </div>
  5546. <div class="tab-pane" id='tab_hardest'>
  5547. <h2>Most Difficult Levels</h2>
  5548. </div>
  5549. <div class="tab-pane" id='tab_mostplayed'>
  5550. <h2>Most Played Levels</h2>
  5551. </div>
  5552. <div class="tab-pane" id='tab_records_player'>
  5553. <h2>Most Records (Player)</h2>
  5554. </div>
  5555. <div class="tab-pane" id='tab_records_clan'>
  5556. <h2>Most Records (Clan)</h2>
  5557. </div>
  5558. <div class="tab-pane" id='tab_topCreators'>
  5559. <h2>Top Creators</h2>
  5560. </div>
  5561. <div class="tab-pane" id='tab_ownLevels'>
  5562. <h2>Your Levels</h2>
  5563. </div>
  5564. <div class="tab-pane" id='tab_ownRecords'>
  5565. <h2>Own Your Records</h2>
  5566. </div>
  5567. <div class="tab-pane" id='tab_stats'>
  5568. <h2>Statistics</h2>
  5569. </div>
  5570. <div id="searchLevel" class='tab-pane'>
  5571. <h2>Search Level</h2>
  5572. <input class="searchLevelInput"/>
  5573. <button class="searchLevelBtn">Search</button>
  5574. <div class="foundLevels"></div>
  5575. </div>
  5576. </div>
  5577. `)
  5578. $("#newestLevels").appendTo("#content > .tab-content")
  5579. $("#content").prepend(`
  5580. <ul class="nav nav-tabs" role="tablist">
  5581. <li class="nav-item">
  5582. <a data-toggle="tab" class="nav-link active" href='#newestLevels'>Newest Levels</a>
  5583. </li>
  5584. <li class="nav-item">
  5585. <a class="nav-link tab_hot" data-toggle="tab" href='#tab_hot'>Hot</a>
  5586. </li>
  5587. <li class="nav-item">
  5588. <a class="nav-link tab_liked" data-toggle="tab" href='#tab_liked'>Most Liked</a>
  5589. </li>
  5590. <li class="nav-item">
  5591. <a class="nav-link tab_hardest" data-toggle="tab" href='#tab_hardest'>Most Difficult</a>
  5592. </li>
  5593. <li class="nav-item">
  5594. <a class="nav-link tab_mostplayed" data-toggle="tab" href='#tab_mostplayed'>Most Played</a>
  5595. </li>
  5596. <li class="nav-item">
  5597. <a class="nav-link" data-toggle="tab" href='#tab_records_player'>Most Records (Player)</a>
  5598. </li>
  5599. <li class="nav-item">
  5600. <a class="nav-link" data-toggle="tab" href='#tab_records_clan'>Most Records (Clan)</a>
  5601. </li>
  5602. <li class="nav-item">
  5603. <a class="nav-link" data-toggle="tab" href='#tab_topCreators'>Top Creators</a>
  5604. </li>
  5605. <li class="nav-item">
  5606. <a class="nav-link" data-toggle="tab" href='#tab_ownLevels'>Your Levels</a>
  5607. </li>
  5608. <li class="nav-item">
  5609. <a class="nav-link" data-toggle="tab" href='#tab_ownRecords'>Your Records</a>
  5610. </li>
  5611. <li class="nav-item">
  5612. <a class="nav-link" data-toggle="tab" href='#tab_stats'>Statistics</a>
  5613. </li>
  5614. <li class="nav-item">
  5615. <a data-toggle="tab" class='search nav-link' href='#searchLevel'>Search </a>
  5616. </li>
  5617. </ul>`)
  5618. $("h1").prependTo("#AutoContainer")
  5619. $(".searchLevelBtn").on("click", function () {
  5620. searchLevel()
  5621. })
  5622. $('.searchLevelInput').keyup(function (e) {
  5623. if (e.keyCode == 13) {
  5624. searchLevel()
  5625. }
  5626. });
  5627. addCSS(`
  5628. .ui-tabs {
  5629. border: none;
  5630. background: none;
  5631. }
  5632. .ui-tabs-nav {
  5633. background: none;
  5634. border: none;
  5635. border-bottom: 1px gray solid;
  5636. }
  5637. .striped th, .striped td {
  5638. border-bottom: 1px gray solid;
  5639. text-align: left;
  5640. }
  5641. `)
  5642. $("li").on("click", function() {
  5643. $('[data-toggle=popover]').popover('hide');
  5644. })
  5645. var mainjsReady = $.Deferred();
  5646. $(".tab_hot").on("click", function () {
  5647. $.when(mainjsReady).done(function () {
  5648. $.each($("#tab_hot tr[data-levelid]:visible"), function (key, row) {
  5649. var id = $(row).attr("data-levelid")
  5650. loadLevelData(id)
  5651. })
  5652. })
  5653. })
  5654. $(".tab_liked").on("click", function () {
  5655. $.when(mainjsReady).done(function () {
  5656. $.each($("#tab_liked tr[data-levelid]:visible"), function (key, row) {
  5657. var id = $(row).attr("data-levelid")
  5658. loadLevelData(id)
  5659. })
  5660. })
  5661. })
  5662. $(".tab_hardest").on("click", function () {
  5663. $.when(mainjsReady).done(function () {
  5664. $.each($("#tab_hardest tr[data-levelid]:visible"), function (key, row) {
  5665. var id = $(row).attr("data-levelid")
  5666. loadLevelData(id)
  5667. })
  5668. })
  5669. })
  5670. $(".tab_mostplayed").on("click", function () {
  5671. $.when(mainjsReady).done(function () {
  5672. $.each($("#tab_mostplayed tr[data-levelid]:visible"), function (key, row) {
  5673. var id = $(row).attr("data-levelid")
  5674. loadLevelData(id)
  5675. })
  5676. })
  5677. })
  5678. $.ajax({
  5679. type: 'GET',
  5680. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=7`,
  5681. dataType: 'jsonp',
  5682. crossDomain: true,
  5683. }).done(function (response) {
  5684. if (response.data) {
  5685. var levels = response.data
  5686. $("#tab_hot").append(`<table id="HotLevelsTable" cellpadding="8"></table>`)
  5687. $.each(levels, function (key, level) {
  5688. $("#HotLevelsTable").append(renderLevelRow(level, key))
  5689. $(`[data-levelid='${level.levelId}']`).attr("data-rating", level.rating)
  5690. })
  5691. $("#HotLevelsTable").append("<button class='btn btn-primary' id='loadMoreHot'>Load More</button>")
  5692. $("#loadMoreHot").on("click", function () {
  5693. $.each($("#tab_hot tr:hidden:lt(5)"), function (key, row) {
  5694. $(this).fadeIn()
  5695. $.when(mainjsReady).done(function () {
  5696. loadLevelData($(row).attr("data-levelid"))
  5697. })
  5698. })
  5699. if ($("#tab_hot tr:hidden:lt(5)").length == 0) {
  5700. $("#loadMoreHot").remove();
  5701. }
  5702. })
  5703. }
  5704. });
  5705. $.ajax({
  5706. type: 'GET',
  5707. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=8`,
  5708. dataType: 'jsonp',
  5709. crossDomain: true,
  5710. }).done(function (response) {
  5711. if (response.data) {
  5712. var levels = response.data
  5713. $("#tab_liked").append(`<table id="MostLikedLevels" cellpadding="8"></table>`)
  5714. $.each(levels, function (key, level) {
  5715. $("#MostLikedLevels").append(renderLevelRow(level, key))
  5716. $(`[data-levelid='${level.levelId}']`).attr("data-rating", level.rating)
  5717. })
  5718. $("#MostLikedLevels").append("<button class='btn btn-primary' id='loadMoreLiked'>Load More</button>")
  5719. $("#loadMoreLiked").on("click", function () {
  5720. $.each($("#tab_liked tr:hidden:lt(5)"), function (key, row) {
  5721. $(this).fadeIn()
  5722. $.when(mainjsReady).done(function () {
  5723. loadLevelData($(row).attr("data-levelid"))
  5724. })
  5725. })
  5726. if ($("#tab_liked tr:hidden:lt(5)").length == 0) {
  5727. $("#loadMoreLiked").remove();
  5728. }
  5729. })
  5730. }
  5731. });
  5732. $.ajax({
  5733. type: 'GET',
  5734. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=1`,
  5735. dataType: 'jsonp',
  5736. crossDomain: true,
  5737. }).done(function (response) {
  5738. if (response.data) {
  5739. var levels = response.data
  5740. $("#tab_hardest").append(`<table id="HardestLevelsTable" cellpadding="8"></table>`)
  5741. $.each(levels, function (key, level) {
  5742. $("#HardestLevelsTable").append(renderLevelRow(level, key))
  5743. })
  5744. $("#HardestLevelsTable").append("<button class='btn btn-primary' id='loadMoreDifficult'>Load More</button>")
  5745. $("#loadMoreDifficult").on("click", function () {
  5746. $.each($("#tab_hardest tr:hidden:lt(5)"), function (key, row) {
  5747. $(this).fadeIn()
  5748. $.when(mainjsReady).done(function () {
  5749. loadLevelData($(row).attr("data-levelid"))
  5750. })
  5751. })
  5752. if ($("#tab_hardest tr:hidden:lt(5)").length == 0) {
  5753. $("#loadMoreDifficult").remove();
  5754. }
  5755. })
  5756. }
  5757. });
  5758. $.ajax({
  5759. type: 'GET',
  5760. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=2`,
  5761. dataType: 'jsonp',
  5762. crossDomain: true,
  5763. }).done(function (response) {
  5764. if (response.data) {
  5765. var levels = response.data
  5766. $("#tab_mostplayed").append(`<table id="MostPlayedLevelsTable" cellpadding="8"></table>`)
  5767. $.each(levels, function (key, level) {
  5768. $("#MostPlayedLevelsTable").append(renderLevelRow(level, key))
  5769. })
  5770. $("#MostPlayedLevelsTable").append("<button class='btn btn-primary' id='loadMoreMostPlayed'>Load More</button>")
  5771. $("#loadMoreMostPlayed").on("click", function () {
  5772. $.each($("#tab_mostplayed tr:hidden:lt(5)"), function (key, row) {
  5773. $(this).fadeIn()
  5774. $.when(mainjsReady).done(function () {
  5775. loadLevelData($(row).attr("data-levelid"))
  5776. })
  5777. })
  5778. if ($("#tab_mostplayed tr:hidden:lt(5)").length == 0) {
  5779. $("#loadMoreMostPlayed").remove();
  5780. }
  5781. })
  5782. }
  5783. });
  5784. $.ajax({
  5785. type: 'GET',
  5786. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=3`,
  5787. dataType: 'jsonp',
  5788. crossDomain: true,
  5789. }).done(function (response) {
  5790. if (response.data) {
  5791. var players = response.data;
  5792. var pointsHelp = "The points for every player are calculated as following:<br><br> <pre>AVG = Average win rate of every level the player has a record on<br>N = Number of records the player has <br><br>Points = (1 - AVG) * N</pre>";
  5793. $("#tab_records_player").append(`<table id="PlayerRecordsTable" cellpadding="8" class="striped"></table>`)
  5794. $("#PlayerRecordsTable").prepend(`<thead><th>#</th><th>Name</th><th>Number of Records</th><th>Points <img tabindex="0" class="help-icon" src="${IMAGES.QUESTION}" data-content="${pointsHelp}" data-toggle="popover"></th></thead>`)
  5795. $.each(players, function (key, player) {
  5796. $("#PlayerRecordsTable").append(renderRecordPlayerRow(player, key))
  5797. });
  5798. $("[data-toggle=popover]").popover({
  5799. trigger: 'click',
  5800. html: true
  5801. })
  5802. }
  5803. });
  5804. $.ajax({
  5805. type: 'GET',
  5806. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=4`,
  5807. dataType: 'jsonp',
  5808. crossDomain: true,
  5809. }).done(function (response) {
  5810. if (response.data) {
  5811. var clans = response.data
  5812. $("#tab_records_clan").append(`<table id="ClanRecordsTable" cellpadding="8" class="striped"></table>`)
  5813. $("#ClanRecordsTable").prepend(`<thead><th>#</th><th>Name</th><th>Number of Records</th></thead>`)
  5814. $.each(clans, function (key, clan) {
  5815. $("#ClanRecordsTable").append(renderClanRow(clan, key))
  5816. })
  5817. }
  5818. });
  5819. $.ajax({
  5820. type: 'GET',
  5821. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=9`,
  5822. dataType: 'jsonp',
  5823. crossDomain: true,
  5824. }).done(function (response) {
  5825. if (response.data) {
  5826. var stats = response.data
  5827. console.log(stats)
  5828. $("#tab_stats").append(renderStatsRow("Total number of levels", stats.totalLevels))
  5829. $("#tab_stats").append(renderStatsRow("Total attempts", stats.totalAttempts))
  5830. $("#tab_stats").append(renderStatsRow("Average attempts", Math.round(stats.totalAttempts / stats.totalLevels, 0)))
  5831. $("#tab_stats").append(renderStatsRow("Total likes", stats.totalLikes))
  5832. $("#tab_stats").append(renderStatsRow("Average likes", Math.round(stats.totalLikes / stats.totalLevels, 0)))
  5833. $("#tab_stats").append(renderStatsRow("Total creators", stats.totalCreators))
  5834. $("#tab_stats").append(renderStatsRow("Total record holders", stats.totalRecordHolders))
  5835. }
  5836. });
  5837. addCSS(`
  5838. tr td {
  5839. vertical-align: middle!important;
  5840. }
  5841. `)
  5842. $.ajax({
  5843. type: 'GET',
  5844. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?m=6`,
  5845. dataType: 'jsonp',
  5846. crossDomain: true,
  5847. }).done(function (response) {
  5848. if (response.data) {
  5849. var players = response.data;
  5850. var pointsHelp = `The points for every creator are calculated as following:<br><br> <pre>N = Total number of levels created<br>L = Total number of likes received<br>A = Total number of attempts<br>W = Total number of wins<br><br>x = when N < 8 then 0.1 * N + 0.2 else 1 <br><br>Points = L / (N + 2) * 10 * x + A /(N + 2) * 0.5 * x + 350* (1 - W / A) * x
  5851. </pre>`;
  5852. $("#tab_topCreators").append(`<table id="CreatorsTable" cellpadding="8" class="table table-striped mb-0"></table>`)
  5853. $("#CreatorsTable").prepend(`<thead><th>#</th><th>Name</th><th>Total Likes</th><th>Total Attempts</th><th>Total Wins</th><th>Overall Win Rate</th><th>Total Levels</th><th>Points <img tabindex="0" class="help-icon" src="${IMAGES.QUESTION}" data-content="${pointsHelp}" data-toggle="popover"></th><th>-</th></thead><tbody></tbody>`)
  5854. $.each(players, function (key, player) {
  5855. $("#CreatorsTable tbody").append(renderCreatorPlayerRow(player, key))
  5856. })
  5857. var dataTable = $$$("#CreatorsTable").DataTable({
  5858. paging: false,
  5859. sDom: 't',
  5860. initComplete: function () {
  5861. $("#CreatorsTable").removeClass("dataTable")
  5862. },
  5863. });
  5864. $("[data-toggle=popover]").popover({
  5865. trigger: 'click',
  5866. html: true
  5867. });
  5868. $("[data-toggle=popover]").on("click", function(e) {
  5869. e.stopPropagation();
  5870. e.preventDefault();
  5871. })
  5872. }
  5873. });
  5874. var id = $("nav a[href*='Profile']").attr("href").replace(/\/Profile\?p=/, "");
  5875. $.ajax({
  5876. type: 'GET',
  5877. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?p=${id}`,
  5878. dataType: 'jsonp',
  5879. crossDomain: true,
  5880. }).done(function (response) {
  5881. if (response.data) {
  5882. var levels = response.data
  5883. $("#tab_ownLevels").append(`<table id="OwnLevelsTable" cellpadding="8"></table>`)
  5884. $.each(levels, function (key, level) {
  5885. $("#OwnLevelsTable").append(renderLevelRow(level, key, true))
  5886. })
  5887. }
  5888. });
  5889. $.ajax({
  5890. type: 'GET',
  5891. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?o=${id}`,
  5892. dataType: 'jsonp',
  5893. crossDomain: true,
  5894. }).done(function (response) {
  5895. if (response.data) {
  5896. var levels = response.data
  5897. $("#tab_ownRecords").append(`<table id="OwnRecordsTable" cellpadding="8"></table>`)
  5898. $.each(levels, function (key, level) {
  5899. $("#OwnRecordsTable").append(renderLevelRow(level, key, true))
  5900. })
  5901. }
  5902. });
  5903. var div = $("<div></div>")
  5904. var mainjs = "";
  5905. div.load('https://www.warzone.com/SinglePlayer/Level?ID=882053', function () {
  5906. mainjs = div.find("script:contains(MainJS.Init)").html()
  5907. $.getScript("https://d2wcw7vp66n8b3.cloudfront.net/js/Release/wl.js?v=636045359309573936").done(function () {
  5908. eval(mainjs);
  5909. $("#WaitDialogJSWhiteBox").remove();
  5910. $("#WaitDialogJSBacking").remove();
  5911. mainjsReady.resolve();
  5912. })
  5913. });
  5914. }
  5915.  
  5916. function renderStatsRow(name, value) {
  5917. if (value && Number(value)) {
  5918. return $("<div style='margin-bottom: 10px'>").html("<b>" + name + "</b>: " + Number(value).toLocaleString("en"))
  5919. }
  5920. }
  5921.  
  5922. function searchLevel() {
  5923. var query = $(".searchLevelInput").val().toLowerCase();
  5924. $(".foundLevels *").remove();
  5925. $.ajax({
  5926. type: 'GET',
  5927. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?q=${query}`,
  5928. dataType: 'jsonp',
  5929. crossDomain: true,
  5930. }).done(function (response) {
  5931. if (response.data) {
  5932. if (response.data.length > 0) {
  5933. var levels = response.data
  5934. $(".foundLevels").append(`<table id="FoundLevelTable" cellpadding="8"></table>`)
  5935. $.each(levels, function (key, level) {
  5936. $("#FoundLevelTable").append(renderLevelRow(level, key))
  5937. })
  5938. }
  5939. else {
  5940. $(".foundLevels").append(`<span>No levels found!</span>`)
  5941. }
  5942. }
  5943. else {
  5944. $(".foundLevels").append(`<span>Error searching for levels</span>`)
  5945. }
  5946. });
  5947. }
  5948.  
  5949. function decode(str) {
  5950. var decoded = "";
  5951. try {
  5952. decoded = decodeURIComponent((str + '').replace(/%(?![\da-f]{2})/gi, function () {
  5953. return '%25'
  5954. }).replace(/\+/g, '%20'))
  5955. }
  5956. catch (e) {
  5957. decoded = unescape(str);
  5958. }
  5959. return decoded;
  5960. }
  5961.  
  5962. function renderRecordPlayerRow(player, key) {
  5963. var rank = getRankHtml(key + 1)
  5964. return `
  5965. <tr>
  5966. <td>${rank}</td>
  5967. <td>
  5968. ${player.recordClanId > 0 ? '<a href="/Clans/?ID=' + player.recordClanId + '" title="' + player.recordClanName + '"><img border="0" style="vertical-align: middle" src="' + player.recordClanImage + '"></a>' : ''}
  5969. <a href="${player.recordHolderUrl}"> ${decode(player.recordHolderName)} </a>
  5970. </td>
  5971. <td>
  5972. ${player.numOfRecords}
  5973. </td>
  5974. <td>
  5975. ${(Math.round(player.points*10)/10).toFixed(2)}
  5976. </td>
  5977. </tr>`
  5978. }
  5979.  
  5980. function renderCreatorPlayerRow(player, key) {
  5981. var id = player.createdByUrl.match(/[0-9]+/)[0]
  5982. var rank = getRankHtml(key + 1)
  5983. return `
  5984. <tr>
  5985. <td style="text-align:center;padding:0" data-sort="${key+1}">${rank}</td>
  5986. <td>
  5987. ${player.creatorClanId > 0 ? '<a href="/Clans/?ID=' + player.creatorClanId + '" title="' + player.creatorClanName + '"><img border="0" style="vertical-align: middle" src="' + player.creatorClanImage + '"></a>' : ''}
  5988. <a href="${player.createdByUrl}"> ${decode(player.createdByName)} </a>
  5989. </td>
  5990. <td>
  5991. ${player.numOfTotalLikes}
  5992. </td>
  5993. <td>
  5994. ${player.numOfTotalAttempts}
  5995. </td>
  5996. <td>
  5997. ${player.numOfTotalWins}
  5998. </td>
  5999. <td>
  6000. ${(player.numOfTotalWins / player.numOfTotalAttempts * 100).toFixed(2)}%
  6001. </td>
  6002. <td>
  6003. ${player.numOfCreatedLevels}
  6004. </td>
  6005. <td>
  6006. ${player.points}
  6007. </td>
  6008. <td>
  6009. <a href="https://www.warzone.com/SinglePlayer/LevelsByCreator?p=${id.substring(2, id.length-2)}">Show Levels</a>
  6010. </td>
  6011. </tr>`
  6012. }
  6013.  
  6014. function renderClanRow(clan, key) {
  6015. var rank = getRankHtml(key + 1)
  6016. return `
  6017. <tr>
  6018. <td>${rank}</td>
  6019. <td>
  6020. <a href="/Clans/?ID=${clan.recordClanId}" title="${clan.recordClanId}"><img border="0" style="vertical-align: middle" src="${clan.recordClanImage}">${decode(clan.recordClanName)}</a>
  6021. </td>
  6022. <td>
  6023. ${clan.numOfRecords}
  6024. </td>
  6025. </tr>`
  6026. }
  6027.  
  6028. function renderLevelRow(level, key, showAll) {
  6029. return `
  6030. <tr data-levelid="${level.levelId}" ${(key >= 10 && showAll != true) ? 'style="display:none"' : ''}>
  6031. <td style="position: relative">
  6032. <img src="${level.mapImage}" width="140" height="80" style="position:relative">
  6033. </td>
  6034. <td>
  6035. <a style="font-size: 17px; color: white"
  6036. href="/SinglePlayer/Level?ID=${level.levelId}">${key+1}. ${decode(level.name)}
  6037. </a> &nbsp;&nbsp;
  6038. <font color="gray">${level.likes} likes, ${level.wins} wins in ${level.attempts} attempts</font><br>
  6039.  
  6040. <font color="gray">Created by</font> ${level.creatorClanId > 0 ? '<a href="/Clans/?ID=' + level.creatorClanId + '" title="' + level.creatorClanName + '"><img border="0" style="vertical-align: middle" src="' + level.creatorClanImage + '"></a>' : ''} <a href="${level.createdByUrl}">${decode(level.createdByName)}</a><br>
  6041.  
  6042. <font color="gray">Record holder:</font> ${level.recordClanId > 0 ? '<a href="/Clans/?ID=' + level.recordClanId + '" title="' + level.recordClanId + '"><img border="0" style="vertical-align: middle" src="' + level.recordClanImage + '"></a>' : ''} ${level.recordHolderName ? '<a href="' + level.recordHolderUrl + '">' + decode(level.recordHolderName) + '</a>' + getTurnText(level.recordHolderText) : 'None'}<br>
  6043.  
  6044. <font color="gray">Win rate: </font>${level.percentage}%<br>
  6045. </td>
  6046. <td><span style="font-size: 17px"><a href="/SinglePlayer?Level=${level.levelId}">Play</a></span></td>
  6047. </tr>`
  6048. }
  6049.  
  6050. function getTurnText(turns) {
  6051. return ` in ${turns} ${turns > 1 ? 'turns' : 'turn'}`
  6052. }
  6053.  
  6054. function getRankHtml(rank) {
  6055. if (rank == 1) {
  6056. return `<img height=30 width=30 style="padding:0" src="https://i.imgur.com/dG4hKlp.gif">`
  6057. }
  6058. else if (rank == 2) {
  6059. return `<img height=30 width=30 style="padding:0" src="https://imgur.com/qmpjRNs.gif">`
  6060. }
  6061. else if (rank == 3) {
  6062. return `<img height=30 width=30 style="padding:0" src="https://imgur.com/DgtbQDN.gif">`
  6063. }
  6064. return rank;
  6065. }
  6066.  
  6067. function loadLevelData(id) {
  6068. warlight_shared_viewmodels_spe_SPEManager.GetLevelResult(id, function (levelData) {
  6069. if (levelData && levelData.WinCount > 0) {
  6070. $(`[data-levelid="${id}"] td:nth-of-type(2)`).append(`You won ${getTurnText(levelData.WonInTurns)}`)
  6071. $(`[data-levelid="${id}"] td:nth-of-type(1)`).append('<img src="https://d2wcw7vp66n8b3.cloudfront.net/Images/TransparentCheck.png" width="61" height="53" style="position: absolute; right: 0px; bottom: 0px">')
  6072. }
  6073. $(`[data-levelid="${id}"]`).attr("data-levelid", "done")
  6074. })
  6075. }
  6076.  
  6077. function setupPlayerAttempDataTable() {
  6078. var playerData = []
  6079. $("#AutoContainer ul").find("li").map(function () {
  6080. var player = $(this).children().map(function () {
  6081. return $(this).outerHTML()
  6082. }).get().join("")
  6083. var str = $(this).clone().children().remove().end().text();
  6084. var attemps = str.split(", ")[0].replace(/[^0-9]/g, '')
  6085. var wins = str.split(", ")[1].replace(/[^0-9]/g, '')
  6086. playerData.push({
  6087. player: player,
  6088. attemps: attemps,
  6089. wins: wins
  6090. })
  6091. })
  6092. var table = "<table id='playlogPreview'><thead><th>Name</th><th>Attemps</th><th>Wins</th></thead>"
  6093. $.each(playerData, function (k, player) {
  6094. var tr = `<tr><td>${player.player}</td><td>${player.attemps}</td><td>${player.wins}</td></tr>`;
  6095. table += tr;
  6096. })
  6097. table += "</table>"
  6098. $("#AutoContainer ul").replaceWith(table)
  6099. loadDataTableCSS();
  6100. var dataTable = $$$("#playlogPreview").DataTable({
  6101. "order": [2],
  6102. paging: false,
  6103. sDom: 't',
  6104. columnDefs: [{
  6105. targets: [0, 1, 2],
  6106. }, {
  6107. targets: [1],
  6108. orderData: [1, 2, 0]
  6109. }, {
  6110. targets: [2],
  6111. orderData: [2, 1, 0],
  6112. }],
  6113. "aoColumns": [
  6114. {
  6115. "orderSequence": ["asc", "desc"]
  6116. },
  6117. {
  6118. "orderSequence": ["desc", "asc"]
  6119. },
  6120. {
  6121. "orderSequence": ["desc", "asc"]
  6122. },
  6123. ],
  6124. });
  6125. addCSS(`
  6126. #playlogPreview a {
  6127. margin-right: 10px;
  6128. }
  6129. #playlogPreview td {
  6130. white-space: nowrap;
  6131. }
  6132. `)
  6133. }
  6134. function parseForumSPLevels() {
  6135. console.log("parsing sp levels")
  6136. var path = 'SinglePlayer';
  6137. var regex = new RegExp(path, 'i');
  6138. $('.region a').each(function () {
  6139. var href = $(this).attr('href')
  6140. if (href && href.match(regex)) {
  6141. parseSPLevel(this, href);
  6142. }
  6143. });
  6144. addCSS(`
  6145. table.SPTable {
  6146. width:100%;
  6147. background: rgba(255,255,255,0.05)
  6148. }
  6149. .SPTable tr {
  6150. display: flex;
  6151. align-items: stretch;
  6152. }
  6153. .SPTable td:last-child {
  6154. flex: 1;
  6155. display: flex;
  6156. align-items: center;
  6157. justify-content: flex-end;
  6158. margin-right: 5px;
  6159. }
  6160. `)
  6161. }
  6162.  
  6163. function parseSPLevel(elem, href) {
  6164. var levelId = getLeveId(href);
  6165. if (levelId) {
  6166. $.ajax({
  6167. type: 'GET',
  6168. url: `https://w115l144.hoststar.ch/wl/communityLevels.php?id=`+levelId,
  6169. dataType: 'jsonp',
  6170. crossDomain: true,
  6171. }).done(function (response) {
  6172. if (response.data) {
  6173. console.log(response.data)
  6174. var level = response.data[0]
  6175. var row = renderLevelRow(level, 0, true);
  6176. var table = $("<table class='SPTable'></table>")
  6177. table.append(row)
  6178. $(elem).replaceWith(table);
  6179. table.find("tr td").css("text-align", "left");
  6180. }
  6181. });
  6182. }
  6183. }
  6184.  
  6185. function getLeveId(href) {
  6186. var match = href.match(/level\?id=(.*)/i) || href.match(/level=(.*)/i)
  6187. if (match) {
  6188. return match[1]
  6189. }
  6190. }
  6191. function getArt() {
  6192. return {
  6193. Types: {
  6194. DivA: {
  6195. Player: {
  6196. FullHeight: 250,
  6197. IconHeight: 60
  6198. },
  6199. Clan: {
  6200. FullHeight: 350,
  6201. IconHeight: 80
  6202. }
  6203. },
  6204. DivB: {
  6205. Player: {
  6206. FullHeight: 200,
  6207. IconHeight: 50
  6208. },
  6209. Clan: {
  6210. FullHeight: 250,
  6211. IconHeight: 70
  6212. }
  6213. }
  6214. },
  6215. Groups: [
  6216. {
  6217. Type: "DivA",
  6218. Title: "Clan League 9",
  6219. Players: {
  6220. //Malakkan
  6221. 257509174: ["https://i.imgur.com/16vS4Ut.png"],
  6222. //#Master [QB]
  6223. 5518973792: ["https://i.imgur.com/ZssJxOk.png", "https://i.imgur.com/5xKJQVQ.png"],
  6224. //Master Ryiro
  6225. 5015900432: ["https://i.imgur.com/NDCh1iF.png", "https://i.imgur.com/9AchdrO.png"],
  6226. //Master Jz
  6227. 4439722815: ["https://i.imgur.com/ZH0MaxV.png"],
  6228. //Master of the Dead
  6229. 2428496679: ["https://i.imgur.com/OLo56yI.png", "https://i.imgur.com/0Wy9qmT.png", "https://i.imgur.com/HeInmGN.png"],
  6230. //PanagiotisTheGreekFreak
  6231. 2049943516: ["https://i.imgur.com/mz3FZql.png"],
  6232. //Timinator • apex
  6233. 816809922: ["https://i.imgur.com/6kljYSb.png", "https://i.imgur.com/BqCAzbp.png"],
  6234. //{101st} Master Sarah♦
  6235. 4543063534: ["https://i.imgur.com/QbffPl9.png", "https://i.imgur.com/RTNBhYr.png"],
  6236. //Beren • apex
  6237. 314032996: ["https://i.imgur.com/98JUdFy.png"],
  6238. //Muli
  6239. 2211733141: ["https://i.imgur.com/XqV4Hjy.png"],
  6240. //Sephiroth
  6241. 9911415828: ["https://i.imgur.com/PD93aHT.png"],
  6242. //Master Atom ◆Elite◆
  6243. 3427873563: ["https://i.imgur.com/SDTtj3O.png"],
  6244. //Jefferspin
  6245. 6319040229: ["https://i.imgur.com/ewDBddw.png"],
  6246. //master of desaster
  6247. 2214950915: ["https://i.imgur.com/1oTZcHn.png", "https://i.imgur.com/xeuvFzs.png"],
  6248. //AWESOMEGUY
  6249. 796423469: ["https://i.imgur.com/17IV10e.png"]
  6250. },
  6251. Clans: {
  6252. //Masters
  6253. 11: ["https://i.imgur.com/spTbW2c.png"],
  6254. //One
  6255. 170: ["https://i.imgur.com/r0KGhkC.png"],
  6256. //Outlaws
  6257. 260: ["https://i.imgur.com/rjYJbAL.png"]
  6258. }
  6259. }, {
  6260. Type: "DivB",
  6261. Title: "Clan League 9",
  6262. Players: {
  6263. //smileyleg
  6264. 3929495241: ["https://i.imgur.com/bGzoMkd.png"],
  6265. //Master Moto
  6266. 6862295334: ["https://i.imgur.com/eO6T4D2.png"],
  6267. //Ollie
  6268. 7524524629: ["https://i.imgur.com/OCFI7Lw.png"],
  6269. //almosttricky
  6270. 4817205946: ["https://i.imgur.com/W9EugfQ.png"],
  6271. //Hobo
  6272. 239359818: ["https://i.imgur.com/aoe1IAH.png"],
  6273. //Botanator
  6274. 633358359: ["https://i.imgur.com/FIXeYG5.png"],
  6275. //ViralGoat
  6276. 7841556925: ["https://i.imgur.com/DOXeAsO.png"],
  6277. //EZPickens
  6278. 55998716: ["https://i.imgur.com/6QoMxs5.png"],
  6279. //Mifran
  6280. 4825272432: ["https://i.imgur.com/3Dcq6eh.png"],
  6281. //JV
  6282. 8019640756: ["https://i.imgur.com/IxdYo7S.png"],
  6283. //KO
  6284. 7818276235: ["https://i.imgur.com/sOOvMDz.png"],
  6285. //DarrenDieHard
  6286. 82622046: ["https://i.imgur.com/ieeUKje.png"],
  6287. //Inside
  6288. 105380470: ["https://i.imgur.com/xYSTPm4.png"],
  6289. //Tobe
  6290. 4514168736: ["https://i.imgur.com/xQkMg9h.png"],
  6291. //Jaymer
  6292. 3237238849: ["https://i.imgur.com/i1HxTh8.png"],
  6293. //kirby
  6294. 8818886504: ["https://i.imgur.com/hrdHmXm.png"],
  6295. //rakleader
  6296. 8136895102: ["https://i.imgur.com/ugUpnM2.png"],
  6297. //Timtimie
  6298. 8311000679: ["https://i.imgur.com/oQg2idd.png"],
  6299. //Cluster
  6300. 7010496305: ["https://i.imgur.com/3wN6HDI.png"]
  6301. },
  6302. Clans: {
  6303. //GG
  6304. 9: ["https://i.imgur.com/90oitx6.png"],
  6305. //MH
  6306. 141: ["https://i.imgur.com/n55iL2y.png"],
  6307. //VS
  6308. 188: ["https://i.imgur.com/c4bDQ6u.png"]
  6309. }
  6310. }
  6311. ],
  6312. }
  6313. }
  6314.  
  6315. function setupCLArt() {
  6316. setupArtIcons();
  6317. addCSS(`
  6318. #clArt img {
  6319. float: left;
  6320. margin: 5px;
  6321. }
  6322. #clArt {
  6323. max-width: 250px;
  6324. cursor: pointer;
  6325. }
  6326. #clArt a {
  6327. clear: both;
  6328. display: block;
  6329. }
  6330. #awardDialog {
  6331. display: none;
  6332. }
  6333. #awardDialog img {
  6334. display: inline-block;
  6335. margin: 20px;
  6336. webkit-filter: drop-shadow(5px 10px 6px black);
  6337. filter: drop-shadow(5px 10px 6px black);
  6338. }
  6339. #awardDialog .group {
  6340. text-align: left;
  6341. padding: 8px 30px;
  6342. margin: 20px 10px;
  6343. background-size: cover;
  6344. }
  6345. #awardDialog h1 {
  6346. text-align: left;
  6347. text-transform: uppercase;
  6348. font-weight: bold;
  6349. color: rgba(255, 255, 255, 0.66);
  6350. display: block;
  6351. font-size: 28px;
  6352. }
  6353. .clearFloat{
  6354. display: block;
  6355. width: 100%;
  6356. }
  6357. .ui-widget-header {
  6358. border: none;
  6359. background: none;
  6360. }
  6361. .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
  6362. border: none;
  6363. background: none;
  6364. outline: none;
  6365. margin: -2px;
  6366. z-index: 10;
  6367. }
  6368. .ui-dialog {
  6369. background: url(https://i.imgur.com/woAdW0h.png);
  6370. background-size: cover;
  6371. }
  6372. `)
  6373. }
  6374.  
  6375. function setupArtIcons() {
  6376. if (pageIsProfile()) {
  6377. setupArtIconsProfile();
  6378. }
  6379. else if (pageIsClanPage()) {
  6380. setupArtIconsClan();
  6381. }
  6382. }
  6383.  
  6384. function setupArtIconsProfile() {
  6385. var dialog = $('<div id="awardDialog" title=""></div>');
  6386. var dialogContent = $('<div class="content"></div>');
  6387. var id = window.location.href.replace(/.*warzone.com\/Profile\?p=/, "");
  6388. $('a[href*="Achievements"]').closest("tr").after("<tr><td colspan='3' id='clArt'></td></tr>");
  6389. var count = 0;
  6390. getArt().Groups.forEach(function (group, key) {
  6391. var groupContent = $("<div class='group'></div>")
  6392. groupContent.append("<h1>" + group.Title + "</h1><div class='clearFloat'></div>")
  6393. if (group.Players[id]) {
  6394. group.Players[id].forEach(function (img, key) {
  6395. $("#clArt").append(getImageIcon(img, group, "Player"))
  6396. groupContent.append(getImageFullSize(img, group, "Player"))
  6397. count++;
  6398. })
  6399. dialogContent.append(groupContent);
  6400. }
  6401. })
  6402. $("#clArt").prepend("<h3>Awards <font color='gray'>(" + count + ")</font></h3>")
  6403. if (count > 0) {
  6404. $("#clArt").append("<a>Show All</a>")
  6405. }
  6406. else {
  6407. $("#clArt").append("<em>No awards yet</em>")
  6408. }
  6409. dialog.append(dialogContent);
  6410. appendDialog($(dialog).html())
  6411. if (count > 0) {
  6412. $("#clArt").on("click", function () {
  6413. $("#userscriptAwards").modal("show");
  6414. })
  6415. }
  6416. }
  6417.  
  6418. function setupArtIconsClan() {
  6419. $("#AutoContainer > table tr > td:nth-of-type(3)").append("<div id='clArt'></div>");
  6420. $("#AutoContainer > table tr > td:nth-of-type(3)").css("padding-top", 0);
  6421. addCSS(`
  6422. #clArt {
  6423. display: inline-block;
  6424. top: 45px;
  6425. position: absolute;
  6426. }
  6427. `)
  6428. var dialog = $('<div id="awardDialog" title=""></div>');
  6429. var dialogContent = $('<div class="content"></div>');
  6430. var id = window.location.href.replace(/.*Clans\/\?ID=/, "");
  6431. var count = 0;
  6432. getArt().Groups.forEach(function (group, key) {
  6433. var groupContent = $("<div class='group'></div>")
  6434. groupContent.append("<h1>" + group.Title + "</h1><div class='clearFloat'></div>")
  6435. if (group.Clans[id]) {
  6436. group.Clans[id].forEach(function (img, key) {
  6437. $("#clArt").append(getImageIcon(img, group, "Clan"))
  6438. groupContent.append(getImageFullSize(img, group, "Clan"))
  6439. count++;
  6440. })
  6441. dialogContent.append(groupContent);
  6442. }
  6443. })
  6444. $("#clArt").prepend("<h3>Achievements <font color='gray'>(" + count + ")</font></h3>")
  6445. if (count > 0) {
  6446. $("#clArt").append("<a>Show All</a>")
  6447. }
  6448. else {
  6449. $("#clArt").append("<em>No achievements yet</em>")
  6450. }
  6451. $("#clArt").css("position", "inherit")
  6452. dialog.append(dialogContent);
  6453. appendDialog($(dialog).html())
  6454. if (count > 0) {
  6455. $("#clArt").on("click", function () {
  6456. $("#userscriptAwards").modal("show");
  6457. })
  6458. }
  6459. }
  6460.  
  6461. function appendDialog(content) {
  6462. $("body").append(`
  6463. <div class="modal modal-1000 fade" id="userscriptAwards" tabindex="-1" role="dialog">
  6464. <div class="modal-dialog" role="document">
  6465. <div class="modal-content">
  6466. <div class="modal-header">
  6467. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  6468. <span aria-hidden="true">&times;</span>
  6469. </button>
  6470. </div>
  6471. <div class="modal-body">
  6472. ${content}
  6473. </div>
  6474. <div class="modal-footer">
  6475. <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
  6476. </div>
  6477. </div>
  6478. </div>
  6479. </div>
  6480. `)
  6481. }
  6482.  
  6483. function getImageFullSize(href, group, type) {
  6484. var height = getArt().Types[group.Type][type].FullHeight;
  6485. return "<img src='" + href + "' height='" + height + "'>"
  6486. }
  6487.  
  6488. function getImageIcon(href, group, type) {
  6489. var height = getArt().Types[group.Type][type].IconHeight;
  6490. return "<img src='" + href + "' height='" + height + "'>"
  6491. }
  6492. function createUJSMenu() {
  6493. $(".navbar-nav .nav-item:first").before(`
  6494. <li class="nav-item dropdown">
  6495. <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">Game</a>
  6496. <div class="dropdown-menu p-0 br-3 ujs-dropdown"></div>
  6497. </li>`);
  6498. createUJSSubMenu("Mirror Picks", "mirror-picks");
  6499. createUJSSubMenuEntry("ujs-dropdown", "-");
  6500. }
  6501.  
  6502. function createUJSSubMenu(name, className) {
  6503. $(".ujs-dropdown").append(`
  6504. <li class="dropdown-submenu">
  6505. <a class="dropdown-toggle dropdown-item" data-toggle="dropdown" href="#" aria-expanded="true">` + name + `</a>
  6506. <ul class="dropdown-menu ` + className + `" aria-labelledby="navbarDropdownMenuLink"></ul>
  6507.  
  6508. </li>
  6509. `)
  6510. }
  6511.  
  6512. function createUJSSubMenuEntry(parent, name) {
  6513. var entry = $('<li><a class="dropdown-item" href="#">' + name + '</a></li>');
  6514. $("." + parent).append(entry);
  6515. return entry;
  6516. }
  6517. window.teammatesOrdersChanged = function (orders) {
  6518. if(window.Game == undefined) {
  6519. window.setTimeout(function() {window.teammatesOrdersChanged(orders)}, 1000)
  6520. }
  6521. else if (orders != undefined && window.Game.NumberOfTurns == -1) {
  6522. $(".ujs-dropdown .mirror-picks").empty();
  6523. $.each(Object.keys(orders.store.h), function (key, playerId) {
  6524. var picks = orders.store.h[playerId].Picks;
  6525. var playerName = window.Game.Players.store.h[playerId].Player.DisplayName;
  6526. var entry = createUJSSubMenuEntry("mirror-picks", "Mirror " + playerName);
  6527. entry.on("click", function () {
  6528. pickTerritories(picks);
  6529. });
  6530. });
  6531. }
  6532. else {
  6533. $(".mirror-picks").parent().remove();
  6534. }
  6535. }
  6536.  
  6537. function pickTerritories(picks) {
  6538. console.log(picks)
  6539. if ($("#ujs_OrdersListItemContents").children().length == 0) {
  6540. $("svg").click()
  6541. $.each(picks, function (key, val) {
  6542. pickTerritory(val);
  6543. });
  6544. }
  6545. else {
  6546. CreateModal("Alert", "", "Please clear your orders first.", false)
  6547. }
  6548. }
  6549.  
  6550. function pickTerritory(id) {
  6551. var order = new OrderListItem(this.State.Root.Links.get_Us().get_ID(), id, this.State.Orders.length)
  6552. State.InsertOrder(new GameOrderPick(order, State.Root, State.Root.Links.Latest.LatestStanding))
  6553. }
  6554. addCSS(`
  6555. .navbar-nav li:hover > ul.dropdown-menu {
  6556. display: block;
  6557. }
  6558. .dropdown-submenu {
  6559. position:relative;
  6560. }
  6561. .dropdown-submenu>.dropdown-menu {
  6562. top:0;
  6563. left:100%;
  6564. margin-top:-6px;
  6565. }
  6566. .ujs-menu .dropdown-menu {
  6567. padding: 0px;
  6568.  
  6569. }
  6570. `);
  6571. function checkForScripts(controlArray) {
  6572. /*--- Note that this is a self-initializing function. The controlArray
  6573. parameter is only active for the FIRST call. After that, it is an
  6574. event listener.
  6575. The control array row is defines like so:
  6576. [bSearchSrcAttr, identifyingRegex, callbackFunction]
  6577. Where:
  6578. bSearchSrcAttr True to search the SRC attribute of a script tag
  6579. false to search the TEXT content of a script tag.
  6580. identifyingRegex A valid regular expression that should be unique
  6581. to that particular script tag.
  6582. callbackFunction An optional function to execute when the script is
  6583. found. Use null if not needed.
  6584. Usage example:
  6585. checkForScripts ( [
  6586. [false, /old, evil init()/, function () {addJS_Node (init);} ],
  6587. [true, /evilExternalJS/i, null ]
  6588. ] );
  6589. */
  6590. if (!controlArray.length) return null;
  6591. checkForScripts = function (zEvent) {
  6592. for (var J = controlArray.length - 1; J >= 0; --J) {
  6593. var bSearchSrcAttr = controlArray[J][0];
  6594. var identifyingRegex = controlArray[J][1];
  6595. if (bSearchSrcAttr) {
  6596. if (identifyingRegex.test(zEvent.target.src)) {
  6597. blockJavascript(J);
  6598. return false;
  6599. }
  6600. }
  6601. else {
  6602. if (identifyingRegex.test(zEvent.target.textContent)) {
  6603. blockJavascript(J);
  6604. return false;
  6605. }
  6606. }
  6607. }
  6608.  
  6609. function blockJavascript(controlIndex) {
  6610. zEvent.stopPropagation();
  6611. zEvent.preventDefault();
  6612. var callbackFunction = controlArray[J][2];
  6613. if (typeof callbackFunction == "function") callbackFunction(zEvent.target);
  6614. //--- Remove the node just to clear clutter from Firebug inspection.
  6615. zEvent.target.parentNode.removeChild(zEvent.target);
  6616. //--- Script is intercepted, remove it from the list.
  6617. controlArray.splice(J, 1);
  6618. if (!controlArray.length) {
  6619. //--- All done, remove the listener.
  6620. window.removeEventListener('beforescriptexecute', checkForScripts, true);
  6621. }
  6622. }
  6623. }
  6624. window.listener = checkForScripts;
  6625. /*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded.
  6626. See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute
  6627. Note seems to work on acripts that are dynamically created, despite what
  6628. the spec says.
  6629. */
  6630. window.addEventListener('beforescriptexecute', checkForScripts, true);
  6631. return checkForScripts;
  6632. }
  6633.  
  6634. function addJS_Node(text, s_URL, funcToRun) {
  6635. var D = document;
  6636. var scriptNode = D.createElement('script');
  6637. scriptNode.type = "text/javascript";
  6638. if (text) scriptNode.textContent = text;
  6639. if (s_URL) scriptNode.src = s_URL;
  6640. if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
  6641. var targ = D.getElementsByTagName('head')[0] || D.body || D.documentElement;
  6642. targ.appendChild(scriptNode);
  6643. }
  6644. //if (browserIsFirefox()) {
  6645. // checkForScripts([
  6646. // [true, /ujs/, replaceUJS],
  6647. // [false, /UJS_Init/, replaceInitJS]
  6648. // ]);
  6649. // window.ujsReady = false;
  6650. // window.initReady = false;
  6651. //}
  6652.  
  6653. function replaceUJS(scriptNode) {
  6654. var src = scriptNode.src;
  6655. $$$.ajax({
  6656. url: src,
  6657. dataType: "text",
  6658. success: function (data) {
  6659. var srcData = data;
  6660. try {
  6661. data = replaceData(data, /e\.TeammatesOrders=b;/g, " e.TeammatesOrders=b;window.teammatesOrdersChanged(b);");
  6662. data = replaceData(data, /\(a\.Obj\.Game=new cc\);/g, "(a.Obj.Game=new cc);window.Game=a.Obj.Game;");
  6663. data = replaceData(data, /return cc\.DeserializeBinaryGameWL\(a,b,d\)/g, "var res = cc.DeserializeBinaryGameWL(a, b, d);window.Game = res; return res;");
  6664. data = replaceData(data, /this\.State=b;this\.VMImplementor=a;/g, "this.State=b;window.State=b;this.VMImplementor=a;");
  6665. data = replaceData(data, /__class__:Zd}\)/g, "__class__:Zd});window.OrderListItem = Zd;"); //OrdersListItemVM
  6666. data = replaceData(data, /__class__:\$c};/g, "__class__:$c};window.GameOrderPick = $c;");
  6667. addJS_Node(data);
  6668. }
  6669. catch (err) {
  6670. console.log(err);
  6671. addJS_Node(srcData);
  6672. } finally {
  6673. window.ujsReady = true;
  6674. if (window.initReady) {
  6675. window.removeEventListener('beforescriptexecute', window.listener, true);
  6676. addJS_Node(window.initScript);
  6677. }
  6678. }
  6679. }
  6680. });
  6681. }
  6682.  
  6683. function replaceData(data, regex, replace) {
  6684. var matches = data.match(regex);
  6685. matches = matches != null ? matches.length : 0;
  6686. if(matches != 1) {
  6687. throw `Could not replace in UJS. Matches: ${matches}, Regex: ${regex}`;
  6688. }
  6689. return data.replace(regex, replace);
  6690. }
  6691.  
  6692. function replaceInitJS(scriptNode) {
  6693. window.initScript = scriptNode.textContent;
  6694. window.initReady = true;
  6695. if (window.ujsReady) {
  6696. window.removeEventListener('beforescriptexecute', window.listener, true);;
  6697. addJS_Node(window.initScript);
  6698. }
  6699. }
  6700. function setupCommonGamesDataTable() {
  6701. var $$$$$ = jQuery.noConflict(true);
  6702. var dataTable = $$$(".dataTable").DataTable({
  6703. "order": [],
  6704. paging: false,
  6705. sDom: 't',
  6706. columnDefs: [{
  6707. targets: [0],
  6708. orderData: [0, 3]
  6709. }, {
  6710. targets: [1],
  6711. orderData: [1, 2, 3, 0]
  6712. }, {
  6713. targets: [2],
  6714. orderData: [2, 3, 0]
  6715. }, {
  6716. targets: [3],
  6717. orderData: [3, 2, 0]
  6718. }],
  6719. "aoColumns": [
  6720. {
  6721. "orderSequence": ["asc", "desc"]
  6722. },
  6723. {
  6724. "orderSequence": ["asc", "desc"]
  6725. },
  6726. {
  6727. "orderSequence": ["asc", "desc"]
  6728. },
  6729. {
  6730. "orderSequence": ["asc", "desc"]
  6731. },
  6732. ]
  6733. });
  6734. loadDataTableCSS();
  6735. setupCommonGamesHead2Head();
  6736. }
  6737.  
  6738. function setupCommonGamesHead2Head() {
  6739. var games = $(".dataTable tbody tr").map(function (key, row) {
  6740. return $(row).find("td").map(function (key, td) {
  6741. return $(td).text()
  6742. });
  6743. });
  6744. var games1v1 = games.filter(function (key, val) {
  6745. return val[2] == "1v1"
  6746. }).length || 0;
  6747. var wins1v1 = games.filter(function (key, val) {
  6748. return val[2] == "1v1" && val[3] == "Won";
  6749. }).length;
  6750. var gamesNotCounted = games.filter(function (key, val) {
  6751. return val[2] == "1v1" && (val[3] == "Playing" || val[3] == "Ended by vote");
  6752. }).length;
  6753. var winRate = (wins1v1 / (games1v1 - gamesNotCounted) * 100).toFixed(2);
  6754. var losses = games1v1 - wins1v1 - gamesNotCounted;
  6755. $(".dataTable").before(`
  6756. <table cellspacing="0" cellpadding="2" width="100%" class="dataTable head2head">
  6757. <thead>
  6758. <tr>
  6759. <td colspan="2">Head-To-Head</td>
  6760. </tr>
  6761. </thead>
  6762. <tbody>
  6763. <tr>
  6764. <td>1v1 Games</td>
  6765. <td>${games1v1}</td>
  6766. </tr>
  6767. <tr>
  6768. <td>1v1 Wins</td>
  6769. <td>${wins1v1}</td>
  6770. </tr>
  6771. <tr>
  6772. <td>1v1 Losses</td>
  6773. <td>${losses}</td>
  6774. </tr>
  6775. <tr>
  6776. <td>1v1 Win Rate</td>
  6777. <td>${winRate}%</td>
  6778. </tr>
  6779. </tbody>
  6780. </table>
  6781. `);
  6782. addCSS(`
  6783. .head2head {
  6784. width: 50% !important;
  6785. margin-bottom: 25px;
  6786. }
  6787. `)
  6788. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址