Chat Control Panel

Adds a small panel to the top of the chat window with a list of macros, allowing you to fire chat macros with mouse actions.

  1. // ==UserScript==
  2. // @name Chat Control Panel
  3. // @namespace kol.interface.unfinished
  4. // @description Adds a small panel to the top of the chat window with a list of macros, allowing you to fire chat macros with mouse actions.
  5. // @include https://*kingdomofloathing.com/lchat.php*
  6. // @include https://*kingdomofloathing.com/mchat.php*
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @version 2.021
  10. // ==/UserScript==
  11.  
  12. //Version 2.021
  13. // - trying to correct some spacing issues
  14. //Version 2.02
  15. // - change to https
  16. //Version 2.01
  17. // - add @grant, convert GM_log to console.log
  18. //Version 2.0
  19. // - modified heavily to work with the new tabbed chat. This
  20. // changes the way the docking works, and there is now an
  21. // icon on the top right corner that toggles the appearance
  22. // of the panel instead of the bar on the right.
  23. //Version 1.0.3
  24. // - more minor interface changes
  25. // - resizing is now granular, always shrinking or growing by
  26. // a full entry.
  27. // - the toggle bar now stays on the right of the chat control
  28. // panel so you can quickly toggle on/off without moving
  29. // the mouse.
  30. // - the control panel sticks to the top when moved very close
  31. // to the top of the chat pane.
  32. //Version 1.0.2
  33. // - a minor aesthetic change, using partial transparency to
  34. // hide slightly less of the underlying chap panel text.
  35. //Version 1.0.1
  36. // - fix mouse-over message for resize dragging
  37. //Version 1.0
  38. // - changed the docking method, so you now click on a bar
  39. // on the right to dock it on the right
  40. // - added a pull bar next to the docking bar so you can
  41. // slide it anywhere in the chat pane
  42. // - the former docking tab (line) at the bottom is now a
  43. // pull tab so you can resize it to as many entries as
  44. // you want (or can fit).
  45. //Version 0.9
  46.  
  47. var height=unitHeight(5);
  48. var ccmds;
  49. var playername;
  50.  
  51. var dims;
  52.  
  53. function rollHandler() {
  54. var cp = document.getElementById('chatcp');
  55. var cph = document.getElementById('chatcp_handle');
  56. if (cp && cph) {
  57. var v = cp.getAttribute('style');
  58. var w = cph.getAttribute('style');
  59. if (v.match(/display\s*:\s*none/)) {
  60. cp.setAttribute('style',removeStyle(v,'display'));
  61. cph.setAttribute('style',removeStyle(w,'display'));
  62. saveDock(false);
  63. } else {
  64. cp.setAttribute('style','display:none;'+v);
  65. cph.setAttribute('style','display:none;'+w);
  66. saveDock(true);
  67. }
  68.  
  69. }
  70. }
  71.  
  72.  
  73. function replaceOrAddStyle(s,a,v) {
  74. var r = new RegExp(a+'\\s*:','i');
  75. var sa = s.split(';');
  76. for (var i=0;i<sa.length;i++) {
  77. var x = sa[i].match(r);
  78. if (x) {
  79. sa[i] = a+':'+v;
  80. return sa.join(';');
  81. }
  82. }
  83. return a+':'+v+';'+s;
  84. }
  85.  
  86. function removeStyle(s,a) {
  87. var r = new RegExp(a+'\\s*:','i');
  88. var sa = s.split(';');
  89. for (var i=0;i<sa.length;i++) {
  90. var x = sa[i].match(r);
  91. if (x) {
  92. sa[i] = '';
  93. return sa.join(';').replace(';;',';');
  94. }
  95. }
  96. return s;
  97. }
  98.  
  99. function getStyleAttr(s,a) {
  100. var r = new RegExp('(^|;\\s*)'+a+'\\s*:\\s*([0-9]+)','i');
  101. var x = s.match(r);
  102. if (x)
  103. return Number(x[2]);
  104. //console.log('could not find style: "' +a+'" in "'+s+'"');
  105. return -1;
  106. }
  107.  
  108. function setTopBorder(s) {
  109. return replaceOrAddStyle(s,'border-top','1px solid black');
  110. }
  111.  
  112. function removeTopBorder(s) {
  113. return removeStyle(s,'border-top');
  114. }
  115.  
  116. function setWidths(e) {
  117. getMaxDimensions();
  118. var cp = document.getElementById('chatcp');
  119. var cph = document.getElementById('chatcp_handle');
  120. var cpd = document.getElementById('chatcp_dock');
  121. if (cp && cph && cpd) {
  122. var w = (dims.headerw) ? dims.headerw : dims.width; //document.body.clientWidth-19;
  123. //console.log("Setting width to "+w);
  124. cph.setAttribute('style',cph.getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w+1)+'px;'));
  125. cp.setAttribute('style',cp.getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w+1)+'px;'));
  126. if (dims.headerw)
  127. cpd.setAttribute('style',cpd.getAttribute('style').replace(/left\s*:\s*[0-9;px]*/,'left:'+(dims.headerw-15)+'px;'));
  128. else
  129. cpd.setAttribute('style',cpd.getAttribute('style').replace(/left\s*:\s*[0-9;px]*/,'left:'+(w-15)+'px;'));
  130. var texts = document.getElementsByClassName('chatcp_text');
  131. for (var i=0;i<texts.length;i++) {
  132. texts[i].setAttribute('style',texts[i].getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w-56)+'px;'));
  133. }
  134. }
  135. }
  136.  
  137. function tHandler(e) {
  138. var ci = this.getAttribute('cmdidx');
  139. ccmds[ci] = this.value;
  140. saveTable(ccmds);
  141. if (e.keyCode==13)
  142. insertCmd(ccmds[ci]);
  143. }
  144.  
  145.  
  146. function insertCmd(c) {
  147. if (c)
  148. unsafeWindow.submitchat(c);
  149. }
  150.  
  151. function bHandler() {
  152. insertCmd(ccmds[this.getAttribute('cmdidx')]);
  153. }
  154.  
  155.  
  156. function addPanel() {
  157. height = restoreHeight();
  158. ccmds = restoreTable();
  159. var f = document.getElementById('ChatWindow');
  160. var cp = document.getElementById('chatcp');
  161. if (f && !cp) {
  162. placeDockIcon(f);
  163. cp = document.createElement('div');
  164. var w = (dims.headerw) ? dims.headerw : dims.width;//document.body.clientWidth-19;
  165. var p = restorePos();
  166. cp.setAttribute('style','height:'+height+'px;width:'+w+'px;'+((p>0)?'border-top:1px solid black;':'')+'background-image:-moz-linear-gradient(center top , white 50%, transparent 100%);z-index:7;font-size:12px;position:absolute;font-family:arial;left:2px;top:'+p+'px;');
  167. cp.setAttribute('id','chatcp');
  168.  
  169. var t = document.createElement('table');
  170. t.setAttribute('cellspacing','0');
  171. for(var i=0;unitHeight(i)<height;i++) {
  172. newEntry(i,w-40,t);
  173. }
  174.  
  175. var tt = document.createElement('table');
  176. tt.setAttribute('style','vertical-align:top;');
  177. var tr = document.createElement('tr');
  178. var td = document.createElement('td');
  179. tt.setAttribute('cellspacing','0');
  180. tt.setAttribute('cellpadding','0');
  181. td.setAttribute('style','vertical-align:top;');
  182. td.appendChild(t);
  183. tr.appendChild(td);
  184. td = document.createElement('td');
  185. var span = document.createElement('div');
  186. span.setAttribute('style','background:lightgray;height:'+(height-4)+'px;width:15px;position:relative;top:2px;');
  187. span.setAttribute('title','Click and drag to position the chat control panel.');
  188. span.setAttribute('class','chatcpbar');
  189. td.appendChild(span);
  190. tr.appendChild(td);
  191. tt.appendChild(tr);
  192.  
  193. cp.appendChild(tt);
  194.  
  195. var handle = document.createElement('div');
  196. handle.setAttribute('style','height:7px;width:'+(w+1)+'px;text-align:center;vertical-align:middle;border-bottom:1px solid black;background-color:transparent;z-index:8;font-size:12px;position:absolute;font-family:arial;left:2px;top:'+(p+height-3)+'px;');
  197. handle.setAttribute('id','chatcp_handle');
  198. handle.setAttribute('title','Click and drag to resize the chat control panel.');
  199. var a = document.createElement('img');
  200. a.setAttribute('src',"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%1E%00%00%00%05%08%02%00%00%00%DDC%CB%AD%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%07tIME%07%DA%0C%17%002%18%89S%DB%E9%00%00%00%19tEXtComment%00Created%20with%20GIMPW%81%0E%17%00%00%00%16IDAT%18%D3c%60%A0%19%60%FC%FF%FF%3F%C3%90%03C%D3%D5%00W%E9%05%FD%13%F9%A0%92%00%00%00%00IEND%AEB%60%82");
  201. handle.appendChild(a);
  202.  
  203. //handle.addEventListener('click',rollHandler,false);
  204. handle.addEventListener('mousedown',dragStartSize,false);
  205. cp.addEventListener('mousedown',dragStart,true);
  206. f.parentNode.insertBefore(cp,f);
  207. f.parentNode.insertBefore(handle,f);
  208.  
  209. //cp.appendChild(handle);
  210. window.addEventListener('resize',setWidths,false);
  211.  
  212. if (restoreDock())
  213. rollHandler();
  214. setWidths();
  215. }
  216. }
  217.  
  218. function unitHeight(u) {
  219. return u*27+5;
  220. }
  221.  
  222. function heightUnit(h) {
  223. return Math.floor((h-5)/27);
  224. }
  225.  
  226. function saveTable(t) {
  227. var pn = getPlayerNameFromCharpane();
  228. if (pn) {
  229. GM_setValue(pn+'_cmds',t.join('#####'));
  230. }
  231. }
  232.  
  233. function saveHeight(h) {
  234. height = h;
  235. var pn = getPlayerNameFromCharpane();
  236. if (pn) {
  237. GM_setValue(pn+'_cpheight',h);
  238. }
  239. }
  240.  
  241. function restoreHeight() {
  242. var pn = getPlayerNameFromCharpane();
  243. if (pn) {
  244. return Math.ceil(Number(GM_getValue(pn+'_cpheight',unitHeight(5))));
  245. }
  246. return Math.ceil(unitHeight(5));
  247. }
  248.  
  249. function saveDock(b) {
  250. var pn = getPlayerNameFromCharpane();
  251. if (pn) {
  252. GM_setValue(pn+'_docked',b);
  253. }
  254. }
  255.  
  256. function restoreDock() {
  257. var pn = getPlayerNameFromCharpane();
  258. if (pn) {
  259. return Boolean(GM_getValue(pn+'_docked',false));
  260. }
  261. }
  262.  
  263. function restoreTable() {
  264. var pn = getPlayerNameFromCharpane();
  265. if (pn) {
  266. var t = GM_getValue(pn+'_cmds','');
  267. if (t) {
  268. t = t.split('#####');
  269. return t;
  270. }
  271. }
  272. return ['Good morning clan-mates!', '/unequip all', '', '', ''];
  273. }
  274.  
  275.  
  276. function savePos(y) {
  277. var pn = getPlayerNameFromCharpane();
  278. if (pn) {
  279. GM_setValue(pn+'_pos',y);
  280. }
  281. }
  282.  
  283. function restorePos() {
  284. var pn = getPlayerNameFromCharpane();
  285. if (pn) {
  286. var t = Number(GM_getValue(pn+'_pos',2));
  287. return t;
  288. }
  289. return 2;
  290. }
  291.  
  292.  
  293. // utility to get player name; hacked/stolen from Antimarty's fortune cookie script
  294. function getPlayerNameFromCharpane() {
  295. var somef=window.parent.frames;
  296. var goo;
  297. for(var j=0;j<somef.length;j++) {
  298. if (somef[j].name=="charpane") {
  299. goo=somef[j];
  300. var username = goo.document.getElementsByTagName("b");
  301. if (!username || username.length < 1) return playername;
  302. username = username[0];
  303. if (!username) return playername;
  304. username = username.firstChild;
  305. if (!username) return playername;
  306. // in full mode the link is <a><b>Name</b></a>
  307. // in compact mode it's <b><a>Name</a></b>
  308. // so have to handle this, and also can use it to tell
  309. // whether it's in compact mode or not.
  310. var fullmode = true;
  311. while (username && username.nodeType == 1)
  312. {
  313. username = username.firstChild;
  314. fullmode = false;
  315. }
  316. if (!username) return playername;
  317. username = username.nodeValue;
  318. if (!username) return playername;
  319. username = username.toLowerCase();
  320. playername = username;
  321. return username;
  322. }
  323. }
  324. }
  325.  
  326.  
  327. // code to drag the panel around
  328. var d;
  329. function dragStart(event, id) {
  330. var cp = document.getElementById('chatcp');
  331. var cph = document.getElementById('chatcp_handle');
  332. if (cp && cph) {
  333. var v = getStyleAttr(cp.getAttribute('style'),'width');
  334. if (v>=0) {
  335. if (event.clientX<v-50)
  336. return;
  337. }
  338.  
  339. d = new Object();
  340. d.cp = cp;
  341. d.cph = cph;
  342. var x = event.clientX + window.scrollX;
  343. var y = event.clientY + window.scrollY;
  344.  
  345. // Save starting positions of cursor and element.
  346. d.cursorStartX = x;
  347. d.cursorStartY = y;
  348. d.elStartLeft = parseInt(cp.style.left, 10);
  349. d.elStartTop = parseInt(cp.style.top, 10);
  350.  
  351. d.baseH = getStyleAttr(cp.getAttribute('style'),'height');
  352.  
  353. if (isNaN(d.elStartLeft)) d.elStartLeft = 2;
  354. if (isNaN(d.elStartTop)) d.elStartTop = 2;
  355.  
  356. document.addEventListener("mousemove", dragGo, true);
  357. document.addEventListener("mouseup", dragStop, true);
  358. event.preventDefault();
  359. }
  360. }
  361.  
  362. // drag handler for positioning the panel
  363. function dragGo(event) {
  364. var x, y;
  365. // Get cursor position with respect to the page.
  366. y = event.clientY + window.scrollY;
  367.  
  368. //d.elNode.style.left = (d.elStartLeft + x - d.cursorStartX) + "px";
  369. if ((d.elStartTop + y - d.cursorStartY)>=(dims.headerw? (dims.headert+16) : (dims.top+16)) && (d.elStartTop + y - d.cursorStartY)<(dims.height+(dims.headerw? (dims.headert+16) : (dims.top+16)))-height) {
  370. if ((d.elStartTop + y - d.cursorStartY)<=3)
  371. y = d.cursorStartY - d.elStartTop;
  372. d.cp.style.top = (d.elStartTop + y - d.cursorStartY) + "px";
  373. if ((d.elStartTop + y - d.cursorStartY)>0)
  374. d.cp.setAttribute('style',setTopBorder(d.cp.getAttribute('style')));
  375. else
  376. d.cp.setAttribute('style',removeTopBorder(d.cp.getAttribute('style')));
  377. d.cph.style.top = (d.elStartTop + y - d.cursorStartY + d.baseH - 3) + "px";
  378. savePos(d.elStartTop + y - d.cursorStartY);
  379. }
  380. event.preventDefault();
  381. }
  382.  
  383. // terminate dragging to position the panel
  384. function dragStop(event) {
  385. // Stop capturing mousemove and mouseup events.
  386. document.removeEventListener("mousemove", dragGo, true);
  387. document.removeEventListener("mouseup", dragStop, true);
  388. d = null;
  389. }
  390.  
  391.  
  392. // code to resize the panel
  393. function dragStartSize(event, id) {
  394. var cp = document.getElementById('chatcp');
  395. var cph = document.getElementById('chatcp_handle');
  396. if (cp && cph) {
  397. d = new Object();
  398. d.cp = cp;
  399. d.cph = cph;
  400. var y = event.clientY + window.scrollY;
  401. d.baseH = getStyleAttr(cp.getAttribute('style'),'height');
  402. d.baseO = getStyleAttr(cph.getAttribute('style'),'top');
  403.  
  404. // Save starting positions of cursor and element.
  405. d.cursorStartY = y;
  406. d.elStartLeft = parseInt(cp.style.left, 10);
  407. d.elStartTop = parseInt(cp.style.top, 10);
  408.  
  409. if (isNaN(d.elStartLeft)) d.elStartLeft = 2;
  410. if (isNaN(d.elStartTop)) d.elStartTop = 2;
  411.  
  412. document.addEventListener("mousemove", dragGoSize, true);
  413. document.addEventListener("mouseup", dragStopSize, true);
  414. event.preventDefault();
  415. }
  416. }
  417.  
  418. // create cp index i in table t with width w
  419. function newEntry(i,w,t) {
  420. var tr = document.createElement('tr');
  421. tr.setAttribute('id','chatcp_index'+i);
  422. var td = document.createElement('td');
  423. var i1 = document.createElement('input');
  424. i1.setAttribute('type','button');
  425. //i1.setAttribute('value','>');
  426. //var arrow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAMCAYAAACEJVa/AAAAmklEQVQokaXSPQ5BURCG4YcNiGhUGpah0CpFQyOswUpElCLR24VFiJ8FqCQ6Ea7CkdwILseXvN3Mm5nJkJ0mFih8UftRcsIO9XdFuQyghBUSDJB/lky+YIwZrkE0RTEt2fzAOqyVYItyjCTNMcga/0guWKIm2GKYpW/SyaCLNkbhsAf0RaSFM/aoxAiG7uPPY5ofqaLnxYM9cgOSr1GycHbzaQAAAABJRU5ErkJggg==';
  427. //i1.setAttribute('style','font-size:9px;width:22px;');
  428. i1.setAttribute('style','background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAMCAYAAACEJVa/AAAAmklEQVQokaXSPQ5BURCG4YcNiGhUGpah0CpFQyOswUpElCLR24VFiJ8FqCQ6Ea7CkdwILseXvN3Mm5nJkJ0mFih8UftRcsIO9XdFuQyghBUSDJB/lky+YIwZrkE0RTEt2fzAOqyVYItyjCTNMcga/0guWKIm2GKYpW/SyaCLNkbhsAf0RaSFM/aoxAiG7uPPY5ofqaLnxYM9cgOSr1GycHbzaQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;');
  429. i1.setAttribute('cmdidx',i);
  430. i1.addEventListener('mouseup',bHandler,false);
  431. var i2 = document.createElement('input');
  432. i2.setAttribute('type','text');
  433. i2.setAttribute('width','128');
  434. i2.setAttribute('value',((i>=ccmds.length)?'':ccmds[i]));
  435. i2.setAttribute('class','chatcp_text');
  436. i2.setAttribute('style','font-size:9px;width:'+(w-22)+'px;height:13px;');
  437. i2.setAttribute('cmdidx',i);
  438. i2.addEventListener('keyup',tHandler,true);
  439. i2.addEventListener('change',tHandler,true);
  440. td.appendChild(i1);
  441. td.appendChild(i2);
  442. tr.appendChild(td);
  443. t.appendChild(tr);
  444. }
  445.  
  446. // update the interior of the panel during resizing
  447. function updateCPSize(h) {
  448. var bars = document.getElementsByClassName('chatcpbar');
  449. for (var i=0;i<bars.length;i++) {
  450. var s = bars[i].getAttribute('style');
  451. bars[i].setAttribute('style',replaceOrAddStyle(s,'height',(h-4)+'px'));
  452. }
  453. var last = heightUnit(h);
  454. var ins = document.getElementById('chatcp_index'+last);
  455. if (!ins) {
  456. // we must have an entry 0
  457. var w = document.getElementById('chatcp_index0');
  458. if (w) {
  459. var t = w.parentNode;
  460. w = getStyleAttr(w.firstChild.firstChild.nextSibling.getAttribute('style'),'width');
  461. for (var i=1;i<last;i++) {
  462. ins = document.getElementById('chatcp_index'+i);
  463. if (!ins) {
  464. newEntry(i,(w+16),t);
  465. }
  466. }
  467. }
  468. } else {
  469. var del = document.getElementById('chatcp_index'+last);
  470. while (del) {
  471. del.parentNode.removeChild(del);
  472. last++;
  473. del = document.getElementById('chatcp_index'+last);
  474. }
  475. }
  476. saveHeight(h);
  477. }
  478.  
  479. // drag handler for resizing the panel
  480. function dragGoSize(event) {
  481. var y;
  482. // Get cursor position with respect to the page.
  483. y = event.clientY + window.scrollY;
  484.  
  485. var delta = y - d.cursorStartY;
  486. if (delta!=0) {
  487. var newh = d.baseH + delta;
  488. if (newh>unitHeight(1) && newh<(dims.height+(dims.headerw? (dims.headert+16) : (dims.top+16)))) {
  489. newh = unitHeight(heightUnit(newh));
  490. delta = newh - d.baseH;
  491. d.cp.setAttribute('style',replaceOrAddStyle(d.cp.getAttribute('style'),'height',newh+'px'));
  492. d.cph.setAttribute('style',replaceOrAddStyle(d.cph.getAttribute('style'),'top',(d.baseO+delta)+'px'));
  493. updateCPSize(newh);
  494. }
  495. }
  496. event.preventDefault();
  497. }
  498.  
  499. // terminate dragging to resize the panel
  500. function dragStopSize(event) {
  501. // Stop capturing mousemove and mouseup events.
  502. document.removeEventListener("mousemove", dragGoSize, true);
  503. document.removeEventListener("mouseup", dragStopSize, true);
  504. d = null;
  505. }
  506.  
  507. function getMaxDimensions() {
  508. var chats = document.getElementsByClassName('chatdisplay');
  509. for (var i=0;i<chats.length;i++) {
  510. if (chats[i].style.display!='none') {
  511. var header = document.evaluate('.//div[@class="header"]',chats[i],null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
  512. dims = {top:Number(chats[i].style.top.replace(/[^0-9]+/,'')),width:Number(chats[i].clientWidth),height:Number(chats[i].style.height.replace(/[^0-9]+/,''))};
  513. if (header.singleNodeValue) {
  514. dims.headert = Number(header.singleNodeValue.style.top.replace(/[^0-9]+/,''));
  515. dims.headerw = Number(header.singleNodeValue.style.width.replace(/[^0-9]+/,''));
  516. }
  517. //console.log('dimensions: top='+dims.top+', width='+dims.width+', height='+dims.height+', offw='+chats[i].offsetWidth+', cw='+chats[i].clientWidth);
  518. chats[i].addEventListener('scroll',setWidths,false);
  519. return;
  520. }
  521. }
  522. }
  523.  
  524. function placeDockIcon(f) {
  525. var img=document.createElement('img');
  526. img.setAttribute('src',"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0E%00%00%00%0C%08%06%00%00%00R%80%8C%DA%00%00%00%01sRGB%00%AE%CE%1C%E9%00%00%00%06bKGD%00%00%00%00%00%00%F9C%BB%7F%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%07tIME%07%DC%03%1E%14)%06%E8D%1D%FA%00%00%00%19tEXtComment%00Created%20with%20GIMPW%81%0E%17%00%00%00%5BIDAT(%CF%ED%8F%A1%11%C0%20%10%04%97L%8Ay%85%A0%8F%EF%80b%9E%8EPt%81%A7%10%FC%23%A228TD%D6%9C%DA%99%DB%E0%EE%CE%017%40%CE%99Z%2BsNJ)%00%98%19%00)%A5M%EA%BD%3Fb%8C%91%D6%1A%00%AA%FA%DA1%06%22%B2%C9%E1%F4%EA%C5!%7F%E3%A7%1A%17%CC%8BJ%7F%13%D8%1D%F7%00%00%00%00IEND%AEB%60%82");
  527. if (dims.headerw)
  528. img.setAttribute('style','position:absolute;top:'+(dims.headert+1)+'px;left:'+(dims.headerw-15)+'px;z-index:7;');
  529. else
  530. img.setAttribute('style','position:absolute;top:'+(dims.top+2)+'px;left:'+(dims.width-15)+'px;z-index:7;');
  531. img.setAttribute('title','Click to toggle display of chat control panel.');
  532. img.setAttribute('id','chatcp_dock');
  533. img.addEventListener('click',rollHandler,false);
  534. f.parentNode.insertBefore(img,f);
  535. }
  536.  
  537.  
  538. function initialize() {
  539. getMaxDimensions();
  540. if (dims) {
  541. addPanel();
  542. }
  543. }
  544.  
  545. setTimeout(initialize,50);