您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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.
- // ==UserScript==
- // @name Chat Control Panel
- // @namespace kol.interface.unfinished
- // @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.
- // @include https://*kingdomofloathing.com/lchat.php*
- // @include https://*kingdomofloathing.com/mchat.php*
- // @grant GM_getValue
- // @grant GM_setValue
- // @version 2.021
- // ==/UserScript==
- //Version 2.021
- // - trying to correct some spacing issues
- //Version 2.02
- // - change to https
- //Version 2.01
- // - add @grant, convert GM_log to console.log
- //Version 2.0
- // - modified heavily to work with the new tabbed chat. This
- // changes the way the docking works, and there is now an
- // icon on the top right corner that toggles the appearance
- // of the panel instead of the bar on the right.
- //Version 1.0.3
- // - more minor interface changes
- // - resizing is now granular, always shrinking or growing by
- // a full entry.
- // - the toggle bar now stays on the right of the chat control
- // panel so you can quickly toggle on/off without moving
- // the mouse.
- // - the control panel sticks to the top when moved very close
- // to the top of the chat pane.
- //Version 1.0.2
- // - a minor aesthetic change, using partial transparency to
- // hide slightly less of the underlying chap panel text.
- //Version 1.0.1
- // - fix mouse-over message for resize dragging
- //Version 1.0
- // - changed the docking method, so you now click on a bar
- // on the right to dock it on the right
- // - added a pull bar next to the docking bar so you can
- // slide it anywhere in the chat pane
- // - the former docking tab (line) at the bottom is now a
- // pull tab so you can resize it to as many entries as
- // you want (or can fit).
- //Version 0.9
- var height=unitHeight(5);
- var ccmds;
- var playername;
- var dims;
- function rollHandler() {
- var cp = document.getElementById('chatcp');
- var cph = document.getElementById('chatcp_handle');
- if (cp && cph) {
- var v = cp.getAttribute('style');
- var w = cph.getAttribute('style');
- if (v.match(/display\s*:\s*none/)) {
- cp.setAttribute('style',removeStyle(v,'display'));
- cph.setAttribute('style',removeStyle(w,'display'));
- saveDock(false);
- } else {
- cp.setAttribute('style','display:none;'+v);
- cph.setAttribute('style','display:none;'+w);
- saveDock(true);
- }
- }
- }
- function replaceOrAddStyle(s,a,v) {
- var r = new RegExp(a+'\\s*:','i');
- var sa = s.split(';');
- for (var i=0;i<sa.length;i++) {
- var x = sa[i].match(r);
- if (x) {
- sa[i] = a+':'+v;
- return sa.join(';');
- }
- }
- return a+':'+v+';'+s;
- }
- function removeStyle(s,a) {
- var r = new RegExp(a+'\\s*:','i');
- var sa = s.split(';');
- for (var i=0;i<sa.length;i++) {
- var x = sa[i].match(r);
- if (x) {
- sa[i] = '';
- return sa.join(';').replace(';;',';');
- }
- }
- return s;
- }
- function getStyleAttr(s,a) {
- var r = new RegExp('(^|;\\s*)'+a+'\\s*:\\s*([0-9]+)','i');
- var x = s.match(r);
- if (x)
- return Number(x[2]);
- //console.log('could not find style: "' +a+'" in "'+s+'"');
- return -1;
- }
- function setTopBorder(s) {
- return replaceOrAddStyle(s,'border-top','1px solid black');
- }
- function removeTopBorder(s) {
- return removeStyle(s,'border-top');
- }
- function setWidths(e) {
- getMaxDimensions();
- var cp = document.getElementById('chatcp');
- var cph = document.getElementById('chatcp_handle');
- var cpd = document.getElementById('chatcp_dock');
- if (cp && cph && cpd) {
- var w = (dims.headerw) ? dims.headerw : dims.width; //document.body.clientWidth-19;
- //console.log("Setting width to "+w);
- cph.setAttribute('style',cph.getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w+1)+'px;'));
- cp.setAttribute('style',cp.getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w+1)+'px;'));
- if (dims.headerw)
- cpd.setAttribute('style',cpd.getAttribute('style').replace(/left\s*:\s*[0-9;px]*/,'left:'+(dims.headerw-15)+'px;'));
- else
- cpd.setAttribute('style',cpd.getAttribute('style').replace(/left\s*:\s*[0-9;px]*/,'left:'+(w-15)+'px;'));
- var texts = document.getElementsByClassName('chatcp_text');
- for (var i=0;i<texts.length;i++) {
- texts[i].setAttribute('style',texts[i].getAttribute('style').replace(/width\s*:\s*[0-9;px]*/,'width:'+(w-56)+'px;'));
- }
- }
- }
- function tHandler(e) {
- var ci = this.getAttribute('cmdidx');
- ccmds[ci] = this.value;
- saveTable(ccmds);
- if (e.keyCode==13)
- insertCmd(ccmds[ci]);
- }
- function insertCmd(c) {
- if (c)
- unsafeWindow.submitchat(c);
- }
- function bHandler() {
- insertCmd(ccmds[this.getAttribute('cmdidx')]);
- }
- function addPanel() {
- height = restoreHeight();
- ccmds = restoreTable();
- var f = document.getElementById('ChatWindow');
- var cp = document.getElementById('chatcp');
- if (f && !cp) {
- placeDockIcon(f);
- cp = document.createElement('div');
- var w = (dims.headerw) ? dims.headerw : dims.width;//document.body.clientWidth-19;
- var p = restorePos();
- 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;');
- cp.setAttribute('id','chatcp');
- var t = document.createElement('table');
- t.setAttribute('cellspacing','0');
- for(var i=0;unitHeight(i)<height;i++) {
- newEntry(i,w-40,t);
- }
- var tt = document.createElement('table');
- tt.setAttribute('style','vertical-align:top;');
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- tt.setAttribute('cellspacing','0');
- tt.setAttribute('cellpadding','0');
- td.setAttribute('style','vertical-align:top;');
- td.appendChild(t);
- tr.appendChild(td);
- td = document.createElement('td');
- var span = document.createElement('div');
- span.setAttribute('style','background:lightgray;height:'+(height-4)+'px;width:15px;position:relative;top:2px;');
- span.setAttribute('title','Click and drag to position the chat control panel.');
- span.setAttribute('class','chatcpbar');
- td.appendChild(span);
- tr.appendChild(td);
- tt.appendChild(tr);
- cp.appendChild(tt);
- var handle = document.createElement('div');
- 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;');
- handle.setAttribute('id','chatcp_handle');
- handle.setAttribute('title','Click and drag to resize the chat control panel.');
- var a = document.createElement('img');
- 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");
- handle.appendChild(a);
- //handle.addEventListener('click',rollHandler,false);
- handle.addEventListener('mousedown',dragStartSize,false);
- cp.addEventListener('mousedown',dragStart,true);
- f.parentNode.insertBefore(cp,f);
- f.parentNode.insertBefore(handle,f);
- //cp.appendChild(handle);
- window.addEventListener('resize',setWidths,false);
- if (restoreDock())
- rollHandler();
- setWidths();
- }
- }
- function unitHeight(u) {
- return u*27+5;
- }
- function heightUnit(h) {
- return Math.floor((h-5)/27);
- }
- function saveTable(t) {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- GM_setValue(pn+'_cmds',t.join('#####'));
- }
- }
- function saveHeight(h) {
- height = h;
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- GM_setValue(pn+'_cpheight',h);
- }
- }
- function restoreHeight() {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- return Math.ceil(Number(GM_getValue(pn+'_cpheight',unitHeight(5))));
- }
- return Math.ceil(unitHeight(5));
- }
- function saveDock(b) {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- GM_setValue(pn+'_docked',b);
- }
- }
- function restoreDock() {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- return Boolean(GM_getValue(pn+'_docked',false));
- }
- }
- function restoreTable() {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- var t = GM_getValue(pn+'_cmds','');
- if (t) {
- t = t.split('#####');
- return t;
- }
- }
- return ['Good morning clan-mates!', '/unequip all', '', '', ''];
- }
- function savePos(y) {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- GM_setValue(pn+'_pos',y);
- }
- }
- function restorePos() {
- var pn = getPlayerNameFromCharpane();
- if (pn) {
- var t = Number(GM_getValue(pn+'_pos',2));
- return t;
- }
- return 2;
- }
- // utility to get player name; hacked/stolen from Antimarty's fortune cookie script
- function getPlayerNameFromCharpane() {
- var somef=window.parent.frames;
- var goo;
- for(var j=0;j<somef.length;j++) {
- if (somef[j].name=="charpane") {
- goo=somef[j];
- var username = goo.document.getElementsByTagName("b");
- if (!username || username.length < 1) return playername;
- username = username[0];
- if (!username) return playername;
- username = username.firstChild;
- if (!username) return playername;
- // in full mode the link is <a><b>Name</b></a>
- // in compact mode it's <b><a>Name</a></b>
- // so have to handle this, and also can use it to tell
- // whether it's in compact mode or not.
- var fullmode = true;
- while (username && username.nodeType == 1)
- {
- username = username.firstChild;
- fullmode = false;
- }
- if (!username) return playername;
- username = username.nodeValue;
- if (!username) return playername;
- username = username.toLowerCase();
- playername = username;
- return username;
- }
- }
- }
- // code to drag the panel around
- var d;
- function dragStart(event, id) {
- var cp = document.getElementById('chatcp');
- var cph = document.getElementById('chatcp_handle');
- if (cp && cph) {
- var v = getStyleAttr(cp.getAttribute('style'),'width');
- if (v>=0) {
- if (event.clientX<v-50)
- return;
- }
- d = new Object();
- d.cp = cp;
- d.cph = cph;
- var x = event.clientX + window.scrollX;
- var y = event.clientY + window.scrollY;
- // Save starting positions of cursor and element.
- d.cursorStartX = x;
- d.cursorStartY = y;
- d.elStartLeft = parseInt(cp.style.left, 10);
- d.elStartTop = parseInt(cp.style.top, 10);
- d.baseH = getStyleAttr(cp.getAttribute('style'),'height');
- if (isNaN(d.elStartLeft)) d.elStartLeft = 2;
- if (isNaN(d.elStartTop)) d.elStartTop = 2;
- document.addEventListener("mousemove", dragGo, true);
- document.addEventListener("mouseup", dragStop, true);
- event.preventDefault();
- }
- }
- // drag handler for positioning the panel
- function dragGo(event) {
- var x, y;
- // Get cursor position with respect to the page.
- y = event.clientY + window.scrollY;
- //d.elNode.style.left = (d.elStartLeft + x - d.cursorStartX) + "px";
- 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) {
- if ((d.elStartTop + y - d.cursorStartY)<=3)
- y = d.cursorStartY - d.elStartTop;
- d.cp.style.top = (d.elStartTop + y - d.cursorStartY) + "px";
- if ((d.elStartTop + y - d.cursorStartY)>0)
- d.cp.setAttribute('style',setTopBorder(d.cp.getAttribute('style')));
- else
- d.cp.setAttribute('style',removeTopBorder(d.cp.getAttribute('style')));
- d.cph.style.top = (d.elStartTop + y - d.cursorStartY + d.baseH - 3) + "px";
- savePos(d.elStartTop + y - d.cursorStartY);
- }
- event.preventDefault();
- }
- // terminate dragging to position the panel
- function dragStop(event) {
- // Stop capturing mousemove and mouseup events.
- document.removeEventListener("mousemove", dragGo, true);
- document.removeEventListener("mouseup", dragStop, true);
- d = null;
- }
- // code to resize the panel
- function dragStartSize(event, id) {
- var cp = document.getElementById('chatcp');
- var cph = document.getElementById('chatcp_handle');
- if (cp && cph) {
- d = new Object();
- d.cp = cp;
- d.cph = cph;
- var y = event.clientY + window.scrollY;
- d.baseH = getStyleAttr(cp.getAttribute('style'),'height');
- d.baseO = getStyleAttr(cph.getAttribute('style'),'top');
- // Save starting positions of cursor and element.
- d.cursorStartY = y;
- d.elStartLeft = parseInt(cp.style.left, 10);
- d.elStartTop = parseInt(cp.style.top, 10);
- if (isNaN(d.elStartLeft)) d.elStartLeft = 2;
- if (isNaN(d.elStartTop)) d.elStartTop = 2;
- document.addEventListener("mousemove", dragGoSize, true);
- document.addEventListener("mouseup", dragStopSize, true);
- event.preventDefault();
- }
- }
- // create cp index i in table t with width w
- function newEntry(i,w,t) {
- var tr = document.createElement('tr');
- tr.setAttribute('id','chatcp_index'+i);
- var td = document.createElement('td');
- var i1 = document.createElement('input');
- i1.setAttribute('type','button');
- //i1.setAttribute('value','>');
- //var arrow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAMCAYAAACEJVa/AAAAmklEQVQokaXSPQ5BURCG4YcNiGhUGpah0CpFQyOswUpElCLR24VFiJ8FqCQ6Ea7CkdwILseXvN3Mm5nJkJ0mFih8UftRcsIO9XdFuQyghBUSDJB/lky+YIwZrkE0RTEt2fzAOqyVYItyjCTNMcga/0guWKIm2GKYpW/SyaCLNkbhsAf0RaSFM/aoxAiG7uPPY5ofqaLnxYM9cgOSr1GycHbzaQAAAABJRU5ErkJggg==';
- //i1.setAttribute('style','font-size:9px;width:22px;');
- i1.setAttribute('style','background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAMCAYAAACEJVa/AAAAmklEQVQokaXSPQ5BURCG4YcNiGhUGpah0CpFQyOswUpElCLR24VFiJ8FqCQ6Ea7CkdwILseXvN3Mm5nJkJ0mFih8UftRcsIO9XdFuQyghBUSDJB/lky+YIwZrkE0RTEt2fzAOqyVYItyjCTNMcga/0guWKIm2GKYpW/SyaCLNkbhsAf0RaSFM/aoxAiG7uPPY5ofqaLnxYM9cgOSr1GycHbzaQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;');
- i1.setAttribute('cmdidx',i);
- i1.addEventListener('mouseup',bHandler,false);
- var i2 = document.createElement('input');
- i2.setAttribute('type','text');
- i2.setAttribute('width','128');
- i2.setAttribute('value',((i>=ccmds.length)?'':ccmds[i]));
- i2.setAttribute('class','chatcp_text');
- i2.setAttribute('style','font-size:9px;width:'+(w-22)+'px;height:13px;');
- i2.setAttribute('cmdidx',i);
- i2.addEventListener('keyup',tHandler,true);
- i2.addEventListener('change',tHandler,true);
- td.appendChild(i1);
- td.appendChild(i2);
- tr.appendChild(td);
- t.appendChild(tr);
- }
- // update the interior of the panel during resizing
- function updateCPSize(h) {
- var bars = document.getElementsByClassName('chatcpbar');
- for (var i=0;i<bars.length;i++) {
- var s = bars[i].getAttribute('style');
- bars[i].setAttribute('style',replaceOrAddStyle(s,'height',(h-4)+'px'));
- }
- var last = heightUnit(h);
- var ins = document.getElementById('chatcp_index'+last);
- if (!ins) {
- // we must have an entry 0
- var w = document.getElementById('chatcp_index0');
- if (w) {
- var t = w.parentNode;
- w = getStyleAttr(w.firstChild.firstChild.nextSibling.getAttribute('style'),'width');
- for (var i=1;i<last;i++) {
- ins = document.getElementById('chatcp_index'+i);
- if (!ins) {
- newEntry(i,(w+16),t);
- }
- }
- }
- } else {
- var del = document.getElementById('chatcp_index'+last);
- while (del) {
- del.parentNode.removeChild(del);
- last++;
- del = document.getElementById('chatcp_index'+last);
- }
- }
- saveHeight(h);
- }
- // drag handler for resizing the panel
- function dragGoSize(event) {
- var y;
- // Get cursor position with respect to the page.
- y = event.clientY + window.scrollY;
- var delta = y - d.cursorStartY;
- if (delta!=0) {
- var newh = d.baseH + delta;
- if (newh>unitHeight(1) && newh<(dims.height+(dims.headerw? (dims.headert+16) : (dims.top+16)))) {
- newh = unitHeight(heightUnit(newh));
- delta = newh - d.baseH;
- d.cp.setAttribute('style',replaceOrAddStyle(d.cp.getAttribute('style'),'height',newh+'px'));
- d.cph.setAttribute('style',replaceOrAddStyle(d.cph.getAttribute('style'),'top',(d.baseO+delta)+'px'));
- updateCPSize(newh);
- }
- }
- event.preventDefault();
- }
- // terminate dragging to resize the panel
- function dragStopSize(event) {
- // Stop capturing mousemove and mouseup events.
- document.removeEventListener("mousemove", dragGoSize, true);
- document.removeEventListener("mouseup", dragStopSize, true);
- d = null;
- }
- function getMaxDimensions() {
- var chats = document.getElementsByClassName('chatdisplay');
- for (var i=0;i<chats.length;i++) {
- if (chats[i].style.display!='none') {
- var header = document.evaluate('.//div[@class="header"]',chats[i],null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
- dims = {top:Number(chats[i].style.top.replace(/[^0-9]+/,'')),width:Number(chats[i].clientWidth),height:Number(chats[i].style.height.replace(/[^0-9]+/,''))};
- if (header.singleNodeValue) {
- dims.headert = Number(header.singleNodeValue.style.top.replace(/[^0-9]+/,''));
- dims.headerw = Number(header.singleNodeValue.style.width.replace(/[^0-9]+/,''));
- }
- //console.log('dimensions: top='+dims.top+', width='+dims.width+', height='+dims.height+', offw='+chats[i].offsetWidth+', cw='+chats[i].clientWidth);
- chats[i].addEventListener('scroll',setWidths,false);
- return;
- }
- }
- }
- function placeDockIcon(f) {
- var img=document.createElement('img');
- 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");
- if (dims.headerw)
- img.setAttribute('style','position:absolute;top:'+(dims.headert+1)+'px;left:'+(dims.headerw-15)+'px;z-index:7;');
- else
- img.setAttribute('style','position:absolute;top:'+(dims.top+2)+'px;left:'+(dims.width-15)+'px;z-index:7;');
- img.setAttribute('title','Click to toggle display of chat control panel.');
- img.setAttribute('id','chatcp_dock');
- img.addEventListener('click',rollHandler,false);
- f.parentNode.insertBefore(img,f);
- }
- function initialize() {
- getMaxDimensions();
- if (dims) {
- addPanel();
- }
- }
- setTimeout(initialize,50);