您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Estimates time until the next get on 4chan
// ==UserScript== // @author iralakaelah // @name Get Watcher 2 // @version 2022.05.07 // @license WTFPL // @namespace https://greatest.deepsurf.us/en/scripts/419176-get-watcher-2 // @homepage https://greatest.deepsurf.us/en/scripts/ // @description Estimates time until the next get on 4chan // @match http://boards.4channel.org/* // @match https://boards.4channel.org/* // @match http://boards.4chan.org/* // @match https://boards.4chan.org/* // @grant GM_xmlhttpRequest // @grant GM_openInTab // @connect a.4cdn.org // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PHBhdGggZD0iTTAgMzJIMTIuMkwxMS42IDMwLjMgMTMuMiAyMCA0LjYgMTYuMSAwIDIwLjciIGZpbGw9IiM3NmUiLz48cGF0aCBkPSJNNC42IDE2LjFDNC43IDE1LjcgNS42IDE0LjQgNS44IDExLjUgNS45IDEwLjEgNy4zIDkuMiA3LjggOCA4LjUgNi40IDguNCA0LjYgOC45IDIuOSA5LjIgMS45IDkgLjEgMTAuMSAwIDExLjctLjEgMTIuMyAyLjcgMTIuNSA0LjMgMTIuOCA2LjEgMTEuNiA3LjggMTEuMyA5LjVjLS4zIDEuNSAuMyAxLjkgMS40IDEuNCAyLjMtMS4yIDQuNC0xLjggNi4yLTMuMSAyLjctMS43IDQuOS00LjEgNy44LTUuNSAxLjYtLjggNC4xLTMgNS4xLTEuNSAxLjMgMi4xLTMuMiAzLjgtNC45IDUuNS0xLjcgMS43LTUuNiAzLjYtNS4xIDQuOCAuMyAuNyAxIDEuMyAxLjMgMi4xIC4zIDEgLjEgMi4xIC4zIDMuMSAuMiAxIDEgMS44IC45IDIuOC0uMSAyLjEtMS4yIDQuMy0yLjUgNS45LTEgMS4yLTIuMyAyLjQtMy44IDIuNi0yIC4yLTUuOSAyLjUtNi40IDIuN0MxMC4zIDI2LjkgOC40IDIyLjMgNy44IDIxIDcgMTkuNCA1LjYgMTcuNSA0LjYgMTYuMSIgZmlsbD0iI2NiZSIvPjwvc3ZnPg== // ==/UserScript== //<!doctype html><html><head><meta http-equiv="x-ua-compatible" content="ie=edge"></head><body id="hta"><script> 'use strict'; var version='2022.05.07' var boards='3 a aco adv an asp b bant biz c cgl ck cm co d diy e f fa fit g gd gif \ h hc his hm hr i ic int jp k lgbt lit m mlp mu n news o out p po pol pw qa qst r r9k \ s s4s sci soc sp t tg toy trash trv tv u v vg vip vm vmg vp vr vrpg vst vt w wg wsg wsr x xs y'.split(' ') function noDubsBoard(board){ return /^(v|vg|vr)$/.test(board) } function fastBoard(board){ return /^(f)$/.test(board) } function boardTitle(board){ return board=='s4s'?'[s4s]':'/'+board+'/' } if(document.body.id=='hta'){ var zoom=screen.deviceXDPI/96 resizeTo(700*zoom,420*zoom) var info=document.body.firstChild document.body.removeChild(info) var hta=1 var boardName='s4s' var protocol='http:' document.title='Get Watcher' oncontextmenu=function(event){ event.preventDefault() } window.GM_xmlhttpRequest=function(opts){ var xhr=new XMLHttpRequest() xhr.onload=function(){ opts.onload({ responseText:xhr.responseText, status:xhr.status, responseHeaders:xhr.getAllResponseHeaders() }) } xhr.onerror=function(){ opts.onerror() } xhr.open(opts.method,opts.url) for(var i in opts.headers){ xhr.setRequestHeader(i,opts.headers[i]) } xhr.send() } }else{ var zoom=1 var hta=0 var lp=location.pathname var boardName='s4s' var lpmatch=lp.match(/\/([^\/]+)\//) if(lpmatch&&(boards.indexOf(lpmatch[1])+1)){ var boardName=lpmatch[1] } var protocol=location.protocol } var website='greatest.deepsurf.us' var userjsurl=protocol+'//greatest.deepsurf.us/scripts/16671-get-watcher/code/Get%20Watcher.user.js' var metajsurl=protocol+'//greatest.deepsurf.us/scripts/16671-get-watcher/code/Get%20Watcher.meta.js' var verage=toRelativeTime((new Date().getTime()-new Date(version.replace(/\./g,'/')).getTime())/1000,0,1) var delayValue=[1,5,30] var localElements={} var includedCss='#getWatcherBody{background:#fff;z-index:2;color:#000;font:14px sans-serif;margin:0;cursor:default;text-align:left}\ input[type="text"],input[type="number"]{font-size:14px}\ #windowTitle{height:25px;background:#bbb;padding:5px 0 0 5px;color:#555;cursor:default;box-sizing:border-box}\ #windowClose{background:#d77;width:19px;height:19px;position:absolute;top:3px;right:3px}\ #getWatcherBody a{font-weight:bold;color:#00f;text-decoration:none}\ #getWatcherBody a:hover{text-decoration:underline}\ .board-menu{position:absolute;background:#fff;border:1px solid #7f9db9;z-index:2}\ .board-menu div{float:left;width:40px;padding:1px 3px;white-space:nowrap;overflow:hidden}\ #tab1-board-menu div:hover,#tab3-board-menu div:hover,.board-menu .selected{background:#39f;color:#fff}\ .board-menu br{clear:left}\ #board-menu-bg{position:absolute;top:0;bottom:0;left:0;right:0}\ .board-menu .tab2-long-option{width:132px;text-align:center}\ .board-menu input{width:46px;height:100%;box-sizing:border-box;margin:0!important;padding:0 1px!important}\ #getWatcherBody label{display:block;margin:15px 0}\ #getWatcherBody .left-side{float:left;background:#eee;border-right:1px solid #999;padding:20px;width:140px;height:100%}\ #getWatcherBody .left-side input[type="checkbox"],.left-side input[type="text"],.left-side input[type="number"],.left-side select{margin:0 7px}\ #getWatcherBody .center{text-align:center}\ #tab1,#tab2,#tab3,#tab4,#tab5{overflow:hidden;box-sizing:border-box}\ #tab1-delay,#tab2-delay,#tab3-delay{width:50px}\ #tab1-digits,#tab1-custompost,#tab2-board,#tab2-digits,#tab3-custompost{width:90%;box-sizing:border-box}\ .tab1-customshown{margin-bottom:0!important}\ #tab1-customlabel{margin-top:0!important}\ #tab1 input[type="button"],#tab2 input[type="button"],#tab3 input[type="button"]{width:120px;height:30px;font-size:14px}\ #tabs{white-space:nowrap}\ #tabs>div{display:inline-block;width:25%;text-align:center;border-bottom:1px solid #999;height:50px;line-height:50px;background:#eee;box-sizing:border-box}\ #tabs>div:hover{background:#ddd}\ #tabs>.tab-selected{background:#ccc!important}\ #tab1-content,#tab3-content,#tab4{padding:10px}\ #tab1-content,#tab2-content,#tab3-content,#tab4{overflow:auto;height:100%;box-sizing:border-box}\ #tab1-highlighted,#tab3-highlighted{width:100%;background:#eee;border-bottom:1px solid #999;text-align:center;padding:15px;font-size:20px}\ #tab1-board,#tab3-board{width:70px}\ .board-title{font-size:30px;padding-bottom:10px}\ #tab2-content table{border-collapse:collapse;width:100%}\ #tab2-content th,#tab2-content tr:hover{background:#ddd!important}\ #tab2-content td,#tab2-content th{padding:3px;cursor:pointer}\ #tab2-content td:first-child{text-align:center}\ #tab2-content td:nth-child(2),#tab2-content td:nth-child(3){text-align:right}\ #tab2-content th.sortup,#tab2-content th.sortdown{background:#ddd}\ #tab2-content th.sortup::after{content:\'\u25BC\';color:#aaa}\ #tab2-content th.sortdown::after{content:\'\u25B2\';color:#aaa}\ #tab2-content tr:nth-child(2n+1){background:#f5f5f5}\ #tab3-progress{position:absolute;bottom:0;height:10px}\ #tab5{padding-top:80px}\ #tab5-save,#tab5-load{width:60%;height:60px;display:block;margin:0 auto 50px auto;font-size:25px}\ #saveload-input{display:none;width:1px;height:1px;background:none;border:0}' var windowTitle=[] if(hta){ includedCss+='html,#getWatcherBody{height:100%}\ body{margin:0;width:'+100/zoom+'%;height:'+100/zoom+'%}\ body,.board-menu{zoom:'+zoom+'}\ input[type="button"]{border:1px solid #adadad;background:#e1e1e1}\ input[type="button"]:hover{border-color:#0078d7;background:#e5f1fb}\ input[type="button"]:active{border-color:#005499;background:#cce4f7}\ input[type="text"]{border:1px solid #abadb3;font-size:inherit;margin:2px 0;padding:2px}\ input[type="text"]:focus{border-color:#55a2d8}\ select{font-size:14px;border:1px solid #abadb3}\ #tab1,#tab2,#tab3,#tab4,#tab5{height:calc(100% - 50px);box-sizing:border-box}\ #tab3-progress{width:calc(100% - 181px * '+zoom+');border:0;background:#fff;right:0}' }else{ includedCss+='#getWatcherBody{position:fixed;border:1px solid #333;width:700px;height:400px}\ #tab3-progress{width:calc(100% - 194px);right:13px}\ #windowResize{position:absolute;bottom:0;right:0;background:url(data:image/gif;base64,R0lGODlhCwALAPMIAJaWlq2srLm5ucXFxdHR0d3d3ejn5/Hx8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUAAAkALAAAAAALAAsAAAQhMMkpkRmUHhLyLALgjdWVWNi0dSsFii85oaeJtjgX72EEADs=) no-repeat;cursor:se-resize;width:13px;height:13px}\ #tab1,#tab2,#tab3,#tab4,#tab5{height:calc(100% - 75px)}\ #getWatcherBody .tab-selected{font-weight:normal!important}' windowTitle=[ ['div',{ id:'windowTitle', onmousedown:function(){ move=1 moveHandler(event) } },'Get Watcher'], ['div',{ id:'windowClose', onclick:function(){ getWatcherBody.style.display='none' } }], ['div',{ id:'windowResize', onmousedown:function(){ resize=1 moveHandler(event) } }] ] } element( document.body, ['div',{ id:'getWatcherBody', style:'display:none' }, windowTitle[0], windowTitle[1], windowTitle[2], ['div',{ id:'board-menu-bg', style:'display:none', onmousedown:function(){ id('board-menu-bg').style.display= id('tab1-board-menu').style.display= id('tab2-board-menu').style.display= id('tab3-board-menu').style.display='none' } }], ['div',{ id:'tabs' }, ['div',{ id:'tab1-button', class:'tab-selected', onclick:function(){ changeTab(1) } },'One board'], ['div',{ id:'tab2-button', onclick:function(){ changeTab(2) } },'Multiple boards'], ['div',{ id:'tab3-button', onclick:function(){ changeTab(3) } },'Loop'], ['div',{ id:'tab4-button', onclick:function(){ changeTab(4) } },'Help'], ['div',{ id:'tab5-button', style:'display:none' }] ], ['div',{ id:'tab1' }, ['div',{ class:'left-side' }, ['label',{ style:'display:inline' }, 'Board:', ['select',{ id:'tab1-board', onmousedown:function(){ showChooseBoard(1) } }, ['option',{ value:boardName },boardTitle(boardName)] ] ], ['div',{ id:'tab1-board-menu', class:'board-menu', style:'display:none' }], ['label',{ id:'tab1-digitslabel' }, ['select',{ id:'tab1-digits' }, ['option',{ value:2 },'Dubs (2)'], ['option',{ value:3 },'Trips (3)'], ['option',{ value:4 },'Quads (4)'], ['option',{ value:5, selected:1 },'Quints (5)'], ['option',{ value:6 },'Sexts (6)'], ['option',{ value:7 },'Septs (7)'], ['option',{ value:8 },'Octs (8)'], ['option',{ value:9 },'Nons (9)'], ['option',{ value:0 },'Custom post'] ] ], ['label',{ id:'tab1-customlabel', style:'display:none' }, ['input',{ id:'tab1-custompost', type:'text', maxlength:15, onkeydown:changeCustom, onkeyup:changeCustom }] ], ['label',{ class:'tab1-notcustom', }, ['input',{ id:'tab1-clear', type:'checkbox' }], 'Clear' ], ['label',{ class:'tab1-notcustom', }, ['input',{ id:'tab1-palindrome', type:'checkbox' }], 'Palindrome' ], ['label', 'Delay:', ['input',{ id:'tab1-delay', type:'text', value:delayValue[0], min:1, max:99, maxlength:2 }] ], ['label', ['input',{ id:'tab1-fast', type:'checkbox' }], 'Fast check' ], ['label',{ class:'center' }, ['input',{ id:'tab1-check', type:'button', value:'Check', onclick:oneBoard }] ], ['label',{ class:'center' }, ['input',{ type:'button', value:'Save/Load', onclick:function(){ saveLoadTab(1) } }] ] ], ['div',{ id:'tab1-highlighted', style:'display:none' }], ['div',{ id:'tab1-content' }] ], ['div',{ id:'tab2', style:'display:none' }, ['div',{ class:'left-side' }, ['label',{ style:'display:inline' }, ['select',{ id:'tab2-board', onmousedown:function(){ showChooseBoard(2) } }, ['option','Boards...'] ] ], ['div',{ id:'tab2-board-menu', class:'board-menu', style:'display:none' }], ['label', ['select',{ id:'tab2-digits' }, ['option',{ value:2 },'Dubs (2)'], ['option',{ value:3 },'Trips (3)'], ['option',{ value:4 },'Quads (4)'], ['option',{ value:5, selected:1 },'Quints (5)'], ['option',{ value:6 },'Sexts (6)'], ['option',{ value:7 },'Septs (7)'], ['option',{ value:8 },'Octs (8)'], ['option',{ value:9 },'Nons (9)'] ] ], ['label', ['input',{ id:'tab2-clear', type:'checkbox' }], 'Clear' ], ['label', ['input',{ id:'tab2-palindrome', type:'checkbox' }], 'Palindrome' ], ['label', 'Delay:', ['input',{ id:'tab2-delay', type:'text', value:delayValue[1], min:1, max:99, maxlength:2 }] ], ['label', ['input',{ id:'tab2-fast', type:'checkbox', checked:1 }], 'Fast check' ], ['label',{ class:'center' }, ['input',{ id:'tab2-check', type:'button', value:'Check', onclick:multipleBoards }] ], ['label',{ class:'center' }, ['input',{ type:'button', value:'Save/Load', onclick:function(){ saveLoadTab(2) } }] ] ], ['div',{ id:'tab2-content' }] ], ['div',{ id:'tab3', style:'display:none' }, ['div',{ class:'left-side' }, ['label',{ style:'display:inline' }, 'Board:', ['select',{ id:'tab3-board', onmousedown:function(){ showChooseBoard(3) } }, ['option',{ value:boardName },boardTitle(boardName)] ] ], ['div',{ id:'tab3-board-menu', class:'board-menu', style:'display:none' }], ['label', 'Post number:', ['input',{ id:'tab3-custompost', type:'text', maxlength:15, onkeydown:changeCustom, onkeyup:changeCustom }] ], ['label', 'Delay:', ['input',{ type:'text', value:delayValue[2], min:1, max:99, maxlength:2, id:'tab3-delay' }] ], ['label',{ class:'center' }, ['input',{ id:'tab3-check', type:'button', value:'Check', onclick:loopBoard }] ] ], ['div',{ id:'tab3-highlighted', style:'display:none' }], ['div',{ id:'tab3-content' }], ['progress',{ value:0, id:'tab3-progress' }] ], ['div',{ id:'tab4', style:'display:none' }, ['div',{ class:'center' }, ['h3', 'Get Watcher' ], '(', ['a',{ onclick:updateScript, style:'color:#00f;cursor:pointer' },'Version '+version], ', '+verage+' ago)', ['br'], ['br'] ], 'Get Watcher uses 4chan API to predict the time until the next get. You can choose between three options: One board, Multiple boards, and Loop. Get Watcher is open source and is released under public domain.', ['br'], ['br'], ['b','One board'], ': Get stats from only one board, like time until next get, posts per second, etc.', ['br'], ['br'], ['b','Multiple boards'], ': It lists every board\'s stats in a table that you can sort. The table\'s contents are: the board, next get, time until that next get, and how many posts are left until it. To sort the list, click on one of the headers.', ['br'], ['br'], ['b','Loop'], ': Constantly checks the first page for latest post and posts per second value until stopped.', ['br'], ['br'], ['b','Board'], ': The board you want to get stats from.', ['br'], ['br'], ['b','Digits dropdown'], ': Recurring digits at the end of a post number.', ['br'], 'Example: 123444 has three recurring numbers at the end, 133333 has five.', ['br'], ['br'], ['b','Clear'], ': Last digits to be always zero, locked on for boards that don\'t have dubs (/b/, /v/, /vg/, /vr/).', ['br'], 'Example: 130000.', ['br'], ['br'], ['b','Palindrome'], ': Post IDs that read the same forwards and backwards.', ['br'], 'Example: 123321, 4132314.', ['br'], ['br'], ['b','Delay'], ': How much delay in seconds there should be between calls to 4chan API, the documentation suggests no less than 10 seconds. With each call Get Watcher downloads about 25-30KB of JSON data.', ['br'], ['br'], ['b','Fast check'], ': Instead of making two calls for both the first post and for an old post from page 10, it makes only one. Has different results, recommended on for multiple boards.' ], ['div',{ id:'tab5', style:'display:none' }, ['input',{ type:'button', id:'tab5-save', value:'Save', onclick:saveToFile }], ['input',{ id:'tab5-load', type:'button', value:'Load', onclick:function(){ id('saveload-input').style.display='block' id('saveload-input').click() id('saveload-input').style.display='none' } }], ['form',{ id:'saveload-form' }, ['input',{ id:'saveload-input', type:'file', onchange:loadFromFile }] ] ], ['style',includedCss] ] ) var initializeCompleted=0 if(hta){ initialize() }else{ element( document.body, ['input',{ id:'open-get-watcher', type:'button', value:'Open Get Watcher', style:'position:absolute;top:100px;left:10px', onclick:initialize }] ) } var oneBoardCache={} var multipleBoardsCache={} var loopCache={} var sortCache=[2,0] var saveloadFromTab=1 var multipleCurrentBoards=[] var currentBoards=[] var boardIndex=0 var move=0 var resize=0 var tab2BoardOptions var oneBoardTimer var multipleBoardsTimer var loopBoardTimer var mouseXlast=null var mouseYlast=null var getWatcherBody function initialize(){ getWatcherBody=id('getWatcherBody') if(!hta){ getWatcherBody.style.top='100px' getWatcherBody.style.left='100px' } getWatcherBody.style.display='block' if(!initializeCompleted){ initializeCompleted=1 for(var i=1;i<4;i++){ changeTab(i) id('tab'+i+'-board-menu').style.top=(id('tab'+i+'-board').offsetTop+id('tab'+i+'-board').offsetHeight-1)*zoom+'px' id('tab'+i+'-board-menu').style.left=id('tab'+i+'-board').offsetLeft*zoom+'px' } changeTab(1) var tab1Elements=document.querySelectorAll('#tab1 [id^="tab1-"]') for(var i=0;i<tab1Elements.length;i++){ tab1Elements[i].onchange=tab1Changed } var tab2Elements=document.querySelectorAll('#tab2 [id^="tab2-"]') for(var i=0;i<tab2Elements.length;i++){ tab2Elements[i].onchange=tab2Changed } id('tab1-custompost').addEventListener('focus',focusCustom) id('tab3-custompost').addEventListener('focus',focusCustom) id('tab1-custompost').addEventListener('blur',changeCustom) id('tab3-custompost').addEventListener('blur',changeCustom) var boardList=[] for(var i=0;i<boards.length;i++){ if(i&&i%6==0){ boardList.push(['br']) } boardList.push( ['div',{ board:boards[i] },boardTitle(boards[i])] ) } element( id('tab1-board-menu'), boardList, i%6==0?['br']:null, ['div',{ onclick:plusBoard },'+'], id('tab3-board-menu'), boardList, i%6==0?['br']:null, ['div',{ onclick:plusBoard },'+'], id('tab2-board-menu'), boardList, ['br'], ['div',{ class:'tab2-long-option', onclick:function(){ tab2SelectAllBoards() } },'Select all'], ['div',{ class:'tab2-long-option', onclick:function(){ tab2SelectAllBoards(1) } },'Unselect all'] ) var tab1BoardOptions=document.querySelectorAll('#tab1-board-menu div') tab2BoardOptions=document.querySelectorAll('#tab2-board-menu div:not(.tab2-long-option)') var tab3BoardOptions=document.querySelectorAll('#tab3-board-menu div') for(var i=0;i<tab2BoardOptions.length;i++){ if(tab1BoardOptions[i].getAttribute('board')==boardName){ tab1BoardOptions[i].classList.add('selected') tab3BoardOptions[i].classList.add('selected') } tab2BoardOptions[i].classList.add('selected') tab1BoardOptions[i].onclick=tab1or3ChooseBoard tab2BoardOptions[i].onclick=tab2ChooseBoard tab3BoardOptions[i].onclick=tab1or3ChooseBoard } id('tab1-digits').addEventListener('change',function(event){ if(event.currentTarget.value*1){ id('tab1-customlabel').style.display='none' id('tab1-digitslabel').classList.remove('tab1-customshown') }else{ id('tab1-customlabel').style.display='block' id('tab1-digitslabel').classList.add('tab1-customshown') } var notcustom=document.getElementsByClassName('tab1-notcustom') for(var i=0;i<notcustom.length;i++){ notcustom[i].style.display=event.currentTarget.value*1?'block':'none' } }) for(var i=1;i<4;i++){ id('tab'+i+'-delay').addEventListener('change',changeDelay) id('tab'+i+'-delay').addEventListener('blur',changeDelay) id('tab'+i+'-delay').onkeydown=changeDelay id('tab'+i+'-delay').onkeyup=changeDelay } if(!hta){ addEventListener('mousemove',moveHandler) addEventListener('mouseup',function(){ move=0 resize=0 mouseXlast=null mouseYlast=null }) } } } function id(a){ return localElements[a] } function toRelativeTime(difference,originaldate,mode){ var timd=Math.abs(difference) if(mode>1&&timd<10){ var sec=(timd%60*10|0)/10 }else{ var sec=timd%60|0 } timd/=60 var min=timd%60|0 timd/=60 var hrs=timd%24|0 timd/=24 var day=timd%30.4375|0 timd/=30.4375 var mon=timd%12|0 var yer=Math.floor(timd/12) if(mode==1){ var till=[ yer?yer+' year'+(yer>1?'s ':' '):'', mon&&yer<2?mon+' month'+(mon>1?'s ':' '):'', (day&&mon<2)||!mon?day+' day'+(day==1?'':'s'):'' ] }else if(mode==3){ var till=[ yer?formatNumber(yer)+'y':'', mon&&yer<2?mon+'mo':'', day&&mon<2?day+'d':'', hrs&&day<2?hrs+'h':'', min&&hrs<3?min+'m':'', (sec&&min<10)||!min?sec+'s':'' ] }else{ var till=[ yer?formatNumber(yer)+'\xA0year'+(yer>1?'s ':' '):'', mon&&yer<2?mon+'\xA0month'+(mon>1?'s ':' '):'', day&&mon<2?day+'\xA0day'+(day>1?'s ':' '):'', hrs&&day<2?hrs+'\xA0hour'+(hrs>1?'s ':' '):'', min&&hrs<3?min+'\xA0minute'+(min>1?'s ':' '):'', (sec&&min<10)||!min?sec+'\xA0second'+(sec==1?'':'s'):'' ] } for(var g=0;g<till.length&&!till[g];g++){} if(mode==3){ var tout=till[g]+(till[g+1]||'') }else{ var tout=(till[g]+(till[g+1]?'and '+till[g+1]:'')).trim() } if(originaldate){ var newdt=new Date((originaldate*1+difference*1)*1000) if(newdt*1){ try{ var parseddate=newdt.toLocaleTimeString()+' ('+newdt.toDateString()+')' }catch(e){ var parseddate=newdt } }else{ var parseddate='Year\xA0'+formatNumber(new Date(originaldate*1000).getFullYear()+yer) } return [tout,parseddate] }else{ return tout } } function element(){ var parent var lasttag var createdtag var toreturn={} for(var i=0;i<arguments.length;i++){ var current=arguments[i] if(current){ if(current.nodeType){ parent=lasttag=current }else if(Array.isArray(current)){ for(var j=0;j<current.length;j++){ if(current[j]){ if(!j&&typeof current[j]=='string'){ var tagname=current[0].split('#') lasttag=createdtag=document.createElement(tagname[0]) if(tagname[1]){ toreturn[tagname[1]]=createdtag } }else if(current[j].constructor==Object){ if(lasttag){ for(var value in current[j]){ if(value=='id'){ localElements[current[j][value]]=lasttag } if(value!='style'&&value in lasttag){ lasttag[value]=current[j][value] }else{ lasttag.setAttribute(value,current[j][value]) } } } }else{ var returned=element(lasttag,current[j]) for(var k in returned){ toreturn[k]=returned[k] } } } } }else if(current){ createdtag=document.createTextNode(current) } if(parent&&createdtag){ parent.appendChild(createdtag) } createdtag=0 } } return toreturn } function formatNumber(num){ num=num+'' while(/\d{4}/.test(num)){ num=num.replace(/\d+(?=\d{3})/,'$&\u202F') } return num } function changeTab(tabN){ var tabselected=document.getElementsByClassName('tab-selected')[0] if(tabselected){ tabselected.classList.remove('tab-selected') } var tabs=id('tabs').childNodes for(var i=0;i<tabs.length;i++){ id('tab'+(i+1)).style.display='none' } tabs[tabN-1].classList.add('tab-selected') id('tab'+tabN).style.display='block' } function tab2SelectAllBoards(unselect){ for(var i=0;i<tab2BoardOptions.length;i++){ if(unselect){ tab2BoardOptions[i].className='' }else{ tab2BoardOptions[i].className='selected' } } } function showChooseBoard(tabNumber){ var boardMenu=id('tab'+tabNumber+'-board-menu') id('board-menu-bg').style.display=boardMenu.style.display='block' setTimeout(function(){ id('tab'+tabNumber+'-board').blur() },10) } function tab1or3ChooseBoard(event,target){ if(!target){ target=event.currentTarget } var boardSelect=target.parentNode.parentNode var boardMenu=boardSelect.getElementsByClassName('board-menu')[0] var optionElement=boardSelect.getElementsByTagName('option')[0] var selected=boardMenu.getElementsByClassName('selected')[0] if(selected){ selected.classList.remove('selected') } boardMenu.style.display=id('board-menu-bg').style.display='none' target.classList.add('selected') optionElement.value=target.getAttribute('board') optionElement.innerHTML=target.innerHTML } function tab2ChooseBoard(event){ var sourceElement=event.currentTarget if(sourceElement.className){ sourceElement.className='' }else{ sourceElement.className='selected' } } function oneBoard(){ var checkButton=id('tab1-check') if(checkButton.value=='Check'){ var currentBoard=id('tab1-board').value oneBoardCache={ currentBoard:currentBoard } getLastPost(currentBoard,oneBoard2) }else{ clearTimeout(oneBoardTimer) checkButton.value='Check' } } function oneBoard2(lastStats){ var checkButton=id('tab1-check') var currentBoard=oneBoardCache.currentBoard if(lastStats.post){ oneBoardCache={ currentBoard:currentBoard, lastStats:lastStats } if(!id('tab1-fast').checked&&!fastBoard(currentBoard)){ checkButton.value='Stop' oneBoardTimer=setTimeout(function(){ getOldPost(currentBoard,0,oneBoard3) },delayValue[0]*1000) } }else{ oneBoardCache={} } tab1Changed() } function oneBoard3(oldStats){ if(oldStats.post){ oneBoardCache.oldStats=oldStats tab1Changed() } id('tab1-check').value='Check' } function multipleBoards(){ var checkButton=id('tab2-check') if(checkButton.value=='Check'){ currentBoards=id('tab2-board-menu').getElementsByClassName('selected') if(currentBoards.length){ checkButton.value='Stop' multipleBoardsCache={} boardIndex=0 multipleCurrentBoards=[] for(var i=0;i<currentBoards.length;i++){ multipleCurrentBoards[i]=currentBoards[i].getAttribute('board') } multipleBoardsLoop() } }else{ clearTimeout(multipleBoardsTimer) checkButton.value='Check' } } function loopBoard(){ var checkButton=id('tab3-check') if(checkButton.value=='Check'){ checkButton.value='Stop' var currentBoard=id('tab3-board').value loopBoardLoop(currentBoard) }else{ clearTimeout(loopBoardTimer) id('tab3-progress').value=0 checkButton.value='Check' } } function tab1Changed(){ id('tab1-highlighted').innerHTML=id('tab1-content').innerHTML='' var lastStats=oneBoardCache.lastStats if(lastStats){ id('tab1-custompost').placeholder=lastStats.post if(oneBoardCache.oldStats){ var oldStats=oneBoardCache.oldStats }else{ var oldStats=getOldPost(0,lastStats.cache) oneBoardCache.oldStats=oldStats delete oneBoardCache.lastStats.cache } var postsInbetween=lastStats.post-oldStats.post var timeInbetween=lastStats.time-oldStats.time var postsPerSecond=postsInbetween/timeInbetween var currentBoard=oneBoardCache.currentBoard var noDubs=noDubsBoard(currentBoard) var getDigits=id('tab1-digits').value*1 var customPost=id('tab1-custompost').value if(!getDigits){ if(/[-+]/.test(customPost[0])){ customPost-=-lastStats.post } if(customPost>0&&customPost<1e15){ getStats={next:Math.floor(customPost)} }else{ getStats={next:lastStats.post} } }else{ var getClear=id('tab1-clear').checked var getPalindrome=id('tab1-palindrome').checked var getStats=getNextGet(lastStats.post,getDigits,getClear,noDubs,getPalindrome) } var lastGetAgo=lastStats.post-getStats.last var postsUntilGet=getStats.next-lastStats.post var relativeTime=toRelativeTime(postsUntilGet/postsPerSecond,lastStats.time) var lastDate=new Date(lastStats.time*1000) var postPast=postsUntilGet<0 if(noDubs){ postsPerSecond*=0.901 // You can get this number by filling an array with numbers from 0 to 999, not including the numbers that have repeating digits at the end. The resulting array should have 901 numbers, just divide that by 1000 } postsPerSecond=toRelativeTime(1/postsPerSecond,0,2) element( id('tab1-highlighted'),[{ style:'display:block' }], ['div',{ class:'board-title' },boardTitle(currentBoard)], ['b',relativeTime[0]], ' '+(postPast?'after':'until')+' the ', ['b',formatNumber(getStats.next)], ' get', id('tab1-content'), 'Posts ', (postPast?['b','since']:'left'), ': ', ['b',formatNumber(Math.abs(postsUntilGet))], ['br'], 'Board speed: 1 post per ', ['b',postsPerSecond], ['br'], 'Estimated date: ', relativeTime[1], ['br'], ['br'], 'Current post: ', ['a',{ href:protocol+'//sys.4chan.org/'+currentBoard+'/imgboard.php?res='+lastStats.post },formatNumber(lastStats.post)], ' ('+lastDate.toLocaleTimeString()+', '+lastDate.toDateString()+')' ) if(getStats.last&&getDigits){ element( id('tab1-content'), ['br'], 'Last get (', ['a',{ href:protocol+'//sys.4chan.org/'+currentBoard+'/imgboard.php?res='+getStats.last },getStats.last], ') happened ', ['b',lastGetAgo], ' post'+(lastGetAgo==1?'':'s')+' ago' ) } }else{ id('tab1-highlighted').style.display='none' } } function multipleBoardsLoop(){ var currentBoard=multipleCurrentBoards[boardIndex] getLastPost(currentBoard,multipleBoardsLoop2) } function multipleBoardsLoop2(lastStats){ var currentBoard=multipleCurrentBoards[boardIndex] if(lastStats.post){ multipleBoardsCache[currentBoard]={ lastStats:lastStats } tab2Changed() } if(id('tab2-fast').checked||fastBoard(currentBoard)||!lastStats.post){ boardIndex++ if(boardIndex<currentBoards.length){ multipleBoardsTimer=setTimeout(function(){ multipleBoardsLoop(currentBoards,boardIndex) },delayValue[1]*1000) }else{ id('tab2-check').value='Check' } }else{ multipleBoardsTimer=setTimeout(function(){ getOldPost(currentBoard,0,multipleBoardsLoop3) },delayValue[1]*1000) } } function multipleBoardsLoop3(oldStats){ var currentBoard=multipleCurrentBoards[boardIndex] if(oldStats.post){ multipleBoardsCache[new String(currentBoard)].oldStats=oldStats tab2Changed() } boardIndex++ if(boardIndex<currentBoards.length){ multipleBoardsTimer=setTimeout(function(){ multipleBoardsLoop() },delayValue[1]*1000) }else{ id('tab2-check').value='Check' } } function tab2Changed(){ if(Object.keys(multipleBoardsCache).length){ var getDigits=id('tab2-digits').value var getClear=id('tab2-clear').checked var getPalindrome=id('tab2-palindrome').checked var sortWhich=sortCache[0] var sortBackwards=sortCache[1] var rows=['Board','Next get','Happens in','Posts left','Board speed'] var sorttablerow=['tr'] for(var i in rows){ var newth=['th',{ id:'sortTableRow'+i, class:sortWhich==i?sortBackwards?'sortup':'sortdown':'' },rows[i]] if(i!=1){ newth[1].onclick=sortTableRow } sorttablerow.push(newth) } var multipleBoardsStats=[] for(var currentBoard in multipleBoardsCache){ var boardCache=multipleBoardsCache[currentBoard] var noDubs=noDubsBoard(currentBoard) var lastStats=boardCache.lastStats if(boardCache.oldStats){ var oldStats=boardCache.oldStats }else{ var oldStats=getOldPost(0,lastStats.cache) boardCache.oldStats=oldStats delete lastStats.cache } var postsInbetween=lastStats.post-oldStats.post var timeInbetween=lastStats.time-oldStats.time var postsPerSecond=postsInbetween/timeInbetween var getStats=getNextGet(lastStats.post,getDigits,getClear,noDubs,getPalindrome) var postsUntilGet=getStats.next-lastStats.post var relativeTimestamp=postsUntilGet/postsPerSecond if(noDubs){ postsPerSecond*=0.901 } multipleBoardsStats.push([ currentBoard, getStats.next, relativeTimestamp, postsUntilGet, 1/postsPerSecond ]) } if(sortBackwards){ var sortedStats=multipleBoardsStats.sort(function(a,b){ return a[sortWhich]<b[sortWhich]?1:-1 }) }else{ var sortedStats=multipleBoardsStats.sort(function(a,b){ return a[sortWhich]>b[sortWhich]?1:-1 }) } var statstable=[] for(var i in sortedStats){ statstable.push( ['tr',{ id:'table-board-'+sortedStats[i][0], onclick:multipleToSingle }, ['td',boardTitle(sortedStats[i][0])], ['td',formatNumber(sortedStats[i][1])], ['td','(in '+toRelativeTime(sortedStats[i][2])+','], ['td',formatNumber(sortedStats[i][3])+' post'+(sortedStats[i][3]==1?'':'s')+')'], ['td','1 post/\u200B'+toRelativeTime(sortedStats[i][4],0,3)] ] ) } var tab2Content=id('tab2-content') tab2Content.innerHTML='' element( tab2Content, ['table', sorttablerow, statstable ] ) } } function sortTableRow(event){ var sortWhich=event.currentTarget.id.replace('sortTableRow','')*1 if(sortWhich==sortCache[0]&&!sortCache[1]){ sortCache=[sortWhich,1] }else{ sortCache=[sortWhich,0] } tab2Changed() } function multipleToSingle(event){ var target=event.currentTarget for(;target;){ if(target.id){ var currentBoard=target.id.replace('table-board-','') break } target=target.parentNode } oneBoardCache=multipleBoardsCache[currentBoard] oneBoardCache.currentBoard=currentBoard tab1Changed() changeTab(1) } function loopBoardLoop(){ var currentBoard=id('tab3-board').value var lastCall='' if(loopCache.currentBoard==currentBoard){ lastCall=loopCache.lastCall } loopCache={ currentBoard:currentBoard } getLastPost(currentBoard,loopBoardLoop2,lastCall) } function loopBoardLoop2(lastStats){ id('tab3-progress').value=0 if(lastStats){ loopCache={ currentBoard:loopCache.currentBoard, lastCall:lastStats.lastCall, lastStats:lastStats } } tab3Changed() loopBoardTimer=setInterval(function(){ var progress=id('tab3-progress') var maxProgress=delayValue[2] progress.setAttribute('max',maxProgress) var progressValue=progress.value if(progressValue>=maxProgress){ clearTimeout(loopBoardTimer) loopBoardLoop() }else{ progress.value+=1 } },1000) } function tab3Changed(){ id('tab3-highlighted').innerHTML=id('tab3-content').innerHTML='' var lastStats=loopCache.lastStats if(lastStats){ id('tab3-custompost').placeholder=lastStats.post var oldStats=getOldPost(0,lastStats.cache) var postsInbetween=lastStats.post-oldStats.post var timeInbetween=lastStats.time-oldStats.time var lastDate=new Date(lastStats.time*1000) var postsPerSecond=postsInbetween/timeInbetween var customPost=Math.floor(id('tab3-custompost').value) if(customPost==lastStats.post){ customPost=0 } if(customPost>0){ var postsUntilGet=customPost-lastStats.post var relativeTime=toRelativeTime(postsUntilGet/postsPerSecond,lastStats.time) var postPast=postsUntilGet<0 } if(noDubsBoard(loopCache.currentBoard)){ postsPerSecond*=0.901 } postsPerSecond=toRelativeTime(1/postsPerSecond,0,2) element( id('tab3-highlighted'),[{ style:'display:block' }], ['div',{ class:'board-title' },boardTitle(loopCache.currentBoard)], 'Current post: ', ['a',{ href:protocol+'//sys.4chan.org/'+loopCache.currentBoard+'/imgboard.php?res='+lastStats.post, style:'font-weight:bold' },formatNumber(lastStats.post)], ['br'], 'Board speed: 1 post per ', ['b',postsPerSecond] ) if(customPost>0){ element( id('tab3-content'), ['b',relativeTime[0]], ' '+(postPast?'after':'until')+' the ', ['b',formatNumber(customPost)], ' get', ['br'], 'Posts ', (postPast?['b',{ style:'color:red' },'since']:'left'), ': ', ['b',formatNumber(Math.abs(postsUntilGet))], ['br'], 'Estimated date: ', relativeTime[1], ['br'], ['br'] ) } element( id('tab3-content'), 'Current post date: '+lastDate.toLocaleTimeString()+', '+lastDate.toDateString() ) }else{ id('tab3-highlighted').style.display='none' } } function requestPage(currentBoard,page,realNextStep,nextStep,lastCall){ var jsonobj GM_xmlhttpRequest({ method:'get', url:protocol+'//a.4cdn.org/'+currentBoard+'/'+page+'.json', headers:{'If-Modified-Since':lastCall}, onload:function(response){ if(lastCall){ var headers=response.responseHeaders.split('\n') for(var i in headers){ var header=headers[i].split(': ') if(header[0]=='Last-Modified'){ lastCall=header[1] break } } } if(response.status==200){ jsonobj=JSON.parse(response.responseText) }else if(response.status==304){ nextStep() return }else{ connectionError('4chan',response.status,protocol+'//a.4cdn.org/'+currentBoard+'/'+page+'.json') } realNextStep(jsonobj,nextStep,lastCall) }, onerror:function(){ connectionError('4chan',0,protocol+'//a.4cdn.org/'+currentBoard+'/'+page+'.json') realNextStep(jsonobj,nextStep) }, onabort:function(){ for(var i=1;i<4;i++){ id('tab'+i+'-check').value='Check' } } }) } function getLastPost(currentBoard,nextStep,lastCall){ requestPage(currentBoard,1,getLastPost2,nextStep,lastCall) } function getLastPost2(jsonobj,nextStep,lastCall){ if(!jsonobj){ nextStep({ post:0, time:0, cache:[[0],[0]] }) return } var postNumbers=[] var postTimes=[] var allsticky=jsonobj.threads[jsonobj.threads.length-1].posts[0].sticky for(var i=0;i<jsonobj.threads.length;i++){ if(!jsonobj.threads[i].posts[0].sticky||allsticky){ for(var j=0;j<jsonobj.threads[i].posts.length;j++){ postNumbers.push(jsonobj.threads[i].posts[j].no) postTimes.push(jsonobj.threads[i].posts[j].time) } } } var result={ post:Math.max.apply(Math,postNumbers), time:Math.max.apply(Math,postTimes), cache:[postNumbers,postTimes] } if(lastCall){ result.lastCall=lastCall } nextStep(result) } function getOldPost(currentBoard,cache,nextStep){ if(cache){ var postNumbers=cache[0] var postTimes=cache[1] return { post:Math.min.apply(Math,postNumbers), time:Math.min.apply(Math,postTimes) } }else{ requestPage(currentBoard,10,getOldPost2,nextStep) } } function getOldPost2(jsonobj,nextStep){ if(!jsonobj){ nextStep({ post:0, time:0 }) } var postNumbers=[] var postTimes=[] for(var i=0;i<jsonobj.threads.length;i++){ for(var j=0;j<jsonobj.threads[i].posts.length;j++){ postNumbers.push(jsonobj.threads[i].posts[j].no) postTimes.push(jsonobj.threads[i].posts[j].time) } } nextStep({ post:Math.min.apply(Math,postNumbers), time:Math.min.apply(Math,postTimes) }) } function getNextGet(lastPost,getDigits,getClear,noDubs,getPalindrome){ if(getPalindrome) return { next:nextPalindrome(lastPost,0,noDubs), last:nextPalindrome(lastPost,1,noDubs) } var getClear=noDubs||getClear if(noDubs&&getDigits<3) getDigits=3 var tpow=Math.pow(10,getDigits) var allones=tpow/(getClear?1:9)|0 if(allones>lastPost) return { next:allones, last:0 } var unchanged=(lastPost/tpow|0)*tpow if(getClear) return { next:unchanged+tpow, last:unchanged } var array=[] for(var i=getDigits-1;i>=0&&lastPost;i--){ array[i]=lastPost%10 lastPost=lastPost/10|0 } var repdigit=array[0] for(i=0;i<getDigits;i++){ if(array[0]<array[i]) repdigit=(repdigit+1)%10 if(array[0]!=array[i]) break } if(i==getDigits&&array[0]==array[i-1]){ repdigit=(repdigit+1)%10 if(array[0]==9){ unchanged=unchanged+tpow allones=1 } } var alldigits=unchanged+((1/9-1e-16)*repdigit*tpow|0) return { next:alldigits, last:alldigits-allones } } function nextPalindrome(lastPost,prev,noDubs){ if(noDubs&&lastPost<101&&lastPost>8) return prev?9:101 lastPost++ var midf=(Math.log(lastPost)/Math.LN10+1|0)/2 var mid=Math.ceil(midf) var nomid=mid==midf?0:1 var midp=Math.pow(10,mid-nomid) var leftnum=lastPost/midp|0 var mulprev=prev?-1:1 for(;;){ var nextPalin=leftnum*midp for(var i=nomid;i<mid;i++) nextPalin+=((leftnum/Math.pow(10,i)|0)%10)*Math.pow(10,mid-i-1) if(!prev&&leftnum>midp*(nomid?10:1)) return midp*midp*(nomid?10:1)+1 else if(!(nextPalin%10)) return nextPalindrome(lastPost+mulprev-1,prev,noDubs) else if(noDubs&&(nextPalin%10)==(nextPalin/10%10|0)) leftnum=((leftnum/(midp/(nomid?10:100))|0)+(mulprev+1)/2)*(midp/(nomid?10:100))-prev else if(nextPalin*mulprev<lastPost*mulprev+prev) leftnum+=mulprev else break } return nextPalin } function saveLoadTab(tabnum){ saveloadFromTab=tabnum changeTab(5) } function saveToFile(overwrite){ if(saveloadFromTab==1){ var fileName='oneboard.json' var fileContents=oneBoardCache }else{ var fileName='multipleboards.json' var fileContents=multipleBoardsCache } if(hta){ var fileSystem=new ActiveXObject('Scripting.FileSystemObject') if(fileSystem.FileExists(fileName)){ if(overwrite==1){ var openedFile=fileSystem.OpenTextFile(fileName,2,0) }else{ if(confirm(fileName+' exists in the current directory. Overwrite it?')){ saveToFile(1) } return } }else{ var openedFile=fileSystem.CreateTextFile(fileName) } openedFile.WriteLine(JSON.stringify(fileContents)) openedFile.Close() if(!overwrite){ alert('Saved as '+fileName) } }else{ var saveLink=document.createElement('a') saveLink.innerHTML='link' saveLink.href='data:application/json;base64,'+btoa(JSON.stringify(fileContents)) saveLink.setAttribute('download',fileName) saveLink.setAttribute('target','_blank') document.body.appendChild(saveLink) saveLink.click() document.body.removeChild(saveLink) } } function loadFromFile(){ if(window.multipleBoardsTimer){ clearTimeout(multipleBoardsTimer) } if(window.oneBoardTimer){ clearTimeout(oneBoardTimer) } id('tab1-check').value=id('tab2-check').value='Check' var filesInput=id('saveload-input') if(filesInput.files.length){ var openedFile=filesInput.files[0] var reader=new FileReader() reader.onload=function(event){ fileContents=event.currentTarget.result id('saveload-form').reset() try{ var fileContents=JSON.parse(fileContents) }catch(e){ alert('This is not a JSON file!') return } if(fileContents.currentBoard&&fileContents.lastStats){ oneBoardCache=fileContents tab1Changed() changeTab(1) }else{ var error=1 for(var i in fileContents){ if(fileContents[i].lastStats){ error=0 multipleBoardsCache=fileContents tab2Changed() changeTab(2) }else{ alert('The JSON file is corrupt!') } break } if(error){ alert('The JSON file is empty!') } } } } reader.readAsText(filesInput.files[0]) } function focusCustom(event){ var target=event.currentTarget if(target.value==''){ target.value=target.placeholder target.setSelectionRange(target.value.length,target.value.length) } } function changeCustom(event){ var tabNumber=event.currentTarget.id.match(/tab(\d)-custompost/)[1] changeNumber(event,tabNumber==1?1-1e15:1,1e15-1,tabNumber==1) if(tabNumber==1){ tab1Changed() }else{ tab3Changed() } } function changeDelay(event){ var tabNumber=event.currentTarget.id.match(/tab(\d)-delay/)[1] changeNumber(event,1,99) if(event.type=='blur'||event.keyCode==38||event.keyCode==40){ delayValue[tabNumber-1]=event.currentTarget.value } } function changeNumber(event,min,max,mp){ var pressed=event.keyCode var target=event.currentTarget var result=target.value var oldValue=result var cursorPos=target.selectionStart if(event.type=='keydown'){ if(!event.shiftKey&&( pressed>36&&pressed<41||//Arrow keys pressed>41&&pressed<59||//Number row pressed>95&&pressed<106//Numpad digits )){ if(pressed==38||pressed==40){ event.preventDefault() var plus='' if(mp&&result==''||/[-+]/.test(result)){ var plus='+' } result=(result*1+(pressed==38?1:-1))+'' if(plus&&result[0]!='-'){ result=plus+result } } }else if(mp&&( pressed==107||//Numpad plus pressed==109||//Numpad minus event.shiftKey&&pressed==187||//Equals pressed==189//Minus )){ event.preventDefault() result=(pressed==109||pressed==189?'-':'+')+result.replace(/[-+]/,'') }else if( event.ctrlKey|| event.altKey|| pressed==8||//Backspace pressed==9||//Tab pressed==27||//Esc pressed>32&&pressed<37||//Home, End, Page Up/Down event.shiftKey&&pressed>36&&pressed<41||//Arrow keys pressed==46||//Delete pressed>111&&pressed<124//F1-F12 keys ){}else{ event.preventDefault() } if(!/^[-+]$/.test(result)&&( !(result*0+1)|| result<min|| result>max|| target.maxLength!=-1&&(result+'').length>target.maxLength )){ result=target.value } } if(result){ result=result[0].replace(mp?/[^+-\d]/:/\D/,'')+result.slice(1).replace(/\D+/g,'') } if(event.type=='blur'&&result==target.placeholder){ target.value='' }else if(oldValue!=result){ target.value=result if(pressed==38||pressed==40){ target.setSelectionRange(cursorPos,cursorPos) } } } function plusBoard(event){ var input=element(['input#input',{ type:'text', value:event.currentTarget.innerHTML=='+'?'':event.currentTarget.innerHTML.slice(1,-1), onblur:selectPlusBoard, onkeydown:selectPlusBoard }]).input event.currentTarget.parentNode.replaceChild(input,event.currentTarget) input.setSelectionRange(input.value.length,input.value.length) } function selectPlusBoard(event){ if(event.type=='keydown'){ if(event.keyCode==13){ event.currentTarget.blur() } return } var value=event.currentTarget.value.replace(/^\/+|\/+$/g,'') var div=element(['div#div',{ onclick:plusBoard, board:value },value?'/'+value+'/':'+']).div event.currentTarget.parentNode.replaceChild(div,event.currentTarget) if(value){ tab1or3ChooseBoard(0,div) }else{ if(!div.parentNode.getElementsByClassName('selected')[0]){ tab1or3ChooseBoard(0,div.parentNode.querySelector('[board="'+boardName+'"]')) } } } function moveHandler(event){ if(move||resize){ event.preventDefault() getSelection().removeAllRanges() var startX=event.clientX*1 var startY=event.clientY*1 if(mouseXlast!=null){ if(move){ var boxLeft=getWatcherBody.offsetLeft-(mouseXlast-startX) var xmax=document.body.clientWidth-getWatcherBody.offsetWidth var nox=0 if(boxLeft<0){ boxLeft=0 nox=1 } if(boxLeft>xmax){ boxLeft=xmax nox=1 } if(!nox){ mouseXlast=startX } var boxTop=getWatcherBody.offsetTop-(mouseYlast-startY) var ymax=document.body.clientHeight-getWatcherBody.offsetHeight var noy=0 if(boxTop<0){ boxTop=0 noy=1 } if(boxTop>ymax){ boxTop=ymax noy=1 } if(!noy){ mouseYlast=startY } getWatcherBody.style.left=boxLeft+'px' getWatcherBody.style.top=boxTop+'px' }else{ var width=getWatcherBody.style.width.slice(0,-2) var height=getWatcherBody.style.height.slice(0,-2) var boxWidth=width-(mouseXlast-startX) if(boxWidth>700){ mouseXlast=startX }else{ boxWidth=700 } var boxHeight=height-(mouseYlast-startY) if(boxHeight>400){ mouseYlast=startY }else{ boxHeight=400 } getWatcherBody.style.width=boxWidth+'px' getWatcherBody.style.height=boxHeight+'px' } }else{ mouseXlast=startX mouseYlast=startY } } } function updateScript(){ GM_xmlhttpRequest({ method:'get', url:metajsurl, onload:function(response){ if(response.status==200){ var newversion=response.responseText.match(/@version\s+([^\r\n]+)\s*\n/)[1] if(version!=newversion){ var versionTime=new Date(version.replace(/\./g,'/')).getTime() var newVersionTime=new Date(newversion.replace(/\./g,'/')).getTime() if(newVersionTime>versionTime){ var downloadconfirm=confirm('New version ('+newversion+') is available! Download it now?') if(downloadconfirm){ if(hta){ updateHta() }else{ GM_openInTab(userjsurl) } } }else{ alert('You\'re using the latest version') } }else{ alert('You\'re using the latest version') } }else{ connectionError(website,response.status,metajsurl) } }, onerror:function(){ connectionError(website,0,metajsurl) } }) } function updateHta(){ GM_xmlhttpRequest({ method:'get', url:userjsurl, onload:function(response){ if(response.status==200){ var htafile=response.responseText if(htafile.length){ var fileSystem=new ActiveXObject('Scripting.FileSystemObject') var fileName=unescape(location.href.match(/\/([^\/]+)$/)[1]) if(fileName){ if(fileSystem.FileExists(fileName)){ var openedFile=fileSystem.OpenTextFile(fileName,2,0) }else{ var openedFile=fileSystem.CreateTextFile(fileName) } openedFile.WriteLine(htafile) openedFile.Close() location.reload() } } }else{ connectionError(website,response.status,userjsurl) } }, onerror:function(){ connectionError(website,0,userjsurl) } }) } function connectionError(title,status,url){ if(status){ var statusParsed='HTTP '+status }else{ var statusParsed='Connection error' } alert('Couldn\'t connect to '+title+(status==404?'':', it might be offline at the moment')+' ('+statusParsed+')\n\nURL: '+url) } //</script></body></html>