HSX Port Monkey

Port tuneup with sidebar trade panel, trend arrows, tagging, options, etc.

当前为 2016-10-30 提交的版本,查看 最新版本

  1. /*=====================================================================================*\
  2. | Port Monkey - GreaseMonkey Script for Hollywood Stock Exchange |
  3. | (c) 2009-2016 by Eduardo Zepeda |
  4. | A logical and effective re-tuning of the HSX portfolio re-design, including a |
  5. | sidebar trade panel, price trend arrows, custom tagging, color styler, estimated |
  6. | bond adjust fetch, info pop-ups, and configurable options. Works with Opera |
  7. | and Chrome (most features). |
  8. \*=====================================================================================*/
  9.  
  10. // ==UserScript==
  11. // @name HSX Port Monkey
  12. // @namespace edzep.scripts
  13. // @version 5.2.5
  14. // @author EdZep at HSX
  15. // @description Port tuneup with sidebar trade panel, trend arrows, tagging, options, etc.
  16. // @include http://*hsx.com/portfolio/*
  17. // @include http://*hsx.com/trade/*
  18. // @exclude http://*hsx.com/portfolio/bank*
  19. // @exclude http://*hsx.com/portfolio/limit*
  20. // @exclude http://*hsx.com/portfolio/history*
  21. // @exclude http://*hsx.com/portfolio/chart*
  22. // @grant GM_getValue
  23. // @grant GM_setValue
  24. // @grant GM_deleteValue
  25. // @grant GM_setClipboard
  26. // @grant GM_addStyle
  27. // @grant GM_xmlhttpRequest
  28. // @grant GM_getResourceText
  29. // @grant GM_log
  30. // ==/UserScript==
  31.  
  32. // Start
  33.  
  34. (function() {
  35.  
  36. //--- global object references, etc
  37.  
  38. var refSymbol = "";
  39. var refQuantity = "";
  40. var refNavbar = "";
  41. var refMainDataDiv = "";
  42. var refObjectTemp = "";
  43. var holdStatus = "";
  44. var url = "";
  45. var bondBuffer = "";
  46. var hotkeysActive = true;
  47. var mouseDown = false;
  48. var positions = new Array(); // 0=movies, 1=bonds, 2=deriv, 3=funds
  49.  
  50.  
  51. //--- copy data to system clipboard
  52.  
  53. function put2clipboard(sectionName) {
  54. var table = document.getElementById(sectionName);
  55. var clipboard = '';
  56. var chunk = new Array();
  57. if(table != null) {
  58. for(var r = 1, n = table.rows.length; r < n; r++) {
  59. // get values for entire row
  60. for(var j=0; j<10; j++) {
  61. chunk[j]= table.rows[r].cells[j].textContent+' ';
  62. var h = chunk[j].indexOf("H$"); // remove H$, which makes ss text of numbers
  63. if(h>-1) chunk[j]=chunk[j].slice(h+2);
  64. }
  65. // revert to HSX original long/short indicators
  66. chunk[2]="long ";
  67. if(chunk[1].indexOf('-')>-1) {
  68. chunk[2]="short ";
  69. chunk[1]=chunk[1].slice(1); // remove invisible - on short share numbers
  70. }
  71. // remove % sign on last column
  72. GM_log(chunk[9]);
  73. chunk[9] = chunk[9].slice(0,-2);
  74. GM_log(chunk[9]);
  75. clipboard += chunk[0] + chunk[1] + chunk[2] + chunk[3] + chunk[4] + chunk[5] + chunk[6] + chunk[7] + chunk[8] + chunk[9] + "\n";
  76. }
  77. }
  78. GM_setClipboard(clipboard);
  79. }
  80.  
  81. //--- find missing MovieStocks
  82.  
  83. function idMissingMovies() {
  84.  
  85. // find all securities
  86. var findsecurities = document.evaluate("//div[@class='twelve columns last']//a[contains(@href,'security/view')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  87.  
  88. var strAllOwnedMovies = "";
  89. for(var i=0; i<positions[0]; i++) strAllOwnedMovies += findsecurities.snapshotItem(i).textContent + ",";
  90.  
  91. // *** perform 5 searches; results of each expected to be about 300-350 items
  92. // *** HSX can return 500 results per search; if any of the 5 search results
  93. // *** exceeds 500, this whole process will become inaccurate
  94. var doc = new Array();
  95. GM_xmlhttpRequest({
  96. method: 'GET',
  97. url: 'http://www.hsx.com/search/?keyword=&status=ACT&type=1&minprice=min&maxprice=.06&action=submit_advanced',
  98. onload: function(response) {
  99. doc[1] = document.createElement('div');
  100. doc[1].innerHTML = response.responseText;
  101.  
  102. GM_xmlhttpRequest({
  103. method: 'GET',
  104. url: 'http://www.hsx.com/search/?keyword=&status=ACT&type=1&minprice=.07&maxprice=.40&action=submit_advanced',
  105. onload: function(response) {
  106. doc[2] = document.createElement('div');
  107. doc[2].innerHTML = response.responseText;
  108. GM_xmlhttpRequest({
  109. method: 'GET',
  110. url: 'http://www.hsx.com/search/?keyword=&status=ACT&type=1&minprice=.41&maxprice=4&action=submit_advanced',
  111. onload: function(response) {
  112. doc[3] = document.createElement('div');
  113. doc[3].innerHTML = response.responseText;
  114.  
  115. GM_xmlhttpRequest({
  116. method: 'GET',
  117. url: 'http://www.hsx.com/search/?keyword=&status=ACT&type=1&minprice=4.01&maxprice=14&action=submit_advanced',
  118. onload: function(response) {
  119. doc[4] = document.createElement('div');
  120. doc[4].innerHTML = response.responseText;
  121.  
  122. GM_xmlhttpRequest({
  123. method: 'GET',
  124. url: 'http://www.hsx.com/search/?keyword=&status=ACT&type=1&minprice=14.01&maxprice=max&action=submit_advanced',
  125. onload: function(response) {
  126. doc[5] = document.createElement('div');
  127. doc[5].innerHTML = response.responseText;
  128.  
  129. var findDoc1WB = document.evaluate("//div[@class='whitebox_content']", doc[1], null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  130. var doc1Whitebox = findDoc1WB.snapshotItem(0);
  131.  
  132. // merge search results 2,3,4,5 into the first
  133. for(i=2; i<6; i++) {
  134. var findTable = document.evaluate("//table[@class='sortable']", doc[i], null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  135. var docTable = findTable.snapshotItem(0);
  136. doc1Whitebox.insertBefore(docTable, doc1Whitebox.firstChild);
  137. }
  138. var findAllMovies = document.evaluate("//div[@class='whitebox_content']//a[contains(@href,'security/view')]", doc[1], null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  139. var resultsText="Moviestocks listed below are not held in your portfolio.<p>";
  140. var availableCount = 0;
  141. var missingCount = 0;
  142. // each stock will appear TWICE in findAllMovies, so count by 2s
  143. for(i=0; i<findAllMovies.snapshotLength; i+=2) {
  144. var item = findAllMovies.snapshotItem(i);
  145. var title = item.textContent;
  146. var ppNode = item.parentNode.parentNode;
  147. var ticker = ppNode.childNodes[3].textContent;
  148. var status = ppNode.childNodes[7].textContent;
  149. if(status!="IPO") {
  150. availableCount++;
  151. var missingMovie = true;
  152. if(strAllOwnedMovies.indexOf(ticker) > -1) missingMovie = false;
  153. if(missingMovie==true) {
  154. resultsText += "<a href='http://www.hsx.com/security/view/" + ticker + " 'target='_new'>" + ticker + "</a> - " + title + "<br>";
  155. missingCount++;
  156. }
  157. }
  158. }
  159.  
  160. resultsText += "<p>Active Moviestocks: " + availableCount + "<br>Not held: " + missingCount;
  161. var width = 400;
  162. var height = 400;
  163. var left = parseInt((screen.width/2) - (width/2));
  164. var top = parseInt((screen.height/2) - (height/2));
  165. var windowFeatures = "width=" + width + ",height=" + height +
  166. ",status,resizable,left=" + left + ",top=" + top +
  167. "screenX=" + left + ",screenY=" + top + ",scrollbars=yes";
  168.  
  169. var resultsWindow = window.open("data:text/html," + encodeURIComponent(resultsText),"_blank", windowFeatures);
  170. resultsWindow.focus();
  171. }
  172. });
  173. }
  174. });
  175. }
  176. });
  177. }
  178. });
  179. }
  180. });
  181. }
  182.  
  183.  
  184. //--- center "fixed" element in browser
  185.  
  186. function centerThis(e) {
  187. var eRef = document.getElementById(e);
  188. var x = (document.documentElement.clientWidth - eRef.offsetWidth) / 2;
  189. var y = (document.documentElement.clientHeight - eRef.offsetHeight) * .4;
  190. eRef.style.left = x + "px";
  191. eRef.style.top = parseInt(y) + "px";
  192. }
  193.  
  194. //--- color picker functions
  195.  
  196. function colorShowHide() {
  197. var optColor = document.getElementById("colorPanel");
  198. if(optColor.style.left == "-1000px") {
  199. optShowHide();
  200. document.getElementById("opt_cutCorn").checked = GM_getValue("opt_cutCorn", false);
  201. document.getElementById("opt_cutGrad").checked = GM_getValue("opt_cutGrad", false);
  202. document.getElementById("opt_cutGrid").checked = GM_getValue("opt_cutGrid", false);
  203. document.getElementById("opt_cutPx").checked = GM_getValue("opt_cutPx", false);
  204. document.getElementById("opt_cutBrd").checked = GM_getValue("opt_cutBrd", false);
  205. document.getElementById("opt_cutJlogo").checked = GM_getValue("opt_cutJlogo", false);
  206. centerThis("colorPanel");
  207. }
  208. else {
  209. // don't hide, just move, so picker can initialize and work properly
  210. optColor.style.left = "-1000px";
  211.  
  212. var findInputs = document.evaluate("//div[@id='colorPanel']//input[@class='color']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  213. for(var i=0; i<findInputs.snapshotLength; i++) {
  214. var inputID = findInputs.snapshotItem(i).id;
  215. GM_setValue(inputID, document.getElementById(inputID).value);
  216. }
  217.  
  218. GM_setValue("opt_cutCorn", document.getElementById("opt_cutCorn").checked);
  219. GM_setValue("opt_cutGrad", document.getElementById("opt_cutGrad").checked);
  220. GM_setValue("opt_cutGrid", document.getElementById("opt_cutGrid").checked);
  221. GM_setValue("opt_cutPx", document.getElementById("opt_cutPx").checked);
  222. GM_setValue("opt_cutBrd", document.getElementById("opt_cutBrd").checked);
  223. GM_setValue("opt_cutJlogo", document.getElementById("opt_cutJlogo").checked);
  224. }
  225. }
  226.  
  227. function colorDefaults() {
  228. alert("Refresh port to see changes,\nor to further edit colors.");
  229. document.getElementById("colorPanel").style.left = "-1000px";
  230.  
  231. var findInputs = document.evaluate("//div[@id='colorPanel']//input[@class='color']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  232. for(var i=0; i<findInputs.snapshotLength; i++) {
  233. var inputID = findInputs.snapshotItem(i).id;
  234. GM_deleteValue(inputID);
  235. }
  236. }
  237.  
  238. function insertPickerCode() {
  239. var scriptNode = document.createElement("script");
  240. scriptNode.textContent = GM_getResourceText("jscolorXS");
  241. scriptNode.setAttribute("type", "text/javascript");
  242. document.getElementsByTagName("head")[0].appendChild(scriptNode);
  243. }
  244.  
  245. //--- display expected bond adjust info
  246.  
  247. function showBondInfo(clickX, clickY, mode, currentVal, isBond) {
  248. var tempBuffer = bondBuffer;
  249. // get data freshness date
  250. var bondInfoDate = tempBuffer.substring(0,tempBuffer.indexOf('\n')-1);
  251.  
  252. // find and format bond ticker & adjust info
  253. var ticker = refSymbol.value;
  254. if(mode == "inPort") {
  255. ticker = refObjectTemp.getAttribute("alt");
  256. currentVal = parseFloat(refObjectTemp.textContent.slice(2));
  257. }
  258. var future = "the future is hazy";
  259. var info = new Array();
  260. var locate = tempBuffer.indexOf(',' + ticker +','); // mcg
  261. if(locate > -1 && currentVal != -1) {
  262. if(locate > 20) {
  263. do {
  264. locate -= 1;
  265. ch = tempBuffer.charAt(locate);
  266. }
  267. while(ch != '\n');
  268. locate = locate+=1;
  269. }
  270. else locate = 0; // top, for first remaining
  271. tempBuffer = tempBuffer.substring(locate);
  272. for(var i=0; i<3; i++) {
  273. locate = tempBuffer.indexOf(',')+1;
  274. info[i] = tempBuffer.substring(0,locate-1);
  275. tempBuffer = tempBuffer.substring(locate);
  276. }
  277. info[3] = tempBuffer.substring(0,tempBuffer.indexOf('\n')-1);
  278. var futureVal = parseFloat(info[3]).toFixed(2);
  279. var futureStyled = "<b>H$" + futureVal + "</b>";
  280. if(parseFloat(futureVal) > currentVal) futureStyled = "<span class=pmGreen>H$" + futureVal + "</span>";
  281. if(parseFloat(futureVal) < currentVal) futureStyled = "<span class=pmRed>H$" + futureVal + "</span>";
  282. future = futureStyled + " with " + info[1] + ", " + info[0];
  283. }
  284. var position = "absolute";
  285. if(mode == "symbol") {
  286. position = "fixed";
  287. clickX = parseInt(document.getElementById("tradePanel").style.width) - 12;
  288. clickY = parseInt(document.getElementById("topLinkPanel").style.height) * 3.4;
  289. }
  290.  
  291. if(currentVal == -1) currentVal = "Error!";
  292. else currentVal = "H$" + currentVal.toFixed(2);
  293. var bigstr = "<table class='calc'><tr><td style='font-weight:bold'><a href='http://www.hsx.com/security/view/" + ticker + "' target='pm_a'>" + ticker + "</a></td><td width=90%><a href='javascript:closeTipPm();' style='display:block; text-align:right'>X </a></td></tr><tr><td colspan=2>Current: <b>" + currentVal + "</b></td></tr>";
  294. if(isBond) bigstr += "<tr><td colspan=2>Estimated: " + future + "</td></tr>";
  295. bigstr += "<tr><td colspan=2>";
  296. if(currentVal != "Error!" && isBond) bigstr += "<a href='http://www.kaigee.com/SBO/" + ticker + "' target='pm_b' title='Last update: " + bondInfoDate + "'>Details at KaiGee.com</a></td></tr></table>";
  297. displayTip(bigstr,clickX,clickY,3,position);
  298. }
  299. //--- fetch bond adjust info, regular click on current price
  300. function fetchBondInfoA(clickX, clickY, mode) {
  301. if(mode == "symbol") {
  302. // get data from HSX
  303. GM_xmlhttpRequest({
  304. method: 'GET',
  305. url: 'http://www.hsx.com/security/view/' + refSymbol.value,
  306. onload: function(response) {
  307. var doc = document.createElement('div');
  308. var price = -1;
  309. doc.innerHTML = response.responseText;
  310. try {
  311. var findvalue = document.evaluate("//p[@class='value']", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  312. price = parseFloat(findvalue.snapshotItem(0).textContent.slice(2));
  313. }
  314. catch(err) {}
  315. var isBond = false, ttext = "";
  316. try {
  317. findvalue = document.evaluate("//title", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  318. ttext = findvalue.snapshotItem(0).textContent.toLowerCase();
  319. }
  320. catch(err) {}
  321. if(ttext.indexOf('starbond') > -1 && ttext.indexOf('movie fund') < 0)
  322. { isBond = true; }
  323.  
  324. if(bondBuffer != "" || isBond == false)
  325. { showBondInfo(clickX, clickY, mode, price, isBond); }
  326. else {
  327. // get data from the-numbers
  328. fetchBondInfoB(clickX, clickY, mode, price, isBond);
  329. }
  330. }
  331. });
  332. }
  333. else {
  334. // mode = "inPort"
  335. if(bondBuffer != "")
  336. { showBondInfo(clickX, clickY, mode, 0, true); }
  337. else {
  338. // get data from the-numbers
  339. fetchBondInfoB(clickX, clickY, mode, 0, true);
  340. }
  341. }
  342. }
  343.  
  344. function fetchBondInfoB(clickX, clickY, mode, price, isBond) {
  345. GM_xmlhttpRequest({
  346. method: 'GET',
  347. url: 'http://www.kaigee.com/Lists/PM.csv',
  348. onload: function(response) {
  349. bondBuffer = response.responseText;
  350. showBondInfo(clickX, clickY, mode, price, isBond);
  351. }
  352. });
  353. }
  354. //--- retrieve description for SECURITY, click-hold on price paid
  355.  
  356. function showDescription(clickX, clickY) {
  357. var ticker = refObjectTemp.getAttribute("alt");
  358. GM_xmlhttpRequest({
  359. method: 'GET',
  360. url: 'http://www.hsx.com/security/view/' + ticker,
  361. onload: function(response) {
  362. var doc = document.createElement('div');
  363. doc.innerHTML = response.responseText;
  364. var findparagraph = document.evaluate("//div[@class='whitebox_content']//p", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  365. var bigstr = findparagraph.snapshotItem(0).textContent;
  366. if (bigstr.indexOf('nception') > -1 && (bigstr.indexOf('ate') > -1 || bigstr.indexOf('und') > -1))
  367. { bigstr = findparagraph.snapshotItem(1).textContent; }
  368. bigstr = "<table class='calc'><tr><td style='font-weight:bold'>" + ticker + "</td></tr><tr><td>" + ltrim(bigstr) + "</td></tr></table>";
  369. if (mouseDown) { displayTip(bigstr,clickX,clickY,2,"absolute"); }
  370. }
  371. });
  372. }
  373.  
  374. //--- set up window for SECURITY intraday graph fetch, click on today's change
  375.  
  376. function intraday() {
  377. var ticker = refObjectTemp.getAttribute("alt");
  378. var wURL = "http://theun4gven.com/hsx/daily.php?sec=" + ticker;
  379. var wh = "width=" + "450" + ",height=" + "320";
  380. var windowRef = window.open(wURL, "iday", wh);
  381. }
  382.  
  383. //--- do calculations for MOVIE, click-hold on current price
  384.  
  385. function showCalc(clickX, clickY) {
  386. var price = refObjectTemp.textContent.slice(2);
  387. var ticker = refObjectTemp.getAttribute("alt");
  388. var ch = String.fromCharCode(247); //proper divide sign
  389. var calc2 = (price / 2.0).toFixed(2);
  390. var calc3 = (price / 2.2).toFixed(2);
  391. var calc1 = (price / 2.7).toFixed(2);
  392. var calc4 = (price / 4.8).toFixed(2);
  393.  
  394. var newHTML = "<table class='calc'><tr><td colspan=5 style='font-weight:bold'>" + ticker + "</td></tr><tr><td>" + price + "</td><td>" + ch + "</td><td>2.0</td><td>=</td><td style='text-align:right'>" + calc2 + "</td></tr><tr><td></td><td>" + ch + "</td><td>2.2</td><td>=</td><td style='text-align:right'>" + calc3 + "</td></tr><tr><td></td><td><b>" + ch + "</b></td><td><b>2.7</b></td><td><b>=</b></td><td style='text-align:right'><b>" + calc1 + "</b></td></tr><tr><td></td><td>" + ch + "</td><td>4.8</td><td>=</td><td style='text-align:right'>" + calc4 + "</td></tr></table>";
  395.  
  396. displayTip(newHTML,clickX,clickY,1,"absolute");
  397. }
  398.  
  399. //--- display calculation, description or bond tooltip box
  400.  
  401. function displayTip(newHTML,clickX,clickY,mode,position) {
  402. var calcDiv = document.getElementById("calcTip");
  403. calcDiv.innerHTML = newHTML;
  404.  
  405. calcDiv.style.color = GM_getValue("opt_qLnk","#3597B2");
  406. calcDiv.style.top = clickY + 15 + "px";
  407. calcDiv.style.left = clickX + 25 + "px";
  408. calcDiv.style.zIndex = "103";
  409. calcDiv.style.width = "auto";
  410. calcDiv.style.position = position;
  411. // mode 1 = calc division; mode 2 = description; mode 3 = bond info
  412. if (mode == 2) { calcDiv.style.width = document.documentElement.clientWidth - clickX - 50 + "px"; }
  413. if (mode == 3) { calcDiv.style.zIndex = "203"; }
  414. //keep calc display from appearing below screen edge
  415. var divHeight = calcDiv.offsetHeight;
  416. var pageBottom = window.innerHeight + window.scrollY;
  417.  
  418. if (parseInt(calcDiv.style.top) > pageBottom - divHeight + 25)
  419. { calcDiv.style.top = pageBottom - divHeight + 25 + "px"; }
  420. //not sure why 25 is the magic number for bottom-edge tuning
  421. calcDiv.style.visibility = "visible";
  422. }
  423.  
  424. //--- read tag data for tagger and for building table
  425.  
  426. function readTag(ticker) {
  427.  
  428. var tagChar = "";
  429. var tagColor = "";
  430. var tagNote = "";
  431. var tagAllTickers = GM_getValue("tagTickers", "");
  432. ticker += " ";
  433. ticker = ticker.slice(0,7);
  434. var tickerIdx = tagAllTickers.indexOf(ticker);
  435.  
  436. if(tickerIdx > -1) {
  437. var setIdx = tickerIdx / 7 * 3 + 1; // this type of array starts at 1
  438. var splitCh = String.fromCharCode(255);
  439. var tagAllNotes = new Array();
  440. var tempStr = unescape(GM_getValue("tagNotes", ""));
  441. tagAllNotes = tempStr.split(splitCh);
  442.  
  443. tagChar = tagAllNotes[setIdx];
  444. tagColor = tagAllNotes[setIdx+1];
  445. tagNote = tagAllNotes[setIdx+2];
  446. }
  447.  
  448. return [tagChar,tagColor,tagNote];
  449. }
  450.  
  451. //--- tag weeder; kill off tags for sold or delisted items
  452.  
  453. function tagWeeder() {
  454. var tagTickers = GM_getValue("tagTickers", "");
  455. var arrowTickers = GM_getValue("prevTickers", "");
  456. if(arrowTickers == "") return;
  457.  
  458. // get each tag ticker and see if it still exists in the full port ticker list
  459. for(var i=0; i<tagTickers.length/7; i++) {
  460. var ticker = tagTickers.substr(i*7,7);
  461. if( !(arrowTickers.indexOf(ticker) > -1) ) {
  462. // did NOT find it, so call to have it deleted from tag set
  463. writeTag('delete',ticker);
  464. }
  465. }
  466. }
  467.  
  468. //--- write data from tagger
  469.  
  470. function writeTag(mode, ticker) {
  471.  
  472. var tagDiv = document.getElementById("tagPanel"); // get values from form
  473. var movie = document.getElementById("tagMovie").value;
  474. var tagChar = document.getElementById("tagChar").value;
  475. var tagColor = document.getElementById("tagColor").value;
  476. var tagNote = document.getElementById("tagNote").value;
  477.  
  478. var tagAllTickers = GM_getValue("tagTickers", "");
  479.  
  480. var tagWeeder = true; // ticker param. usually omitted, so tagWeeder will become false
  481. if (typeof ticker == "undefined") {
  482. var ticker = movie.substring(0,movie.indexOf('-')-1) + " ";
  483. ticker = ticker.slice(0,7);
  484. tagWeeder = false; // false will by typical use
  485. // if NO ticker has been passed, extract from available info; may be a save or normal delete
  486. // if ticker HAS been passed, should also be mode = 'delete'; we are weeding an orphaned tag
  487. }
  488.  
  489. var tickerIdx = tagAllTickers.indexOf(ticker);
  490. var setIdx = tickerIdx / 7 * 3 + 1; // this type of array starts at 1
  491.  
  492. var splitCh = String.fromCharCode(255);
  493. var tagAllNotes = new Array();
  494. var tempStr = unescape(GM_getValue("tagNotes", ""));
  495. tagAllNotes = tempStr.split(splitCh);
  496.  
  497. if(mode == "save" && tagChar != "" && tagChar != " ") { // new or edited; char must exist and be visible
  498. if ( !(tickerIdx > -1) ) { // add new tag
  499. tagAllTickers += ticker;
  500. GM_setValue("tagTickers", tagAllTickers);
  501. tagAllNotes.push(tagChar); tagAllNotes.push(tagColor); tagAllNotes.push(tagNote);
  502. }
  503. else { // modify existing tag; tickerIdx = 0,7,14; setIdx = 0,3,6
  504. tagAllNotes[setIdx] = tagChar;
  505. tagAllNotes[setIdx+1] = tagColor;
  506. tagAllNotes[setIdx+2] = tagNote;
  507. }
  508. refObjectTemp.textContent = tagChar;
  509. refObjectTemp.setAttribute("style","color:" + tagColor);
  510. refObjectTemp.title = tagNote;
  511.  
  512. // save current values as defaults for next use
  513. GM_setValue("tagPrevChar", tagChar);
  514. GM_setValue("tagPrevColor", tagColor);
  515. GM_setValue("tagPrevNote", tagNote);
  516.  
  517. }
  518. else if(mode == "delete") {
  519. var newAllTickers = "";
  520. if(tickerIdx > 0) newAllTickers = tagAllTickers.substring(0,tickerIdx);
  521. newAllTickers += tagAllTickers.substr(tickerIdx+7);
  522. GM_setValue("tagTickers", newAllTickers);
  523. tagAllNotes.splice(setIdx,3);
  524.  
  525. if(tagWeeder == false) { // if weeding, there's nothing on screen to clear
  526. refObjectTemp.textContent = "!|!";
  527. refObjectTemp.setAttribute("style","color:" + GM_getValue("opt_grayTxt", "#999999"));
  528. refObjectTemp.title = "";
  529. }
  530. }
  531.  
  532. // finalize and write the notes; tickers have already been written,above
  533. tempStr = tagAllNotes.join(splitCh);
  534. GM_setValue("tagNotes", escape(tempStr));
  535. GM_setValue("tagUsePrev", document.getElementById("tagUsePrev").checked);
  536.  
  537. tagDiv.style.visibility = "hidden";
  538. }
  539.  
  540. //--- tagger panel
  541.  
  542. function showTagger() {
  543. var tagDiv = document.getElementById("tagPanel");
  544. var movie = refObjectTemp.getAttribute("movie");
  545.  
  546. if(tagDiv.style.visibility == "hidden") {
  547. document.getElementById("tagMovie").value = movie;
  548. var ticker = movie.substring(0,movie.indexOf('-')-1);
  549. var tagData = readTag(ticker);
  550.  
  551. var tagUsePrev = GM_getValue("tagUsePrev", false);
  552. document.getElementById("tagUsePrev").checked = tagUsePrev;
  553.  
  554. if(tagData[0] == "" || tagUsePrev) { // new or checkbox; put values from last use
  555. document.getElementById("tagChar").value = GM_getValue("tagPrevChar", "&");
  556. document.getElementById("tagColor").value = GM_getValue("tagPrevColor", "blue");
  557. document.getElementById("tagNote").value = GM_getValue("tagPrevNote", "");
  558. if(tagData[0] == "") document.getElementById("tagDelete").disabled = true;
  559. else document.getElementById("tagDelete").disabled = false;
  560. }
  561. else { // use what we read for edit
  562. document.getElementById("tagChar").value = tagData[0];
  563. document.getElementById("tagColor").value = tagData[1];
  564. document.getElementById("tagNote").value = tagData[2];
  565. document.getElementById("tagDelete").disabled = false;
  566. }
  567. centerThis("tagPanel");
  568. tagDiv.style.visibility = "visible";
  569. document.getElementById("tagNote").focus();
  570. }
  571. }
  572.  
  573. //--- manage read/write of settings from the options panel
  574.  
  575. function optShowHide() {
  576.  
  577. var optDiv = document.getElementById("optionsPanel");
  578. if(optDiv.style.visibility == "hidden") { // then read
  579. document.getElementById("optnav").checked = GM_getValue("optnav", true);
  580.  
  581. if(GM_getValue("optarrowmode", "change") == "trend")
  582. { document.getElementById("optarrow3").checked = true; }
  583. else document.getElementById("optarrow4").checked = true;
  584.  
  585. if(GM_getValue("optmjump", "top") == "top")
  586. { document.getElementById("optmjump1").checked = true; }
  587. else document.getElementById("optmjump2").checked = true;
  588. document.getElementById("pmQtyAt").value = GM_getValue("pmQtyAt", "75k");
  589. document.getElementById("pmQtyBt").value = GM_getValue("pmQtyBt", "50k");
  590. document.getElementById("pmQtyCt").value = GM_getValue("pmQtyCt", "25k");
  591. document.getElementById("pmQtyAq").value = GM_getValue("pmQtyAq", "75000");
  592. document.getElementById("pmQtyBq").value = GM_getValue("pmQtyBq", "50000");
  593. document.getElementById("pmQtyCq").value = GM_getValue("pmQtyCq", "25000");
  594. document.getElementById("optpanelw").value = GM_getValue("optpanelw", "138");
  595. document.getElementById("optpanelh").value = GM_getValue("optpanelh", "400");
  596. document.getElementById("optpanelf").value = GM_getValue("optpanelf", "13");
  597. document.getElementById("optconfw").value = GM_getValue("optconfw", "275");
  598. document.getElementById("optconfh").value = GM_getValue("optconfh", "115");
  599. document.getElementById("optpgwidth").value = GM_getValue("optpgwidth", "900");
  600. centerThis("optionsPanel");
  601. optDiv.style.visibility = "visible";
  602. }
  603. else { // write
  604. GM_setValue("optnav",document.getElementById("optnav").checked);
  605.  
  606. if(document.getElementById("optarrow3").checked == true)
  607. { GM_setValue("optarrowmode","trend"); }
  608. else GM_setValue("optarrowmode","change");
  609.  
  610. if(document.getElementById("optmjump1").checked == true)
  611. { GM_setValue("optmjump","top"); }
  612. else GM_setValue("optmjump","MovieStocks");
  613.  
  614. GM_setValue("pmQtyAt", document.getElementById("pmQtyAt").value);
  615. GM_setValue("pmQtyBt", document.getElementById("pmQtyBt").value);
  616. GM_setValue("pmQtyCt", document.getElementById("pmQtyCt").value);
  617. GM_setValue("pmQtyAq", document.getElementById("pmQtyAq").value);
  618. GM_setValue("pmQtyBq", document.getElementById("pmQtyBq").value);
  619. GM_setValue("pmQtyCq", document.getElementById("pmQtyCq").value);
  620. GM_setValue("optpanelw", document.getElementById("optpanelw").value);
  621. GM_setValue("optpanelh", document.getElementById("optpanelh").value);
  622. GM_setValue("optpanelf", document.getElementById("optpanelf").value);
  623. GM_setValue("optconfw", document.getElementById("optconfw").value);
  624. GM_setValue("optconfh", document.getElementById("optconfh").value);
  625. GM_setValue("optpgwidth", document.getElementById("optpgwidth").value);
  626. optDiv.style.visibility = "hidden";
  627. }
  628. }
  629.  
  630. //--- receive and place orders from sidepanel links, via event listener
  631.  
  632. function placeOrder(orderType) {
  633.  
  634. if(refSymbol.value == "") return;
  635. if(refQuantity.value == "") refQuantity.value = "max";
  636.  
  637. var buildURL = "http://hsx.com/trade/?symbol=" + refSymbol.value + "&shares=" + refQuantity.value + "&action=place+order" + "&tradeType=" + orderType;
  638. var wh = "width=" + GM_getValue("optconfw", "275") + ",height=" + GM_getValue("optconfh", "115")
  639. var windowRef = window.open(buildURL, "conf", wh);
  640. }
  641.  
  642. //--- find first decimal in string; cut it and 2 places right, but preserve end
  643.  
  644. function stripDeci(str_in) {
  645.  
  646. var str_out = str_in;
  647. var idx = str_in.indexOf('.');
  648.  
  649. if(idx > -1) str_out = str_in.substring(0,idx) + str_in.substring(idx+3);
  650. return str_out;
  651. }
  652.  
  653. //--- remove commas, and possibly spaces
  654.  
  655. function numberClean(numStr) {
  656. var newStr = "";
  657. for(var i=0; i<numStr.length; i++) {
  658. if(numStr.charCodeAt(i) >= 48 && numStr.charCodeAt(i) <= 57) newStr += numStr.charAt(i);
  659. }
  660. return newStr;
  661. }
  662.  
  663. //--- access correct LTD standings page for ranktip amount; called by onceDaily
  664.  
  665. function doRankTip() {
  666. var ranklink = document.getElementById("ranklink");
  667. var idx = ranklink.textContent.indexOf(':');
  668. var rank = numberClean(ranklink.textContent.substring(idx+1));
  669. var tiptext = "It's good to be the Queen!";
  670. var urlLTD = "http://www.hsx.com/leader/?type=ltd&page=" + parseInt((rank-2)/100);
  671.  
  672. GM_xmlhttpRequest({
  673. method: 'GET',
  674. url: urlLTD,
  675. onload: function(response) {
  676. var doc = document.createElement('div');
  677. doc.innerHTML = response.responseText;
  678.  
  679. if(rank > 1) {
  680. if((rank-1) % 100 == 0) { // current player and higher port are on different pages
  681. var findRow = document.evaluate("//table[@class='sortable']//tr", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  682. var rowNode = findRow.snapshotItem(100);
  683. var higherPort = rowNode.childNodes[9].textContent;
  684. }
  685. else { // both on same page
  686. var findRank = document.evaluate("//table[@class='sortable']//td[ . = " + rank + "]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  687. var rankNode = findRank.snapshotItem(0);
  688. var higherPort = rankNode.parentNode.previousElementSibling.childNodes[9].textContent;
  689. }
  690. tiptext = "Next port to beat: H$" + higherPort;
  691. }
  692. ranklink.title = tiptext; // tooltip will show over Rank link
  693. GM_setValue("rankTipText",tiptext);
  694. }
  695. });
  696. }
  697.  
  698. //--- called after HSX reset, or by manual arrow reset
  699.  
  700. function onceDaily() {
  701. tagWeeder();
  702. doRankTip();
  703. GM_setValue("prevTickers", "");
  704. GM_setValue("prevPrices", "");
  705. }
  706.  
  707. //--- find document position of any object
  708.  
  709. function ObjectPosition(obj) {
  710. // this function by Peter-Paul Koch, http://www.quirksmode.org/js/findpos.html
  711. var curleft = 0;
  712. var curtop = 0;
  713. if (obj.offsetParent) {
  714. do {
  715. curleft += obj.offsetLeft;
  716. curtop += obj.offsetTop;
  717. } while (obj = obj.offsetParent);
  718. }
  719. return [curleft,curtop];
  720. }
  721.  
  722. //--- this section jump method avoids side-shift of existing anchors within table
  723.  
  724. function sectionJump(param) {
  725. var offseth = 0;
  726. var clienth = document.documentElement.clientHeight;
  727. switch(param) {
  728. case 1: // movies top
  729. var objpos = ObjectPosition(document.getElementById(GM_getValue("optmjump", "top"))); break;
  730. case 2: // bonds top
  731. case 5: // movies bottom
  732. var objpos = ObjectPosition(document.getElementById("StarBonds")); break;
  733. case 3: // derivitives top
  734. case 6: // bonds bottom
  735. var objpos = ObjectPosition(document.getElementById("Derivatives")); break;
  736. case 4:
  737. case 7:
  738. var objpos = ObjectPosition(document.getElementById("MovieFunds")); break;
  739. }
  740. if(param == 5 || param == 6 || param == 7) offseth = clienth + 12;
  741. scrollTo(pageXOffset,objpos[1]-12-offseth);
  742. }
  743.  
  744. //--- specific object event handlers, etc.
  745.  
  746. function putTicker(event) {
  747. refSymbol.value = event.target.textContent;
  748. holdStatus = event.target.getAttribute('alt');
  749. }
  750.  
  751. function hotkeysOff(event) {
  752. hotkeysActive = false;
  753. refObjectTemp = event.target; // used in keypress handler to see if Symbol box has focus
  754. }
  755.  
  756. function hotkeysOn() { hotkeysActive = true; }
  757.  
  758. function clearHoldStatus() {
  759. holdStatus = "";
  760. hotkeysActive = true;
  761. }
  762.  
  763. function getParam(tempstr) {
  764. var paren1 = tempstr.indexOf('(');
  765. var paren2 = tempstr.indexOf(')');
  766. return tempstr.substring(paren1+2,paren2-1);
  767. }
  768.  
  769. function ltrim(stringToTrim) {
  770. return stringToTrim.replace(/^\s+/,"");
  771. }
  772.  
  773. //--- global event listeners allow working across scopes
  774.  
  775. document.addEventListener('keydown', function(e) {
  776. if(!e) e=window.event;
  777. var key = e.keyCode;
  778. var quash = false;
  779.  
  780. if(url.indexOf('hsx.com/portfolio') > -1) {
  781. var tagPanelStyle = document.getElementById("tagPanel").style;
  782. if(key == 27 && tagPanelStyle.visibility == "visible")
  783. { tagPanelStyle.visibility = "hidden"; quash=true; }
  784.  
  785. if(key == 113) { // F2
  786. if (refNavbar.style.visibility == "hidden") {
  787. refNavbar.style.visibility = "visible";
  788. refMainDataDiv.style.top = "-45px";
  789. GM_setValue("optnav",true);
  790. }
  791. else {
  792. refNavbar.style.visibility = "hidden";
  793. refMainDataDiv.style.top = "-80px";
  794. GM_setValue("optnav",false);
  795. }
  796. quash=true;
  797. }
  798. }
  799. if(quash == true) {
  800. e.stopPropagation();
  801. e.preventDefault();
  802. }
  803. }, true);
  804.  
  805. document.addEventListener('keypress', function(e) {
  806. if(!e) e=window.event;
  807. var key = e.keyCode ? e.keyCode : e.which;
  808. var quash = false;
  809. //GM_log(key + " " + e.keyCode + " " + e.which);
  810. if(key == 13) {
  811. if(url.indexOf('hsx.com/trade') > -1) { window.close(); }
  812. else if(refObjectTemp.getAttribute('id') == "Symbol") {
  813. refSymbol.value = refSymbol.value.toUpperCase();
  814. fetchBondInfoA(0, 0, "symbol");
  815. refSymbol.select();
  816. }
  817. }
  818.  
  819. if(url.indexOf('hsx.com/portfolio') > -1) {
  820.  
  821. if(hotkeysActive == false) return;
  822.  
  823. var tagPanelStyle = document.getElementById("tagPanel").style;
  824. if(key == 13 && tagPanelStyle.visibility == "visible") { writeTag('save'); quash=true; }
  825.  
  826. if(document.getElementById("optionsPanel").style.visibility == "visible" || tagPanelStyle.visibility == "visible") { return; }
  827.  
  828. if(key == 44) { sectionJump(1); quash=true; } // < unshift
  829. if(key == 91) { sectionJump(2); quash=true; } // [
  830. if(key == 93) { sectionJump(6); quash=true; } // ]
  831. if(key == 61) { sectionJump(7); } // + unshift // w/FF4, quash killed zoom keys
  832.  
  833. if(e.keyCode == 0 && e.which == 45) { sectionJump(3); } // - !insert
  834. if(e.keyCode == 0 && e.which == 46) { sectionJump(5); quash=true; } // > unshift !delete
  835.  
  836. }
  837.  
  838. if(quash == true) {
  839. e.stopPropagation();
  840. e.preventDefault();
  841. }
  842. }, true);
  843.  
  844. document.addEventListener('mouseup', function(event) {
  845.  
  846. var calcDiv = document.getElementById("calcTip");
  847. // using zIndex value 103 to ID click-hold from click-clickable 203
  848. if (calcDiv.style.zIndex == "103") calcDiv.style.visibility = "hidden";
  849. mouseDown = false;
  850. }, true);
  851.  
  852. document.addEventListener('mousedown', function(event) {
  853.  
  854. var tempstr = new String(event.target);
  855. if(tempstr.indexOf('4div') > -1) {
  856. refObjectTemp = event.target;
  857. showCalc(event.pageX, event.pageY);
  858. event.stopPropagation();
  859. event.preventDefault();
  860. }
  861. if(tempstr.indexOf('info') > -1) {
  862. refObjectTemp = event.target;
  863. showDescription(event.pageX, event.pageY);
  864. mouseDown = true;
  865. event.stopPropagation();
  866. event.preventDefault();
  867. }
  868. if(tempstr.indexOf('iday') > -1) {
  869. refObjectTemp = event.target;
  870. intraday();
  871. event.stopPropagation();
  872. event.preventDefault();
  873. }
  874. }, true);
  875.  
  876. document.addEventListener('click', function(event) {
  877. var tempstr = new String(event.target);
  878. var quash = false;
  879.  
  880. if(tempstr.indexOf('putAmountPm') > -1) {
  881. var p = getParam(tempstr);
  882. if (p == "M") p = "max"
  883. else if (p == "75") p = GM_getValue("pmQtyAq", "75000")
  884. else if (p == "50") p = GM_getValue("pmQtyBq", "50000")
  885. else if (p == "25") p = GM_getValue("pmQtyCq", "25000")
  886. else p = "1"
  887. refQuantity.value = p;
  888. quash = true;
  889. }
  890.  
  891. if(event.target.id == "tagOK")
  892. { writeTag('save'); quash = true; }
  893.  
  894. if(event.target.id == "tagDelete")
  895. { writeTag('delete'); quash = true; }
  896.  
  897. if(event.target.id == "tagCancel") {
  898. GM_setValue("tagUsePrev", document.getElementById("tagUsePrev").checked);
  899. document.getElementById("tagPanel").style.visibility = "hidden";
  900. quash = true;
  901. }
  902.  
  903. if(event.target.id == "optButtonOKpm" || event.target == "javascript:optShowHide();")
  904. { optShowHide(); quash = true; }
  905.  
  906. if(event.target.id == "optButtonColors" || event.target.id == "colorOK")
  907. { colorShowHide(); quash = true; }
  908.  
  909. if(event.target.id == "colorDefaults")
  910. { colorShowHide(); colorDefaults(); quash = true; }
  911.  
  912. if(tempstr.indexOf('tagger') > -1)
  913. { refObjectTemp = event.target; showTagger(); quash = true; }
  914.  
  915. if(tempstr.indexOf('4div') > -1 || tempstr.indexOf('info') > -1 || tempstr.indexOf('iday') > -1)
  916. { quash = true; } //kill here; handled in mousedown
  917.  
  918. if(tempstr.indexOf('bondP') > -1) {
  919. // from bond owned in the port
  920. refObjectTemp = event.target;
  921. fetchBondInfoA(event.pageX, event.pageY, "inPort");
  922. quash = true;
  923. }
  924.  
  925. if(tempstr.indexOf('bondS') > -1) {
  926. // from symbol in the SBL box
  927. if (document.getElementById("calcTip").style.visibility == "hidden")
  928. { fetchBondInfoA(0, 0, "symbol"); }
  929. else document.getElementById("calcTip").style.visibility = "hidden";
  930. quash = true;
  931. }
  932.  
  933. if(tempstr.indexOf('closeTipPm') > -1) {
  934. document.getElementById("calcTip").style.visibility = "hidden";
  935. quash = true;
  936. }
  937.  
  938. if(tempstr.indexOf('placeOrderPm') > -1) {
  939. var tradetype = getParam(tempstr);
  940. placeOrder(tradetype);
  941. quash = true;
  942. }
  943.  
  944. if(tempstr.indexOf('arrowReset') > -1) {
  945. onceDaily();
  946. alert('Arrows will reset on port refresh.');
  947. quash = true;
  948. }
  949.  
  950. if(tempstr.indexOf('2clip') > -1) {
  951. if(tempstr.indexOf('movies') > -1) put2clipboard("sortable_MovieStocks");
  952. else put2clipboard("sortable_StarBonds");
  953. quash = true;
  954. }
  955.  
  956. if(tempstr.indexOf('idMissingMovies') > -1) {
  957. idMissingMovies();
  958. quash = true;
  959. }
  960.  
  961. if(tempstr.indexOf('sectionJump') > -1)
  962. { sectionJump(parseInt(tempstr.substr(23,1))); quash = true; }
  963.  
  964. if(quash == true) {
  965. //quash any further actions of events handled here
  966. event.stopPropagation();
  967. event.preventDefault();
  968. }
  969.  
  970. }, true);
  971.  
  972. //--- main script block from this point
  973. function HSXPortMonkey_Run() {
  974. //insertPickerCode();
  975. url = window.location.href; // get URL, determine whether port or trade page; save for later use
  976.  
  977. if(url.indexOf('hsx.com/portfolio') > -1) {
  978. var panelFontSize = GM_getValue("optpanelf", "13") + "px";
  979. var panelBG = GM_getValue("opt_panelBG","#F3F3F3");
  980. // revise HSX base styles
  981. GM_addStyle('#bodywrap {color:' + GM_getValue("opt_dataTxt","#444444") + '}' +
  982. 'p {color:' + GM_getValue("opt_panelTxt","#444444") + '}' +
  983. 'h1,h2,h4 {color:' + GM_getValue("opt_panelTxt","#444444") + '}' +
  984. 'h3 {color:' + GM_getValue("opt_dataTxt","#444444") + '}' +
  985. 'div.table_label p {color:' + GM_getValue("opt_grayTxt","#999999") + '}' +
  986. 'div.whitebox_content {background:' + GM_getValue("opt_dataBG","#FFFFFF") + '}' +
  987. 'body {background:' + GM_getValue("opt_pageBG","#FFFFFF") + '}' +
  988. 'a, a:visited {color:' + GM_getValue("opt_regLnk","#3597B2") + '; text-decoration:none}' +
  989. 'a:hover {color:' + GM_getValue("opt_regHov","#84B84B") + '}' +
  990. 'table,col,tr {border-color: ' + GM_getValue("opt_grid","#DDDDDD") + '}' +
  991. 'tr {border-top: solid 1px ' + GM_getValue("opt_grid","#DDDDDD") + '}' +
  992. 'th {color: ' + GM_getValue("opt_colLab","#FFFFFF") + '}' +
  993. 'thead {background-color: ' + GM_getValue("opt_colBG","#555555") + '}' +
  994. '.sorttable_sorted, .sorttable_sorted_reverse {background-color: #919191}' +
  995. 'h2 {font-size:1.6em; margin-bottom:.7em}');
  996. if(GM_getValue("opt_cutGrad", false)) GM_addStyle('#bodywrap {background: url() #1A1A1A}');
  997. if(GM_getValue("opt_cutGrid", false)) GM_addStyle('table,col,tr {border:none}');
  998. // text & link colors
  999. GM_addStyle('.pmGray {color: ' + GM_getValue("opt_grayTxt","#999999") + '}' +
  1000. '.pmBlack {color: ' + GM_getValue("opt_dataTxt","#444444") + '; font-weight: bold}' +
  1001. '.pmRed {color: ' + GM_getValue("opt_redTxt","#E30000") + '; font-weight: bold; font-style: italic}' +
  1002. '.pmGreen {color: ' + GM_getValue("opt_greenTxt","#038013") + '; font-weight: bold}' +
  1003. '.jlink, .jlink:visited {color: ' + GM_getValue("opt_jumpLnk","#84B84B") + '}' +
  1004. '.jlink:hover {color: ' + GM_getValue("opt_jumpHov","#3597B2") + '}' +
  1005. '.plink, .plink:visited {color: ' + GM_getValue("opt_panLnk","#3597B2") + '}' +
  1006. '.plink:hover {color: ' + GM_getValue("opt_panHov","#84B84B") + '}' +
  1007. '.qlink, .qlink:visited {color: ' + GM_getValue("opt_qLnk","#3597B2") + '; display: block; text-align: center}' +
  1008. '.qlink:hover {color: ' + GM_getValue("opt_qHov","#84B84B") + '}' +
  1009. 'a.pmbutton, a.pmbutton:visited {color: ' + GM_getValue("opt_butTxt","#3597B2") + '}' +
  1010. 'a.pmbutton:hover {color: ' + GM_getValue("opt_butHov","#84B84B") + '}' +
  1011. '.tlink {color: ' + GM_getValue("opt_dataTxt","#444444") + '}' +
  1012. '.tlink:hover {color:black}');
  1013. // tables
  1014. GM_addStyle('table.pmtrade td {border: 1px solid ' + panelBG + '; padding: 4px 3px 0; text-align: center; font-family: sans-serif; font-size:' + panelFontSize + '; line-height: 1}');
  1015. GM_addStyle('table.pmqty {border: 2px ridge silver; text-align:center; margin:0; padding: 0} table.pmqty td {background-color: ' + GM_getValue("opt_popQ","#FFF9E3") + '; text-align: center; font-family: sans-serif; font-size:' + panelFontSize + '; border: 1px solid ' + GM_getValue("opt_popQ","#FFF9E3") + '}');
  1016. GM_addStyle('table.calc {border: 2px ridge #FBEDBB} table.calc td {background-color: ' + GM_getValue("opt_popQ","#FFF9E3") + '; border: 1px solid ' + GM_getValue("opt_popQ","#FFF9E3") + '; padding: 0 3px}');
  1017.  
  1018. // buttons
  1019. GM_addStyle('.pmbutton {font-family: sans-serif; border: 1px solid ' + GM_getValue("opt_buttonShd","#000066") + '; background: ' + GM_getValue("opt_button","#D4E4ED") + '; display: block; text-align: center; border-width : 0px 1px 1px 0px; padding: 3px} .pmbutton:hover {font-weight: normal; border: 1px solid ' + GM_getValue("opt_buttonShd","#000066") + '; background: ' + GM_getValue("opt_buttonHov","#EBFFE9") + '; border-width : 0px 1px 1px 0px} .pmbutton:active {border: 1px solid #DA0808; background: ' + GM_getValue("opt_buttonHov","#EBFFE9") + '; border-width : 0px 1px 1px 0px}');
  1020.  
  1021. // misc.
  1022. GM_addStyle('input.color {text-align: center; width: 6em; font-size: 1.1em; line-height:1; margin:0em; padding: 3px}' +
  1023. 'input.pmInput {color: ' + GM_getValue("opt_inTxt","#444444") + '; background: ' + GM_getValue("opt_inBG","#FFFFFF") + '; width:98%; font-size: 1em; line-height:1; margin:0em; padding: 0}' +
  1024. 'input.w3 {width:2.5em}' +
  1025. '.pmSize {font-size:' + panelFontSize + '}' +
  1026. 'td.center,th.center {text-align: center}' +
  1027. 'p.para1 {line-height:115%; margin-bottom: .7em}');
  1028. // Firefox 3.5+ every other line in different color
  1029. GM_addStyle('table.sortable > tbody > tr:nth-child(2n) {background-color:' + GM_getValue("opt_stripe","#EBFFE9") + '}');
  1030.  
  1031. // overall width
  1032. var oaWidth = GM_getValue("optpgwidth", "900");
  1033. GM_addStyle('div.column.twelve,div.columns.twelve { width: ' + oaWidth + 'px ! important} ' +
  1034. 'div#container,div.container { width: ' + oaWidth + 'px ! important} ' +
  1035. 'div#navigation { width: ' + oaWidth + 'px ! important} ' +
  1036. 'div#navigation form#search-form {right: ' + (oaWidth<971?10:oaWidth-970+10) + 'px ! important} '); // search bar placement
  1037.  
  1038. // tweak column widths
  1039. GM_addStyle("table col.symbol { width:85px ! important} \
  1040. table col.quantity_held { width:95px ! important} \
  1041. table col.trade_transaction_type_id { width:20px ! important} \
  1042. table col.avg_price_paid { width:119px ! important} \
  1043. table col.price { width:123px ! important} \
  1044. table col.price_change { width:115px ! important} \
  1045. table col.pct_price_change { width:20px ! important} \
  1046. table col.tot_worth { width:150px ! important} \
  1047. table col.worth_change { width:150px ! important} \
  1048. table col.pct_worth_change { width:70px ! important} \
  1049. table col.trade_button { width:20px ! important}"); // had been 930 total
  1050.  
  1051. //--- make new add-in panel for portfolio info and trading
  1052.  
  1053. var networth = document.getElementById("net-worth").firstChild.nextSibling.textContent;
  1054. var cash = document.getElementById("cash-on-hand").firstChild.textContent;
  1055. var findtodaychange = document.evaluate("//span[@class='label']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1056. var todaychange = findtodaychange.snapshotItem(0).nextSibling.nextSibling.textContent;
  1057.  
  1058. var todaySpan = stripDeci(todaychange);
  1059. if(todaySpan.indexOf('-') > -1) todaySpan = "<span style='color:" + GM_getValue('opt_redTxt','#E30000') + "'>" + todaySpan + "</span>";
  1060.  
  1061. var findrankspan = document.evaluate("//span[@class='rank']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1062. var ranklink = findrankspan.snapshotItem(0).firstChild;
  1063. ranklink.setAttribute("id","ranklink"); // for later access
  1064. ranklink.setAttribute("class","plink");
  1065. ranklink.setAttribute("title",GM_getValue("rankTipText", ""));
  1066. var rankspan = findrankspan.snapshotItem(0).innerHTML;
  1067. var idx = rankspan.indexOf(')');
  1068. rankspan = rankspan.substring(0,idx+1) + "<br>" + rankspan.substring(idx+4);
  1069.  
  1070. var tradeDiv = document.createElement("div");
  1071. var tradeDivHtml = "<div style='padding:0 0 0 4px'><h2>My Portfolio</h2>" + "<p class='pmSize para1'><strong>Net Worth:</strong><br>" + stripDeci(networth) + "<p class='pmSize para1'><strong>Cash:</strong><br>" + stripDeci(cash) +
  1072.  
  1073. "<p class='pmSize para1'><strong>Today:</strong><br>" + todaySpan + " <a href='javascript:optShowHide();' class='plink' title='Set options'>" + String.fromCharCode(9829) + "</a>" +
  1074.  
  1075. "<p class='pmSize' style='line-height:115%; margin-bottom: .6em'>" + rankspan + "<br><a href='/leader/watchlist.php' class='plink'>Watchlist</a> - <a href='/portfolio/chart.php' class='plink'>Chart</a></div>" +
  1076.  
  1077. "<table class=pmtrade><tr><td align=right><a href='javascript:bondS;' class='plink'>SBL:</a></td><td><input class='pmInput' type=text id=Symbol maxlength=8 onfocus='this.select();' onblur='this.value = this.value.toUpperCase();' /></td></tr>" +
  1078.  
  1079. "<tr><td align=right style='color:" + GM_getValue("opt_panelTxt","#444444") + "'>QTY:</td><td><input type=text class='pmInput' id=Quantity maxlength=6 onfocus='this.select();' onblur='this.value = this.value.toLowerCase(); if(this.value != \"max\" && !(parseInt(this.value)>0)) this.value=\"\";' /></td></tr><tr><td colspan=2 style='padding-bottom: 3px'></td></tr><tr><td rowspan=4 valign=top>" +
  1080.  
  1081. "<table class=pmqty><tr><td><a href='javascript:putAmountPm(\"M\");' class=qlink>Max</a></td></tr><tr><td><a href='javascript:putAmountPm(\"75\");' class=qlink>" + GM_getValue("pmQtyAt","75k") + "</a></td></tr><tr><td><a href='javascript:putAmountPm(\"50\");' class=qlink>" + GM_getValue("pmQtyBt","50k") + "</a></td></tr><tr><td><a href='javascript:putAmountPm(\"25\");' class=qlink>" + GM_getValue("pmQtyCt","25k") + "</a></td></tr><tr><td style='padding-bottom: 3px'><a href='javascript:putAmountPm(\"R\");' class=qlink>1</a></td></tr></table>" +
  1082.  
  1083. "</td><td><a href='javascript:placeOrderPm(\"buy\");' class=pmbutton>Buy</a></td></tr><tr><td><a href='javascript:placeOrderPm(\"sell\");' class=pmbutton>Sell</a></td></tr><tr><td><a href='javascript:placeOrderPm(\"short\");' class=pmbutton>Short</a></td></tr><tr><td><a href='javascript:placeOrderPm(\"cover\");' class=pmbutton>Cover</a></td></tr></table>";
  1084.  
  1085. tradeDiv.innerHTML = tradeDivHtml;
  1086. tradeDiv.id = "tradePanel";
  1087. tradeDiv.style.position = "fixed";
  1088. tradeDiv.style.top = "111px";
  1089. tradeDiv.style.backgroundColor = panelBG;
  1090. tradeDiv.style.padding = "7px 5px";
  1091. tradeDiv.style.height = GM_getValue("optpanelh", "400") + "px";
  1092. tradeDiv.style.width = GM_getValue("optpanelw", "138") + "px";
  1093. tradeDiv.style.zIndex = "101";
  1094. tradeDiv.style.borderWidth = "1px";
  1095. tradeDiv.style.borderStyle = "solid";
  1096. tradeDiv.style.borderColor = GM_getValue("opt_cutBrd", false)?panelBG:"#151515";
  1097.  
  1098. //--- make new add-in panel for top-left links
  1099.  
  1100. var topDiv = document.createElement("div");
  1101. topDiv.innerHTML = "<p class='pmSize' style='line-height:155%; margin-bottom: 1em'><a href='javascript:sectionJump(1);' class='jlink' title='Keyboard shortcuts: < or > (unshifted) to top/bottom'>Moviestocks</a><br><a href='javascript:sectionJump(2);' class='jlink' title='Keyboard shortcuts: [ or ] to top/bottom'>Starbonds</a><br><a href='javascript:sectionJump(3);' class='jlink' title='Keyboard shortcuts: - or + (unshifted) to top/bottom'>Derivatives</a><br><a href='javascript:sectionJump(4);' class='jlink'>Movie Funds</a>";
  1102.  
  1103. topDiv.id = "topLinkPanel";
  1104. topDiv.style.position = "fixed";
  1105. topDiv.style.padding = "10px";
  1106. topDiv.style.height = "92px";
  1107. topDiv.style.width = parseInt(tradeDiv.style.width) - 8 + "px";
  1108. topDiv.style.zIndex = "102";
  1109. topDiv.style.backgroundColor = panelBG;
  1110. if(GM_getValue("opt_cutJlogo", false)) document.getElementById("top").style.left = "-148px";
  1111. else topDiv.style.background = "url(/images/logo.jpg)";
  1112.  
  1113. //--- make new add-in panel for Port Monkey options
  1114.  
  1115. var optDiv = document.createElement("div");
  1116. var optDivHtml = "<p><b><u>OPTIONS</u> - <a href='http://ez-edzep.tripod.com/' class='plink' title='Port Monkey homepage' target='_new'>Port Monkey</a></b> by EdZep" +
  1117.  
  1118. "<p>Show HSX nav bar: <input id='optnav' type='checkbox' /> (use keyboard F2 for live toggle)<br>" +
  1119.  
  1120. "Arrow mode: <input id='optarrow3' name='optarrowmode' type='radio' /> <a href='javascript:;' class='plink' title='A trend arrow remains until price movement changes direction' onclick='document.getElementById(\"optarrow3\").checked = true;'>trend</a>&nbsp;&nbsp; <input id='optarrow4' name='optarrowmode' type='radio' /> <a href='javascript:;' class='plink' title='A change arrow shows only if a price has changed since the last reload' onclick='document.getElementById(\"optarrow4\").checked = true;'>change</a><br>" +
  1121.  
  1122. "Movietsocks jump link / hotkey: <input id='optmjump1' name='optmjump' type='radio' /> to page top&nbsp;&nbsp; <input id='optmjump2' name='optmjump' type='radio' /> to section start</p>" +
  1123.  
  1124. "<p style='margin-bottom:-.6em'>Custom quantities (button text): <input id='pmQtyAt' type='text' maxlength='3' class=w3 />&nbsp;&nbsp;<input id='pmQtyBt' type='text' maxlength='3' class=w3 />&nbsp;&nbsp;<input id='pmQtyCt' type='text' maxlength='3' class=w3 /> from top, after Max<br>" +
  1125.  
  1126. "Custom quantities (amounts): <input id='pmQtyAq' type='text' maxlength='5' style='width:3.5em' />&nbsp;&nbsp;<input id='pmQtyBq' type='text' maxlength='5' style='width:3.5em' />&nbsp;&nbsp;<input id='pmQtyCq' type='text' maxlength='5' style='width:3.5em' /> (no commas)<br>" +
  1127.  
  1128. "Sidepanel width: <input id='optpanelw' type='text' maxlength='3' class=w3 />&nbsp;&nbsp; height: <input id='optpanelh' type='text' maxlength='3' class=w3 />&nbsp;&nbsp; font size: <input id='optpanelf' type='text' maxlength='2' style='width:2em' /> (all in pixels)<br>" +
  1129.  
  1130. "Confirm. window width: <input id='optconfw' type='text' maxlength='3' class=w3 />&nbsp;&nbsp;height: <input id='optconfh' type='text' maxlength='3' class=w3 /> px<br>" +
  1131.  
  1132. "Overall content width: <input id='optpgwidth' type='text' maxlength='4' class=w3 /> px</p>" +
  1133.  
  1134. "<hr><p style='margin-top:-.1em; margin-bottom:0'>Most changes occur on port refresh<p style='margin-top:.4em; margin-bottom:0'><input id='optButtonOKpm' type='button' value=' OK ' />";
  1135. optDivHtml += " <input id='optButtonColors' type='button' value=' Color Styler ' />";
  1136.  
  1137. optDiv.innerHTML = optDivHtml;
  1138. optDiv.id = "optionsPanel";
  1139. optDiv.style.position = "fixed";
  1140. optDiv.style.visibility = "hidden";
  1141. optDiv.style.backgroundColor = panelBG;
  1142. optDiv.style.padding = "10px";
  1143. optDiv.style.zIndex = "103";
  1144. optDiv.style.borderWidth = "5px";
  1145. optDiv.style.borderStyle = "ridge";
  1146. optDiv.style.borderColor = "gray";
  1147.  
  1148. //--- make new add-in panel for tagger
  1149.  
  1150. var tagDiv = document.createElement("div");
  1151. tagDiv.innerHTML = "<p><b><u>TAGGER</u></b><form style='margin-bottom:1.2em'><p>Security: <input id='tagMovie' type='text' disabled='disabled' style='width:23em' /><br>Tag character: <input id='tagChar' onblur='document.getElementById(\"tagNote\").focus();' type='text' maxlength='1' onfocus='this.select()' style='width:1.5em' />&nbsp;&nbsp; " +
  1152.  
  1153. "Tag color: <select id='tagColor' onchange='document.getElementById(\"tagNote\").focus();'><option>Black</option>.<option>Red</option><option>Purple</option><option>Magenta</option><option>Green</option><option>Lime</option><option>Blue</option><option>Turquoise</option></select><br>" +
  1154.  
  1155. "<p style='line-height:190%; margin-top:-.8em; margin-bottom:-.6em'>Tooltip note:<br><input id='tagNote' type='text' onfocus='this.select()' maxlength='60' style='width:28em' />" +
  1156.  
  1157. "<p style='margin-top:-.3em; margin-bottom:-.1em'>For edits, last values entered override existing: <input id='tagUsePrev' type='checkbox' /> <a href='javascript:;' class='plink' onclick='document.getElementById(\"tagUsePrev\").checked = !document.getElementById(\"tagUsePrev\").checked' title='OK, Cancel or Delete will save this setting.'>note</a></form>" +
  1158.  
  1159. "<hr><p style='margin-top:.8em; margin-bottom:0'><input id='tagOK' type='button' value=' OK ' /> <input id='tagCancel' type='button' value=' Cancel ' /> <input id='tagDelete' type='button' value=' Delete ' /></p>";
  1160.  
  1161. tagDiv.id = "tagPanel";
  1162. tagDiv.style.position = "fixed";
  1163. tagDiv.style.visibility = "hidden";
  1164. tagDiv.style.backgroundColor = panelBG;
  1165. tagDiv.style.padding = "10px";
  1166. tagDiv.style.zIndex = "103";
  1167. tagDiv.style.borderWidth = "5px";
  1168. tagDiv.style.borderStyle = "ridge";
  1169. tagDiv.style.borderColor = "gray";
  1170.  
  1171. //--- div panel for calculation pseudo-tooltip
  1172.  
  1173. var calcDiv = document.createElement("div");
  1174. calcDiv.id = "calcTip";
  1175. calcDiv.style.position = "absolute";
  1176. calcDiv.style.zIndex = "103";
  1177. calcDiv.style.visibility = "hidden";
  1178.  
  1179. //--- div panel for color picker
  1180.  
  1181. var colorDiv = document.createElement("div");
  1182. colorDiv.innerHTML = "<p><b><u>COLOR STYLER</u></b> - Click and pick!</p><div><div style='float:left'><p style='line-height:115%'>" +
  1183. "<input id='opt_pageBG' type='text' value='" + GM_getValue("opt_pageBG", "#FFFFFF") + "' class='color' /> Page background<br>" +
  1184. "<input id='opt_panelBG' type='text' value='" + GM_getValue("opt_panelBG", "#F3F3F3") + "' class='color' /> Panel background<br>" +
  1185. "<input id='opt_dataBG' type='text' value='" + GM_getValue("opt_dataBG", "#FFFFFF") + "' class='color' /> Data background<br>" +
  1186. "<input id='opt_panelTxt' type='text' value='" + GM_getValue("opt_panelTxt", "#444444") + "' class='color' /> Panel text<br>" +
  1187. "<input id='opt_dataTxt' type='text' value='" + GM_getValue("opt_dataTxt", "#444444") + "' class='color' /> Data text<br>" +
  1188. "<input id='opt_grayTxt' type='text' value='" + GM_getValue("opt_grayTxt", "#999999") + "' class='color' /> Data accent text<br>" +
  1189. "<input id='opt_greenTxt' type='text' value='" + GM_getValue("opt_greenTxt", "#038013") + "' class='color' /> Positive text<br>" +
  1190. "<input id='opt_redTxt' type='text' value='" + GM_getValue("opt_redTxt", "#E30000") + "' class='color' /> Negative text<br>" +
  1191. "<input id='opt_colBG' type='text' value='" + GM_getValue("opt_colBG", "#555555") + "' class='color' /> Column header<br>" +
  1192. "<input id='opt_colLab' type='text' value='" + GM_getValue("opt_colLab", "#FFFFFF") + "' class='color' /> Column label<br>" +
  1193. "<input id='opt_grid' type='text' value='" + GM_getValue("opt_grid", "#DDDDDD") + "' class='color' /> Data grid<br>" +
  1194. "<input id='opt_stripe' type='text' value='" + GM_getValue("opt_stripe", "#EBFFE9") + "' class='color' /> Data stripe<br>" +
  1195. "<input id='opt_inBG' type='text' value='" + GM_getValue("opt_inBG", "#FFFFFF") + "' class='color' /> Input background<br>" +
  1196. "<input id='opt_inTxt' type='text' value='" + GM_getValue("opt_inTxt", "#444444") + "' class='color' /> Input text" +
  1197. "</p></div><div style='float:right; padding:0 0 0 18px'><p style='line-height:115%'>" +
  1198. "<input id='opt_regLnk' type='text' value='" + GM_getValue("opt_regLnk", "#3597B2") + "' class='color' /> Data links<br>" +
  1199. "<input id='opt_regHov' type='text' value='" + GM_getValue("opt_regHov", "#84B84B") + "' class='color' /> Data hover<br>" +
  1200. "<input id='opt_jumpLnk' type='text' value='" + GM_getValue("opt_jumpLnk", "#84B84B") + "' class='color' /> Jump links<br>" +
  1201. "<input id='opt_jumpHov' type='text' value='" + GM_getValue("opt_jumpHov", "#3597B2") + "' class='color' /> Jump hover<br>" +
  1202. "<input id='opt_panLnk' type='text' value='" + GM_getValue("opt_panLnk", "#3597B2") + "' class='color' /> Panel links<br>" +
  1203. "<input id='opt_panHov' type='text' value='" + GM_getValue("opt_panHov", "#84B84B") + "' class='color' /> Panel hover<br>" +
  1204. "<input id='opt_qLnk' type='text' value='" + GM_getValue("opt_qLnk", "#3597B2") + "' class='color' /> Quick-pick links<br>" +
  1205. "<input id='opt_qHov' type='text' value='" + GM_getValue("opt_qHov", "#84B84B") + "' class='color' /> Quick-pick hover<br>" +
  1206. "<input id='opt_butTxt' type='text' value='" + GM_getValue("opt_butTxt", "#3597B2") + "' class='color' /> Button text<br>" +
  1207. "<input id='opt_butHov' type='text' value='" + GM_getValue("opt_butHov", "#84B84B") + "' class='color' /> Button text hover<br>" +
  1208. "<input id='opt_button' type='text' value='" + GM_getValue("opt_button", "#D4E4ED") + "' class='color' /> Button face<br>" +
  1209. "<input id='opt_buttonHov' type='text' value='" + GM_getValue("opt_buttonHov", "#EBFFE9") + "' class='color' /> Button face hover<br>" +
  1210. "<input id='opt_buttonShd' type='text' value='" + GM_getValue("opt_buttonShd", "#000066") + "' class='color' /> Button shadow<br>" +
  1211. "<input id='opt_popQ' type='text' value='" + GM_getValue("opt_popQ", "#FFF9E3") + "' class='color' /> Pop-up/Q-pick BG" +
  1212. "</p></div></div>" +
  1213. "<p><input id='opt_cutCorn' type='checkbox' /> Remove rounded white corners&nbsp;&nbsp; <input id='opt_cutGrid' type='checkbox' /> Remove data grid<br><input id='opt_cutGrad' type='checkbox' /> Remove gray gradient&nbsp;&nbsp; <input id='opt_cutBrd' type='checkbox' /> Remove panel border<br><input id='opt_cutJlogo' type='checkbox' /> Match jump link BG to panel&nbsp;&nbsp; <input id='opt_cutPx' type='checkbox' /> Shift data 4px left</p><hr><input id='colorOK' type='button' value=' OK ' /> <input type='button' onclick='document.getElementById(\"colorPanel\").style.left=\"-1000px\"' value=' Cancel ' /><input style='float:right' id='colorDefaults' type='button' value=' Default Colors ' />";
  1214.  
  1215. colorDiv.id = "colorPanel";
  1216. colorDiv.style.position = "fixed";
  1217. colorDiv.style.left = "-1000px";
  1218. colorDiv.style.backgroundColor = panelBG;
  1219. colorDiv.style.padding = "10px";
  1220. colorDiv.style.zIndex = "103";
  1221. colorDiv.style.borderWidth = "5px";
  1222. colorDiv.style.borderStyle = "ridge";
  1223. colorDiv.style.borderColor = "gray";
  1224.  
  1225. //--- place new panels into HTML
  1226.  
  1227. var item = document.getElementsByTagName("body")[0];
  1228. item.insertBefore(topDiv, item.firstChild);
  1229. item.insertBefore(tradeDiv, item.firstChild);
  1230. item.insertBefore(optDiv, item.firstChild);
  1231. item.insertBefore(tagDiv, item.firstChild);
  1232. item.insertBefore(calcDiv, item.firstChild);
  1233. item.insertBefore(colorDiv, item.firstChild);
  1234.  
  1235. //--- store global references to trade inputs, etc. for later use
  1236.  
  1237. refSymbol = document.getElementById("Symbol");
  1238. refSymbol.addEventListener("focus", hotkeysOff, false);
  1239. refSymbol.addEventListener("blur", clearHoldStatus, false);
  1240. refQuantity = document.getElementById("Quantity");
  1241. refQuantity.addEventListener("focus", hotkeysOff, false);
  1242. refQuantity.addEventListener("blur", hotkeysOn, false);
  1243.  
  1244. //--- reformat page features
  1245.  
  1246. // adjust width, and move content to leave space at left
  1247. var bodywrapstyle = document.getElementById("bodywrap").style;
  1248. bodywrapstyle.width = parseInt(oaWidth) + 8 + "px";
  1249. bodywrapstyle.left = parseInt(tradeDiv.style.width) + (GM_getValue("opt_cutPx", false)?8:12) + "px";
  1250.  
  1251. // put time display and see if it's time to clear trend arrows
  1252. var findTime = document.getElementsByTagName("dt");
  1253. var hsxTime = findTime[1].textContent;
  1254. var item = document.getElementById("account-actions");
  1255. item.setAttribute("style","color: dimgray");
  1256. item.innerHTML = item.innerHTML + "<br>" + hsxTime;
  1257. var cutItem = item.parentNode.childNodes[5]; // WHO YOU OWN slogan, to remove
  1258. try { cutItem.parentNode.removeChild(cutItem); }
  1259. catch(err) {}
  1260.  
  1261. var idx = hsxTime.indexOf(':');
  1262. var newTime = hsxTime.substr(idx+2,2) + hsxTime.substr(idx+5,2);
  1263. lastRefresh = GM_getValue("lastRefresh", "0000");
  1264. if(newTime < lastRefresh) onceDaily(); //reset actions
  1265. GM_setValue("lastRefresh", newTime);
  1266.  
  1267. // delete original top panels, jump links
  1268. var cutpanel = document.getElementById("announce_bar");
  1269. try { cutpanel.parentNode.removeChild(cutpanel); }
  1270. catch(err) {}
  1271.  
  1272. var findpanel = document.evaluate("//div[@class='four columns']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1273. var cutpanel0 = findpanel.snapshotItem(0);
  1274. var cutpanel1 = findpanel.snapshotItem(1);
  1275. var cutpanel2 = findpanel.snapshotItem(1).nextSibling.nextSibling;
  1276. cutpanel0.parentNode.removeChild(cutpanel0);
  1277. cutpanel1.parentNode.removeChild(cutpanel1);
  1278. cutpanel2.parentNode.removeChild(cutpanel2);
  1279.  
  1280. findpanel = document.evaluate("//div[@class='column-row secondary_nav']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1281. cutpanel = findpanel.snapshotItem(0);
  1282. cutpanel.parentNode.removeChild(cutpanel);
  1283.  
  1284. findpanel = document.evaluate("//p[@class='top']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1285. for(var i=0; i<findpanel.snapshotLength; i++) {
  1286. cutpanel = findpanel.snapshotItem(i);
  1287. cutpanel.parentNode.removeChild(cutpanel);
  1288. }
  1289.  
  1290. // remove rounded corners; needed to allow non-white data backgrounds
  1291. if(GM_getValue("opt_cutCorn", false)) {
  1292. findpanel = document.evaluate("//div[@class='whitebox_start']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1293. cutpanel = findpanel.snapshotItem(0);
  1294. cutpanel.parentNode.removeChild(cutpanel);
  1295. findpanel = document.evaluate("//div[@class='whitebox_stop']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1296. cutpanel = findpanel.snapshotItem(0);
  1297. cutpanel.parentNode.removeChild(cutpanel);
  1298. findpanel = document.evaluate("//div[@class='whitebox_content']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1299. findpanel.snapshotItem(0).style.padding = "10px 10px 5px";
  1300. }
  1301. // use/not use nav bar, and adjust vertical position of main data panel
  1302. refNavbar = document.getElementById("navigation"); // global reference for later use
  1303. findpanel = document.evaluate("//div[@class='column-row']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1304. refMainDataDiv = findpanel.snapshotItem(1); // global reference for later use
  1305.  
  1306. if(GM_getValue("optnav", true) == true) refMainDataDiv.style.top = "-45px";
  1307. else {
  1308. refNavbar.style.visibility = "hidden";
  1309. refMainDataDiv.style.top = "-80px";
  1310. }
  1311.  
  1312. // tidy up section summary info
  1313. findInfo = document.evaluate("//span[@class='summary_shares']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1314.  
  1315. for(var i=0; i<findInfo.snapshotLength; i++)
  1316. {
  1317. var item1 = findInfo.snapshotItem(i);
  1318. var item2 = item1.nextSibling.nextSibling;
  1319. var item3 = item2.nextSibling.nextSibling;
  1320. var item0 = item1.parentNode.firstChild.nextSibling;
  1321.  
  1322. item3.removeAttribute("class");
  1323. item3.textContent = "Gain: " + stripDeci(item3.textContent);
  1324. item3.setAttribute("style","position: absolute; left: 330px");
  1325. var linkyText = '';
  1326. // before moving stuff, get positions counts, for use in main loop, stocks not owned, etc.
  1327. var pText = item0.textContent;
  1328. positions[i] = parseInt(pText.substr(0,pText.indexOf(' ')));
  1329. if (i == 0) {
  1330. var item4 = item3.nextSibling.nextSibling;
  1331. item4.removeAttribute("class");
  1332. item4.setAttribute("style","position: absolute; right: 0px");
  1333. item4.firstChild.textContent = "Sort: ";
  1334. linkyText = "<b><a href='javascript:movies2clip();' title='Copy Moviestock holdings to clipboard'>" + String.fromCharCode(8623) + "</a> <a href='javascript:idMissingMovies();' title='List Moviestocks not owned'>" + String.fromCharCode(8800) + "</a><a href='javascript:arrowReset();' title='Reset arrows'>" + String.fromCharCode(9650) + "</a> |</b> ";
  1335. }
  1336.  
  1337. if (i == 1) {
  1338. linkyText = "<b><a href='javascript:bonds2clip();' title='Copy Starbond holdings to clipboard'>" + String.fromCharCode(8623) + "</a> |</b> ";
  1339. }
  1340. item0.innerHTML = linkyText + item0.innerHTML + " <b>|</b> " + item3.innerHTML;
  1341. item3.parentNode.removeChild(item3);
  1342. item2.parentNode.removeChild(item2);
  1343. item1.parentNode.removeChild(item1);
  1344. }
  1345.  
  1346. // add missing column dividers
  1347. var findtables = document.evaluate("//table[@class='sortable']//colgroup", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1348. var item = "", nodeToday = "", nodeGain = "", nodeGainPct = "";
  1349.  
  1350. for(var i=0; i<findtables.snapshotLength; i++)
  1351. {
  1352. try { // potential problem in some browsers
  1353. item = findtables.snapshotItem(i);
  1354. nodeToday = item.childNodes[10];
  1355. nodeGain = item.childNodes[16];
  1356. nodeGainPct = item.childNodes[18];
  1357. nodeToday.removeAttribute("style");
  1358. nodeGain.removeAttribute("style");
  1359. if (i==0) nodeGainPct.removeAttribute("style");
  1360. }
  1361. catch(err) {}
  1362. }
  1363.  
  1364. // tweak table headings
  1365. var findtables = document.evaluate("//th[@class='sorttable_alpha']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1366. var item = "", pNode = "";
  1367. //var nodeShares = "", nodeCurrent = "", nodeValue = "";
  1368. var nodeHeld = "", nodePaid = "", nodeToday = "";
  1369. var nodeTodayPct = "", nodeGain = "", nodeGainPct = "", nodeButton = "";
  1370.  
  1371. for(var i=0; i<findtables.snapshotLength; i++)
  1372. {
  1373. item = findtables.snapshotItem(i);
  1374. pNode = item.parentNode;
  1375.  
  1376. //nodeShares = pNode.childNodes[3];
  1377. nodeHeld = pNode.childNodes[5];
  1378. nodePaid = pNode.childNodes[7];
  1379. //nodeCurrent = pNode.childNodes[9];
  1380. nodeToday = pNode.childNodes[11];
  1381. nodeTodayPct = pNode.childNodes[13];
  1382. //nodeValue = pNode.childNodes[15];
  1383. nodeGain = pNode.childNodes[17];
  1384. nodeGainPct = pNode.childNodes[19];
  1385. nodeButton = pNode.childNodes[21];
  1386.  
  1387. nodeHeld.textContent = "&"; //String.fromCharCode(8727); //notes 9834, 9835; asterisks 8727, 10033
  1388. nodeHeld.setAttribute("class","center");
  1389. nodeHeld.setAttribute("title", "Tags (semi-sortable if page has been reloaded since tag entry)");
  1390. nodePaid.textContent = "Paid";
  1391. nodeToday.textContent = "Today";
  1392. nodeTodayPct.textContent = String.fromCharCode(9650); //up-arrow
  1393. nodeTodayPct.setAttribute("title", "Price movement arrows (not sortable)");
  1394. nodeGain.textContent = "Gain / Loss";
  1395. nodeGainPct.textContent = String.fromCharCode(177); //plus-minus
  1396.  
  1397. nodeButton.setAttribute("class","center");
  1398. if (i==0) {
  1399. nodeButton.textContent = String.fromCharCode(9733); //star
  1400. nodeButton.setAttribute("title", "Phase (not sortable)"); //916, delta
  1401. }
  1402. }
  1403.  
  1404. //--- tweak data for every single security
  1405.  
  1406. var findsecurities = document.evaluate("//div[@class='twelve columns last']//a[contains(@href,'security/view')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1407. var item = "", ppNode = "", held = "", nodePaid = "";
  1408. var nodeShares = "", nodeHeld = "", nodeCurrent = "", nodeToday = "";
  1409. var nodeTodayPct = "", nodeValue = "", nodeGain = "", nodeGainPct = "", nodeButton = "";
  1410.  
  1411. var tagChar = "", tagColor = ""; tagNote = ""; ititle = "";
  1412. var lightGray = GM_getValue("opt_grayTxt", "#999999");
  1413. var tagAllTickers = GM_getValue("tagTickers", "");
  1414. var arrowmode = GM_getValue("optarrowmode", "change");
  1415. var ticker = "", price = "", paddedTicker = "";
  1416. var allTickersNew = "", allPricesNew = "";
  1417. var allTickersOld = GM_getValue("prevTickers", "---"); // get trend info
  1418. var allPricesOld = GM_getValue("prevPrices", "---");
  1419.  
  1420. // pre-format trend arrows
  1421. var pkgarrowup = "<span class='pmGreen'>" + String.fromCharCode(9650) + "</span>";
  1422. var pkgarrowdown = "<span class='pmRed'>" + String.fromCharCode(9660) + "</span>";
  1423.  
  1424. // bigass loop; main impact on speed is here
  1425. for(var i=0; i<findsecurities.snapshotLength; i++)
  1426. {
  1427. item = findsecurities.snapshotItem(i);
  1428. ppNode = item.parentNode.parentNode;
  1429.  
  1430. nodeShares = ppNode.childNodes[3];
  1431. nodeHeld = ppNode.childNodes[5];
  1432. nodePaid = ppNode.childNodes[7];
  1433. nodeCurrent = ppNode.childNodes[9];
  1434. nodeToday = ppNode.childNodes[11];
  1435. nodeTodayPct = ppNode.childNodes[13];
  1436. nodeValue = ppNode.childNodes[15];
  1437. nodeGain = ppNode.childNodes[17];
  1438. nodeGainPct = ppNode.childNodes[19];
  1439. nodeButton = ppNode.childNodes[21];
  1440.  
  1441. ticker = item.textContent;
  1442. ititle = item.title; //used for tagger and phase
  1443. item.addEventListener("mouseover", putTicker, false);
  1444. held = nodeHeld.textContent;
  1445.  
  1446. if (held == "short") { nodeShares.innerHTML = "<span style='display:none;'>-</span><span class='pmRed'>" + nodeShares.textContent + "</span>"; }
  1447. else { nodeShares.innerHTML = "<span class='pmGreen'>" + nodeShares.textContent + "</span>"; }
  1448.  
  1449. var gainToday = nodeToday.textContent;
  1450.  
  1451. var todayColor = "tlink";
  1452. if (nodeToday.firstChild.getAttribute("class") == "down")
  1453. {
  1454. nodeToday.innerHTML = "<span class='pmRed'>-" + gainToday + "</span>";
  1455. todayColor = "pmRed";
  1456. }
  1457. else if (gainToday.substring(2) > 0)
  1458. {
  1459. nodeToday.innerHTML = "<span class='pmGreen'>" + gainToday + "</span>";
  1460. todayColor = "pmGreen";
  1461. }
  1462. else nodeToday.innerHTML = gainToday;
  1463.  
  1464. nodeHeld.removeAttribute("style");
  1465. nodeHeld.setAttribute("class","center");
  1466.  
  1467. nodePaid.innerHTML = "<a href='javascript:info;' alt='" + ticker + "' class='tlink'>" + nodePaid.textContent + "</a>";
  1468.  
  1469. // processes that only occur for movie section
  1470. if(i < positions[0]) {
  1471. var phase = ititle.charAt(ititle.lastIndexOf('(') + 1);
  1472. nodeButton.innerHTML = phase;
  1473. nodeButton.setAttribute("class","pmGray center"); // phase color default
  1474. if (phase == 'C') {
  1475. nodeButton.setAttribute("class","pmRed center");
  1476. nodeButton.setAttribute("style","font-style:normal");
  1477. }
  1478. if (phase == 'D') nodeButton.setAttribute("class","pmBlack center");
  1479. if (phase == 'P') nodeButton.setAttribute("class","pmGreen center");
  1480. ititle = ititle.substring(0,ititle.lastIndexOf('(')-1); //shortened, for tagger
  1481. nodeCurrent.innerHTML = "<a href='javascript:4div;' alt='" + ticker + "' class='tlink'>" + nodeCurrent.textContent + "</a>";
  1482. nodeToday.innerHTML = "<a href='javascript:iday;' alt='" + ticker + "' class='" + todayColor + "'>" + nodeToday.textContent + "</a>";
  1483. }
  1484. else nodeButton.innerHTML = ""; //remove trade button on lower sections
  1485.  
  1486. // processes that only occur for starbonds
  1487. if(i >= positions[0] && i < positions[0] + positions[1]) {
  1488. nodeCurrent.innerHTML = "<a href='javascript:bondP;' alt='" + ticker + "' class='tlink'>" + nodeCurrent.textContent + "</a>";
  1489. }
  1490.  
  1491. // put tags in place
  1492. tagChar = "!|!";
  1493. tagColor = lightGray;
  1494. tagNote = "";
  1495.  
  1496. paddedTicker = ticker + " ";
  1497. paddedTicker = paddedTicker.slice(0,7); // also used below, for arrow read
  1498.  
  1499. if(tagAllTickers.indexOf(paddedTicker) > -1) { // this is ticker pre-scan
  1500. var tagInfo = readTag(ticker); // switch back to all function call by removing condition around this
  1501. if(tagInfo[0] != "") {
  1502. tagChar = tagInfo[0];
  1503. tagColor = tagInfo[1];
  1504. tagNote = tagInfo[2];
  1505. }
  1506. }
  1507.  
  1508. nodeHeld.innerHTML = "<a href='javascript:tagger;' style='color:" + tagColor + "' title='" + tagNote + "' movie='" + ticker + " - " + ititle + "'>" + tagChar + "</a>";
  1509.  
  1510. nodeValue.textContent = stripDeci(nodeValue.textContent);
  1511.  
  1512. // format gain/loss and percent data
  1513. var gaintext = stripDeci(nodeGain.textContent);
  1514.  
  1515. if (nodeGainPct.textContent.indexOf('-') > -1)
  1516. { nodeGain.innerHTML = "<span class='pmRed'>-H$" + gaintext + "</span>"; }
  1517. else if (parseInt(gaintext) > 0)
  1518. { nodeGain.innerHTML = "<span class='pmGreen'>H$" + gaintext + "</span>"; }
  1519. else nodeGain.innerHTML = "H$" + gaintext;
  1520.  
  1521. var gainPct = nodeGainPct.textContent;
  1522. nodeGainPct.innerHTML = gainPct.substring(1,gainPct.length-5) + "%";
  1523.  
  1524. // trend arrows
  1525. price = nodeCurrent.textContent.slice(2);
  1526. var indicator = " ";
  1527. var tickerIdx = allTickersOld.indexOf(paddedTicker);
  1528. if (tickerIdx > -1) {
  1529. var oldPrice = parseFloat(allPricesOld.substr(tickerIdx,6));
  1530. if(arrowmode == "trend") indicator = allPricesOld.substr(tickerIdx + 6,1);
  1531.  
  1532. if (price > oldPrice) indicator = "^";
  1533. if (price < oldPrice) indicator = "v";
  1534. }
  1535.  
  1536. if (indicator == "v") nodeTodayPct.innerHTML = pkgarrowdown;
  1537. else if (indicator == "^") nodeTodayPct.innerHTML = pkgarrowup;
  1538. else nodeTodayPct.textContent = "";
  1539.  
  1540. allTickersNew += paddedTicker;
  1541. price = price + " ";
  1542. price = price.slice(0,6) + indicator;
  1543. allPricesNew += price;
  1544. }
  1545.  
  1546. // save trend info after loop concludes
  1547. GM_setValue("prevTickers", allTickersNew);
  1548. GM_setValue("prevPrices", allPricesNew);
  1549.  
  1550. }
  1551.  
  1552. else {
  1553. if (url.indexOf('symbol') < 0 || url.indexOf('shares') < 0 || url.indexOf('tradeType') < 0 || url.indexOf('action') < 0 || url.indexOf('limit') > -1 || url.indexOf('trade_origin_url') > -1) return;
  1554.  
  1555. // get trade info from URL, to use in CONFIRMATION WINDOW
  1556. var urlHash = url;
  1557. var chunk = new Array();
  1558. var eq = ""; var amp = "";
  1559. var tradeInfo = "";
  1560.  
  1561. for(var i=0; i<4; i++) {
  1562. eq = urlHash.indexOf('=');
  1563. amp = urlHash.indexOf('&');
  1564. chunk[i] = urlHash.substring(eq+1,amp);
  1565. if(i == 3) chunk[3] = urlHash.substring(eq+1);
  1566. if(chunk[i] != "submit" && chunk[i] != "place+order") {
  1567. tradeInfo += " " + chunk[i];
  1568. if(i < 3) tradeInfo += ",";
  1569. }
  1570. urlHash = urlHash.substring(amp+1);
  1571. }
  1572.  
  1573. // cut stuff out
  1574. var cutpanel = document.getElementById("announce_bar");
  1575. try { cutpanel.parentNode.removeChild(cutpanel); }
  1576. catch(err) {}
  1577. cutpanel = document.getElementById("header");
  1578. cutpanel.parentNode.removeChild(cutpanel);
  1579. cutpanel = document.getElementById("navigation");
  1580. cutpanel.parentNode.removeChild(cutpanel);
  1581. cutpanel = document.getElementById("footer");
  1582. cutpanel.parentNode.removeChild(cutpanel);
  1583. findpanel = document.evaluate("//div[@class='column-row']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1584. cutpanel = findpanel.snapshotItem(0);
  1585. cutpanel.parentNode.removeChild(cutpanel);
  1586. cutpanel = findpanel.snapshotItem(2);
  1587. cutpanel.parentNode.removeChild(cutpanel);
  1588. findpanel = document.evaluate("//div[@class='four columns last']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1589. cutpanel = findpanel.snapshotItem(0);
  1590. cutpanel.parentNode.removeChild(cutpanel);
  1591.  
  1592. // make new add-in panel with close button
  1593. var buttonDiv = document.createElement("div");
  1594. buttonDiv.innerHTML = "<form><input value='Close' onclick='javascript:window.close();' type='submit' title='Keyboard shortcut: Enter' />" + tradeInfo + "</form>";
  1595. buttonDiv.id = "buttonPanel";
  1596. buttonDiv.style.position = "relative";
  1597.  
  1598. // add panel, and cut out more
  1599. var h1 = document.getElementsByTagName("h1");
  1600. if(h1[0].textContent != "Trade Placed") {
  1601. document.title = "Failed!";
  1602. var item = document.getElementById("adv-trader-container");
  1603. item.insertBefore(buttonDiv, item.firstChild);
  1604. cutpanel = document.getElementById("advanced-trader-form");
  1605. cutpanel.parentNode.removeChild(cutpanel);
  1606. cutpanel = item.firstChild.nextSibling.nextSibling;
  1607. cutpanel.parentNode.removeChild(cutpanel);
  1608. cutpanel = item.firstChild.nextSibling.nextSibling.nextSibling;
  1609. cutpanel.parentNode.removeChild(cutpanel);
  1610. }
  1611. else {
  1612. document.title = tradeInfo; // trade success
  1613. var item = document.getElementById("reg-container");
  1614. item.insertBefore(buttonDiv, item.firstChild);
  1615. for (var i=0; i<5; i++) {
  1616. cutpanel = item.firstChild.nextSibling;
  1617. cutpanel.parentNode.removeChild(cutpanel);
  1618. }
  1619. cutpanel = item.firstChild.nextSibling;
  1620. cutpanel.innerHTML = "<span style='color: green; font-weight: bold'>Success!</span>";
  1621. }
  1622. }
  1623. }
  1624.  
  1625. HSXPortMonkey_Run();
  1626.  
  1627. })();
  1628. // End