(function(win, u){var alienFrame = /(plusone\.google\.com|spmbt\.github\.io)/.test(location.host) ,metaTx = !alienFrame && function(s){return(s= //если Firefox+GreaseMonkey, требуется удалить "/*" перед "; // @resource meta habrAjax.meta.js // @icon data:image/gif;base64,R0lGODlhIAAgAMMBAG6Wyv///2+NtIucstfY2b/FzpSmvY+QkM3Nzunp6fLy8qGwweDg4MbFxa2trrm6uiwAAAAAIAAgAAAE/xDISau9OM/AOe2edoHBBwqiRZodmrKhRLqXYFfrdmLCQBQGWk62swgOiERAQQgChs9iRZBMKDgEFGnbMi4YDMU1gNBytzSJDcGwXhUD4lmqZofFioZrPqMIDARtYksIAzZ8dAINgngJVgkLUH1qBmBuCgmBYA6SUgKBl0wICA6lk1FdAAIFjngKDAgEpKYgWXIcKH8EDQ0EVwmjsrycIA4FZl2rDwcHDgivow8ODwzEHca3ASgDpMylsrEOzdUkDk59AtOl07wIDcwNkDbzCy7z8xIDD8Ps3Q5hCQqscxBHgw0DbEY1WIbEkRtHZV6oMsAq0wNqrcQ4KihR1Z9YjzUeKjjWcYqABUoaJeBY0k8bAm5ItqxgANjFBnBmTgnTQNw0nVOSNBjQLA1QXdEMATVioGnJCAA7 // @downloadURL none // ==/UserScript== */s//]]> )} // © licensed by LGPLv3 Open Source www.gnu.org/licenses/lgpl-3.0.en.html ,isFxScr = typeof GM_getMetadata !=u //-Scriptish ,readMeta = function(s, isFxScr){ //парсинг многострочного текста по мета-директивам if(typeof s !='string') //очистка оболочки функций, выделение мн-стр-комментария s = typeof s=='function' ? ((/\*/.test(function(){/**/}+1) ? s : s(!1) )+'') .replace(/(^[\s\S]*\*\/\/\*\r?\n?|\r?\n?\*\/s[\s\S]*$)/gm,'') : (typeof s !=u && s!==null && s.toString ? s.toString() :''); //здесь же- 'xml' var metaD ={}, j =0; if(s==='false'&& isFxScr){ //получать ли данные средствами Scriptish metaD = GM_getMetadata(); for(var i in metaD){ //приведение к нормальному виду if(metaD[i].length ==1) metaD[i] = metaD[i][0]; j++; } }else{ var meta = s.split('\n'), aa, a2; for(var i=0, mL = meta.length; i < mL; i++){ if(( aa = /^.*?\/\/\s*@([\S]+)\s(\s*)(.*)/g.exec(meta[i]) )){ a2 = aa[3] !==undefined && aa[3] || aa[2]; if(metaD[aa[1]]===undefined) metaD[aa[1]] = a2; else{ if(! (metaD[aa[1]] instanceof Array)) metaD[aa[1]] = [metaD[aa[1]]]; metaD[aa[1]].push(a2); } j++; }else if(!/^.*?\/\/\s*[\-=]*\s*\/?\s*UserScript\s*[\-=]*\s*$/i.test(meta[i])) metaD[j++] = meta[i]; } } return j >1 && metaD || undefined; //хеш директив + нум.список простых строк + _length -чис.простых строк или und., если не найдено }, extMeta = function(m, callback, callErr){ //или (url, callback, callErr)//получение внешних метаданных if(typeof m =='string') var shortNum = (/^\d+(\.meta\.js)?$/.test(m) ? m :'') + (/^\d+$/.test(m) ?'meta.js':'') ,xUrl = shortNum ? URLSCR + HAJAX +'/code'+ shortNum : m ; //wcl(m, shortNum, xUrl) if(typeof GM_xmlhttpRequest !=u){ GM_xmlhttpRequest({ url: xUrl ,method:'get' //Chrome ,onload: callback //параметр - req (для req.responseText) ,onerror: callErr //параметр - req (для req.responseText) }); }else if(win.opera && xUrl){ //load metadata for Opera var ifr = document.createElement('iframe'); ifr.src = xUrl; ifr.style.display ='none'; document.body.appendChild(ifr); ifr.name = ifr.id ='operaEmbedMeta'; win.addEventListener('msg', function(ev){ //слушать приход Event callback({responseText: ev.data.replace(/\n?\noperaEmbedMeta$/,''), finalUrl: xUrl}); },!1); }else wcl('~~No read metadata!'); //другой способ запроса внешнего сервера по ajax return {waitHandler: 0 //для немедленного таймаута ,callback: callback, callErr: callErr}; //для немедленного завершения }; win = (function(){return this})(); var DAY = 86400000 ,CHKUPD = 15 //мин. период проверок обновлений скрипта (минут) при ошибках чтения ,NOWdate = new Date() ,NOW = +NOWdate,HSO='http://habrastorage.org',SHRU='https://habrahabr.ru/auth' ,HRU ='http://habrahabr.ru',sHQ='habr.statis.tk/c?id=@&in=@&zc=@&at=@' //37.230.115.43исп-ть ли сервер статистики ,HRs ={ha: HRU, geek:'http://geektimes.ru',manag:'http://megamozg.ru',qa:'http://toster.ru',haru:'http://haru'} ,HClons ={soha:'sohabr',sape:'savepearlharbor',haru:'haru'} ,ROOT = location.protocol +'//'+ location.host ,URLSCR ='https://greasyfork.org/scripts/' ,URLCSS ='http://userstyles.org/styles/33690/' ,HAJAX ='1970-habrajax/' ,userNameMaxLen = 25 ,isFx = /Firefox/.test(navigator.userAgent) ,isChrome = /Chrome\//.test(navigator.userAgent) ,wcl = function(a){ a = a!==undefined ? a :''; //консоль как метод строки или функция, с отключением по hS.noConsole.val ==1 if(win.console && typeof hS !=u && !hS.noConsole.val) win.console.log.apply(console, this instanceof String ? ["'=="+ this +"'"].concat([].slice.call(arguments)) : arguments); } , strongCutImgMinH; String.prototype.wcl = wcl; String.prototype.trim = function(s){var s = this ||s; return s.replace(/(^\s+|\s+$)/g,'')}; if(win.opera || typeof GM_xmlhttpRequest ==u) GM_xmlhttpRequest = function(h){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ var responseState ={ responseXML: xhr.readyState==4 ? xhr.responseXML :'' ,responseText: xhr.readyState==4 ? xhr.responseText :'' ,readyState: xhr.readyState ,responseHeaders: xhr.readyState==4 ? xhr.getAllResponseHeaders() :'' ,status: xhr.readyState==4 ? xhr.status : 0 ,statusText: xhr.readyState==4 ? xhr.statusText :'' }; h.onreadystatechange && h.onreadystatechange(responseState); if(xhr.readyState==4){ if(h.onload && xhr.status>=200 && xhr.status<300) h.onload(responseState); if(h.onerror && (xhr.status<200 || xhr.status>=300)) h.onerror(responseState); }}; try{//cannot do cross domain xhr.open(h.method, h.url); }catch(er){ if(h.onerror) //simulate a real error h.onerror({responseXML:'',responseText:'',readyState:4,responseHeaders:'',status:403,statusText:'Forbidden'}); return; } if(h.headers) for(var prop in h.headers) xhr.setRequestHeader(prop, h.headers[prop]); xhr.send((typeof(h.data) !=u) ? h.data : null); }; try{ //для оповещения об ошибках в Fx var metaD = readMeta(metaTx, isFxScr) //metaTx == false ||'false'(строка) - если Fx|| строки метаданных ,gPlusFrame = alienFrame && /plusone/.test(location.host); win.adriver = function(){}; win.adriver.domReadyQueue ={execute: function(){},Plugin: function(){this.a =1;}}; //=============================================== //'testUScr'.wcl({isFxScr:isFxScr, unsafeWindow: typeof unsafeWindow !=u}); //win !==window при Greasemonkey|Scriptish if(!alienFrame){ //alert(addEventListener) win.addEventListener('message', function(ev){ //слушать приход данных //'start_parse'.wcl(win.JSON , win.JSON.parse, win.JSON.decode) if(win.JSON && !win.JSON.parse && win.JSON.decode) win.JSON.parse = win.JSON.decode; //habr - old //опера требует этого внутри хендлера //'decode'.wcl(win.JSON , !win.JSON.parse , win.JSON.decode, win.JSON && !win.JSON.parse); if(/likes/.test(ev.data) && /frme/.test(ev.data) && win.JSON && win.JSON.parse){ //поставить лайки снаружи var n = JSON.parse(ev.data); if(n){ //'parsed_data'.wcl(n); var frs = document.getElementsByTagName('iframe'); for(var i in frs) if(frs[i].name == n.frme){ frs[i].setAttribute('likes', n.likes); var x = frs[i].parentNode.parentNode.querySelector('.likes div div'); x && (x.innerHTML = n.likes); } } } if(/\noperaEmbedMeta$/.test(ev.data) && win.JSON && win.JSON.parse){ //alert(ev.data) var evt = document.createEvent('Event'); //генерировать для перехвата на приёме файла evt.initEvent('msg',!0,!0); evt.data = ev.data; win.dispatchEvent(evt);} },!1); } if(gPlusFrame){ /** * evaluate script in window scope * @param{Function} fs function or string is body of function * @param{String|Array} s string or array of strings for arguments * @param{Boolean} noOnce not delete script after exec */ var winEval = function(fs, s, noOnce){ //exec function/text in other scope s = (s ||[]) instanceof Array? s ||[] : [s]; //wrap by array alert(s +' '+ 'fs2') var fs2 = typeof fs=='function' ? (fs +'').replace(/(^\s*function\s*\([^\)]*\)\s*\{\s*|\s*\}\s*$)/g,'') //clean wrapper : fs ,as =''; for(var i =0, sL =s.length; i < sL; i++) //sequential array as += (i?',':'') +"'"+ s[i].replace(/'/g,"\\'").replace(/(\r\n|\r|\n)/g,"\\\n") +"'"; fs = '(function(){'+ fs2 +'}).apply(window,['+ as +']);'; //'fs'.wcl(fs, fs2) var d = document ,scr = d.createElement('script'); scr.setAttribute('type','application/javascript'); scr.textContent = fs; var dPlace = d.body || d.getElementsByTagName('head') && d.getElementsByTagName('head')[0]; dPlace.appendChild(scr); if(!noOnce) dPlace.removeChild(scr); }; /** * check occurrence of third-party event with growing interval * @constructor * @param{Number} t start period of check * @param{Number} i number of checks * @param{Number} m multiplier of period increment * @param{Function} check event condition * @param{Function} occur event handler */ var Tout = function(h){ var th = this; (function(){ if((h.dat = h.check() )) //wait of positive result, then occcurense h.occur(); else if(h.i-- >0) //next slower step th.ww = win.setTimeout(arguments.callee, (h.t *= h.m) ); })(); }; new Tout({t:320, i:6, m: 1.6 ,check: function(){ return document && document.querySelector('#aggregateCount'); } ,occur: function(){ var id = location.hash.match(/(\?|#|&)id=([^&]+)/) //frame id [or name] ,w = win; id = id && id.length && id[2]; var s = w.JSON && w.JSON.stringify && w.JSON.stringify( //must supported earlier {likes: this.dat.innerHTML, frme: id}) //data format ,pHost = (function(a){ //host extract from parameter (#|&)parent if(!a.match(/^https?\:\/\//)) return''; var b = document.createElement('a'); b.href = a; b.pathname = b.search = b.hash =''; return b.href.replace(/\/\??\#?$/,'') })( decodeURIComponent( (w.location.href.match(/.*(\?|#|&)parent=([^&]+)/) ||[])[2] ||'') ); try{ if(!isChrome || w.parent && w.parent.postMessage){ s && w.parent.postMessage(s, pHost); //all browsers except Chrome }else if(s) winEval(function(args){ var w = window ,p1 = arguments[0] ,p2 = arguments[1]; if(w.postMessage && p1 && w != w.parent){ function wpm(){ w.parent.postMessage(p1, p2); //msg with a glance Chrome bug } w.document.all ? w.setTimeout(wpm, 0) : wpm(); } }, [s, pHost]); }catch(er){wcl(er)} } }); }else if(alienFrame){ // для Оперы (только) в фрейме greasyfork.org - отправка метаданных document.addEventListener('DOMContentLoaded',function(){ var dd = document.querySelector('pre') ,s = dd && dd.innerHTML; if(s && win.parent && win.parent.postMessage) win.parent.postMessage(s +'\noperaEmbedMeta', ROOT); },!1); } //(далее выполняется, если не в alienFrame) if(alienFrame) return; var setLocStor = function(name, hh){ if(!localStorage) return; localStorage['habrAjax_'+ name] = JSON.stringify({h: hh}); }, getLocStor = function(name){ return (JSON.parse(localStorage && localStorage['habrAjax_'+ name] ||'{}')).h; } ,removeLocStor = function(name){localStorage.removeItem('habrAjax_'+ name);} ,lh = location.href ,$q = function(q, f, f2, args){ // контекстный DOM-селектор или условная функция с ним: (elem)q | ((str)q, f, args) | ((str)q, elem) | ((str)q, (elem)context, f, args) var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelector(q); return f instanceof Function ? f && Q ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q : f2 instanceof Function ? f2 && Q ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q } ,$qA = function(q, f, f2, args){ var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelectorAll(q); return f instanceof Function ? f && Q.length ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q : f2 instanceof Function ? f2 && Q.length ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q } previButt = $q('#post_form .buttons input[name="preview"]') wwPrevi =0; previButt && previButt.addEventListener('click',function(ev){ wcl('previclick'); win.clearTimeout(wwPrevi); textContentPrev ='00'; fillLetter();$pd(ev); },!1); var textContentPrev ='00' ,fillLetter = function(){ //сформировать письмо в ЛС var aLHash = lh.replace(/^[^#]*#/,'').split('&') ,hLHash ={} ,lStor = getLocStor('composeLetter') ,lStNoBq = lStor && !/<\/?blockquote>/.test(lStor.cite); if(/\/(add|edit)\//.test(lh)){ //страница редактирования (своей) статьи - по цитате var ta = $q('#text_textarea') ,cite = lStor && lStor.cite ,text = lStor && lStor.text ,textContentDiv = $q('#preview_placeholder .content'); if(textContentDiv) var textContent = textContentDiv.innerHTML; //содержимое статьи if(ta && typeof cite !=u){ var tVal = ta.value ,iS =[] ,cL = cite.length; for(var i =0, tL = tVal.length; i < tL; i++) if(tVal.substr(i, cL) == cite) iS.push(i); //все индексы вхождения строк 'cite'.wcl(iS, cite) if(iS.length){ if(iS.length >1) //выделить найденное hN && hN.addNote(nSufRu(iS.length, ['образ','ец','ца','цов'])+' для правки; следующий',0,0,function(){ var c1 = $q('a', this.o); c1.addEventListener('click', function(ev){ var i = !c1.getAttribute('data-curr') ? 1: +c1.getAttribute('data-curr') ,a = JSON.parse(c1.getAttribute('data-match') ) ,cite = c1.getAttribute('data-patrn'); ta && ta.setSelectionRange && ta.setSelectionRange(a[i], a[i] + cite.length); c1.setAttribute('data-curr', (++i) % a.length); ta.blur(); ta.focus(); $pd(ev); },!1); }); var i1 = iS[0]; 'citeEnd0'.wcl(nSufRu(iS.length, ['образ','ец','ца','цов']) ) ta && ta.setSelectionRange && ta.setSelectionRange(i1, i1 + cL); 'citeEnd'.wcl(iS, cite) }else hN && hN.addNote('не найдено образцов для правки'); 'citeEnd1'.wcl(iS, cite) ta.focus(); removeLocStor('composeLetter'); } if(textContentPrev !='00'&& textContent != textContentPrev){ //обработать подгруженное 'renderOfAvaxTxt'.wcl(textContentPrev && textContentPrev.length, textContent && textContent.length) authorClicks(textContentDiv); //особые клики по авторам (напр. в фрейм) //blockBrs(textContentDiv); //сокращение верт.зазоров extLinks(textContentDiv); //ext.links и подписи к старым местным линкам handlImgViews(textContentDiv); //images byTextNodes(textContentDiv, haReplace); // --> XX //обработка выделения текста }else wwPrevi = win.setTimeout(fillLetter, 1499); //проверка обновлений cite if(textContentPrev =='00') textContentPrev = textContent; return; } 'conversations'.wcl(lStor, hLHash, lStNoBq, aLHash.length); if(aLHash[0] ==lh) aLHash =[]; for(var i =0; i < aLHash.length; i++){ var a = aLHash[i].split('='); hLHash[a[1]!==undefined && a[0]] = decodeURIComponent(a[1]!==undefined && a[1] || a[0]); } var fieldTo = $q('.conversation_page input[name="users-suggest"]') ,fieldTheme ='Тема: ' ,fieldText = $q('#text_textarea'); 'fieldTo'.wcl(fieldTo, fieldTheme, fieldText); fieldTo &&(fieldTo.value = hLHash.to && hLHash.to.trim() || lStor && lStor.to ||''); fieldTheme += hLHash.subj && hLHash.subj.trim() || (lStor ?(lStor.url ?'':'') + lStor.subj +(lStor.url ?'':''):'') +(!hLHash.subj && lStor && lStor.date && lStor.subj ?' ('+ lStor.date +')':''); if(fieldText) fieldText.value = (fieldTheme ? fieldTheme +'\n':'') + (aLHash.length && !(/^comment_\d+$/.test(aLHash[0])) && ( //по URL-параметрам hLHash.cite && ('
'+ hLHash.cite +'
') ||' ' )|| (lStor ?( //по хранилищу, если нет URL-параметров (lStor.commId ?' # '+ lStor.commId +' ' +'@'+ lStor.commAuthor +'\n':'') +(lStNoBq?'
':'')+ (lStor.cite ||'') +(lStor.commDate?' ('+lStor.commDate+')':'') +(lStNoBq?'
':'') +(lStor.text ? lStor.text :'') ):'') ); 'lStor.cite'.wcl(lStor && '|'+lStor.cite+'|'+lStor.commAuthor) if(lStor && !aLHash.length && !lStor.noReceiver) removeLocStor('composeLetter'); if(lStor && lStor.noReceiver){ if(lStor && lStor.noReceiver ==2) delete lStor.noReceiver; 'lStor'.wcl(lStor) lStor.noReceiver =2; setLocStor('composeLetter', lStor); } if(fieldTo) fieldTo.focus(),fieldTo.select(); //выделен адресат для быстрой смены if(fieldText){ fieldText.focus(); //в поле ввода текста /*var evt = document.createEvent("KeyEvents"); evt.initKeyEvent('keyup',!0,!0, win,!1,!1,!1,!1, 40,0); fieldText.dispatchEvent(evt);*/ } }, nSufRu = function(n, vocab){ //числительные склонения слов ("день" и др.) var an = Math.abs(n) ,vocab = typeof vocab =='number'? [['д','ень','ня','ней']][vocab] : vocab; return n +' '+ vocab[0] + (an % 10 >0 && an % 10 <5 && Math.floor(an % 100 / 10) !=1 ? (an % 10 ==1 ? vocab[1] : vocab[2]) : vocab[3]); }; //===begin from Dollchan Extension Tools=== --группа функций просмотра изображений-- var doc = win.document ,$pd = function(ev){ev.preventDefault();} ,$sp = function(ev){ev.stopPropagation();},$pdsp = function(ev){ev.preventDefault();ev.stopPropagation();} ,$dispTogl = function(el){el.style.display = el.style.display ==='none'?'':'none'; return el;} ,$offset = function(el){ var box = el.getBoundingClientRect(), aa; 'offset'.wcl(aa={ top: Math.round(box.top + win.pageYOffset), left: Math.round(box.left + win.pageXOffset) }) return aa; }, addFullImg = function(a, sz, x2, isExp){ //построение изображения по клику на ссылке x2 = x2 || 1; var newW ='' ,newH ='' ,fullW = x2* sz[0] ,fullH = x2* sz[1] ,scrW = doc.documentElement.clientWidth -10 ,scrH = win.innerHeight -3 ,isA = a.tagName =='A' ,full = isA ? $q('.de-img-full', a) : a.nextSibling; if(full && /de-img-full/.test(full.className) && isExp || !full && isExp === false) return; if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val && !$q('img[style*="fixed"]', a) ) $dispTogl($q('img', a)); //TODO зкспериментально; отключено if(full && /de-img-full/.test(full.className)){ if(full.moved) full.moved = false; else{ $dispTogl(full); setTimeout(function(){full.parentNode.removeChild(full);},1); } return; } if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val) scrW -= $offset(a).left + 25; //TODO зкспериментально; отключено else{ var el = $q('.de-img-center', doc); el && el.parentNode.removeChild(el); } if(fullW && fullH){ newW = Math.min(fullW, scrW); newH = newW * fullH / fullW; if(hS.viewImgCenter.val && newH > scrH){ newH = scrH; newW = newH * fullW / fullH; } if(newW/fullW < 1.13 && newW / fullW >0.88){ newW = +fullW; newH = +fullH; var title = x2 +'00%'; } } if(!title) title = Math.round(newW / fullW *100)* x2 +'%'; var isViewUrl = !hS.addImgs.val && a.getAttribute('data-viewUrl') ,url = isA ? a.href : isViewUrl || (a.previousSibling && a.previousSibling.firstChild.src)|| a.src; if(/#\.jpg/.test(url) ) url = a.firstChild.src; if(isViewUrl) title ='100%'; var ht =''+
		url +'' if(a.insertAdjacentHTML) a.insertAdjacentHTML(isA ?'beforeend':'afterend', ht); //Fx8+ else $e( $x(isA?{apT: a}:{aft: a}, {ht:ht}) ); //неточно, и ошибки в Fx3.6 if(hS.viewImgCenter.val){ var resizeImg = function(ev){ //обработчик колеса мыши - масштаб картинки var curX = ev.clientX ,curY = ev.clientY ,oldL = parseInt(this.style.left, 10) ,oldT = parseInt(this.style.top, 10) ,oldW = parseFloat(this.style.width || this.width) ,oldH = parseFloat(this.style.height || this.height) ,d = isFx ? -ev.detail : ev.wheelDelta ,newW = oldW * (d >0 ? 1.25 : 0.8) ,newH = oldH * (d >0 ? 1.25 : 0.8) ,sizes = full.getAttribute('data-sizes').split('x'); if(newW/sizes[0] < 1.13 && newW / sizes[0] >0.88){ newW = +sizes[0]; newH = +sizes[1]; this.title = x2 +'00%'; }else this.title = Math.round(newW / fullW *100)* x2 +'%'; $pd(ev); this.style.width = newW +'px'; this.style.height = newH +'px'; this.style.left = parseInt(curX - (newW/oldW) * (curX - oldL), 10) +'px'; this.style.top = parseInt(curY - (newH/oldH) * (curY - oldT), 10) +'px'; }; full = $e({el: isA ? a.lastChild : a.nextSibling ,clAdd:'de-img-center' ,cs: {left: (scrW - newW)/2 +'px', top: (scrH - newH)/2 +'px'} ,at: {'data-sizes': fullW +'x'+ fullH} ,on: isFx ? {DOMMouseScroll: resizeImg}:{mousewheel: resizeImg} }); !isA && full.addEventListener('click',function(ev){ $pdsp(ev); if(full.moved) full.moved = false; else{ $dispTogl(full); win.setTimeout(function(){full.parentNode && full.parentNode.removeChild(full);},1); } },!1); (function(el){ //makeMoveable --перетаскивание var elMove = function(ev){ el.style.left = ev.clientX - el.curX +'px'; el.style.top = ev.clientY - el.curY +'px'; el.moved = true; }, elStop = function(ev){ var t = ev.target; $e({el: doc.body ,revent:{mousemove: elMove, mouseup: elStop}}); if(ev.ctrlKey && t.parentNode.tagName=='A') t.parentNode.click(); //нативный клик вынесен под Ctrl+ if((Math.abs(ev.clientX - el.startX) + Math.abs(ev.clientY - el.startY) ||0) <5 && ev.which ==1){ $dispTogl(t); win.setTimeout(function(){t.parentNode.removeChild(t);},1); } }; el.onmousedown = function(ev){ $pd(ev); el.curX = (el.startX = ev.clientX) - parseInt(el.style.left, 10); el.curY = (el.startY = ev.clientY) - parseInt(el.style.top, 10); $e({el: doc.body ,on:{mousemove: elMove, mouseup: elStop}}); }; })(full); } }, handlImgViews = function(el, selector){ //обработчики просмотров картинок var selector = selector ||'.content a[href$=".jpg"],.content a[href$=".jpeg"],.content a[href$=".png"],.content a[href$=".gif"], .message a[href$=".jpg"],.message a[href$=".png"],.message a[href$=".gif"], .comments .text a[href$=".jpg"], .comments .text a[href$=".png"], .comments .text a[href$=".gif"]' ,els = $qA(selector, el); //все ссылки на картинки //'handlImgViews'.wcl(el, selector, els ) for(var i =0, linkImg; linkImg = els[i++];){ //подгрузка картинок в рамках до 200 на 200 по расширениям файлов в ссылках var a = linkImg.cloneNode(false) ,imgsInLink = $qA('img', linkImg); if(imgsInLink && imgsInLink.length !=1 && hS.addImgs.val){ //подгружать картинки-ссылки var lastLink = linkImg; $e({el:'img' //малая картинка со ссылкой перед найденной ссылкой ,cl:'de-img-pre' ,at:{src: a.href, alt: a.href.substr(0,200)} ,on:{load: function(){ var t = this ,fullW = t.width ,fullH = t.height ,x2 = hS.viewX2.val && fullW *2 < win.innerHeight -3 ? 2:1; //признак "x2" - удваивать масштаб t.title = (x2 ==2 ?'/':'')+ fullW +'x'+ fullH; //'on:{load'.wcl(t.title, lastLink) if(lastLink.firstChild && lastLink.firstChild.tagName =='BUTTON'){var evt = document.createEvent('Event');evt.initEvent('loadImg',!0,!0); evt.data = t.title; win.dispatchEvent(evt);} t.style.cursor = x2 ?'ne-resize':'move'; if(/^imgL$/.test(t.parentNode.className)|| t.parentNode.className =='lnk'){ //включить видимость копий, выключить - оригиналы ссылок t.parentNode.style.display ='inline-block'; t.parentNode.nextSibling.style.display ='none'; t.parentNode.title = t.title; if(t.parentNode.className =='lnk') t.parentNode.className ='lnk imgL'; }else $dispTogl(t.parentNode); if(fullW <= 200 && fullH <= 200) return; var k = fullW/fullH; t.width = k < 1 ? 200 * k : 200; t.height = k < 1 ? 200 : 200/k; }}, apT: $e({el: function(){ var pImg = linkImg.previousSibling; if(pImg && pImg.className=='aPrevi imgL') pImg.parentNode.removeChild(pImg); pImg = linkImg.previousSibling; if(pImg && pImg.className=='aPrevi imgL') pImg.parentNode.removeChild(pImg); return $dispTogl(a); } ,at:{target:'_blank'} ,on:{click: function(ev){ //eventLinkImg(a); //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1) if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){ if(ev.ctrlKey) return; $pd(ev); if(showImgMenu(ev, ev.currentTarget.frstChild) ) //по Shift+клик return; var titl = this.firstChild.title ,imgWH = titl.match(/(\d+)x(\d+)$/) ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2" if(imgWH && imgWH.length ==3) addFullImg(this, imgWH.slice(1), x2); } }} ,bef: linkImg }) }); }else //подготовка тамбнейла для просмотра по клику на нём ссылки imgsInLink && imgsInLink.length ==1 && $e({el: imgsInLink[0] ,clAdd:'de-img-thumb' ,at:{'data-viewUrl': linkImg.href} }); } if(!(hS.viewImgs && hS.viewImgs.val) && !hS.viewImgCenter.val) //не просматривать картинки в странице return; for(var img, i =0, imgs = $qA('.content img:not(._noAddOwnView),.message img:not(._noAddOwnView),.message .text img:not(._noAddOwnView)', el); img = imgs[i++];){ //'12'.wcl(img,img.width , img.height) if( (img.width >22 || img.height >22 || img.width==0 || img.height==0) && (!img.previousSibling || img.previousSibling && img.previousSibling.className !='de-img-hid') ) (function(img){$e({el:'img' //полная картинка в невидимом диве с overflow ,cl:'_noAddOwnView' ,at:{src: hS.addImgs.val && img.getAttribute('data-viewUrl') || img.src} ,cs:{position:'absolute', left:'-9999px'} ,on:{load: function(ev){ var fullW = this.width ,fullH = this.height; this.title = fullW +'x'+ fullH; $dispTogl(this.parentNode); //'WHBig'.wcl(fullW, img.width, fullH, img.height, img); if(fullW == img.width && fullH == img.height){ img.style.cursor ='ne-resize'; if(hS.viewX2.val) this.title = '/'+ this.title; //признак "x2" (особый курсор) }else if(!hS.viewX2.val){ img.style.cursor ='move'; img.setAttribute('data-view',1); } }}, apT: img.previousSibling && img.previousSibling.className =='de-img-hid' && img.previousSibling || $e({cl:'de-img-hid' ,cs:{overflow:'hidden', width:0, height:'8px'} ,bef: img }) }) })($e({el: img //обработчик и смена курсора картинки ,cs: hS.viewX2.val ?{cursor:'move'}:{} ,on:{click: function(ev){ //eventLinkImg(a); //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1) var t = ev.currentTarget; if(!hS.viewX2.val && !t.getAttribute('data-view') ) return; //не просматривать, если размер не изменится if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){ if(ev.ctrlKey) return; $pd(ev); if(showImgMenu(ev, t)) //по Shift+клик return; var titl = this.previousSibling.firstChild.title ,imgWH = titl.match(/(\d+)x(\d+)$/) ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2" if(imgWH && imgWH.length ==3) addFullImg(this, imgWH.slice(1), x2); } }} })); } }, showImgMenu = function(ev, img){ //контекстное меню на картинке - поиск по изображению if(!ev.shiftKey) return; else{ var srcD ={TinEye:{url:'tineye.com/search/?url='} ,Google:{url:'google.com/searchbyimage?image_url='} ,Yandex: {url:'images.yandex.ru/yandsearch?text=&rpt=imagedups&img_url='} ,SauceNAO:{url:'saucenao.com/search.php?url='} ,IQDB:{url:'iqdb.org/?url='} } ,srcMenu = $e({cl:'de-menu' ,on:{mouseout: function(){ $dispTogl(srcMenu); win.setTimeout(function(){srcMenu.parentNode.removeChild(srcMenu);},1); }} ,cs:{left: ev.pageX -30 +'px', top: ev.pageY -24 +'px'} ,apT: doc.body }); for(var i in srcD) $e({el:'A' ,cl:'de-src' ,at:{target:'_blank', href:'http://'+ srcD[i].url + img.src} ,ht:' '+ i ,on:{mouseout: function(ev){ $sp(ev);}} ,apT: srcMenu }); } return 1; };//===end from Dollchan var allASCII = function(s){ //все символы строки - ASCII for(var i =0; i < s.length; i++) if(s.charCodeAt(i) >127) return !1; return!0; }, $x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el;}, //===extend=== $e = function(g){ //===создать или использовать имеющийся элемент=== //g={el|clone,blck,elA,cl|(clAdd,clRemove),ht,cs,at,atRemove,on,revent,ap,apT,prT,bef,aft,f+fA} if(typeof g.el =='function') g.el = g.el.apply(g, g.elA); if(!g.el && g.el !==undefined && g.el !='') return g.el; //null|0|false var x, o = g.el = g.el || g.clone && typeof g.clone !='string' && g.clone.cloneNode(!0) || /\W/.test(g.clone) && (x = $q(g.clone, g.blck)) && x.cloneNode(!0) ||'DIV'; o = g.el = typeof o =='string'? /\W/.test(o) ? $q(o, g.blck) : document.createElement(o) : o; if(o){ //выполнять, если существует el или clone if(g.cl) o.className = g.cl; else{ if(g.clAdd) o.classList.add(g.clAdd); if(g.clRemove) o.classList.remove(g.clRemove);} if(g.cs) $x(o.style, g.cs); if(g.ht || g.at){ var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;} if(at) for(var i in at){ if(i=='innerHTML') o[i] = at[i]; else o.setAttribute(i, at[i]);} if(g.atRemove) for(var i in g.atRemove) o.removeAttribute(g.atRemove[i]); if(g.htT){ //подготовка шаблона if(!(typeof g.htTA =='object')) g.htTA =[g.htTA]; for(var i in g.htTA) g.htT = g.htT.replace(RegExp('\\{\\{'+ i +'\\}\\}','g'), g.htTA[i]) o.innerHTML = g.htT;} if(g.on) for(var i in g.on) if(g.on[i]) o.addEventListener(i, g.on[i],!1); if(g.revent) for(var i in g.revent) if(g.revent[i]) o.removeEventListener(i, g.revent[i],!1); if(g.ap){ //добавление нод if(g.ap instanceof Array){ for(var i in g.ap) if(g.ap[i] && i !='length') o.appendChild(g.ap[i]); }else o.appendChild(g.ap);} g.apT && g.apT.appendChild(o); g.prT && (g.prT.firstChild ? g.prT.insertBefore(o, g.prT.firstChild) : g.prT.appendChild(o) ); g.bef && g.bef.parentNode.insertBefore(o, g.bef); g.aft && (g.aft.nextSibling ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling) : g.aft.parentNode.appendChild(o) ); g.remove && g.remove.parentNode.removeChild(g.remove); if(typeof g.f =='function') g.f.apply(g, g.fA); //this - это g } return o; /* var x= {cl: function(){o.className = g.cl;} ,clAdd: function(){o.classList.add(g.clAdd);} ,clRemove: function(){o.classList.remove(g.clRemove);} ,cs: function(){$x(o.style, g.cs);} ,ht: function(){var at = g.at ||{}; at.innerHTML = g.ht;} ,at: function(){var at = g.at ||{}; for(var i in at){ if(i=='innerHTML') o[i] = at[i]; else o.setAttribute(i, at[i]);}} ,ap:function(){if(g.ap instanceof Array){ for(var i in g.ap) if(g.ap[i] && i !='length') o.appendChild(g.ap[i]); }else o.appendChild(g.ap);} ,on:function(){for(var i in g.on) if(g.on[i]) o.addEventListener(i, g.on[i],!1);} ,revent:function(){for(var i in g.revent) if(g.revent[i]) o.removeEventListener(i, g.revent[i],!1);} ,apT:function(){g.apT.appendChild(o)} ,prT:function(){g.prT.firstChild ? g.prT.insertBefore(o, g.prT.firstChild) : g.prT.appendChild(o)} ,bef:function(){g.bef.parentNode.insertBefore(o, g.bef)} ,aft:function(){g.aft.nextSibling ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling) : g.aft.parentNode.appendChild(o)} }; for(var i in g) //проход по числу параметров, проп-о объёму задачи g[i] && x[i] && x[i]();*/ }, addRules = function(css){ if(typeof GM_addStyle !=u) GM_addStyle(css); //Fx,Chr else if(typeof addStyle !=u) addStyle(css); else{ //Op var heads = document.getElementsByTagName('head') ,node = $e({el:'style' ,apT: heads.length && heads[0] }); node.appendChild(document.createTextNode(css)); //не проходит в Опере через $e } }, getPosition = function(o){ var x =0, y =0; while(o){ x += o.offsetLeft ||0; y += o.offsetTop ||0; o = o.offsetParent || o.parentNode; } return {x:x, y:y}; }, parents = function(cl, elem){ for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.parentNode); return el; }, parentsPrev = function(cl, elem){ for(var el = elem, pr; el!=null && !RegExp(cl).test(el.className); el = el.parentNode) pr = el; el.prev = pr; return el; }, prev = function(cl, elem){ for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.previousSibling); return el; }, next = function(cl, elem){ for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.nextSibling); //el.className != cl return el; }, evtChangeDom = function(voteA){ //===== сообщение о смене DOM, 'chgDom' ==== var evt = document.createEvent("CustomEvent"); if(evt && evt.initCustomEvent){ //TODO поддержку простых Event через хранилище или GM_setValue evt.initCustomEvent('chgDom',!0,!0, voteA); win.dispatchEvent(evt); return!0; }}; if(/habrastorage\.org/.test(lh)){ var hsoLogo = $q('.wrapper .header .logo'), hsoCloud = $q('.content #upload_cloud img'); if(hsoLogo && hsoCloud){ hsoCloud.src ='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAACPCAMAAAAbfxOfAAABPlBMVEVOhrqrx95/qszW4u5fotmWttbE2OlkmMJipt/w9fpWlsqZw+p+st6w1vLE3/VtsupUksXg7/i3z+Kiwttwos1xq9+Evu7+/v7Q4OymyuaqzOqMs9JunsZam9BWjr2fvttmq+T1+vzo8fljncvS4/Nck7/g6vLK3uudy/FSjr2xzuWXvt+91ud3tup4pcqQw+5nos/K2ur29vqRut6myuJ/uuy72/Z/rtbX6fmWxvB2qtSGuuaOutpuruijzfKyyuFqnsa+0uamw9ys0vKSttJqreXq9v16uu6qyuaGrs6avtnE2u5qmsTw9v5alsyexua21/PK4fW50uqfw+JyptKKv+2KttpentZmrurq8v5qnsrQ5vpdlcZ6tu5ysupSjsK+1u5qotaGuuqGstZqrupOirrY5vFeptqYutgAAAD/YHsOAAAAanRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AvOTc4wAAAAFiS0dEAIgFHUgAAAgHSURBVHjaxZz7Y9JIEMdDwUDwSoEqm5OSkliwaS2IHrT1TmpbW18FWx8Hnhzcg+Tg//8HLhtCy2N3M3ky/mRV+Djz3dnXzHJjryYrelTEppcF5PXDOPf/VKlF7q3FtTkrbb3fzkblkHHkJ2cVSaMaF89nyygkHD1S0QBWyvNC4Djl7fnwqINBOp1OJpNt81fS+M1gMFCtP107FQLEEU6u5kjSyXah04kl5iwW6xQKBpbFlBdRMDjl/DxKIWaAFA0bzln3wviRQdUxmAb478ZPZP9xxDvBqBgFk3SHdMNMGAkTSZuCvzh3MBOWRZfQkSZEUCAQTnltCjNIg1ms0GGidlrVpAjyB0cY3cIkO45YpkSJWMEAivM+4KBsyYJJFwyY7tCNGS4qGLpeU7ziKGuznhm6NhNIlU6QJxxe8gVmAoRDtia4x5GtTKMmC27DtAg0KPFuccpXU9HEfIAxgRKdpLqNXOFYgVK9x2lulBXSjIDRcSLcRDWGa4Y+GnbQleIUB72xAuWja6ZAsUIv6gxHXrMC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'; $e({el:hsoLogo ,cs:{backgroundImage:'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABHCAMAAAB4UkqjAAABblBMVEVorulnrednrObW5vX2+Pmhv9tTkcTm7/eVw+ygye681/LI3vS41vGCuemeutRNiLmKsdR0s+r1+Pn1+PihvtqGqsve6vb09vjt8fXi7PBakL6Vt9fz9vjr8fPR4OuRs9BNiblorua0yd3u8/iWuNhdkb6hu9aLsM9YjrxPibpOiLlNibtZmdForelOiruKr9PI1+WtyeNOiLpPibtRjL5cnNVorObE2/FPir5Xk8xkp95nrufl7PKpwdjN4PJwocxRi75cntVmrOVoruiIq83t8vXT3+yTstBOibxanNJmrOdNiLpUkshjp+Foreh6osfb5O3S3ulQjMBdnthnrOdOibtWlMtiqePk6/G+0OFQjr5gotlsmsJbnNNVlcpUkcVTkcZNirlXlstOiLxentXW5vRRjsBipNzU4e5Si75bmcxkqeNQjcBZmM5ko91nq+ZnrulOi7xVk8hcn9djpuJNibpQjb9jqN5lquVnrOicjUr2AAAAAWJLR0QAiAUdSAAAAWpJREFUeNrtlk1Lw0AQhgtdUCsGhVawfkCq1YuMejJ2G70YQ0+JCBVr0BxCsJSoh4J/39mPxB6kZLPBg+xz2ckGHt6ZLGwaDYPBYDAY/j2U1uNpEkLasZCtYL3Ky7UWYay3NqiiywIhY65NLLeapKBNVV1CxlwdLLcLk7fTjamqi8uEC3Zz097+gY9vbKV5gZBJVw+XwyPc6h+fdHE5VXahjLnOAM5xuYCCSWIr9shkfPbCdRnnKudqQNVdMBQ9umxW1zdyc5pQlR4XucUxeby680WuUWUX5oJOfiJ44PFcIxdAEMqn+z5A+kA1ciGWtIVYvzxWn70geOIyFw/Fs64LIAplsJG+CwIWjDVZg4t9Tw/X1+quiPRc9ugOZY+x5rnPsfR6DBdULJaTVHZF3o+KnVVIByVdb7/M3ueTIp7LP8Q0m5W9g2JYTpq9f3zWInPGydxWuB2XyCbZV+lQBoOh5j9XMwKD4S/4Bpvib4HQl4+eAAAAAElFTkSuQmCC)',opacity:1} }); } var testLegacyFrame =0; $e({ht:'

→ Перетащи картинку сюда ←

(куда-нибудь в это окно)
К сожалению, будет работать только для картинок размером менее 10КБ. Держатели сайта знают, а работа по устранению недостатка через клиент — ведётся.' ,apT:$q('#bittonsHolder') }); if(testLegacyFrame) $e({ht:'