Guest User

Untitled

a guest
Dec 2nd, 2016
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.05 KB | None | 0 0
  1. // ==UserScript==
  2. // @name War Base Extended
  3. // @namespace vinkuun.warBaseExtended
  4. // @author Vinkuun [1791283]
  5. // @description Brings back the old war base layout, adds a filter to the war base, enables enemy tagging
  6. // @include *.torn.com/factions.php?step=your*
  7. // @include *.torn.com/profiles.php?XID=*
  8. // @version 2.4.1
  9. // @require http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. 'use strict';
  14.  
  15. this.$ = this.jQuery = jQuery.noConflict(true);
  16.  
  17. // global CSS
  18. GM_addStyle(
  19. '#vinkuun-extendedWarBasePanel { line-height: 2em }' +
  20. '#vinkuun-extendedWarBasePanel label { background-color: rgba(200, 195, 195, 1); padding: 2px; border: 1px solid #fff; border-radius: 5px }' +
  21. '#vinkuun-extendedWarBasePanel input { margin-right: 5px; vertical-align: text-bottom }' +
  22. '#vinkuun-extendedWarBasePanel input[type="number"] { vertical-align: baseline; line-height: 1.3em }' +
  23. '#vinkuun-extendedWarBasePanel { padding: 4px; }'
  24. );
  25.  
  26. var $MAIN = $('#faction-main');
  27.  
  28. // ============================================================================
  29. // --- FEATURE: War Base Layout
  30. // ============================================================================
  31. function enableWarBaseLayout() {
  32. var fragment = document.createDocumentFragment();
  33.  
  34. $('.f-war-list .desc-wrap').each(function() {
  35. var row = document.createElement('li');
  36. row.classList.add('descriptions');
  37.  
  38. $(this.children).each(function() {
  39. row.appendChild(this);
  40. });
  41.  
  42. fragment.appendChild(row);
  43. });
  44.  
  45. $('.f-war-list li:not(.clear)').remove();
  46.  
  47. $('.f-war-list').prepend(fragment);
  48.  
  49. $('.f-msg').css('margin-bottom', '10px');
  50.  
  51. GM_addStyle(
  52. '.f-war-list .descriptions { margin-top: 10px !important; border-radius: 5px !important }' +
  53. '.f-war-list .descriptions .status-desc { border-radius: 5px 5px 0 0 !important }'
  54. );
  55. }
  56.  
  57. // ============================================================================
  58. // --- FEATURE: War base filter
  59. // ============================================================================
  60. var warBaseFilter;
  61. var $filterStatusElement;
  62.  
  63. /**
  64. * Adds the filter panel to the war base extended main panel
  65. * @param {jQuery-Object} $panel Main panel
  66. */
  67. function addWarBaseFilter($panel) {
  68. var $warList = $('.f-war-list');
  69. var $statusElement = $('<p>', {text: 'The war base is currently hidden. Click the bar above to show it.', style: 'text-align: center; margin-top: 4px; font-weight: bold'}).hide();
  70.  
  71. $('.f-msg')
  72. .css('cursor', 'pointer')
  73. .on('click', function() {
  74. if (shouldHideWarBase()) {
  75. localStorage.vinkuunHideWarBase = false;
  76. $warList.show();
  77. $statusElement.hide();
  78. } else {
  79. localStorage.vinkuunHideWarBase = true;
  80. $warList.hide();
  81. $statusElement.show();
  82. }})
  83. .attr('title', 'Click to show/hide the war base')
  84. .after($statusElement);
  85.  
  86. if (shouldHideWarBase()) {
  87. $warList.hide();
  88. $statusElement.show();
  89. }
  90.  
  91. // load saved war base filter settings
  92. warBaseFilter = JSON.parse(localStorage.vinkuunWarBaseFilter || '{}');
  93. warBaseFilter.status = warBaseFilter.status || {};
  94.  
  95. $filterStatusElement = $('<span>', {text: 0});
  96.  
  97. addFilterPanel($panel);
  98.  
  99. applyFilter();
  100. }
  101.  
  102. // returns true if the layout is enabled, false if not
  103. function shouldHideWarBase() {
  104. return JSON.parse(localStorage.vinkuunHideWarBase || 'false');
  105. }
  106.  
  107. /**
  108. * Applys the filter to the war base
  109. *
  110. * @param {jquery-Object} $list
  111. * @param {Object} filter
  112. */
  113. function applyFilter() {
  114. var $list = $MAIN.find('ul.f-war-list');
  115.  
  116. // show all members
  117. $list.find('li').show();
  118.  
  119. var countFiltered = 0;
  120. var items;
  121.  
  122. if (warBaseFilter.status.okay) {
  123. items = $list.find('span:contains("Okay")');
  124. countFiltered += items.length;
  125.  
  126. items.parent().parent().hide();
  127. }
  128.  
  129. if (warBaseFilter.status.traveling) {
  130. items = $list.find('span:contains("Traveling")');
  131. countFiltered += items.length;
  132.  
  133. items.parent().parent().hide();
  134. }
  135.  
  136. if (warBaseFilter.status.federal) {
  137. items = $list.find('span:contains("Federal")');
  138. countFiltered += items.length;
  139.  
  140. items.parent().parent().hide();
  141. }
  142.  
  143. if (warBaseFilter.status.hospital) {
  144. $list.find('span:contains("Hospital")').each(function() {
  145. var $this = $(this);
  146.  
  147. var $li = $this.parent().parent();
  148.  
  149. var hospitalTimeLeft = remainingHospitalTime($li.find('.member-icons #icon15').attr('title'));
  150.  
  151. if (hospitalTimeLeft > warBaseFilter.status.hospital) {
  152. countFiltered++;
  153. $li.hide();
  154. }
  155. });
  156. }
  157.  
  158. // update the number of hidden members
  159. $filterStatusElement.text(countFiltered);
  160. }
  161.  
  162. /**
  163. * Panel to configure the filter - will be added to the main panel
  164. */
  165. function addFilterPanel($panel) {
  166. var enemiesInWarBase = $('ul.f-war-list .act-cont').length;
  167. $panel.append('<p>There are ' + enemiesInWarBase + ' enemies in the war base.</p>');
  168. $panel.append("Hide enemies who are ");
  169.  
  170. // status: traveling filter
  171. var $travelingCheckbox = $('<input>', {type: 'checkbox'})
  172. .on('change', function() {
  173. reapplyFilter({status: {traveling: this.checked}});
  174. });
  175. var $travelingElement = $('<label>', {text: 'traveling'}).prepend($travelingCheckbox);
  176. $panel.append($travelingElement).append(', ');
  177.  
  178. // status: okay filter
  179. var $okayCheckbox = $('<input>', {type: 'checkbox'})
  180. .on('change', function() {
  181. reapplyFilter({status: {okay: this.checked}});
  182. });
  183. var $okayElement = $('<label>', {text: 'okay'}).prepend($okayCheckbox);
  184. $panel.append($okayElement).append(' or ');
  185.  
  186. // status: federal filter
  187. var $federalCheckbox = $('<input>', {type: 'checkbox'})
  188. .on('change', function() {
  189. reapplyFilter({status: {federal: this.checked}});
  190. });
  191. var $federalElement = $('<label>', {text: 'in federal prison'}).prepend($federalCheckbox);
  192. $panel.append($federalElement).append(', ');
  193.  
  194. // status: hospital filter
  195. var $hospitalTextfield = $('<input>', {type: 'number', style: 'width: 50px'})
  196. .on('change', function() {
  197. if (isNaN(this.value)) {
  198. reapplyFilter({status: {hospital: false}});
  199. } else {
  200. reapplyFilter({status: {hospital: parseInt(this.value, 10)}});
  201. }
  202. });
  203. var $hospitalElement = $('<label>', {text: 'in hospital for more than '})
  204. .append($hospitalTextfield)
  205. .append(' minutes');
  206. $panel.append($hospitalElement);
  207.  
  208. $panel.append(' (').append($filterStatusElement).append(' enemies are hidden by the filter.)');
  209.  
  210. // set the states of the elements according to the saved filter
  211. $travelingCheckbox[0].checked = warBaseFilter.status.traveling || false;
  212. $okayCheckbox[0].checked = warBaseFilter.status.okay || false;
  213. $federalCheckbox[0].checked = warBaseFilter.status.federal || false;
  214. $hospitalTextfield.val(warBaseFilter.status.hospital || '');
  215. }
  216.  
  217. /**
  218. * Reapplies the war base filter - current settings will be merged with the new filter settings
  219. * @param {Object} newFilter new filter settings
  220. */
  221. function reapplyFilter(newFilter) {
  222. $.extend(true, warBaseFilter, newFilter);
  223.  
  224. localStorage.vinkuunWarBaseFilter = JSON.stringify(warBaseFilter);
  225.  
  226. applyFilter(warBaseFilter);
  227. }
  228.  
  229. /**
  230. * Returns the remaining hospital time in minutes
  231. *
  232. * @param {String} text The tooltip text of the hospital icon
  233. * @return {Integer} time in minutes
  234. */
  235. function remainingHospitalTime(text) {
  236. var match = text.match(/data-time='(\d+)'/);
  237.  
  238. return match[1] / 60;
  239. }
  240.  
  241. // ============================================================================
  242. // --- FEATURE: Enemy tagging
  243. // ============================================================================
  244.  
  245. var TAGS = {
  246. tbd: {text: 'Difficulty', color: 'inherit'},
  247. easy: {text: 'Easy', color:'rgba(161, 248, 161, 1)'},
  248. medium: {text: 'Medium', color:'rgba(231, 231, 104, 1)'},
  249. impossible: {text: 'Impossible', color:'rgba(242, 140, 140, 1)'}
  250. };
  251.  
  252. var enemyTags = JSON.parse(localStorage.vinkuunEnemyTags || '{}');
  253.  
  254. function addEnemyTagging() {
  255. GM_addStyle(
  256. 'select.vinkuun-enemeyDifficulty { font-size: 12px; vertical-align: text-bottom }' +
  257. '.member-list li div.status, .member-list li div.act-cont { font-weight: bold }'
  258. );
  259.  
  260. var $list = $MAIN.find('.member-list > li').each(function() {
  261. var $this = $(this);
  262.  
  263. var id = $this.find('.user.name').eq(0).attr('href').match(/XID=(\d+)/)[1];
  264.  
  265. $this.find('.member-icons').prepend(createDropdown($this, id));
  266. });
  267. }
  268.  
  269. function createDropdown($li, id) {
  270. var $dropdown = $('<select>', {'class': 'vinkuun-enemeyDifficulty'}).on('change', function() {
  271. enemyTags[id] = $(this).val();
  272.  
  273. localStorage.vinkuunEnemyTags = JSON.stringify(enemyTags);
  274.  
  275. updateColor($li, id);
  276. });
  277.  
  278. $.each(TAGS, function(key, value) {
  279. var $el = $('<option>', {value: key, text: value.text});
  280.  
  281. if (enemyTags[id] && key === enemyTags[id]) {
  282. $el.attr('selected', 'selected');
  283. }
  284.  
  285. $dropdown.append($el);
  286. });
  287.  
  288. updateColor($li, id);
  289.  
  290. return $dropdown;
  291. }
  292.  
  293. function updateColor($li, id) {
  294. if (enemyTags[id] && TAGS[enemyTags[id]]) {
  295. $li.css('background-color', TAGS[enemyTags[id]].color);
  296. }
  297. }
  298.  
  299. // ============================================================================
  300. // --- MAIN
  301. // ============================================================================
  302.  
  303. /**
  304. * Shows/Hides the control panel according to the current tab
  305. * @param {jQuery-Object} $element control panel
  306. */
  307. function addUrlChangeCallback($element) {
  308. var urlChangeCallback = function () {
  309. if (window.location.hash === '#/tab=main' || window.location.hash === '') {
  310. $element.show();
  311. } else {
  312. $element.hide();
  313. }
  314. };
  315.  
  316. // call it one time to show/hide the panel after the page has been loaded
  317. urlChangeCallback();
  318.  
  319. // listen to a hash change
  320. window.onhashchange = urlChangeCallback;
  321. }
  322.  
  323. /**
  324. * Initialises the script's features
  325. */
  326. function init() {
  327. var $warBaseExtendedPanel = $('#vinkuun-extendedWarBasePanel');
  328.  
  329. if ($warBaseExtendedPanel.length !== 0) {
  330. $warBaseExtendedPanel.empty();
  331. } else {
  332. $warBaseExtendedPanel = $('<div>', { id:'vinkuun-extendedWarBasePanel' });
  333. $MAIN.before($warBaseExtendedPanel);
  334. }
  335.  
  336. var $title = $('<div>', { 'class': 'title-black m-top10 title-toggle tablet active top-round', text: 'War Base Extended' });
  337. $MAIN.before($title);
  338.  
  339. var $panel = $('<div>', { 'class': 'cont-gray10 bottom-round cont-toggle' });
  340. $MAIN.before($panel);
  341.  
  342. $warBaseExtendedPanel.append($title).append($panel);
  343.  
  344. enableWarBaseLayout();
  345. addWarBaseFilter($panel);
  346. addEnemyTagging();
  347.  
  348. addUrlChangeCallback($warBaseExtendedPanel);
  349. }
  350.  
  351. function initWarBase() {
  352. try {
  353. // observer used to apply the filter after the war base was loaded via ajax
  354. var observer = new MutationObserver(function(mutations) {
  355. mutations.forEach(function(mutation) {
  356. // The main content is being added to the div
  357. for (var i = 0; i < mutation.addedNodes.length; i++) {
  358. if (mutation.addedNodes[i].className === 'faction-respect-wars-wp') {
  359. init();
  360. break;
  361. }
  362. }
  363. });
  364. });
  365.  
  366. // start listening for changes
  367. var observerTarget = $MAIN[0];
  368. var observerConfig = { attributes: false, childList: true, characterData: false };
  369. observer.observe(observerTarget, observerConfig);
  370. } catch (err) {
  371. console.log(err);
  372. }
  373. }
  374.  
  375. function initProfileTargetIndicator() {
  376. var userId = location.search.split('=')[1];
  377.  
  378. var attackButton = $('li.action-icon-attack a');
  379.  
  380. if (enemyTags[userId]) {
  381. attackButton.css({
  382. 'background-color': TAGS[enemyTags[userId]].color || 'rgb(132, 129, 129)',
  383. 'border-radius': '5px'
  384. });
  385.  
  386. attackButton.attr('title', 'Difficulty: ' + enemyTags[userId]);
  387. }
  388. }
  389.  
  390. if (location.href.indexOf('torn.com/profiles.php?XID=') !== -1) {
  391. initProfileTargetIndicator();
  392. } else if (location.href.indexOf('torn.com/factions.php') !== -1) {
  393. initWarBase();
  394. }
Add Comment
Please, Sign In to add comment