GameCATs Highlighting

Highlights stuff, I dunno.

  1. // ==UserScript==
  2. // @name GameCATs Highlighting
  3. // @version 2.1.0
  4. // @author Metallia
  5. // @namespace Cats
  6. // @description Highlights stuff, I dunno.
  7. // @include https://www.gamefaqs.com/*
  8. // @include https://gamefaqs.gamespot.com/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_deleteValue
  12. // @noframes
  13. // ==/UserScript==
  14.  
  15. // css guys, look for ".gamecats-highlight" for anything I've added a background colour to, or ".gamecats-text" for text colour changes, or just the "friend" class GameFAQs itself uses for their own highlighting.
  16. // Also, to be more specific:
  17. // .gamecats-highlight-message-tr
  18. // .gamecats-highlight-message-td
  19. // .gamecats-highlight-topic-tr
  20. // .gamecats-highlight-topic-td
  21. // .gamecats-text-tr
  22. // .gamecats-text-td
  23. // .gamecats-text-a
  24. // .gamecats-autocontrast-black
  25. // .gamecats-autocontrast-white
  26.  
  27. // First run check, fill in some settings. Also fill in one list if they try to save with none. >_>
  28. if (!GM_getValue("numberOfLists") || GM_getValue("numberOfLists") == 0) {
  29. GM_setValue("numberOfLists",1);
  30. GM_setValue("useColouredCustomCSS",false);
  31. GM_setValue("caseInsensitive",true);
  32. GM_setValue("styleGroupAsTag",false);
  33. GM_setValue("settingsLinkLocation",2);
  34. GM_setValue("allowRightclickHijacks",true);
  35. GM_setValue("Main Settings","Script Author|Metallia|#B266FF|auto|true,false,true,false,false,true,false,false,false,false,false,false,false,false,false");
  36. GM_setValue("version","2.1.0");
  37. }
  38.  
  39. // Attach a link to the settings page on GameFAQs.
  40. var userSubnav = document.getElementsByClassName("top_user_subnav");
  41. if (userSubnav[0] != null) {
  42. if (GM_getValue("settingsLinkLocation","unset") === 0 || GM_getValue("settingsLinkLocation","unset") === 2) {
  43.  
  44. var settingsListItem = document.createElement('li');
  45. var settingsLink = document.createElement('a');
  46. settingsLink.setAttribute("href","#HighlightSettings");
  47. settingsLink.addEventListener('click',function() {prepSettings();},true);
  48. settingsLink.textContent = "GameCATs";
  49.  
  50. userSubnav[0].childNodes[1].insertBefore(settingsListItem,userSubnav[0].childNodes[1].childNodes[0]);
  51. settingsListItem.appendChild(settingsLink);
  52. }
  53. }
  54. if ((document.location.href.match(/(^[^#]*)/)[0] === "https://www.gamefaqs.com/user") || (document.location.href.match(/(^[^#]*)/)[0] === "https://gamefaqs.gamespot.com/user")) {
  55. if (GM_getValue("settingsLinkLocation","unset") === 1 || GM_getValue("settingsLinkLocation","unset") === 2) {
  56. var myAccountTable = document.getElementsByTagName("tbody")[2];
  57. var settingsTR = document.createElement('tr');
  58. var settingsTD = document.createElement('td');
  59. settingsTD.setAttribute("colspan","2");
  60. var settingsLink = document.createElement('a');
  61. settingsLink.setAttribute("href","#HighlightSettings");
  62. settingsLink.addEventListener('click',function() {prepSettings();},true);
  63. settingsLink.textContent = "GameCATs";
  64. myAccountTable.appendChild(settingsTR);
  65. settingsTR.appendChild(settingsTD);
  66. settingsTD.appendChild(settingsLink);
  67. }
  68. }
  69.  
  70. var version = GM_getValue("version").split(".");
  71. var theme = document.getElementsByTagName("body")[0].getAttribute("class");
  72.  
  73. // Settings to get filled in by getSettings()
  74. var storedNumberOfLists = new Array();
  75. var storedListNames = new Array();
  76. var storedUsernames = new Array();
  77. var storedHighlightColours = new Array();
  78. var storedHighlightTextColours = new Array();
  79. var storedActionHighlightTopic = new Array();
  80. var storedActionIgnoreTopic = new Array();
  81. var storedActionHighlightPost = new Array();
  82. var storedActionIgnorePost = new Array();
  83. var storedActionTagTopic = new Array();
  84. var storedActionTagPost = new Array();
  85. var storedActionHighlightTopicContent = new Array();
  86. var storedActionIgnoreTopicContent = new Array();
  87. var storedActionHighlightPostContent = new Array();
  88. var storedActionIgnorePostContent = new Array();
  89. var storedActionAllowStacking = new Array();
  90. var storedActionHighlightAdmin = new Array();
  91. var storedActionHighlightMod = new Array();
  92. var storedActionHighlightVIP = new Array();
  93. var storedActionHighlightTC = new Array();
  94. var storedCaseInsensitive = new Array();
  95. var storedUseColouredCustomCSSSetting = new Array();
  96. var storedStyleGroupAsTagSetting = new Array();
  97. var storedAllowRightclickHijacksSetting = new Array();
  98.  
  99. // Highlight functions
  100.  
  101. function compareVersion (testVersion,exact) {
  102. testVersion = testVersion.split(".");
  103. if (exact) {
  104. return ((testVersion[0] == version[0]) && (testVersion[1] == version[1]) && (testVersion[2] == version[2]));
  105. } else {
  106. if (version[0] < testVersion[0]) {
  107. return true;
  108. } else if (version[0] == testVersion[0]) {
  109. if (version[1] < testVersion[1]) {
  110. return true;
  111. } else if (version[1] == testVersion[1]) {
  112. if (version[2] < testVersion[2]) {
  113. return true;
  114. } else {
  115. return false;
  116. }
  117. } else {
  118. return false;
  119. }
  120. } else {
  121. return false;
  122. }
  123. }
  124. }
  125.  
  126. function getSettings () {
  127. storedNumberOfLists = GM_getValue("numberOfLists");
  128. var allOfTheThings = GM_getValue("Main Settings");
  129. var fullList = allOfTheThings.split("^");
  130. var splitListItems = new Array();
  131. var usernames = new Array();
  132. var splitActions = new Array();
  133.  
  134.  
  135. for (var i = 0; i < storedNumberOfLists; i++) {
  136. splitListItems = fullList[i].split("|");
  137. splitActions[i] = splitListItems[4].split(",");
  138.  
  139. storedListNames[i] = splitListItems[0];
  140. storedUsernames[i] = splitListItems[1].split(",");
  141. storedHighlightColours[i] = splitListItems[2];
  142. storedHighlightTextColours[i] = splitListItems[3];
  143. // These look kinda funky, but I'm trading in the stored "true" and "false" strings for actual booleans.
  144. storedActionHighlightTopic[i] = (splitActions[i][0] == "true");
  145. storedActionIgnoreTopic[i] = (splitActions[i][1] == "true");
  146. storedActionHighlightPost[i] = (splitActions[i][2] == "true");
  147. storedActionIgnorePost[i] = (splitActions[i][3] == "true");
  148. storedActionTagTopic[i] = (splitActions[i][4] == "true");
  149. storedActionTagPost[i] = (splitActions[i][5] == "true");
  150. storedActionHighlightTopicContent[i] = (splitActions[i][6] == "true");
  151. storedActionIgnoreTopicContent[i] = (splitActions[i][7] == "true");
  152. storedActionHighlightPostContent[i] = (splitActions[i][8] == "true");
  153. storedActionIgnorePostContent[i] = (splitActions[i][9] == "true");
  154. storedActionAllowStacking[i] = (splitActions[i][10] == "true");
  155. storedActionHighlightAdmin[i] = (splitActions[i][11] == "true");
  156. storedActionHighlightMod[i] = (splitActions[i][12] == "true");
  157. storedActionHighlightVIP[i] = (splitActions[i][13] == "true");
  158. storedActionHighlightTC[i] = (splitActions[i][14] == "true");
  159. }
  160.  
  161. storedCaseInsensitive = GM_getValue("caseInsensitive");
  162. storedUseColouredCustomCSSSetting = GM_getValue("useColouredCustomCSS");
  163. storedStyleGroupAsTagSetting = GM_getValue("styleGroupAsTag");
  164. storedAllowRightclickHijacksSetting = GM_getValue("allowRightclickHijacks");
  165. }
  166.  
  167. if (compareVersion("0.8.0")) {
  168. GM_deleteValue("useChromeSettings");
  169. }
  170. if (compareVersion("0.9.0")) {
  171. GM_deleteValue("respectTags");
  172. }
  173. if (compareVersion("1.2.3")) {
  174. GM_setValue("settingsLinkLocation",2);
  175. }
  176. if (compareVersion("2.0.22")) {
  177. GM_setValue("allowRightclickHijacks",true);
  178. }
  179.  
  180. getSettings();
  181.  
  182. GM_setValue("version","2.1.0");
  183.  
  184. // The settings page save button and right click menu prime the data for storage first, then recall this function with a new origin to actually store it.
  185. function saveSettings (origin,username,listIndex,addOrRemove) {
  186. var smashedUsernames;
  187. var smashedActions;
  188. var smashedFullList = new Array();
  189. var smashedAllOfTheThings = new Array();
  190.  
  191. if (origin == "import") {
  192. var importField = document.getElementById("exportImportField");
  193. var importString = importField.value;
  194.  
  195. if (importString.split("|").length <= 3) {
  196. if (!confirm("This data seems malformed and may break your settings.\nImport data anyway?")) {
  197. throw "Abort settings import.";
  198. }
  199. }
  200.  
  201. GM_setValue("Main Settings",importString);
  202. GM_setValue("numberOfLists",importString.split("^").length);
  203. }
  204.  
  205. if (origin == "internal") {
  206. for (var i = 0; i < storedNumberOfLists; i++) {
  207. smashedUsernames = storedUsernames[i].join(",");
  208. smashedActions = storedActionHighlightTopic[i]+","+storedActionIgnoreTopic[i]+","+storedActionHighlightPost[i]+","+storedActionIgnorePost[i]+","+storedActionTagTopic[i]+","+storedActionTagPost[i]+","+storedActionHighlightTopicContent[i]+","+storedActionIgnoreTopicContent[i]+","+storedActionHighlightPostContent[i]+","+storedActionIgnorePostContent[i]+","+storedActionAllowStacking[i]+","+storedActionHighlightAdmin[i]+","+storedActionHighlightMod[i]+","+storedActionHighlightVIP[i]+","+storedActionHighlightTC[i];
  209. smashedFullList[i] = storedListNames[i]+"|"+smashedUsernames+"|"+storedHighlightColours[i]+"|"+storedHighlightTextColours[i]+"|"+smashedActions;
  210. }
  211. smashedAllOfTheThings = smashedFullList.join("^");
  212. GM_setValue("Main Settings",smashedAllOfTheThings);
  213.  
  214. var importField = document.getElementById("exportImportField");
  215. if (importField){
  216. importField.setAttribute('value',smashedAllOfTheThings);
  217. }
  218. }
  219.  
  220. if (origin == "rightclickmenu") {
  221. if (addOrRemove == "add") {
  222. storedUsernames[listIndex][storedUsernames[listIndex].length] = username;
  223.  
  224. }
  225. if (addOrRemove == "remove") {
  226. storedUsernames[listIndex].splice(storedUsernames[listIndex].indexOf(username),1);
  227. }
  228. saveSettings("internal");
  229. }
  230.  
  231. if (origin == "settingspage") {
  232. var lists = document.evaluate('//div', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  233. var actionLists = document.evaluate('//input[@type="checkbox"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  234.  
  235. var realLists = 0;
  236. for (var i = 0; i < lists.snapshotLength; i++) {
  237. if (lists.snapshotItem(i).getAttribute("class") !== "container") {
  238. continue; // Fuck you, Chrome >_>
  239. }
  240. storedListNames[realLists] = lists.snapshotItem(i).getElementsByClassName("listnameFields")[0].value;
  241. storedHighlightColours[realLists] = lists.snapshotItem(i).getElementsByClassName("colourFields")[0].value;
  242. storedHighlightTextColours[realLists] = lists.snapshotItem(i).getElementsByClassName("textColourFields")[0].value;
  243. storedUsernames[realLists] = lists.snapshotItem(i).getElementsByClassName("usernameFields")[0].value.replace(/, /g,",").split(",");
  244. storedActionHighlightTopic[realLists] = actionLists.snapshotItem(realLists*15).checked;
  245. storedActionIgnoreTopic[realLists] = actionLists.snapshotItem(realLists*15+1).checked;
  246. storedActionHighlightPost[realLists] = actionLists.snapshotItem(realLists*15+2).checked;
  247. storedActionIgnorePost[realLists] = actionLists.snapshotItem(realLists*15+3).checked;
  248. storedActionTagTopic[realLists] = actionLists.snapshotItem(realLists*15+4).checked;
  249. storedActionTagPost[realLists] = actionLists.snapshotItem(realLists*15+5).checked;
  250. storedActionHighlightTopicContent[realLists] = actionLists.snapshotItem(realLists*15+6).checked;
  251. storedActionIgnoreTopicContent[realLists] = actionLists.snapshotItem(realLists*15+7).checked;
  252. storedActionHighlightPostContent[realLists] = actionLists.snapshotItem(realLists*15+8).checked;
  253. storedActionIgnorePostContent[realLists] = actionLists.snapshotItem(realLists*15+9).checked;
  254. storedActionAllowStacking[realLists] = actionLists.snapshotItem(realLists*15+10).checked;
  255. storedActionHighlightAdmin[realLists] = actionLists.snapshotItem(realLists*15+11).checked;
  256. storedActionHighlightMod[realLists] = actionLists.snapshotItem(realLists*15+12).checked;
  257. storedActionHighlightVIP[realLists] = actionLists.snapshotItem(realLists*15+13).checked;
  258. storedActionHighlightTC[realLists] = actionLists.snapshotItem(realLists*15+14).checked;
  259.  
  260. realLists++;
  261. }
  262.  
  263. GM_setValue("numberOfLists",realLists);
  264.  
  265. // Straggler settings not part of a loop
  266. GM_setValue("caseInsensitive",document.getElementById("caseInsensitiveToggle").checked);
  267. GM_setValue("useColouredCustomCSS",document.getElementById("customCSSToggle").checked);
  268. GM_setValue("settingsLinkLocation",parseInt(document.getElementById("settingsLinkLocation").value));
  269. GM_setValue("styleGroupAsTag",document.getElementById("styleGroupAsTagToggle").checked);
  270. GM_setValue("allowRightclickHijacks",document.getElementById("allowRightclickHijacksToggle").checked);
  271.  
  272. saveSettings("internal");
  273. }
  274. }
  275.  
  276. function makeInsensitive (voodoo) {
  277. if (storedCaseInsensitive) {
  278. return voodoo.toLowerCase();
  279. } else {
  280. return voodoo;
  281. }
  282. }
  283.  
  284. // Always returns in rgba, prefilling an alpha of '1' if none was present.
  285. // Accepts #RRGGBB, rgba(r,g,b,a), or rgb(r,g,b).
  286. function decimalColour (colour, returnAs) {
  287. // The usual #RRGGBB you expect to deal with from user input.
  288. if (colour.substring(0,1) == "#") {
  289. if (returnAs === "style") {
  290. return ("rgba("+parseInt(colour.substring(1,3),16)+","+parseInt(colour.substring(3,5),16)+","+parseInt(colour.substring(5,7),16)+",1)");
  291. } else if (returnAs === "testvalue") {
  292. return true;
  293. } else {
  294. return [parseInt(colour.substring(1,3),16),parseInt(colour.substring(3,5),16),parseInt(colour.substring(5,7),16),1];
  295. }
  296. } else {
  297. // And now for when rgba(r,g,b,a) and rgb(r,g,b) decide to show up, like when pulling the colour directly out of the DOM. >_>
  298. if (colour.substring(0,4) == "rgba") {
  299. var numbersOnly = colour.substring(5,colour.length-1).replace(/, /g,",").split(",");
  300. if (returnAs === "style") {
  301. return ("rgba("+numbersOnly[0]+","+numbersOnly[1]+","+numbersOnly[2]+","+numbersOnly[3]+")");
  302. } else if (returnAs === "testvalue") {
  303. return true;
  304. } else {
  305. return numbersOnly;
  306. }
  307. } else if (colour.substring(0,4) == "rgb(") {
  308. var numbersOnly = colour.substring(4,colour.length-1).replace(/, /g,",").split(",");
  309. if (returnAs === "style") {
  310. return ("rgba("+numbersOnly[0]+","+numbersOnly[1]+","+numbersOnly[2]+",1)");
  311. } else if (returnAs === "testvalue") {
  312. return true;
  313. } else {
  314. numbersOnly[3] = 1;
  315. return numbersOnly;
  316. }
  317. } else if (returnAs === "testvalue") {
  318. return false;
  319. }
  320. }
  321. }
  322.  
  323. function autoContrast (pageType,colour,usernameNode) {
  324. var backgroundColour = decimalColour(colour);
  325.  
  326. if (!decimalColour(colour,"testvalue")) {
  327. return false;
  328. }
  329.  
  330. //todo: Check new site colours, update switch values. These are probably wrong.
  331. switch (theme) {
  332. case "red": var themeColour = decimalColour("#7E2525"); break;
  333. case "green": var themeColour = decimalColour("#669E2E"); break;
  334. case "orange": var themeColour = decimalColour("#834121"); break;
  335. case "purple": var themeColour = decimalColour("#330066"); break;
  336. case "cloudy": var themeColour = decimalColour("#192457"); break;
  337. case "sepia": var themeColour = decimalColour("#6C4013"); break;
  338. case "dark-blue": var themeColour = decimalColour("#A1AFF7"); break;
  339. case "dark-red": var themeColour = decimalColour("#F9B8B8"); break;
  340. case "dark-green": var themeColour = decimalColour("#CCF7A1"); break;
  341. case "dark-orange": var themeColour = decimalColour("#FFCCB3"); break;
  342. case "dark-purple": var themeColour = decimalColour("#E5CCFF"); break;
  343. case "grayscale": var themeColour = decimalColour("#404040"); break;
  344. case "cottoncandy": var themeColour = decimalColour("#FF0000"); break;
  345. default: var themeColour = decimalColour("#3449B2");
  346. }
  347.  
  348. if (storedUseColouredCustomCSSSetting) {
  349. themeColour = decimalColour(window.getComputedStyle(usernameNode).getPropertyValue("color"));
  350. }
  351.  
  352. // http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
  353. // http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
  354. var lumiCustom = (0.2126*backgroundColour[0] + 0.7152*backgroundColour[1] + 0.0722*backgroundColour[2])/256;
  355. var lumiDefault =(0.2126*themeColour[0] + 0.7152*themeColour[1] + 0.0722*themeColour[2])/256;
  356.  
  357. if (lumiCustom >= lumiDefault) {
  358. var contrastRatio = (lumiCustom + 0.05) / (lumiDefault + 0.05);
  359. } else {
  360. var contrastRatio = (lumiDefault + 0.05) / (lumiCustom + 0.05);
  361. }
  362.  
  363. // If the contrast is awful, we need to replace the text colour.
  364. var themeBrightness = ((themeColour[0]*299) + (themeColour[1]*587) + (themeColour[2]*114)) / 255000;
  365.  
  366. if ((contrastRatio <= 3.5) || ((contrastRatio > 3.5) && (lumiCustom <= 0.03) && (themeBrightness <= 0.5))) {
  367. // http://stackoverflow.com/a/9664560
  368. var brightness = ((backgroundColour[0]*299) + (backgroundColour[1]*587) + (backgroundColour[2]*114)) / 255000;
  369. // First return is "do we even need to attach styles to text?", second is link colour, and third is plain text.
  370. // I make links "brighter" than the plain text it's next to using the alpha channel.
  371. if (brightness >= 0.5) {
  372. return([true,"rgba(0,0,0,0.8)","rgba(0,0,0,1)","gamecats-autocontrast-black"]);
  373. } else {
  374. return([true,"rgba(256,256,256,1)","rgba(256,256,256,0.8)","gamecats-autocontrast-white"]);
  375. }
  376. } else {
  377. return([false]);
  378. }
  379. }
  380.  
  381. function textHighlight (pageType,tr,usernameNode,colour,textColour,currentStyles) {
  382. // Don't do anything if the field was left blank.
  383. if (textColour !== "") {
  384. if (pageType == "messagelist") {
  385. var postInfo = tr.childNodes[0].childNodes[0];
  386. } else {
  387. var postInfo = tr;
  388. }
  389. var plainTextColour = textColour;
  390. var postInfoLinks = postInfo.getElementsByTagName("a");
  391. var postInfoSpans = postInfo.getElementsByTagName("span");
  392. var catchResults = new Array();
  393.  
  394. // Check for auto and break out early if we decide we don't need it.
  395. if (textColour == "auto" || textColour == "automatic" || textColour == "automagic" ) {
  396. catchResults = autoContrast(pageType,colour,usernameNode);
  397. if (catchResults[0]) {
  398. textColour = catchResults[1];
  399. plainTextColour = catchResults[2];
  400. } else {
  401. return(false);
  402. }
  403. }
  404.  
  405. postInfo.setAttribute("class",(postInfo.getAttribute("class")||"")+" gamecats-text gamecats-text-tr "+(catchResults[3]||""));
  406.  
  407. // If people are stacking styles, we need to replace text colours without blowing up the existing CSS.
  408. var isStyled = false;
  409. for (var i = 0; i < currentStyles.length; i++) {
  410. if (currentStyles[i].indexOf(" color:") != -1) {
  411. isStyled = true;
  412. currentStyles[i] = " color:"+plainTextColour+"!important;";
  413. postInfo.setAttribute("style",currentStyles.join(";"));
  414. break;
  415. }
  416. }
  417. // And if there was no text colour already, just toss one on at the end.
  418. if (!isStyled) {
  419. postInfo.setAttribute("style",(postInfo.getAttribute("style")||"")+" color:"+plainTextColour+"!important;");
  420. }
  421.  
  422. for (var i = 0; i < postInfoLinks.length; i++) {
  423. if ((postInfoLinks[i].parentNode.nodeName != "LI") && (postInfoLinks[i].parentNode.nodeName != "FORM")) {
  424. postInfoLinks[i].setAttribute("class",(postInfoLinks[i].getAttribute("class")||"")+" gamecats-text gamecats-text-a "+(catchResults[3]||""));
  425. postInfoLinks[i].setAttribute("style","color:"+textColour+"!important;");
  426. }
  427. }
  428. for (var i = 0; i < postInfoSpans.length; i++) {
  429. if ((postInfoSpans[i].getAttribute("class")||"").indexOf("tag") == -1) {
  430. postInfoSpans[i].setAttribute("class",(postInfoSpans[i].getAttribute("class")||"")+" gamecats-text gamecats-text-span "+(catchResults[3]||""));
  431. postInfoSpans[i].setAttribute("style","color:"+textColour+"!important;");
  432. }
  433. }
  434. }
  435. }
  436.  
  437. function highlight (mode,pageType,usernameNode,listName,colour,textColour,topicHighlight,topicIgnore,messageHighlight,messageIgnore,topicListName,messageListName,topicContentHighlight,topicContentIgnore,postContentHighlight,postContentIgnore,allowStacking) {
  438. if (decimalColour(colour,"testvalue")) {
  439. var appendType = "background-color:";
  440. } else {
  441. var appendType = "background-image:";
  442. }
  443.  
  444. if (pageType == "topiclist") {
  445. var tr = usernameNode.parentNode.parentNode;
  446. if (usernameNode.parentNode.nodeName == "SPAN") { // Stickies still don't have spans
  447. tr = tr.parentNode;
  448. }
  449. var td = tr.childNodes;
  450.  
  451. if (((tr.getAttribute("class").indexOf("gamecats-highlight") == -1) || (allowStacking)) && ((topicHighlight && !topicIgnore) || (mode == "contentMatch" && topicContentHighlight && !topicContentIgnore))) {
  452. var currentStyles = (tr.getAttribute("style")||"").split(";");
  453. var isStyled = false;
  454.  
  455. if (allowStacking) {
  456. for (var i = 0; i < currentStyles.length; i++) {
  457. if (currentStyles[i].indexOf(appendType) != -1) {
  458. isStyled = true;
  459. currentStyles[i] = appendType+colour+", "+currentStyles[i].substring(17);
  460. tr.setAttribute("style",currentStyles.join(";"));
  461. break;
  462. }
  463. }
  464. }
  465. if (!isStyled) {
  466. tr.setAttribute("style",(tr.getAttribute("style")||"")+appendType+colour+";");
  467. currentStyles = (tr.getAttribute("style")||"").split(";");
  468. }
  469. tr.setAttribute("class",(tr.getAttribute("class")||"")+" friend gamecats-highlight gamecats-highlight-topic-tr")
  470. textHighlight(pageType,tr,usernameNode,colour,textColour,currentStyles);
  471. for (var i = 0; i < td.length; i++) {
  472. td[i].setAttribute("style","background-color: transparent; background-image: none;");
  473. td[i].setAttribute("class",(td[i].getAttribute("class")||"")+" friend gamecats-highlight gamecats-highlight-topic-td")
  474. }
  475. }
  476.  
  477. if (topicListName) {
  478. if (usernameNode.parentNode.nodeName == "SPAN") { // Stickies don't have spans
  479. var existingList = usernameNode.parentNode.nextSibling;
  480. if (existingList) {
  481. existingList.textContent = " "+listName+existingList.textContent;
  482. } else {
  483. var newList = usernameNode.parentNode.parentNode.appendChild(document.createTextNode(" "+listName));
  484. }
  485. } else {
  486. var existingList = usernameNode.nextSibling;
  487. if (existingList) {
  488. existingList.textContent = " "+listName+existingList.textContent;
  489. } else {
  490. var newList = usernameNode.parentNode.appendChild(document.createTextNode(" "+listName));
  491. }
  492. }
  493.  
  494. }
  495.  
  496. if (((mode == "usernameMatch" || mode == "tagMatch") && topicIgnore) || (mode == "contentMatch" && topicContentIgnore)) {
  497. if (tr.parentNode) {
  498. tr.parentNode.removeChild(tr);
  499. }
  500. }
  501. }
  502.  
  503. if (pageType == "messagelist") {
  504. // Adding group names
  505. if (messageListName) {
  506. var existingList = usernameNode.parentNode.nextSibling;
  507. if (!storedStyleGroupAsTagSetting) {
  508. if (existingList) {
  509. existingList.textContent = " "+listName+existingList.textContent;
  510. } else {
  511. var newListSpan = usernameNode.parentNode.parentNode.appendChild(document.createElement("span"));
  512. newListSpan.setAttribute("class","user_info");
  513. var newList = newListSpan.appendChild(document.createTextNode(" "+listName));
  514. }
  515. } else {
  516. var newTagSpan = usernameNode.parentNode.parentNode.appendChild(document.createElement("span"));
  517. var whitespace = usernameNode.parentNode.parentNode.appendChild(document.createTextNode(" "));
  518. newTagSpan.textContent = listName;
  519. newTagSpan.setAttribute("class","tag");
  520. }
  521. }
  522.  
  523. var tr = usernameNode.parentNode.parentNode.parentNode.parentNode.parentNode;
  524. var div = tr.childNodes[0].childNodes[0];
  525.  
  526. if ((((tr.getAttribute("class")||"").indexOf("gamecats-highlight") == -1) || (allowStacking)) && (((mode == "usernameMatch" || mode == "tagMatch") && messageHighlight && !messageIgnore) || (mode == "contentMatch" && postContentHighlight && !postContentIgnore))) {
  527. var currentStyles = (div.getAttribute("style")||"").split(";");
  528. var isStyled = false;
  529.  
  530. if (allowStacking) {
  531. for (var i = 0; i < currentStyles.length; i++) {
  532. if (currentStyles[i].indexOf(appendType) != -1) {
  533. isStyled = true;
  534. currentStyles[i] = appendType+colour+", "+currentStyles[i].substring(17);
  535. div.setAttribute("style",currentStyles.join(";"));
  536. break;
  537. }
  538. }
  539. }
  540.  
  541. if (!isStyled) {
  542. div.setAttribute("style",(div.getAttribute("style")||"")+appendType+colour+";");
  543. currentStyles = (tr.getAttribute("style")||"").split(";");
  544. }
  545. tr.setAttribute("class",(tr.getAttribute("class")||"")+" friend gamecats-highlight gamecats-highlight-message-tr");
  546. div.setAttribute("class",(div.getAttribute("class")||"")+" friend gamecats-highlight gamecats-highlight-message-div");
  547.  
  548. textHighlight(pageType,tr,usernameNode,colour,textColour,currentStyles);
  549. }
  550.  
  551. if (((mode == "usernameMatch" || mode == "tagMatch") && messageIgnore) || (mode == "contentMatch" && postContentIgnore)) {
  552. if (tr.parentNode) {
  553. tr.parentNode.removeChild(tr);
  554. }
  555. }
  556. }
  557. }
  558.  
  559. // Finding usernames, looking for tags, etc
  560. var pageType;
  561. var authorTDs;
  562. var titlePostContent;
  563. var userTagsContent;
  564. var topicList = document.evaluate('//table[contains(@class,"board topics tlist newbeta")]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  565. if (topicList !== null) {
  566. authorTDs = document.evaluate('//td[contains(@class,"tauthor")]//a', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  567. pageType = "topiclist";
  568. }
  569.  
  570. var messageList = document.evaluate('//table[contains(@class,"board message")]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  571. if (messageList !== null) {
  572. authorTDs = document.evaluate('//td[contains(@class,"msg")]//a[@class="name menu_toggle"]//b', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  573. pageType = "messagelist";
  574. }
  575.  
  576. if (topicList !== null || messageList !== null) {
  577. for (var k = 0; k < authorTDs.snapshotLength; k++) {
  578. authorTDs.snapshotItem(k).isAdmin = false;
  579. authorTDs.snapshotItem(k).isMod = false;
  580. authorTDs.snapshotItem(k).isVIP = false;
  581. authorTDs.snapshotItem(k).isTC = false;
  582.  
  583. // Content highlight setup
  584. titlePostContent = authorTDs.snapshotItem(k);
  585. while (titlePostContent.nodeName != "TR") {
  586. titlePostContent = titlePostContent.parentNode;
  587. }
  588. if (pageType == "topiclist") {
  589. titlePostContent = titlePostContent.getElementsByTagName("td")[1].textContent;
  590. } else {
  591. titlePostContent = titlePostContent.childNodes[0].childNodes[1];
  592. var embedStrings = ""; // Embeds have no text attached, so I need to fetch their information directly
  593.  
  594. var embedsExist = titlePostContent.getElementsByClassName("yt_player"); // Youtube embeds
  595. if (embedsExist) {
  596. for (var l = 0; l < embedsExist.length; l++) {
  597. embedStrings += " "+embedsExist[0].getAttribute("data-id");
  598. }
  599. }
  600.  
  601.  
  602. embedsExist = titlePostContent.getElementsByClassName("img_container"); // Image embeds
  603. if (embedsExist) {
  604. for (var l = 0; l < embedsExist.length; l++) {
  605. embedStrings += " "+embedsExist[0].getAttribute("href");
  606. }
  607. }
  608.  
  609. titlePostContent = titlePostContent.textContent + embedStrings;
  610. }
  611.  
  612. // Tag highlight setup
  613. userTagsContent = authorTDs.snapshotItem(k);
  614. if (pageType == "messagelist") {
  615. while (userTagsContent.getAttribute("class") != "msg_infobox") {
  616. userTagsContent = userTagsContent.parentNode;
  617. }
  618.  
  619. userTagsContent = userTagsContent.getElementsByClassName("user_info")[0];
  620. if (userTagsContent) {
  621. userTagsContent = userTagsContent.textContent;
  622. }
  623.  
  624. // Make sure we don't forget the first post in a topic, since it doesn't get the (Topic Creator) tag
  625. if ((k == 0) || (k == authorTDs.snapshotLength-1)) {
  626. var anchors = authorTDs.snapshotItem(k).parentNode.parentNode.parentNode.parentNode.getElementsByTagName("a");
  627. if (anchors[0].getAttribute("name") == "1") {
  628. authorTDs.snapshotItem(k).isTC = true;
  629. }
  630. }
  631. } else {
  632. while (userTagsContent.nodeName != "TD") {
  633. userTagsContent = userTagsContent.parentNode;
  634. }
  635.  
  636. if (userTagsContent.childNodes[1]) {
  637. userTagsContent = userTagsContent.childNodes[1].textContent;
  638. }
  639. }
  640. if (typeof userTagsContent == "string") {
  641. if ((userTagsContent.indexOf("(A)") != -1) || (userTagsContent.indexOf("(Admin)") != -1)) {
  642. authorTDs.snapshotItem(k).isAdmin = true;
  643. }
  644. if ((userTagsContent.indexOf("(M)") != -1) || (userTagsContent.indexOf("(Moderator)") != -1) || (userTagsContent.indexOf("(Lead Moderator)") != -1)) {
  645. authorTDs.snapshotItem(k).isMod = true;
  646. }
  647. if ((userTagsContent.indexOf("(V)") != -1) || (userTagsContent.indexOf("(VIP)") != -1)) { // Not sure if these are the right strings to be looking for, haven't found a VIP to compare against.
  648. authorTDs.snapshotItem(k).isVIP = true;
  649. }
  650. if (userTagsContent.indexOf("(Topic Creator)") != -1) {
  651. authorTDs.snapshotItem(k).isTC = true;
  652. }
  653. }
  654.  
  655. // Normal stuff
  656. for (var i = 0; i < storedNumberOfLists; i++) {
  657. for (var j = 0; j < storedUsernames[i].length; j++) {
  658. // Standard username match check
  659. if ((pageType == "topiclist" && (storedActionHighlightTopic[i] || storedActionIgnoreTopic[i])) || (pageType != "topiclist" && (storedActionHighlightPost[i] || storedActionIgnorePost[i]))) {
  660. if (authorTDs.snapshotItem(k).textContent == storedUsernames[i][j]) {
  661. highlight("usernameMatch",pageType,authorTDs.snapshotItem(k),storedListNames[i],storedHighlightColours[i],storedHighlightTextColours[i],storedActionHighlightTopic[i], storedActionIgnoreTopic[i], storedActionHighlightPost[i], storedActionIgnorePost[i], storedActionTagTopic[i], storedActionTagPost[i], storedActionHighlightTopicContent[i], storedActionIgnoreTopicContent[i], storedActionHighlightPostContent[i], storedActionIgnorePostContent[i], storedActionAllowStacking[i]);
  662. }
  663. }
  664. // Content-based highlighting check
  665. if ((pageType == "topiclist" && (storedActionHighlightTopicContent[i] || storedActionIgnoreTopicContent[i])) || (pageType != "topiclist" && (storedActionHighlightPostContent[i] || storedActionIgnorePostContent[i]))) {
  666. if (makeInsensitive(titlePostContent).indexOf(makeInsensitive(storedUsernames[i][j])) != -1) {
  667. highlight("contentMatch",pageType,authorTDs.snapshotItem(k),storedListNames[i],storedHighlightColours[i],storedHighlightTextColours[i],storedActionHighlightTopic[i], storedActionIgnoreTopic[i], storedActionHighlightPost[i], storedActionIgnorePost[i], storedActionTagTopic[i], storedActionTagPost[i], storedActionHighlightTopicContent[i], storedActionIgnoreTopicContent[i], storedActionHighlightPostContent[i], storedActionIgnorePostContent[i], storedActionAllowStacking[i]);
  668. }
  669. }
  670. // Tag checks, admin, tc, etc.
  671. if ((storedActionHighlightAdmin[i] && authorTDs.snapshotItem(k).isAdmin) || (storedActionHighlightMod[i] && authorTDs.snapshotItem(k).isMod) || (storedActionHighlightVIP[i] && authorTDs.snapshotItem(k).isVIP) || (storedActionHighlightTC[i] && authorTDs.snapshotItem(k).isTC)) {
  672. highlight("tagMatch",pageType,authorTDs.snapshotItem(k),storedListNames[i],storedHighlightColours[i],storedHighlightTextColours[i],storedActionHighlightTopic[i], storedActionIgnoreTopic[i], storedActionHighlightPost[i], storedActionIgnorePost[i], storedActionTagTopic[i], storedActionTagPost[i], storedActionHighlightTopicContent[i], storedActionIgnoreTopicContent[i], storedActionHighlightPostContent[i], storedActionIgnorePostContent[i], storedActionAllowStacking[i]);
  673. }
  674. // Setting up for the right click menu
  675. if (((i == 0) && (j == 0)) && storedAllowRightclickHijacksSetting) {
  676. authorTDs.snapshotItem(k).setAttribute("contextmenu", "gamecats-menu");
  677. authorTDs.snapshotItem(k).addEventListener("contextmenu", e => { readyMenu(e); e.preventDefault();}, false);
  678. }
  679. }
  680. }
  681. }
  682. }
  683.  
  684. /*******************\
  685. * Right click menu! *
  686. \*******************/
  687.  
  688. function nukeMenu () {
  689. var oldMenu = document.getElementById("gamecats-menu");
  690. if (oldMenu) {
  691. oldMenu.parentNode.removeChild(oldMenu);
  692. }
  693. }
  694.  
  695. function readyMenu (rightClick) {
  696. getSettings();
  697. nukeMenu();
  698. if (pageType == "topiclist") {
  699. var mainMenu = rightClick.target.parentNode.parentNode.appendChild(document.createElement("div"));
  700. } else if (pageType == "messagelist") {
  701. var mainMenu = rightClick.target.parentNode.parentNode.parentNode.appendChild(document.createElement("div"));
  702. }
  703. var mainMenuLabel = mainMenu.appendChild(document.createElement("select"));
  704. mainMenu.setAttribute("id","gamecats-menu");
  705. mainMenuLabel.setAttribute("label","GameCATs Highlighting");
  706. mainMenuLabel.setAttribute("style","font-size:12px;");
  707.  
  708. var node = rightClick.target;
  709. var clickedUsername = node.textContent;
  710. console.log(clickedUsername);
  711. var menuItems = new Array();
  712. var placeholder = document.createElement("option");
  713. placeholder.textContent = "GameCATs";
  714. placeholder.setAttribute("style","display:none;");
  715. mainMenuLabel.appendChild(placeholder);
  716. for (var i = 0; i < storedNumberOfLists; i++) {
  717. menuItems[i] = document.createElement("option");
  718. menuItems[i].setAttribute("value",i);
  719. mainMenuLabel.appendChild(menuItems[i]);
  720.  
  721. // Check the box if already listed, and use the "remove" option
  722. if (storedUsernames[i].indexOf(clickedUsername) != -1) {
  723. menuItems[i].textContent = "☑ "+storedListNames[i]; //menuItems[i].setAttribute("checked","true");
  724. menuItems[i].addEventListener("click", function() {saveSettings("rightclickmenu",clickedUsername,this.getAttribute("value"),"remove"); nukeMenu();}, false);
  725. } else {
  726. menuItems[i].textContent = "☐ "+storedListNames[i];
  727. menuItems[i].addEventListener("click", function() {saveSettings("rightclickmenu",clickedUsername,this.getAttribute("value"),"add"); nukeMenu();}, false);
  728. }
  729. /* Eventually I might fix this. Maybe.
  730. var textHighlightColour = storedHighlightTextColours[i];
  731. if (textHighlightColour == "auto" || textHighlightColour == "automatic" || textHighlightColour == "automagic" ) {
  732. catchResults = autoContrast(pageType,textHighlightColour,node);
  733. if (catchResults[0]) {
  734. textHighlightColour = catchResults[2];
  735. }
  736. } */
  737. menuItems[i].setAttribute("style","color:"+storedHighlightTextColours[i]+"; background-color:"+storedHighlightColours[i]+"; background-image:"+storedHighlightColours[i]+";"); // Maybe someday a firefox update will turn background-image on.
  738. }
  739. var cancelButton = document.createElement("option");
  740. cancelButton.textContent = "Cancel";
  741. cancelButton.addEventListener("click", function() {nukeMenu();}, false);
  742. mainMenuLabel.appendChild(cancelButton);
  743. }
  744.  
  745. /*********************************\
  746. * Time to create a settings page! *
  747. \*********************************/
  748.  
  749. function createSettingsPage () {
  750.  
  751. // Styyyyyle!
  752. var style = document.createElement("style");
  753. style.textContent = '.container { clear:both; } .priorityButtons, .deleteButtons { display: block; } .usernameFields { height: 160px; width: 447px; } span {float: left;} span:nth-child(2) {clear: left;} label.actionLabels:nth-child(2):after {content: "Highlight/Ignore in Topic List\\00000A"; white-space: pre;} label.actionLabels:nth-child(4):after {content: "Highlight/Ignore in Message List\\00000A"; white-space: pre;} label.actionLabels:nth-child(6):after {content: "Add group name in Topic/Message List\\00000A"; white-space: pre;} label.actionLabels:nth-child(8):after {content: "Highlight/Ignore content in Topic List\\00000A"; white-space: pre;} label.actionLabels:nth-child(10):after {content: "Highlight/Ignore content in Message List\\00000A"; white-space: pre;} label.actionLabels:nth-child(11):after {content: "Allow stacking\\00000A"; white-space: pre;} label.actionLabels:nth-child(15):after {content: "Target Admins/Mods/VIPs/TCs\\00000A"; white-space: pre;} label.caseInsensitiveToggle, label.customCSSToggle, label.settingsLinkLocation, label.allowRightclickHijacksToggle { clear:both; display: block;} label.caseInsensitiveToggle:after {content: "Ignore case sensitivity on content matches";} label.customCSSToggle:after {content: "Using CSS with custom colours";} label.allowRightclickHijacksToggle:after {content: "Allow hijacking the right click context menu";} label.styleGroupAsTagToggle:after {content: "Style groups as GameFAQs tags";} label.settingsLinkLocation:before {content: "Settings link location: "} .exportImportLabel:before {content: "\\00000A Import/Export: "; white-space: pre;}';
  754. document.getElementsByTagName("head")[0].appendChild(style);
  755.  
  756. // Creating all the variables I'll need for the upcoming loop.
  757. var body = document.getElementsByTagName("body")[0];
  758. var container = new Array();
  759. var listname = new Array();
  760. var listnameFields = new Array();
  761. var username = new Array();
  762. var usernameFields = new Array();
  763. var colour = new Array();
  764. var colourFields = new Array();
  765. var textColour = new Array();
  766. var textColourFields = new Array();
  767. var action = new Array();
  768. var actionFields = new Array();
  769. var labels = new Array();
  770. var deleteButtons = new Array();
  771. var priorityButtons = new Array();
  772. var spans = new Array();
  773.  
  774. // Creating a bunch of input fields for each highlight list.
  775. for (var i = 0; i < storedNumberOfLists; i++) {
  776. // Wrap each entry in its own div, for easy location of children and deletion.
  777. container[i] = document.createElement('div');
  778. container[i].setAttribute('id','container'+i);
  779. container[i].setAttribute('class','container');
  780. body.appendChild(container[i]);
  781. // Pairing a few other things in spans for the sake of styling.
  782. spans[i,0] = document.createElement('span');
  783. spans[i,1] = document.createElement('span');
  784. spans[i,2] = document.createElement('span');
  785. spans[i,3] = document.createElement('span');
  786. container[i].appendChild(spans[i,0]);
  787. container[i].appendChild(spans[i,1]);
  788. container[i].appendChild(spans[i,2]);
  789. container[i].appendChild(spans[i,3]);
  790.  
  791. // List name, for user organizition or if you choose to let the name of said list show next to usernames.
  792. listnameFields[i] = document.createElement('input');
  793. listnameFields[i].setAttribute('type','text');
  794. listnameFields[i].setAttribute('id','listnameFields'+i);
  795. listnameFields[i].setAttribute('class','listnameFields');
  796. listnameFields[i].setAttribute('placeholder','Group Name');
  797. listnameFields[i].setAttribute('value',storedListNames[i]);
  798. spans[i,0].appendChild(listnameFields[i]);
  799.  
  800. // The colour to change the background to when a username is matched with one on the list.
  801. colourFields[i] = document.createElement('input');
  802. colourFields[i].setAttribute('type','text');
  803. colourFields[i].setAttribute('id','colourFields'+i);
  804. colourFields[i].setAttribute('class','colourFields');
  805. colourFields[i].setAttribute('placeholder','Background Colour');
  806. colourFields[i].setAttribute('value',storedHighlightColours[i]);
  807. spans[i,0].appendChild(colourFields[i]);
  808.  
  809. // The colour to change text to when a username is matched with one on the list.
  810. textColourFields[i] = document.createElement('input');
  811. textColourFields[i].setAttribute('type','text');
  812. textColourFields[i].setAttribute('id','textColourFields'+i);
  813. textColourFields[i].setAttribute('class','textColourFields');
  814. textColourFields[i].setAttribute('placeholder','Text Colour (optional)');
  815. textColourFields[i].setAttribute('value',storedHighlightTextColours[i]);
  816. spans[i,0].appendChild(textColourFields[i]);
  817.  
  818. // Username lists.
  819. usernameFields[i] = document.createElement('textarea');
  820. usernameFields[i].textContent = storedUsernames[i].join(",");
  821. usernameFields[i].setAttribute('id','usernameFields'+i);
  822. usernameFields[i].setAttribute('class','usernameFields');
  823. usernameFields[i].setAttribute('placeholder','Usernames and/or post content to match, case sensitive.');
  824. spans[i,1].appendChild(usernameFields[i]);
  825.  
  826. // Actions to perform when we find a match, or special matching conditions
  827. for (var j = 0; j < 15; j++) {
  828. labels[i*15+j] = document.createElement('label');
  829. labels[i*15+j].setAttribute('class','actionLabels');
  830. actionFields[i*15+j] = document.createElement('input');
  831. actionFields[i*15+j].setAttribute('type','checkbox');
  832. actionFields[i*15+j].setAttribute('id','actionFields'+(i*15+j));
  833. actionFields[i*15+j].setAttribute('class','actionFields');
  834.  
  835. spans[i,2].appendChild(labels[i*15+j]);
  836. labels[i*15+j].appendChild(actionFields[i*15+j]);
  837. }
  838. // Pre-check the boxes only if the setting is already present.
  839. if (storedActionHighlightTopic[i] === true) {
  840. actionFields[i*15].setAttribute('checked','');
  841. }
  842. if (storedActionIgnoreTopic[i] === true) {
  843. actionFields[i*15+1].setAttribute('checked','');
  844. }
  845. if (storedActionHighlightPost[i] === true) {
  846. actionFields[i*15+2].setAttribute('checked','');
  847. }
  848. if (storedActionIgnorePost[i] === true) {
  849. actionFields[i*15+3].setAttribute('checked','');
  850. }
  851. if (storedActionTagTopic[i] === true) {
  852. actionFields[i*15+4].setAttribute('checked','');
  853. }
  854. if (storedActionTagPost[i] === true) {
  855. actionFields[i*15+5].setAttribute('checked','');
  856. }
  857. if (storedActionHighlightTopicContent[i] === true) {
  858. actionFields[i*15+6].setAttribute('checked','');
  859. }
  860. if (storedActionIgnoreTopicContent[i] === true) {
  861. actionFields[i*15+7].setAttribute('checked','');
  862. }
  863. if (storedActionHighlightPostContent[i] === true) {
  864. actionFields[i*15+8].setAttribute('checked','');
  865. }
  866. if (storedActionIgnorePostContent[i] === true) {
  867. actionFields[i*15+9].setAttribute('checked','');
  868. }
  869. if (storedActionAllowStacking[i] === true) {
  870. actionFields[i*15+10].setAttribute('checked','');
  871. }
  872. if (storedActionHighlightAdmin[i] === true) {
  873. actionFields[i*15+11].setAttribute('checked','');
  874. }
  875. if (storedActionHighlightMod[i] === true) {
  876. actionFields[i*15+12].setAttribute('checked','');
  877. }
  878. if (storedActionHighlightVIP[i] === true) {
  879. actionFields[i*15+13].setAttribute('checked','');
  880. }
  881. if (storedActionHighlightTC[i] === true) {
  882. actionFields[i*15+14].setAttribute('checked','');
  883. }
  884.  
  885. // Priority buttons, to move this div to the top.
  886. priorityButtons[i] = document.createElement('input');
  887. priorityButtons[i].setAttribute('id','priorityButtons'+i);
  888. priorityButtons[i].setAttribute('class','priorityButtons');
  889. priorityButtons[i].setAttribute('type','button');
  890. priorityButtons[i].setAttribute('value','Send To Top');
  891. priorityButtons[i].addEventListener('click',function() {this.parentNode.parentNode.parentNode.insertBefore(this.parentNode.parentNode,this.parentNode.parentNode.parentNode.childNodes[0]);},true);
  892. spans[i,3].appendChild(priorityButtons[i]);
  893.  
  894. // Delete buttons, to trash the whole containing div.
  895. deleteButtons[i] = document.createElement('input');
  896. deleteButtons[i].setAttribute('id','deleteButtons'+i);
  897. deleteButtons[i].setAttribute('class','deleteButtons');
  898. deleteButtons[i].setAttribute('type','button');
  899. deleteButtons[i].setAttribute('value','Delete');
  900. deleteButtons[i].addEventListener('click',function() {this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);},true);
  901. spans[i,3].appendChild(deleteButtons[i]);
  902.  
  903. }
  904.  
  905. // Done with all the looping junk, now for the ever-important "save settings" and "new list" buttons.
  906.  
  907. function newList() {
  908. GM_setValue("numberOfLists",GM_getValue("numberOfLists")+1);
  909. GM_setValue("Main Settings",GM_getValue("Main Settings")+"^||||false,false,false,false,false,false,false,false,false,false,false");
  910.  
  911. // The anchor set here gets watched on page load to automatically reopen the settings page.
  912. window.location.href = window.location.href.split("#")[0]+"#ReloadHighlightSettings";
  913. location.reload();
  914. }
  915.  
  916. var caseInsensitiveToggle = [document.createElement('label'),document.createElement('input')];
  917. caseInsensitiveToggle[1].setAttribute('type','checkbox');
  918. caseInsensitiveToggle[1].setAttribute('id','caseInsensitiveToggle');
  919. caseInsensitiveToggle[0].setAttribute('class','caseInsensitiveToggle');
  920. caseInsensitiveToggle[1].setAttribute('class','caseInsensitiveToggle');
  921. if (storedCaseInsensitive == true) {
  922. caseInsensitiveToggle[1].setAttribute('checked','');
  923. }
  924. body.appendChild(caseInsensitiveToggle[0]);
  925. caseInsensitiveToggle[0].appendChild(caseInsensitiveToggle[1]);
  926.  
  927. var customCSSToggle = [document.createElement('label'),document.createElement('input')];
  928. customCSSToggle[1].setAttribute('type','checkbox');
  929. customCSSToggle[1].setAttribute('id','customCSSToggle');
  930. customCSSToggle[0].setAttribute('class','customCSSToggle');
  931. customCSSToggle[1].setAttribute('class','customCSSToggle');
  932. if (storedUseColouredCustomCSSSetting == true) {
  933. customCSSToggle[1].setAttribute('checked','');
  934. }
  935. body.appendChild(customCSSToggle[0]);
  936. customCSSToggle[0].appendChild(customCSSToggle[1]);
  937.  
  938. var styleGroupAsTagToggle = [document.createElement('label'),document.createElement('input')];
  939. styleGroupAsTagToggle[1].setAttribute('type','checkbox');
  940. styleGroupAsTagToggle[1].setAttribute('id','styleGroupAsTagToggle');
  941. styleGroupAsTagToggle[0].setAttribute('class','styleGroupAsTagToggle');
  942. styleGroupAsTagToggle[1].setAttribute('class','styleGroupAsTagToggle');
  943. if (storedStyleGroupAsTagSetting == true) {
  944. styleGroupAsTagToggle[1].setAttribute('checked','');
  945. }
  946. body.appendChild(styleGroupAsTagToggle[0]);
  947. styleGroupAsTagToggle[0].appendChild(styleGroupAsTagToggle[1]);
  948. var allowRightclickHijacksToggle = [document.createElement('label'),document.createElement('input')];
  949. allowRightclickHijacksToggle[1].setAttribute('type','checkbox');
  950. allowRightclickHijacksToggle[1].setAttribute('id','allowRightclickHijacksToggle');
  951. allowRightclickHijacksToggle[0].setAttribute('class','allowRightclickHijacksToggle');
  952. allowRightclickHijacksToggle[1].setAttribute('class','allowRightclickHijacksToggle');
  953. if (storedAllowRightclickHijacksSetting == true) {
  954. allowRightclickHijacksToggle[1].setAttribute('checked','');
  955. }
  956. body.appendChild(allowRightclickHijacksToggle[0]);
  957. allowRightclickHijacksToggle[0].appendChild(allowRightclickHijacksToggle[1]);
  958.  
  959. var settingsLinkLocationDropdown = [document.createElement('label'),document.createElement('select')];
  960. var settingsLinkOptions = [document.createElement('option'),document.createElement('option'),document.createElement('option')];
  961. settingsLinkLocationDropdown[1].setAttribute('id','settingsLinkLocation');
  962. settingsLinkLocationDropdown[0].setAttribute('class','settingsLinkLocation');
  963. settingsLinkLocationDropdown[1].setAttribute('class','settingsLinkLocation');
  964. settingsLinkOptions[0].setAttribute('id','header');
  965. settingsLinkOptions[0].setAttribute('value',0);
  966. settingsLinkOptions[0].textContent = 'Header';
  967. settingsLinkOptions[1].setAttribute('id','accountSettings');
  968. settingsLinkOptions[1].setAttribute('value',1);
  969. settingsLinkOptions[1].textContent = 'Account Settings';
  970. settingsLinkOptions[2].setAttribute('id','both');
  971. settingsLinkOptions[2].setAttribute('value',2);
  972. settingsLinkOptions[2].textContent = 'Both';
  973.  
  974. body.appendChild(settingsLinkLocationDropdown[0]);
  975. settingsLinkLocationDropdown[0].appendChild(settingsLinkLocationDropdown[1]);
  976. settingsLinkLocationDropdown[1].appendChild(settingsLinkOptions[0]);
  977. settingsLinkLocationDropdown[1].appendChild(settingsLinkOptions[1]);
  978. settingsLinkLocationDropdown[1].appendChild(settingsLinkOptions[2]);
  979. settingsLinkOptions[GM_getValue("settingsLinkLocation")].selected = true;
  980.  
  981. var newListButton = document.createElement('input');
  982. newListButton.setAttribute('id','newListButton');
  983. newListButton.setAttribute('class','newListButton');
  984. newListButton.setAttribute('type','button');
  985. newListButton.setAttribute('value','New Highlighting List');
  986. body.appendChild(newListButton);
  987. newListButton.addEventListener('click',newList,true);
  988.  
  989. var saveSettingsButton = document.createElement('input');
  990. saveSettingsButton.setAttribute('id','saveSettingsButton');
  991. saveSettingsButton.setAttribute('class','saveSettingsButton');
  992. saveSettingsButton.setAttribute('type','button');
  993. saveSettingsButton.setAttribute('value','Save Settings');
  994. body.appendChild(saveSettingsButton);
  995. saveSettingsButton.addEventListener('click',function() {var here = this;saveSettings("settingspage");here.setAttribute("value","Saved!");setTimeout(function(){here.setAttribute("value","Save Settings")},1000);},true);
  996.  
  997. var exitButton = document.createElement('input');
  998. exitButton.setAttribute('id','exitButton');
  999. exitButton.setAttribute('class','exitButton');
  1000. exitButton.setAttribute('type','button');
  1001. exitButton.setAttribute('value','Exit');
  1002. body.appendChild(exitButton);
  1003. exitButton.addEventListener('click',function() {window.scrollTo(0,0); window.location.href = window.location.href.split("#")[0];},true);
  1004.  
  1005. var exportImportLabel = document.createElement('label');
  1006. exportImportLabel.setAttribute('id','exportImportLabel');
  1007. exportImportLabel.setAttribute('class','exportImportLabel');
  1008. var exportImportField = document.createElement('input');
  1009. exportImportField.setAttribute('id','exportImportField');
  1010. exportImportField.setAttribute('class','exportImportField');
  1011. exportImportField.setAttribute('type','text');
  1012. body.appendChild(exportImportLabel);
  1013. exportImportLabel.appendChild(exportImportField);
  1014.  
  1015. var importButton = document.createElement('input');
  1016. importButton.setAttribute('id','importButton');
  1017. importButton.setAttribute('class','importButton');
  1018. importButton.setAttribute('type','button');
  1019. importButton.setAttribute('value','Import');
  1020. body.appendChild(importButton);
  1021. importButton.addEventListener('click',function() {var here = this;saveSettings("import");here.setAttribute("value","Imported!");setTimeout(function(){window.location.href = window.location.href.split("#")[0]+"#ReloadHighlightSettings"; location.reload();},300);},true);
  1022.  
  1023. if (window.location.href.split("#")[1] == "ReloadHighlightSettings") {
  1024. window.location.href = window.location.href.split("#")[0]+"#HighlightSettings";
  1025. window.scrollTo(0,document.body.scrollHeight);
  1026. }
  1027. }
  1028.  
  1029. function prepSettings () {
  1030. var gfaqsBody = document.getElementsByTagName("body")[0];
  1031. var gfaqsHead = document.getElementsByTagName("head")[0];
  1032. var killMe = gfaqsBody.childNodes;
  1033. var killMeToo = gfaqsHead.childNodes;
  1034. for (var i = killMe.length-1; i >= 0; i--) {
  1035. gfaqsBody.removeChild(killMe[i]);
  1036. }
  1037. for (var i = killMeToo.length-1; i >= 0; i--) {
  1038. gfaqsHead.removeChild(killMeToo[i]);
  1039. }
  1040. var title = gfaqsHead.appendChild(document.createElement("title"));
  1041. title.textContent = "Highlight Settings";
  1042. createSettingsPage();
  1043. }
  1044.  
  1045. if (window.location.href.split("#")[1] == "ReloadHighlightSettings") {
  1046. prepSettings();
  1047. }