HabrAjax

Cumulative script with over 60 functions for Fx-Opera-Chrome

目前为 2015-05-23 提交的版本,查看 最新版本

  1. (function(win, u){var alienFrame = /(plusone\.google\.com|spmbt\.github\.io)/.test(location.host)
  2. ,metaTx = !alienFrame && function(s){return(s=
  3. //если Firefox+GreaseMonkey, требуется удалить "/*" перед "<!", чтобы читались многострочные данные!
  4. /*<![CDATA[*//*
  5. // ==UserScript==
  6. // @id HabrAjax
  7. // @name HabrAjax
  8. // @version 146.2015.5.24
  9. // @namespace github.com/spmbt
  10. // @author spmbt0
  11. // @description Cumulative script with over 60 functions for Fx-Opera-Chrome
  12. // @include /^https?://(m\.|webcache\.googleusercontent\.com\/search\?q=cache(:|%3A|%3a)(http(:|%3A|%3a)(\/|%2F|%2f)(\/|%2F|%2f))?)?(habrahabr|geektimes|megamozg|tmfeed|h).ru(?!\/special|\/api)/
  13. // @include http://habrahabr.ru/
  14. // @include https://plusone.google.com/*
  15. // @include http://spmbt.github.io/haPages/userscript/habrAjax/*
  16. // @include http://habrastorage.org/
  17. // @include http://legacy.habrastorage.org/
  18. // @update 145 .c2 >.block_after_post;
  19. // @update 144 .block_after_post .live_broadcast .posts_list;
  20. // @update 143 footer width; sidebar width in %%;
  21. // @resource meta habrAjax.meta.js
  22. // @icon data:image/gif;base64,R0lGODlhIAAgAMMBAG6Wyv///2+NtIucstfY2b/FzpSmvY+QkM3Nzunp6fLy8qGwweDg4MbFxa2trrm6uiwAAAAAIAAgAAAE/xDISau9OM/AOe2edoHBBwqiRZodmrKhRLqXYFfrdmLCQBQGWk62swgOiERAQQgChs9iRZBMKDgEFGnbMi4YDMU1gNBytzSJDcGwXhUD4lmqZofFioZrPqMIDARtYksIAzZ8dAINgngJVgkLUH1qBmBuCgmBYA6SUgKBl0wICA6lk1FdAAIFjngKDAgEpKYgWXIcKH8EDQ0EVwmjsrycIA4FZl2rDwcHDgivow8ODwzEHca3ASgDpMylsrEOzdUkDk59AtOl07wIDcwNkDbzCy7z8xIDD8Ps3Q5hCQqscxBHgw0DbEY1WIbEkRtHZV6oMsAq0wNqrcQ4KihR1Z9YjzUeKjjWcYqABUoaJeBY0k8bAm5ItqxgANjFBnBmTgnTQNw0nVOSNBjQLA1QXdEMATVioGnJCAA7
  23. // ==/UserScript==
  24. */s//]]>
  25. )} // © licensed by LGPLv3 Open Source www.gnu.org/licenses/lgpl-3.0.en.html
  26. ,isFxScr = typeof GM_getMetadata !=u //-Scriptish
  27. ,readMeta = function(s, isFxScr){ //парсинг многострочного текста по мета-директивам
  28. if(typeof s !='string') //очистка оболочки функций, выделение мн-стр-комментария
  29. s = typeof s=='function'
  30. ? ((/\*/.test(function(){/**/}+1) ? s : s(!1) )+'')
  31. .replace(/(^[\s\S]*\*\/\/\*\r?\n?|\r?\n?\*\/s[\s\S]*$)/gm,'')
  32. : (typeof s !=u && s!==null && s.toString ? s.toString() :''); //здесь же- 'xml'
  33. var metaD ={}, j =0;
  34. if(s==='false'&& isFxScr){ //получать ли данные средствами Scriptish
  35. metaD = GM_getMetadata();
  36. for(var i in metaD){ //приведение к нормальному виду
  37. if(metaD[i].length ==1)
  38. metaD[i] = metaD[i][0];
  39. j++;
  40. }
  41. }else{
  42. var meta = s.split('\n'), aa, a2;
  43. for(var i=0, mL = meta.length; i < mL; i++){
  44. if(( aa = /^.*?\/\/\s*@([\S]+)\s(\s*)(.*)/g.exec(meta[i]) )){
  45. a2 = aa[3] !==undefined && aa[3] || aa[2];
  46. if(metaD[aa[1]]===undefined)
  47. metaD[aa[1]] = a2;
  48. else{
  49. if(! (metaD[aa[1]] instanceof Array))
  50. metaD[aa[1]] = [metaD[aa[1]]];
  51. metaD[aa[1]].push(a2);
  52. }
  53. j++;
  54. }else if(!/^.*?\/\/\s*[\-=]*\s*\/?\s*UserScript\s*[\-=]*\s*$/i.test(meta[i]))
  55. metaD[j++] = meta[i];
  56. }
  57. }
  58. return j >1 && metaD || undefined; //хеш директив + нум.список простых строк + _length -чис.простых строк или und., если не найдено
  59. },
  60. extMeta = function(m, callback, callErr){ //или (url, callback, callErr)//получение внешних метаданных
  61. if(typeof m =='string')
  62. var shortNum = (/^\d+(\.meta\.js)?$/.test(m) ? m :'') + (/^\d+$/.test(m) ?'meta.js':'')
  63. ,xUrl = shortNum ? URLSCR + HAJAX +'/code'+ shortNum : m ;
  64. //wcl(m, shortNum, xUrl)
  65. if(typeof GM_xmlhttpRequest !=u){
  66. GM_xmlhttpRequest({
  67. url: xUrl
  68. ,method:'get' //Chrome
  69. ,onload: callback //параметр - req (для req.responseText)
  70. ,onerror: callErr //параметр - req (для req.responseText)
  71. });
  72. }else if(win.opera && xUrl){ //load metadata for Opera
  73. var ifr = document.createElement('iframe');
  74. ifr.src = xUrl;
  75. ifr.style.display ='none';
  76. document.body.appendChild(ifr);
  77. ifr.name = ifr.id ='operaEmbedMeta';
  78. win.addEventListener('msg', function(ev){ //слушать приход Event
  79. callback({responseText: ev.data.replace(/\n?\noperaEmbedMeta$/,''), finalUrl: xUrl});
  80. },!1);
  81. }else
  82. wcl('~~No read metadata!'); //другой способ запроса внешнего сервера по ajax
  83. return {waitHandler: 0 //для немедленного таймаута
  84. ,callback: callback, callErr: callErr}; //для немедленного завершения
  85. };
  86. win = (function(){return this})();
  87. var DAY = 86400000
  88. ,CHKUPD = 15 //мин. период проверок обновлений скрипта (минут) при ошибках чтения
  89. ,NOWdate = new Date()
  90. ,NOW = +NOWdate,HSO='http://habrastorage.org',SHRU='https://habrahabr.ru/auth'
  91. ,HRU ='http://habrahabr.ru',sHQ='habr.statis.tk/c?id=@&in=@&zc=@&at=@' //37.230.115.43исп-ть ли сервер статистики
  92. ,HRs ={ha: HRU, geek:'http://geektimes.ru',manag:'http://megamozg.ru',qa:'http://toster.ru',haru:'http://haru'}
  93. ,HClons ={soha:'sohabr',sape:'savepearlharbor',haru:'haru'}
  94. ,ROOT = location.protocol +'//'+ location.host
  95. ,URLSCR ='https://greasyfork.org/scripts/'
  96. ,URLCSS ='http://userstyles.org/styles/33690/'
  97. ,HAJAX ='1970-habrajax/'
  98. ,userNameMaxLen = 25
  99. ,isFx = /Firefox/.test(navigator.userAgent)
  100. ,isChrome = /Chrome\//.test(navigator.userAgent)
  101. ,wcl = function(a){ a = a!==undefined ? a :''; //консоль как метод строки или функция, с отключением по hS.noConsole.val ==1
  102. if(win.console && typeof hS !=u && !hS.noConsole.val)
  103. win.console.log.apply(console, this instanceof String
  104. ? ["'=="+ this +"'"].concat([].slice.call(arguments))
  105. : arguments);
  106. }
  107. , strongCutImgMinH;
  108. String.prototype.wcl = wcl;
  109. String.prototype.trim = function(s){var s = this ||s;
  110. return s.replace(/(^\s+|\s+$)/g,'')};
  111. if(win.opera || typeof GM_xmlhttpRequest ==u)
  112. GM_xmlhttpRequest = function(h){
  113. var xhr = new XMLHttpRequest();
  114. xhr.onreadystatechange = function(){
  115. var responseState ={
  116. responseXML: xhr.readyState==4 ? xhr.responseXML :''
  117. ,responseText: xhr.readyState==4 ? xhr.responseText :''
  118. ,readyState: xhr.readyState
  119. ,responseHeaders: xhr.readyState==4 ? xhr.getAllResponseHeaders() :''
  120. ,status: xhr.readyState==4 ? xhr.status : 0
  121. ,statusText: xhr.readyState==4 ? xhr.statusText :''
  122. };
  123. h.onreadystatechange && h.onreadystatechange(responseState);
  124. if(xhr.readyState==4){
  125. if(h.onload && xhr.status>=200 && xhr.status<300)
  126. h.onload(responseState);
  127. if(h.onerror && (xhr.status<200 || xhr.status>=300))
  128. h.onerror(responseState);
  129. }};
  130. try{//cannot do cross domain
  131. xhr.open(h.method, h.url);
  132. }catch(er){
  133. if(h.onerror) //simulate a real error
  134. h.onerror({responseXML:'',responseText:'',readyState:4,responseHeaders:'',status:403,statusText:'Forbidden'});
  135. return;
  136. }
  137. if(h.headers)
  138. for(var prop in h.headers)
  139. xhr.setRequestHeader(prop, h.headers[prop]);
  140. xhr.send((typeof(h.data) !=u) ? h.data : null);
  141. };
  142. try{ //для оповещения об ошибках в Fx
  143. var metaD = readMeta(metaTx, isFxScr) //metaTx == false ||'false'(строка) - если Fx|| строки метаданных
  144. ,gPlusFrame = alienFrame && /plusone/.test(location.host);
  145. win.adriver = function(){};
  146. win.adriver.domReadyQueue ={execute: function(){},Plugin: function(){this.a =1;}};
  147.  
  148. //===============================================
  149. //'testUScr'.wcl({isFxScr:isFxScr, unsafeWindow: typeof unsafeWindow !=u}); //win !==window при Greasemonkey|Scriptish
  150. if(!alienFrame){
  151. //alert(addEventListener)
  152. win.addEventListener('message', function(ev){ //слушать приход данных
  153. //'start_parse'.wcl(win.JSON , win.JSON.parse, win.JSON.decode)
  154. if(win.JSON && !win.JSON.parse && win.JSON.decode) win.JSON.parse = win.JSON.decode; //habr - old //опера требует этого внутри хендлера
  155. //'decode'.wcl(win.JSON , !win.JSON.parse , win.JSON.decode, win.JSON && !win.JSON.parse);
  156. if(/likes/.test(ev.data) && /frme/.test(ev.data) && win.JSON && win.JSON.parse){ //поставить лайки снаружи
  157. var n = JSON.parse(ev.data);
  158. if(n){
  159. //'parsed_data'.wcl(n);
  160. var frs = document.getElementsByTagName('iframe');
  161. for(var i in frs)
  162. if(frs[i].name == n.frme){
  163. frs[i].setAttribute('likes', n.likes);
  164. var x = frs[i].parentNode.parentNode.querySelector('.likes div div');
  165. x && (x.innerHTML = n.likes);
  166. }
  167. }
  168. }
  169. if(/\noperaEmbedMeta$/.test(ev.data) && win.JSON && win.JSON.parse){
  170. //alert(ev.data)
  171. var evt = document.createEvent('Event'); //генерировать для перехвата на приёме файла
  172. evt.initEvent('msg',!0,!0);
  173. evt.data = ev.data;
  174. win.dispatchEvent(evt);}
  175. },!1);
  176. }
  177. if(gPlusFrame){
  178. /**
  179. * evaluate script in window scope
  180. * @param{Function} fs function or string is body of function
  181. * @param{String|Array} s string or array of strings for arguments
  182. * @param{Boolean} noOnce not delete script after exec
  183. */
  184. var winEval = function(fs, s, noOnce){ //exec function/text in other scope
  185. s = (s ||[]) instanceof Array? s ||[] : [s]; //wrap by array
  186. alert(s +' '+ 'fs2')
  187. var fs2 = typeof fs=='function'
  188. ? (fs +'').replace(/(^\s*function\s*\([^\)]*\)\s*\{\s*|\s*\}\s*$)/g,'') //clean wrapper
  189. : fs
  190. ,as ='';
  191. for(var i =0, sL =s.length; i < sL; i++) //sequential array
  192. as += (i?',':'') +"'"+ s[i].replace(/'/g,"\\'").replace(/(\r\n|\r|\n)/g,"\\\n") +"'";
  193. fs = '(function(){'+ fs2 +'}).apply(window,['+ as +']);';
  194. //'fs'.wcl(fs, fs2)
  195. var d = document
  196. ,scr = d.createElement('script');
  197. scr.setAttribute('type','application/javascript');
  198. scr.textContent = fs;
  199. var dPlace = d.body || d.getElementsByTagName('head') && d.getElementsByTagName('head')[0];
  200. dPlace.appendChild(scr);
  201. if(!noOnce) dPlace.removeChild(scr);
  202. };
  203. /**
  204. * check occurrence of third-party event with growing interval
  205. * @constructor
  206. * @param{Number} t start period of check
  207. * @param{Number} i number of checks
  208. * @param{Number} m multiplier of period increment
  209. * @param{Function} check event condition
  210. * @param{Function} occur event handler
  211. */
  212. var Tout = function(h){
  213. var th = this;
  214. (function(){
  215. if((h.dat = h.check() )) //wait of positive result, then occcurense
  216. h.occur();
  217. else if(h.i-- >0) //next slower step
  218. th.ww = win.setTimeout(arguments.callee, (h.t *= h.m) );
  219. })();
  220. };
  221. new Tout({t:320, i:6, m: 1.6
  222. ,check: function(){
  223. return document && document.querySelector('#aggregateCount');
  224. }
  225. ,occur: function(){
  226. var id = location.hash.match(/(\?|#|&)id=([^&]+)/) //frame id [or name]
  227. ,w = win;
  228. id = id && id.length && id[2];
  229. var s = w.JSON && w.JSON.stringify && w.JSON.stringify( //must supported earlier
  230. {likes: this.dat.innerHTML, frme: id}) //data format
  231. ,pHost = (function(a){ //host extract from parameter (#|&)parent
  232. if(!a.match(/^https?\:\/\//)) return'';
  233. var b = document.createElement('a');
  234. b.href = a;
  235. b.pathname = b.search = b.hash ='';
  236. return b.href.replace(/\/\??\#?$/,'')
  237. })( decodeURIComponent( (w.location.href.match(/.*(\?|#|&)parent=([^&]+)/) ||[])[2] ||'') );
  238. try{
  239. if(!isChrome || w.parent && w.parent.postMessage){
  240. s && w.parent.postMessage(s, pHost); //all browsers except Chrome
  241. }else if(s)
  242. winEval(function(args){
  243. var w = window
  244. ,p1 = arguments[0]
  245. ,p2 = arguments[1];
  246. if(w.postMessage && p1 && w != w.parent){
  247. function wpm(){
  248. w.parent.postMessage(p1, p2); //msg with a glance Chrome bug
  249. }
  250. w.document.all ? w.setTimeout(wpm, 0) : wpm();
  251. }
  252. }, [s, pHost]);
  253. }catch(er){wcl(er)}
  254. }
  255. });
  256. }else if(alienFrame){ // для Оперы (только) в фрейме greasyfork.org - отправка метаданных
  257. document.addEventListener('DOMContentLoaded',function(){
  258. var dd = document.querySelector('pre')
  259. ,s = dd && dd.innerHTML;
  260. if(s && win.parent && win.parent.postMessage)
  261. win.parent.postMessage(s +'\noperaEmbedMeta', ROOT);
  262. },!1);
  263. } //(далее выполняется, если не в alienFrame)
  264. if(alienFrame) return;
  265. var setLocStor = function(name, hh){
  266. if(!localStorage) return;
  267. localStorage['habrAjax_'+ name] = JSON.stringify({h: hh});
  268. },
  269. getLocStor = function(name){
  270. return (JSON.parse(localStorage && localStorage['habrAjax_'+ name] ||'{}')).h;
  271. }
  272. ,removeLocStor = function(name){localStorage.removeItem('habrAjax_'+ name);}
  273. ,lh = location.href
  274. ,$q = function(q, f, f2, args){ // контекстный DOM-селектор или условная функция с ним: (elem)q | ((str)q, f, args) | ((str)q, elem) | ((str)q, (elem)context, f, args)
  275. var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelector(q);
  276. return f instanceof Function ? f && Q ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q
  277. : f2 instanceof Function ? f2 && Q ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q }
  278. ,$qA = function(q, f, f2, args){
  279. var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelectorAll(q);
  280. return f instanceof Function ? f && Q.length ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q
  281. : f2 instanceof Function ? f2 && Q.length ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q }
  282. previButt = $q('#post_form .buttons input[name="preview"]')
  283. wwPrevi =0;
  284. previButt && previButt.addEventListener('click',function(ev){
  285. wcl('previclick');
  286. win.clearTimeout(wwPrevi);
  287. textContentPrev ='00';
  288. fillLetter();$pd(ev);
  289. },!1);
  290. var textContentPrev ='00'
  291. ,fillLetter = function(){ //сформировать письмо в ЛС
  292. var aLHash = lh.replace(/^[^#]*#/,'').split('&')
  293. ,hLHash ={}
  294. ,lStor = getLocStor('composeLetter')
  295. ,lStNoBq = lStor && !/<\/?blockquote>/.test(lStor.cite);
  296. if(/\/(add|edit)\//.test(lh)){ //страница редактирования (своей) статьи - по цитате
  297. var ta = $q('#text_textarea')
  298. ,cite = lStor && lStor.cite
  299. ,text = lStor && lStor.text
  300. ,textContentDiv = $q('#preview_placeholder .content');
  301. if(textContentDiv)
  302. var textContent = textContentDiv.innerHTML; //содержимое статьи
  303. if(ta && typeof cite !=u){
  304. var tVal = ta.value
  305. ,iS =[]
  306. ,cL = cite.length;
  307. for(var i =0, tL = tVal.length; i < tL; i++)
  308. if(tVal.substr(i, cL) == cite)
  309. iS.push(i); //все индексы вхождения строк
  310. 'cite'.wcl(iS, cite)
  311. if(iS.length){
  312. if(iS.length >1) //выделить найденное
  313. hN && hN.addNote(nSufRu(iS.length, ['образ','ец','ца','цов'])+' для правки; <a href=# data-match="'+ JSON.stringify(iS) +'" data-patrn="'+ cite.replace(/"/g,'&quot;') +'">следующий</a>',0,0,function(){
  314. var c1 = $q('a', this.o);
  315. c1.addEventListener('click', function(ev){
  316. var i = !c1.getAttribute('data-curr') ? 1: +c1.getAttribute('data-curr')
  317. ,a = JSON.parse(c1.getAttribute('data-match') )
  318. ,cite = c1.getAttribute('data-patrn');
  319. ta && ta.setSelectionRange && ta.setSelectionRange(a[i], a[i] + cite.length);
  320. c1.setAttribute('data-curr', (++i) % a.length);
  321. ta.blur();
  322. ta.focus();
  323. $pd(ev);
  324. },!1);
  325. });
  326. var i1 = iS[0];
  327. 'citeEnd0'.wcl(nSufRu(iS.length, ['образ','ец','ца','цов']) )
  328. ta && ta.setSelectionRange && ta.setSelectionRange(i1, i1 + cL);
  329. 'citeEnd'.wcl(iS, cite)
  330. }else
  331. hN && hN.addNote('не найдено образцов для правки');
  332. 'citeEnd1'.wcl(iS, cite)
  333. ta.focus();
  334. removeLocStor('composeLetter');
  335. }
  336. if(textContentPrev !='00'&& textContent != textContentPrev){ //обработать подгруженное
  337. 'renderOfAvaxTxt'.wcl(textContentPrev && textContentPrev.length, textContent && textContent.length)
  338. authorClicks(textContentDiv); //особые клики по авторам (напр. в фрейм)
  339. //blockBrs(textContentDiv); //сокращение верт.зазоров
  340. extLinks(textContentDiv); //ext.links и подписи к старым местным линкам
  341. handlImgViews(textContentDiv); //images
  342. byTextNodes(textContentDiv, haReplace); // --> XX
  343. //обработка выделения текста
  344. }else
  345. wwPrevi = win.setTimeout(fillLetter, 1499); //проверка обновлений cite
  346. if(textContentPrev =='00')
  347. textContentPrev = textContent;
  348. return;
  349. }
  350. 'conversations'.wcl(lStor, hLHash, lStNoBq, aLHash.length);
  351. if(aLHash[0] ==lh) aLHash =[];
  352. for(var i =0; i < aLHash.length; i++){
  353. var a = aLHash[i].split('=');
  354. hLHash[a[1]!==undefined && a[0]] = decodeURIComponent(a[1]!==undefined && a[1] || a[0]);
  355. }
  356. var fieldTo = $q('.conversation_page input[name="users-suggest"]')
  357. ,fieldTheme ='<b>Тема</b>: '
  358. ,fieldText = $q('#text_textarea');
  359. 'fieldTo'.wcl(fieldTo, fieldTheme, fieldText);
  360. fieldTo &&(fieldTo.value = hLHash.to && hLHash.to.trim() || lStor && lStor.to ||'');
  361. fieldTheme += hLHash.subj && hLHash.subj.trim()
  362. || (lStor ?(lStor.url ?'<a href="'+lStor.url+'">':'<i>')
  363. + lStor.subj +(lStor.url ?'</a>':'</i>'):'<i></i>')
  364. +(!hLHash.subj && lStor && lStor.date && lStor.subj ?' ('+ lStor.date +')':'');
  365.  
  366. if(fieldText) fieldText.value = (fieldTheme ? fieldTheme +'\n':'')
  367. + (aLHash.length && !(/^comment_\d+$/.test(aLHash[0])) && ( //по URL-параметрам
  368. hLHash.cite && ('<blockquote>'+ hLHash.cite +'</blockquote>') ||' '
  369. )|| (lStor ?( //по хранилищу, если нет URL-параметров
  370. (lStor.commId ?' # <a href='+ lStor.url +'#'+ lStor.commId +'>'+ lStor.commId +'</a> '
  371. +'@'+ lStor.commAuthor +'\n':'')
  372. +(lStNoBq?'<blockquote>':'')+ (lStor.cite ||'')
  373. +(lStor.commDate?' <i><font color=#999>('+lStor.commDate+')</font></i>':'')
  374. +(lStNoBq?'</blockquote>':'')
  375. +(lStor.text ? lStor.text :'')
  376. ):'') );
  377. 'lStor.cite'.wcl(lStor && '|'+lStor.cite+'|'+lStor.commAuthor)
  378. if(lStor && !aLHash.length && !lStor.noReceiver)
  379. removeLocStor('composeLetter');
  380. if(lStor && lStor.noReceiver){
  381. if(lStor && lStor.noReceiver ==2)
  382. delete lStor.noReceiver;
  383. 'lStor'.wcl(lStor)
  384. lStor.noReceiver =2;
  385. setLocStor('composeLetter', lStor);
  386. }
  387. if(fieldTo)
  388. fieldTo.focus(),fieldTo.select(); //выделен адресат для быстрой смены
  389. if(fieldText){
  390. fieldText.focus(); //в поле ввода текста
  391. /*var evt = document.createEvent("KeyEvents");
  392. evt.initKeyEvent('keyup',!0,!0, win,!1,!1,!1,!1, 40,0);
  393. fieldText.dispatchEvent(evt);*/
  394. }
  395. },
  396. nSufRu = function(n, vocab){ //числительные склонения слов ("день" и др.)
  397. var an = Math.abs(n)
  398. ,vocab = typeof vocab =='number'? [['д','ень','ня','ней']][vocab] : vocab;
  399. return n +' '+ vocab[0] + (an % 10 >0 && an % 10 <5 && Math.floor(an % 100 / 10) !=1
  400. ? (an % 10 ==1 ? vocab[1] : vocab[2]) : vocab[3]);
  401. };
  402. //===begin from Dollchan Extension Tools=== --группа функций просмотра изображений--
  403. var doc = win.document
  404. ,$pd = function(ev){ev.preventDefault();}
  405. ,$sp = function(ev){ev.stopPropagation();},$pdsp = function(ev){ev.preventDefault();ev.stopPropagation();}
  406. ,$dispTogl = function(el){el.style.display = el.style.display ==='none'?'':'none'; return el;}
  407. ,$offset = function(el){
  408. var box = el.getBoundingClientRect(), aa;
  409. 'offset'.wcl(aa={
  410. top: Math.round(box.top + win.pageYOffset),
  411. left: Math.round(box.left + win.pageXOffset) })
  412. return aa;
  413. },
  414. addFullImg = function(a, sz, x2, isExp){ //построение изображения по клику на ссылке
  415. x2 = x2 || 1;
  416. var newW =''
  417. ,newH =''
  418. ,fullW = x2* sz[0]
  419. ,fullH = x2* sz[1]
  420. ,scrW = doc.documentElement.clientWidth -10
  421. ,scrH = win.innerHeight -3
  422. ,isA = a.tagName =='A'
  423. ,full = isA ? $q('.de-img-full', a) : a.nextSibling;
  424. if(full && /de-img-full/.test(full.className) && isExp || !full && isExp === false)
  425. return;
  426. if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val && !$q('img[style*="fixed"]', a) )
  427. $dispTogl($q('img', a)); //TODO зкспериментально; отключено
  428. if(full && /de-img-full/.test(full.className)){
  429. if(full.moved)
  430. full.moved = false;
  431. else{
  432. $dispTogl(full);
  433. setTimeout(function(){full.parentNode.removeChild(full);},1);
  434. }
  435. return;
  436. }
  437. if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val)
  438. scrW -= $offset(a).left + 25; //TODO зкспериментально; отключено
  439. else{
  440. var el = $q('.de-img-center', doc);
  441. el && el.parentNode.removeChild(el);
  442. }
  443. if(fullW && fullH){
  444. newW = Math.min(fullW, scrW);
  445. newH = newW * fullH / fullW;
  446. if(hS.viewImgCenter.val && newH > scrH){
  447. newH = scrH;
  448. newW = newH * fullW / fullH;
  449. }
  450. if(newW/fullW < 1.13 && newW / fullW >0.88){
  451. newW = +fullW;
  452. newH = +fullH;
  453. var title = x2 +'00%';
  454. }
  455. }
  456. if(!title)
  457. title = Math.round(newW / fullW *100)* x2 +'%';
  458. var isViewUrl = !hS.addImgs.val && a.getAttribute('data-viewUrl')
  459. ,url = isA ? a.href : isViewUrl || (a.previousSibling && a.previousSibling.firstChild.src)|| a.src;
  460. if(/#\.jpg/.test(url) )
  461. url = a.firstChild.src;
  462. if(isViewUrl)
  463. title ='100%';
  464. var ht ='<img class="de-img-full" src="'+ url +'" alt="'+
  465. url +'" width="'+(isViewUrl ?'': Math.floor(newW))+'" height="'+(isViewUrl ?'': Math.floor(newH)) +'" title="'+ title +'">'
  466. if(a.insertAdjacentHTML)
  467. a.insertAdjacentHTML(isA ?'beforeend':'afterend', ht); //Fx8+
  468. else
  469. $e( $x(isA?{apT: a}:{aft: a}, {ht:ht}) ); //неточно, и ошибки в Fx3.6
  470. if(hS.viewImgCenter.val){
  471. var resizeImg = function(ev){ //обработчик колеса мыши - масштаб картинки
  472. var curX = ev.clientX
  473. ,curY = ev.clientY
  474. ,oldL = parseInt(this.style.left, 10)
  475. ,oldT = parseInt(this.style.top, 10)
  476. ,oldW = parseFloat(this.style.width || this.width)
  477. ,oldH = parseFloat(this.style.height || this.height)
  478. ,d = isFx ? -ev.detail : ev.wheelDelta
  479. ,newW = oldW * (d >0 ? 1.25 : 0.8)
  480. ,newH = oldH * (d >0 ? 1.25 : 0.8)
  481. ,sizes = full.getAttribute('data-sizes').split('x');
  482. if(newW/sizes[0] < 1.13 && newW / sizes[0] >0.88){
  483. newW = +sizes[0];
  484. newH = +sizes[1];
  485. this.title = x2 +'00%';
  486. }else
  487. this.title = Math.round(newW / fullW *100)* x2 +'%';
  488. $pd(ev);
  489. this.style.width = newW +'px';
  490. this.style.height = newH +'px';
  491. this.style.left = parseInt(curX - (newW/oldW) * (curX - oldL), 10) +'px';
  492. this.style.top = parseInt(curY - (newH/oldH) * (curY - oldT), 10) +'px';
  493. };
  494. full = $e({el: isA ? a.lastChild : a.nextSibling
  495. ,clAdd:'de-img-center'
  496. ,cs: {left: (scrW - newW)/2 +'px', top: (scrH - newH)/2 +'px'}
  497. ,at: {'data-sizes': fullW +'x'+ fullH}
  498. ,on: isFx ? {DOMMouseScroll: resizeImg}:{mousewheel: resizeImg}
  499. });
  500. !isA && full.addEventListener('click',function(ev){
  501. $pdsp(ev);
  502. if(full.moved)
  503. full.moved = false;
  504. else{
  505. $dispTogl(full);
  506. win.setTimeout(function(){full.parentNode && full.parentNode.removeChild(full);},1);
  507. }
  508. },!1);
  509. (function(el){ //makeMoveable --перетаскивание
  510. var elMove = function(ev){
  511. el.style.left = ev.clientX - el.curX +'px';
  512. el.style.top = ev.clientY - el.curY +'px';
  513. el.moved = true;
  514. },
  515. elStop = function(ev){
  516. var t = ev.target;
  517. $e({el: doc.body
  518. ,revent:{mousemove: elMove, mouseup: elStop}});
  519. if(ev.ctrlKey && t.parentNode.tagName=='A')
  520. t.parentNode.click(); //нативный клик вынесен под Ctrl+
  521. if((Math.abs(ev.clientX - el.startX) + Math.abs(ev.clientY - el.startY) ||0) <5 && ev.which ==1){
  522. $dispTogl(t);
  523. win.setTimeout(function(){t.parentNode.removeChild(t);},1);
  524. }
  525. };
  526. el.onmousedown = function(ev){
  527. $pd(ev);
  528. el.curX = (el.startX = ev.clientX) - parseInt(el.style.left, 10);
  529. el.curY = (el.startY = ev.clientY) - parseInt(el.style.top, 10);
  530. $e({el: doc.body
  531. ,on:{mousemove: elMove, mouseup: elStop}});
  532. };
  533. })(full);
  534. }
  535. },
  536. handlImgViews = function(el, selector){ //обработчики просмотров картинок
  537. 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"]'
  538. ,els = $qA(selector, el); //все ссылки на картинки
  539. //'handlImgViews'.wcl(el, selector, els )
  540. for(var i =0, linkImg; linkImg = els[i++];){ //подгрузка картинок в рамках до 200 на 200 по расширениям файлов в ссылках
  541. var a = linkImg.cloneNode(false)
  542. ,imgsInLink = $qA('img', linkImg);
  543. if(imgsInLink && imgsInLink.length !=1 && hS.addImgs.val){ //подгружать картинки-ссылки
  544. var lastLink = linkImg;
  545. $e({el:'img' //малая картинка со ссылкой перед найденной ссылкой
  546. ,cl:'de-img-pre'
  547. ,at:{src: a.href, alt: a.href.substr(0,200)}
  548. ,on:{load: function(){
  549. var t = this
  550. ,fullW = t.width
  551. ,fullH = t.height
  552. ,x2 = hS.viewX2.val && fullW *2 < win.innerHeight -3 ? 2:1; //признак "x2" - удваивать масштаб
  553. t.title = (x2 ==2 ?'/':'')+ fullW +'x'+ fullH;
  554. //'on:{load'.wcl(t.title, lastLink)
  555. if(lastLink.firstChild && lastLink.firstChild.tagName =='BUTTON'){var evt = document.createEvent('Event');evt.initEvent('loadImg',!0,!0); evt.data = t.title; win.dispatchEvent(evt);}
  556. t.style.cursor = x2 ?'ne-resize':'move';
  557. if(/^imgL$/.test(t.parentNode.className)|| t.parentNode.className =='lnk'){ //включить видимость копий, выключить - оригиналы ссылок
  558. t.parentNode.style.display ='inline-block';
  559. t.parentNode.nextSibling.style.display ='none';
  560. t.parentNode.title = t.title;
  561. if(t.parentNode.className =='lnk')
  562. t.parentNode.className ='lnk imgL';
  563. }else
  564. $dispTogl(t.parentNode);
  565. if(fullW <= 200 && fullH <= 200)
  566. return;
  567. var k = fullW/fullH;
  568. t.width = k < 1 ? 200 * k : 200;
  569. t.height = k < 1 ? 200 : 200/k;
  570. }},
  571. apT: $e({el: function(){
  572. var pImg = linkImg.previousSibling;
  573. if(pImg && pImg.className=='aPrevi imgL')
  574. pImg.parentNode.removeChild(pImg);
  575. pImg = linkImg.previousSibling;
  576. if(pImg && pImg.className=='aPrevi imgL')
  577. pImg.parentNode.removeChild(pImg);
  578. return $dispTogl(a);
  579. }
  580. ,at:{target:'_blank'}
  581. ,on:{click: function(ev){ //eventLinkImg(a);
  582. //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1)
  583. if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){
  584. if(ev.ctrlKey)
  585. return;
  586. $pd(ev);
  587. if(showImgMenu(ev, ev.currentTarget.frstChild) ) //по Shift+клик
  588. return;
  589. var titl = this.firstChild.title
  590. ,imgWH = titl.match(/(\d+)x(\d+)$/)
  591. ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2"
  592. if(imgWH && imgWH.length ==3)
  593. addFullImg(this, imgWH.slice(1), x2);
  594. }
  595. }}
  596. ,bef: linkImg
  597. })
  598. });
  599. }else //подготовка тамбнейла для просмотра по клику на нём ссылки
  600. imgsInLink && imgsInLink.length ==1 && $e({el: imgsInLink[0]
  601. ,clAdd:'de-img-thumb'
  602. ,at:{'data-viewUrl': linkImg.href} });
  603. }
  604. if(!(hS.viewImgs && hS.viewImgs.val) && !hS.viewImgCenter.val) //не просматривать картинки в странице
  605. return;
  606. for(var img, i =0, imgs = $qA('.content img:not(._noAddOwnView),.message img:not(._noAddOwnView),.message .text img:not(._noAddOwnView)', el); img = imgs[i++];){
  607. //'12'.wcl(img,img.width , img.height)
  608. if( (img.width >22 || img.height >22 || img.width==0 || img.height==0) && (!img.previousSibling || img.previousSibling && img.previousSibling.className !='de-img-hid') )
  609. (function(img){$e({el:'img' //полная картинка в невидимом диве с overflow
  610. ,cl:'_noAddOwnView'
  611. ,at:{src: hS.addImgs.val && img.getAttribute('data-viewUrl') || img.src}
  612. ,cs:{position:'absolute', left:'-9999px'}
  613. ,on:{load: function(ev){
  614. var fullW = this.width
  615. ,fullH = this.height;
  616. this.title = fullW +'x'+ fullH;
  617. $dispTogl(this.parentNode);
  618. //'WHBig'.wcl(fullW, img.width, fullH, img.height, img);
  619. if(fullW == img.width && fullH == img.height){
  620. img.style.cursor ='ne-resize';
  621. if(hS.viewX2.val)
  622. this.title = '/'+ this.title; //признак "x2" (особый курсор)
  623. }else if(!hS.viewX2.val){
  624. img.style.cursor ='move';
  625. img.setAttribute('data-view',1);
  626. }
  627. }},
  628. apT: img.previousSibling && img.previousSibling.className =='de-img-hid' && img.previousSibling || $e({cl:'de-img-hid'
  629. ,cs:{overflow:'hidden', width:0, height:'8px'}
  630. ,bef: img
  631. })
  632. }) })($e({el: img //обработчик и смена курсора картинки
  633. ,cs: hS.viewX2.val ?{cursor:'move'}:{}
  634. ,on:{click: function(ev){ //eventLinkImg(a);
  635. //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1)
  636. var t = ev.currentTarget;
  637. if(!hS.viewX2.val && !t.getAttribute('data-view') )
  638. return; //не просматривать, если размер не изменится
  639. if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){
  640. if(ev.ctrlKey)
  641. return;
  642. $pd(ev);
  643. if(showImgMenu(ev, t)) //по Shift+клик
  644. return;
  645. var titl = this.previousSibling.firstChild.title
  646. ,imgWH = titl.match(/(\d+)x(\d+)$/)
  647. ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2"
  648. if(imgWH && imgWH.length ==3)
  649. addFullImg(this, imgWH.slice(1), x2);
  650. }
  651. }}
  652. }));
  653. }
  654. },
  655. showImgMenu = function(ev, img){ //контекстное меню на картинке - поиск по изображению
  656. if(!ev.shiftKey) return;
  657. else{
  658. var srcD ={TinEye:{url:'tineye.com/search/?url='}
  659. ,Google:{url:'google.com/searchbyimage?image_url='}
  660. ,Yandex: {url:'images.yandex.ru/yandsearch?text=&rpt=imagedups&img_url='}
  661. ,SauceNAO:{url:'saucenao.com/search.php?url='}
  662. ,IQDB:{url:'iqdb.org/?url='} }
  663. ,srcMenu = $e({cl:'de-menu'
  664. ,on:{mouseout: function(){
  665. $dispTogl(srcMenu);
  666. win.setTimeout(function(){srcMenu.parentNode.removeChild(srcMenu);},1); }}
  667. ,cs:{left: ev.pageX -30 +'px', top: ev.pageY -24 +'px'}
  668. ,apT: doc.body
  669. });
  670. for(var i in srcD)
  671. $e({el:'A'
  672. ,cl:'de-src'
  673. ,at:{target:'_blank', href:'http://'+ srcD[i].url + img.src}
  674. ,ht:'<img src="http://'+ srcD[i].url.replace(/\/.*/,'') +'/favicon.ico"> '+ i
  675. ,on:{mouseout: function(ev){ $sp(ev);}}
  676. ,apT: srcMenu
  677. });
  678. }
  679. return 1;
  680. };//===end from Dollchan
  681. var allASCII = function(s){ //все символы строки - ASCII
  682. for(var i =0; i < s.length; i++)
  683. if(s.charCodeAt(i) >127)
  684. return !1;
  685. return!0;
  686. },
  687. $x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el;}, //===extend===
  688. $e = function(g){ //===создать или использовать имеющийся элемент===
  689. //g={el|clone,blck,elA,cl|(clAdd,clRemove),ht,cs,at,atRemove,on,revent,ap,apT,prT,bef,aft,f+fA}
  690. if(typeof g.el =='function') g.el = g.el.apply(g, g.elA);
  691. if(!g.el && g.el !==undefined && g.el !='') return g.el; //null|0|false
  692. 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';
  693. o = g.el = typeof o =='string'? /\W/.test(o) ? $q(o, g.blck) : document.createElement(o) : o;
  694. if(o){ //выполнять, если существует el или clone
  695. if(g.cl)
  696. o.className = g.cl;
  697. else{
  698. if(g.clAdd)
  699. o.classList.add(g.clAdd);
  700. if(g.clRemove)
  701. o.classList.remove(g.clRemove);}
  702. if(g.cs)
  703. $x(o.style, g.cs);
  704. if(g.ht || g.at){
  705. var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;}
  706. if(at)
  707. for(var i in at){
  708. if(i=='innerHTML') o[i] = at[i];
  709. else o.setAttribute(i, at[i]);}
  710. if(g.atRemove)
  711. for(var i in g.atRemove)
  712. o.removeAttribute(g.atRemove[i]);
  713. if(g.htT){ //подготовка шаблона
  714. if(!(typeof g.htTA =='object')) g.htTA =[g.htTA];
  715. for(var i in g.htTA)
  716. g.htT = g.htT.replace(RegExp('\\{\\{'+ i +'\\}\\}','g'), g.htTA[i])
  717. o.innerHTML = g.htT;}
  718. if(g.on)
  719. for(var i in g.on) if(g.on[i])
  720. o.addEventListener(i, g.on[i],!1);
  721. if(g.revent)
  722. for(var i in g.revent) if(g.revent[i])
  723. o.removeEventListener(i, g.revent[i],!1);
  724. if(g.ap){ //добавление нод
  725. if(g.ap instanceof Array){
  726. for(var i in g.ap) if(g.ap[i] && i !='length')
  727. o.appendChild(g.ap[i]);
  728. }else o.appendChild(g.ap);}
  729. g.apT && g.apT.appendChild(o);
  730. g.prT && (g.prT.firstChild
  731. ? g.prT.insertBefore(o, g.prT.firstChild)
  732. : g.prT.appendChild(o) );
  733. g.bef && g.bef.parentNode.insertBefore(o, g.bef);
  734. g.aft && (g.aft.nextSibling
  735. ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling)
  736. : g.aft.parentNode.appendChild(o) );
  737. g.remove && g.remove.parentNode.removeChild(g.remove);
  738. if(typeof g.f =='function')
  739. g.f.apply(g, g.fA); //this - это g
  740. }
  741. return o;
  742. /*
  743. var x=
  744. {cl: function(){o.className = g.cl;}
  745. ,clAdd: function(){o.classList.add(g.clAdd);}
  746. ,clRemove: function(){o.classList.remove(g.clRemove);}
  747. ,cs: function(){$x(o.style, g.cs);}
  748. ,ht: function(){var at = g.at ||{}; at.innerHTML = g.ht;}
  749. ,at: function(){var at = g.at ||{};
  750. for(var i in at){
  751. if(i=='innerHTML') o[i] = at[i];
  752. else o.setAttribute(i, at[i]);}}
  753. ,ap:function(){if(g.ap instanceof Array){
  754. for(var i in g.ap) if(g.ap[i] && i !='length')
  755. o.appendChild(g.ap[i]);
  756. }else o.appendChild(g.ap);}
  757. ,on:function(){for(var i in g.on) if(g.on[i])
  758. o.addEventListener(i, g.on[i],!1);}
  759. ,revent:function(){for(var i in g.revent) if(g.revent[i])
  760. o.removeEventListener(i, g.revent[i],!1);}
  761. ,apT:function(){g.apT.appendChild(o)}
  762. ,prT:function(){g.prT.firstChild
  763. ? g.prT.insertBefore(o, g.prT.firstChild)
  764. : g.prT.appendChild(o)}
  765. ,bef:function(){g.bef.parentNode.insertBefore(o, g.bef)}
  766. ,aft:function(){g.aft.nextSibling
  767. ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling)
  768. : g.aft.parentNode.appendChild(o)}
  769. };
  770. for(var i in g) //проход по числу параметров, проп-о объёму задачи
  771. g[i] && x[i] && x[i]();*/
  772.  
  773. },
  774. addRules = function(css){
  775. if(typeof GM_addStyle !=u) GM_addStyle(css); //Fx,Chr
  776. else if(typeof addStyle !=u) addStyle(css);
  777. else{ //Op
  778. var heads = document.getElementsByTagName('head')
  779. ,node = $e({el:'style'
  780. ,apT: heads.length && heads[0]
  781. });
  782. node.appendChild(document.createTextNode(css)); //не проходит в Опере через $e
  783. }
  784. },
  785. getPosition = function(o){
  786. var x =0, y =0;
  787. while(o){
  788. x += o.offsetLeft ||0;
  789. y += o.offsetTop ||0;
  790. o = o.offsetParent || o.parentNode;
  791. }
  792. return {x:x, y:y};
  793. },
  794. parents = function(cl, elem){
  795. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.parentNode);
  796. return el;
  797. },
  798. parentsPrev = function(cl, elem){
  799. for(var el = elem, pr; el!=null && !RegExp(cl).test(el.className); el = el.parentNode)
  800. pr = el;
  801. el.prev = pr;
  802. return el;
  803. },
  804. prev = function(cl, elem){
  805. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.previousSibling);
  806. return el;
  807. },
  808. next = function(cl, elem){
  809. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.nextSibling); //el.className != cl
  810. return el;
  811. },
  812. evtChangeDom = function(voteA){ //===== сообщение о смене DOM, 'chgDom' ====
  813. var evt = document.createEvent("CustomEvent");
  814. if(evt && evt.initCustomEvent){ //TODO поддержку простых Event через хранилище или GM_setValue
  815. evt.initCustomEvent('chgDom',!0,!0, voteA);
  816. win.dispatchEvent(evt);
  817. return!0;
  818. }};
  819. if(/habrastorage\.org/.test(lh)){
  820. var hsoLogo = $q('.wrapper .header .logo'), hsoCloud = $q('.content #upload_cloud img');
  821. if(hsoLogo && hsoCloud){
  822. 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+GnbQleIUB72xAuWja6ZAsUIv6gxHXrMC5Zdq5h1U6NWc4MgVK1C+u8YaYp0kD8cJmMYMWPspFMeiMWRzMRwGx8PDcCzdpDsByGZOQCIEB+XDoDF5dABOZEozDNiKiWeKLQ7PhUSDeV4+t8Epq6HRYJ4XiIkjxEPRzR3PHhPnvZVvwqHB411n4GTNmSG47EfgeShTcTLmkiIZIo3Bs0/DQWY2TsfCpDFWQCIFxwzVoBMqzUK4ZnAUaSKc7jBknk9EnLwz4eSaqYyMEJIvjxq7B554ygQcnXOQ/+qNSzRnmfO+e/n8ipZw0JYZKhBN7gdaNrnh2kXFmyUc3gwVZFT1U4hi6xsueQ7QAg66go6qagtRLVN3Ga7UAs7EOYBRtY6YduzNPdyMciAJsIFsrOmOJzWHI2LnFBLeaRDadYVTn8NZgznnHAGs6ornaAZH4UDOqUJokJz7Vq3mnKah4xmcbZBz+i3kwL6nnLmpdYuD8HlbO+GDcOat5UTX17c4NZxzbJ1TR84tk3MmZm46edrnnBRyY/CBlrFwZAkyW/WROwMHbN3C4UFCPneJA07UdQtnBBLykVsc+S2QR5ngxCGT5wZybUfwicLAKeNY2S4Cq+5xoHn62MTJgmJ17gEHZRoQoj7COHlArP68lpE3kxt1gHg4Uzo24+oghfywVN1WPNxYMHMgM052nslKJREE9IgdhKaBI9rkwAPbEY7Fp8J4dOZEnzNwImzp5FoQGjCPUGcmE278himdnAyjAfPI31ha5sYVnHWoiRtMA+f5h46zw+GBRVVy/xJOA48XXT8NTmYpGaRiDS/eJAc8Uao0zjmFoeSm3QefmjR4ltmqOeD5QOPZ5XT6QrBvJ5ynExqEcZADHuExhafKifSBZbc25i2aCQ56Auf5EiMvPXMcTx1Yds6Z+maKY/knCplSCzFyyuWy1IF1DvTNLc7EP5IOGOwj8nf2GTgZ9kea48mkucWZ+CcOcE+Z/KV9LkJb7LxFtjhTR9zimP5RIeqJa22SYDEOOe3YjfJa/EEZLeKgmqSdgMa6ppIGEHdCy4IO1jgzOIYuYFP7lpYk4WRpOBmXODATjDVogihlCk4rUBx52xAJAYen4aBAcdCJpKUJeUdcEU5W0lRCVtZXhIOvXAlzlrIinE0Szi6HaHknWCk//0DCOcerQfIkcRQojpIn4aTwWpmM0wgUR6+QcI648YiywDgOFIffMpZ9S995yY1PKDj9QHH28I6hS9hnRWmrwR/gzzYm94pD6ZzFjTl0Eecb3qNzlKU7PFpPpV7UGU4tX9IG/5H26OMrCs7GJQrKhEictCbGJxjjN7R9VjMwHHFE3N2Z5zun1F1oJiAama/g7dTSbsI8jFNoW4nig4Bw+DND/Okl5zyenJxe0TZaxc1AaDJYOWpnyTn71rkydVdcrAWh41N8e0ZYmpYnOCL9zOAi6j/N2WsJD6sl55SsU3dUop8NvtL9psm+Ni86lx3w7/TG5h7j+OuC95VGGZn1U6RdhD7FEQeMs8riyE8Vj0oa+aS227u77YuzTnKLf4h+BYrPl8xybNK3vbi7C40wz7mL6ns/FPRc3zZLGdrk71JmborZtwBFVatkBW+JWM/eq8QZlWXPZu/R8+xz9yKuJqxs8mU3NxNymd+sxK96ky4UWg3gx1mcqM2tRFHVfDCVURs+XxJSsbkLLU7bm1zbIMnqQvl5Hke0vSkuJmJt9z7CAma156CFcqJK4BVxrP/uL4vVTWIyMVydoaVStMOwCwZnbG+5Mq5cWJl7HpPqBrdjq3LPDglHeLYi9xySa075FalHphQI/x56vSm2z7R6ZeHvFbjnJb2a+8kK1Cwzat2/hB4ukVV6L/8Usnv22X0SysNQeb7adZHshBmunmzbY/NXiO5RAA1Rj0Lj2YH0Z6FPIfF8hHWvofuh8HyG9vaFwrMH73xE97ur8A21LxQ1u6HrhtnEe10Md0zZ9RTfXISYbwAd15mDgGAeuOm4NpY/1UBoXrjt1kfr/sNIHz28ZXBUDy9QkJce5KavNO88P8vho4O+2r5cAnglBDX6gaY+x2+otPyI2BcfX5hRdj3C7MPe4AG/v6M0XwUO4+h1IvnaXZruvYM/l+To7Sa047wb7FAP8mWrlpNGHu3rZ4evf7l490u+aUKi1jvknb9E5vKRNiXVzDFR9gRXn+vhzTik3Fw3q/UZT20c5KqHv+1lVvKE3V30Wsp35fulLHv/qP8BqHPfIquWK4UAAAAASUVORK5CYII=';
  823.  
  824. $e({el:hsoLogo
  825. ,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}
  826. });
  827. }
  828. var testLegacyFrame =0;
  829. $e({ht:'<h2>&rarr; Перетащи картинку сюда &larr;</h2>(куда-нибудь в это окно)<br>К сожалению, будет работать только для картинок размером менее 10КБ. Держатели сайта знают, а работа по устранению недостатка через клиент &mdash; ведётся.'
  830. ,apT:$q('#bittonsHolder') });
  831. if(testLegacyFrame) $e({ht:'<iframe src='+ HSO.replace(/\/\/ha/,'//legacy.ha') +'>&rarr; Перетащи картинку сюда &#8592;</h2>(куда-нибудь в это окно)'
  832. ,apT:$q('#bittonsHolder') });
  833. addRules('.logo{margin-bottom:0; margin-top: -90px}');
  834. var doDrop //для Chrome
  835. ,getKeyUser = function(){ alert(win.userKey +' '+ win.user); }
  836. ,listenDrag = function(win){ $e({el: win, on:{
  837. dragover: function(ev){hS.noConsole.val =0;'dragover'.wcl();doc.body.style.backgroundColor ='#e8e8f2'; $pdsp(ev);}
  838. ,mouseout: function(ev){doc.body.style.backgroundColor ='#fff';}
  839. ,dragend: function(){'dragend'.wcl();'dragend'.wcl(); return!1;}
  840. ,drop: doDrop = function(ev){'drop'.wcl('window.user');
  841. if(0&& isChrome){
  842. if(window.win != window){
  843. //winEval(getKeyUser);
  844. return;
  845. }
  846. win = window;
  847. }else
  848. $pdsp(ev);
  849. doc.body.style.backgroundColor ='#fff';
  850. if(isChrome) win = (function(){return this})();
  851. 'drop2'.wcl(win.user, win.userKey,win, win.unsafeWindow && unsafeWindow)
  852. if(win.user && win.user.length >0){
  853. var xhr = new XMLHttpRequest()
  854. ,file = ev.dataTransfer.files[0]
  855. ,uploadsCount =0
  856. ,formData = new FormData()
  857. ,reader = new FileReader();
  858. reader.readAsDataURL(file);
  859. reader.onload = function(ev){
  860. 'fileDrop-target'.wcl(ev.target, ev.target.result);
  861. };
  862. 'file'.wcl(file)
  863. xhr.open('POST', (!/legacy\.habrastorage\.org/.test(lh) ? HSO : HSO.replace(/\/\/ha/,'//legacy.ha') ) +'/uploadController/?username=' + win.user + '&userkey=' + win.userKey,!0);
  864. //formData.append('username', win.user);
  865. //formData.append('userkey', win.userKey);
  866. formData.append('Filedata', file);
  867. xhr.setRequestHeader('Origin', HSO);
  868. xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
  869. //xhr.setRequestHeader('Accept-Encoding', 'nogzip, deflate');
  870. xhr.send(formData);
  871. xhr.onreadystatechange = function(){
  872. if(xhr.readyState == 4 && xhr.status == 200){
  873. var mbJson = /\{/.test(xhr.responseText)
  874. ,answer = mbJson && JSON.parse(xhr.responseText)||{}
  875. ,upF = $q('#uploadedFiles'), upFI;
  876. $e({el: upFI = $q('#uploadedFilesItems')
  877. ,ht: upFI.innerHTML +(mbJson ?'<div class="uploaded-item">'
  878. +'<div class="uploaded-thumbnail"><label for="file-name-0"><img src="'
  879. + answer.crop +'" height="96" width="96" title="'+ answer.filename +', '
  880. + file.size +' байт"></label></div>'
  881. +'<div class="uploaded-url"><input size=37 onclick=this.select() value="'
  882. +'&lt;img src=&quot;'+ answer.url +'&quot;/&gt;" id="file-name-0" title="'
  883. + file.mozFullPath +'"><input size=35 onclick=this.select() value="'
  884. + answer.url +'" id="file-name-1" title="'+ file.lastModifiedDate +'"></div></div>': xhr.responseText)
  885. });
  886. upF.style.display ='block';
  887. $e({el:'#divStatus', ht:'Загружено: '+ ++uploadsCount, cs:{display:'block'} });
  888. 'message_0from_storage'.wcl(ev.data, win.parent,'<img src="'+ answer.url +'"/>');
  889. if(isChrome){ win = (function(){return this})();
  890. win.parent.postMessage('<img src="'+ answer.url +'"/>', ROOT);
  891. }else{
  892. wcl(answer.url)
  893. try{
  894. win.parent && win.parent.habraWYG && win.parent.habraWYG.insertTag(/*h.taSaved.el*/ $q('textarea'), '<img src="'+ answer.url +'"/>');
  895. }catch(er){'er'.wcl(er)}
  896. }
  897. }};
  898. }
  899. return!1;
  900. }} }) };
  901. if(0&& isChrome){
  902. //winEval(evtChangeDom,'window');
  903. ;//addEventListener('getWinJs', listenDrag,!1);
  904. }else
  905. listenDrag(win);
  906. }else
  907. win.addEventListener('message', function(ev){ //слушать сторадж для вставки тега в поле ввода
  908. //'message'.wcl(ev.origin);
  909. if(ev.origin !=HSO) return;
  910. 'message_from_storage'.wcl(ev.data);
  911. win.habraWYG.insertTag(/*h.taSaved.el*/ $q('textarea'), ev.data);
  912. },!1);
  913.  
  914. var h = {}
  915. ,hNE, hNCloseButt, hNCiteList,
  916. hN ={ //noteBar
  917. elem: hNE = $e({cl:'noteBar' //сервис замечаний и выделения текста
  918. ,cs: window.innerWidth <600 ?{left:'50px', maxWidth:'85%'}:''
  919. ,ap:[$e({cl:'closeButt'
  920. ,ht:'X'
  921. ,on:{click: function(ev){
  922. parents('^noteBar$', this).style.display ='none';
  923. var notes = $qA('.noteBar .notes .note');
  924. for(var i in notes)
  925. notes[i].parentNode && notes[i].parentNode.removeChild(notes[i]);
  926. }}
  927. })
  928. ,$e({cl:'delim'})
  929. ,hNCiteList = $e({cl:'list'})]
  930. ,apT: document.body})
  931. ,addNote: function(s, type, id, callb){ //==== добавить напоминание в бар ====
  932. var once = !type || type !='*'? 1:0; //noonce if type=='*'
  933. if(win.opera)
  934. $e({el: hNE, apT: document.body}); //т.к. при раннем старте не подгружается в .body
  935. var notes = $e({
  936. el: $q('.notes', hNE) ||''
  937. ,cl:'notes'
  938. ,bef: $q('.delim', hNE)
  939. });
  940. //'.notes'.wcl($q('.notes', hNE))
  941. $e({
  942. el: $q('#'+ (id ||'id0'), notes) ||''
  943. ,at:{id: id ||'id0'}
  944. ,ht:'<span style="color:#a76">('+(once ?'!':'*')+')</span> '+ s
  945. ,cl:'note' +(once?' once':'')
  946. ,apT: notes
  947. ,f: callb
  948. });
  949. hNE.style.display ='block';
  950. },
  951. retainView: function(){ //скрыть нотификатор, если внутри - только блоки однократного показа, + скрыть блоки однократного показа
  952. var t = this
  953. ,notes = $qA('.note', t.elem)
  954. ,noonce;
  955. //wcl(t.elem, notes.length, noonce)
  956. for(var i in notes){
  957. if(!/ once/.test(notes[i].className) && notes.length )
  958. noonce =1;
  959. else
  960. win.setTimeout(function(){notes[i].parentNode && notes[i].parentNode.removeChild(notes[i]);}, 99);
  961. //notes[i].style.display ='none';
  962. }
  963. //'noonce'.wcl(noonce)
  964. var selField = $q('.sele .selText', t.elem);
  965. selField && selField.parentNode.removeChild(selField);
  966. if(noonce) return;
  967. t.elem.style.display ='none';
  968. }
  969. },
  970. hideC2 = function(ev){ //скрыть содержание
  971. var topic = parents('^post($| )', this) || parents('^rotated_posts', this) //на контейнер статьи
  972. ,cont = $q('.content',topic)
  973. ,inln = / inln/.test(cont.className)
  974. ,c2 = $q('.content.c2',topic);
  975. if(/ n2/.test(this.className)) //подкрутка окна
  976. (isChrome?document.body:document.documentElement)['scrollTop'] -= c2.offsetHeight - this.getAttribute('rel') +12; //qa +3
  977. cont.style.display = inln?'inline':'block'; //показать начало статьи (до ката)
  978. if(inln)
  979. cont.className = cont.className.replace(/ content/,'')
  980. $q('.btnBack:not(.showComm)',topic).style.display //скрытие верхнего "Свернуть"
  981. = $q('.btnBack.n2',topic).style.display //скрытие нижнего "Свернуть"
  982. = c2.style.display ='none'; //скрыть полную статью
  983. if(isChrome){
  984. var info = $q('.infopanel', topic);
  985. info.style.top =(h.inZen?'-':'')+'3px';
  986. }
  987. },
  988. hideComm = function(ev){
  989. var topic = parents('^post($| )', this)
  990. ,c2 = $q('.comments.c2', topic);
  991. if(/ n2/.test(this.className)) //подкрутка окна
  992. (isChrome?document.body:document.documentElement)['scrollTop'] -= c2.offsetHeight - this.getAttribute('rel') +8; //QA -2, ес. не перед EV
  993. $q('.showComm.btnBack:not(.inln)', topic).style.display
  994. = $q('.comments.c2', topic).style.display
  995. = $q('.showComm.btnBack.n2', topic).style.display ='none';
  996. },
  997. addTaButtons = function(comms){ //добавление тегов в поле ввода
  998. var panels = $qA('.panel', comms.parentNode)
  999. ,topicAdd = $q('.topic_add') || $q('.qa_add');
  1000. //'addTaButtons/comms,panels=='.wcl(comms, panels)
  1001. if(panels && panels.length){
  1002. var win = (typeof unsafeWindow !=u)? unsafeWindow: (function(){return this})();
  1003. //в Хроме window не видно, => прих-ся переписывать или вызывать через DOM
  1004. if(!win.habraWYG) win.habraWYG ={};
  1005. win.habraWYG.insertTag = function(link, startTag, endTag){
  1006. var ta = $q('textarea', parents('editor', link));
  1007. endTag = endTag ||'';
  1008. if(ta){
  1009. ta.focus();
  1010. var scrtop = ta.scrollTop
  1011. ,cPos = ta.setSelectionRange
  1012. ?{start: ta.selectionStart, end: ta.selectionEnd}
  1013. :{start:0, end:0}
  1014. ,sTag = ta.value.substring(0, cPos.start)
  1015. + startTag + ta.value.substring(cPos.start, cPos.end) + endTag
  1016. ,newCPos = cPos.start == cPos.end
  1017. ? cPos.start + startTag.length
  1018. : sTag.length;
  1019. ta.value = sTag + ta.value.substring(cPos.end);
  1020. if(ta.selectionStart)
  1021. ta.setSelectionRange(newCPos, newCPos);
  1022. if(scrtop)
  1023. ta.scrollTop = scrtop;
  1024. }
  1025. return!1;
  1026. };
  1027. for(var i in panels){ if(panels[i] && panels[i].appendChild){
  1028. var panel = panels[i]
  1029. ,addBtn = function(tag, tag2, title, view, color, before){
  1030. return $e({cl:'spanned font', ht:'<b><a tabindex="-1" href="#" onclick="return habraWYG.insertTag(this, \''+tag+'\',\''+tag2+'\');" title="'+title+'"><font style="color:#'+(color||'79b')+';padding-left: 6px; top: 2px; position: relative">'+view+'</font></a></b>', apT: before?'':panel, prT: before?panel:''});
  1031. };
  1032. addBtn('<blockquote>','</blockquote>','Цитата','Q&nbsp;').className ='spanned quot'; //цитата
  1033. var btnFo = addBtn('<font color=&quot;#223377&quot;>','</font>','Font color','F','a86'); //цветной текст
  1034. var pTmp;
  1035. for(var j in {blockquote:1, insertUser:2, insertSpoiler:3})
  1036. if(pTmp = $q('a[onclick*="'+ j +'"]', panel) )
  1037. pTmp.parentNode.removeChild(pTmp);
  1038. if(pTmp = $q('a[onclick*="insertHabracut"]', panel) )
  1039. pTmp.setAttribute('onclick','return habraWYG.insertTag(this,\'<habracut text=\"\',\'\">\')');
  1040. addBtn('<hh user=&quot;','&quot;/>','User','<img width=12 height=12 src=/i/bg-user2.gif alt=U style="padding:0"/>').className ='spanned user'; //юзер
  1041. addBtn('<spoiler title=&quot;&quot;>','</spoiler>','Спойлер','SP&nbsp;');
  1042. if(topicAdd)
  1043. addBtn('<h3>','</h3>','Заголовок','H3&nbsp;',null,1);
  1044. if(pTmp = $q('a[onclick*="insertLink"]', panel) ) //ссылка; упрощение "a href"
  1045. pTmp.setAttribute('onclick',"return habraWYG.insertTag(this, '<a href=\"\">','</a>');");
  1046. //'pTmp insertImage'.wcl($q('a[onclick*="insertImage"]'), panel) //картинка
  1047. if(pTmp = $q('a[onclick*="insertImage"]'), panel){ //упрощение IMG
  1048. pTmp.setAttribute('onclick',"return habraWYG.insertTag(this, (event.ctrlKey || event.shiftKey ?'<nobr>':'') +'<img src=\"',(event.ctrlKey && event.shiftKey?'\" align=\"center': (event.ctrlKey?'\" align=\"right':'') +(event.shiftKey?'\" align=\"left':'') ) +'\"/>'+ (event.ctrlKey || event.shiftKey ?'</nobr>':'') );");
  1049. pTmp.title ='IMG (Shift: left; Ctrl: right; Shift+Ctrl: center)';
  1050. }
  1051. if($q('.g-icon-code', panel))
  1052. $e({el: $q('.g-icon-code', panel).parentNode
  1053. ,at:{onclick:"return habraWYG.insertTag(this, '<code>','</code>');", title:'code'}
  1054. ,cs:{cursor:'pointer'} });
  1055. if(!hS.tagsInput.val) return;
  1056. var hoverMenu = function(btn, ht, type, el){ //всплывание меню
  1057. for(var j =0; j < ht.length; j++)
  1058. ht[j] = ht[j] =='br'?'<br/>': ['<b>','<span>','<span style=color:#'+ ht[j] +'>'][type]
  1059. + ht[j] + ['</b>','</span>','</span>'][type];
  1060. var colrs,ww0,ww1;
  1061. $e({cl: ['langs','langs2','colrs'][type]
  1062. ,ht: ht.join('')
  1063. ,on:{mouseover: colrs=function(ev, ths){
  1064. var panelEcho = ev && parents('panel', ev.target) || ths; //ths - панель
  1065. var colrS = panelEcho && $qA('.'+['langs','langs2','colrs'][type], panelEcho);
  1066. if(ww0) win.clearTimeout(ww1);
  1067. if(ww1) win.clearTimeout(ww1);
  1068. if(colrS){
  1069. colrS[el &&(el-1) || 0].style.display = ev && ev.type=='mouseover'|| ev===0?'block':'none';
  1070. colrS[el &&(el-1) || 0].style.top = -colrS[el &&(el-1) || 0].offsetHeight +2 +'px';
  1071. }
  1072. },
  1073. mouseout: function(){win.clearTimeout(ww1);ww1 = win.setTimeout(function(){colrs(null, panel)}, 300)}
  1074. ,click: function(ev){return win.habraWYG.insertTag(ev.target, type <2
  1075. ?'<source lang="'+ ev.target.innerHTML.replace(/#/,'s') +'">\n'
  1076. :'<font color=#'+ ev.target.innerHTML.replace(/(.)/g,'$1$1') +'>'
  1077. ,type <2 ?'\n</source>':'</font>') }
  1078. }, apT: panel});
  1079. btn && btn.addEventListener('mouseover', colrs,!1);
  1080. btn && btn.addEventListener('mouseout', function(ev){ww1 = win.setTimeout(function(){colrs(null, panel)}, 300)},!1);
  1081. };
  1082. hoverMenu($q('.btn-dropdown ~.btn-dropdown', panel),('bash,lisp,scala,tex,dos,br,ruby,python,php,perl,br,'
  1083. +'xml,javascript,html,css,br,lua,java,cpp,c#,sql').split(','),0);
  1084. hoverMenu($q('a[onclick*="\'video\'"]', panel),('actionscript,apache,cmake,diff,vbscript,br'
  1085. +',coffeescript,django,delphi,erlang,erlang_repl,br'
  1086. +',haskell,go,matlab,mel,markdown,nginx,vala,br'
  1087. +',objectivec,vhdl,smalltalk,rust,axapta,1c').split(','),1);
  1088. hoverMenu($q('.quot', panel), ('000,003,006,009,00c,00f,300,303,306,309,30c,30f,br,'
  1089. +'030,033,036,039,03c,03f,330,333,336,339,33c,33f,br,'
  1090. +'060,063,066,069,06c,06f,360,363,366,369,36c,36f,br,'
  1091. +'090,093,096,099,09c,09f,390,393,396,399,39c,39f,br,'
  1092. +'0c0,0c3,0c6,0c9,0cc,0cf,3c0,3c3,3c6,3c9,3cc,3cf,br,'
  1093. +'0f0,0f3,0f6,0f9,0fc,0ff,3f0,3f3,3f6,3f9,3fc,3ff').split(','),2,1);
  1094. hoverMenu(btnFo, ('600,603,606,609,60c,60f,900,903,906,909,90c,90f,br,'
  1095. +'630,633,636,639,63c,63f,930,933,936,939,93c,93f,br,'
  1096. +'660,663,666,669,66c,66f,960,963,966,969,96c,96f,br,'
  1097. +'690,693,696,699,69c,69f,990,993,996,999,99c,99f,br,'
  1098. +'6c0,6c3,6c6,6c9,6cc,6cf,9c0,9c3,9c6,9c9,9cc,9cf,br,'
  1099. +'6f0,6f3,6f6,6f9,6fc,6ff,9f0,9f3,9f6,9f9,9fc,9ff').split(','),2,2);
  1100. hoverMenu($q('.user', panel), ('c00,c03,c06,c09,c0c,c0f,f00,f03,f06,f09,f0c,f0f,br,'
  1101. +'c30,c33,c36,c39,c3c,c3f,f30,f33,f36,f39,f3c,f3f,br,'
  1102. +'c60,c63,c66,c69,c6c,c6f,f60,f63,f66,f69,f6c,f6f,br,'
  1103. +'c90,c93,c96,c99,c9c,c9f,f90,f93,f96,f99,f9c,f9f,br,'
  1104. +'cc0,cc3,cc6,cc9,ccc,ccf,fc0,fc3,fc6,fc9,fcc,fcf,br,'
  1105. +'cf0,cf3,cf6,cf9,cfc,cff,ff0,ff3,ff6,ff9,ffc,fff').split(','),2,3);
  1106. }}
  1107. }
  1108. },
  1109. settOpera = function(i){
  1110. return i>1||win.opera ?', <a class="ope'+i+'" href="#note">примеч.для Оперы</a>':'';
  1111. },
  1112. getVersionDate = function(vv){if(vv){ //чтение версии из метаданных "@version version_date"
  1113. var mVer = vv.match(/([^\.]+)\.(\d{4})\.(\d{1,2})\.([1-3]0(?=0)|0?[1-3]0$|[1-3][1-9](?!0)|0?[1-9])[_.-]?(.*|$)/)
  1114. ,major, minor, date;
  1115. return {major: major = mVer && mVer[1] //версия - основная часть
  1116. ,minor: minor = mVer && mVer[5].replace(/^0+/,'') //минор-версия
  1117. ,version: major + (minor ?'.'+ minor :'')
  1118. ,date: date = mVer && mVer[2] +'-'+ (mVer[3].length <2 ?0:'') + mVer[3] +'-'+ (mVer[4].length <2 ?0:'') + mVer[4] //версия, дата выпуска
  1119. ,days: 1? Math.floor( (new Date() - new Date(date)) /DAY) :'--' //прошло дней
  1120. };
  1121. }else return {};};
  1122. if(typeof metaD !=u && !metaD.version) //для Firefox 3.6
  1123. metaD.version = /@version/.test(metaD[1]) && metaD[1].replace(/^[^\d]+/,'');
  1124. var verDat = getVersionDate(typeof metaD !=u && metaD.version)
  1125. ,hS ={ //настройки скрипта
  1126. version: (verDat.version &&'<a class="hADotted current" href="#_show_version_info" style="color:#36a" title="Показать подробности о версии">'+ verDat.version +'</a>' || '<a class="hADotted note" href="#_no_read_metadata" onclick="return!1" title="Нет чтения метаданных;'+ (isFx?' для решения (Firefox) &mdash; удалить 2 символа &quot;/\*&quot; в скрипте перед &quot;<!&quot;, строка 4; или устанавливать скрипт через расширение Scriptish':'')+'"><i>???</i></a>')
  1127. +'~ &mdash; версия; '+ verDat.date + ' &mdash; дата версии'
  1128. ,versionNumb: typeof metaD !=u && metaD.version && (metaD.version.replace(/\..*/,'') + metaD.version.replace(/(\.*?\d\d)\d+$/,'$1')) ||'???'
  1129. ,chkUpdate:'0~<span style="color:#b66;font-size:15px">&uparrow;</span> <a class="hADotted" href="#_check_update" title="кликнуть, чтобы проверить однократно">проверка</a> обновлений, <a href="#set_period" id="chkUpdateBtn" title="через сколько дней проверять">с периодом</a>'+settOpera(1)+'~2012-03-05'
  1130. ,chkUpdNoMinor:'~не уведомлять о <i style="color:#955" title="шаг подверсии не кратен 10">минорных версиях</i>~2012-03-05'
  1131. ,chkUpdPeriod: {val: 3, desc2:'(хранилище - период проверки обновлений, дней)'}
  1132. ,chkFailDate: {val: 0, desc2:'(хранилище - дата неуспешной проверки)'}
  1133. ,chkDate: {val:0, desc2:'дата последней проверки (вычисляемая)'}
  1134. ,noConsole:'1~без сообщений отладочной консоли wcl()~2011-12'
  1135. ,zenPresent:'0~подключены ли ВНЕШНИЕ стили ZenComment в <u>12-й Опере</u> (установить вручную)~2012-10-16'
  1136. //функции и оформление страницы
  1137. ,reformal:'1~<a href="http://habrajax.reformal.ru/" target="_blank" title="открыть в новом окне">идеи и замечания о скрипте</a> (reformal.ru)~2011-07'
  1138. ,inZen:'0~<i style="color:#955" title="встроенная версия стилей &mdash; @">встроенные в скрипт</i> стили <a href="'+ URLCSS +'" target="_blank" title="встроенная версия @; актуальная внешняя версия - в новом окне">ZenComment</a>~2011-08'
  1139. ,regimeNoZen:'1~режим комментариев "Компакт"/"Дзен"</i>~2011-11'
  1140. ,postsLinkNew:'1~сменить ссылку "Лента" на "Лента - новые"~2011-07'
  1141. ,allFeed:'0~-""- на "Все посты" (без компаний)~2012-04-25'
  1142. ,gooYa:'1~поиск Гугла и Яндекса по сайту~2011-10'
  1143. ,killToTop:'0~скрывание поля "Прокрутить наверх"~2012-06-10'
  1144. //оформление аннотаций в ленте
  1145. ,underCut:'1~подгружать статьи без перехода на новую страницу (хабр-аякс)~2011-05'
  1146. ,colorTopic:'1~подкраска переводов, топиков-ссылок, новостей, компаний~2011-08' //с удалением слов "Б.к."
  1147. ,toBK:'1~вид заголовков в ленте: размер шрифта, подсказка ссылки~2011-08'
  1148. ,shortenHub:'1~короткие хабы и компании (до 13 симв.)~2012-10-15'
  1149. ,noBK:'0~свернуть аннотации БК~2011-05'
  1150. ,noPodcast:'1~свернуть подкасты~2011-05'
  1151. ,noNews:'1~свернуть новости~2013-03-01'
  1152. ,listNewsAuthors: {val:'alizar,marks,aleksandrit,ilya42,FakeFactFelis,DaryaZ,mayuxi,shifttstas,wwakabobik,sharamyshara,Captcha,Mairon,ivansychev,Shapelez,semen_grinshtein'.split(','), desc2:'(авторы-новостники)'},a:0
  1153. ,noEvent:'1~сворачивать события в ленте~2012-08-20'
  1154. ,noAuthor:'1~свернуть <a id="showNoAuthor" href="#">по списку авторов</a>~2012-01-15'
  1155. ,listNoAuthor: {val:'', desc2:'(хранилище списка авторов)'}
  1156. ,noContent:'0~свернуть <a id="showNoContent" href="#" title="могут быть регекспы без слешей по краям">по списку содержимого</a>~2012-01-15'
  1157. ,listNoContent: {val:'', desc2:'(хранилище списка тел регекспов для статей)'}
  1158. ,noSmart:'0~... <a id="showNoSmart" href="#" title="могут быть регекспы без слешей по краям">по признакам обзора смартфонов</a>~2013-09-17'
  1159. ,listNoSmart: {val:'Asha,Lumia,HTC,Jolla,Nexus,Alcatel,Xperia,Galaxy,китайс.{1,,33}смартф,LG.{1,,15}Optimus', desc2:'(хранилище списка тел регекспов для признаков обзоров смартфонов)'}
  1160. ,strongCut:'1~принудительный кат, <a href="#" id="strongCutBtn">до высоты</a>~2012-03-05~2012-01-15'
  1161. ,hStrongCut: {val: 120, desc2:'(макс. высота для аннотаций при "StrongCut")'}
  1162. ,ha:'0~подмес habr к лентам geektimes и др.~2015-01-24'
  1163. ,geek: '1~подмес geektimes.ru~2015-01-24'
  1164. ,manag: '0~подмес megamozg.ru~2015-01-24'
  1165. //статья или вопрос и их оформление:
  1166. ,noTwit:'0~не показывать кнопки Твиттера~2011-06'
  1167. ,noVk:'0~не показывать кнопки ВК~2011-06'
  1168. ,noFb:'0~не показывать кнопки ФБ~2011-06'
  1169. ,noGP:'0~не показывать Г+-шаринг~2012-04-19'
  1170. ,gPlus:'0~лайки Google Plus'+settOpera(2)+'~2011-07'
  1171. //тексты статей и комментариев:
  1172. ,shortDates:'1~короткие даты текущего года~2011-09'
  1173. ,extLinks:'1~внешние ссылки &mdash; в новом окне~2012-09-03'
  1174. ,justify:'1~выравнивание колонок в статьях и ответах~2012-01-12'
  1175. //картинки в текстах:
  1176. ,viewImgCenter:'1~<u>просмотр картинок</u> в окне по центру~2013-01-21'
  1177. ,addImgs:'0~подгружать ссылки-картинки (увеличит траффик, будет переспрошено)~2013-01-20'
  1178. ,addImgsOK: 0 //для подтверждений addImgs (только =0)
  1179. ,viewX2:'1~смотреть увеличенные вдвое картинки~2013-01-17'
  1180. ,haReplace:'1~сокращение "хабра-" до "χ"~2012-09-03'
  1181. ,chtoBy:'0~исправление "что бы" на "чтобы"~2014-01-26'
  1182. //заголовок комментариев:
  1183. ,listAuthorsComms:'1~цвета активных комментаторов в начале~2011-09'
  1184. ,similarAfter:'1~похожие посты &mdash; в заголовке комментариев, в виде спадающего списка~2012-10-06'
  1185. ,shortSubscribe:'1~"слеж." вместо "отслеживать новые"~2012-07-22~2011-09'
  1186. ,commInfo:'1~навигатор по веткам комментариев~2012-11-17'
  1187. //отдельный комментарий/ответ:
  1188. ,noAva:'1~без аватаров в ответах~2011-11'
  1189. ,brAsBlock:'1~серые блоки в просветах на месте BR~2011-11'
  1190. ,noExpiredVote:'1~скрыть неактивные стрелки голосования~2012-01-08'
  1191. ,colorAuthorTopic:'0~пометки постов автора (цвет фуксии)~2011-09'
  1192. ,colorAuthorTAH:'1~то же, розовым фоном заголовка~2012-04-14'
  1193. ,colorStyle1:'1~расцветка сообщений по авторам (0/8 цв)~2012-10-22~2011-09'
  1194. ,colorStyle2:'1~расцветка авторов, 2-я часть (20/16 цв.)~2012-10-21'
  1195. ,shortReply:'1~сокращения кнопок "отв|ответ"~2011-08'
  1196. //ввод ответа в поле ввода:
  1197. ,tagsInput:'1~поле ввода &mdash; &lt;source> и &lt;font>~2012-10~2011-09'
  1198. ,innerTab:'1~ввод <i title="нажимать Shift+Tab" style="color:#955">Tab</i> и <i title="для ввода - нажимать Ctrl+Пробел" style="color:#955">&amp;nbsp;</i> в textarea~2012-02-04~~1'
  1199. ,autoGrow:'1~авторост полей ввода textarea~2012-07-20'
  1200. ,contextSelect:'1~контекстные кнопки по выделению текста~2013-04-20'
  1201. ,correctCite:'0~контекстный цитатник-корректор [бета]~2012-04-15~2012-01'
  1202. ,hQuotes:'1~<a target=_blank title="инструкция с иллюстрациями" href=http://spmbt.github.io/haPages/doc/habrAjax/habraQuotes-support.htm>выделять и отправлять</a> на <a target=_blank href="http://habraQuotes.ru/" title="(новое окно)">HabraQuotes</a>~2013-01-03~2012-04-13'
  1203. //сайдбар:
  1204. ,hideBest24:'0~скрыть блок "лучшее за 24"~2011-08'
  1205. ,hideDirectBand:'0~скрыть "прямой эфир"~2011-08'
  1206. ,hideEmploy:'0~скрыть "работу"~2012-10-13'
  1207. ,hideFreel:'0~скрыть "фрилансим"~2012-11-07'
  1208. ,hideEve:'0~скрыть блок "события". <i>Если скрыть все 5 и выключен "сайдбар под статьями"...</i>~2011-08'
  1209. ,sidebarDown:'0~сайдбар &mdash; под статьями~2011-08'
  1210. ,noAlienScripts:'1~подавление посторонних виджетов~2011-09'
  1211. ,noSomeSideBlocks:'1~без лишних боковых блоков~2012-10-13'
  1212. //Футер:
  1213. ,underFooter:'1~прибитый к низу футер~2012-09-07'
  1214. ,stru:{ //структурирование настроек и дописывание описаний
  1215.  
  1216. 'Настройки скрипта <a href="https://greasyfork.org/en/scripts/1970-habrajax" style="color:#36a" target="_blank">HabrAjax</a> (<a href="http://spmbt.github.io/haPages/doc/habrAjax/" target="_blank" title="на описание функций">что это</a>)':{sett:'version,chkUpdate,chkUpdNoMinor,noConsole,zenPresent'
  1217. ,desc:'Скрипт с рядом функций для сайта <b>habr.ru</b> и его оформления.<br><br>Есть отключаемые функции (настройки) и неотключаемые &mdash; элементы, отсутствие которых неудобно, а присутствие &mdash; не мешает.<br><br><b>Пример</b>: логотип скрипта (32x32) справа вверху каждой страницы вызывает данные настройки, помогает перейти на страницу хостинга скрипта и стилей и не отключается.<br><br><b>Пример 2</b>: если статьи на сайте не обнаружилось, пустая страница заполняется <a href="'+HRU+'/post/146200/"target=_blank>ссылками на сохранённые копии статей</a>. Точнее, на те места, где они могут быть. Гугл чаще всего сохраняет копии, поэтому страница <b>Гугл-кеша</b> по ссылке <i>тоже обрабатывается скриптом</i> HabrAjax и стилями ZenComment. Всё это неотключаемо, но никак не мешает остальным функциям просмотра сайта, потому что работает совсем на других страницах.<br><br><b>Пример 3</b>: в скрипте заложены 2 стиля оформления: HabrAjax <a href="'+HRU+'/post/135686/"target=_blank>со стилями ZenComment</a> (используется автором скрипта при просмотре сайта) и <a href="'+HRU+'/post/154923/"target=_blank>без</a> них. Но не имеется режима с полным отсутствием стилевых модификаций.'
  1218. ,descS:['Версии скрипта пишутся и обновляются, если на сайте произошло обновление, конфликтующее со скриптами, или если появилась новая функция в арсенале скрипта. В среднем получается, что обновляются версии довольно часто &mdash; раз в 5-15 дней.<br><br>Следить за обновлениями можно несколькими способами. Браузеры поддерживают <u>автообновление</u> и ручную проверку обновлений всех скриптов по кнопке.<br><br>HabrAjax имеет встроенную в скрипт <u>проверку обновлений</u>. 1 раз в сутки или реже, в 5 утра или позже он сравнивает версию в браузере с версией на сайте и сообщает, какие изменения произошли &mdash; причины обновления поясняются в специальном комментарии на 1-2 строчки.'
  1219. ,'Слежение скрипта за обновлениями на сайте. Не чаще раза в сутки, но если чтение не удалось, следующая попытка &mdash; через 15 минут. Кликом по ссылке &mdash; ручная проверка обновлений в любое время.'
  1220. ,'Версии, помеченные как минорные, не будут беспокоить сообщениями об обновлениях (на самом деле, <a href="'+HRU+'/post/175187/"target=_blank>механизм минорных версий</a> почти не используется, потому что редко, когда происходят невынужденные изменения скрипта &mdash; даже дополнения новых функций чаще идут вместе с исправлениями замеченных ошибок).'
  1221. ,'Не показывать сообщения отладочной консоли скрипта, которая постоянно используется для отладки и может выводить произвольную отладочную информацию, ненужную для пользователя.'
  1222. ,'Для Оперы 12: требуется установить вручную для корректной работы опознавателя стилей: установлены ли внешние стили ZenComment для сайта. Из-за того, что Опера 12 загружает стили очень рано, страница ещё не может знать этой информации, когда уже нужно делать некоторое форматирование со знанием про стили.']}
  1223. ,'функции и оформление страницы':{sett:'reformal,inZen,regimeNoZen,postsLinkNew,allFeed,gooYa,killToTop'
  1224. ,desc:'Группа настроек относится к почти каждой странице сайта, управляя общими элементами: стили, поля поиска, меню и т.д.'
  1225. ,descS:['Виджет сервиса замечаний и предложений отображается в виде кнопки, висящей справа на каждой странице. Впрочем, можно им пользоваться, переходя по ссылке из настроек, висение кнопки совершенно необязательно.'
  1226. ,'Стили, подгружаемые скриптом, появляются чуть позже (на 0.5-1 сек.), чем стили из Stylish, поэтому лучше включать через аддон Stylish, а здесь &mdash; только примерить для себя, удобны ли они.'
  1227. ,' "Компакт" менее зависим от мыши и отображается менее плотно, на белом фоне (рекомендуется). Чтобы работал режим "дзен", нужно поставить во внешних стилях пробел в 18-й строчке.<br><br>"Дзен" &mdash; это показ комментариев с минимумом лишней информации, на сером фоне страницы. Только имя комментатора и его текст. Существует 4 области размещения мыши, при которых в этом режиме появляется различная информация о комментариях. В целом, он излишне сложный для простого чтения.'
  1228. ,'Первая ссылка в меню сайта ведёт на "захабренные", но не все предпочитают этот режим показа ленты. Чтобы не ходить по цепочке ссылок каждый раз, просто ставим на первую ссылку ленту "Новые-все".'
  1229. ,'Как прежняя настройка, но лента &mdash; без вопросов и блогов компаний'
  1230. ,'К кнопке поиска по сайту добавляются 2 кнопки &mdash; поиск по сайту через Гугл и через Яндекс. Кроме того, смотреть результаты можно в 2-3 модификациях: фрейм половинной высоты, новое окно (Ctrl или Shift) или то же самое окно (только для местного поиска, если ввести Enter).<br><br>Поиск также выполняется через выделение текста и контекстные кнопки поиска (3 кнопки и их модификаторы Ctrl+клик).'
  1231. ,'Убрать навязчивую кнопку-колонку "Наверх". Актуально для неавторизованных, потому что у авторизованных пользователей имеется настройка пользователя для убирания этой кнопки.']}
  1232. ,'оформление аннотаций в ленте':{sett:'underCut,colorTopic,toBK,shortenHub,noBK,noPodcast,noNews,noEvent,noAuthor,noContent,noSmart,strongCut,ha,geek,manag'
  1233. ,desc:'Аннотации (краткие описания) &mdash; это начала статей в списках статей и лентах, фрагменты результатов поиска.<br><br>Лент на сайте имеется несколько видов, и все они поддерживаются общими настройками из этого раздела.'
  1234. ,descS:['Аякс-подгрузка статей и комментариев.<br><br>Появляются дополнительные кнопки возле ссылки "Далее" и комментариев, которые приводят не к переходу, а к подгрузке страницы со статьёй и комментариями.<br><br>После просмотра статью или комментарии можно свернуть, кликнув по специальной широкой кнопке над или под текстом.'
  1235. ,'Фон заголовков особенных статей немного подкрашивается в различные оттенки.'
  1236. ,'Шрифт заголовка становится тем меньше, чем длиннее заголовок, что сбалансирует место, занимаемое слишком длинными названиями.'
  1237. ,'Сокращаются длинные названия компаний и хабов до 13 символов; остальное &mdash; в подсказку.'
  1238. ,'Статьи из блогов компаний сворачиваются до одного названия. Если кликнуть по нему и развернуть, далее показ статьи ничем не отличается от других, отличие &mdash; только в начальном показе лишь одного заголовка статьи в лените.'
  1239. ,'Сворачивание подкастов до видимости одного названия без аннотации.'
  1240. ,'Новости, распознанные по формальным признакам (принадлежат фиксированному в скрипте кругу авторов или не имеют текста под катом), <a href="'+HRU+'/post/168147/"target=_blank>сворачиваются в аннотациях до названия</a>. После клика ведут себя далее как обычные статьи.'
  1241. ,'События в ленте <a href="//toster.ru/q/23089/"target=_blank>сворачиваются до слова "ev"</a> и пустой строки, наведение на которую показывает всё название, а клик делает переход на страницу события.'
  1242. ,'Сворачивание статей по списку авторов, составленному читателем (запоминается в хранилище).'
  1243. ,'Сворачивание <a href="'+HRU+'/post/136301/"target=_blank>по ключевым словам и буквосочетаниям</a> в заголовках и в аннотациях.'
  1244. ,'то же - по признакам обзора смартфонов, составленному читателем (запоминается в хранилище)'
  1245. ,'<a href="'+HRU+'/post/136301/"target=_blank>Ограничение высоты аннотации</a> размером, заданным читателем (выбор по ссылке в настройках).<br><br>Указывается половинная высота блока, потому что она определяет размер (высоту) картинок, получающихся в этом режиме (по умолчанию &mdash; 120 для ZenComment и 170 (но пишется 120) для обычного HabrAjax). Картинки и видео уменьшаются и переносятся вправо или влево от потока текста. Кликом по картинке их можно просматривать в натуральном или увеличенном виде, если включена настройка просмотра картинок ("просмотр картинок в окне по центру").'
  1246. ,'Добавляет аннотации из ленты Хабра в текущую просматриваемую ленту Geektimes или Manager, комментарии в ленту комментариев, ...'
  1247. ,'Аннотации из ленты Geektimes - в другую просматриваемую ленту.'
  1248. ,'Из ленты Manager - в другую просматриваемую ленту. Аналогично - для комментариев, избранного, чьих-либо статей, лучшего, поиска. Извлекается от начала ленты и не работает при немедленном переходе на не первую страницу ленты (из-за отсутствия информации о том, с какой по какую даты собраны аннотации на некоторой странице).']}
  1249. ,'статья и её оформление':{sett:'noTwit,noVk,noFb,noGP,gPlus'
  1250. ,desc:'Стили и функции для текстов статей.<br><br>Из неотключаемого: дата, автор и автор оригинала (имеется при переводах) дублируются вверху и внизу статьи.'
  1251. ,descS:['Убирание социальных кнопок из подписей к статье: Твиттер'
  1252. ,'','','Убирание соцкнопки расшаривания в Гугл-плюс'
  1253. ,'Добавление кнопки, которой нет на сайте &mdash; <a href="'+HRU+'/post/124057/"target=_blank>лайк Гугл-плюса</a>. Позволяет смотреть, сколько лайков поставили статье читатели и ставить лайки самому, если авторизован в Г+. Выполняет подгрузку множества скриптов (50-100К на кнопку) с серверов Гугла.']}
  1254. ,'тексты статей и комментариев':{sett:'shortDates,extLinks,justify,viewImgCenter,addImgs,viewX2,haReplace,chtoBy'
  1255. ,desc:'действия, применяемые к текстам и картинкам; в отличие от прежней группы, эти настройки относятся не только к текстам статей'
  1256. ,descS:['Отображение дат укорачивается, оставаясь понятным и удобочитаемым: удаляется текущий год или год в датах последних 8 месяцев, добавляются дни недели (2 буквы) для всех дат, кроме "сегодня" и "вчера".'
  1257. ,'На все внешние ссылки ставит открывание в новом окне и специальный символ (двойная стрелка вправо-вверх) в конце ссылки.<br><br>Местные ссылки выдаются <u>с подсказками дат</u> (месяц и год ссылки). Даты вычисляются приблизительно, по номеру статьи или вопроса.'
  1258. ,'Колонка выравнивается стилем justify (левый и правый край текстов в колонке &mdash; ровный, пробелы в строке &mdash; переменной ширины).'
  1259. ,'<a href="'+HRU+'/post/166575/"target=_blank>Показывает картинки на сайте</a> на той же странице с возможностью перемещения и масштабирования (как в имаджбордах).<br><br>Shift+клик &mdash; меню поиска по картинкам на нескольких их сервисах.<br><br>Ctrl-клик — переход по ссылке с картинки.'
  1260. ,'Все ссылки, найденные с расширениями картинок, подгружаются и предварительно просматриваются в размере не более 200 пикс. Таких картинок могут быть многие мегабайты, поэтому на включение этой настройки в скрипте предусмотрено дополнительное подтверждение пользователем, происходящее один раз после установки настройки.'
  1261. ,'Картинки покажутся в удвоенном размере. Колесом мыши их можно и без того увеличить или уменьшить, но настройка нужна для комфортного начального просмотра в зависимости от монитора перед глазами.'
  1262. ,'Заменяет буквосочетания "хабр" греческими буквами "хи".'
  1263. ,'Заменяет грамматическую ошибку (большей частью) "что бы" на слитное написание.']}
  1264. ,'заголовок комментариев':{sett:'listAuthorsComms,similarAfter,shortSubscribe,commInfo'
  1265. ,desc:'Заголовок прячет и содержит ворох полезной информации: распределение популярности авторов комментариев, кнопка просмотра похожих статей, инфографика корневых веток комментариев. Кроме того, он сделан контрастным для лучшей распознаваемости в колонках длинных статей.'
  1266. ,descS:['Список авторов по количеству сделанных комментариев и раздача авторам цветов для расцветки их комментариев.'
  1267. ,'Из сайдбара сюда <a href="'+HRU+'/post/150954/"target=_blank>перенесены "Похожие посты"</a>. Можно отменить перенос и смотреть их традиционно, в сайдбаре.'
  1268. ,'сокращения слов, поясняющих назначения чекбоксов подписки на комментарии'
  1269. ,'Инфографика &mdash; навигатор по веткам комментариев. Показывает объёмы текстов, плюсов и минусов в ветках, ссылки и картинки в них. Появляется при наведении мыши на заголовок комментариев.']}
  1270. ,'отдельный комментарий':{sett:'noAva,brAsBlock,noExpiredVote,colorAuthorTopic,colorAuthorTAH,colorStyle1,colorStyle2,shortReply'
  1271. ,desc:'функции и стили для каждого комментария'
  1272. ,descS:['Аватары появляются при наведении мыши на место расположения аватара, а иначе &mdash; не отвлекают внимание. Размер аватара &mdash; 16х16, хотя на сайте они имеют больший размер.'
  1273. ,'Для более плотного расположения текстов комментариев и слитности комментариев одного человека из них убираются вертикальные пробелы, заменяясь небольшими серыми разделительными блоками высотой 3px, не занимающих высоты строки.'
  1274. ,'Там, где наличие стрелок голосования не имеет смысла, там они убраны, в том числе, с помощью стилей. Если стилей не установлено, можно отключать стрелки скриптом.'
  1275. ,'3 варианта выделения комментариев автора статьи или отключение выделения комментариев автора.<br><br>Первый чекбокс &mdash; выделяется фон под именем автора (площадь подсветки невелика, поэтому цвет фона &mdash; контрастный).'
  1276. ,'Выделение комментария автора статьи фоном заголовка комментария.'
  1277. ,'2 чекбокса &mdash; 4 варианта расцветки авторов комментариев, что, по идее, заменяет различение авторов по аватарам и по именам. по расцветкам видно, разные ли авторы участвуют в диалоге. (Кнопки "ответ" расцвечиваются теми же разными цветами.)<br><br>Если оба чекбокаса выключены, расцветки авторов нет. Если включен первый &mdash; используется палитра в 8 цветов. Они наиболее различимы, но слишком мало авторов выделяется своими цветами.'
  1278. ,'Второй чекбокс выбора палитр. Всего &mdash; 3 палитры: 8, 16 и 20 цветов или отключение расцветки.'
  1279. ,'Сокращения слов-кнопок "ответить". (Нужно для стилей ZenComment, потому что там эти кнопки располагаются вертикально и должны поместиться в высоту сообщения.)']}
  1280. ,'ввод ответа в поле ввода':{sett:'tagsInput,innerTab,autoGrow'
  1281. ,desc:'Ввод текстов &mdash; важные функции сайта, поэтому рядом настроек они сделаны более удобными.<br><br>Из ненастраиваемых: при вводе и редактировании статей размер поля ввода устанавливается размером с весь блок текста, но не более 80% высоты окна. Это же относится и ко всем остальным полям ввода, но более заметно на статьях, так как они обычно объёмны.<br><br>Перейти ко вводу текстов можно и через контекстные кнопки (включаются настройкой "контекстные кнопки"). Они помогают писать комментарии и цитировать прямо в контексте статьи или комментария, писать письма в ЛС, просто выделив цитату (автор определится сам или может быть изменён).<br><br>Для ввода статей модифицируются специфические кнопки: h3 &mdash; ввод тегов &lt;h3> для заголовков; атрибут text="" для ката; позиционирование рисунков слева, справа и по центру.'
  1282. ,descS:['Ввод <a href="'+HRU+'/post/141976/"target=_blank>кодов языков в теге Source</a>.<br>Всего можно указать 1 из более 40 языков для выбора подсветки ключевых слов. Для удобного выбора список языков разбит на 2 и показывается в виде дополнительных списков над баром кнопок.<br><br>Так же организованы и множество ссылок выбора цвета текста в теге FONT, разбитые на 3 подсписка.'
  1283. ,'Ctrl+пробел &mdash; вводится неразрывный пробел &amp;nbsp; в поле ввода. <br><br>Shift+Tab &mdash; вводится символ табуляции (обычно нужен для форматирования кодов программ).'
  1284. ,'Стилями отключена фиксация высоты поля ввода на сайте, поэтому всегда можно увеличить его вручную.<br><br>Но есть и <a href="'+HRU+'/post/148188/"target=_blank>автоматическое увеличение поля ввода</a> со вводом каждой новой строки (уменьшение не предусмотрено).<br><br>Работает для всех полей ввода текстов, кроме страниц настроек пользователя.']}
  1285. ,'контекстные кнопки':{sett:'contextSelect,correctCite,hQuotes'
  1286. ,desc:'Масса функций по вводу текстов добавляется при включении контекстных кнопок.<br><br>После выделения текста рядом с выделением появляется бледная полупрозрачная кнопка "<_>", а по наведению мыши на неё &mdash; остальные 9-15 кнопок-функций. Клик &mdash; выполнение. Модификатор &mdash; удержание Ctrl перед кликом.<br><br>Для правки собственных статей при выделении фрагмента собственной статьи (при условии авторизации на сайте) к контекстным кнопкам добавляется "<Е>", которая помогает <a href="'+HRU+'/post/177427/"target=_blank>редактировать свою статью</a> &mdash; выделяет цитату в поле ввода статьи в фрейме или новом окне.<br><br>Редактирование своей статьи работает и без фрейма, если выделение происходит на странице редактирования или создания статьи. Можно сделать несколько исправлений текста, переходя к фрагментам таким способом, прежде чем отправить его на сервер.'
  1287. ,descS:['Режим <a href="'+HRU+'/post/171777/"target=_blank>работы с контекстной кнопкой </a>"<_>", которая возникает после выделения текста на странице. По наведению мыши вокруг кнопки "<_>" появляются 9-15 других кнопок, помогающих в общении на сайте:<br> *) Ответ на комментарий прямо из места цитирования;<br>*) написание письма или переход к фрейму с формой написания письма автору статьи или комментария;<br>*) выбор имени автора из текста страницы, которому хочется написать письмо;<br>*) поиск по сайту;<br>*) редактирование собственных статей с переходом к месту редактирования.<br><br>Контекстное поле ввода и кнопки можно перемещать по странице перетаскиванием.'
  1288. ,'Функциональность "Корректора" &mdash; в стадии <a href="'+HRU+'/post/169761/"target=_blank>разработки</a>.'
  1289. ,'Быстро публикует копии интересных комментариев на стороннем сервисе, просто по выделению части комментария (опубликуется весь), или группы до 10. Достаточно 1 клика по кнопке "HQ". Успешность сообщается в примечании вверху окна, ссылка на публикацию &mdash; там же.']}
  1290. ,'сайдбар':{sett:'hideBest24,hideDirectBand,hideEmploy,hideFreel,hideEve,sidebarDown,noAlienScripts,noSomeSideBlocks'
  1291. ,desc:'Стилями ZenComment ширина сайдбара несколько уменьшена (до 26%), а настройками его можно вообще убрать или перенести вниз, что могло бы быть удобно на смартфонах и узких окнах менее 1000 пикселей. В зависимости от ширины окна применяется адаптивный дизайн &mdash; уменьшение отступов по краям, начиная с 640 пикс. и меньше. При более 1100 &mdash; наоборот, отступы размещаются несколько свободнее.<br><br>Имеется ненастраиваемая функция заполнения сайдбара блога компании, который обычно пуст, запомненным в прежней странице сайдбаром. Это сохраняет привычный для читателя баланс информации и ссылок справа.<br><br>Чтобы вернуть блок "Похожие посты" в сайдбар, отключают настройку "похожие посты и вопросы" в группе "заголовок комментариев". Сайдбар немного разрастётся, но названия статей будут перед глазами.'
  1292. ,descS:[' Скрывание различных блоков сайдбара. По настройке внизу &mdash; уже скрыты ненужные, остались 6, но и те можно выборочно скрыть.<br><br>Блок "Лучшее за 24 часа" полезен показом ссылок на наиболее популярные статьи за последние сутки. Скрипт <a href="http://spmbt.github.io/haPages/sidebarLive2Dailybest.htm">удаляет дублирующие ссылки</a> из блока "Что обсуждают", но переносит признак обсуждения (число комментариев) в "Лучшее".'
  1293. ,'Показывает самые последние комментарии и их авторов. Блок показывает активность комментаторов и существование статей, которые ещё не стали "Лучшими" за день, но на них отвечают. Обычно содержимое блока очень часто меняется (каждые несколько минут) и может рассматриваться как список случайных комментируемых статей.<br><br>Если дата статьи старее месяца, фон ссылки делается чуть более тёмным, подсвеченным, а в подсказке <a href="//toster.ru/q/23257/"target=_blank>появляется приблизительная дата</a>, вычисленная по номеру статьи или вопроса. (Каждый месяц данные о дате статей дополняются в скрипте вручную.) Выделение показывает, что ответили на старую статью, что бывает нечасто.'
  1294. ,'Если географическая локализованность предлагаемых работ или их тематика неинтересна читателю, есть смысл скрыть блок "Работа". Обычно в нём встречаются предложения из Москвы, Питера, Минска и намного реже &mdash; из других мест.'
  1295. ,'Если блок предложений по фрилансу неинтересен, он скрывается этой настройкой.'
  1296. ,'Если скрыть все 5 блоков и будет выключен "сайдбар под статьями", правый сайдбар будет скрыт; Из побочных эффектов &mdash; скрываются настройки ленты, которые бывают нужны.'
  1297. ,'Если "сайдбар под статьями", то настройки ленты не будут скрываться, а будут отображаться под статьями, лентами.<br><br>Для окон нормальной для десктопов ширины смысла переносить сайдбар особого нет &mdash; колонки становятся широкими и хуже читаемыми. Перенос полезен для окон смартфонов, ширин окна порядка 800 и меньше.'
  1298. ,'Подавление ненужных скриптов в сайдбаре, которые могут устанавливаться компаниями в рекламных целях или просто "потому что есть такая возможность".'
  1299. ,'Из всех блоков остаётся 5 наиболее полезных ("Похожие посты" в сайдбаре не считаются, так как перенесены скриптом в заголовок комментариев).']}
  1300. ,'футер':{sett:'underFooter'
  1301. ,desc:'В футере имеются ещё 3 неотключаемых и удобных функции: подгрузка для чтения 1 из 3 статей в футере, <a href="'+HRU+'/post/152055/"target=_blank>сбалансированное отображение названий</a> этих 3 ссылок, скрывание 4 постоянных ссылок на родственные ресурсы в футере.'
  1302. ,descS:['На коротких страницах располагает футер <a href="'+HRU+'/post/151320/"target=_blank>прилепленным к нижней кромке страницы</a>. В Хроме может работать некорректно, поэтому сделано отключаемым. ']}
  1303. ,desc2:'альтернативный способ просмотра настроек'
  1304.  
  1305. }
  1306. ,defa:{} //для сохр_дефолтных
  1307. ,get: function(ret){ try{ //если настройки записаны, они читаются; иначе используются данные из скрипта
  1308. var s = (function(){return this.GM_getValue('habrAjax_settings','{}')||{};})(); //this -- доступ к текущему window
  1309. if(s !=null && (function(){return this.JSON && JSON.parse;})()){
  1310. var saved = JSON.parse(s)
  1311. ,addSett =0;
  1312. if(ret)
  1313. return saved ||{};
  1314. for(var i in hS){
  1315. var sI = hS[i];
  1316. if(typeof sI !='function'&& typeof sI !='object'&& sI.length >9){
  1317. var sIA = sI.split('~')
  1318. ,vals =['val','desc','date','date0','noChrome'];
  1319. hS[i] ={};
  1320. for(var j =0; j < sIA.length;j++)
  1321. hS[i][vals[j]] = j || i =='version'? sIA[j] : +sIA[j];
  1322. }
  1323. if(sI.val) hS.defa[i] = sI.val;
  1324. }
  1325. if(typeof saved =='object'){
  1326. for(var i in saved){ var hSI = hS[i];
  1327. if(hSI && (hSI.val ===undefined || hSI.val ==-1) || typeof hSI ==u && i!='sHQ'){ //стереть, если настройки нет или пусто, или -1
  1328. delete saved[i];
  1329. addSett =1;
  1330. }
  1331. if(saved[i] !==undefined && i !='version'){
  1332. if(typeof hSI ==u)
  1333. hS[i] ={};
  1334. hS[i].val = saved[i]; //если настройка - другая, использовать из памяти
  1335. }
  1336. }
  1337. if(hS.addImgs && hS.addImgs.val && !saved.addImgsOK)
  1338. if(confirm('Включена настройка "Подгрузка рисунков",\nно не подтверждена. Согласны ли Вы\n'
  1339. +'с увеличением траффика за счёт подгрузки рисунков?')){
  1340. saved.addImgsOK =1; addSett =1;
  1341. }else
  1342. hS.addImgs.val =0;
  1343. if(!saved.a){
  1344. saved.a ={}; saved.a[nameGen()] = Math.floor(NOW/10e6); addSett =1;}
  1345. for(var i in saved.a){sHQ = sHQ.replace(/@/,i).replace(/@/,(saved.a[i]+'').substr(1));/*('sHQ_'+ saved.a[i]).wcl(i,hS);*/}
  1346. if(addSett)
  1347. hS.save(saved);
  1348. }
  1349. }
  1350. }catch(er){'!!err_getSettings()'.wcl(er +' '+ i, er.lineNumber||'')};
  1351. return hS;
  1352. },
  1353. init: function(){ //создать блок для настроек
  1354. var divSett = $e({cl:'habrAjaxSettings', apT: document.body}); //вывод настроек для просмотра
  1355. $e({el:'BUTTON'
  1356. ,cs:{position:'relative', padding:'0 2px'}
  1357. ,ht:'X'
  1358. ,at:{title:'Без сохранения'}
  1359. ,on:{click: hS.edit}
  1360. ,apT: $e({cs:{cssFloat:'right', margin:'-4px 2px 0 -8px', height:'1px'}, apT: divSett})
  1361. });
  1362. var dScroll = $e({cs:{maxHeight: win.innerHeight - 50 - 25 +'px', overflow:'auto', marginBottom:'2px', paddingBottom:'2px'}, apT: divSett }) //ограниченный по высоте див со скроллингом
  1363. ,sGroupS =[], groupI =0;
  1364. for(var i in hS.stru){ var hSSI = hS.stru[i]; //разброс описаний по массиву
  1365. if(hSSI.sett)
  1366. sGroupS.push({name: i, desc: hSSI.desc, settS: hSSI.sett.split(','), descS: hSSI.descS});
  1367. }
  1368. for(var i in hS){var hSI = hS[i];
  1369. //'hSI'.wcl(hSI && hSI.val !==undefined , hSI.desc !==undefined ,!(isChrome && hSI.noChrome), hSI )
  1370.  
  1371. if(hSI && hSI.val !==undefined && hSI.desc !==undefined //генерация списка настроек
  1372. && !(isChrome && hSI.noChrome)){
  1373. //поиск элемента в группах; если в новой группе - выводится заголовок
  1374. if(sGroupS[groupI])
  1375. for(var j =0, sL = sGroupS[groupI].settS.length; j < sL; j++){
  1376. var sGJ = sGroupS[groupI].settS[j];
  1377. if(i == sGJ){
  1378. var sGDJ = sGroupS[groupI].descS && sGroupS[groupI].descS[j];
  1379. //'sGJ, sGDJ'.wcl(sGJ, sGDJ)
  1380. break;}
  1381. if(j == sL -1){ //элемент не найден в текущей группе (группы джб синхронизированы)
  1382. j = -1;
  1383. groupI++;}
  1384. }
  1385. if(j ==0){ var sGI = sGroupS[groupI];
  1386. $e({ht: sGI.name +' ('+ sGI.settS.length +')' //вывод заголовка группы
  1387. ,cl:'group'
  1388. ,on:{mouseover: sGI.desc ? hView :'', mouseout: sGI.desc ? hViewHide :''}
  1389. ,at:{'data-hView': sGI.desc ||''}
  1390. ,apT: dScroll} );
  1391. }
  1392.  
  1393. var dSettingsLine = $e({cl:'sett'
  1394. ,on:{mouseover: sGDJ ? hView :'', mouseout: sGDJ ? hViewHide :''}
  1395. ,at:{'data-hView': sGDJ ||''}
  1396. ,apT: dScroll}) //элемент настройки
  1397. ,isNew = hSI.date && NOW - (new Date(hSI.date)) < 31*DAY + 20*DAY*(!/\-\d+\-/.test(hSI.date))
  1398. ,chk0 = $e({el:'SPAN'
  1399. ,cl: (isNew ?'latest':'')+(hSI.val ==0 ?' notChecked':'')
  1400. ,cs:{verticalAlign:'middle'}
  1401. ,apT: dSettingsLine })
  1402. ,no1_1 = hSI.val !=1 && hSI.val !=0 && hSI.val !=-1
  1403. ,chk = $e({el: no1_1 ?'I':'INPUT'
  1404. ,ht: no1_1 ? hSI.val :''
  1405. ,at:{type:'checkbox'
  1406. ,title: i +(hSI.date?', '+ hSI.date + (isNew?', новое':''):'')
  1407. ,id: i
  1408. ,rel: i}
  1409. ,apT: chk0 })
  1410. if(isNew)
  1411. chk.style.top = !win.opera ?'1px':0;
  1412. if(hSI.val ==-1) chk.setAttribute('disabled','disabled');
  1413. if(hSI.val ==1 || hSI.val ==0) chk.checked = hSI.val;
  1414.  
  1415. $e({el:'LABEL', at:{for: i}, ht: hSI.desc, apT: dSettingsLine});
  1416. }}
  1417. $e({el:'BUTTON', cs:{cssFloat:'right', marginRight:'6px', padding:'0 3px'}
  1418. ,ht:'>', at:{title:'экспорт/импорт/сброс'}
  1419. ,on:{'click': function(){
  1420. var c = hS.save(hS.get(1), 1)
  1421. ,s = prompt('Изменить/сохранить/стереть настройки HabrAjax', c);
  1422. if(s==null)
  1423. return;
  1424. if(s=='')
  1425. s='{}';
  1426. if(s != c){
  1427. hS.save(s); //c проверкой на синтаксис хеша
  1428. divSett.style.display ='none';
  1429. }
  1430. }}, apT: divSett});
  1431. $e({el:'BUTTON', ht:'Сохранить', at:{title:'Изменения вступят в силу после обновления страницы (F5)'}
  1432. , on:{click: hS.saveByHand}, apT: divSett});
  1433. $e({el:'BUTTON', ht:'Без сохранения', at:{title:'закрыть блок'}, on:{click: hS.edit}, apT: divSett});
  1434.  
  1435. for(i =1; i <= 2; i++){ //обработчики на "примеч. для Оперы"
  1436. var dQO = $q('.ope'+i, divSett);
  1437. dQO && dQO.addEventListener('click', function(){
  1438. hN.addNote('<b>Примечание по необходимым настройкам <span class="hlp">браузера Opera</span> для работы отдельных настроек юзерскрипта</b><br>'
  1439. +'&nbsp; &nbsp; <i>Установка скриптов в Опере требует <u>особых настроек</u> для некоторых обычных действий, связанных с кроссдоменным доступом скриптов. Они довольно длинны, и у других браузеров такого нет, но альтернатива для Оперы &mdash; только аддон, которого для HabrAjax не существует (можно сделать вручную). Если настроек не будет, ничего критического не произойдёт, просто не будут выполняться функции из тех пунктов настроек, в которых указана ссылка на это примечание.<br></i><div class="hlp">Все существенные иллюстрации приведены <a href="http://radikal.ru/F/s019.radikal.ru/i623/1203/82/306bfe31b142.png" target="_blank" title="в новом окне">на скриншоте настроек Оперы</a></div>'
  1440. +'<div class="hlp"><b>1)</b> Чтобы стали отображаться <i><b>кнопки Google Plus</b> с количеством "лайков"</i> над кнопками, нужно прописать этот юзерскрипт (папку, в которой он расположен у вас на компьютере) <u>в настройках браузера</u> для сайта plusone.google.com:</div>'
  1441. +'<div class="hlp"><b>1:А)</b> Открыть "Инструменты &mdash; Общие настройки &mdash; Расширенные - Содержимое - Настройки для сайтов - Добавить - Сайт - (ввести: "plusone.google.com") - Скрипты - Папка пользовательских файлов Javascript - (установить: каталог, в котором расположен скрипт HabrAjax) - ОК - Закрыть - ОК;</div>'
  1442. +'<div class="hlp"><b>1:Б)</b> открыть настройки <a target="_blank" href="opera:config#User%20Prefs" title="в новом окне">opera: config #User Prefs</a> - User JavaScript on HTTPS - (выбрать чекбокс) - кнопка "Сохранить внизу раздела(!); Проще - ввести "HTTPS" в поле "Найти" (фильтр на странице). После этого количества "лайков" в кнопках Google Plus начнут отображаться. К сожалению, после этого браузер будет периодически (при первом посещении любой страницы https:) спрашивать, разрешается работа юзерскриптов в защищённых страницах, даже если кнопок "лайков" на них не будет.</div>'
  1443. +'<div class="hlp"><b>2.</b> Чтобы работали автообновления и <a href='+ URLSCR + HAJAX +'code/habrAjax.meta.js>просмотр мета-директив с сайта-хостера</a> в Опере, нужно такие же действия, как в пункте <b>1:А</b>, сделать для сайта <b>'+ URLSCR +'</b>. <i>(Включения HTTPS по п. 1:Б для данной функциональности не требуется.)</i></div><div>&nbsp;</div>'
  1444. +'&nbsp; &nbsp; Инструкция <a href="'+HRU+'/post/140643/">по установке юзерскриптов в Оперу</a>','*');
  1445. hNE.style.opacity =1;
  1446. },!1); }
  1447. return divSett;
  1448. },
  1449. edit: function(ev){ //показать список настроек
  1450. if(ev.ctrlKey ^ ev.shiftKey){
  1451. window.open(URLSCR + HAJAX,'_blank');return;}
  1452. var sett = $q('.habrAjaxSettings');
  1453. sett.style.display = sett.style.display !='block'?'block':'none';
  1454. $q('.habrAjaxSettings>div+div').style.maxHeight = win.innerHeight - 50 - 25 +'px';
  1455. if(ev.preventDefault) $pd(ev);
  1456. },
  1457. updSettings: function(hh){ //добавить|обновить настройки
  1458. var sSaved = hS.get(1);
  1459. for(var i in hh){
  1460. sSaved[i] = hh[i];
  1461. hS[i].val = hh[i];
  1462. }
  1463. hS.save(sSaved);
  1464. },
  1465. saveByHand: function(){ //сохранить из списка настроек
  1466. var oi = $qA('.habrAjaxSettings input')
  1467. ,s={}, key;
  1468. for(var i in oi){
  1469. key = oi[i].getAttribute && oi[i].getAttribute('rel');
  1470. if(!oi[i].disabled && key) //грузим только 0, 1 и не disabled
  1471. s[key] = oi[i].checked ?1:0;
  1472. }
  1473. var sSaved = hS.get(1) //сохранённое ранее
  1474. ,sNew ={};
  1475. if(typeof sSaved !='object') sSaved ={};
  1476. for(var i in hS) //сохранить все сгенерированные ранее сохранённые настройки
  1477. if(hS[i].desc2 && sSaved[i] !==undefined && hS[i] !==null)
  1478. s[i] = hS[i].val;
  1479. for(i in s) //сохранять ключи с отличными от прежних значениями или сохранённые ранее
  1480. if(s[i] != hS[i].val || sSaved[i] !==undefined)
  1481. sNew[i] = s[i];
  1482. sNew.version = this.versionNumb;
  1483. if(sNew.addImgs ==1)
  1484. sNew.addImgsOK = sSaved.addImgsOK;
  1485. hS.save(sNew);
  1486. $q('.habrAjaxSettings').style.display ='none';
  1487. hN.addNote('Изменения настроек вступят в силу после перезагрузки страницы (или при просмотре новых страниц в этом же браузере)', null,'chgSettings');
  1488. },
  1489. save: function(sett, ret){ try{ //запись настроек
  1490. if( (function(){return this.JSON && JSON.stringify && this.GM_setValue;})() ){
  1491. var s = (typeof sett =='string') && sett || JSON.stringify(sett);
  1492. if(!ret)
  1493. (function(){this.GM_setValue('habrAjax_settings', s);})();
  1494. else
  1495. return s;
  1496. }}catch(er){alert(er +' _saveSettings()')}
  1497. }
  1498. },
  1499. getDay = function(datArr, mon){return 'вспнвтсрчтптсб'.match(/../g)[new Date(datArr[3]
  1500. +'-'+(mon >8?'':0)+(mon +1)+'-'+(datArr[1]>9?'':0)+datArr[1]).getDay()];},
  1501. datesShorten = function(blck, dateSelect){ //переработка вида дат: не показывать текущий год или год за последние 8 месяцев
  1502. var dates = typeof blck=='string'?[{innerHTML:dates}]:$qA(dateSelect, blck) //(на вход - массив DOM-элементов с датами)
  1503. ,thYear = NOWdate.getFullYear()
  1504. ,thMonth = NOWdate.getMonth()
  1505. ,yestDate = new Date(NOW - DAY)
  1506. ,datMonth ={'января':0,'февраля':1,'марта':2,'апреля':3,'мая':4,'июня':5,'июля':6,'августа':7,'сентября':8,'октября':9,'ноября':10,'декабря':11}
  1507. ,monthName = function(m){
  1508. for(var i in datMonth)
  1509. if(datMonth[i] == m) return ' '+ i;
  1510. };
  1511. if(dates && dates.length)
  1512. for(var i in dates){ var dat = dates[i]; if(dat.innerHTML){
  1513. //парсинг дат
  1514. var datKBI = dat.attributes && ($q('.time_changed', dat) || $q('.changed', dat) );
  1515. if(datKBI){
  1516. datKBI.title = datKBI.innerHTML.replace(/( \(|\))/g,'');
  1517. datKBI.innerHTML ='(изм)';
  1518. }
  1519. var datFull = dat.innerHTML
  1520. ,datQaToday = /сегодня/.test(datFull)
  1521. ,datQaYest = /вчера/.test(datFull)
  1522. ,dateText = datFull.replace(/ в /,' ').replace(/(сегодня |вчера )/,'')
  1523. ,datArr = dateText.match(/(\d+)\s+([а-яё]+)\s+(\d{4})?/i)
  1524. ,mon = datArr && datMonth[datArr[2]]
  1525. if(datArr && !datArr[3])
  1526. datArr[3] = thYear;
  1527. var today = datQaToday || thYear == (datArr && datArr[3]) && thMonth == mon && NOWdate.getDate() == datArr[1]
  1528. ,todYest = today || datQaYest || datArr && (yestDate.getFullYear() == datArr[3] && yestDate.getMonth() == mon && yestDate.getDate() == datArr[1])
  1529. ,dateMon = datArr && (datArr[1]+' '+datArr[2]) || (today ? NOWdate.getDate() + monthName(thMonth) : yestDate.getDate() + monthName(yestDate.getMonth()))
  1530. ,day = datArr && !todYest ?','+ getDay(datArr, mon) : today ?'':',';
  1531. if(todYest)
  1532. dateText = dateText.replace(/(\d+)\s+([а-яё]+)\s*/i,'').replace(/$/, today ?'':'вчера');
  1533. if(datArr && (datArr[3] == thYear //текущий год
  1534. || Number(datArr[3]) +1 == thYear && mon && thMonth +12 <= mon +8 ) || todYest) //последние 8 мес
  1535. dateText = dateText.replace(/ ?\d{4}\s*/,'');
  1536. //'datesShorten'.wcl(dateText, dateText.length, datArr, NOWdate.getDate(), thYear)
  1537. dat.innerHTML = dateText.replace(/(.*?)(\d{1,2}:\d\d)(.*)/,'$2#$1$3').replace(/(#|$)/, day);
  1538. if(typeof blck=='string') return dat.innerHTML;
  1539. var dT = dat.getAttribute('datetime') ||''; // 2011-05-13T05:56:14+04:00
  1540. if(!dT)
  1541. dT = dat.title;
  1542. if(todYest)
  1543. dT +=' ';
  1544. if(dT)
  1545. dat.title = dT.replace(/\d*-\d*-\d*T/,'').replace(/:00$/,'').replace(/$/, todYest ?(dT.length >2?', ':'')+ dateMon :'');
  1546. }}
  1547. },
  1548. blockBrs = function(replyM){
  1549. var brs = $qA('br', replyM);
  1550. if(brs && brs.length){
  1551. var prevBR, prevPrevBR;
  1552. for(var j in brs){ if(brs[j].parentNode){ //BR -> DIV + нек.удаления BR в концах сообщ.
  1553. var brn = brs[j].nextSibling
  1554. ,brnn = brn ? brn.nextSibling :null;
  1555. //wcl(!prevBR , brn && brn.tagName =='BR', brnn && brnn.tagName, brn && brn.nodeValue =='\n', brnn && brnn.nextSibling
  1556. // && brnn.nextSibling.nodeValue);
  1557. if(!prevBR && brn && (brn.tagName =='BR'
  1558. || brnn && brnn.tagName =='BR' && brn.nodeValue =='\n' && brnn.nextSibling
  1559. && (!/^\s+$/.test(brnn.nextSibling.nodeValue) || brnn.nextSibling.nextSibling) ) ){
  1560. //wcl('val='+brn.nodeValue.charCodeAt(0)+' '+brn.nodeValue.charCodeAt(1)+' '+brn.nodeValue+' '+brnn.nextSibling.nodeValue)
  1561. prevBR =1;
  1562. $e({cl:'vSpace', bef: brs[j] });
  1563. brs[j].parentNode.removeChild(brs[j]);
  1564. }else{
  1565. var brp = brs[j].previousSibling;
  1566. //wcl(authorCommName, brp && brp.nodeValue, brp && brp.tagName, brn && !/^\s+$/.test(brn.nodeValue), brnn && !/^\s+$/.test(brnn.nodeValue));
  1567. var setV = !prevBR && (brn && !/^\s+$/.test(brn.nodeValue) || brnn && !/^\s+$/.test(brnn.nodeValue))
  1568. && brp && (brp.nodeValue && brp.nodeValue.replace(/\s+/m,'') > 53 || /BLOCKQUOTE|H1|H2|H3|H4|H5|H6|UL|OL|IMG/i.test(brp.tagName)|| brp.className =='strongCutImgPlace');
  1569. if(setV && /powerCut/.test(replyM.className) && (brp.tagName =='IMG' || brp.className =='strongCutImgPlace') ){
  1570. brs[j].parentNode.removeChild(brs[j]);
  1571. //'brs[j].previousSibling'.wcl(brp)
  1572. }else if(setV){
  1573. $e({cl:'vSpace3', bef: brs[j] });
  1574. brs[j].parentNode.removeChild(brs[j]);
  1575. }else if(prevPrevBR)
  1576. brs[j].parentNode.removeChild(brs[j]);
  1577. }
  1578. prevPrevBR = prevBR;
  1579. prevBR =0;
  1580. }}
  1581. }
  1582. },
  1583. correctCommentsBefore = function(comms){ //коррекции комментариев в тексте HTML, после подгрузки
  1584. if(!hS.brAsBlock.val) return comms;
  1585. return (comms.replace(/<br\/>\r?\n?<br\/>(?!\s+<\/div>)/gm, '\n<div class="vSpace"></div>')
  1586. .replace(/<br\/>(?!\s+<\/div>)/gm, '\n<div class="vSpace3"></div>'));
  1587. },
  1588. correctCommentsAfter = function(comms, topic){ //коррекции в DOM после разворота комментов
  1589. //схема цветов: [colors:основные, pastelColors:пастельные, ge2Color:авторские, общие на оставшихся, общие пастельные, colorTAH:автора топика, colorTAHnew:новые от автора топика]
  1590. var scheme ={sch0:'ccc,ebc,ea8,ed8,cf9,9da,9ed,abe,ebe0f5'
  1591. ,sch1:'ccc,ebb,eed5bb,eeedbb,d4eebb,beb,a6dfc1,bee,bbd6ee,bbe,cec0dd,e7c9d9,f5e0e0,f5eae0,f5f5e0,eaf5e0,e0f5e1,d0eddf,e0f5f5,e0ebf5,ebe0f5'
  1592. ,sch2:'ccc,c88fa5,d79a89,a4c57d,78aa8e,dec3ce,edd4ce,d6e3c7,b7cec1,eedae2,f8e7e1,e8f1dd,d3e3da,f2ebee,fcf4f2,f5f9ef,eaf3ee,fbf4f6'},
  1593. pastel = function(colr){ //побледнение цвета
  1594. var pastelK = 0.64
  1595. ,s ='#';
  1596. colr = colr.substr(1).match(/../g);
  1597. for(var i in colr)
  1598. s += (function(x){return (Number(x) <= 9 ?'0':'')+ Number(x).toString(16)})
  1599. (255 - Math.floor((255 - parseInt(colr[i], 16)) * pastelK));
  1600. return s;
  1601. },
  1602. prepColors = function(colr){ //подготовка цветовой схемы //подсветки повторяющихся авторов (избранные цвета, по количеству ответов)
  1603. colr = (colr||'').split(',');
  1604. for(var i in colr){
  1605. var ci = colr[i];
  1606. if(i ==0) //контрастирование автора
  1607. ci = [ci,'eba2eb','f9ddec','f1d0f0'][hS.colorAuthorTAH.val *2 + hS.colorAuthorTopic.val]||[];
  1608. if(ci.length ==3)
  1609. ci = ci.replace(/(.)/g,'$1$1');
  1610. colr[i] ='#'+ ci;
  1611. pastelColors.push(pastel(colr[i]) );
  1612. }
  1613. return colr;
  1614. },
  1615. pastelColors =[]
  1616. ,authorColors = hS.colorStyle2.val *2 + hS.colorStyle1.val
  1617. ,colors = prepColors(scheme['sch'+ (authorColors -(authorColors?1:0)) ]) //цветовая схема (8/20/16 цветов)
  1618. //'pastelColors'.wcl(pastelColors)
  1619. ,ge2Color = colors[colors.length -1] //цвет кнопок для авторов без избранных цветов, но имеющих 2 и более ответа
  1620. ,pastelGe2Color = pastelColors[pastelColors.length -1]
  1621. ,c = comms, n =20, tp = topic
  1622. ,colorTAH ='#fee' //'#fdd' topicAuthorHighlight
  1623. ,colorTAHnew ='#f5ecf5' //'#efd9ef' topicAuthorHighlight New
  1624. ,oneLineHeight =25
  1625. ,newEntity = $q('.comment_item >.comment_body >.message', topic) //новая вёрстка комментариев
  1626. ,topicAuthor = $q('.post .infopanel .author a', topic) //===место автора топика
  1627. ,authorTopicName = topicAuthor ? topicAuthor.innerHTML :'(без автора)';
  1628. (function(s){
  1629. var replyMsgs = $qA('.message, .comment_item >span.text', c) //===сообщения - ответы
  1630. ,hght
  1631. ,authors =[{name: authorTopicName, n: 0}];
  1632. if(!replyMsgs || !replyMsgs.length)
  1633. replyMsgs = $qA('.comment_item', c);
  1634. for(var i in replyMsgs){if(replyMsgs[i].attributes){
  1635. var replyMI = replyMsgs[i]
  1636. ,replyMP = replyMI.parentNode
  1637. ,repInfo = replyMP && $q('.info', replyMP)
  1638. ,replyButt = replyMP && (next('^reply$', replyMI) || $q('a.reply_link',replyMP) || $q('a.reply',replyMP) ) //===поиск кнопки ответа
  1639. ,author = $q('a.username', replyMP); //===поиск автора сообщ.
  1640. if(author && $q('a', author))
  1641. author = $q('a', author);
  1642. var authorCommName = author && author.innerHTML ||'===';
  1643. //'author'.wcl(replyMP, author, replyButt)
  1644. hght = replyMI.offsetHeight;
  1645. if(!hght) continue;
  1646. s += hght ||0; //контроль генерации блока
  1647. if(authorColors){
  1648. if(replyButt && replyButt.tagName !='A')
  1649. replyButt = $q('a.reply_link',replyButt) || $q('a.reply',replyButt);
  1650. //'replyMI, replyButt'.wcl(replyMI, replyButt, replyMP)
  1651. //'BUTT'.wcl(replyButt, authorColors || hS.listAuthorsComms.val, replyMP.className)
  1652. if(!replyButt && authorColors && next('^reply$', replyMI)){ //для неавторизованных - фантомные "ответы" для подсветки кнопок
  1653. replyButt = $e({el:'.reply', blck: replyMP
  1654. ,ht:'<a class="reply_link" href="#" onclick="return!1">ответить</a>'});
  1655. //wcl('reply_fake')
  1656. }
  1657. for(var j = authors.length -1; j >=0; j--) //===сбор данных об авторах
  1658. if(authorCommName == authors[j].name){authors[j].n++; break;}
  1659. if(j < 0)
  1660. authors[authors.length] ={name: authorCommName, n: 1};
  1661. }
  1662. if(authorCommName == authorTopicName && (replyButt) ){ //===подсветка комментариев автора топика
  1663. if(hS.colorAuthorTAH.val){
  1664. repInfo.style.backgroundColor = /is_new/.test(repInfo.className) ? colorTAHnew : colorTAH;
  1665. repInfo.className +=' is_topicAuthor';
  1666. }
  1667. }
  1668. if(authorCommName == authorTopicName && hS.colorAuthorTopic.val){ //цвет авторов по частоте сообщений
  1669. author.style.backgroundColor = pastelColors[0] || pastelGe2Color;
  1670. //author.style.color ='#569';
  1671. if((newEntity) && /message/.test(replyMI.className)){
  1672. replyMI.style.borderLeftWidth ='4px';
  1673. replyMI.style.borderLeftStyle ='solid';
  1674. replyMI.style.marginLeft ='-4px';
  1675. replyMI.style.borderLeftColor = colors[0] || ge2Color;
  1676. }
  1677. }
  1678. if(replyMP)
  1679. var infoButt = prev('info', replyMI);
  1680. if(hS.noAva.val && infoButt) //не показывать уменьшенные аватары
  1681. $q('.avatar', infoButt).style.opacity =0;
  1682. //'replyMsgs'.wcl(replyMI, replyMsgs.length, i)
  1683. //'authorCommName,'.wcl(authorCommName, authors.length, j)
  1684. if(hS.brAsBlock.val) //замена BR и BR-BR на прослойки
  1685. blockBrs(replyMI);
  1686. if(replyButt)
  1687. replyButt.innerHTML = replyButt.innerHTML.replace(/(ответить|комментировать)/, hS.shortReply.val && hght < oneLineHeight ?'отв':'ответ'); //ес.одна строчка; меньше, чем примерно 18 пикс - сокращение высоты кнопок
  1688. //'offsetHeight'.wcl(hS.shortReply.val && replyMI.offsetHeight)
  1689. //=== точка "Каждый комментарий (свои и добавленные)" ===
  1690. byTextNodes(replyMI, haReplace); // обработка слов комментария
  1691. extLinks(replyMI);
  1692. }}
  1693. if(s < 20 && replyMsgs.length && --n >0){ win.setTimeout(arguments.callee, 200); return;} //ожидание генерации DOM-ветви TODO ош.с нулевой выс.
  1694. if(authorColors){ //===== раздача цветов =====
  1695. var k =1, s =' <tt style="background:'+ colors[0] +'" title="'+ authors[0].name +'">'+ authors[0].n +'</tt> '; //счёт цветов
  1696. for(i =1; i < authors.length; i++){ //раздача цветов по количеству сообщений - сортировка
  1697. var nMax =0, betterAuthor =0, aLen = authors.length;
  1698. for(j =0; j < aLen; j++)
  1699. if(authors[j].n > nMax && !authors[j].choice && authors[j].name != authorTopicName){
  1700. nMax = authors[j].n;
  1701. betterAuthor = j;
  1702. }
  1703. authors[betterAuthor].color = colors[k];
  1704. authors[betterAuthor].pColor = pastelColors[k];
  1705. s +='<tt style="background:'+ (colors[k] || (authors[betterAuthor].n >=2 ? ge2Color :'#f2f2f2'))
  1706. +'" title="'+ authors[betterAuthor].name +'">'+ authors[betterAuthor].n +'</tt> ';
  1707. authors[betterAuthor].choice = k++; //выбран наибольший параметр "n" из оставшихся
  1708. if(k >= colors.length +3) break; //ограничение по длине списка
  1709. }
  1710. s +=(authors.length > colors.length +3 ?'<i>...</i>':'')+'<tt>('+ authors.length +')</tt>';
  1711. authors[0].color = colors[0];
  1712. authors[0].pColor = pastelColors[0];
  1713. //for(i =0; i < authors.length; i++)
  1714. // 'authors'.wcl(authors[i].n+' '+authors[i].name+' '+(authors[i].choice||''))
  1715. for(i in replyMsgs){ //2-й проход и расстановка цветов
  1716. var replyMI = replyMsgs[i]
  1717. ,replyMP = replyMI.parentNode;
  1718. //'replyMp'.wcl(replyMP, i)
  1719. if(!replyMP) continue;
  1720. var author = newEntity && $q('a.username', replyMP); //===поиск автора сообщ.
  1721. if(author && $q('a', author))
  1722. author = $q('a', author);
  1723. var authorCommName = author && author.innerHTML ||'===';
  1724. //'author.innerHTML'.wcl(author && author.innerHTML, authors.length)
  1725. if(!hS.colorAuthorTopic.val)
  1726. authors[0].color = colorTAH;
  1727. for(var j = authors.length -1; j >=0; j--){ //счёт всех авторов
  1728. //'=='.wcl(j, authorCommName == authors[j].name , (authors[j].choice || authors[j].n >=2))
  1729. if(authorCommName == authors[j].name && (authors[j].choice || authors[j].n >=2)){ //...и избранный цвет
  1730. var replyButt = replyMP && (next('^reply$', replyMI) || $q('a.reply_link',replyMP) || $q('a.reply',replyMP) );
  1731. //'replyButt'.wcl(replyButt, authorCommName)
  1732. if(replyButt && replyButt.tagName !='A')
  1733. replyButt = $q('a.reply_link',replyButt) || $q('a.reply',replyButt);
  1734. if(replyButt)
  1735. replyButt.style.backgroundColor = authors[j].color || ge2Color;
  1736. if(author){ //цвет авторов по частоте сообщений
  1737. author.style.backgroundColor = (author.parentNode.className=='info'? authors[j].color : authors[j].pColor) || ge2Color;
  1738. }
  1739. var isMsg = /message/.test(replyMI.className);
  1740. if(isMsg){
  1741. replyMI.style.borderLeftStyle ='solid';
  1742. replyMI.style.marginLeft ='-4px';
  1743. }
  1744. replyMI.style.borderLeftColor = authors[j].pColor || ge2Color;
  1745. replyMI.style.borderLeftWidth ='4px';
  1746. break;
  1747. }
  1748. }
  1749. }
  1750. }
  1751. var o = $q('.comments_list .title', tp) || $q('.comments.c2 .title', tp)
  1752. ,oL = o && $q('label', o)
  1753. ,oL2 = o && $q('label + label', o);
  1754.  
  1755. if(hS.shortSubscribe.val && oL){ //укорочение надписи "подписаться на комментарии"
  1756. oL.title ='следить за новыми комментариями через почту';
  1757. var aChilds = oL2 && oL.parentNode.childNodes || oL.childNodes;
  1758. for(var i=0; i < aChilds.length; i++)
  1759. if(/(подпи|отсл)/.test(aChilds[i].nodeValue)) aChilds[i].nodeValue ='слеж.';
  1760. for(var i=0; i < oL.childNodes.length; i++)
  1761. if(/почт/.test(oL.childNodes[i].nodeValue)) oL.childNodes[i].nodeValue ='';
  1762. if(oL2){
  1763. oL2.title ='... через трекер';
  1764. for(var i=0; i < oL2.childNodes.length; i++)
  1765. if(/трек/.test(oL2.childNodes[i].nodeValue)) oL2.childNodes[i].nodeValue ='';
  1766. oL2.style.paddingRight ='6px';
  1767. }
  1768. }
  1769. if(hS.listAuthorsComms.val)
  1770. $e({el:'TT', ht: s, apT: o}); //активные комментаторы (с цветами, в заголовке комментариев)
  1771. if(hS.commInfo && hS.commInfo.val){ //=== навигатор по веткам комментариев ===
  1772. var isMail = /\/conversations\//.test(lh)
  1773. ,commInfo = $e({cl:'commInfo', prT: $q('.title', isMail ? c.parentNode : c)})
  1774. ,comRoots = $qA('.comments.c2 >.title, .comments_list >.title, .comments.c2 >.comment_item >.comment_body >.info, .comments_list >.comment_item >.comment_body >.info, #messages .info', c)
  1775. ,branch ={linksTo:[]};
  1776. if(comRoots.length){
  1777. for(var i in comRoots){ var cRI = comRoots[i]; if(cRI.attributes){ //по корневым веткам
  1778. var nCom = $qA('.info', isMail ? cRI.parentNode : cRI.parentNode.parentNode) //число ответов в корневой ветке
  1779. ,nP =0
  1780. ,nM =0
  1781. ,nSym =''
  1782. ,hash = cRI.getAttribute('rel') //якорь корневого коммента
  1783. ,linksRoot = $e({cl:'links root'})
  1784. ,imgsRoot = $e({cl:'imgs root'})
  1785. ,nImg =0
  1786. ,hrf = hash ?'#comment_'+ hash :'#comments';
  1787. for(var j in branch.linksTo){
  1788. $e({el:'a'
  1789. ,cl:'nx branch'
  1790. ,ht:'>'
  1791. ,at:{href: hrf, title:'следующая ветка'}
  1792. ,aft: branch.linksTo[j]
  1793. });
  1794. }
  1795. //'nCom'.wcl(nCom.length, cRI)
  1796. branch.linksTo =[];
  1797. for(var j in nCom){ var nCJ = nCom[j]; if(nCJ.attributes){ //по комментам
  1798. var nCJS = $q('.mark .score', nCJ);
  1799. if(nCJS){
  1800. var nS = nCJS.title && nCJS.title.match(/\d+/g);
  1801. if(nS.length ==3){
  1802. nP += Number(nS[1]);
  1803. nM += Number(nS[2]);
  1804. }}
  1805. var msg = $q(isMail?'.text':'.message', nCJ.parentNode);
  1806. if(msg){
  1807. nSym += msg.innerHTML;
  1808. var kLnk = $qA('a', msg) //подсписок ссылок
  1809. ,kImg = $qA('img:not(._noAddOwnView)', msg); //подсписок рисунков
  1810. for(var k in kLnk){ var kLK = kLnk[k]; if(kLK.attributes){ //ссылки
  1811. if(!$q('img:not(._noAddOwnView)', kLK) )
  1812. $e({el:'a', cl:'lnk'
  1813. ,at:{title: kLK.href.replace(/^https?:\/\/(habrahabr\.ru)?/,'')
  1814. ,href: kLK.href, target:'_blank'}
  1815. ,apT: linksRoot});
  1816. }}
  1817. for(var k in kImg){ var kIK = kImg[k]; if(kIK.attributes){ //рисунки
  1818. if(kIK.parentNode.tagName !='A')
  1819. $e({el:'a', cl:'imgL'
  1820. ,at:{href: kIK.src, target:'_blank'}
  1821. ,apT: imgsRoot});
  1822. else //рисунок с внешней ссылкой
  1823. $e({el:'a', cl:'imgLink'
  1824. ,at:{href: kIK.parentNode.href, target:'_blank'}
  1825. ,apT: imgsRoot});
  1826. nImg++;
  1827. }}
  1828. }
  1829. var toPar = $q('time', nCJ);
  1830. if(!toPar)
  1831. toPar = $q('.to_parent', nCJ);
  1832. if(!toPar)
  1833. toPar = $q('.to_chidren', nCJ);
  1834. if(toPar && hash){ //переход к предыдущей ветке - кнопка
  1835. if(branch.href)
  1836. branch.linksTo.push( $e({el:'a'
  1837. ,cl:'prv branch'
  1838. ,ht:'<'
  1839. ,at:{href: branch.href, title:'предыдущая ветка'}
  1840. ,aft: toPar
  1841. }) );
  1842. }
  1843. }}
  1844. branch.href = hrf;
  1845. if(nImg==0)
  1846. imgsRoot.style.display ='none';
  1847. var overLink = $e({cl:'overLink', apT: commInfo})
  1848. ,hLnk ={el:'a', cl:'root'
  1849. ,at:{href: hrf}
  1850. ,apT: overLink }
  1851. ,nVLink = $e(hLnk) // N's-Votes-link
  1852. ,pMLink = $e(hLnk); //plus-minus-link
  1853. $e({el: linksRoot, apT: overLink});
  1854. $e({el: imgsRoot, apT: overLink});
  1855. if(comRoots.length ==1 && nCom.length ==0)
  1856. break;
  1857. if(nP !=0 || nM !=0){ //минусы +плюсы
  1858. var pluses = boxBuild(nP,'nP',pMLink,'+')
  1859. ,minuses = boxBuild(nM,'nM',pMLink,'-');
  1860. //'m-p'.wcl(parseInt(minuses.style.width), parseInt(pluses.style.width))
  1861. if(parseInt(minuses.style.width) + parseInt(pluses.style.width) > 43){
  1862. var hP = parseInt(pluses.style.height)
  1863. ,hM = parseInt(minuses.style.height)
  1864. minuses.style.marginBottom ='-'+ (hM -3) +'px';
  1865. if(hM - hP -3 >0)
  1866. pluses.style.marginBottom = (hM - hP -3) +'px';
  1867. pMLink.style.lineHeight =overLink.style.lineHeight ='4px';
  1868. }
  1869. }else
  1870. pMLink.style.display ='none';
  1871. //сообщения + объём
  1872. var strings = boxBuild(Math.floor((nSym.length +75)/150),'nLin',nVLink,'"длинных строк" '); //вставка блока графики по объёму байтов
  1873. var msgs = boxBuild(nCom.length,'nCom',nVLink,'Сообщений в ветке: '); //--по числу ответов в ветви
  1874. //'strings'.wcl(parseInt(strings.style.width), parseInt(msgs.style.width))
  1875. if(parseInt(strings.style.width) + parseInt(msgs.style.width) > 43 -4){
  1876. msgs.style.marginBottom ='-'+ (parseInt(msgs.style.height) -3) +'px';
  1877. nVLink.style.lineHeight = overLink.style.lineHeight ='4px';
  1878. }
  1879. if(i==0){ //общий счётчик
  1880. overLink.style.marginTop ='-'+ Math.max(parseInt(msgs.style.height)+28, parseInt(strings.style.height)+28, minuses && (parseInt(minuses.style.height)+28), pluses && (parseInt(pluses.style.height)+28) ) +'px';
  1881. overLink.style.marginBottom ='22px';
  1882. nVLink.style.verticalAlign = pMLink.style.verticalAlign
  1883. = linksRoot.style.verticalAlign= imgsRoot.style.verticalAlign ='bottom';
  1884. overLink.title ='комментариев: число, объём (160-симв. строк), минусов, плюсов, ссылки, рисунки';
  1885. }
  1886. }}
  1887. handlImgViews(commInfo,'.commInfo a[href$=".jpg"],.commInfo a[href$=".jpeg"],.commInfo a[href$=".png"],.commInfo a[href$=".gif"]'); //просмотр картинок
  1888. }
  1889. }
  1890. if(hS.shortDates.val)
  1891. datesShorten(c,'.info time');
  1892. })(0);
  1893. },
  1894. boxBuild = function(n, cl, el, def){ //выдача DOM-объекта (блока) по правилам построения инфографики
  1895. // (блок dim*dim есть 150 символов или 1 элемент; ar[ity]-кратное расширение влево, затем вниз)
  1896. var dim = 4
  1897. ,ar = 4
  1898. ,logN2 = 2/ ar /Math.LN2 // 1/log4(1)
  1899. ,log = Math.log(n) *logN2 // log4( n )
  1900. ,flor = Math.floor(log) // [log4( n )]
  1901. ,flor12 = Math.floor((flor +1)/2 )
  1902. ,flor2 = Math.floor(flor /2)
  1903. ,growHoriz = flor12 == flor2 ?1:0 // делать рост по горизонтали/вертикали
  1904. ,fract = log - flor // { log4( n ) }
  1905. ,w = Math.pow(ar, flor12)
  1906. ,h = Math.pow(ar, flor2);
  1907. //'commRootBlks'.wcl(w +' '+ h +' '+ n +' '+ Math.floor(dim*( w + growHoriz*(n-w)/ w )) +' '+ Math.floor(dim*( h + (1- growHoriz)*(n-h)/ w )));
  1908. return $e({cl: cl
  1909. ,cs:{width: Math.floor(w ? dim*( w + growHoriz*(n -w* w)/ w ): 2)+'px'
  1910. ,height: Math.floor(w ? dim*( h + (1- growHoriz)*(n -h* w)/ w ): 3)+'px' //деление на 4 учтено через flor12
  1911. ,color:'#dd3'
  1912. ,verticalAlign:'top'}
  1913. //,ht: '*'
  1914. ,at:{title: def + n}
  1915. ,prT: el
  1916. });
  1917. },
  1918. imgWait = '<img src="data:image/gif;base64,R0lGODlhEAAQAMMGAG6WysLS6pKy2ubu9rXK5oKi0v7+/t7m8p622naezsra7oqq1qa+3u7y+gAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAOACwAAAAAEAAQAAAETNDJSau91SzAgSSEYWmdlADFkBWlo7CFOBHoNhksQW2KRimABYWDIU6MGaSDR2G4ghRa7MjIUXAohaQzpQxYiS1nIbuCxOMyZs2eRAAAIfkECQoADgAsAgAAAAwAEAAABFXQyZGCvNgVsE52BpEA5IANGwkwYANuRQAkjbEUIYA7C/EChAVAISEWOaQPSAUwKElCo8Go4BB0zuCPYCiwGqMAzOlyMJgF02WgSnA/B2FBeQkk1I4IACH5BAkKAA4ALAIAAAAMABAAAART0MnpmqDYBaCoIQsAJKMhDYWoioRjpEV3iElHAIXp3IwedhLCwKW4ATKSFdLAUpgGLYkCsJAYGIDoK+tQkAAHgwJmMq5wQxfpuyDopIAAciJoICMAIfkECQoADgAsAgABAA0ADQAABEXQyUmdMdKQBcAi13I4Q9GdQMEdhlkokmJ2B5FiGUcTCTzptIpQcigWcRUUg6JIEByn5aQFeJ5eF9kNipihCgPJUqP7ICMAIfkECQoADgAsAAACABAADAAABFTQSWfIAmARM3srWAgUQzcxhcIpYMFNJdUZIOGUB8A0phMAiULCcQFuJIoiJvALLRQTQgKzcASngV6DATjcHITRS2LgxMgtlYG1GMNAohGvVylq3BEAIfkECQoADgAsAAACABAADAAABFPQyUkAWMTMaUhwimUVw6YkQGJoYAEUrCACzGa4hNQEqFVOocXGciDkhgAkS2I8WDYLgGIzECUCDeZr6WDMBJLbS6FZoRLTycAlmioymzAhCjhuIgA7" title="подгрузка содержимого...">',
  1919. openInFrame = function(ev, t, blck, Li){ //открывать в фрейме (если ссылка не в фрейме)
  1920. if(ev && ev.shiftKey ^ ev.ctrlKey){
  1921. t.target ='_blank'; //в новой вкладке, если Ctrl+click
  1922. win.setTimeout(function(){t.target ='';},200);
  1923. return;
  1924. }
  1925. if(ev && ev.shiftKey && ev.ctrlKey){
  1926. $pd(ev);
  1927. location.href = t.href;
  1928. return!1;
  1929. }
  1930. try{
  1931. var name ='hA_userinfoView'
  1932. ,uFrm = //document.getElementById(name);
  1933. $e({el:$q('#'+ name)||'iframe'
  1934. ,at:{id: name, name: name, src:''}
  1935. ,cs:{position:'fixed', width: h.uFrmWid, height:'200px', top:'200px', borderWidth:0, backgroundColor:'#f4f6f7', zIndex: 101}
  1936. ,apT: document.body
  1937. });
  1938. if(!uFrm){
  1939. /*uFrm = document.createElement("iframe");
  1940. uFrm.id = uFrm.name = name;
  1941. uFrm.src ='';
  1942. uFrm.style.position ='fixed'; uFrm.style.height ='200px'; uFrm.style.width = h.uFrmWid; uFrm.style.borderWidth =0;
  1943. uFrm.style.backgroundColor ='#f4f6f7';
  1944. uFrm.style.zIndex = 101; uFrm.style.top ='200px';
  1945. document.body.appendChild(uFrm);*/
  1946. if(isChrome)
  1947. win.setInterval(function(){ //опрос ширины фрейма по сообщению изнутри
  1948. var frameWidth = uFrm.contentDocument && uFrm.contentDocument.body && uFrm.contentDocument.body.getAttribute('frameWidth');
  1949. if(frameWidth && uFrm.style.display =='block')
  1950. uFrm.style.width = frameWidth;
  1951. },250);
  1952. }}catch(er){'Err_authorClicks: '.wcl(er)}
  1953. var dFrm = $q('.imgWait');
  1954. if(!dFrm) dFrm = $e({cl:'imgWait'
  1955. ,cs:{position:'fixed',width:'20px', height:'20px', zIndex: 101
  1956. , top: Math.floor(win.innerHeight /2 +3) +'px'}
  1957. ,ht: imgWait
  1958. ,apT: document.body});
  1959. else
  1960. $x(dFrm.style, {display:'block',top: Math.floor(win.innerHeight /2 +3) +'px'} );
  1961. uFrm.style.height = Math.floor(win.innerHeight /2 -20) +'px';
  1962. win.setTimeout(function(){dFrm.style.display ='none';}, 2700);
  1963.  
  1964. var srchField = $q('#search_form input[name="q"]')
  1965. ,noInFrame = Li && srchField && Li.parentNode == srchField.parentNode && srchField.getAttribute('keyLast')==13 //для непоказа фрейма при открывании в том же окне
  1966. ,ifTop = ev.clientY > win.innerHeight /2;
  1967. //'Li'.wcl(ev.clientY)
  1968. uFrm.style.top = ifTop ?'19px':'';
  1969. uFrm.style.bottom = ifTop ?'':'-2px';
  1970. if(h.uFrmPrevClick != t.href) //Url последней кликнутой ссылки, загруженной в фрейм
  1971. uFrm.src = t.href;
  1972. uFrm.style.display = (h.uFrmPrevClick == (t.href ||1) && uFrm.style.display =='block'
  1973. || noInFrame) && !/\/edit\//.test(t.href) ?'none':'block';
  1974. h.uFrmPrevClick = t.href;
  1975. if(Li && Li != blck)
  1976. ev && $pd(ev);
  1977. },
  1978. openInFrmHndl = function(blck, Li){ //Li={href:ссылка, открываемая в фрейме}; {href:1} - признак откр.в фрейме со всеми данными в blck, +блокирование умолчательного поведения клика
  1979. var a = Li.href.match(/(http:\/\/)(\w+)\.(habrahabr\.ru)(.*)/) //замена 3-го уровня на 2-й
  1980. ,c =0 //TEST
  1981. ,linNext;
  1982. if(a && a.length && a[2] !='m')
  1983. Li.href = a[1] + a[3] +'/users/'+ a[2] + a[4];
  1984. else{
  1985. a = Li.href.match(/(\/favorites\/)(.*)/); //замена в избранном //TODO .* -- .+
  1986. //'favorites'.wcl(h.uName , h.uName2, a, Li.next)
  1987. if(a && a.length){
  1988. Li.href = '/users/'+ (linNext? h.uName2 : h.uName) + a[1] + (a[2] ? a[2] :'');
  1989. linNext =1; //чтобы первый линк на избранное был на своё (если авторизован)
  1990. }
  1991. }
  1992. a = Li.href.match(/(http:\/\/)(habrahabr\.ru)(\/users\/|\/job\/|\/tag\/)([^\/]+)(.+)/); //обработчик клика на юзере | */job/7671/ | теги -- открывать в фрейме
  1993. //'a'.wcl(a, blck, Li, !/tab_user/.test(Li.className) );
  1994. if(a && a.length >1 )
  1995. c++; //TEST
  1996. if(a && a.length ==6 && (a[5]=='/'|| a[5]=='/favorites/') && !inFrame && !/tab_user/.test(Li.className)
  1997. || RegExp(SHRU+'/settings/').test(Li.href) || Li.href==1){
  1998. if(Li.href==='1')
  1999. Li = blck; //вешать на кнопку
  2000. Li && Li.addEventListener('click', function(ev){openInFrame(ev, this, blck, Li)},!1);
  2001. //'writeListener'.wcl(a && a.length ==6 && (a[5]=='/'|| a[5]=='/favorites/') && !inFrame
  2002. }
  2003. },
  2004. authorClicks = function(blck){ //расст.обраб.кликов по ссылкам; blck - блок, в кот.ищут ссылки
  2005. if(!blck) return;
  2006. var linx = $qA('a[href]',blck); //все ссылки в блоке
  2007. //'aa'.wcl(blck, linx)
  2008. if(linx || blck.tagName =='INPUT'){
  2009. if(blck.tagName =='INPUT') //для подвешивания открывания поиска в фрейме на кнопке поиска
  2010. linx =[{href:'1'}];
  2011. for(var i in linx)
  2012. if(linx[i].href)
  2013. openInFrmHndl(blck, linx[i]);
  2014. }
  2015. if(win.opera || /Firefox\/[345]\./.test(navigator.userAgent)){
  2016. if(win.addKarmEvent) //показ кармы, если установлен HabraKarmaView.user.js
  2017. win.addKarmEvent(blck);
  2018. if(win.habrPercentageRing)
  2019. win.habrPercentageRing(blck);
  2020. }else
  2021. evtChangeDom(blck); //CustomEvent в блоке
  2022. },
  2023. getHourMins = function(D){
  2024. var date = D || new Date;
  2025. return date.getHours() +':'+ (date.getMinutes()<=9?'0':'') + date.getMinutes();
  2026. },
  2027. showContent = function(ev){ //подгрузить и показать статью
  2028. if(ev.ctrlKey ^ ev.shiftKey) return;
  2029. var URL = location.href
  2030. ,isSearchPage = /\/search/.test(URL)
  2031. ,tLink = this.tagName.toUpperCase() !='SPAN' && this || this.parentNode
  2032. ,inFooter = parents('rotated_posts', tLink)
  2033. ,topic = parents('^post($| )', tLink) || inFooter //топик или блок в футере
  2034. ,info2 = $q('.infopanel', topic)
  2035. ,clickComments = /comments|infopanel/.test(this.parentNode.className); //признак клика по ссылке/кнопке комментариев
  2036. //'~~topic'.wcl(tLink, topic, info2)
  2037. if(!tLink.href && (clickComments || parents('habracut', this)) ) //поправка для малых правых кнопок
  2038. tLink.href = $q('a', prev('comments', this) || parents('habracut', this) ).href;
  2039. var commLink = $q('.comments a', info2);
  2040. if(/ link/.test(topic.className)) //сменить ссылку для подгрузки (на ту, которая в комментариях)
  2041. tLink = commLink;
  2042. var topicTitle = $q('.post_title', topic) || parents('^grey$', tLink); //заголовок статьи
  2043. //if(inFooter && !/infopanel/.test(this.parentNode.className) ) //нажатая кнопка в футере
  2044. // $q('span.inln',tLink).className +=' content';
  2045. if(inFooter && !/^post($| )/.test(inFooter.className))
  2046. inFooter.className ='post content_left '+ inFooter.className;
  2047. if(!/blk2nd/.test(this.className)){ //защита от повторного клика
  2048. this.setAttribute('class', this.className +' blk2nd'); //блокировка повторного клика
  2049. try{
  2050. var cnte = $qA('.content', topic)
  2051. ,topicHaCut = $q('a.habracut', topic)
  2052. ,commC2 = $q('.comments.c2', topic); //комментарии, если есть с прежней подгр.
  2053. //'cnte'.wcl(this.tagName.toUpperCase() !='SPAN', this, this.parentNode, cnte[0],cnte[1],topicHaCut, commLink);
  2054. //'commC2=='.wcl(commC2 && getComputedStyle(commC2, null).getPropertyValue('display'))
  2055. var wasComms = commC2 && getComputedStyle(commC2, null).getPropertyValue('display') =='none'; //"были ли показаны комментарии"
  2056. if(cnte.length >1 && !clickComments && !ev.ctrlKey && !ev.shiftKey){ //просто показать ранее загруженное
  2057. cnte[0].style.display ='none';
  2058. $q('.btnBack:not(.showComm)', topic).style.display //показ верхней кн."Свернуть"
  2059. = cnte[1].style.display //показ статьи
  2060. = $q('.btnBack.n2', topic).style.display ='block'; //показ нижней кн."Свернуть"
  2061. }
  2062. //'commC2,clickComments,wasComms'.wcl(commC2, '/', clickComments, '/', wasComms)
  2063. var isBtnBack = $q('.showComm.btnBack:not(.inln)', topic)
  2064. ,isBtnBack2 = $q('.showComm.btnBack.n2', topic);
  2065. if(commC2 && clickComments && wasComms && !ev.ctrlKey && !ev.shiftKey
  2066. && isBtnBack && isBtnBack2){ //показ комментариев
  2067. isBtnBack.style.display = commC2.style.display = isBtnBack2.style.display = 'block';
  2068. if(/ noShowYet/.test(commC2.className)){ //корректировки отображения после вывода:
  2069. //'>By NoShowYet'.wcl('');
  2070. correctCommentsAfter(commC2, topic); //кнопки "Отв"; расцветка авторов; поправки дат
  2071. authorClicks(commC2); //расст.обраб.кликов по ссылкам
  2072. //'authorClicks2'.wcl(commC2, cnte[1])
  2073. authorClicks(cnte[1]);
  2074. commC2.className = commC2.className.replace(/ noShowYet/,'');
  2075. handlImgViews(commC2); handlImgViews(cnte[1]); //показ увеличенных картинок
  2076. }
  2077. }
  2078. //'cnte=='.wcl(cnte, topic, $q('.btnBack.n2', topic))
  2079. if(cnte.length <=1 || ev.ctrlKey){ //подгрузить или пере-подгрузить страницу по ссылке - только при необходимости нарисовать содержимое (контент .content.c2 и .comments.c2)
  2080. this.innerHTML = imgWait + this.innerHTML; //сигнал об ожидании Ajax
  2081. var xhr = new window.XMLHttpRequest()
  2082. ,reGet = ev.ctrlKey && ev.shiftKey; //режим пере-подгрузки
  2083. if(reGet){ //другой признак пере-подгрузки - $q('.btnBack.n2', topic)
  2084. var cont = inFooter ? $q('.contentCell', inFooter) : topic;
  2085. cont.removeChild($q('.content.c2', cont));
  2086. cont.removeChild($q('.comments.c2', cont)); //контент удалён
  2087. xhr.wasArrows =1; //(стрелки были - и остались)
  2088. }
  2089. //topicTitle && 'tLink'.wcl(topicTitle, tLink.href, topicTitle.link);
  2090. var url = topicTitle && (tLink.href || commLink && commLink.href || topicTitle.link);
  2091. //-обход заголовка-ссылки, не-ссылок, отсутствия ссылки на комментарии
  2092. xhr.open('GET', url.replace(/_/g,'%5F'), true); //странно, но "_" не переваривает (FF)
  2093. xhr.link = this; //активный элемент клика мыши
  2094. xhr.onreadystatechange = function(){ //===показ статьи===
  2095.  
  2096. if(this.readyState !=4) return;
  2097. if(inFooter && !$q('.contentRow',inFooter)){ //область контента-c2 в над-футере для подгрузки
  2098. var cntRow = $e({cl:'contentRow'
  2099. ,cs:{display:'table-row', backgroundColor:'#fff'}
  2100. ,aft: $q('.rotated_posts .rotTRow') });
  2101. $e({cl:'contentCell', el:'td'
  2102. ,cs:{display:'table-cell', padding:'0 13%'}
  2103. ,at:{colspan:3}
  2104. ,ht:'<div class=content></div><div class=infopanel><span class="showComm btnBack inln" title="комментарии; Ctrl+Shift - пере-подгрузка">&rarr;</span></div><div class=clear></div>'
  2105. ,apT: cntRow});
  2106. topic = inFooter = $q('.contentCell', cntRow);
  2107. $q('.showComm', topic).addEventListener('click',showContent,!1);
  2108. }
  2109. xhr.link.removeChild($q('img', xhr.link)); //снять сигнал об ожидании Ajax
  2110. var tContent = !inFooter
  2111. ? cnte[0] || $q('.hubs', topic) || $q('.title', topic)
  2112. : $q('.contentCell .content', topic) //начало статьи (аннотация)
  2113. ,contHeight = tContent.offsetHeight //для будущей подкрутки текста при сворачивании статьи
  2114. ,showComm = clickComments && !wasComms || !topicHaCut && !isSearchPage && !inFooter;
  2115. //'xhr.link'.wcl(xhr.link, tContent)
  2116. //'clickComments'.wcl(clickComments, !wasComms, !topicHaCut);
  2117. /*var state = new defineState();// ALLHIDE;
  2118. stateRoll(state, 0, topicHaCut);*/
  2119. //wcl(tContent.style.display,'/', cnte[1] && cnte[1].style.display,'/', wasComms, 'showComm='+showComm, topicHaCut)
  2120. if(!showComm || inFooter)
  2121. tContent.style.display ='none'; //скрыть начало статьи
  2122. var contEdge = $q(!xhr.wasArrows ?'.tags':'.btnBack.n2', topic); //контекст, перед кот.ставится содержание
  2123. //'contEdge2'.wcl(contEdge, !xhr.wasArrows) || info2; //если нет контекста (блока с тегами)- ориентир.на блок с подписями
  2124. //'contEdge'.wcl(contEdge)
  2125. //=== точка "ajax-парсинг страницы" ===
  2126. var conte = this.responseText.match( // ====== парсинг страницы, шаблон ======
  2127. /<div class="content html_format">([\s\S]*?)<div class="clear"><\/div>\s+?<\/div>[\s\S]+?(<ul class="tags">|<div class="tags">)\s*([\s\S]*?)\s*(<\/div>|<\/ul>)[\s\S]*?<div class="infopanel/m) //вся статья (до тегов или подписи)
  2128. ,tagPars = conte && conte.length ==5 ? conte[3] :''; //вытаскивание тегов
  2129. //'conte~~'.wcl(conte.length, conte, info2)
  2130. conte = conte ? conte[1] :''; //устранение ошибки пустого ответа
  2131. conte = haReplace(conte); // обработка слов статьи (без комментариев)
  2132. var len2 = !conte ?'1': conte.replace(/<a name="habracut"><\/a>(.*|\r|\n)*/m,'') //статья до ката
  2133. //чтобы было "0%" при отсут.текста
  2134. ,date = getHourMins()
  2135. ,percnt = Math.floor((1- len2.length / (conte.length+1))*100)
  2136. ,percent = '&nbsp;'+ percnt +'%, <i>'+ date +'</i>';
  2137. if(!xhr.wasArrows){ //"Свернуть статью" (полоса внизу)
  2138. var btnBackN2 = $e({cl:'btnBack n2'
  2139. ,ht:'<i>&larr; Свернуть</i><div class="percent" style=float:right>/'+date+'/</div>'
  2140. ,at:{rel: contHeight}
  2141. ,on:{click: hideC2}
  2142. ,aft: tContent});
  2143. if(showComm)
  2144. $q('.btnBack:not(.showComm)', topic).style.display ='none';
  2145. }else //...или показать её
  2146. $q('.btnBack:not(.showComm)', topic).style.display ='block';
  2147. var contC2 = $e({cl:'content c2' // ==== блок с полной статьёй (контентом)
  2148. ,ht: /<a name="habracut"><\/a>/.test(this.responseText)
  2149. ?'<div style="background: #efeff2; padding: 2px 3px 2px 7px; margin: -2px -3px -2px -7px; position: relative">'
  2150. + conte.replace(/<a name="habracut"><\/a>/,'</div>')
  2151. :(!topicHaCut || conte.length >20 || clarif.length >20 ? conte + clarif :'<i style="color: #999">(пустой блок)</i>')
  2152. ,aft: tContent }); //(-бывает, что ката в результирующем блоке нет, а в начальном есть)
  2153. extLinks(contC2);
  2154. authorClicks(contC2); //расст.обраб.кликов по ссылкам
  2155. handlImgViews(contC2); //показ увеличенных картинок
  2156. if(showComm)
  2157. contC2.style.display ='none';
  2158. //wcl('trace_00')
  2159. if(!xhr.wasArrows){
  2160. var btnBack = $e({cl:'btnBack'
  2161. ,ht:'<i>&larr; Свернуть</i> <div class="percent"></div>'
  2162. ,on:{click: hideC2} //"Свернуть статью" (полоса вверху)
  2163. ,aft: tContent});
  2164. if(showComm)
  2165. btnBackN2.style.display = btnBack.style.display ='none';
  2166. else if(isChrome){
  2167. var info = $q('.infopanel', topic);
  2168. info.style.top ='-5px';
  2169. }
  2170. }else if(!showComm) //...или показать контент
  2171. contC2.style.display ='block';
  2172. var tags = $q('.tags', topic);
  2173. if(tags)
  2174. tags.style.display ='block';
  2175. else if(tagPars) //добавление тегов из парсинга, если нет исходных
  2176. $e({el:'ul', cl:'tags'
  2177. ,ht: tagPars
  2178. ,bef: info2});
  2179. //'-*-'.wcl(tags, info2)
  2180. //wcl('trace_01')
  2181. //'!xhr.wasArrows ,showComm ,!topicHaCut'.wcl(!xhr.wasArrows ,showComm ,!topicHaCut)
  2182. if(!xhr.wasArrows && showComm && !topicHaCut) //скрыть статью, если надо только комм.
  2183. hideC2.call(tLink);
  2184.  
  2185. var infoDelim = $q('.infopanel +.clear', topic);
  2186. //'infoDelim'.wcl(infoDelim)
  2187. if(!xhr.wasArrows){ //создание кнопки над комментариями
  2188. $e({cl:'showComm btnBack n2' //созд_кноп.сворач_ под комментариями
  2189. ,ht:'<i>&larr; Свернуть</i> <div class="percent0"><i></i> <div class="percent">/'+date+'/</div></div>'
  2190. ,at:{rel: -26}, on:{click: hideComm}
  2191. ,aft: infoDelim});
  2192. var b = $q('.content_left .posts_list .showComm.btnBack:not(.inln)', topic.parentNode);
  2193. if(b) b.style.marginTop ='25px';
  2194. //'zenPresent'.wcl(hS.zenPresent.val, zenChecked, topic.querySelector('.btnBack:not(.inln):not(.n2)'), topic.querySelector('.comments.c2 ul.hentry'))
  2195. var back1 = $q('.showComm.btnBack:not(.inln):not(.n2)', topic);
  2196. if(!zenChecked && !$q('.comments.c2 ul.hentry', topic) && back1 ) //двигать вверх для новых внутренних вёрсток, но не для новых в старом окружении
  2197. back1.style.top ='-22px';
  2198. }
  2199.  
  2200. if(topicHaCut){ //показ процентов при наличии (и возле) ката
  2201. var prevLastInAnno = $q('.prevLastInAnno',topic)
  2202. ,gPercent = $e({cl:'gPercent'
  2203. ,ht:'<div style="width:'+(100 - percnt)+'px"></div>'
  2204. ,on:{click: showContent}
  2205. ,bef: prevLastInAnno});
  2206. $e({cl:'percent'
  2207. ,ht: percent
  2208. ,bef: prevLastInAnno});
  2209. $q('.btnBack:not(.showComm) .percent', topic).innerHTML = '<div class="gPercent"><div style="width:'+(100 - percnt)+'px"></div></div>'+ percent;
  2210. }
  2211.  
  2212. //wcl('trace_02')
  2213. //шаблон, парсинг, комментарии
  2214. var matchComments = this.responseText.match(/<div( class="comments_list " | )id="comments">([\s\S]*?)<\/div>\s+?<div (id|class)="sidebar/m);
  2215. //'matchComments'.wcl(matchComments);
  2216. if(matchComments.length ==4)
  2217. matchComments[1] = matchComments[2];
  2218. if(matchComments && hS.shortReply.val){ //шаблон, парсинг
  2219. matchComments[1] = matchComments[1].replace(/( class="reply_link">[\n\r\s]*<a[\s\S]+?)(ответить|комментировать)(<\/a>[\n\r\s]*<\/)/gm,'$1ответ$3').replace(/id="js-field-holder-with-help"/,'id="js-field-holder-with-help" class="hidden"');
  2220. }
  2221. var comms = correctCommentsBefore(matchComments[1])
  2222. ,comments = matchComments
  2223. ? $e({cl:'comments c2 noShowYet', ht: comms}) : null
  2224. ,replyA = $qA('.reply a',comments); //коррекция комментов для FF3.6
  2225. for(var i in replyA){
  2226. if(!replyA.getAttribute) continue;
  2227. replyA[i].setAttribute('onclick','return!1;'+replyA[i].getAttribute('onclick'));
  2228. replyA[i].addEventListener('click', function(ev){
  2229. if(win.commentForm){
  2230. //wcl(win.commentForm)
  2231. win.commentForm.moveForm('reply_form_'+ this.getAttribute('onclick').replace(/\D/g,''));
  2232. }
  2233. $pd(ev);
  2234. },!1);
  2235. }
  2236.  
  2237. //wcl('trace_021');
  2238. if(!xhr.wasArrows){ //=====вывести комментарии=====
  2239. //topic.appendChild(comments);
  2240. $e({el: comments
  2241. ,aft: infoDelim});
  2242. var id = url.replace(/\/([^\/]*)$/g,'').replace(/\D/g,'');
  2243. //'_comment_id'.wcl(id); //номер сообщения (для оценок и комментариев)
  2244. }else if(reGet){ //или вставка перед нижней кнопкой сворачивания
  2245. topic.insertBefore(comments, $q('.showComm .btnBack.n2', topic));
  2246. }
  2247.  
  2248. //wcl(tContent.style.display,'/', cnte[1] && cnte[1].style.display,'/', wasComms, 'showComm='+showComm, topicHaCut)
  2249. //'trace_03: !xhr.wasArrows, win.commentForm:'.wcl(!xhr.wasArrows, win.commentForm)
  2250. win.commentForm ={};
  2251. if(!xhr.wasArrows){ //&& win.commentForm
  2252. //wcl('trace_04', win.commentForm && win.commentForm.reloadCommentsOnload)
  2253. //addTaButtons(comments); //добавл_ кнопок над полем ввода
  2254. $e({cl:'showComm btnBack'
  2255. ,ht:'<i>&larr; Свернуть</i>'
  2256. ,on:{click: hideComm}
  2257. ,aft: infoDelim });
  2258. //'.percent'.wcl(topic.querySelector('.showComm.btnBack.n2 .percent'))
  2259. $q('.showComm.btnBack.n2 .percent', topic) //====подгрузка комментариев (обработчик)====
  2260. .addEventListener('click', function(ev){
  2261. //wcl('trace_05', win.commentForm && win.commentForm.reloadCommentsOnload)
  2262. var fLoadCommentsBack = win.commentForm && win.commentForm.reloadCommentsOnload;
  2263. win.commentForm && (win.commentForm.reloadCommentsOnload = function(data, contxt){ //коллбек - подгрузка комментариев
  2264. var newComms = data.responseText.match(/<comment comment_id=/gm);
  2265. newComms = newComms ? newComms.length :0; //число комментариев в подгрузке
  2266. //wcl('trace_06', getHourMins() +', '+ newComms)
  2267. $q('.showComm.btnBack.n2 .percent0 i', topic).innerHTML //...и выв.дату подгрузки
  2268. = getHourMins() + ', (+'+ newComms+')';
  2269. //wcl('trace_07')
  2270. win.commentForm && fLoadCommentsBack.call(win.commentForm, data, contxt); //продолжение подгрузки
  2271. //wcl('trace_08')
  2272. });
  2273. if(win.commentForm){
  2274. win.commentForm.targetId = id;
  2275. win.commentForm.targetType ='post';
  2276. win.commentForm.reloadComments(); //-updateComments: добавление новых комментариев; далее это не работает, т.к. Mootools
  2277. $sp(ev);
  2278. }
  2279. },!1);
  2280. if(!isChrome)
  2281. win.tm && win.tm.init && win.tm.init.add(function(){ //дубликат tm.init.add(function(){...}) под Greasemonkey для отправки коммента
  2282. var c_form_node = $q('#comment_form', topic);
  2283. //'c_form_node:'.wcl(c_form_node, ' win.commentForm:'+ (win.commentForm ? win.commentForm :'==no=='));
  2284. if(c_form_node){ //если есть форма ответа...
  2285. //c_form_node.input_preview = c_form_node.getElement('input.preview');
  2286. c_form_node.input_preview = $q('input.preview', c_form_node); //определеяем кнопку предпросмотра
  2287. if(c_form_node.input_preview){ //если она есть...
  2288. c_form_node.input_preview.addEventListener('click',function(){ //обработчик клика
  2289. //alert('preview')
  2290. win.commentForm.sendComment(c_form_node, 'preview', $q('input.preview', c_form_node));
  2291. //приход данных есть, но не идёт дальше (.fireEvent)
  2292. },!1);
  2293. }
  2294. var comment_type = $q('#comment_type', c_form_node).getAttribute('title');
  2295. var c_form_submit = function(){
  2296. //'last_text=='.wcl(c_form_node.last_text, c_form_node['comment[message]'] && c_form_node['comment[message]'].value, win.comment_type);
  2297. if(c_form_node.last_text && c_form_node.last_text == (c_form_node['comment[message]'] && c_form_node['comment[message]'].value) ){
  2298. '--fff-найден дубликат сообщения'.wcl('') //(найден дубликат сообщения)
  2299. }else{
  2300. //TODO изолировать все одинаковые структуры по отображению, если есть
  2301. //win.commentForm.sendComment(c_form_node, comment_type, c_form_node);
  2302. 'win.commentForm.sendComment(c_form_node, win.comment_type, c_form_node);'.wcl(comment_type);
  2303. //TODO вернуть всё обратно
  2304.  
  2305. //TODO область Saved_stuff
  2306. }
  2307. return false;
  2308. }
  2309. var postButt = $q('input.post', c_form_node);
  2310. postButt.setAttribute('type','button'); //пассивность кнопки
  2311. postButt.addEventListener('click', c_form_submit,!1); //обработчик клика на отправку
  2312. }
  2313. });
  2314. //'win.commentForm:'.wcl(win.commentForm)
  2315. }
  2316. //'showComm'.wcl(showComm);
  2317. if(showComm){ //показ комментариев
  2318. var commC2 = $q('.comments.c2', topic);
  2319. $q('.showComm.btnBack:not(.inln)', topic).style.display
  2320. = commC2.style.display
  2321. = $q('.showComm.btnBack.n2', topic).style.display = 'block';
  2322. if(/ noShowYet/.test(commC2.className)){// корректировки отображения после вывода:
  2323. //'comments,topic'.wcl(comments, topic)
  2324. correctCommentsAfter(comments, topic); //кнопки "Отв"; расцветка авторов; поправки дат
  2325. //'authorClicks21'.wcl(commC2)
  2326. authorClicks(commC2); //расст.обраб.кликов по ссылкам
  2327. var cont = $q('div.content', topic);
  2328. //'authorClicks22'.wcl(commC2, cont)
  2329. authorClicks(cont); //обраб кликов по созданному контенту
  2330. handlImgViews(commC2); handlImgViews(cont); //показ увеличенных картинок
  2331. //'authorClicks3'.wcl(commC2)
  2332. commC2.className = commC2.className.replace(/ noShowYet/,'');
  2333. }
  2334. }
  2335. xhr.link.setAttribute('class', xhr.link.className.replace(/ blk2nd/,'')); //снять блок повторного клика
  2336. showSourceLang(topic); //показ языка кодов в подгруженном
  2337. };
  2338. xhr.send(null);
  2339. }else
  2340. this.setAttribute('class', this.className.replace(/ blk2nd/, '')); //снять блок повторного клика
  2341. }catch(er){alert('error_HAjax_showContent()_'+url +' '+ er);}
  2342. }
  2343. $pdsp(ev);
  2344. if(!win.comment_show_reply_form)
  2345. win.comment_show_reply_form = function(){};
  2346. //===== место подключения плагинов для showContent() =======
  2347. },
  2348. showSourceLang = function(area, addLabels){ //показать язык кода (в блоке показа кода), и подействовать hljs, ес.не addLabels
  2349. if(!area) return;
  2350. if(!area.length)
  2351. area = [area];
  2352. for(var j in area){if(area[j].childNodes){ //подсветка синтаксиса подгруж. блоков (не-Хром)
  2353. var b0a = area[j].querySelectorAll('pre >code');
  2354. for(var i in b0a){if(b0a[i].childNodes){
  2355. var bi = b0a[i]
  2356. biP = bi.parentNode
  2357. ,bL = document.createElement('DIV');
  2358. if(win.hljs && win.$ && !addLabels)
  2359. win.hljs.highlightBlock(bi,' ');
  2360. bL.className = biP.className ='hALang';
  2361. if(biP.parentNode && /content/.test(biP.parentNode.className) && !/html_format/.test(biP.parentNode.className))
  2362. biP.parentNode.className +=' html_format';
  2363. bL.innerHTML = bi.className;
  2364. biP.insertBefore(bL, bi);
  2365. }}}}
  2366. },
  2367. zenChecked,
  2368. extLinks = function(node, oldChk, tops){ //внешние ссылки в новом окне
  2369. if(!hS.extLinks.val || !node) return;
  2370. var links = $qA('a', node)
  2371. ,monthRu ='январь,февраль,март,апрель,май,июнь,июль,август,сентябрь,октябрь,ноябрь,декабрь'.split(',');
  2372. for(var i in links){var LI = links[i]; if(LI.attributes && LI.attributes['href']){
  2373. var lH = LI.attributes['href'].nodeValue
  2374. ,postMatch, qaMatch;
  2375. if(!RegExp('^('+ HRU.replace(/\/\//,'//(\\w+\\.)*').replace(/ahabr/,'(ahabr)?\\') +'|/(?!\/)|#)','i').test(lH) && !/^textDecorationColor/.test(LI.className) ){
  2376. LI.className ='textDecorationColor'+(LI.className ?' '+ LI.className :'');
  2377. LI.setAttribute('target','_blank');
  2378. $e({el:'SPAN', ht:"⇗", cs:{color:'#248'}, aft: LI}); //стрелк2 верх-прав
  2379. if((qaMatch = lH.match(/\/q\/(\d+)/)) && !/habracut/.test(LI.className)){ //вопросы-даты
  2380. var postNum = qaMatch[1]
  2381. ,postYM =[0,0,0,0,0,0,0,0,1,983,1804,2711 //по 12 чисел с янв 2010
  2382. ,3525,4389,5295,6332,7178,8084,9057,9979,10931,11992,13072,14030
  2383. ,14973,15959,17004,17983,18936,20058,21103,22184,23422,24724,27161,29583
  2384. ,31593,33727,35603,37596,39471,41108,42742,44390,46050,47746,49552,54596
  2385. ,61336,68300,75230,82958,91033,99151,107675,116875,126229,135799,147005,158837
  2386. ,169713,182213,195255,206961,213979,221001]; //июн.2015 qa -прогноз
  2387. for(var j = postYM[postYM.length -1]; --j >=0;) //получение примерной даты - 2-й способ
  2388. if(postNum >= postYM[j]){
  2389. var txt = monthRu[j % 12] +' '+ (2010 + (0|j/12)); break;}
  2390. if(!oldChk){
  2391. if(!/post_name/.test(LI.className) )
  2392. LI.title = LI.title && txt + '; ' + LI.title || txt;
  2393. else
  2394. $e({ht: txt, cl:'when', aft: LI});
  2395. }else if((j < postYM.length -3 || j == postYM.length -3 && NOWdate.getDate() >5)
  2396. && LI.className =='post_name'){
  2397. LI.title = LI.title && txt +'; '+ LI.title || txt;
  2398. LI.style.backgroundColor ='#f2fbf6';}
  2399. }
  2400. }else if((postMatch = lH.match(/\/(post|blog)\/(\d+)/)) && !/habracut/.test(LI.className)){// посты-даты
  2401. var postNum = postMatch[2]
  2402. ,postY =[1,4909,18277,48215]
  2403. ,postYM =[79815,82680,85884,89552,92535,95099,97893,100688,103185,105320,107313,109124
  2404. ,111037,112913,114666,116587,118465,120339,123152,125327,127474,129518,131623,133750
  2405. ,135593,137388,139154,141161,143096,145002,146858,148825,150655,152897,156927,160927
  2406. ,164511,167841,171141,174897,178523,181712,185178,188544,192134,195908,200442,204302
  2407. ,207968,211020,214263,217769,221545,224805,228191,231847,235117,238753,242143,244603
  2408. ,247199,249403,251783,254567,257097,259501]; //июн.2015 -прогноз
  2409. //,0,245130,246570,248202,249848,251208]; //geektimes
  2410. //,0,0,0,13790,14858,15800]; //megamo
  2411. //.!обновлять каждый месяц, писать последнее число как прогноз
  2412. for(var j = postYM[postYM.length -1]; --j >=0;) //получение примерной даты - 2-й способ
  2413. if(postNum >= postYM[j]){
  2414. var month = monthRu[j % 12] +' '+ (2010 + (0|j/12)); break;}
  2415. if(j <0)
  2416. for(var k = postY[3]; --k >=0;)
  2417. if(postNum >= postY[k]){ month = (2006 + k) +'';break;}
  2418. if(!oldChk)
  2419. LI.title = LI.title && month +'; '+ LI.title || month;
  2420. else if(LI.className =='post_name'){
  2421. if(j < postYM.length -3 || j == postYM.length -3 && NOWdate.getDate() >5){ //признак новизны статьи, для отметок в "Прямом эфире" (прошлый месяц и старее, но не моложе 5 дней)
  2422. LI.title = LI.title && month +'; '+ LI.title || month;
  2423. LI.style.backgroundColor ='#f4f4fa';
  2424. }
  2425. if(tops){ //перенос комментария к лучшим
  2426. var topComm = tops['p'+ postNum]
  2427. ,lsiP = parents(/post_item/, LI);
  2428. if(topComm && lsiP){
  2429. $e({el:'span', ht:' ', apT: topComm});
  2430. $e({el:'.count', blck: lsiP, apT: topComm});
  2431. $e({el:'span', ht:' ', apT: topComm});
  2432. $e({el:'.user_name', blck: lsiP, apT: topComm.parentNode});
  2433. lsiP.parentNode.removeChild(lsiP);
  2434. }}
  2435. }
  2436. }
  2437. }}
  2438. },
  2439. nameGen = function(len){ len = len || 6; //ген.имён
  2440. var syl ='a,ab,ba,abb,bab,bba'.split(','),L ={a:'aeiouy',b:'bcdfghjklmnprstvwxz'},s ='',sy =''
  2441. ,rnd = function(n){return Math.floor(Math.random() * n);};
  2442. wh:while(1){ sy = sy.length ==1 ? syl[rnd(syl.length -1) +1] : syl[rnd(syl.length)];
  2443. for(var i =0; i < sy.length; i++){
  2444. var ab = L[sy.charAt(i) ]; //тип буквы
  2445. s += ab.charAt(rnd(ab.length)); //случайная буква
  2446. if(s.length == len) break wh;
  2447. }}
  2448. return s;
  2449. },
  2450. haReplace = function(txt){
  2451. var t = hS.chtoBy.val ? txt.replace(/([Чч])то бы(\s)/gi,'$1тобы$2') : txt;
  2452. t = hS.haReplace.val ? t.replace(/хабра/gi,'χ·').replace(/χ·хабр/gi,'χα').replace(/хабр/gi,'χ·') : t;
  2453. return t;
  2454. },
  2455. byTextNodes = function(node, ff){ //рекурсивный проход по всем текстовым нодам
  2456. if(!hS.haReplace.val)
  2457. return;
  2458. if(node && node.hasChildNodes())
  2459. for(j in node.childNodes){var ch = node.childNodes[j]; if(ch.parentNode){
  2460. if((ch.nodeType ==3 || ch.nodeType ==2 && ch.nodeName =='title') && ch.nodeValue && ch.nodeValue.length >8)
  2461. ch.nodeValue = ff(ch.nodeValue);
  2462. else if(ch.nodeType ==1 || ch.nodeType ==11){
  2463. arguments.callee(ch, ff);
  2464. }
  2465. }}
  2466. };
  2467. var inFrame = top != window,
  2468. scanAliens = function(time){ if(!document && !document.querySelectorAll) return;
  2469. var anyScript = document.querySelectorAll('script'), aL;
  2470. if(anyScript && (aL=anyScript.length))
  2471. for(var i in anyScript) if(anyScript[i].childNodes){
  2472. if(!/(habrahabr.ru\/|apis.google.com\/)/.test(anyScript[i].src))
  2473. anyScript[i].src ='';
  2474. if(/(_gaq|analytics.com|an.yandex.ru|pink.habralab.ru)/.test(anyScript[i].innerHTML))
  2475. anyScript[i].innerHTML ='';
  2476. }
  2477. },
  2478. checkInZen = function(){
  2479. if($q('#header .userpanel'))
  2480. var cssGet = win.getComputedStyle($q('#header .userpanel'), null);
  2481. if(!cssGet && $q('.panel-personal'))
  2482. cssGet = win.getComputedStyle($q('.panel-personal'), null);
  2483. //for(var i in cssGet)
  2484. // 'getComputedStyle'.wcl(i+' = ', cssGet[i], cssGet.getPropertyValue(cssGet[i]))
  2485. var zenChecked = cssGet && (cssGet.getPropertyValue('z-index')=='10026'); //индикатор подключения юзерстилей ZenComment
  2486. return zenChecked;
  2487. },
  2488. wwHV =0, //для setTimeout
  2489. hView = function(ev){ //просмотр блока (подсказки, меню) по наведению, с удержанием, задержкой
  2490. //blckMajor, blckMinr, sett, fClick, fMsMove
  2491. var tg = ev.currentTarget, tgHVi, hView;
  2492. win.clearTimeout(wwHV);
  2493. win.setTimeout(function(){
  2494. if((tgHVi = tg.getAttribute('data-hView')) || tg.className =='habrAjaxSettings hView'){
  2495. var xywh = $x(getPosition(tg), {w: tg.offsetWidth, h: tg.offsetHeight});
  2496. hView = $e({el:$q('.habrAjaxSettings.hView') ||'div'
  2497. ,cl:'habrAjaxSettings hView'+ (tg.className =='group'?' group':'')
  2498. ,ht: tgHVi
  2499. ,cs:{display:'block', left: xywh.x + xywh.w +'px', top: xywh.y + xywh.h /2 +'px'
  2500. ,width: Math.min(320, win.innerWidth - 61 - 320 - 10) +'px'}
  2501. ,on:{mouseover: function(){win.clearTimeout(wwHV)}, mouseout: hViewHide}
  2502. ,apT: document.body
  2503. });
  2504. if(hView)
  2505. hView.style.top = Math.min(win.innerHeight - hView.offsetHeight, Math.max(0, xywh.y + xywh.h /2 - hView.offsetHeight/2 - $q('.habrAjaxSettings >div+div').scrollTop )) +'px'
  2506. }
  2507. },100);
  2508. },
  2509. hViewHide = function(ev){
  2510. win.clearTimeout(wwHV);
  2511. wwHV = win.setTimeout(function(){
  2512. $e({el:'.habrAjaxSettings.hView'
  2513. ,cs:{display:'none'} });
  2514. },590);
  2515. }
  2516. ,selS ={} //окружение выделенного текста (всё, что вычислили, исходя из текущего выделения)
  2517. ,citeS =[] //список цитат данной статьи
  2518. ,citeA =[]; //список статей, имеющих цитаты в хранилище
  2519. (function(){ //внедрение функций GM_... для Хрома, FF4+
  2520. if(1 ){
  2521. this.GM_getValue = function(key, deflt){ return localStorage[key] || deflt };
  2522. this.GM_setValue = function(key, value){ return localStorage[key] = value };
  2523. this.GM_deleteValue = function(key){ return delete localStorage[key] };
  2524. }})();
  2525.  
  2526. hS = hS.get(); //settings; взять настройки из памяти (GM), если есть
  2527. if(/\/(conversations|edit|add)\//.test(lh) && !win.opera) //заполнение полей письма
  2528. fillLetter();
  2529. var vers = navigator.userAgent.match(/Version\/(\d+)/);
  2530. if(vers && vers[1])
  2531. vers = parseInt(vers[1]);
  2532. if(!(win.opera && vers >11)) //ручной zenPresent - для Оперы 12+, для остальных скрыть в еастройках
  2533. delete hS.zenPresent.desc;
  2534. if(win.getComputedStyle)
  2535. zenChecked = checkInZen();
  2536. h.inZen = (typeof zenChecked!=u ? zenChecked : hS.zenPresent.val) || hS.inZen.val;
  2537. var ZenNCh = h.inZen && !isChrome; //случаи приоритетности стилей из скриптов в Хроме
  2538. //'zenChecked'.wcl(typeof zenChecked, zenChecked && zenChecked.length, hS.zenPresent.val, hS.inZen.val, h.inZen)
  2539. strongCutImgMinH = hS.hStrongCut.val;
  2540. if(!h.inZen)
  2541. strongCutImgMinH +=50;
  2542. var css='body{text-align: inherit!important; font-family: Verdana,sans-serif!important}'
  2543. +'#layout{height: auto!important}.posts_list .blog_title.small{font-size:14px!important}'
  2544. +'.post div.btnBack, .btnBack{position: relative; height: 12px; margin: 3px 1px 5px 0; padding:0 3px!important; border: 1px solid #b3d2ee;border-radius:3px; font-size: 12px; background: #d3e2f0;color:#8ac;cursor:pointer}'
  2545. +'.content+.btnBack.n2{margin-top:-5px!important}'
  2546. +'.comments.c2{clear: both; position: relative; display:none; border-bottom: 2px solid #fff!important}'
  2547. +'.comments.c2:hover{border-bottom: 2px solid #eee!important}'
  2548. +'.comments.c2:hover >.comment_item:not(:hover){margin-right:-2px!important;border-right: 2px solid #eee!important;background:#eee}'
  2549. +'.comments.c2 .comment_item:hover{background:#fff}'
  2550. +'.comments.c2 >h2.title,.posts_list .comments.c2 >h2.comments-header{'
  2551. +'margin: -0.8em 0 4px!important;padding: 0.5em 0 3px 0.4em!important; border: 1px solid #e8e8ee!important;-moz-border-radius: 8px;-webkit-border-radius: 8px; border-radius: 8px; background-color: #f0f0e7!important}'
  2552. +'.comments.c2 h2.title span,.comments.c2 h2.comments-header span{position: relative;margin-bottom: 32px;height: 34px;font-size: 26px;vertical-align: 0%}'
  2553. +'h2.title .subscribe_comments{font-size: 12px!important}'
  2554. +'#wrapper .comments.c2 >h2.title{margin: 0 0 4px 6px!important;}'
  2555. +'.comments_list .comment_item .reply_comments{margin-top:10px!important}'
  2556. +'.comments.c2 >.comment_item,#wrapper .comments.c2 .reply_comments >.comment_item,.content_left .comments.c2 .reply_comments >.comment_item{'
  2557. +'position:relative;margin-top: 8px!important;margin-left: -4px!important;padding-top: 0!important;padding-left: 24px!important}'
  2558. +'#wrapper .comments.c2 >.comment_item,.content_left .comments.c2 >.comment_item{'
  2559. +'margin-left: -24px!important;border-left: 1px solid #dddde2!important}'
  2560. +'.comments.c2 .info{height:16px}'
  2561. +'.comments.c2 .info a.username{top:-11px!important;margin-top:-5px!important}'
  2562.  
  2563. +'.comments.c2 .info time{position:relative; top:'+(1||h.inZen?-10:0)+'px!important; margin-right:10px!important}'
  2564. +'.comments.c2 >.comment_item:hover .info .voting{display:block!important}'
  2565. +'.comments.c2 >.comment_item:hover .comment_item:not(:hover) .info a.username'
  2566. +',.comments.c2:hover >.comment_item:not(:hover) .info a.username'
  2567. +',.comments.c2 >.comment_item:hover .comment_item:not(:hover) .info time'
  2568. +',.comments.c2:not(:hover) .reply >a.reply_link'
  2569. +',.comments_list:not(:hover) .reply >a.reply_link'
  2570. +',.comments.c2:hover >.comment_item:not(:hover) .reply >a.reply_link'
  2571. +',.comments_list:hover >.comment_item:not(:hover) .reply >a.reply_link'
  2572. +',.comments.c2 >.comment_item:hover .comment_item:not(:hover) a.reply_link'
  2573. +',.comments_list >.comment_item:hover .comment_item:not(:hover) a.reply_link{visibility:hidden}'
  2574. +'.comments.c2 >comment_item_plain >.comment_item .info time'
  2575. +',.comments.c2 >.comment_item:hover .info time'
  2576. +',.comments.c2 >.comment_item:hover .reply a.reply_link{visibility:visible}'
  2577. +'.comments.c2 >.block_after_post{display:none}'
  2578. +'.content.c2 table{width: 100%; margin: 6px 0!important; border: 1px solid #ccc; clear: both; border-collapse: collapse; border-spacing: 0}.content.c2 table td, .content.c2 table th{border: 1px solid #ccc; padding: 2px 3px!important}.content.c2 .polling table.result,.content.c2 .polling table.result td{border:0}'
  2579.  
  2580. +'.eventLine .eventHid, .eventLine .date{visibility:hidden}.eventLine:hover .eventHid, .eventLine:hover .date{visibility:visible}'
  2581. +'.eventLine .date{color:#999}'
  2582.  
  2583. +'.commInfo{position: absolute; z-index: 4; display: inline-block; visibility:hidden; left:0; max-width:43px; margin-top: 6px; border: 1px dotted #d97;'
  2584. +'-webkit-transition:visibility 0s linear 1s,opacity 1s linear;'
  2585. +'-moz-transition:visibility 0s linear 1s,opacity 1s linear;'
  2586. +'-o-transition:visibility 0s linear 1s,opacity 1s linear;'
  2587. +'opacity: 0;}'
  2588. +'.title:hover .commInfo{visibility:visible; opacity: 1; transition-delay:0s;}'
  2589. +'.commInfo .root{display: inline-block; margin: 1px 0 1px 2px; text-decoration: none; line-height:4px; white-space: normal;}'
  2590. +'.commInfo .overLink{line-height:6px; white-space: nowrap'+(isChrome?';font-size:0':'')+'}'
  2591. +'.commInfo .overLink:hover{background-color:#eee}'
  2592. +'.commInfo .root .nCom{display: inline-block; background:#9ab;opacity:0.7}.commInfo .root .nLin{display: inline-block; margin-left: 3px; background:#88c;opacity:0.7}'
  2593. +'.commInfo .root .nP{display: inline-block; background:#7d7;opacity:0.8}.commInfo .root .nM{display: inline-block; margin-left: 3px; background:#c87046;opacity:0.8}'
  2594. +'.commInfo .links.root{min-height: 4px; vertical-align: top}'
  2595. +'.commInfo .imgs.root{min-height: 6px; vertical-align: top}'
  2596. +'.commInfo .links.root .lnk{display: inline-block; width: 5px; height: 2px; margin:1px 0 0 1px; line-height:2px; vertical-align: top; border:1px solid #24f}'
  2597. +'.commInfo .links.root .imgL,' //перекраска для просмотра
  2598. +'.commInfo .imgs.root .imgL{display: inline-block; width: 6px; height: 4px; margin:-1px 0 -1px 1px; line-height:4px; vertical-align: top; border:1px solid red; background-color:#ff4}'
  2599. +'.commInfo .links.root .lnk:visited{border:1px solid #e4d}'
  2600. +'.comments .comment_item .info .branch,#comments .comment_item .info .branch{Visibility: hidden; position: relative; top:-11px!important; text-decoration: none}'
  2601. +'.comments .comment_item .info:hover .branch,#comments .comment_item .info:hover .branch{Visibility: visible}'
  2602.  
  2603. +'.post div.btnBack.inln{display: inline-block; vertical-align: middle; overflow: hidden; height: 14px; line-height: 14px!important; margin: 0 2px 3px}'
  2604. +'.post .btnBack:not(.inln):not(.n2){position: relative;z-index: 1}'
  2605. +'.post .content .percent,.post .btnBack .percent,.post .btnBack >i{display: inline-block;vertical-align:top; line-height:10px}'
  2606. +'.post .content .percent{font-size:12px;color:#8ac}'
  2607. +'.post .content .gPercent,.post .btnBack .gPercent'
  2608. +'{display: inline-block; width: 100px; height: 10px; vertical-align: top; margin-left: 9px; border: 1px solid #b3d2ee; background-color: #ecefee; cursor: pointer}'
  2609. +'.post .content .gPercent div,.post .btnBack .gPercent div'
  2610. +'{display: inline-block; height: 10px; vertical-align: top;border-right: 1px solid #b3d2ee; background-color: #e0e5e8}'
  2611. +'.post .content .gPercent div{background-color: #f4f8fb}'
  2612. +'.post .dblAuthor .published{float:none}'
  2613. +'.showComm.btnBack:not(.inln), .showComm.btnBack.n2{display: none; clear: both}'
  2614. +'.showComm.btnBack:not(.inln):not(.n2){margin-top: 22px}'
  2615. +'.showComm.btnBack.n2 .percent0{float:right} .showComm.btnBack.n2 .percent{vertical-align: top; border: 1px solid #b3d2ee; margin: -1px 3px 0; padding: 0 13px 1px; line-height:11px; background-color: #ecefee}'
  2616. +'#poxupih a{color:#7ab}.gertuik{font-size: 16px!important;color:#eee}'
  2617. +'#header .main_menu a.date, #navbar .tab_menu .date{display:inline-block; text-align:center; text-decoration: none!important; font: 11px/8px Verdana,Tahoma,sans-serif!important;'+ (ZenNCh?'margin: 11px 6px 0 -1px!important; color:#479!important':'')+'}'
  2618. +'#header .search form input[type="text"]{margin-right: 21px;}'
  2619. +'#header .search form input[type="submit"],.panel-search .in-submit{display:none;clear: right;float: right!important;margin: 0 0 0 -21px!important}#header .search:hover form input[type="submit"],.panel-search:hover .in-submit{display:block}'
  2620. +'.panel-search .panel-search-label{margin-right: 24px}.panel-search .js-autosuggest-output-container{clear: left!important}'
  2621.  
  2622. +'#layout img[align="middle"],#layout img[align="center"]{display:block;margin:0 auto 2px!important}' //Fx fix
  2623. +'.comments.c2{position: static!important;overflow: visible!important;min-height: 2em; padding-left: 32px!important;border-right: 2px solid #fff!important;background:#fff}'
  2624. +'#header .userpanel:hover .habrauser-newmail{margin-right: -4px!important; margin-left: 6px!important}'
  2625. +'.header .user_panel +.logo{margin:0!important; background-position:0 0!important; width:75px!important; height:71px!important}'
  2626.  
  2627. +'.comments.c2 .info-text{display:none!important}'
  2628. +'.comments.c2 h2.comments-header{margin:0 0 0 -12px!important}'
  2629. +'.comments.c2 .comment-preview{font: 1.08em Verdana,sans-serif!important}'
  2630. +'.info a.link_to_comment{float:right;position:relative;visibility:hidden;left:35px}.comment_item .to_parent,.comment_item .show_tree{display:none!important}.info:hover a.link_to_comment{visibility:visible}'
  2631. +'.hAjaxLogo{position: relative; z-index: 6; float: right; width:0; height: 32px; opacity: 0.6}.hAjaxLogo:hover{opacity: 1}.hAjaxLogo .hLogo{position: absolute; float: right; right: 0; min-width: 32px; height: 32px; margin-top: 3px; border-radius: 5px; background-color: #6e96ca; color: #e0e4e8; cursor: pointer}.hAjaxLogo span.hLogo{padding: 2px 3px!important}.hAjaxLogo:hover .hLogo{background-color: #c42;color: #fcb}#reg-wrapper{padding-right:10px;}#reg-wrapper .hAjaxLogo{margin-top:16px}'
  2632.  
  2633. +'.comments.c2 .comment_holder .mark{left:0}'
  2634. +'.g-plusone >iframe[id^="I"][src^="https://plusone.google.com"]{display:block!important;width:width:24px!important; margin-right: 6px!important}'
  2635. +'.infopanel .g-plusone,.infopanel div[id*="__plusone"]{float: left!important;overflow:hidden; width: 24px!important; margin-top: 5px!important; margin-right: 6px!important}.infopanel >.g-plusone:hover{overflow:inherit}'
  2636.  
  2637. +'.infopanel >.g-plusone +.likes{position: relative; float: left; left: -33px; width: 0; height: 16px; padding: 0!important; text-align: center}'
  2638. +'.infopanel >.g-plusone +.likes >div{float: none; width: 30px; height: 10px; margin-top: '+(isChrome?8:2)+'px!important; padding: 0; line-height: 10px; font-size:12px;}'
  2639. +'.infopanel >.g-plusone +.likes >div >div{display: inline-block; float: none; min-width: 12px; height: 10px; line-height: 10px; padding: 0; padding-left: 2px!important; background: #efefef!important; border-radius: 2px}'
  2640. +'.infopanel >.g-plusone:hover +.likes{display: none}'
  2641. +'.comment_item .info .comma{display:none!important}'
  2642.  
  2643. +'#comment_form .panel .spanned, #comments_form .panel .spanned, .editor .panel .spanned{display:block; float:left}'
  2644. +'.editor .panel .spanned{padding: 0!important}'
  2645. +'.panel .langs, .panel .langs2,.panel .colrs{display: none; position: absolute; top:-6.3em; left: 15em; padding: 2px; text-align: center; background: #EAECEA; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; opacity:0.8}.tm-form.ajax .panel .langs{left:22em}'
  2646. +'.panel .langs b, .panel .langs2 span, .panel .colrs span{display: inline-block; margin: 0; padding: 2px 8px; line-height: normal!important; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; cursor: pointer}'
  2647. +'.panel .colrs{top:-6.3em;left:16.2em;line-height:1!important; white-space: nowrap;background: #fff}.panel .colrs span{min-width:3ex;padding: 0 1px;line-height:1!important}.panel .colrs:hover{opacity:1}'
  2648. +'.panel .langs b:hover, .panel .langs2 span:hover{background: #fff} .panel .colrs span:hover{background: #eee}'
  2649. +'.panel .langs i{display: inline-block;}'
  2650. +'.panel .langs2{text-align: left;z-index: 12; white-space: nowrap; opacity:1}'
  2651. +'.panel .langs2 span{padding: 2px; font-weight: normal}.panel .langs2 span:nth-child(even){color:#00a}'
  2652. +'pre.hALang{position: relative; margin-top:-0.5em; padding-top:0.5em;}pre >.hALang{position: absolute; top:0; right:'+(h.inZen?5.7:1)+'em; padding: 0 4px 1px; border: 1px solid #e1e1e8; border-radius: 4px; background: #f1f1f3; line-height: 0.8; color:#aaa}pre:hover >.hALang{display:none}'
  2653.  
  2654. +'.powerCut{max-height: '+(strongCutImgMinH*2 +4)+'px; overflow-y: auto!important;padding-right:3px!important; padding-bottom:1px!important}'
  2655. +'.content.powerCut .pressed{line-height: '+(h.inZen ? 1.08 : 1.24)+'!important}'
  2656. +'.content.powerCut .showComm img{margin-top:-1px!important}'
  2657. +'.post .content.powerCut blockquote{clear:none}'
  2658. +'.content.powerCut img{clear:right; max-width: '+(strongCutImgMinH*2)+'px; max-height: '+strongCutImgMinH+'px; margin-top:2px!important}'
  2659. +'.powerCut img:not([align]){float:right; margin-left:6px!important}'
  2660. +'.powerCut img[align="center"], .powerCut img[align="middle"]{float:left; clear:left; padding-right:6px!important; padding-left:6px!important; border-left: 1px dotted #aaa!important}'
  2661. +'.strongCutImgPlace{border:1px solid #99e; min-width:14px; float: right; margin: -4px -1px -1px 2px; padding: 0 1px 0 3px; background: #ee6; opacity: 0.3}#layout img.youtub,#wrapper img.youtub{border-left: 3px dotted #833!important}'
  2662. +'.powerCut +.tags{max-height: 1.5em; overflow:hidden}.powerCut +.tags:hover{overflow:inherit}.powerCut +.tags li{position:relative; z-index:2}'
  2663. +'textarea{font: 12px/15px Verdana,Arial,Helvetica,sans-serif!important;resize:vertical!important}'
  2664. //нотификатор, панель цитат
  2665. +'.noteBar{display:none;position: fixed; overflow: auto; min-width: 96px; max-width: 65%; top: 0; left: 96px; min-height: 20px; max-height: 250px; margin:-5px 0 0!important; padding: 1px 4px 0!important; border: 1px solid #999!important;border-radius:5px; z-index: 3025;background-color: #dcc;font-size: 13px; opacity:0.85}'
  2666. +'.noteBar .closeButt{float:right; margin-right:-3px!important; padding: 0 2px!important; border: 1px solid #999!important;border-radius:5px;cursor: pointer}'
  2667. +'.noteBar .list:nth-child(2){margin-right:16px!important}.noteBar .notes{margin:0!important}'
  2668. +'.noteBar .notes .note{color:#622}.noteBar .notes a{color:#a66}.noteBar .notes img{padding-top:3px; vertical-align: baseline}.noteBar .delim{height: 2px; background:#a88}'
  2669. +'.noteBar .hlp{text-indent:2em; margin:0 2px 1px;padding:0 3px; background:#f6f8fa}'
  2670. //контекстное меню для цитат (выделений текста)
  2671. +'.citeBtns{position: absolute; display: none; z-index: 101; width: 3em;-webkit-user-select: none;-moz-user-select: -moz-none;-o-user-select: none; user-select: none}'
  2672. +'.citeBtns .citeCmdBase{position: relative; left:-3px;width:2.5em; opacity:0.5}'
  2673. +'.citeBtns:hover .citeCmdBase{opacity:1}'
  2674. +'.citeBtns button{display:none; margin:0!important; padding: 0 2px!important;background-color:#e6dada; border-width: 1px;border-radius:3px}'
  2675. +'.citeBtns button:first-child{display: block}'
  2676. +'.citeBtns .citeCmdBase button{float: left; width: 2.5em; margin: 0 3px}'
  2677. +'.citeBtns .citeTxTa{position: relative; display: none; min-height: 26px; margin:-22px -2em -4px;}' //буфер для перетаскивания
  2678. +'.citeBtns .citeTx{position: absolute; text-align: center; bottom: 12px; min-height: 1.4em; margin: 0 -10em 0 -7em; padding: 0 2px 0 3px; border: #bbb dotted 1px; background: #f8f7f5; opacity:0.9}' //блок цитат
  2679. +'.citeBtns .citeLst{position: absolute; left: -1px; text-align: left}'
  2680. +'.citeBtns .citeLst2{border: 1px solid #ddd; background: #f8f7f1}'
  2681. +'.citeBtns .citeLst .cite{margin:0 1px; padding; 1px 2px; border: 1px solid #ddd; background: #f8f7f1}'
  2682. +'.citeBtns .citeTx .selText{position: relative; left: 1.1em; padding: 0 3px!important; background: #fae7e5;}'
  2683. +'.citeBtns .citeTa{position: absolute; bottom:-2px; margin: 0 10px!important; min-height: 1.4em;}' //буфер д.перетаск.
  2684. +'.citeBtns .citeTa .ta, .citeBtns .citeTa .taAbs {position: relative; bottom: 0; min-height: 1.4em; margin: -1px; margin-top:-2px; padding-left: 2px; padding-bottom: 2px; border:#bbb solid 1px; background:#f5f7f8; opacity:0.9}'
  2685. +'.citeBtns .citeTa .taAbs{position: absolute; left: -10098px; opacity:1}'
  2686. +'.citeBtns .citeTx,.citeBtns .citeTa .ta {-webkit-user-select: text; -moz-user-select: text;-o-user-select: text; user-select: text}'
  2687. +'.citeBtns .citeCmdTop{height: 6px; cursor:move}.citeBtns .citeCmdTop:hover{border-color:#137; background-color:#137}'
  2688. +'.citeBtns .pre{border-color:#dae4da; background-color:#dae4da}'
  2689.  
  2690. +'.citeBtns .citeCmdLeft{position:absolute; display:none; float: left; width: 1px}'
  2691. +'.citeBtns .citeCmdLeft button{position:relative; display: block; float: right}'
  2692. +'.citeBtns .citeCmdRight{position:absolute; display:none; float: right; width: 1px; margin-left: '+(isFx?'2.2':'2')+'em}'
  2693. +'.citeBtns .citeCmdRight button{position:relative; display: block; float: left}'
  2694. +'.citeBtns:hover .citeCmdLeft, .citeBtns:hover .citeCmdRight, .citeBtns:hover button{display:block}'
  2695. +'.citeBtns .hov button{display:none}.citeBtns .hov:hover button{display:block}'
  2696. +'.citeCmds2{}' //2-й плавающий блок
  2697. //подсветки выделений текстов для цитирования:
  2698. +(hS.contextSelect.val ?'.content::-moz-selection{background-color: #66e;color:#fff} .content::selection{background-color: #66e;color:#fff}'
  2699. +'.content *::-moz-selection{background-color: #33b;color:#eef} .content *::selection{background-color: #33b;color:#eef}'
  2700. +'.message::-moz-selection{background-color: #c96;color:#fff} .message::selection{background-color: #c96;color:#fff}'
  2701. +'.message *::-moz-selection{background-color: #963;color:#fee}.message *::selection{background-color: #963;color:#fee}'
  2702. +'.comment_item .text::-moz-selection{background-color: #c98;color:#eff}.comment_item .text::selection{background-color: #c98;color:#eff}'
  2703. :'')+'.textDecorationColor{text-decoration: underline;text-decoration-color:#248!important}'
  2704.  
  2705. +'.tutor1{display: inline-block; position: relative; top:-2px; height: 1.2em; margin:0 -2px 0 1px; padding: 0 0 0 3px; border-bottom: 1px solid #ffc3dd; border-bottom-left-radius: 2px; border-top-left-radius: 2px; line-height: 1em; font-size: 10px; background-color: #ffc3dd;color: #ffc3dd}'
  2706. +'.tutor2{position: relative;left: 0.2em;float: right;width: 1px; height: 1px; border-color: #ffc3dd #fff #ffc3dd #ffc3dd; border-style:solid; border-width: 0.6em 0.5em 0.6em 0;}'
  2707. +'.tutor3{color: #d36992;position: absolute;}'
  2708.  
  2709. +'.decision1{display: inline-block; position: relative; top:-2px; height: 1.2em; margin:0 -2px 0 1px; padding: 0 0 0 3px; border-bottom: 1px solid #d4ecb2; border-bottom-left-radius: 2px; border-top-left-radius: 2px; line-height: 1em; font-size: 10px; background-color: #d4ecb2;color: #d4ecb2}'
  2710. +'.decision2{position: relative;left: 0.2em;float: right;width: 1px; height: 1px; border-color: #d4ecb2 #fff #d4ecb2 #d4ecb2; border-style:solid; border-width: 0.6em 0.5em 0.6em 0;}'
  2711. +'.decision3{color: #684;position: absolute;}'
  2712.  
  2713. +'.sand1{display: inline-block; position: relative; top:-2px; height: 1.2em; margin:0 -2px 0 1px; padding: 0 0 0 3px; border-bottom: 1px solid #eeedd8; border-bottom-left-radius: 2px; border-top-left-radius: 2px; line-height: 1em; font-size: 10px; background-color: #eeedd8;color: #eeedd8}'
  2714. +'.sand2{position: relative;left: 0.2em;float: right;width: 1px; height: 1px; border-color: #eeedd8 #fff #eeedd8 #eeedd8; border-style:solid; border-width: 0.6em 0.5em 0.6em 0;}'
  2715. +'.sand3{color: #8c896b;position: absolute;text-decoration:none;border-bottom:1px dotted #aa8}'
  2716.  
  2717. +'.trans1{display: inline-block; position: relative; top:-2px; height: 1.2em; margin:0 -2px 0 1px; padding: 0 0 0 3px; border-bottom: 1px solid #b3d5ea; border-bottom-left-radius: 2px; border-top-left-radius: 2px; line-height: 1em; font-size: 10px; background-color: #b3d5ea;color: #b3d5ea}'
  2718. +'.trans2{position: relative;left: 0.2em;float: right;width: 1px; height: 1px; border-color: #b3d5ea #fff #b3d5ea #b3d5ea; border-style:solid; border-width: 0.6em 0.5em 0.6em 0;}'
  2719. +'.trans3{color: #6a7fa3;position: absolute;}'
  2720.  
  2721. +'.recov1{display: inline-block; position: relative; top:-2px; height: 1.2em; margin:0 -2px 0 1px; padding: 0 0 0 3px; border-bottom: 1px solid #f4ddae; border-bottom-left-radius: 2px; border-top-left-radius: 2px; line-height: 1em; font-size: 10px; background-color: #f4ddae;color: #f4ddae}'
  2722. +'.recov2{position: relative;left: 0.2em;float: right;width: 1px; height: 1px; border-color: #f4ddae #fff #f4ddae #f4ddae; border-style:solid; border-width: 0.6em 0.5em 0.6em 0;}'
  2723. +'.recov3{color: #a28546;position: absolute;text-decoration:none;border-bottom:1px dotted #b97}'
  2724. +'#write_message_form [name=recipients]::-moz-selection{background-color: #66e;color:#ffa} #write_message_form input[name=recipients]::selection{background-color: #66e;color:#ffa}'
  2725.  
  2726. //поддержка отсутствия стилей:
  2727.  
  2728. +'.content_left{padding-right: 27%}'
  2729. +'.sidebar_right{margin-left: -25%; width: 25%}'
  2730. +'.content_left .post h1.title .post_title{display: inline-block;margin: -1px -3px!important; padding: 0 2px 1px 3px!important; border-radius: 2px;background-image: none!important}h1{letter-spacing:0!important}'
  2731. +'.content_left table.menu .profile a{position:relative; z-index:2; opacity:0.4}'
  2732. +'.content_left table.menu .profile a:hover{opacity:0.9}'
  2733. +'.content_left .post{margin: 12px 0 32px !important;overflow: inherit !important}'
  2734. +'.content_left .company_post .post{margin-bottom: -5px!important}'
  2735. +'.company_header .company_icon img{position: absolute; margin-top:'+(h.inZen?29:43)+'px!important}'
  2736. +'.content_left .post h1.title{margin: 3px 0 -3px!important;font: 16px/188% normal Verdana,Tahoma,sans-serif!important}'
  2737. +'.content_left .post h1.title .post_title{ line-height: 16px;font-size: 16px;text-decoration: none!important;color: #48a!important}'
  2738. +'.post h1.title .locked{background-position: 2px 0px!important}'
  2739. +'.sidebar_right .block .all a:visited,.content_left .post h1.title .post_title:visited{color: #b99!important}'
  2740. +'.content_left .company_post h1.title .post_title{font-size: 18px!important;font-weight: normal}'
  2741. +'.content_left :not(.company_post) .post h1.title .post_title:hover{color: #84b18a!important}'
  2742. +'.content_left .post .hubs{float: right; position: relative; z-index:2; margin: 1px 8px 2px -12px!important; white-space: nowrap; opacity: 0.7; background: 0 0!important; color: transparent!important}.content_left .hubs +.content{clear: both}'
  2743. +'.content_left .hubs .profiled_hub{display: inline-block; vertical-align: top!important; height: 9px!important; margin:0 -4px 0 1px!important; font-size:5px!important; background-color: #cbd6ce}'
  2744.  
  2745. +'.content_left .stats{margin-left: 3em}.content_left .stats .item{display: inline-block}'
  2746. +'.content_left .stats .item a{padding:0 2px; font-style: italic; color:#668}.content_left .stats .item a:hover{color:#4D7285}'
  2747. +'.content a,.content_left .comments_list a,.comments.c2 a{color:#497da5!important}'
  2748. +'.content a:hover,.comments_list a:hover,.comments.c2 a:hover{color:#4d7285!important}'
  2749. +'.comment_item .info .voting{float: right; margin: 2px 0 -6px!important; padding-right: 16px; position: relative}'
  2750. +'.comment_item .info a.avatar{position: relative; float: left; top:-8px; margin: 0 10px -8px 0!important; padding-top: 0!important}'
  2751. +'.comment_item .info a.avatar img{width:24px; height:24px}'
  2752. +'.comment_item .reply a.reply_link, .comment_holder .reply a.reply_link{ -moz-transform: rotate(-90deg);-o-transform: rotate(-90deg);-webkit-transform: rotateZ(-90deg);transform : rotate(-90deg); -moz-transform-origin: 0 20px; -o-transform-origin: 0% 20px;-webkit-transform-origin: 0% 20px; -moz-box-shadow: inset 2px -2px 3px #dde;-webkit-box-shadow: inset 2px -2px 3px #dde;box-shadow: inset 2px -2px 3px #dde; border-bottom: 2px solid transparent !important; border-radius:4px; color: #acc!important; display: inline-block; height: auto; left:0; opacity:0.5; padding: 1px 1px 0!important; position: relative; top:-14px; width:auto}'
  2753. +'.reply .edit_link{position: relative; z-index: 1; top:-5px; margin-top: 0!important}'
  2754. +'.comment_item .reply a.reply_link:hover{opacity:1}'
  2755. +'.vote .positive,.voting .positive{color: #390!important}.vote .negative,.voting .negative{color:#c00!important}'
  2756. +'.comment_holder .vote{top: -3px}.comment_holder .reply{height:0}'
  2757. +'.translation .topic,.podcast .topic,.link .topic{background-position: 0 0!important}'
  2758. +'.search-results{margin: 30px 0 0 -22px!important;padding-left: 22px!important}'
  2759. +'body.company .comments_list h2.comments-header,.content_left .comments_list h2.title{max-width: 1200px;padding: 15px 0 2px 25px!important;border-radius:8px;background: #f0f0e7!important;'+(ZenNCh?'margin:0 -3px 0 -17px!important;':'')+(h.inZen?'border: 1px solid #e8e8ee!important':'border-radius:16px;box-shadow: 0 0 8px #fff inset, 0 0 6px #eed!important')+'}'
  2760. +'.comments.c2 .comment_item .info div.voting{top:'+(h.inZen?3:'-2')+'px}'
  2761. +'.comments_list{overflow:visible!important; padding-left:17px!important; padding-right:3px!important}'
  2762. +'.comment_item .info a.favorite{visibility:hidden}'+(h.inZen?'':'.comment_item .info:hover a.favorite,')+'.comment_item .info a.favorite:hover{visibility:visible}'
  2763.  
  2764. +'.habrAjaxSettings{position: fixed; display: none; text-align:left; left: 61px; top: 47px; width: 320px; padding: 1px 2px 4px 2px; border: 1px solid #668; font-size:12px; background: #eee; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px;z-index: 99992}'
  2765. +'.habrAjaxSettings .group{margin: 1px 1px 1px -6px; padding: 2px 2px 2px 8px; font-weight: bold; background:#ddd}'
  2766. +'.habrAjaxSettings .sett{padding-left:6px}.habrAjaxSettings .sett:hover{background:#f4f4f4}'
  2767. +'.habrAjaxSettings input[type="checkbox"]{position:relative; margin:1px; top:3px}'
  2768. +'.habrAjaxSettings span{border:2px solid transparent; border-radius:2px}'
  2769. +'.habrAjaxSettings span.latest{margin-right:2px; border-color:#ca9!important} .habrAjaxSettings span.latest input{margin-top:-2px!important}'
  2770. +'.habrAjaxSettings span.notChecked ~label{color:#999}'
  2771. +'.habrAjaxSettings >div>div:not(:first-child) label:hover{border-bottom:1px dotted #bbb}'
  2772. +'.habrAjaxSettings.hView{padding-left: 6px}.habrAjaxSettings a{color:#25a}.habrAjaxSettings a:hover{color:#57a}.habrAjaxSettings.hView.group{background: #ddd; padding: 6px 0 8px 7px}'
  2773.  
  2774. +'a.hADotted{text-decoration: none; border-bottom:1px dotted transparent}a.hADotted:hover{border-bottom:1px dotted #69d}.hADotted.note{color:#d00}'
  2775. +'.comments-header tt tt,.comments_list >.title tt tt,.comments.c2 >.title tt tt{padding: 1px 5px 0; font-size: 14px!important; color: #666;-moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px}.comments-header tt i, .comments-header tt,.comments_list >.title tt i,.comments_list >.title tt,.comments.c2 >.title tt i,.comments.c2 >.title tt{font-size: 9px}'
  2776. +'.comment_item .message{margin-left:-4px!important;'
  2777. +' margin-right:-3px!important; padding: 0 3px 0!important;border-left:4px solid transparent}'
  2778. +'.comments.c2 .voting .plus, .comments.c2 .voting .minus, .comments.c2 .comments_form,#wrapper .comments_form,.comments.c2 .add-comment, .comments.c2 .sort{display:none}'//TODO до починки ввода
  2779. +'.info a.username,.comments >.comment_item span.username a{color: #569!important;letter-spacing: 1px}'
  2780. +'.info a.username{line-height: 11px!important;'+(ZenNCh?'margin:6px 8px 0 2px !important;':'')+'padding:0 3px 1px 4px!important;border-radius:4px;text-decoration: none!important;font-size: 10px!important;font-weight:normal!important}'
  2781. +'#wrapper .comments.c2 .info{position: relative}'
  2782. +'.comments.c2 .comment_item >span.info{background:url("'+ROOT+'/i/bg-user2.gif") no-repeat 1px 7px!important; font-size: 11px; font-weight: bold; padding-left: 14px;}'
  2783. +'.comments .comment_item >span.info a{padding:0 3px 1px 4px; border-radius:3px; color:#666!important}'
  2784. +'.userpanel .count,.user_panel .count,.userpanel .bottom a.newmail,.user_panel .bottom a.newmail{display: inline-block!important; margin: 0 4px!important; background-color: #eee!important; background-position: 3px 3px!important; padding: 0 4px 1px!important; font-weight: bold!important; color: #d63!important; border: 1px solid #999!important;border-radius:5px}.userpanel .count[href*=tracker],.user_panel .count[href*=tracker]{color: #68a!important}.userpanel:hover .count,.user_panel:hover .count{border: 1px solid #999!important}.userpanel .count:empty,.user_panel .count:empty{display: none!important}'
  2785. +'.panel-personal dd a.habrAjaxSettButt, #header .userpanel a.habrAjaxSettButt, #header .user_panel a.habrAjaxSettButt{display: none}'
  2786. +'.panel-personal:hover dd a.habrAjaxSettButt, #header .userpanel:hover a.habrAjaxSettButt, #header .user_panel:hover a.habrAjaxSettButt{display: inline-block}.userpanel .charge a,.user_panel .charge a{margin: 0 3px!important; text-decoration:none}'
  2787. +'.editor .panel a{display: inline-block!important;float:none!important;min-width: 20px;height: 20px;line-height:18px;padding: 0 6px!important;text-decoration: none!important;margin: 0!important;border-radius:5px}'
  2788. +'.editor .panel .wysiwyg_wrapper{float:left}.editor .panel >.wysiwyg_wrapper >a:hover,.editor .panel >div >b >a:hover,.comment_item .reply .editor .panel >div >a:hover,.content_left #comments_form .editor .panel a:hover{background:#fff}'
  2789. +'.editor .panel .wysiwyg_wrapper .btn{display: inline-block; height: 20px!important; line-height: 22px!important}'
  2790. +'.editor .panel .wysiwyg_wrapper .btn.btn-dropdown{float: none!important}'
  2791. +'#js-field-holder-with-help{overflow: inherit!important}'
  2792. +'.editor .panel{position: relative!important; overflow: inherit!important; z-index: 11; width: 98%!important; min-height: 22px; padding: 2px 5px 0!important}'
  2793. +'.panel select.with-title{display:none!important}'
  2794. +'.editor .panel .can_use_html{right: -4px; position: absolute; z-index:10; height: 20px!important; margin-top: 0!important; line-height: 22px!important; white-space: nowrap; color: #999!important}.editor .panel .can_use_html a{position: relative; z-index: 12}'
  2795. +'.post .infopanel >div{line-height:20px!important}.post .infopanel .voting{margin: 2px 26px 2px 0!important}.post .infopanel .voting a,.post .infopanel .voting .mark{z-index: 5}'
  2796. +'.post .infopanel .original-author,.post .infopanel .author,.post .infopanel .comments{padding-top:2px!important;padding-bottom:3px!important; font-weight:normal!important}'
  2797. +'.infopanel .original-author a{font-size:12px!important; color:#a33!important}.post .infopanel .author a{font-size:12px!important}'
  2798. +'.post .infopanel .comments{margin-left:8px!important; background-position:4px 7px!important;'+ (ZenNCh?'padding:0!important;background-color:#f4f6ff!important':'')+'}.post .infopanel .comments a{display: inline-block;padding:2px 4px 3px 21px!important;font-size:12px!important}'
  2799. +'.i-am-your-father-luke .post .infopanel{width: 94%; margin: 3px 0 0 4px!important;border: 1px solid #ddd;letter-spacing: -1px;border-radius: 5px;font-size:11px;line-height:1.7}'
  2800. +'p img[src*="error-404-monster"]{display:none}#write_message_form, #write_message_form .item{margin-bottom:0!important}'
  2801. +'#write_message_form label[for="text"]{display:none!important}'
  2802. +'.rotated_posts .rotTRow a{display: table-cell; padding:0 12px 4px!important; text-align: center;text-decoration: none!important; font-size: 13px!important; line-height:1.1!important}'
  2803. +'.rotated_posts .rotated_post{display:none!important}.rotated_posts .rotTRow a span{position:relative}'
  2804. +'.daily_best_posts .posts_list .post_item a.user_name{color:#ddd!important}.daily_best_posts .posts_list .post_item:hover a.user_name{color:#999!important}'
  2805. +'.sidebar_right .block{font-family:Verdana,Arial,Helvetica,sans-serif!important}'
  2806. +(h.inZen?'':'.sidebar_right .block{border-radius:28px; box-shadow: 0 0 20px #fff inset, 0 0 16px #eed!important}') //размытые границы сайдбара
  2807. +'.sidebar_right .block .all{text-align: right}'
  2808. +'.sidebar_right .block.float_block{position: static!important}'
  2809. +'.sidebar_right .block a{text-decoration: none!important}'
  2810. +'.sidebar_right .block .post_item,'
  2811. +'.vacancies .job_item,'
  2812. +'.tasks .task{margin-bottom: 0!important; line-height: 1.18!important; text-indent:-2ex}'
  2813. +'.Sidebar .block_brainstorage .vacancies .job_item, .Sidebar .block_freelansim .tasks .task{line-height: 1.04!important}'
  2814. +'.live_broadcast .qa_activity{margin-top: 0.8em!important; display: block!important}'
  2815. +'.sidebar_right .freelansim .title,'
  2816. +'.sidebar_right .block.new_vacanies .title{display:inline-block!important; margin-bottom: 6px!important; opacity:0.3}'
  2817. +'.sidebar_right .block.freelansim .tasks .task a,'
  2818. +'.sidebar_right .block.new_vacanies .vacancies .job_item a{font-size: 12px!important}'
  2819.  
  2820. +'.content_left .block_after_post{margin-top: 0!important}'
  2821. +'.content_left .similar_posts,'
  2822. +'.content_left .similar_questions{margin:-4px 0 0!important; padding-top: 0!important}'
  2823. +'.content_left .similar_posts .posts_list,'
  2824. +'.content_left .similar_posts:hover,'
  2825. +'.content_left .similar_questions:hover{position: static; float: none;}'
  2826. +'.content_left .similar_questions .posts_list,'
  2827. +'.rotated_posts{max-width: 1440px; margin: 0 auto!important; padding: 0 0 0 72px; border-top: 1px solid #eee!important; background: #f8f8f8}'
  2828. +(isChrome?'.content_left .similar_posts{position:relative!important; top:-1.5em;border-top:0!important}':'')
  2829. +'.content_left .similar_posts .even,'
  2830. +'.content_left .similar_questions .even{width:99%}'
  2831. +'.content_left .similar_posts .even .post_item,'
  2832. +'.content_left .similar_posts .when,'
  2833. +'.content_left .similar_questions .when,'
  2834. +'.content_left .similar_questions .even .post_item{padding: 0 3px; border-radius: 3px; background: #f2f2f2}'
  2835. +'.content_left .similar_posts .even .when,.content_left .similar_questions .even .when{background:#f8f8f8}'
  2836. +'.content_left .similar_posts .posts_list .post_item:nth-child(4n+1),'
  2837. +'.content_left .similar_questions .posts_list .post_item:nth-child(4n+1){clear:none!important}'
  2838. +'.content_left .similar_posts .posts_list .post_item:nth-child(8n),.content_left .similar_posts .posts_list .post_item:nth-child(8n-1),.content_left .similar_posts .posts_list .post_item:nth-child(8n-2),.content_left .similar_posts .posts_list .post_item:nth-child(8n-3){background:#eee}'
  2839.  
  2840. +'.block_after_post .block{padding: 3px 15px}'
  2841. +'.block_after_post .block .title{margin-bottom: 0}'
  2842. +'.rotated_posts .rotated_post a,'
  2843. +'.content_left .similar_posts .title,'
  2844. +'.content_left .similar_questions .title{display: block; padding: 0 3px 2px!important; text-decoration: none!important; font-size: 13px!important; line-height: 1.1!important; background: #f8f8f8}'
  2845. +'.content_left .similar_questions .title{position: relative; z-index: 13; top:-1.6em; float: right; height: 1.2em; margin:-3px -4em 0 -6em!important; padding: 2px 5px 4px!important; border-radius: 5px; background: #ecedf2}'
  2846. +'.content_left .similar_posts .title,'
  2847. +'.content_left .similar_questions .title,'
  2848. +'.content_left .similar_posts .post_item .when{padding-bottom: 0!important; font: 12px Arial,Helvetica,sans-serif!important}'
  2849. +'.content_left .similar_posts .posts_list,'
  2850. +'.content_left .similar_questions .posts_list{position: absolute; z-index: 12; display: none; max-width: 1540px; margin:-6px 4px 0!important; padding: 0 12px 2px!important}'
  2851. +'.content_left .similar_posts .posts_list{margin-top:'+ (h.inZen ?-0.1:0.9) +'em!important; background: #f8f8f8}'
  2852. +'.content_left .similar_posts:hover .posts_list,'
  2853. +'.content_left .similar_posts .posts_list:hover,'
  2854. +'.content_left .similar_questions:hover .posts_list,'
  2855. +'.content_left .similar_questions .posts_list:hover{display: block}'
  2856. +'.content_left .similar_posts .post_item,'
  2857. +'.content_left .similar_questions .post_item,'
  2858. +'.content_left .similar_posts .post_item .when{margin-bottom: 0!important}'
  2859. +'.content_left .similar_posts .post_item .when,'
  2860. +'.content_left .similar_questions .post_item .when{position: absolute; display: none; z-index: 2; left: 0; bottom: -1.2em; border: 1px solid #ccc; font-size: 12px!important; color: #777; background: #f8f8f8}'
  2861. +'.content_left .similar_posts .post_item:hover .when,.content_left .similar_questions .post_item:hover .when{display: block}'
  2862. +'.content_left .similar_posts .post_item .post_name,'
  2863. +'.content_left .similar_questions .post_item .post_name{display: inline; text-decoration: none!important}'
  2864. +'.content_left .similar_posts .post_item .post_name{color: #6da3bd!important}'
  2865. +'.content_left .similar_posts .post_item .post_name:hover{color: #4d7285!important}'
  2866. +'.content_left .similar_posts .post_item,'
  2867. +'.content_left .similar_questions .post_item{position: relative; display: inline-block; vertical-align: middle!important; width: 24%!important; margin-right: 0!important; padding-bottom: 1px!important; line-height: 1.14!important; text-indent: 0}'
  2868. +'.post .published{float: right; margin: 3px 0 -4px 4px!important}'
  2869. +'.post .content .buttons{display: inline-block!important; padding: 0!important}'
  2870. +'.post .content .buttons a.button,'
  2871. +'.post .content .buttons input[type="button"]{position: relative; padding: 0 2px 1px!important; border: 0!important; border-radius: 2px!important; background: transparent!important; color: #6da3bd!important; box-shadow: 0 0 2px rgba(255,255,255,0.4) inset, 0 0 2px rgba(0,0,0,0.2)!important}'
  2872. +'.buttons a.button{height: 1.3em!important; top:-1px!important; line-height: 1.3em!important}'
  2873. +'.post .content .buttons input[type="button"]{color: #367!important}'
  2874. +'#comment_form #send_msg,'
  2875. +'#post_form #send_msg, #write-post #send_msg, #comments_form input.submit, #write_message_form input.submit, #add_message_form input.submit{margin-left: 60px !important}'
  2876. +'.post .content .buttons a.button:hover{background: #f4f4f9!important}'
  2877. +'.post .content .buttons a.button:visited{color: #b98!important}'
  2878. //футер
  2879. +'.page-nav #nav-pages,.page-nav{margin: 0 -20px; padding: 0 0 1px 1px!important}'
  2880. +'.page-nav ul.next-prev li{padding-right: 0.3em!important}'
  2881. +'.page-nav #nav-pages{position: fixed; z-index: 1001; bottom: -1px; margin: 6px 0!important;opacity: 0.5;filter: alpha(opacity=50)}'
  2882. +'.page-nav #nav-pages:hover{opacity: 1; filter:none}'
  2883. +'.page-nav #nav-pages li{margin: 0!important}'
  2884. +'.page-nav #nav-pages li a,.page-nav #nav-pages li em{margin: 0 1px!important;padding: 2px 24px!important;border: 1px solid #ddc!important;border-radius:5px;text-decoration: none!important;font: 18px Verdana,Arial,Helvetica!important;background-color: #fdfdf4}'
  2885. +'.page-nav #nav-pages li em{border: 1px solid #3E8592!important; background-color: #7a9bac}'
  2886. +'.page-nav #nav-pages li a:hover{margin: -1px!important;padding: 3px 26px!important;border: 1px solid #8ab!important;background:#C5DAE5!important}'
  2887. +'#footer{position:relative; width: auto!important; min-width: 314px!important; max-width: 1440px; margin: 0 auto 20px!important; padding: 6px 0 22px!important}'
  2888. +'#footer .bottom_menu{width: 100%!important}'
  2889. +'#footer a{text-decoration: none!important}'
  2890. +'#footer dl{width: 46%!important; float:right}'
  2891. +'#footer dl:last-child{display:none}'
  2892. +'#footer dt{float:left; width: 4em; margin: 0!important; line-height: 120%!important}'
  2893. +'#footer dt:after{content:":"}'
  2894. +'#footer dd:not(:last-child):after{content:","}'
  2895. +'#footer dd{float:left; margin: 0 0 0 6px!important; line-height: 120%!important}'
  2896. +'#footer .copyright{position: relative; left: 7%; width: auto!important; float: none!important; margin-right: 12px!important}'
  2897. +'#footer .copyright .footer_logo{margin:0!important; position:absolute; left: -21px!important}'
  2898. +'#footer .copyright .about{float:left!important; width: auto!important; vertical-align: middle!important; margin:0 0 0 2px!important}'
  2899. +'#footer .about br,#footer .copyright .about br,body >img[src*="habr.statis.tk/c?"]{display: none}'
  2900. +'#footer .about >a{margin-left: 10px!important}'
  2901. +'#footer .about div,#footer .social_accounts{display: inline-block; height: 1.2em!important; margin: 0!important}'
  2902. +'#footer .social_accounts a{margin-bottom: -8px!important}'
  2903. //просмотр картинок
  2904. +'.de-img-pre, .de-img-full{border: medium none; cursor: pointer; display: block; margin: 2px 6px; outline: medium none}'
  2905. +'.de-img-thumb{cursor:move}.commInfo .imgL .de-img-pre,.commInfo .lnk .de-img-pre{margin: 4px 0;display:none}.commInfo .imgL:hover .de-img-pre,.commInfo .lnk:hover .de-img-pre{display:inline}'
  2906. +'.content ._noAddOwnView,.html_format img.de-img-full,.html_format img.de-img-pre,.post .content img.de-img-full,.post .content img.de-img-pre{max-width: none!important; max-height: none!important}.de-img-pre{background-color: rgba(230,230,230,0.6)}'
  2907. +'.de-img-full{float: left}'
  2908. +'.aPrevi .de-img-pre{display:none}'
  2909. +'.de-img-center{background-color: rgba(244,244,244,0.9); border: 1px solid black; position: fixed; z-index: 9999}'
  2910. +'.de-menu{position: absolute; z-index: 10; display: inline-block; padding:3px 6px; background:rgba(238,238,238,0.76); border-radius: 4px}'
  2911. +'.de-menu a{display:block}.de-menu a:hover{background:#ddd}'
  2912. +'.de-menu a img{height:16px; vertical-align:middle}'
  2913. +'.comments.c2 .comment_item .comment_body >.reply a.abuse_link{display:none; margin-top:0!important}.info a.link_to_comment{left: 15px!important;top:-5px}'
  2914. +'.comments_list .comment_item .comment_body:hover >.reply a.abuse_link{position: relative; display: inline-block!important; float: right; width: 2.3em; height: 15px; overflow: hidden; left: 1.7em; top:-2px; margin-top:-15px!important; border-radius: 4px; background-color:#f2f2e4; color: #8ca!important}.comments_list .comment_item .comment_body:hover >.reply a.abuse_link:hover{width: auto; overflow: inherit}'
  2915. +'body[bgcolor="white"]{min-width: 624px!important}body[bgcolor="white"] .stars{max-width: 640px!important}#habr_center_universe{left: 312px!important}.hajax404{width: 99%; padding: 4px 2px; border: 1px solid #ddd; background: #eee;}.under404{margin-bottom:60px; background-color:rgba(230,230,230,0.5)}'
  2916. +'.hoverView{display: inline; line-height: 1.3; color:#862}'
  2917. +'.hoverView a{font-style:italic; text-decoration: none; color:#ccc}'
  2918. +'.hoverView .hovered,.hoverView +.hovered,.hoverView.hovered{position: absolute; visibility: hidden; margin:-1px 3px 0 -12px; padding-left: 2px; background-color:#fff; border:1px solid #ddd; border-radius:5px}'
  2919. +'.hoverView:hover .hovered,.hoverView:hover +.hovered,.hoverView:hover.hovered{visibility:visible; line-height:1.2}'
  2920. +'.habrAjaxInfo{margin:2px 2px 0; padding-top:2px; background-color:#fff; border:1px solid #ddd; border-radius:5px; font-size: 12px; color:#999}.habrAjaxInfo a{color:#497DA5;text-decoration: none}'
  2921. +'.habrAjaxInfo button{height: 1.4em; margin:-2px 2px 0 2px; padding: 0 11px 1px; line-height: 1.2em;'
  2922. +'box-shadow: 0 0 2px rgba(255, 255, 255, 0.4) inset, 0 0 2px rgba(0, 0, 0, 0.2); transition-duration: 0.2s; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); border-radius: 4px; border: 1px solid #9d9471; border-color: #9d9471 #8596aa #7b8a9d; background-color: #b4cbe6/*#cfe8c4*/;color:#237}.habrAjaxInfo button:hover{background-color: #def2fd/*#fcfcfc*/;}'
  2923. +'.habrAjaxInfo .imgDimens{text-align: center}'
  2924. +'.habrAjaxInfo button.previ{float:left; width:60px; height:2.6em; line-height: 1em; margin:-1px 0 0 -11px; border:1px solid #ead7b6; background-color:#fff3d2}.habrAjaxInfo button:hover.previ{background-color:#fffcf8}'
  2925. +'.habrAjaxInfo button.previCancel{width:40px;border:1px solid #dee7fd; background-color:#effeff}'
  2926. +'.habrAjaxInfo input{width: 4.5em; border:1px solid #bcd; margin:-1px 14px 0 4px; text-align: center}'
  2927. +'.habrAjaxInfo input[type=radio]{width:auto; margin:-1px 3px 0;vertical-align:middle;}'
  2928. +'.habrAjaxInfo .radios span,.habrAjaxInfo .radios label{display: inline!important;font-weight: normal!important;background:#ede7e4;color:#999}'
  2929. +'#resizeWidth::-moz-placeholder,#resizeWidth2::-moz-placeholder, #aUrl::-moz-placeholder{color:#aac; background:#efeff8}#resizeWidth::-webkit-input-placeholder,#resizeWidth2::-webkit-input-placeholder,#aUrl::-webkit-input-placeholder{color:#ddd; background-color:#fafafa}'
  2930. +'#resizeHeight::-moz-placeholder,#resizeHeight2::-moz-placeholder{color:#aac; background:#efeff8}#resizeHeight::-webkit-input-placeholder,#resizeHeight2::-webkit-input-placeholder{color:#ddd; background-color:#fafafa}'
  2931. +'.preImgSend{position: absolute; display:none; width:98%; top:-4.2em; margin-left:3px; text-align: justify; background:#ede7e4;}'
  2932. +'#header_mouse_activity{display: block!important; height:12px!important}#header_bg{height:7px!important}'
  2933. +'.radios >.radios2 >.rAll{display:none!important}.radios >.radios2:hover >.rAll{display:inline!important}'
  2934. +'.habrAjaxInfo.droppedF{position:absolute; display:none; top:0; min-height:110px}'
  2935. +'.habrAjaxInfo.pixList{min-height:110px}'
  2936. +'.habrAjaxInfo .imgDate{position: absolute; display:none; top:-1.46em; padding:0 6px; border: 1px solid #ada7a4; white-space:nowrap; background: #ede7e4}'
  2937. +'.habrAjaxInfo .overUrl{position:relative; display:inline-block; line-height: 0.03}.content_left .habrAjaxInfo{line-height: 0.03}'
  2938. +'.habrAjaxInfo .overUrl:hover .imgDate{display:inline-block; line-height: 1.3}'
  2939. +'#TMpanel .menu.special, .special_navbar_image,'
  2940. +'#navbar .nav_tab .line +.title, #navbar .nav_tab .line +.title +.menu{display: none!important}'
  2941. +'.saveCompaSideTitle{margin-top: 0.5em; padding-left:6px; background: #acf; color:#669}'
  2942. +'#TMpanel, #TMpanel .container, #layout{min-width:auto}';
  2943. var zz = hS.inZen ||{}; //встроенная версия ZenComment
  2944. zz.desc = zz && zz.desc && typeof zz.desc =='string' && zz.desc.replace(/@/g,"430");
  2945. addRules((hS.inZen.val ?'body{text-align: inherit!important;font-family: Verdana,sans-serif!important} #layout{width:auto!important;min-width: 314px!important;max-width: 1420px!important;height: auto!important;margin-right:auto!important;margin-left:auto!important;padding-top: 0!important;padding-right: 0!important;padding-left: 0!important} #layout .inner{margin: 0!important;padding-bottom:30px!important} #wrapper{margin: -15px 0 1px!important;width: auto!important;padding: 20px 0 4px 6px!important;overflow: hidden;min-width: 314px!important} .comments.c2 >.comment_item .info .voting,.comments_list >.comment_item .info .voting{display:block!important} .comments.c2 >.comment_item .info time,.comments_list >.comment_item .info time,.conversation_page .messages .message .info .time{visibility: visible} .comments.c2 .comment_item .info a.username,.comments_list .comment_item .info a.username,.conversation_page .messages .message .info .login a{visibility: visible!important} .comments.c2 .comment_item,.comments_list .comment_item{ margin-top: 1px!important;margin-right:-2px!important;padding-top: 9px!important;border-right: 2px solid #fff!important;background:#fff!important} .comments_list:hover >.comment_item:not(:hover) .comment_item:last-child:not(:only-of-type) >.reply_comments{border-left: 2px solid #fff!important} .comments_list:hover >.comment_item:not(:hover) .reply{border-top: 1px solid #fff!important} .comment_item .message{width: 100%}.App{overflow: hidden} .header,#header{width: 100%;height: 13px;top:1px;min-width: 314px!important;margin:0;padding:5px 0 0!important} #header .userpanel,#header .user_panel{ position: fixed!important;top: 0!important;right: 0;left: auto!important;z-index: 10026;float: right;width: auto!important;height: 15px;padding: 0 6px 2px!important;font-size: 12px;border-bottom: 1px solid #999!important;border-left: 2px solid #666!important;border-bottom-left-radius:5px;background-color: #ccc;opacity: 0.5;filter: alpha(opacity=50)} .page_head{line-height: 0} .page_head h2.title{font-size: 13px!important;position: relative;top: 1.8em;left: 1ex} .page_head .controls{position: absolute;left: 5px;top: 2.8em} .page_head .controls .new_hubs{position: relative;top: -5px;} #TMpanel{display: block!important;z-index: 99992!important;width:auto!important;right: auto!important;left: 140px!important;min-width: 0!important;height: 4px!important;border: 0!important;text-align: left!important;background: transparent!important;-webkit-transition: left 1s;-moz-transition: left 1s;-o-transition: left 1s;transition: left 1s;} #TMpanel .container{overflow:inherit!important;min-width:0!important;height:4px!important} #TMpanel .menu{margin-left:-12px!important;line-height: normal!important} #TMpanel .container .menu{display: block!important} #TMpanel .menu a{max-width:5.2ex!important;overflow: hidden;margin: 0 6px!important;padding: 0 4px!important;white-space: nowrap;background-image: linear-gradient(#d3e2f0 20%,rgba(238,238,238,0.3) 90%);color: transparent!important;opacity: 0.65} #TMpanel .menu a:last-child{margin-right: -9ex!important} #TMpanel .menu a.current{display: none!important} #TMpanel .menu:hover a{text-decoration: none!important;background-color: #f0f4fa;color: #47a !important;opacity: 1} #header .user_panel{font: 12px/14px Arial,Helvetica,sans-serif!important} #header .userpanel:hover,#header .user_panel:hover{background-color: #fff;opacity: 1;filter: none} #header .userpanel .top,#header .user_panel .top{ float: right;display: inline-block;white-space: nowrap;text-align: right} #header .userpanel sup{vertical-align: baseline!important} #header .userpanel a,#header .user_panel a{text-decoration:none!important} #header .userpanel a.username,#header .user_panel a.username{margin-left: 1px} #header .userpanel a.nav-settings,#header .user_panel a.nav-settings{ display: none;float: left;margin: 0 0 0!important} #header .userpanel:hover .top a.nav-settings{display: inline-block;position: relative;top:0} *|html[xmlns*=""] #header .userpanel:hover .top a.nav-settings{position: relative;top: -1.3em}*|html[xmlns*=""] #header .user_panel:hover .top a.nav-settings{position: relative;top: -1.3em} #header .userpanel a[href*="login"],#header .user_panel a[href*="login"]{display: inline-block!important;float: right} #header .userpanel a[href*="logout"],#header .user_panel a[href*="logout"]{display: inline-block;width: 12px;margin-right: 3px!important;background: no-repeat 0% 50% url(data:image/gif;base64,R0lGODlhDAAKAIABAN3d3f///yH5BAEAAAEALAAAAAAMAAoAAAIYhB+plhyw4JPOqQbZ2XvyfmGTOJZVBF4FADs=);color: transparent!important} #registration_page,#login_page{padding: 0 22px!important} #header .userpanel .bottom,#header .user_panel .bottom{float: left;margin-right:6px!important} #header .userpanel a[href*="sandbox/add"],#header .userpanel a[href*="register"],#header .user_panel a[href*="register"]{display: none;float: left} .userpanel .bottom a,.user_panel .bottom a{display: none;margin:-1px 0 0!important;padding:1px 3px 2px!important} .userpanel:hover .bottom a,.user_panel:hover .bottom a{display: inline-block} .userpanel .bottom a:hover,.user_panel .bottom a:hover{display: inline-block;background-color:#f2f4f8!important} .userpanel:hover .bottom a.nav-settings,.user_panel:hover .bottom a.nav-settings{display: inline!important} #header .userpanel:hover a[href*="register"],#header .user_panel:hover a[href*="register"]{display: block} .userpanel .count,.user_panel .count{ display: inline-block!important;margin: 0 4px!important;background-color: #eee!important;background-position: 3px 3px!important;padding: 0 4px 1px!important;font-weight: bold!important;color: #d63!important;border: 1px solid #999!important;border-radius:5px} .userpanel .count[href*=tracker],.user_panel .count[href*=tracker]{color: #68a!important} .userpanel:hover .count,.user_panel:hover .count{border: 1px solid #999!important} .userpanel .count:empty,.user_panel .count:empty{display: none!important} #header .userpanel .charge,#header .user_panel .charge{ position: absolute;display: none!important;width: 10.5em;right: 10px;margin: 0!important;padding: 0 3px 1px!important;border: 1px solid #999!important;border-radius:3px;text-align: right;font-size: 9px;font-family: Tahoma,Arial,sans-serif;color: #59d!important;opacity: 0.5!important} #header .userpanel:hover .charge,#header .user_panel:hover .charge{ float: right!important;display: inline-block!important;white-space: normal;top: 16px;background: #fff} #header .userpanel .charge:hover,#header .user_panel .charge:hover{opacity: 1!important} .header .logo,#header a.logo{ position: fixed;z-index: 10027;width: 86px!important;height: 78px!important;left: 0;top: 0;margin: -60px -55px 0!important;background-position: 50% -144px!important;border-bottom-right-radius:5px;background-color: #ccc!important;opacity: 0.5;filter: alpha(opacity=50)} .header .logo:hover,#header .logo:hover{background-position: 50% -274px!important} #header .search,#header .search_panel{ position: absolute!important;top: -1px!important;right: 178px!important;z-index: 25!important;width: 240px!important;margin: 0!important} #header .search #search_form input[name="q"],#header .search_panel #search_form input[name="q"]{ float:none!important;width: 214px!important;margin-right: 0!important;padding: 0 3px 1px!important;border-radius:3px;-webkit-box-shadow: 0 2px 10px #eee inset;box-shadow: 0 2px 10px #eee inset;font-size: 14px!important;opacity: 0.8;filter: alpha(opacity=80)} #header .search input[name="q"]:focus,#header .search_panel input[name="q"]:focus{ border-color: #5699D8!important;outline: 0!important;-webkit-box-shadow: 0 2px 10px #eee inset,0 0 2px #5ec6fb;box-shadow: 0 2px 10px #eee inset,0 0 2px #5ec6fb;color:#333!important;opacity: 1;filter: none} #header .search #search_form input[type="submit"],#header .search_panel #search_form input[type="submit"]{display:none!important;float: right!important;margin-left: -21px!important;padding: 1px 3px!important;color:#666!important} #header .search #search_form input[type="submit"]:not([value=""])#header .search_panel #search_form input[type="submit"]:not([value=""]){clear: both} form#search_form{width: 245px!important;height:21px} #header .search form#search_form:hover input[type="submit"]{display: block!important} #header .search form#search_form:hover input[type="submit"],.autocomplete{ z-index: 25!important;margin: -2px 0 0 1px!important;border: 0!important;border-radius:0 0 5px 5px;-webkit-box-shadow: 0 0 10px rgba(0,0,0,.3);box-shadow: 0 0 10px rgba(0,0,0,.3);} .autocomplete div{position: relative!important;border: 0!important;z-index: 50!important} .autocomplete div:hover{border-bottom-color: #fff!important} .autocomplete >div:last-child{border-radius: 0 0 5px 5px} #header .main_menu{ position: fixed!important;width: 16px!important;height: 20px;min-width: 1.4em!important;top: 0;left: 0;overflow: hidden;z-index: 10027;margin: -5px 0 0 7px!important;padding: 1px 0 0!important;border: 1px solid #999!important;border-right: 2px solid #666!important;font-size: 18px!important;background-color: #ccc;opacity: 0.5;filter: alpha(opacity=50)} #header .main_menu:hover{ overflow: visible;width: auto!important;background-color: #fff;opacity: 1;filter: none} #header .main_menu a{font-size: 18px!important;margin-right: 10px!important} #header .main_menu a.date{margin: 3px 6px 0 -1px!important;letter-spacing:-1px;font-size: 11px!important;color:#000!important} .main_menu a[href*="companies"]{display:inline-block;width: 1.25ex;overflow: hidden} .main_menu a:hover[href*="companies"]{width: auto;margin-right: 3px!important} #header_bg{position:absolute!important} .company_header,.profile-header{height: 28px!important;margin-bottom:-10px!important;padding:13px 0 0 5px!important;font-size:inherit!important} .inner .company_header .company_icon img{position: absolute;z-index: 3;margin-top: 5px!important} .company_header .name{margin: 0 26px -10px 51px!important} .company_header .name a,.company_header .rating{margin-bottom: -10px;font-size: 180%!important} .profile-header .profile-actions dt{font-size: 220%!important;padding-top: 6px!important} .profile-header h1{margin: 0!important} .profile-header h1 .favicon{margin-top: 6px!important} .profile-header dt{margin-bottom: -3px!important} #navbar{position:fixed!important;width:100%!important;max-width:1420px;margin-right:auto!important;margin-left:auto!important;bottom: auto!important} #scroll_to_top{display: none!important} #navbar .nav_panel{width: 100%!important;height:0!important;bottom:auto!important} #navbar a.logo{float: left;width: 32px!important;height: 20px!important;border-bottom-right-radius:3px;background-image: url(http://habrahabr.ru/images/navbar.sprite.v2.x1.png)!important;background-size: 500px 200px!important;background-position: -426px -25px!important} #navbar a.logo[href*=geektimes]{ width: 30px!important;background-image: url(http://geektimes.ru/images/logo.svg)!important;background-size: 100px 60px !important;background-position:-22px -19px!important} #navbar a.logo[href*=megamozg]{ width: 30px!important;background-image: url(http://megamozg.ru/images/logo.svg)!important;background-size: 51px 40px !important;background-position:-10px -10px!important} #navbar a.tab{ position: absolute!important;width: 32px!important;height: 20px!important;right:0;padding: 0 6px!important;border-bottom:0!important;border-radius: 0 0 6px 6px} #navbar a.tab:hover{background-color: #eaeffd!important} #navbar a.tab_user{left: auto!important} #navbar a.tab_user,#navbar a.tab_settings{float:right} #navbar a.tab_user img{ width: 20px!important;height: 20px!important;top: 0!important;left: 14px!important;border-radius: 0 0 4px 4px!important;} #navbar .nav_panel{opacity:0.5} #navbar .nav_panel:hover{opacity:1} #navbar .nav_panel .tab{line-height: normal!important} #navbar a.tab_tracker{height: 25px!important;left: 31px!important;margin-top:-5px!important;padding-left:9px!important} #navbar a.tab_menu{display: none!important;position: absolute;left: 74px!important;height: 18px!important;padding:2px 13px 1px!important} #navbar a.tab_add_post{ visibility: hidden;float: right;height: 30px!important;right: 44px;margin-top:-10px!important} #navbar a.tab_settings{ display: none!important;position: absolute;height: 26px!important;left: auto!important;right: 88px;margin-top:-6px!important} #navbar #print_tab{display: none!important} #navbar a.tab_user:hover ~ a.tab_add_post,#navbar a.tab_add_post:hover{visibility: visible} #navbar a.tab_add_post:hover + a.tab_settings,#navbar a.tab_settings:hover,#navbar a.tab_tracker:hover + a.tab_menu,#navbar a.tab_menu:hover,#navbar a.logo:hover + a.tab_menu{display: block!important} #navbar a.logo + a.tab_menu{left: 32px!important} .g-icon-alarm:before{position: relative;top: -4px;color: rgba(153,153,153,0.25)} .g-icon-alarm:hover:before{color: rgba(85,153,216,0.24)} .g-icon-burger:before{position: relative;top: -8px;color: rgba(85,153,216,0.25)} .g-icon-burger:hover:before{color: rgba(85,153,216,0.37)} .g-icon-write:before{color: rgba(85,153,216,0.43)} .g-icon-gear:before{color: rgba(85,153,216,0.35)} #navbar .nav_panel .tab.open:not(:hover){background: transparent!important} #navbar .nav_panel .tab.open:before{width:0!important} #navbar .nav_panel #print_tab{top:-22px;right:129px} #navbar a.tab:after{ position:relative!important;float:right;top: 0!important;right: 4px!important} #navbar .tab .count{z-index: 2;} #navbar .nav_tabs_content{position:relative!important;width: 100%!important;overflow:inherit!important} #navbar .nav_tabs_content .nav_tab{top: 0!important;left: -200px;bottom: auto!important;opacity: 0.75} #navbar .nav_tabs_content .nav_tab .title{background-color:#999} #navbar .open #menu_tab{top: -5px!important;left: 60px!important} #navbar .open #user_tab{top:-8px!important;left: auto!important;right:7px!important} #navbar .open #tracker_tab{top:11px!important;left: 3px!important} #navbar .open #settings_tab{left: auto!important;right:70px!important} #navbar .nav_tabs_content .nav_tab .title{padding-top: 5px!important} #navbar .menu a{font: 14px Arial,Helvetica,sans-serif;color: #3b73af!important} #navbar .nav_tabs_content .nav_tab .menu a.exit{ position: static!important;bottom: auto!important;left: auto!important;padding: 10px 25px!important;right: auto!important} #navbar .nav_panel .tab.tab_settings,#navbar .nav_panel .tab.tab_login{ position: relative;border-bottom: 1px solid #EBEAEA;border-top: 0 none;bottom: auto} #navbar .nav_panel .tab.tab_login{left: auto;right: 0} #navbar .nav_panel .tab.tab_login span{position: relative;top:-3px;font-size: 23px} #navbar_overlay{background: none repeat scroll 0 0 rgba(0,0,0,0.17)!important} #navbar #menu_tab .title{padding-left: 80px!important} #navbar .nav_tab .line +.title,#navbar .nav_tab .line +.title +.menu{display: none!important} #js-addFan,#js-addWorker{margin: 6px 0 0!important} .profile-karma-holder{margin: -10px 8px!important} .company-header .profile-karma-holder{margin: 0 12px 0 0!important} .profile-header .vote_holder .mark span{position: relative!important;top: 5px!important;font-size: 75%!important} .profile-header .profile-actions dt,.profile-karma-holder .karma{background: transparent!important} .profile-karma-holder >dl >dt,.profile-header .habraforce >dt{font-size: 9px!important} .profile-header .habraforce .number{ height: 30px!important;margin: -13px 0 -4px!important;padding: 15px 0 0!important;font-size: 220%!important} .profile-header .karma .total{margin-top: -2px!important} .profile-header .karma .total em{padding: 0 2px;background: #fff;font-size: 9px!important} .habraforce{background: transparent!important} .profile-header .karma a{margin-top: 4px!important} .profile-header .karma dt,.profile-header .karma .total,.profile-header .habraforce dt,.profile-header .habraindex dt,.habraindex dt{color: #999!important} .profile-header .habraindex .number{font-size: 200%!important} .profile-header .karma dd.vote{overflow: visible!important} .user-actions dd,.user-actions dt{border-radius:5px!important} .profile-actions-menu{padding: 2px 3px!important;border-radius:5px!important;-webkit-box-shadow:0 0 15px rgba(0,0,0,.3);box-shadow:0 0 15px rgba(0,0,0,.3);border-color: #397dbd!important} .profile-actions-menu .cor-1px{border-radius:5px!important;border: 0!important} .popup-text-field{border:1px #ceceaf solid;border-radius:5px;background-image: none!important;-webkit-box-shadow:0 0 15px rgba(0,0,0,.3);box-shadow:0 0 15px rgba(0,0,0,.3)} .popup-text-field div{background-image: none!important} .user_profile{width: 99%!important} .user_profile dl{margin-bottom:5px!important} .user_profile .fullname{margin:0 0 5px!important;padding: 2px 0 0 36px!important} .user_profile #people-tags li{margin-bottom: 0!important} .user_profile .dl_logic_wrap{margin: 0 0 2px!important} .user_profile .hubs_list ul,.user_profile .dl_logic_wrap ul,.user_profile .friends_list ul{max-height: 120px;overflow-y: auto!important} .user_profile #people-tags a{height: auto!important;min-height: 28px} .user_profile #people-tags a.habred{display: none!important} .user_profile #people-tags li{padding-bottom: 5px!important} .user_profile #people-tags{padding-top: 2px!important} .user_profile dl{margin: 0 0 3px!important} .page-navigation{overflow: inherit!important;margin-bottom: 5px!important} .hub_header{margin: -6px 0 0 26px!important;padding:0!important} .hub_header h2 a{font-size: 20px!important} .hub_header h2 span.profiled_blog{z-index: 3} .hub_header .hub-index .label{line-height:18px!important} .hub_header .hub-index .value{font-size: 18px!important;line-height:6px!important} .user_header h2.username a,.hub_header .hub_title{color: #6da3bd!important} .user_header h2.username,.user_header .karma .score .num,.user_header .rating .num{font-size: 24px!important} .user_header h2.username a:hover,.hub_header h2 .hub_title:hover{color: #84b18a!important} .user_header a.avatar{top: 21px;left: 1px} .content_left{width: 240px;min-width: 74%;margin-right: 0!important;padding:0!important} .content_left .add_post{position: relative;left: 35px;opacity: 0.5;filter: alpha(opacity=50)} .content_left table.menu{word-wrap:break-word} .content_left table.menu tr td a,.Header ul.topmenu li a{padding: 9px 0 7px!important;display: inline-block!important;width: 100%;font-size: 12px!important} .content_left table.menu .profile a{position:relative;z-index:2;opacity:1!important} .content_left table.menu .profile a:hover{opacity:0.9} .content_left .submenu{position: relative;display: inline-block;z-index: 3;height: 22px;top: -13px;margin: -13px 0 -9px!important} .content_left .post{overflow: inherit!important;margin:12px 0 32px!important} .content_left .company_post .post{margin-bottom: -5px!important} h1{letter-spacing:0!important} .content_left .post h1.title{ margin: 3px 0 -3px!important;padding-left: 25px!important;font: 16px/118% normal Verdana,Tahoma,sans-serif!important} .content_left .post h1.title .post_title{ line-height: 16px;font-size: 16px;text-decoration: none!important;color: #257!important} .post h1.title .locked{background-position: 2px 0!important} .content_left .post h1.title .post_title:visited{color: #977!important} .App >.container{padding: 0!important} .App >.container .left_column{width: 240px!important;min-width: 74%;padding-right: 0!important} .Filter{margin:0 0!important;padding: 0 0 6px 2px} .Posts >ul{padding: 0 0 0 24px!important} .Posts >ul li{clear: both;position: relative;margin: 0!important} .Posts >ul li h2{ width: 100%;margin-right: -80px!important;padding: 0 0 0 115px!important;text-indent: -2ex;font: 13px/1.1 Verdana,Tahoma,Helvetica,sans-serif!important} .Posts >ul li h2 a{display: block;min-height: 2.5em;text-decoration: none!important;color: #000!important} .Posts >ul li h2 a:hover{background-color: #f2f2f2!important} .Posts >ul li h2 a:visited{color: #735!important} .Posts >ul li h2 a:active{color: #d12!important} .Posts >ul li .meta{ overflow: hidden;position: relative;width: 110px;height: 32px;margin: -32px 0 0 -22px!important;padding: 0 0 0 6ex!important} .Posts ul li .meta .item.highlighted{border-radius: 5px;background-color: #ddd!important} .Posts >ul li .meta .favicon{position: relative;z-index: 2;border-radius: 7px} .Posts >ul li .meta .favicon.habrahabr{margin-left:-7px;opacity: 0.62} .Posts >ul li .meta .favicon.geektimes{opacity: 0.6} .Posts >ul li .meta .favicon.megamozg{margin-left: 6px;opacity: 0.5;box-shadow: 0 0 2px 4px rgba(160,90,72,0.65) inset} .Posts >ul li .meta .time_published{position:absolute;display: inline-block;overflow: hidden;top: 0;right: 0;margin-right: -7.5ex} .Posts >ul li .meta .comments_count{position:absolute;top: 14px;right: 1ex;margin: 0!important;padding: 0!important} .Posts >ul li .meta .comments_count span{display: inline-block;overflow: hidden;width: 4.8ex;vertical-align: bottom;margin-right: 6px;color: #c7c7c7} .Posts >ul li .meta .comments_count b{color: #b56} .Posts >ul li .meta .reading_count{position:absolute;top: 15px;right: 56px;font-size: 10px;color: #bbb} .Posts >ul li .meta .reading_count.highlighted{color: #aaa} .Posts >ul li .meta .reading_count b{margin: 0 -3px} .Posts >ul li .meta .favorites_count{position:absolute;top: 2px;right: 72px;color: #9f6036} .Posts >ul li .meta .score{position:absolute;z-index: 1;top: 6px;right: 31px} .Posts >ul li .meta .score b{color: #8b4} .Posts >ul li .reading_count span,.Posts >ul li .favorites_count span,.Posts >ul li .score span{display:none} .container >.Sidebar{display: block!important} .content_left .company_post h1.title .post_title{font-size: 18px!important;font-weight: normal} .content_left :not(.company_post) .post h1.title .post_title:hover{color: #84b18a!important} .title sup{ padding:0 4px!important;font: 13px/118% normal Verdana,Tahoma,sans-serif !important;font-size-adjust: 0.45;font-variant: small-caps;vertical-align: 2px!important;border-radius: 4px;} .post h1.title .translation{background-color:#def!important} .content_left .post .hubs{float: right;position: relative;z-index:2;margin: -1px 8px -3px -12px!important;white-space: nowrap;opacity: 0.7;background: 0 0!important;color: transparent!important} .content_left .hubs +.content{clear: both} .content_left .hubs .profiled_hub{display: inline-block;vertical-align: top!important;height: 9px!important;margin:0 -4px 0 1px!important;font-size:5px!important;background-color: #cbd6ce} .post .content ul li,.post .content ol li{position: relative;left: 11px;margin: 0 6px 0 0!important;padding-left:6px!important} .aaaa{margin: -2px -3px -2px -7px;padding: 2px 3px 2px 7px;} .content_left .event,.content_left .post .content,.content_left.post .content{ max-width: 1200px;min-height: 2px;margin: 6px 4px 6px 9px!important;padding-right:2px!important;padding-left:24px!important;word-wrap: break-word;line-height: 1.31!important;font-size: 13px!important} .content.html_format >h3{font-size:14px!important} .content.html_format >h2,.content.html_format >h1{font-size:16px!important} .content_left .post >.hubs +.content{margin: 0 4px 0 9px!important} .comment_item .message img[align="left"],.comment_item .message img[align="right"],.content img[align="left"],.content img[align="right"]{max-width: 50%!important} .comment_item .message img[align="left"],.content img[align="left"]{margin: 2px 15px 2px -2px!important} .comment_item .message img[align="right"],.content img[align="right"]{margin: 2px -2px 2px 15px!important} .post .content ul,.post .content ol{margin: 6px 9px 6px 18px!important;list-style: decimal inside none!important;text-indent:-0.75em} #wrapper .comment_item .message pre,#wrapper .comment_item .message code,.content_left .comments_list .comment_item .message pre,.content_left .comments_list .comment_item .message code,.content_left .post .content pre,.content_left .post .content code{ max-width: 100%;overflow: auto;line-height: 1.3!important;font-size:100%!important} .content_left .post .content br+br,.content_left .post .content h4+br,.content_left .post .content pre+br{display: inline-block!important;height: 10px!important;line-height: 10px!important} *|html[xmlns*=""] .content_left .post .content br+br,.content_left .post .content h4+br,.content_left .post .content pre+br{display: block!important} .comment_item >.message br+br,.comment_item >.message blockquote+br{display: inline-block!important;height: 6px!important;line-height: 6px!important} *|html[xmlns*=""] .comment_item >.message br+br,.comment_item >.message blockquote+br{display: block!important} .content >blockquote,.message >blockquote{margin:2px 0!important;padding-left: 6px!important} .content .vSpace,.comments .vSpace,.content .vSpace3,.comments .vSpace3,.comments_list .vSpace,.comments_list .vSpace3{width:3.6em;height:4px;margin:-1px 0 -3px 1.6em!important;background:#ddd} .content .vSpace3,.comments .vSpace3,.comments_list .vSpace3{width: 2.8em;height: 2px;margin: 0 0 -2px 1.6em!important} .content_left .post .content iframe{max-width:100%} .post .content a[name="habracut"] .btnBack{margin: 1px 12px -1px 0;padding-left: 3px;border: 1px solid #b3d2ee;border-radius: 3px;background: #d3e2f0;cursor: pointer} .content_left .post .content a[name="habracut"] .btnBack.inln{display: inline-block;width: 1.2em;height: 16px;margin: 0 2px;overflow: hidden;vertical-align: middle} .post div.btnBack,.btnBack{margin: 3px 1px -8px 0} #layout >.content_left .post div.tags,.content_left .post ul.tags{ position:relative;float: right;max-width: 1200px;margin: -5px 10px -10px 52px!important;padding: .2em 0 3px 19px!important;background-position: 2px 3px!important;background-color: transparent!important;color:#888!important} ul.tags li a,ul.tags li{font-size: 10px!important} ul.tags li a{text-decoration:none!important} .post ul.tags li a:hover{background-color:#fffcf8;color:#333!important} .post .content .poll table.result tr td{width: 90%!important;border: 0!important} .post .content .poll table.result tr td.percent{width: 10%!important} .content_left >.post .tags +.infopanel{background-color:#f9fbf8} .content_left .post .infopanel{ min-width:93%;min-height:15px;top:2px;margin:-2px 10px -26px 17px!important;padding:0 10px 0!important;line-height:1.6!important;border-color: #edede0!important;border-radius:6px;background-color: #f6f6fb} .i-am-your-father-luke .post .infopanel{width: 94%;margin:3px 0 0 4px!important;border: 1px solid #ddc;border-radius: 5px;font-size:11px;line-height:1.7} .company_post .post .infopanel{min-width:0%;margin-top:11px!important} .post .infopanel >div{ max-height:17px;margin-top:0!important;margin-bottom:0!important;padding-top:0!important;padding-bottom:0!important;line-height:16px!important;background-position:0 0!important} .post .published{position: relative;float: right;margin:3px 4px -4px!important;font-size: 10px!important} .post .infopanel .comments,.post .infopanel .comments a,.post .infopanel .voting{margin-right: 7px!important} .post .infopanel .voting .mark{font-weight: normal!important} .post .infopanel .favorite{padding-right: 3px!important} .post .infopanel .favs_count{height: 1.5em!important;padding-right: 12px!important} .post .infopanel .twitter{margin-left:5px!important} .post .infopanel .googleplus{margin-right:5px!important} .post .infopanel .share{margin:2px 0 0 6px!important} .post .infopanel .share >div{width: 16px!important;height: 16px!important;margin:-2px 2px 0!important;padding:0!important} .post .infopanel a{font-weight: normal!important;font-size: 12px!important;line-height:12px!important} .infopanel .original-author{color:#a33!important} .post .infopanel .author{margin-left:6px!important} .post .infopanel .author .rating{top: auto!important;vertical-align: -3px!important;font-weight: normal!important} .post .infopanel .comments{margin-left: 5px!important;background: url(data:image/gif;base64,R0lGODlhDAAOANQVAIGhtsHU2uLq79Tv8qbE0dLh6/f//+z6+9/09r/c8Nru+rfL2O3y9sbY4+Pz+4movMjk8K/K0svc59Xr+r3P3P7//4WkuQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABcALAAAAAAMAA4AAAVRIFOMJCmJVaqukmS8cNxIxxHceN00SO//u8EgQiwKKRShcjmgLCAQgnQKXSwG0Gx2YHXUDgpozRERPM6PhiJhaQsu8AsjPQHE7/K0HR9nSOMhADs=) no-repeat 2px 2px #e5e4eb!important} .post .infopanel .comments a{padding:3px 4px 4px 17px!important} .page-nav #nav-pages,.page-nav{ margin: 0 40px 0!important;padding: 0 0 1px 1px!important} .page-nav ul.next-prev li{padding-right: 0.3em!important} .page-nav #nav-pages{ position: fixed;z-index: 1001;left: 0;bottom: -1px;margin: 6px 0!important;opacity: 0.5;filter: alpha(opacity=50)} .page-nav #nav-pages:hover{opacity: 1;filter:none} .page-nav #nav-pages li{margin: 0!important} .page-nav #nav-pages li a,.page-nav #nav-pages li em{ margin: 0 1px!important;padding: 2px 24px!important;border: 1px solid #ddc!important;border-radius:5px;text-decoration: none!important;font: 18px Verdana,Arial,Helvetica!important;background-color: #fdfdf4} .page-nav #nav-pages li em{border: 1px solid #3E8592!important;background-color: #7a9bac} .page-nav #nav-pages li a:hover{ margin: -1px!important;padding: 3px 26px!important;border: 1px solid #8ab!important;background:#c5dae5!important} .content_left .post #edit_tags_form{margin:0 0 -6px!important;padding: 5px!important} .content_left .comments_list{ position: static!important;overflow: visible!important;min-height: 2em;margin: -5.6em -2px 0 0!important;padding-top: 5.6em!important;padding-left: 30px!important;border-right: 2px solid #fff!important;background:#fff} .content_left .comments_list{border-bottom: 2px solid #fff!important} .content_left .comments_list:hover{border-bottom: 2px solid #eee!important} .comments_list:hover >.comment_item:not(:hover){ margin-right:-2px!important;border-right: 2px solid #eee!important;background:#eee} .comments_list .comment_item:hover{background:#fff} body.company .comments_list h2.comments-header,.content_left .comments_list h2.title{ max-width: 1200px;margin:-25px 1px 0 -26px!important;padding: 15px 0 0 25px!important;border: 1px solid #e8e8dd!important;border-radius:8px;background: #f0f0e7!important} .company_post .comments_list h2.title{margin-top: 0!important;padding-top:22px!important;} h2.title .subscribe_comments{font-size: 12px!important;cursor: inherit!important} .comments_list .comment_item .reply_comments{margin-top:0!important} .conversation_page .title{margin-top: 0.8em!important} .conversation_page .messages .message,.comments_list .comment_item{position:relative;margin-top: 8px!important;margin-bottom: 0!important;margin-left: -4px!important;padding-top: 0!important;padding-bottom: 2px!important;padding-left: 24px!important;border-top: 0!important} .comments_list .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item{padding-left: 10px!important} .comments_list .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item .comment_item{padding-left:4px!important} .content_left .comments_list >.comment_item{margin-left:-24px!important;border-left: 1px solid #dddde2!important} .comment_item .info{ position: static!important;max-width: 1016px;height: 9px!important;overflow: inherit!important;margin: -2px 0!important;padding-top: 5px !important;padding-right: 4px!important;line-height: 11px!important;font-family: tahoma,sans-serif!important;background-position:1px 7px!important} .comments.c2 .comment_body{margin-top: 12px !important} .comment_item >.info >a:not(.username):not(.favorite),.comment_item .info >div:not(.clear){ position: relative;height: 3px!important} .conversation_page .message.new .info,.comment_item .info.is_new{background:#f0f0fc} .conversation_page .message .info{background:#ecefef} .my-reply,.conversation_page .message.my .info,.comment_item .info.is_author{background:#e5f7e7!important} .comment_item .info .comma{display:none!important} .comment_item .info div.voting{position:absolute!important;z-index: 2;display:none;top:-7px;height: 18px!important;right:2.2em;padding-right: 16px} .comments.c2 >.comment_item .info div.voting{top:12px;} .comments.c2 .reply_comments >.comment_item .info div.voting{top:-7px;} .user_comments .comment_item .info .voting{display:block} .comment_item .info .voting .plus{position: absolute;z-index:2;float:left!important;min-width:11px;min-height:15px;left: -31px;margin-top:-1px!important} .comment_item .info .voting .minus{position: absolute;z-index:2;min-width:11px;min-height:16px;left: 20px;margin-left: 0!important;margin-top:-1px!important} .comment_item .info .voting .mark span.score{ position: absolute;width: 3.2em;left: -15px;top: -1px;text-align: center} .comment_item .info a.avatar{ position:absolute;overflow:visible!important;width:16px!important;height:16px!important;left:-20px;top:0;border:1px solid transparent!important;z-index: 3;opacity: 0;filter: alpha(opacity=0)} .comment_item .info a.avatar img[src*="stub-user-small"]{display:none!important} .comment_item .info a.avatar img{position:relative;width:16px!important;height:16px!important} .comment_item .info a.avatar:hover{border:1px solid #ddd!important;opacity:1!important;filter:none!important} .comment_item .info a.avatar img:hover:not([src*="stub-ser-small"]){ display:block!important;width:24px!important;height:24px!important;top: -8px;left:0} .comments.c2 .comment_item .comment_body >.reply a.abuse_link{display:none;margin-top:0!important} .comments_list .comment_item .reply .abuse_success{display:inline-block;position: relative;top: -4px;line-height:0.8} .comments_list .comment_item .comment_body:hover >.reply a.abuse_link{ position: relative;display: inline-block!important;float: right;width: 2.3em;height: 15px;margin-top:-15px!important;overflow: hidden;left: 1.7em;top:-2px;border-radius: 4px;background-color:#f2f2e4;color: #8ca!important} .comments_list .comment_item .comment_body >.reply a.abuse_link:hover{width: auto;overflow: inherit} .buttons .orange,.post .abuse_form{width: 94%!important} .post .abuse{position: relative;float: right;margin: -2px 12px -24px!important} .post .abuse.cancel_abuse{margin: 11px 10px -24px 2px!important} .comment_head span.info a,.info a.username,.messages .message .info .login a{ visibility:visible;display:inline-block;position: relative;height: 13px;line-height: 11px!important;margin:-8px 8px -4px 32px!important;padding:0 3px 0 4px!important;border-radius:4px;text-decoration: none!important;font-size: 10px!important;letter-spacing:1px;font-weight:normal!important} .messages .message .info .login{visibility: hidden;} .comments >.comment_item span.username a{padding:0 3px 1px 4px!important;border-radius:4px;text-decoration:none!important} .comments_list >.comment_item:hover .comment_item:not(:hover) .info a.username,.comments_list:hover >.comment_item:not(:hover) .info a.username{visibility:hidden} .reply_comments:hover .comment_item:not(:hover) .info time,.comments_list >.comment_item:hover .comment_item:not(:hover) .info time{visibility:hidden}.comments .comment_item .info time,#comments .comment_item .info time,.messages .message .info .time{ display:inline-block!important;position: relative;float: none!important;top: -10px!important;height:10px;margin-top: 1px!important;padding-right: 1px!important;white-space: nowrap;font-style: italic!important;color:#a97!important} .conversation_page .messages .message .info .time{top: -5px;} .comment_item .info .show_tree,.comment_item .info a.link_to_comment{ position: absolute!important;left: auto!important;right: 2px!important;top: -2px;display:none!important;margin: 4px 0 0!important} .comments.c2 .reply_comments >.comment_item .info a.link_to_comment{top: -7px;} .comments.c2 >.comment_item .info a.link_to_comment{top: 12px;} .comment_item .info a.favorite{ position: absolute;z-index:2;float:right!important;visibility:hidden;width:15px!important;height:13px!important;top: -8px;right:-6px!important;left: auto!important;margin: 0 6px -12px 0!important} .comment_item .info .voting:hover ~ a.favorite{visibility:visible!important} .comment_item .info a.favorite:hover{visibility:visible} .comments_list >.comment_item:hover .info .voting,.comment_item .info:hover a.link_to_comment{display:block!important} .comments_list >.comment_item_plain >.comment_item .info time{visibility:visible} .comment_item .info a.to_parent,.comment_item .info .show_tree{display:none!important} .comment_item div.message,.conversation_page .messages .message .text{ display: inline-block!important;overflow: inherit !important;max-width: 840px;margin-top: -3px!important;margin-bottom: -2px!important;padding: 0 2px 2px!important;word-wrap: break-word;line-height:1.25!important;font-size: 12px!important;background:#fff;font-family: Verdana,Arial,Helvetica,sans-serif!important} .comments .comment_item .username{font: 10px Verdana,sans-serif normal!important} .comment_item .message a{word-wrap: break-word} .comments_list .comment_item .message.bad1,.comments_list .comment_item .message.bad2,.comments_list .comment_item .message.bad3,.comments_list .comment_item .message.bad4,.comments_list .comment_item .message.bad5{ margin-top: 1px!important;background-color: #fff!important} .comments.c2 .comment_item .reply,.comments.c2 .comment_item .reply_link,.comments_list .comment_item .reply,.comments_list .comment_item .reply_link{ min-height: 19px;margin: -1px 0 -18px!important;border-top: 1px solid #fff!important} .comments.c2:hover >.comment_item:not(:hover) div.reply,.comments_list:hover >.comment_item:not(:hover) div.reply{border-top: 1px solid #eee!important} .comments.c2:hover div.reply,.comment_item:hover div.reply{border-top: 1px solid #fff!important} .comments.c2:not(:hover) .reply >a.reply_link,.comments_list:not(:hover) .reply >a.reply_link,.comments.c2:not(:hover) .reply >a.reply,.comments_list:not(:hover) .reply >a.reply,.comments.c2:hover >.comment_item:not(:hover) .reply >a.reply_link,.comments_list:hover >.comment_item:not(:hover) .reply >a.reply_link,.comments.c2:hover >.comment_item:not(:hover) .reply >a.reply,.comments_list:hover >.comment_item:not(:hover) .reply >a.reply,.comments.c2 >.comment_item:hover .comment_item:not(:hover) a.reply_link,.comments_list >.comment_item:hover .comment_item:not(:hover) a.reply_link,.comments.c2 >.comment_item:hover .comment_item:not(:hover) a.reply,.comments_list >.comment_item:hover .comment_item:not(:hover) a.reply{visibility:hidden} .comments_list >.comments_list .comment_item:hover .reply a.reply_link,.comments_list >.comments_list .comment_item:hover .reply a.reply{visibility:visible} .comment_item .reply a.reply_link,.comment_item .reply a.reply,.comment_holder .reply a{ padding: 2px 7px 5px!important;border-radius:5px;background-color: #f2f2f2} .comment_item .reply a.reply_link:hover,.comment_item .reply a.reply:hover,.comment_holder .reply a:hover{background-color:#f6f6f6} .comments .comment_item .comment_head{margin-bottom:0!important} .comment_item .reply a.reply_link,.comment_item .reply a.reply{ position: relative;display: inline-block;width: auto;height:auto;-moz-transform: rotate(-90deg);-o-transform: rotate(-90deg);-webkit-transform: rotateZ(-90deg);transform : rotate(-90deg);left: -4px;padding: 1px 1px 0!important;-moz-transform-origin: 0% 20px;-o-transform-origin: 0% 20px;-webkit-transform-origin: 0% 20px;-webkit-box-shadow: inset 2px -2px 3px #dde;box-shadow: inset 2px -2px 3px #dde;border-bottom: 2px solid transparent!important;color: #acc!important;top: -16px;opacity: 0.5} .comment_holder .reply a.js-serv{left: -1px;top: -20px} .comment_item .reply a.reply_link:hover,.comment_item .reply a.reply:hover{opacity: 1} .comment_item:last-child:not(:only-of-type) >.reply_comments{ margin-bottom: -1px!important;margin-left: -25px!important;padding-left: 25px!important;border-top: 1px solid #dddde2!important} .comments.c2 .comment_item:last-child:not(:only-of-type) >.reply_comments,.comments_list .comment_item:last-child:not(:only-of-type) >.reply_comments{border-left: 2px solid white!important} .comments_list{position:relative;top: -0.6em;margin: 0 -8px 0 0!important;padding: 0.6em 8px 0 25px!important} .comments.c2:hover >.comment_item:not(:hover) .comment_item:last-child:not(:only-of-type) >.reply_comments,.comments_list:hover >.comment_item:not(:hover) .comment_item:last-child:not(:only-of-type) >.reply_comments{border-left: 2px solid #eee!important} .comments.c2 .comment_item:last-child:not(:only-of-type):hover >.reply_comments,.comments_list .comment_item:last-child:not(:only-of-type):hover >.reply_comments{border-left: 2px solid #fff!important;clear: both} .comments.c2 .comment_item[id^="comment_"] +.comment_item,.comments_list .comment_item +.comment_item{border-left: 1px solid transparent!important} .comments.c2 .comment_item[id^="comment_"]:not(:only-of-type),.comments_list .comment_item:not(:only-of-type){border-left: 1px solid #dddde2!important} .comments.c2 .folding-dot-holder,.comments_list .folding-dot-holder,.comment_item .info .folding-dot-holder{visibility:hidden} .comments_list .comment_item_plain{overflow:inherit!important} .comments_list .comment_item_plain .post_info{width:auto!important;position:relative;z-index:2;height: 0.3em} .user_comments .comments_list{padding-left:9px!important} .user_comments .post_info a{text-decoration: none!important} .user_comments .comment_item_plain .post_info{height: auto} .postoffice .comments_list{margin: -70px -8px 0 0 !important;overflow: inherit!important} .postoffice .editor{margin: 9px 0 -10px -4px!important} .content_left .comments_form{margin-bottom:19px!important} .content_left .comments_form h2.title{position:relative;margin-bottom:-20px!important;background-position: 0.3em 0.45em!important} .content_left .comments_form h2.title a{ border-bottom: 1px dashed!important;font: 20px normal Verdana,Tahoma,sans-serif!important;color: #afa56a!important;text-decoration: none!important} .comment_item .reply >form,.content_left .comments_form form#comments_form{ margin-bottom: 21px!important;margin-left: 3px!important;padding-top: 0!important} #preview_placeholder{margin: 4px -2px 2px -1px!important;padding: 3px 8px 4px 3px!important} .preview_placeholder,#clarify_form{margin:-2px 0 -2px!important;padding: 5px!important} .comments_form #preview_placeholder{margin-top:20px!important;padding: 5px!important} .company_post >.comments_form >form >#preview_placeholder{margin: 18px -2px 2px -1px!important;padding: 3px 8px 4px 3px!important} .editor .panel{ position: relative!important;overflow: inherit!important;z-index: 11;width: 98%!important;min-height: 22px;margin: 0 -7px -1px 3px!important;padding: 2px 1px 0!important;border-radius:5px;opacity: 0.2;background-color:#eee} .editor .panel:hover{opacity: 1} .editor .panel a{ display: inline-block!important;float:none!important;min-width: 20px;height: 20px;line-height:18px;padding: 0 6px!important;text-decoration: none!important;margin: 0 -2px!important;border-radius:5px} .editor .panel .spanned,.editor .panel .wysiwyg_wrapper .btn{ display: inline-block!important;position:relative;float: left;z-index: 11;height: 20px!important;line-height: 22px!important} .editor .panel .wysiwyg_wrapper .btn.btn-dropdown{float: none!important} .editor .panel >div >b >a{position:relative;top:-2px} .editor .panel >a:first-child,.editor .panel .wysiwyg_wrapper .btn:first-of-type{margin-left: 3px!important} .editor .panel .wysiwyg_wrapper .btn[onclick*="twitter"]{display: none!important} .editor .panel .spanned{padding: 0!important} #js-topic-form-holder .editor .panel .spanned a >font{top:0!important} .editor .panel >.wysiwyg_wrapper >.btn:hover,.editor .panel >.wysiwyg_wrapper >a:hover,.editor .panel >div >b >a:hover,.comment_item .reply .editor .panel >div >a:hover,.content_left #comments_form .editor .panel a:hover{background:#fff} .editor .panel .with-title{margin: 1px 6px 0 3px!important} .editor .panel .can_use_html{ position: absolute;right:-8px;top: 0;z-index: 10;height: 20px!important;line-height: 22px!important;white-space: nowrap;color: #999!important} .editor .panel .can_use_html a{ position:relative;display: inline;margin-right: 7px!important;padding: 0 3px!important;z-index:12} .text-holder textarea,form#comments_form .editor .text-holder textarea#comment_text{ border-width: 0!important;border-style: none!important;width:99.4%!important;font: 12px/15px Verdana,Arial,Helvetica,sans-serif!important;-moz-appearance: none;resize:vertical!important} div.inbox_page_write .editor textarea#text_textarea{height:auto!important} .inbox_page_read2 h2,.inbox_page_read2 #add_message_form{margin-left:7px!important} #write_message_form,#write_message_form .item{margin-bottom:0!important} #write_message_form label[for="text"]{display:none!important} .content_left #write_message_form,#reply_form_0 .text-holder textarea{margin-left: 17px!important} h3+ #reply_form_0 .text-holder textarea{margin-left: 0!important} #comment_form #send_msg,#post_form #send_msg,#write-post #send_msg,#comments_form input.submit,#write_message_form input.submit,#add_message_form input.submit{margin-left: 60px!important} #post_form >.item{margin:0!important} .conversation_page{margin-left:3px!important} #sidebar,.sidebar_right,.Sidebar{overflow: hidden;float: none!important;width:auto!important;margin:0!important;padding-bottom:3px;line-height: 1.18 !important} .block.float_block{position:static!important} .block.user_info .join{float:right;padding-top:0!important} .block.user_info .stats{width:auto!important} .block.user_info .stats .item{margin-bottom:0!important} .sidebar_right .block,.Sidebar .block{font-family: Verdana,Arial,Helvetica,sans-serif!important;background: transparent!important;box-shadow: none!important} .block.blog_info{position: relative;margin:-2px 0 -12px 2px!important;padding:0 30px!important} .habralenta_settings >.title+p{text-indent: 2.2ex} .block.blog_info{margin-bottom: 4px!important} .block.blog_info >.title{display: none!important} .block.blog_info .stats >div{padding-top: 3px!important;font-size: 12px!important} .block.blog_info .info .join{float: none!important;overflow: hidden!important} .block.blog_info .info .join a#addBlogMember,.block.blog_info .info .join a#removeBlogMember,a#js-addBlogMember,a#js-removeBlogMember{ position: absolute!important;float: none!important;z-index: 2;overflow: hidden;top: 9px;left: 0;width: 0;height: 18px;padding: 4px 0 2px 32px!important;background-image:url(data:image/gif;base64,R0lGODlhLgAoANU/AFZ6lq7K3trm6u7y9oamusbW4p6+0trq9pKuwvr6+sre8ubu9m6Squ76/tLe5q7O5qbK4sbe7uLy+uLq7qbG4pK2yury/vb6+rbS4trq8qbC1tLm9r7a6uby9rbO4oqqwtru9vr+/pq6znqetqK+0rrW6naarpq2ytbq9oKiur7W5qrG2mqOppKyxs7i8vb+/sLa5vL29t7u+rLK3ur+/t7q9vr6/uLu+vb6/t7q8s7a5v7+/uru8rbS6vL2+v///yH5BAEAAD8ALAAAAAAuACgAAAb/wAiH4/oZj8ikcslUKhqNUnNKrUZoNAxHUe16f4pQCEMrmc+R3XdtTO9mrw12DoKF2F/YbhfYyV6AgTIld3hVKnsrOxJ7jXsdGIWGTRiAGjs3jo41HpNTM1AkDS6BpYAknk0BNzciFioWLLKzFhYGGRk5ujcLCx0WAz7CFzg2IY1NKwcHJwczB7OzMswFBTrXDg4C2xMTPAMDMT4XNntNJC4uFQoGES4b8PDvFalMIhERCCUVPf3+PQoiiKi35ES/Dw9SUFjI0MwJSQSPtHjw4AMEhBQpluBQAWJEIx8WEuihAYRJkwpaePz4A2MKDiNiyvyQgKUSfSVSmCBgs8oH/3wjenYhYMJEC6FWhhRBOuVJFKZTrmRhomAL0jBjmJQoc8ZMGoJuZmiNMwdLnZVs9PAxAgNDCbcYPPgx9WIQ2i+IdqwwIkLGDRAyZPRhpGkHpLtdKr3QYISAzJiKMu0p2oiTJ1ANUC0RRQpQ0VKMJ626YYCJgVexWDBYzaKWhhw1FvDyBUzYsGLGGiljxqTZs2iypomwlk3btgwTFnwLNy5BuR3o1DFZ1+6drAMbXKAYOOlePiNE0qXTx68fAAAKAEbQbMhgjw9GTgSej1DhwgclepgRgbjKxIogPTYCARdR1MMDbnHUn08iMZECSSeZFIFK9bjExAgwCUgTQTilwBEEUTwJ9VMEQUH1YVFHmbhEEAA7)!important;background-position: 0 -20px!important;background-repeat: no-repeat!important;background-color: transparent!important;border: 0!important;border-radius: 0!important;color: #ccc!important} .sidebar_right .block:not(.blog_info):not(.habralenta_settings),.Sidebar .block:not(.blog_info):not(.habralenta_settings){ overflow: visible!important;margin: 0 0 0 3px;padding: 0 0 0 2.2ex!important} .block.company_info{margin: 0 0 -0.7em 0!important} .company_widgets{margin: 0 0 0 3px!important;padding-bottom: 0.2ex} .posts_list .post_item a,.sidebar_right .links .link,.Sidebar .links .link,.block .post_item{margin-bottom: 0!important;padding-bottom: 0!important;line-height: 1.1!important;text-indent:-1ex;font-family:Verdana,Helvetica,sans-serif} .block .all a:visited,.posts_list .post_item a:not(.blog_name):not(.user_name):visited{color: #a88!important} .block .event,.new_vacanies .vacancies,.block_brainstorage .vacancies,.freelansim .tasks,.block_freelansim .tasks{margin-left: -1.6ex!important;word-wrap:break-word} .freelansim .tasks .task,.block_freelansim .tasks .task,.new_vacanies .job_item,.block_brainstorage .job_item{overflow: inherit!important;padding-left: 1.4ex!important} .block a{margin: 0!important;padding: 0!important;text-decoration: none!important;border-bottom: 1px dotted transparent!important} .block a:hover{padding: 10px;border-bottom: 1px dotted #666!important;color: #333!important} .block a.user_name{background-position: 2px 50%!important} .block >.title{margin: 3px 0 3px 2ex!important;font-size: 18px!important;color: #5699d8!important} .block .all{position: relative;margin:-2px 2px!important;text-align:right} .block:not(.freelansim):not(.block_freelansim):not(.new_vacanies):not(.block_brainstorage) >div >div{overflow: inherit!important} .block.company_info .join{width: 104px} .block.habralenta_settings,.block.habralenta_settings p{margin:0!important;padding:0!important} .habralenta_settings .hub a{margin-left:20px!important} .block .category-list .category{margin-bottom:3px!important} .block .category-list .category .blogs{padding-top:4px!important} .block .category-list .category .blogs .blog{margin-bottom:3px!important;padding-left:18px!important} .block .category-list .category .blogs .blog .checkbox{margin:0!important} .block.daily_best_posts h1 sup,.block.geektimes_top h1 sup{vertical-align: baseline!important} .block.daily_best_posts .posts_list .post_item,.block.geektimes_top .posts_list .post_item{margin: 0!important} .block.daily_best_posts h1 sup,.block.megamozg_top h1 sup{vertical-align: baseline!important} .block.daily_best_posts .posts_list .post_item,.block.megamozg_top .posts_list .post_item{margin: 0!important} .block .posts_list .post_item a.user_name{padding-left:2.5ex!important} .block.new_vacanies h1,.block.block_brainstorage h1,.block.new_vacanies .title,.block.block_brainstorage .title{display: none} .sidebar_right .freelansim .title,.block.block_freelansims .title,.sidebar_right .block.new_vacanies .title,.block.block_brainstorage .title{ display: inline-block !important;margin-bottom: 6px !important;opacity: 0.3} .block.freelansim .task,.block.block_freelansim .task,.block.new_vacanies .job_item,.block.block_brainstorage .job_item{margin:0!important} .best_company +.block.new_vacanies .vacancies .job_item,.best_company +.block.block_brainstorage .vacancies .job_item{display: block} .block .vacancies .job_item >div{float: none!important;background-color:transparent!important;color:#666} .block .vacancies .job_item .title a{font: inherit!important} .block .vacancies .job_item .pay{font: inherit!important;font-style: italic!important;color:#84b18a!important} .bottom_promo_blocks{padding-top: 15px!important} .block.freelansim .title,.block.block_freelansim .title{margin: 9px 0 10px!important} .block .events_items .event_item{margin:0 0 2px -2.5ex!important;overflow:hidden} .block.similar_events .title{margin-left:15px!important} .block.similar_events .date{ position:static!important;width: 99px!important;height: 1.1em!important;overflow: inherit!important;clear:left;color: #999!important} .block .date .day{font-size: 18px!important;line-height: 20px!important;color: #aaa;font-weight: normal!important} .block .date .title{overflow: hidden!important;margin-left:auto!important} .block.favorite_tags .top-tags{margin:0 4px 0 0!important}.block.favorite_tags .top-tags a .name{text-decoration:none!important} .block.favorite_tags .top-tags a:hover,.block.favorite_tags .top-tags a.current{background:#e4e7e4!important} .block.last_links .links .link small{color:#84b18a!important} .content_left .topic_add{margin-left: 10px!important} .content_left .similar_posts,.content_left .similar_posts .posts_list,.rotated_posts{margin-top:0!important;margin-bottom:0!important;padding-top:0!important;border-top:1px solid #eee!important;background:#f8f8f8} .footer_panel{height: 0.6em} .rotated_posts,#footer{max-width: 1420px;margin-left: auto !important;margin-right: auto !important} .rotated_posts .rotated_post{margin-bottom: 0!important} .rotated_posts .rotated_post a,.content_left .similar_posts .title{display:block;padding:0 3px 2px!important;text-decoration:none!important;font-size: 13px!important;line-height:1.1!important;background:#f8f8f8} .content_left .similar_posts .title,.content_left .similar_posts .post_item .when{padding-bottom:0!important;font: 12px Arial,Helvetica,sans-serif!important} .content_left .similar_posts .posts_list{display:none;max-width:1540px;margin:-6px 4px 0!important;padding: 0 12px 2px!important}.content_left .similar_posts .posts_list{margin-top:14px!important} .content_left .similar_posts{margin-top:-4px!important;padding: 0 !important} .content_left .similar_posts .title{float:right;height:1.2em;margin: -3px 24px 0 12px!important;padding:2px 5px 4px!important;border-radius:5px} .content_left .similar_posts >.title,.content_left .similar_posts .post_item,.content_left .similar_posts .post_item .when{margin-bottom:0!important} .content_left .similar_posts .post_item .when{font-size: 12px!important;color:#777} .content_left .similar_posts:hover{float:none;position:static} .content_left .similar_posts:hover .posts_list,.content_left .similar_posts .posts_list:hover{position:absolute;z-index:12;display:block} .content_left .similar_posts .post_item .when,.content_left .similar_posts .post_item .post_name{display:inline;text-decoration:none!important} .content_left .similar_posts .post_item{display:inline-block;vertical-align: middle!important;width:24%!important;margin-right:0!important;padding-bottom:1px!important;line-height:1.14!important;text-indent:0} .posts_list .sort_menu{margin: 10px 0 -12px!important} .search_results,.comment_item_plain:first-child{margin-top: 17px} #footer{width: auto!important;min-width: 314px!important;margin-bottom: 0!important;padding: 7px 0 0 0!important} #footer:before{position:relative;display:block;float:right;height:0;top:-5px;right:2px;white-space:nowrap;margin-top:-4px!important;font-size: 9px;color:#888;content:"ZenComment by spmbt"} #footer .bottom_menu{width: 100%!important} #footer a{text-decoration: none!important} #footer dl{width: 49.6%!important;float:right} #footer dl:last-child{display:none} #footer dt{float:left;width: 4em;margin: 0 0 0 2px!important;line-height: 120%!important} #footer dt:after{content:":"} #footer dd:not(:last-child):after{content:","} #footer dd{float:left;margin:0 0 0 6px!important;line-height: 120%!important} #footer .copyright{position: relative;left: 12px;width: auto!important;float: none!important;margin-right: 12px!important} #footer .copyright .footer_logo{margin:0!important;position:absolute;left: -21px!important} #footer .copyright .about{float:left!important;width: auto!important;vertical-align: middle!important;margin:0 0 0 2px!important} #footer .about br,#footer .copyright .about br{display: none} #footer .about >a{margin-left: 10px!important} #footer .about div,#footer .social_accounts{display: inline-block;height: 1.2em!important;margin: 0!important} #footer .social_accounts a{margin-bottom: -8px!important} #xpanel a.change{background-color: #999!important} #xsidebar,#xpanel,#xpanel a:last-child{border-bottom-left-radius:5px} #xsidebar,#xpanel a:first-child{border-top-left-radius:5px} @media (max-width: 1100px){ .content_left .post .content,.content_left.post .content{padding-left: 10px!important} .content_left{width: 240px!important;}} @media (max-width: 405px){.App >.container{padding-top:18px!important}.Posts > ul li h2{font-size:11px!important}} @media (max-width: 570px){ .App >.container .left_column{min-width: 100%} .Posts > ul li h2{font-size:12px!important} .App >.container >.Sidebar{display: none!important}} @media (max-width: 640px){ .content_left .post .content,.content_left.post .content{padding-left: 0!important} .daily_best_posts .posts_list,.geektimes_top .posts_list{margin-left:-12px!important} .daily_best_posts .post_item,.geektimes_top .post_item{text-indent:-1ex!important} .daily_best_posts .posts_list,.megamozg_top .posts_list{margin-left:-12px!important} .daily_best_posts .post_item,.megamozg_top .post_item{text-indent:-1ex!important} .block .post_item,.vacancies .job_item,.tasks .task{margin-left: 0.2ex!important} .Sidebar .block_brainstorage .vacancies .job_item,.Sidebar .block_freelansim .tasks .task{line-height: 1.04!important} .content_left .post .infopanel{margin-left: 2px!important} .content_left{width: 240px;} #TMpanel{left: 0!important} #TMpanel .menu a{margin: 0 2px!important} .Posts ul li h2{padding-left: 107px!important}} @media (min-width: 1520px){ #layout,.rotated_posts,#footer{margin-right:0!important} #TMpanel{left: 205px !important} #navbar .nav_panel .logo{margin-left: -7px;border-bottom-left-radius:3px} #navbar a.logo + a.tab_menu{left: 22px!important} #navbar_overlay,#navbar .tab_user,#navbar .tab_tracker,#navbar .tab_tracker,#navbar a.tab_add_post:hover +a.tab_settings{display: none!important} #navbar a.tab_add_post{visibility: visible;right:auto;left:-114px!important;background-color: #ccc} #navbar .nav_tabs_content{ position: static!important;overflow: inherit!important;width: 1612px!important;height: 0!important;left: 0!important;margin: 0 auto!important} #navbar #menu_tab,#navbar #user_tab,#navbar #tracker_tab,#navbar #settings_tab{position: static!important;display: block!important;margin-left:-190px} #navbar .nav_tabs_content .nav_tab .title,#navbar .nav_tabs_content .nav_tab .global_search_form,#navbar .nav_tabs_content .nav_tab .text,#navbar .nav_tabs_content .nav_tab .menu a{text-align: right;padding: 4px 10px 4px 40px!important} #navbar .nav_tabs_content .nav_tab .global_search_form input{text-align: right} #navbar .nav_tabs_content .nav_tab .global_search_form{margin: 0!important} #navbar .nav_tabs_content .nav_tab .menu a.new_window:after{top: 4px!important;right: 100px!important} #navbar .nav_tabs_content .nav_tab .title{font: 12px Arial,Helvetica,sans-serif bold} #navbar .menu a,#navbar .nav_tab .global_search_form,#navbar .nav_tab .text{background-color: #f2f2f2} .page-nav #nav-pages{left: 110px}} @media (min-width: 1574px){#layout,.rotated_posts,#footer{margin-right:26px!important}} @media (min-width: 1650px){#layout,.rotated_posts,#footer{margin-right:auto!important}} .block.daily_best_posts .posts_list .post_item a.user_name,.block.geektimes_top .posts_list .post_item a.user_name{color:#ddd!important} .block.daily_best_posts .posts_list .post_item:hover a.user_name,.block.geektimes_top .posts_list .post_item:hover a.user_name{color:#999!important} .block.daily_best_posts .posts_list .post_item a.user_name,.block.megamozg_top .posts_list .post_item a.user_name{color:#ddd!important} .block.daily_best_posts .posts_list .post_item:hover a.user_name,.block.megamozg_top .posts_list .post_item:hover a.user_name{color:#999!important} .block.freelansim .title,.block.block_freelansim .title,.block.new_vacanies .title,.block.block_brainstorage .title{opacity:0.3} .bottom_promo_blocks .block.new_vacanies .vacancies .job_item,.bottom_promo_blocks .block.freelansim .tasks .task{white-space: normal!important} .block.freelansim .tasks .task a,.block.block_freelansim .tasks .task a,.block.new_vacanies .vacancies .job_item a,.block.block_brainstorage .vacancies .job_item a{font-size: 12px!important} .Sidebar .copyright{text-align: right;margin-right: 6px} .author_banned,.ufo-was-here{max-width: 900px;height: 14px;margin: 1px 0 1px 12px!important;font-size: 6px!important;background: #f0f0f0;color: #fff!important;}.author_banned:hover,.ufo-was-here:hover{background: #d8d8d8}.author_banned:before,.ufo-was-here:before{content: "_удалено: `"} .i-am-your-father-luke{font: 20px/110% Arial,Helvetica,sans-serif!important;letter-spacing: -1px!important;margin-bottom: -4px!important;padding: 0 0 0 12px!important} #navbar .nav_tab .line,#navbar .nav_tab .line +.title,#navbar .nav_tab .line +.title +.menu{display: none!important} #TMpanel .menu.special,.special_navbar_image,#print_tab,.header .panel-nav-top .banner_special,div[id^="dd_"],div[id^="topline"],#header .main_menu .banner_special,.post_inner_banner,.top_banner,.right_panel,body >iframe[width="100%"],iframe[src*="//www.facebook.com/plugins"],.sidebar_right .banner_240x400,.posts_list .post_item img,body >a,.sidebar_right .block:not(.blog_info):not(.user_info):not(.habralenta_settings):not(.fast_navigator):not(.similar_posts):not(.daily_best_posts):not(.habrahabr_top):not(.geektimes_top):not(.megamozg_top):not(.live_broadcast):not(.similar_questions):not(.company_info):not(.corporate_news):not(.company_links):not(.corporate_blog):not(.new_vacanies):not(.block_brainstorage):not(.freelansim):not(.block_freelansim):not(.similar_events):not(.events_search_filter):not(.user_info):not(.favorite_tags):not(.for_authors_help),.sidebar_right div[class*=banner],.company_top_banner{display:none!important} #header_mouse_activity,.block.daily_best_posts .posts_list .post_item a:not(.blog_name):not(.user_name):not(.post_name),iframe[src*="facebook"],.footer_logos{display:none} .post .content .poll dl{margin-bottom: 3px!important}.post .content .poll dl dt{width: 5em!important}.post .content .poll .total{padding: 0 0 4px!important} #layout img[align="middle"],#layout img[align="center"]{display:block;margin:0 auto 2px!important} .content_left table.menu tr td.active{border-bottom: 1px solid transparent} .content_left .peoples_list,.content_left .hubs_list .hub{margin-left: 24px!important} #layout .wrapper .inner,#layout .inner{ border-radius:0;padding: 0!important} .buttons a.button,.buttons input:disabled:active,.buttons input{padding:0 10px!important} .post .content .buttons{display:inline-block!important;padding:0!important} .post .content .buttons a.button,.post .content .buttons input[type="button"]{position: relative;top:-2px;padding:0 2px 1px!important;border:0!important;border-radius:2px!important;background:transparent!important;color:#6da3bd!important;box-shadow: 0 0 2px rgba(255,255,255,0.4) inset,0 0 2px rgba(0,0,0,0.2)!important} .buttons a.button{height: 1.3em!important;top:-1px!important;line-height: 1.3em!important} .post .content .buttons input[type="button"]{color:#367!important} .post .content .buttons a.button:hover{background:#f4f4f9!important} .post .content .buttons a.button:visited{color:#b98!important} .to_top{top:16px!important} .to_top.mini{width:3px!important} .user_settings{margin: 0 0 8px 24px!important} .user_profile .twitter .text{word-wrap:break-word} .content a,.content_left .comments_list a,.comments.c2 a{color:#497da5!important} .content a:hover,.comments_list a:hover,.comments.c2 a:hover{color:#4d7285!important} .editor .text-holder{border: 0!important;clear:both} .editor .text-holder textarea,#js-field-comment,#report_form_container_textarea,.textfield{ width: 99.4% !important;border: 0!important;border-radius:5px;padding: 3px;-webkit-box-shadow:0 1px 6px #ddd inset;box-shadow:0 1px 6px #ddd inset} .editor .text-holder textarea:focus,#js-field-comment:focus,#report_form_container_textarea:focus,.textfield:focus{-webkit-box-shadow: 0 1px 6px #ddd inset,0 0 2px #5ec6fb;box-shadow: 0 1px 6px #ddd inset,0 0 2px #5ec6fb;border-color: #5699d8!important;outline:0!important}'
  2946.  
  2947. + (isChrome?'#header .userpanel:hover a.nav-settings,#header .user_panel:hover a.nav-settings{position: relative; top: -1.3em}#comments .info .voting.voted_plus .plus{background-position:1px -1px!important}#comments .info .voting.voted_minus .minus{background-position:-11px 1px!important}.comments_list .info .voting .plus{margin-right:30px;background-position: 1px -16px!important}.comments_list .info .voting .minus{background-position:-11px -16px!important}':'')
  2948. :'')+ css
  2949. + (hS.regimeNoZen.val ?'.comments.c2 >.comment_item .info .voting,#comments >.comment_item .info .voting,'
  2950. +'#layout .comments.c2 >.comment_item .info a.link_to_comment,'
  2951. +' #layout #comments >.comment_item .info a.link_to_comment{display:block!important}'
  2952. +'#layout .comments.c2 >.comment_item .info time, #layout #comments >.comment_item .info time{display:inline-block!important;visibility: visible!important}'
  2953. +'.comment_item .info time{padding-left:6px!important; white-space: nowrap; font: 12px tahoma,sans-serif!important; font-style: italic!important; color:#a97!important}'
  2954. +'.comments.c2 .comment_item .info a.username, #comments .comment_item .info a.username'
  2955. +' {visibility: visible!important}'
  2956. +'#layout .content_left .comments.c2 .comment_item, #layout .content_left #comments .comment_item{'
  2957. +' margin-top: 1px!important;'
  2958. +' margin-right: -2px!important;'
  2959. +(ZenNCh?' padding-top: 9px!important;':'')
  2960. +' border-right: 2px solid #fff!important;'
  2961. +' background:#fff!important}'
  2962. +'#layout .content_left .user_comments #comments .comment_item{margin-right:0!important}'
  2963. +'#layout .comment_item:last-child:hover:not(:only-of-type) >div.reply_comments,'
  2964. +'#layout #comments:hover >.comment_item:not(:hover) .comment_item:last-child:not(:only-of-type) >div.reply_comments{border-left-color: #fff!important}'
  2965. +'#layout #comments >.comment_item .reply{border-top: 1px solid transparent!important}'
  2966. +'#layout #comments:hover >.comment_item:not(:hover) .reply{border-top: 1px solid #fff!important}'
  2967. +'.comment_item .message{width: 100%}':'')
  2968. + (hS.noAva.val ?'.comment_item .info a.avatar:hover{opacity:0.8!important}':'')
  2969. + (hS.justify.val?'.content_left .event .text, .post .content, .comment_item >.comment_body >.message, .comments .comment_item, form >.preview_placeholder, form >#preview_placeholder{text-align: justify}':'')
  2970.  
  2971. +'.comments_list .info .voting:not(.voted_plus) span.plus,'
  2972. +'.post .infopanel .voting:not(.voted_plus) span.plus,'
  2973. +'.vote_holder .vote.expired:not(.voted_plus) .vote_plus,'
  2974. +'.vote_holder .voting.expired:not(.voted_plus) .vote_plus,'
  2975. +'.vote_holder .vote.no_auth .vote_plus,'
  2976. +'.vote_holder .voting.no_auth .vote_plus,'
  2977. +'#comments .info .voting.voted_minus .plus,'
  2978. +'.vote_holder .vote.voted_minus .vote_plus{visibility:'
  2979. + (hS.noExpiredVote.val ?'hidden':'visible!important') +'}'
  2980. +'.comments_list .info .voting:not(.voted_minus) span.minus,'
  2981. +'.post .infopanel .voting:not(.voted_minus) span.minus,'
  2982. +'.vote_holder .vote.expired:not(.voted_minus) .vote_minus,'
  2983. +'.vote_holder .voting.expired:not(.voted_minus) .vote_minus,'
  2984. +'.vote_holder .vote.no_auth .vote_minus,'
  2985. +'.vote_holder .voting.no_auth .vote_minus,'
  2986. +'#comments .info .voting.voted_plus .minus,'
  2987. +'.vote_holder .vote.voted_plus .vote_minus{visibility:'
  2988. + (hS.noExpiredVote.val ?'hidden':'visible!important') +'}'
  2989.  
  2990. +(h.inZen ?'.comment_item .info a.favorite{left:-3px}':'.entry-info-wrap .btnBack{top:7px}'
  2991. +'.infopanel >.g-plusone +.likes{margin-top: 5px}')
  2992. +(hS.noSomeSideBlocks.val && !h.inZen?'.sidebar_right .block:not(.blog_info):not(.user_info):not(.habralenta_settings):not(.fast_navigator):not(.similar_posts):not(.similar_questions):not(.daily_best_posts):not(.habrahabr_top):not(.geektimes_top):not(.megamozg_top):not(.live_broadcast):not(.new_vacanies):not(.company_info):not(.corporate_news):not(.company_links):not(.corporate_blog):not(.freelansim):not(.similar_events):not(.events_search_filter):not(.user_info):not(.for_authors_help):not(.for_authors),#header .main_menu .banner_special,div[id^="topline"],.post_inner_banner,.top_banner,.right_panel,body >iframe[width="100%"],iframe[src*="//www.facebook.com/plugins"],.sidebar_right .banner_240x400,.posts_list .post_item img,#print_tab{display:none!important}.sidebar_right .block.daily_best_posts .posts_list .post_item a:not(.blog_name):not(.post_name):not(.user_name),iframe[src*="facebook"],.footer_logos{display:none}':''));
  2993. if(hS.colorAuthorTAH.val) addRules('.comment_item .info.is_new.is_topicAuthor, .comment_item .comment_head.is_new.is_topicAuthor{background:#F5ECF5!important}');
  2994. h.uFrmWid = h.inZen || win.opera ?'74%':'66%';
  2995.  
  2996. var dSettings = hS.init() //элементы DOM для настроек
  2997. ,showUpdate = function(mD){ //сообщения о новом в версиях
  2998. var a = mD && mD.update
  2999. ,s ='';
  3000. if(a){
  3001. if(!(a instanceof Array) &&!(a[0] && typeof a[0]=='string')) a =[a];
  3002. for(var i=0, aL = a.length; i < aL; i++){
  3003. var d1 = Number(a[i].replace(/ .*/,''))
  3004. ,d2 = a[i].replace(/^[^ ]* /,'');
  3005. s +='<div class="hlp">'+ (d1 && d2
  3006. ?'<b>Новое по сравнению с '+ d1 +'</b>: ' + d2 +'</div>'
  3007. :'<b>Новое</b>: '+ a[i]) +'</div>';
  3008. }
  3009. }
  3010. if(mD['uso:installs'])
  3011. s += '<a href="'+ URLSCR + HAJAX +'stats" target="_blank">installs</a>: '+ mD['uso:installs'];
  3012. if(mD['uso:reviews'] || mD['uso:discussions'] )
  3013. s += ', <a href="'+ URLSCR + HAJAX +'feedback" target="_blank">talks</a>: '+ ((Number(mD['uso:reviews'])||0) + (Number(mD['uso:discussions'])||0) );
  3014. if(mD['uso:script'])
  3015. s += ', '+ '<a href="'+ URLSCR + HAJAX +'versions'+ mD['uso:script'] +'" target="_blank"><b>версии</b></a>.';
  3016. return s;
  3017. };
  3018. //document.body && document.body.appendChild(hNE) || document.documentElement && document.documentElement.appendChild(hNE);
  3019.  
  3020. if($q('.userpanel .username')) h.uName = $q('.userpanel .username').innerHTML;
  3021. var linksBug = 'Сообщить об ошибке в скрипте или идею <a href="http://habrajax.reformal.ru/" target="_blank">на Reformal</a>'
  3022. +(h.uName ?', <a href="/conversations/spmbt/#subj=HabrAjax%20notes" target="_blank">в личное сообщение</a> автору (в новом окне).':'') +'<br/>'
  3023. ,chkUpdElem = $q('.hADotted:not(.note):not(.current)', dSettings)
  3024. ,now5am = function(dte, hour){ //число в секундах, соответствующее последним 5 часам утра
  3025. if(!hour) hour =5;
  3026. if(dte && dte instanceof Date) dte = +dte;
  3027. dte = dte && new Date(dte - DAY/24 * hour) || NOWdate;
  3028. return (+new Date(dte.getFullYear(), dte.getMonth(), dte.getDate()) + DAY/24 * hour) /1000;
  3029. }
  3030. ,chkUpdate = function(ev){ //пров.обновление скрипта
  3031. var a = metaD && metaD.resource, url;
  3032. if(a){ //значение ресурса с ключом "meta" (число, имя файла на "USO" или URL)
  3033. if(!(a instanceof Array)) a =[a];
  3034. for(var i=0, aL = a.length; i < aL; i++)
  3035. if(a[i].replace(/ .*/,'') =='meta'){
  3036. url = a[i].replace(/[^ ]* /,''); break;}
  3037. }
  3038. if(url){ //TODO подогнать обновление к хостингу (имя файла)
  3039. //способы задания важности обновл_: 1) явно в метаданных: severity minor | major | critical;
  3040. // 2) номером версии: если минорный номер кратен 10, то critical; если нет, то minor
  3041. if(!hS.chkUpdate.val)
  3042. hN.addNote(imgWait +'&nbsp;'); //знак ожидания Ajax - только для ручной проверки
  3043. extMeta(url, function(dat){ //==читать внешние метаданные==, dat - прочитано с сервера (хеш)
  3044. var urlUpd = dat.finalUrl.replace(/meta\.js$/,'user.js')
  3045. ,metaDExt = readMeta(dat.responseText)
  3046. ,vD = getVersionDate(metaDExt.version) //версия на сервере //проверка версии
  3047. ,vDCur = getVersionDate(metaD.version) //установленная версия
  3048. ,severity = metaDExt.severity || (vD.major == vDCur.major //важность/критичность
  3049. ? vD.minor ? (+vD.minor % 10 ?'minor':'critical') :'minor'
  3050. :'major')
  3051. //vDCur = getVersionDate('105.2013.03.14'); //TEST
  3052. //metaDExt.update =['104 новые новые новые','103 снова снова снова', '01dfsfgs']; //TEST
  3053. //severity ='minor'; //TEST
  3054. if(!(severity=='minor' && hS.chkUpdNoMinor.val)){
  3055. 'vDCur'.wcl(vDCur, vD)
  3056. if(vDCur.version > vD.version || vDCur.version == vD.version && vDCur.days <= vD.days){
  3057. var s = (vDCur.version == vD.version && vDCur.date == vD.date
  3058. ?'Обновлений скрипта на хостинге <b class="hlp">нет':'На сервере - версия <b>с более ранн'
  3059. +(vDCur.days==vD.days ?'им номером '+ vD.version:'ей датой'))
  3060. +' с '+ vD.date +'</b> ('+ nSufRu(vD.days,0) +')'
  3061. + (vDCur.version == vD.version && vDCur.date == vD.date ?', загружена последняя версия':'')+'.<br>';
  3062. }else{
  3063. s ='<a href="'+ urlUpd +'" target="_blank" class="hlp"><b>Установить</b></a> '+ (severity=='minor'
  3064. ?'незначительные обновления в версии':(severity=='critical'?'важное обновление'
  3065. :'новую версию')) +' <b class="hlp">'+ vD.version +'</b>, от '+ vD.date
  3066. +' ('+ nSufRu(vD.days,0) +' назад).<br>';
  3067. }
  3068. s += linksBug
  3069. +'<div><i><b>Справка</b>: автопроверка обновлений &mdash; не чаще 1 раза кажды'
  3070. +(hS.chkUpdPeriod.val==1 ?'й день':'е '+ nSufRu(hS.chkUpdPeriod.val,0))
  3071. +'; настройки: период проверок; не сообщать о минорных версиях; отключить автопроверку; проверить обновление вручную.</i></div>';
  3072. s += showUpdate(metaDExt);
  3073. if(hS.chkUpdate.val){
  3074. hN.addNote(imgWait +'&nbsp;'); //поиск директив "@update version text"
  3075. win.setTimeout(function(){hN.addNote(s,'*');},1999);
  3076. }else
  3077. hN.addNote(s,'*');
  3078. //'updS'.wcl(hS.chkFailDate.val , now5am())
  3079. }
  3080. hS.updSettings({chkFailDate: 0, chkDate: now5am()}); //"прочитано", запомнена дата проверки обновления
  3081. }, function(er){
  3082. if(!hS.chkUpdNoMinor.val){
  3083. var s2='~~Ошибка чтения обновлений. '+ (hS.chkUpdate.val ?'<br/>Будет повторено не ранее, чем через '+ CHKUPD +' мин.':'');
  3084. if(hS.chkUpdate.val){
  3085. hN.addNote(imgWait +'&nbsp;');
  3086. win.setTimeout(function(){hN.addNote(s2,'*');},999);
  3087. }else
  3088. hN.addNote(s2,'*');
  3089. }
  3090. 'er'.wcl(er)
  3091. hS.updSettings({chkFailDate: Math.floor(+new Date() /1000)}); //дата неуспешной проверки обновлений
  3092. });
  3093. }else
  3094. hN.addNote('Не прочитан элемент meta и адрес серверного скрипта в ресурсе метаданных');
  3095. ev && $pd(ev);
  3096. };
  3097. if(chkUpdElem) chkUpdElem.addEventListener('click', chkUpdate,!1); //ручная проверка обновлений
  3098. if(hS.chkUpdate.val && !win.opera &&(!hS.chkFailDate.val && Math.floor((NOW - hS.chkDate.val *1000) /DAY) >= hS.chkUpdPeriod.val //опера не может проверять очень рано
  3099. || hS.chkFailDate.val && NOW - hS.chkFailDate.val *1000 > CHKUPD *60000 ) )
  3100. chkUpdate(); //автопроверка обновлений скрипта
  3101. var showVersionInfo = $q('.hADotted.current', dSettings);
  3102. if(showVersionInfo) showVersionInfo.addEventListener('click', function(ev){ //инф.о текущей версии
  3103. var vDCur = getVersionDate(metaD.version);
  3104. //metaD.update =['0.80 новые новые новые','0.812 снова снова снова', 'dfgdgdfh dhg hsd']; //TEST
  3105. hN.addNote('Версия <b>'+ vDCur.version +'</b>, появилась '+ vDCur.date +', '+ nSufRu(vDCur.days,0) +' назад.<br>' + linksBug + showUpdate(metaD));
  3106. $pd(ev);
  3107. },!1);
  3108. if(hS.noAlienScripts.val){ //сканер сторонних скриптов (поможет иногда; лучше делать "чистую загрузку")
  3109. var n =7
  3110. ,timeCheckAli = NOW
  3111. ,wwAli = win.setTimeout(function(){
  3112. scanAliens(timeCheckAli);
  3113. if(new Date() - timeCheckAli < 1300 && --n >0) win.setTimeout(arguments.callee,30); //ограничение активного сканирования кода по времени
  3114. }, 30);
  3115. }
  3116. habrAjax = h; //внешнее имя для детектирования повторных загрузок
  3117. try{if(typeof GM_registerMenuCommand !=u) //настройки HabrAjax [и тест юзерскрипта до загрузки страницы]
  3118. GM_registerMenuCommand('HabrAjax: settings', hS.edit); //settings
  3119. }catch(e){'_err_'.wcl('habrAjax = h;')};
  3120. //return h;})());//собрание уникальных для window имён и их внутренние имена (переименование)
  3121.  
  3122. //===============================================
  3123. titleBase ='подгрузка статьи; Ctrl- или Shift+клик - новая страница';
  3124. titleAdd ='; Ctrl+Shift - пере-подгрузка';
  3125. //==========для подгрузки скриптов=================
  3126. //Форматы: addJs(URL, тело тега SCRIPT, имя ожидаемого объекта после подгр.скрипта, функция коллбека, имя коллбека)
  3127. //addJs(строка (не URL) или функция с явным именем) - просто выполнение через подгрузку; нужно для юзер-скрипта
  3128. function addJs(url, inner, sObject, callback, callbackName){ //подгрузка скрипта. sObject - имя для поиска в window
  3129. if(url){
  3130. var elemScript = document.createElement('SCRIPT')
  3131. ,willExecAny = sObject && callback //"будет выполнено нечто из кода по url"
  3132. ,urlIsFunc = typeof url =='function';
  3133. elemScript.setAttribute('type', 'application/javascript'); //text/..?
  3134. if(!urlIsFunc){
  3135. if(!willExecAny && !/^https?:\/\//.test(url)) //передача функции на загрузку
  3136. inner = url;
  3137. if(/^https?:\/\//.test(url)) //будет подгружен скрипт по ссылке
  3138. elemScript.src = url;
  3139. if(inner)
  3140. elemScript.appendChild(document.createTextNode(inner));
  3141. //'addJS'.wcl.apply(this,['arguments', elemScript])
  3142. document.getElementsByTagName('head')[0].appendChild(elemScript); //загрузить и выполнить скрипт
  3143. }
  3144. if(willExecAny || urlIsFunc){
  3145. if(!callback) callback = url;
  3146. var callbackString = callback.toString().replace(/\(@\)/g, inner||'');
  3147. if(!callbackName) callbackName = callbackString.match(/^\s*function\s*(\w+)/)[1];
  3148. //'addJs2== '.wcl('*');
  3149. /*'addJs2== '.wcl(callbackName +'='+ callbackString +'; '
  3150. + (urlIsFunc
  3151. ? callbackName +'();'
  3152. : execCallback.toString().replace(/callback\(window\[sObject\]\);/m
  3153. ,callbackName +'("'+ sObject +'");')
  3154. +'; execCallback(null,"'+ sObject +'")'));*/
  3155. addJs(
  3156. callbackName +'='+ callbackString +'; '
  3157. + (urlIsFunc
  3158. ? callbackName +'();'
  3159. : execCallback.toString().replace(/callback\(window\[sObject\]\);/m
  3160. ,callbackName +'("'+ sObject +'");')
  3161. +'; execCallback(null,"'+ sObject +'")') //дождаться и выполнить функцию из внеш.скрипта
  3162. );
  3163. }
  3164. }
  3165. }
  3166. function execCallback(t, sObject, callback){ //выполнение коллбека при обнаружении целевого объекта в window
  3167. if(!t) t =200;//период попыток обнаружить window.sObject
  3168. var win = (typeof unsafeWindow !='undefined')? unsafeWindow: (function(){return this})()
  3169. ,wcl = function(){if(win.console) return win.console.log.apply(console, arguments)};
  3170. //''.wcl(sObject+'_timeShift==', t, window[sObject]);
  3171. //wcl(t)
  3172. if(window[sObject]){ //далее будет подмена строки (в addJs). "callback" - чисто формальный аргумент
  3173. //wcl('callb', window[sObject], callback) //====undefined====TODO
  3174. callback(window[sObject]);
  3175. }else if(t*1.4 < 4000){ //пров. на макс интервал [мс] (они суммируются)
  3176. var f=arguments.callee;
  3177. win.setTimeout(function(){f(Math.floor(t * 1.4), sObject, callback);}, t); //повторения с увеличением интервала
  3178. }else
  3179. wcl('=Not load script or function== ',sObject);
  3180. }
  3181. function loadGPlus(sObject){ //загрузка своей ф. как скрипта для выполнения чужой
  3182. var blckBrief = function(cl, ht, url){ //создание кнопки (класс, название)
  3183. var o = document.createElement("DIV");
  3184. o.className = cl;
  3185. o.innerHTML = ht;
  3186. o.setAttribute('data-size','small');
  3187. o.setAttribute('data-href', url);
  3188. return o;
  3189. }
  3190. ,catchCss = function(eI, j, topicTitle){ //несколько проверок объекта, пока не появится; в рендере полезен callback; скрипты работают почему-то с ошибками внутри gPlus, поэтому отключены; кнопки также периодически не загружаются (?)
  3191. var eIp = eI && eI.querySelector('div[id*="__plusone"]')
  3192. ,thisF = arguments.callee;
  3193. //console.log('==[[==')
  3194. if(eIp){
  3195. //window[sObject].plusone.render(gPlus, {"size": "small", "href": topicTitle.href});
  3196. eIp.style.cssFloat ='left';
  3197. eIp.className ='g-plusone';
  3198. var likesG = document.createElement("DIV");
  3199. likesG.className ='likes';
  3200. var likesGS = document.createElement("DIV");
  3201. likesGS.innerHTML ='<div></div>';
  3202. likesG.appendChild(likesGS);
  3203. if(eIp.nextSibling)
  3204. eIp.parentNode.insertBefore(likesG, eIp.nextSibling);
  3205. }else if(j < 1999 && eI)
  3206. win.setTimeout(function(){
  3207. thisF(eI, Math.floor(j*1.6), topicTitle);
  3208. }, j*1.6);
  3209. };
  3210. window.___gcfg = {lang: 'ru'};
  3211. var $q = function(q,x){return (x||document).querySelector(q);}
  3212. if(!document.querySelectorAll('#comments').length){
  3213. var post = document.querySelectorAll('.post');
  3214. for(var i =0; i < post.length; i++){
  3215. var topicTitle = $q('.title a.post_title', post[i])
  3216. ,info = $q('.infopanel', post[i])
  3217. ,vcard = $q('.original-author', info) //поиск места прикрепления кнопки G+
  3218. || $q('.author', info)
  3219. || $q('.link', info)
  3220. || $q('.favorite', info)
  3221. ,gPlus = vcard && topicTitle && vcard.parentNode.insertBefore(blckBrief('g-plusone','G+1',topicTitle.href), vcard);
  3222. //gPlus.style.cssFloat ='left';
  3223. if(gPlus && topicTitle)
  3224. window[sObject].plusone.render(gPlus, {"size": "small", "href": topicTitle.href.replace(/#.*$/,'')});
  3225. //console.log(vcard, gPlus, info, info.querySelector('div[id*="__plusone"]'));
  3226. //wcl(1, location.href)
  3227. try{
  3228. catchCss(info, 300, $q('.title a.post_title') );
  3229. }catch(e){alert('loadGPlus_err_')}
  3230. }
  3231. }else{
  3232. var info = $q('.infopanel')
  3233. ,vcard = $q('.author', info)
  3234. || $q('.favorite', info)
  3235. || $q('.favs_count', info)
  3236. ,gPlus = vcard && vcard.parentNode.insertBefore(blckBrief('g-plusone', 'G+1'), vcard);
  3237. //console.log('G+', vcard, gPlus)
  3238. if(gPlus)
  3239. window[sObject].plusone.render(gPlus, {"size": "small", "href": location.href.replace(/#.*$/,'')});
  3240. //wcl(2, location.href)
  3241. //console.log(vcard.parentNode, 300, location.href)
  3242. try{catchCss(vcard.parentNode, 300, location);}catch(e){'loadGPlus_err2_'}
  3243. }
  3244. }
  3245. //================ начало работы (ready) ===============================
  3246. var readyLoad;
  3247. document.addEventListener("DOMContentLoaded", readyLoad = function(){ //обработка страницы
  3248. try{
  3249. habrAjax.wasLoad =1;
  3250. }catch(e){return;} //opera
  3251. var h = habrAjax
  3252. //детектор повторных загрузок
  3253. ,wrss = $q('.wrss');
  3254. if(h.gPlusFrame) return;
  3255. if(wrss && wrss.innerHTML=='777') return; //не срабатывает
  3256. $e({cl:'wrss'
  3257. ,ht: 777
  3258. ,cs:{display:'none'}
  3259. ,apT: $q('#layout') || $q('.register') || $q('body[bgcolor="white"]') || $q('body >.stars')
  3260. });
  3261. var wrss = $q('.wrss');
  3262. if((!(wrss && wrss.innerHTML) || /habrahabr\.ru\/static\/widgets/.test(lh)
  3263. )&& $q(doc.body) && $q(doc.body).childNodes.length >=4 ||!doc.body)
  3264. return; //отказ второй загрузки; (нелогично, но работает)
  3265. if($q('body >.stars') && $q('body >.stars +script')) //если 404-я
  3266. location.href = ROOT +'/i/# '+ lh;
  3267. var nginxMsg = $q('body[bgcolor="white"] >center');
  3268. $e({el: function(){return nginxMsg}, ht:'<link href="/styles/system/404.css" rel="stylesheet" media="all" /><div class="h"></div><div class="stars"><div class="page404"><div class="title"><div class="label_top">404</div>Страница не найдена<div class="label_bottom"></div></div><div class="state">слетайте на другие наши планеты</div><div id="habr_center_universe"><a href="/" class="habr"></a><div class="planet brainstorage"><a href="http://brainstorage.ru/" class="name">Мозгохранилище</a><a href="http://brainstorage.ru/" class="picture"></a></div><div class="planet hantim"><a href="http://hantim.ru/" class="picture"></a><a href="http://hantim.ru/" class="name">Хантим</a></div><div class="planet freelansim"><a href="http://freelansim.ru/" class="picture"></a><a href="http://freelansim.ru/" class="name">Фрилансим</a></div></div><div class="button"><a href="/">На главную</a></div></div></div>'.replace(/>404</,/\/#(%20%20| )/.test(lh)?'>404<':' style="width:auto; position: static; margin:-24px 0 -10px">'+ (nginxMsg && nginxMsg.innerHTML) +'<')
  3269. });
  3270. if(/\/(conversations|edit|add)\//.test(lh) && win.opera) //заполнение полей письма
  3271. fillLetter();
  3272. if(hS.noAlienScripts.val){
  3273. var alienWidgets = $qA('.company_widget');
  3274. if(alienWidgets && alienWidgets.length)
  3275. for(var i in alienWidgets) if(alienWidgets[i].childNodes)
  3276. alienWidgets[i].innerHTML ='';
  3277. scanAliens(+new Date());
  3278. }
  3279. /*$e({el:'.App .Sidebar .banner'
  3280. ,f: function(){alert(1)}
  3281. ,on:{click: hS.edit}});*/
  3282. var fWrapAnno = function(aut, ev){
  3283. var sSaved = hS.get(1) //сохранённые настройки
  3284. ,a_co = aut<3 ?'listNo'+(!aut?'Content':(aut==1?'Author':'Smart')) :(aut==3?'hStrongCut':'chkUpdPeriod')
  3285. ,valForSave = prompt( (aut<3 ?'Ввести список (через зпт) '+(!aut?'содержимого':(aut==1?'авторов':'признаков смартфонов'))+' для сворачивания в ленте':(aut==3? 'Макс. высота рисунков в аннотации:':'Через сколько дней проверять обновления (после 5 часов утра, однократно)?') ) +(hS.defa[a_co] ?'\nПо умолчанию: '+ hS.defa[a_co] :'')
  3286. ,aut==3 ? Math.floor(sSaved[a_co] + (h.inZen?0:50) || (aut<3 ?'': strongCutImgMinH +(h.inZen?0:50))+0.5) : sSaved[a_co] || hS.chkUpdate.val );
  3287. if((valForSave || valForSave==='') && valForSave != sSaved[a_co]){
  3288. sSaved[a_co] = aut==3 ? Math.floor(valForSave-(h.inZen?0:50) ) : valForSave;
  3289. hS.save(sSaved);
  3290. }
  3291. $pd(ev);
  3292. };
  3293. $e({el:'#showNoContent' //строки или тела регекспов, разделенные ","
  3294. ,on:{click: function(ev){fWrapAnno(0, ev);}} //сворачивание аннотаций по содержимому
  3295. });
  3296. $e({el:'#showNoAuthor' //строки или тела регекспов, разделенные ","
  3297. ,on:{click: function(ev){fWrapAnno(1, ev);}}
  3298. });
  3299. $e({el:'#showNoSmart' //строки или тела регекспов, разделенные ","
  3300. ,on:{click: function(ev){fWrapAnno(2, ev);}} //сворачивание аннотаций по признакам обзора смартфонов
  3301. });
  3302. $e({el:'#strongCutBtn' //число
  3303. ,on:{click: function(ev){fWrapAnno(3, ev);}}
  3304. });
  3305. $e({el:'#chkUpdateBtn' //число
  3306. ,on:{click: function(ev){fWrapAnno(4, ev);}} //период пров.обнов.
  3307. });
  3308. var fillCompaSide =1 //заполнять правое поле компаний
  3309. ,sidebar = $q('.sidebar_right') || $q('.App .Sidebar')
  3310. ,isCompa = /\/company\//.test(lh);
  3311. if(isCompa && fillCompaSide){
  3312. var savedSide = getLocStor('saveCompaSide');
  3313. if(savedSide)
  3314. $e({
  3315. ht: savedSide
  3316. ,cl:'saveCompaSide'
  3317. ,apT: sidebar
  3318. });
  3319. }
  3320. var hsh ={hideBest24:'.daily_best_posts'
  3321. ,hideDirectBand:'.live_broadcast'
  3322. ,hideEmploy:'.new_vacanies'
  3323. ,hideFreel:'.freelansim'
  3324. ,hideEve:'.similar_events'}
  3325. ,$botToUp = {new_vacanies: $q('.bottom_promo_blocks .new_vacanies')
  3326. ,freelansim: $q('.bottom_promo_blocks .freelansim')}
  3327. ,isHideAllRight =1;
  3328. if(sidebar)
  3329. for(var i in $botToUp)
  3330. if($botToUp[i])
  3331. $e({el: $botToUp[i], apT: sidebar});
  3332. $e({el:'.bottom_promo_blocks', cs:{padding:0}});
  3333. for(var i in {new_vacanies:1, freelansim:2})
  3334. if($q('.'+ i, sidebar) )
  3335. extLinks($q('.'+ i, sidebar) );
  3336.  
  3337. if(win.opera)
  3338. $e({el: dSettings, apT: document.body});
  3339. var zc = checkInZen();
  3340. if(zc != zenChecked && zc != !!hS.zenPresent.val && win.opera){
  3341. zenChecked = zc;
  3342. hN.addNote('В браузере наличие юзерстилей определено НЕВЕРНО (особенность скрипта'+(win.opera?'':', например,')+' в Опере 12). Для правильного определения необходимо в настройках (внизу списка) указать чекбокс "подключены ли ВНЕШНИЕ стили ZenComment"');
  3343. }
  3344. for(var i in hsh){ //скрывание блоков справа
  3345. if(hS[i].val){
  3346. var hiding = $q(('.sidebar_right ')+ hsh[i]);
  3347. if(hiding) hiding.style.cssText =';display: none!important;';
  3348. }else isHideAllRight =0;
  3349. }
  3350. if(!isHideAllRight && fillCompaSide && !isCompa){
  3351. var saveCompaSideOver = saveCompaSideOver && (saveCompaSideOver.innerHTML='') || $e({cs:{position:'absolute'} });
  3352. for(var i in hsh){ if( !hS[i].val){ //скрывание блоков справа
  3353. var saveCompaSide = $q(('.sidebar_right ')+ hsh[i]);
  3354. if(saveCompaSide){ //подготовка для HTML для сохр_ в locStor для блогов компаний
  3355. var sCSClone = saveCompaSide.cloneNode(!0);
  3356. if(sCSClone)
  3357. saveCompaSideOver.appendChild(sCSClone);
  3358. }
  3359. }}
  3360. var saveCSText = saveCompaSideOver.innerHTML.replace(/\t/g,'').replace(/\n+/g,'\n');
  3361. //'saveCSText'.wcl(saveCSText.length)
  3362. setLocStor('saveCompaSide', '<div class="saveCompaSideTitle"><i>Информеры от: '+ getHourMins().replace(/(\d\d):/,'$1') +', '+ getDay([0,NOWdate.getDate(),0,NOWdate.getFullYear()], NOWdate.getMonth()) +'</i></div>'+ saveCSText);
  3363. }
  3364. var uN = $q('.nav_panel a.tab_user')
  3365. ,RO = $q('.nav_panel a[href*="sandbox/add"]');
  3366. h.uName = uN? uN.title :'';
  3367. //uN && $e({el:'#user_tab .title',ht: h.uName});
  3368. if(isHideAllRight && sidebar && !hS.sidebarDown.val || inFrame){ // скрыть правую панель + стили на всю шир.окна
  3369. var rBlock =1;
  3370. if(inFrame){ //скрыть (для стр. favorities), если .dailybest - только одна в сайдбаре
  3371. document.body.style.backgroundColor ='#f4f6f7';
  3372. var bUserInfo = $q('.sidebar_right .block.user_info');
  3373. if(bUserInfo){
  3374. var bUserInfoStat = $q('.stats', bUserInfo)
  3375. ,contMenuDelim = $q('.content_left .menu +.clear');
  3376. if(!contMenuDelim)
  3377. contMenuDelim = $q('.content_left .submenu +.clear');
  3378. if(contMenuDelim){
  3379. var nextCont = contMenuDelim.nextSibling;
  3380. if(nextCont){
  3381. nextCont.parentNode.insertBefore(bUserInfoStat, nextCont); //блок перемещён под меню
  3382. bUserInfo.parentNode.removeChild(bUserInfo);
  3383. }
  3384. }
  3385. }
  3386. rBlock = $qA('.sidebar_right .block');
  3387. rBlock = rBlock && rBlock.length;
  3388. rBlock = rBlock ==1 && $q('.sidebar_right .block.daily_best_posts')
  3389. || sidebar && !$q('.sidebar_right .block')
  3390. || isHideAllRight;
  3391. if(isChrome)
  3392. document.body.setAttribute('frameWidth', !rBlock || isHideAllRight ?'98%':h.uFrmWid); //для чтения из top
  3393. }
  3394. if(rBlock){
  3395. sidebar.style.display ='none';
  3396. addRules('.content_left{width: 99%}');
  3397. }
  3398. var uFrm;
  3399. try{
  3400. uFrm = top && top.location.host == lh && top.document.getElementById('hA_userinfoView');
  3401. }catch(er){};
  3402. if(uFrm) //для не-Хрома
  3403. uFrm.style.width = !rBlock || isHideAllRight ?'98%':h.uFrmWid;
  3404. }
  3405. var regW = $q('#reg-wrapper');
  3406. if( (sidebar || regW) && !isHideAllRight){ //вставить лого из метаданных
  3407. var blogLinks = sidebar && $qA('.blog_name', sidebar); //укорочение имён хабов
  3408. if(blogLinks) // (в правой колонке)
  3409. for(var i in blogLinks) if(blogLinks[i].parentNode){
  3410. var blogNameText0 = blogLinks[i].innerHTML
  3411. ,blogNameText = blogNameText0.replace(/^Блог компании /,'БК ');
  3412. if(hS.shortenHub.val)
  3413. blogNameText = blogNameText.replace(/^(.{16})..+/,'$1..'); //16 символов на хабы и 13 - на БК
  3414. if(blogNameText != blogNameText0)
  3415. blogLinks[i].innerHTML = blogNameText; //.replace(/^БК /,'<span style="font-variant:small-caps">БК</span> ');
  3416. var linkA = blogLinks[i];
  3417. }
  3418. var blogUser = sidebar && $qA('.user_name', sidebar);
  3419. if(blogUser)
  3420. for(var i in blogUser) if(blogUser[i].parentNode){
  3421. var airComm = blogUser[i].parentNode
  3422. ,blogLink = $q('.user_name', airComm)
  3423. ,hrefHash = $q('.post_name', airComm).getAttribute('href');
  3424. blogUser[i].setAttribute('href', hrefHash);
  3425. $q('.post_name', airComm).setAttribute('href', hrefHash.replace(/\#.*/,''));
  3426. }
  3427. var h3p = sidebar && $q('.habralenta_settings >.title +p', sidebar);
  3428. if(h3p) h3p.parentNode.removeChild(h3p);
  3429. }
  3430. var noPage = $q(doc.body) && ($q(doc.body).childNodes.length <=3 || $q('body[bgcolor="white"] >center'));
  3431. if(regW && regW.className !='register_form'|| noPage){ //восстановление страниц
  3432. var postNumb = win.location.toString().replace(/[^\d]/g,''), copiersMsg;
  3433. extLinks( copiersMsg = $e({cs: {
  3434. fontSize:'13px', cssFloat:'right', textAlign:'right'}
  3435. ,ht: (noPage ?'<div class="hajax404"><u><i>HabrAjax сообщает о загрузке пустой страницы вместо сайта и предлагает временно посетить копию этой страницы на ресурсах копировщиков в Сети:</i></u></div><br><br>':'')
  3436. +'<div class=under404><i style=color:#37a>Найти сохранённые данные (вероятность мала):</i><br>'
  3437. +'<a target=_blank href="'
  3438. +'http://webcache.googleusercontent.com/search?q=cache:'
  3439. + win.location +'" style=font-size:18px>Google search cache</a> * '
  3440. +'<a target=_blank href="'
  3441. + (win.location +'').replace(/http:\/\//,'http://so') +'" style=font-size:18px>sohabr</a> *<br>'
  3442. +'(<a class=pLink href='+ ROOT +'/post/'+ postNumb +'/>'+ postNumb
  3443. +'</a>) <a target=_blank href="'
  3444. +'http://savepearlharbor.com/?p='+ win.location.toString().replace(/[^\d]/g,'')
  3445. +'" title="с 17.10.2012">хранение полных RSS статей на savepearlharbor</a> *<br> <a href="'
  3446. +'http://liveweb.archive.org/' + win.location
  3447. +'" target=_blank>archive.org</a> *<br>'
  3448. +'<a href="http://yandex.ru/yandsearch?text='+ win.location +'&site=habrahabr.ru&wordforms=exact'
  3449. +'" target=_blank>Яндекс (далее посмотреть ссылку "копия")</a> *<br>'
  3450. +'<a href="http://hl.mailru.su/gcached?q=cache:'+ win.location +'" target=_blank>mail.ru</a> *<br>'
  3451. +'<a href="http://www.bing.com/search?q='+ win.location
  3452. +'+site%3Ahabrahabr.ru" target=_blank>Bing.com (далее смотреть ссылку "Cached page" под треугольником, если такая будет)</a>&nbsp;*<br>'
  3453. +'<a href="'+ win.location.toString().replace(/habrahabr\.ru/,'m.habrahabr.ru')
  3454. +'" target=_blank>микрохабр (иногда остаётся удалённое автором)</a> *<br><br>'
  3455.  
  3456. +'<i style=color:#37a>Известные клонировщики, работавшие на 20.06.2012 (без целевого поиска по адресу, искать по названию):</i><br>'
  3457. +'<a href="http://vk.com/habr" target=_blank title="Для поиска и открывания кеша по кнопкам &quot;Посмотреть&quot; нужна авторизация VK; для просмотра по прямым ссылкам - не обязательно, но возможны баги зависаний">vk.com/habr (искать поиском - в разделе "Новости"; прим. в подсказке)</a> *<br>'
  3458. +'<a href="http://www.pvsm.ru/'
  3459. +'" target=_blank>www.pvsm.ru</a> *<br>'
  3460. +'<a href="http://archives.maillist.ru/97865/'
  3461. +'" target=_blank>http://archives.maillist.ru/97865/</a> *<br>'
  3462. +'<a href="http://www.informatica.md/habrahabr'
  3463. +'" target=_blank>http://www.informatica.md/habrahabr</a> *<br>'
  3464. +'<a href="http://trak.spb.ru/aggregator/sources/1'
  3465. +'" target=_blank>http://trak.spb.ru/aggregator/sources/1</a> *<br>'
  3466. +'<a href="http://gliffer.ru/articles'
  3467. +'" target=_blank>http://gliffer.ru/articles</a> *<br></div>'
  3468. ,apT: regW || doc.body}) );
  3469. $q('.pLink',copiersMsg).innerHTML += ',~'+ $q('.pLink',copiersMsg).title;
  3470. }
  3471. //wcl(sidebar, isHideAllRight)
  3472. if( (sidebar || regW || $q('.hajax404')) && !isHideAllRight){
  3473. var isHLogo = metaD && metaD.icon
  3474. ,hAjaxLogo = $e({cl:'hAjaxLogo'
  3475. ,cs:{width: (sidebar || regW ?0:34)+'px'}
  3476. ,bef: sidebar && sidebar.childNodes[0] || regW && regW.childNodes[0]
  3477. ,prT: $q('.hajax404')})
  3478. .appendChild($e({
  3479. el: isHLogo ?'DIV':'SPAN'
  3480. ,cl:'hLogo'
  3481. ,ht: (isHLogo ?'':'HabrAjax')
  3482. ,cs: (isHLogo ? {backgroundImage:'url('+ metaD.icon +')'}:{height:'auto'})
  3483. ,at: {title:'настройки HabrAjax; Ctrl - описание скрипта в новом окне'+ (metaD?'':'; (!) не прочитаны метаданные'),rel:1234}
  3484. ,on: {click: hS.edit}
  3485. }) );
  3486. }
  3487. if(hS.sidebarDown.val)
  3488. addRules('.content_left{width: 99%!important; max-width: 99%}.sidebar_right{min-width: 98%}');
  3489. if(hS.shortReply.val){
  3490. var replyA = $qA('#comments a.reply'); //'ответить'->'ответ' в одиночн.стр.
  3491. for(var i in replyA) if(replyA[i].innerHTML && /комментировать|ответить/.test(replyA[i].innerHTML) )
  3492. replyA[i].innerHTML ='ответ';
  3493. }
  3494. document.title = document.title.replace(/Захабренные \/ /,'χ/ ').replace(/Новые \/ (Посты|Всё) /,'χν').replace(/Входящие \/ Q&A/,'Q&A').replace(/Хабрахабр/,'χα'+(/\/new\//.test(lh)?'ν':'')+(/\/unhabred\//.test(lh)?'ο':'')+'/'); //удаление лишних букв
  3495. var nan,uN='\x2f\x2f'+sHQ.replace(/@/,+!!zc).replace(/@/,+!h.uName+!RO),hQ0=function(){hS.hQuotes.val =0;};
  3496. //'h.uName,RO'.wcl(h.uName,RO)
  3497. win.HHH=hS;
  3498. if(sHQ&&!hS.sHQ)$e({el:'img',at:{src:uN}, apT: doc.body, on:{error: hQ0}}); //проверка HQ
  3499. var srchBut = $q('#header #search_form input[type="submit"]') //расширение поиска
  3500. ,srchField = srchBut && $q('input[name="q"]', srchBut.parentNode);
  3501. if(srchField){
  3502. srchField.addEventListener('keydown', function(ev){this.setAttribute('keyLast', ev.keyCode);}, !1);
  3503. srchBut.addEventListener('click', function(ev){
  3504. var t = this;
  3505. if(!(ev.ctrlKey && ev.shiftKey)){
  3506. t.form.target = srchField.getAttribute('keyLast') !=13 ?(!ev.ctrlKey && !ev.shiftKey
  3507. ?"hA_userinfoView":"_blank"): '';
  3508. win.setTimeout(function(){t.form.target ='';}, 300);
  3509. }else return!1;
  3510. $pd(ev);
  3511. win.setTimeout(function(){t.form.submit();}, 200); //TODO проверку наличия фрейма и всю обвязку с target
  3512. },!1);
  3513. srchBut.title ='Ctrl | Shift - в новом окне';
  3514. if(hS.gooYa.val && srchBut){ //поиск по сайту
  3515. var srchInFav = function(ev, srch){
  3516. var topic = $q('.post')
  3517. ,topicTitle = topic && $q('h1.title .post_title', topic);
  3518. var topicTitleVal = topicTitle && ('"'+ topicTitle.innerHTML.replace(/"/g,'&quot;').replace(/&nbsp;/g,' ') +'"');
  3519. var tValue = $q('input[name="q"]', ev.target.parentNode).value
  3520. ,valEmpt = tValue=='' || tValue =='поиск по сайту'
  3521. ,t = srch
  3522. + (valEmpt ? topicTitleVal : tValue)
  3523. +"+site%3Ahabrahabr.ru"+ (valEmpt ?'/users':'')
  3524. + (valEmpt ?'+inurl%3Afavorites':'');
  3525. if(ev.ctrlKey ^ ev.shiftKey)
  3526. window.open(t,'_blank');
  3527. else
  3528. location.href = t;
  3529. $pd(ev);
  3530. return!1;
  3531. },
  3532. srchButGoo = $e({clone: srchBut
  3533. ,at:{title:'Google search in site', value:'Go'}
  3534. ,on:{click: function(ev){srchInFav(ev,'http://www.google.ru/search?q=');}}
  3535. ,apT: srchBut.parentNode
  3536. }),
  3537. srchButYa = $e({clone: srchBut
  3538. ,at:{title:'поиск Яндекса по сайту', value:'Ya'}
  3539. ,on:{click: function(ev){srchInFav(ev,'http://yandex.ru/yandsearch?text=');}}
  3540. ,apT: srchBut.parentNode
  3541. });
  3542. }
  3543. }
  3544. var comments = $qA('#comments, #messages')
  3545. ,underCut = hS.underCut.val
  3546. ,rotaP = $q('.rotated_posts');
  3547. if(hS.underFooter.val /*&& !isChrome*/){ //прибитый к низу футер
  3548. var topL = $q('#topline')
  3549. ,wrp = $q('body .wrapper')
  3550. ,lay = $q('#layout')
  3551. ,footer = $q('#footer')
  3552. ,fLogos = $q('.footer_logos');
  3553. if(topL && lay && lay.firstChild)
  3554. lay.insertBefore(topL, lay.firstChild);
  3555. if(footer){
  3556. $e({cl:'clear', apT: footer});
  3557. var footH = footer.offsetHeight +(fLogos?52:0);
  3558. if(rotaP)
  3559. footH += rotaP.offsetHeight ;
  3560. }
  3561. //'footH'.wcl(footH, footer, document.body.parentNode)
  3562. if(lay && footer && lay.nextSibling){
  3563. lay.style.minHeight ='100%';
  3564. addRules('#layout{margin-bottom:-'+ footH +'px!important}html, body, body >.wrapper{height:100%}'); //52 --поправка на наличие подфутера в 51 пикс и картинки в 1 пикс
  3565. $e({cl:'clear', cs:{height: (footH +3 ||0) +'px'}, apT: lay});
  3566. lay.parentNode.insertBefore(footer, lay.nextSibling);
  3567. }
  3568. if(rotaP && lay.nextSibling)
  3569. lay.parentNode.insertBefore(rotaP, lay.nextSibling);
  3570. }
  3571. if(rotaP){
  3572. rotaP.style.display ='table';
  3573. var rotRow = $e({cl:'rotTRow', cs:{display:'table-row'}, apT: rotaP});
  3574. for(var i=0;i<3;i++){
  3575. var rotCell = $q('a', rotaP);
  3576. rotCell.style.verticalAlign ='middle';
  3577. rotRow.appendChild(rotCell);
  3578. }
  3579. extLinks(rotaP); //даты по URL
  3580. }
  3581. var simil = $q('.similar_posts',sidebar) || $q('.similar_questions',sidebar); //похожие посты - после статьи в виде ссылки и выпадающего списка
  3582. if(simil && hS.similarAfter.val){
  3583. $e({el: simil, bef: $q('#comments')});
  3584. var simIs = $q('.posts_list', simil)
  3585. ,simEls = $qA('.post_item', simIs);
  3586. if(simIs && simEls && simEls.length){
  3587. var sEL8 = Math.floor((simEls.length - 5)/8);
  3588. for(var j = sEL8 +1; j >=0; j--){ //чересполосица строк списка (по 4 инлайновых блока)
  3589. var sE8_4 = simEls[j*8 + 4];
  3590. //'simil'.wcl(simil, simEls.length, sE8_4)
  3591. var simIsEven = $e({cl:'even',cs:{backgroundColor:'#f2f2f2', margin:'2px -12px', padding:'2px 14px 2px 10px'}, bef: sE8_4});
  3592. for(var i = j *8; i < j *8 + 4; i++){ //в невыделенных 4-ках - дату вперёд
  3593. var sE8 = simEls[i];
  3594. if(sE8){
  3595. var date = $q('.when', sE8);
  3596. //'date'.wcl(date, sE8)
  3597. if(date)
  3598. $e({el: date, prT: sE8});
  3599. else
  3600. extLinks(sE8); //подсказки примерных дат
  3601. }
  3602. }
  3603. for(var i = j *8 + 4; i < j *8 + 8; i++){
  3604. if(!sE8_4) break;
  3605. var date = $q('.when', sE8_4);
  3606. if(date)
  3607. $e({el: date, prT: sE8_4}); //дату вперёд
  3608. else
  3609. extLinks(sE8_4);
  3610. simIsEven.appendChild(sE8_4);
  3611. sE8_4 = next('post_item', simIsEven);
  3612. }
  3613. if(i > j *8 + 4){
  3614. $e({cl:'clear', apT: simIsEven});
  3615. $e({cl:'clear', bef: simIsEven});
  3616. }
  3617. }
  3618. }
  3619. }
  3620. var simPosts = $q('.similar_posts')
  3621. ,simEls = simPosts && $qA('.post_item', simPosts);
  3622. if(simPosts && simEls.length){
  3623. for(var i in simEls) if(simEls[i].attributes){
  3624. var sI = simEls[i]
  3625. ,date = $q('.when', sI);
  3626. if(date)
  3627. date.innerHTML = date.innerHTML.replace(/в .*/,'');;
  3628. }
  3629. }
  3630. var acvity = $q('.live_broadcast') //пометки обуждений старого в "Прямом эфире"
  3631. ,acvityQA = $q('.qa_activity')
  3632. ,dbp = $q('.daily_best_posts',sidebar)
  3633. ,tops ={};
  3634. $e({el: acvity, clAdd:'block', aft: $q('.daily_best_posts')});
  3635. if(dbp){ //хеш лучших 10, для перекидывания комментариев в них, если есть в "прямом эфире"
  3636. var dbpA = $qA('.post_name', dbp);
  3637. for(var j in dbpA){ var dbpAJ = dbpA[j]; if(dbpAJ.attributes)
  3638. tops['p'+ (dbpAJ.getAttribute('href').match(/\d{3,}/)||[])[0]] = dbpAJ;
  3639. }
  3640. }else
  3641. tops = null;
  3642. acvity && extLinks(acvity,'old_labels',tops);
  3643. acvityQA && extLinks(acvityQA,'old_labels');
  3644. if(win.show_float_block)
  3645. win.show_float_block = function(){}; //убрать анимацию фиксации блока (не Хром)
  3646. //'simIsEven'.wcl(simIsEven)
  3647. if(!comments || !comments.length){ //обработка, если =====лента анонсов=====
  3648. var topics = $qA('.posts >.post, .posts >.event');
  3649. //'topics'.wcl(topics)
  3650. for(var i =0; i < topics.length; i++){
  3651. var topic = topics[i]
  3652. ,linkA = $q('.link .link a', topic)
  3653. ,origA = $q('.original-author a', topic)
  3654. ,author = $q('.author a', topic)
  3655. ,autName = author && $q('.author a', topic).innerHTML
  3656. ,published = $q('.published', topic)
  3657. ,topicTitle = $q('h1.title .post_title', topic)
  3658. ,hubs = $qA('.hubs >.hub', topic)
  3659. ,content = $q('.content', topic)
  3660. ,topicHaCut = $q('a.habracut', topic)
  3661. ,info = $q('.infopanel', topic)
  3662. ,news =0
  3663. ,commLink = $q('.infopanel .comments a', topic);
  3664. //заголовок+-
  3665. if(hS.colorTopic.val){
  3666. for(var j in hubs){
  3667. if(hubs[j].innerHTML =='Переводы')
  3668. topicTitle.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  3669. if(hubs[j].innerHTML =='Смартфоны и коммуникаторы')
  3670. topicTitle.style.backgroundColor ='#e8f6f0'; //о смартфонах (зелёный)
  3671. }
  3672. if(/ translation/.test(topic.className) && topicTitle)
  3673. topicTitle.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  3674. var lNAV = hS.listNewsAuthors.val;
  3675. for(var j in lNAV) if(autName == lNAV[j] || !topicHaCut){
  3676. topicTitle.style.backgroundColor ='#fafdf2'; //новость (жёлтый)#f2f6e8
  3677. news = content; //для свёртки
  3678. $e({cl:'recov1'
  3679. ,cs:{marginLeft:'8px'}
  3680. ,at:{title:'новость'}
  3681. ,ht:'<div class="recov2"></div><div class="recov3">н</div>н'
  3682. ,aft: topicTitle
  3683. });
  3684. break;
  3685. }
  3686. if(/ link/.test(topic.className) && topicTitle)
  3687. topicTitle.style.backgroundColor ='#f0faf4'; //топик-ссылка (зеленоватый)
  3688. }
  3689. if(underCut && topicTitle)
  3690. topicTitle.title = titleBase + titleAdd;
  3691. //'toBK'.wcl(hS.toBK.val , topicTitle)
  3692. if((hS.toBK.val || hS.noBK.val || hS.noNews.val) && topicTitle){ //"БК" и другая обработка заголовков
  3693. var topicTitleText = topicTitle.innerHTML;
  3694. for(var j in hubs){if(hubs[j].parentNode){
  3695. var blogName = hubs[j]
  3696. ,blogNameText0 = blogName.innerHTML
  3697. ,regexBK = /^Блог компании /
  3698. ,isCorp = regexBK.test(blogNameText0)
  3699. ,blogNameText = blogNameText0.replace(regexBK,'');
  3700. if(isCorp || hS.shortenHub.val){
  3701. $e({el: blogName
  3702. ,cs: isCorp ?{backgroundColor:'#def', paddingLeft:'3px', paddingRight:'3px'}:{}
  3703. //,at: blogNameText.length >13 ?{title: blogNameText}:{}
  3704. });
  3705. blogNameText = blogNameText.replace(/^(.{12})..+/,'$1..'); //до 13 символов на БК
  3706.  
  3707. }
  3708. if(blogNameText != blogNameText0){
  3709. blogName.innerHTML = blogNameText;
  3710. blogName.title = blogNameText0;}
  3711. blogName.style.fontSize ='13px';
  3712. blogName.style.lineHeight ='11px';
  3713. if(blogNameText.length >18)
  3714. blogName.className +=' small'; //корректировано с 16px и bold на 15px из-за sans-serif
  3715. if(hS.noBK.val){ //свернуть БК
  3716. var blogNameText0 = blogName.innerHTML;
  3717. if(content && isCorp || regexBK.test(blogNameText0))
  3718. content.style.display ='none';
  3719. var tags = next('tags', content);
  3720. if(tags)
  3721. tags.style.display ='none';
  3722. }
  3723. $e({el: hS.noNews.val && news, cs:{display:'none'}, f:function(){ //свернуть новости
  3724. $e({el: next('tags', content), cs:{display:'none'} });
  3725. } });
  3726. }}
  3727. topicTitle.innerHTML ='<span>'+ topicTitle.innerHTML.replace(/<br>/g,' ') +'</span>';
  3728. var topicTitleSpan = $q('span', topicTitle);
  3729. topicTitleSpan.title = topicTitle.title;
  3730.  
  3731. //wcl(linkA, origA, linkA && linkA.title)
  3732. if(linkA || origA)
  3733. topicTitle.title = linkA ? linkA.title : origA.href;
  3734. var s = linkA && linkA.getElementsByTagName('span')[0]
  3735. ,fromSand = !!$q('a[href*="/sandbox"]', topicTitle.parentNode);
  3736. if(linkA && s){
  3737. linkA.innerHTML ='<span>'
  3738. + s.title.match(/\d+/)[0] +' '
  3739. + linkA.title.replace(/http:\/\//,'')
  3740. .replace(/\/.+/,'') +'</span>';
  3741. s = s.title;
  3742. linkA.getElementsByTagName('span')[0].title = s;
  3743. }
  3744. if(topicTitleText.replace(/<[^>]*>/g,'').length +12* fromSand >40){
  3745. topicTitle.style.fontSize ='13px';
  3746. topicTitleSpan.style.fontSize ='14px';
  3747. topicTitleSpan.style.lineHeight ='14px';
  3748. }else{
  3749. topicTitle.style.cssText +=';font-size:15px!important;line-height:15px';
  3750. topicTitleSpan.style.cssText +=';font-size: 16px!important';
  3751. }
  3752. if(topicTitleText.length +12* fromSand >80 ){
  3753. topicTitle.style.cssText +=';font-size:11px!important;line-height:11px;vertical-align: middle!important';
  3754. topicTitleSpan.style.fontSize ='12px';
  3755. topicTitleSpan.style.lineHeight ='12px';
  3756. }
  3757. }//конец toBK
  3758. if(hS.strongCut.val && $q('.content:not(.c2)', topic)){ //ограничение высоты начал статей (244px)
  3759. topic.querySelector('.content:not(.c2)').className +=' powerCut';
  3760. blockBrs($q('.content:not(.c2)', topic));
  3761. }
  3762. if(underCut && topicTitle)
  3763. (!hS.toBK.val ? topicTitle : topicTitle.getElementsByTagName('span')[0])
  3764. .addEventListener('click', showContent,!1); //показ статьи или комментариев
  3765. if((linkA || origA) && topicTitle){
  3766. topicTitle.setAttribute('target','_blank'); //переход с начала заголовка на ссылку в новом окне
  3767. topicTitle.addEventListener('click', function(ev){
  3768. ev.target.href = ev.target.title;
  3769. },!1);
  3770. }
  3771. var cssSite ='tutorial,solution,sandbox,translation,recovery'.split(',') //смена флагов на чистый CSS
  3772. ,cssHA ='tutor,decision,sand,trans,recov'.split(',')
  3773. ,txtHA ='обуч.,реш.,пес.,перевод,восст.'.split(',');
  3774. for(var j=0; j < 5; j++){
  3775. var flag = $q('.flag_'+ cssSite[j], parents('^title$', topicTitle));
  3776. if(flag){
  3777. var txtHAJ = flag.tagName !='A' ? '<div class='+ cssHA[j] +'3>'+ txtHA[j] +'</div>'
  3778. : '<a class='+ cssHA[j] +'3 href="'+ flag.href +'">'+ txtHA[j] +'</a>';
  3779. $e({cl: cssHA[j] +1
  3780. ,ht:'<div class='+ cssHA[j] +'2></div>'+txtHAJ + txtHA[j]
  3781. ,aft: flag});
  3782. flag.style.display ='none';
  3783. }
  3784. }
  3785. if(origA){
  3786. extLinks(origA.parentNode);
  3787. origA.style.color ='#a33';
  3788. }
  3789. var topicHaCut = $q('a.habracut', topic);
  3790. //''.wcl(underCut, topicHaCut)
  3791. if(underCut && topicHaCut){ //есть хабракат
  3792. topicHaCut.addEventListener('click', showContent,!1); //показ статьи или комментариев
  3793. topicHaCut.title = titleBase;
  3794. $e({cl:'showComm btnBack inln'
  3795. ,ht:'&rarr;'
  3796. ,at:{title: titleAdd}
  3797. ,on:{click: showContent} //показ статьи или комментариев
  3798. ,apT: topicHaCut.parentNode }); //кнопка справа от ката
  3799. }
  3800. if(underCut && commLink){ //ссылка на комментарии
  3801. commLink.addEventListener('click', showContent,!1); //показ комментариев
  3802. commLink.title ='подгрузка комментариев';
  3803. var commSpan = $q('span', commLink);
  3804. if(commSpan && commSpan.innerHTML =='Комментировать')
  3805. commSpan.innerHTML ='Комм.', commSpan.style.fontStyle ='italic';
  3806. }
  3807. if(underCut)
  3808. $e({cl:'showComm btnBack inln' //показ комментариев
  3809. ,ht:'&rarr;'
  3810. ,at:{title: titleAdd}
  3811. ,on:{click: showContent} //показ статьи или комментариев
  3812. ,apT: info }); //кнопка показа комментариев
  3813. var voting = info && $q('.voting', info);
  3814. (function(voteA){if(voteA)
  3815. voteA.addEventListener('click',function(){ //место события "проверка оценок"
  3816. if(!$q('canvas', this))
  3817. win.setTimeout(function(){evtChangeDom(voteA);}, 2499);
  3818. }, !1);})(voting);
  3819. //'chkVote'.wcl(win.habrPercentageRing , !info.querySelector('.voting').querySelector('canvas'))
  3820. if(hS.noPodcast.val || hS.noAuthor.val || hS.noContent.val || hS.noSmart.val || hS.noEvent.val){ //свернуть подкасты, фильтр по авторам, по содержимому
  3821. if(hS.noAuthor.val){
  3822. var aAut = hS.listNoAuthor.val.split(',');
  3823. for(var j =0, aL = aAut.length; j < aL; j++)
  3824. if(aAut[j].replace(/(^ *| *$)/g,'') == autName) break;
  3825. var isToHide = (j!=aL);
  3826. }
  3827. if(hS.noContent.val || hS.noSmart.val){ //"контент" - это заголовок, хабы и текст
  3828. var aAut = hS.noContent.val ? hS.listNoContent.val.split(',') : [];
  3829. if(hS.noSmart.val){
  3830. aAut = aAut.concat(hS.defa.listNoSmart.replace(/([^,]),(?!,)/g,'$1@@').replace(/,,/g,',').split('@@') )
  3831. if(!(hS.listNoSmart.val.split(',').length ==1 && hS.listNoSmart.val.split(',')[0]==''))
  3832. aAut = aAut.concat(hS.listNoSmart.val.replace(/([^,]),(?!,)/g,'$1@@').replace(/,,/g,',').split('@@') );
  3833. }
  3834. var topicTitleI = topicTitle && topicTitle.innerHTML.replace(/<.*?>/g,'');
  3835. var aHubs =[], s =!1;
  3836. for(var j in hubs) //проверка набора хабов на включение строк
  3837. if(hubs[j].parentNode) aHubs[j] = hubs[j].innerHTML;
  3838. for(var j =0, aL = aAut.length, j0 = aL; j < aL; j++){
  3839. var r = RegExp(aAut[j],'im');
  3840. for(var kk=0, aHL = aHubs.length; kk < aHL; kk++)
  3841. s = s || r.test(aHubs[kk]);
  3842. if(r.test(topicTitleI) || s || r.test(content && content.innerHTML)){ //найден фильтр
  3843. var o = document.createElement('SPAN');
  3844. o.innerHTML = '<i style="color:#aaa">/</i>'+ aAut[j] +'<i style="color:#aaa">/i</i>';
  3845. o.title ='стоп-строка (рег. выражение)';
  3846. info.appendChild(o);
  3847. var j0 = j;
  3848. }
  3849. }
  3850. isToHide = isToHide || j0 != aL;
  3851. //'isToHide'.wcl(j, topicTitleI, isToHide)
  3852. }
  3853. //'noContent'.wcl(isToHide, hubs)
  3854. if(hS.noPodcast.val && content || isToHide){
  3855. var isPodcast = /подкаст/i.test(topicTitle.innerHTML); //обнаружение подкаста
  3856. if(isPodcast || isToHide){
  3857. content.style.display ='none';
  3858. var ifrPres = $q('iframe', content);
  3859. if(ifrPres){
  3860. if(!isChrome)
  3861. ifrPres.style.display ='none';
  3862. else{
  3863. ifrPres.style.position ='absolute'; //баг хрома
  3864. ifrPres.style.left ='-999px';}
  3865. }
  3866. var tags = next('tags', content);
  3867. if(tags)
  3868. tags.style.display ='none';
  3869. }
  3870. }
  3871. if(hS.noEvent.val && /event/.test(topic.className) && topicTitle){
  3872. topic.style.display ='none';
  3873. datesShorten($e({cl:'eventLine', cs:{marginLeft:'3px'}, ht:'<a href="'+ topicTitle.href +'" target="_blank">ev <span class="eventHid">'+ $q('span', topicTitle).innerHTML +'</span></a> <i class="date">&mdash; '+ $q('.date', topic).getAttribute('title').replace(/^0(\d)/,'&nbsp;$1') +'</i>', bef: topic}), '.date');
  3874. }
  3875. isToHide =0;
  3876. }
  3877. if(published && info){
  3878. $e({clone: published, cs:{cssFloat:'none',display:'inline-block'}, apT: info}); //дубль дат
  3879. }
  3880. //=== точка "каждая аннотация" ===
  3881. byTextNodes(topic, haReplace);
  3882. var aut = $q('.author', topic) //округление рейтинга
  3883. ,rating = aut && $q('.rating', aut);
  3884. if(rating)
  3885. rating.innerHTML = Math.round(parseFloat(rating.innerHTML.replace(/,/,'.').replace(/–/,'-') ));
  3886. if(content) //обработчики контента (вызов событием)
  3887. if(win.opera || /Firefox\/[345]\./.test(navigator.userAgent)){
  3888. if(win.addKarmEvent) //показ кармы, если установлен HabraKarmaView.user.js
  3889. win.addKarmEvent(content);
  3890. if(win.habrPercentageRing)
  3891. win.habrPercentageRing(content);
  3892. }else
  3893. evtChangeDom(content); //CustomEvent в блоке
  3894. extLinks(content); //внешние ссылки в подгруженном
  3895. showSourceLang(content); //показ языка кодов в подгруженном
  3896. }
  3897. if(hS.strongCut.val){ //перенос изображений вверх после их загрузки
  3898. var sCutI =0, sCutWw;
  3899. sCutWw = win.setTimeout(function(){
  3900. var imgsUp = function(topic){ //==подъём висящих рисунков==
  3901. var imgs = $qA('img:not(._noAddOwnView)', topic)
  3902. ,prevImg =0;
  3903. for(var j =0, iL = imgs.length; j < iL; j++){ //по картинкам в аннотации
  3904. var img = imgs[j];
  3905. if(img.offsetHeight ==0)
  3906. noAllImgLoaded =1;
  3907. if(img.offsetHeight && (!img.getAttribute('viewed') || img.getAttribute('viewed')==1) && (
  3908. img.offsetTop - topic.offsetTop >= strongCutImgMinH
  3909. || img.offsetHeight + img.offsetTop - topic.offsetTop > tT + 20
  3910. && img.offsetTop - topic.offsetTop >5)){
  3911. var pCut = parentsPrev(' powerCut$', img)
  3912. ,nu = Number(img.getAttribute('number') || j)
  3913. ,c = $e({el:'SPAN' //метка рисунка
  3914. ,cl:'strongCutImgPlace'
  3915. ,ht:'рис.'+ (nu+1)
  3916. ,cs: img.align=='left'|| img.align=='center'|| img.align=='middle'
  3917. ? {cssFloat:'left', margin:'-4px 4px -1px -2px'}
  3918. : {}
  3919. }),
  3920. prevImg0 = parentsPrev(' powerCut$', img).prev;
  3921. if(prevImg0.tagName =='A'){ //перекрашивание метки рисунка, если ссылка
  3922. var a = document.createElement('A');
  3923. a.href = prevImg0.href;
  3924. a.appendChild(c);
  3925. c.style.background ='#9ce';
  3926. c.style.color ='#148';
  3927. c = a;
  3928. }
  3929. if(pCut.prev && pCut.prev.nextSibling){ //вставка метки рисунка
  3930. pCut.insertBefore(c, pCut.prev.nextSibling);
  3931. if(pCut.prev.nextSibling.nextSibling && pCut.prev.nextSibling.nextSibling.tagName=='BR') //удаление лишних BR
  3932. pCut.removeChild(pCut.prev.nextSibling.nextSibling);
  3933. }else
  3934. pCut.appendChild(c);
  3935. var movedHid = prevImg0 && prevImg0.tagName=='IMG' && prevImg0.previousSibling && prevImg0.previousSibling.className =='de-img-hid' && prevImg0.previousSibling; //привязанный к IMG блок для просмотра
  3936. //'movedHid'.wcl(movedHid, prevImg0, prevImg0.previousSibling && prevImg0.previousSibling.tagName)
  3937. if(prevImg0 && pCut && prevImg && prevImg.nextSibling) //поднятие рисунка
  3938. pCut.insertBefore(prevImg0, prevImg.nextSibling);
  3939. else
  3940. pCut.insertBefore(prevImg0, pCut.childNodes[0]);
  3941. if(movedHid) //совместный перенос блока с IMG
  3942. pCut.insertBefore(movedHid, prevImg0);
  3943. img.title = 'рис.'+(nu+1) +' '+ (img.title ||'');
  3944. img.setAttribute('viewed','upped');
  3945. }else{
  3946. if(img.getAttribute('viewed')!='upped')
  3947. img.setAttribute('viewed',1);
  3948. var f2 = function(topic){
  3949. //'22loaded'.wcl(topic);
  3950. return function(){imgsUp(topic);};
  3951. }
  3952. img.addEventListener('load',new f2(topic) ,!1);
  3953. }
  3954. if(!img.getAttribute('number'))
  3955. img.setAttribute('number',j);
  3956. prevImg = prevImg0;
  3957. }
  3958. };
  3959. var topics = $qA('.powerCut')
  3960. ,tO = strongCutImgMinH *2 +4
  3961. ,noAllImgLoaded =0;
  3962. for(var i =0; i < topics.length; i++){
  3963. var topic = topics[i]
  3964. ,ifrs = $qA('iframe[src*="youtube.com/"]', topic);
  3965. if(ifrs.length){
  3966. for(var j=0; j < ifrs.length; j++){
  3967. var ifr = ifrs[j]
  3968. ,srcCode = ifr.getAttribute('src').match(/\/([\w-]*)($|\?)/);
  3969. if(srcCode.length >1){
  3970. srcCode = 'http://i3.ytimg.com/vi/'+ srcCode[1] +(strongCutImgMinH <=120?'/default.jpg':'/sddefault.jpg');
  3971. if(!isChrome)
  3972. ifr.style.display ='none'; //обход бага
  3973. else{
  3974. ifr.style.position ='absolute';
  3975. ifr.style.left ='-999px';}
  3976. $e({el:'IMG' //превью-картинка ютуба
  3977. ,cl:'youtub'
  3978. ,at:{src: srcCode, title:'=youtube=', align:'center'}
  3979. ,apT: $e({el:'A'
  3980. ,at:{href:ifr.getAttribute('src').replace(/embed\//,'watch?v='), target:'_blank'}
  3981. ,bef: ifr}) });
  3982. }
  3983. }
  3984. //youtube.com/watch?v=jq_WaOLjdyQ http://www.youtube.com/embed/jq_WaOLjdyQ
  3985. //i3.ytimg.com/vi/jq_WaOLjdyQ/hqdefault.jpg // /default - 120x90
  3986. }else{
  3987. ifr = $q('object[data*="vimeo.com/"]', topic);
  3988. if(ifr){
  3989. ifr.setAttribute('width', Math.floor(ifr.getAttribute('width')/2) );
  3990. ifr.setAttribute('height', Math.floor(ifr.getAttribute('height')/2) );
  3991. ifr.style.cssFloat ='left';
  3992. ifr.style.marginRight ='6px';
  3993. if(ifr.nextSibling && ifr.nextSibling.tagName=='BR')
  3994. ifr.parentNode.removeChild(ifr.nextSibling);
  3995. }
  3996. }
  3997. $e({cl:'prevLastInAnno'
  3998. ,bef: $q('div.clear', topic) }); //индикатор висящих рис.
  3999. var tT = $q('.prevLastInAnno', topic).offsetTop - topic.offsetTop;
  4000. imgsUp(topic); //подъём висящих рисунков
  4001. var koefPress =1.14; //коэффициент для сжатия интерлиньяжа (захват 2 строк)
  4002. (function(topic2, j){win.setTimeout(function(){
  4003. var tS = topic2.scrollHeight
  4004. ,p = document.createElement('DIV')
  4005. ,tT = $q('.prevLastInAnno', topic2).offsetTop - topic2.offsetTop;
  4006. //'sett-topic2'.wcl(topic2, (+new Date())-j, tO, tT, tS, tT >= tO && tT < tO *koefPress && tS < tO *koefPress, tS - tT);
  4007. if(tT >= tO && tT < tO *koefPress && tS < tO *koefPress){
  4008. p.className ='content powerCut'; //дополнительное сжатие по высоте на 10%
  4009. topic2.className ='pressed';
  4010. topic2.parentNode.insertBefore(p, topic2.nextSibling);
  4011. p.appendChild(topic2);
  4012. }
  4013. imgsUp(topic2); //(повторный) подъём висящих рисунков
  4014. },600);})(topic, +new Date()); //TODO делать по onload рисунков
  4015. }
  4016. if(++sCutI <1 && !noAllImgLoaded) win.setTimeout(arguments.callee, 499 + sCutI *400);
  4017. },499);
  4018. }
  4019. //=== Подмесы - добавление в список аннотаций/поиска аналогичного списка других заявленных в настр. сайтов===
  4020. for(var i in HRs){ //на каком сайте находимся?
  4021. if(RegExp(location.host).test(HRs[i])){
  4022. var siteCurrent = i; break;}}
  4023. //additinal mixins
  4024. var addMixes =[]; //сайты, из которых надо подмешать списки
  4025. for(var i in hS)
  4026. for(var j in HRs)
  4027. if(hS[i].val && i == j)
  4028. addMixes.push({i: j, site: HRs[j]});
  4029. 'addMixes'.wcl(addMixes, hS.ha.val, hS.geek.val, hS.manag.val);
  4030. /*for(var i in addMixes){
  4031. var aI = addMixes[i]
  4032. , mixUrl = aI.site + location.pathname;
  4033. //TODO сверять авторизованность
  4034. var xhr = new window.XMLHttpRequest();
  4035. xhr.open('GET', mixUrl.replace(/_/g, '%5F'), true); //странно, но "_" не переваривает (FF)
  4036. xhr.setRequestHeader('Origin', aI.site);
  4037. xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
  4038. xhr.send(null);
  4039. xhr.onreadystatechange = function(){ //===показ статьи===
  4040. if(this.readyState !=4) return;
  4041. var conte = this.responseText.match( // ====== парсинг страницы, шаблон ======
  4042. /<div class="content html_format">([\s\S]*?)<div class="clear"><\/div>\s+?<\/div>[\s\S]+?(<ul class="tags">|<div class="tags">)\s*([\s\S]*?)\s*(<\/div>|<\/ul>)[\s\S]*?<div class="infopanel/m); //вся статья (до тегов или подписи)
  4043. 'conte'.wcl(conte);
  4044. }
  4045. }*/
  4046. //TODO делать фрейм, монодоменный запрос и пронос результата через стенку фрейма (для всех доменов в addMixes)
  4047. }
  4048. var rotPosts = $q('.rotated_posts .rotTRow');
  4049. if(rotPosts){ //обработка ===== нижних 3 ссылок =====
  4050. var rPostA = $qA('a.grey', rotPosts);
  4051. //'rPost'.wcl(rPostA)
  4052. for(var i in rPostA){ var rPAI = rPostA[i]; if(rPAI.attributes){
  4053. rPAI.innerHTML = '<span>'+ rPAI.innerHTML +'</span> ';
  4054. $e({el:'span'
  4055. ,cl:'showComm btnBack inln'
  4056. ,ht:'&rarr;'
  4057. ,at:{title:'подгрузить статью с комментариями'}
  4058. ,on:{click: showContent} //показ статьи или комментариев
  4059. ,apT: rPAI }); //кнопка справа от ката
  4060. //'rPAI'.wcl(rPAI.innerHTML);
  4061. }}
  4062. }
  4063. //===== далее - простая одиночная страница с комментариями =======
  4064.  
  4065. var lukes = $qA('.i-am-your-father-luke'); //добавление подписей к Вн.Голосу
  4066. if(lukes && lukes.length){
  4067. var o = document.createElement('DIV');
  4068. o.className ='post';
  4069. o.innerHTML ='<div class="infopanel">(это сообщение в формате "<a style="color:#888" target="_blank" href="'+HRU+'/info/help/tools/" title="описание на странице помощи">Внутренний Голос ⇗</a>" от лидера рейтинга пользователей или администрации)</div>';
  4070. for(var i in lukes){ //скрытие ненужных шаринг-кнопок
  4071. var lui = lukes[i];
  4072. if(lui.parentNode)
  4073. lui.appendChild(o);
  4074. }
  4075. }
  4076. var hsh ={noTwit:'twitter', noVk:'vkontakte', noFb:'facebook', noGP:'googleplus'};
  4077. for(var i in hsh){ if(hS[i].val){ //скрытие ненужных шаринг-кнопок
  4078. var shars = $qA('.infopanel .'+ hsh[i]);
  4079. if(shars && shars.length)
  4080. for(var j in shars)
  4081. if(shars[j].style)
  4082. shars[j].style.display ='none';
  4083. }}
  4084. if(hS.shortDates.val) //укорочение дат
  4085. datesShorten(document,'.post .published, .conversation_page .messages .info .time');
  4086. if(comments && comments.length){
  4087. correctCommentsAfter(comments[0], document.body); //==== обработка комментариев ====
  4088. var topic = $q('.post')
  4089. ,panel = $q('.infopanel')
  4090. ,date = topic && $q('.published', topic)
  4091. ,author = panel && $q('.author', panel)
  4092. ,issue = panel && $q('.original-author', panel)
  4093. ,topicTitle = topic && $q('.title', topic)
  4094. ,doubleDataAuthor = document.createElement('SPAN')
  4095. ,voting = panel && $q('.voting', panel)
  4096. ,voteRO = voting && $q('.plus', voting)
  4097. ,isRO = voteRO && /read-only/i.test(voteRO.title);
  4098. //=== точка "одна статья" ===
  4099. byTextNodes(topic, haReplace); // обработка слов статьи (без комментариев)
  4100. extLinks($q('.content', topic));
  4101. extLinks($q('.original-author', topic));
  4102. (function(voteA){if(voteA)
  4103. voteA.addEventListener('click',function(){ //место события "проверка оценок"
  4104. if(!$q('canvas', this))
  4105. win.setTimeout(function(){evtChangeDom(voteA);}, 2999);
  4106. }, !1);})(voting);
  4107. doubleDataAuthor.className ='dblAuthor'; //дублирование даты-автора вверху
  4108. if(date){
  4109. doubleDataAuthor.appendChild($e({clone: date, cs:{display:'inline'} }) );
  4110. $e({el: date
  4111. ,aft: !issue && author ? author : issue && author ? issue : $q('.share', panel) });
  4112. }
  4113. if(author){
  4114. var rating = $q('.rating', author);
  4115. if(rating)
  4116. rating.innerHTML = Math.round(parseFloat(rating.innerHTML.replace(/,/,'.').replace(/–/,'-') ));
  4117. doubleDataAuthor.appendChild(document.createTextNode(' — '));
  4118. doubleDataAuthor.appendChild($e({clone: author, cs:{display:'inline'} }) );
  4119. }
  4120. if(issue){
  4121. $q('a', issue).style.color ='#a33';
  4122. /*issue.querySelector('a').setAttribute('target','_blank'); //ссылка в новое окно*/
  4123. doubleDataAuthor.appendChild(document.createTextNode('; '));
  4124. doubleDataAuthor.appendChild($e({clone: issue, cs:{display:'inline'} }) );
  4125. }
  4126. doubleDataAuthor.style.cssFloat ='right';
  4127. doubleDataAuthor.style.marginLeft ='-100%';
  4128. doubleDataAuthor.style.position ='relative';
  4129. doubleDataAuthor.style.top ='-1.1em';
  4130. topicTitle && topicTitle.parentNode.insertBefore(doubleDataAuthor, topicTitle);
  4131. var lnkA = topic && $qA('.dblAuthor a', topic);
  4132. if(lnkA)
  4133. for(var i =0, lA = lnkA.length; i < lA; i++){
  4134. lnkA[i].style.color = i <1 ?'#cf0000':'#a33';
  4135. lnkA[i].style.textDecoration ='none';
  4136. if(i ==1) lnkA[i].setAttribute('target','_blank'); //ссылка в новое окно
  4137. }
  4138. var topicTitleSpan = topicTitle && $q('span.post_title', topicTitle)
  4139. ,author = topic && $q('.author a', topic)
  4140. ,autName = topic && author && $q('.author a', topic).innerHTML
  4141. ,hubs = topic && $qA('.hubs >.hub', topic);
  4142. //'lNAV'.wcl(autName, topicHaCut, topicTitle, hubs)
  4143. if(hS.colorTopic.val && topicTitle && hubs){
  4144. for(var j in hubs) if(hubs[j].innerHTML =='Переводы'){
  4145. topicTitleSpan.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  4146. break;
  4147. }
  4148. if(topic && / translation/.test(topic.className) && topicTitleSpan){
  4149. topicTitleSpan.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  4150. topicTitleSpan.style.paddingRight ='8px';
  4151. }
  4152. var lNAV = hS.listNewsAuthors.val
  4153. ,topicHaCut = $q('a[name="habracut"]', topic);
  4154. for(var j in lNAV) if(autName == lNAV[j] || !topicHaCut){
  4155. topicTitleSpan.style.backgroundColor ='#fafdf2'; //новость (жёлтый)#f2f6e8
  4156. $e({cl:'recov1'
  4157. ,cs:{marginLeft:'8px'}
  4158. ,at:{title:'новость'}
  4159. ,ht:'<div class="recov2"></div><div class="recov3">н</div>н'
  4160. ,aft: topicTitleSpan
  4161. });
  4162. break;
  4163. }
  4164. if(topic && / link/.test(topic.className) && topicTitleSpan){
  4165. topicTitleSpan.style.backgroundColor ='#f0faf4'; //топик-ссылка (зеленоватый)
  4166. topicTitleSpan.style.backgroundImage ='url(http://456)';
  4167. topicTitleSpan.style.paddingRight ='8px';
  4168. }
  4169. }
  4170. if(isRO){ //скрыть стрелки оцениваний для read-only
  4171. var votes = $qA('.comments_list .info .voting a');
  4172. if(votes) for(var i in votes) if(votes[i].attributes)
  4173. votes[i].style.display ='none';
  4174. }
  4175. }
  4176. var fileBase64Post = function(){
  4177. var dataURL = this.canvas.toDataURL(this.getImageType()) // grab the snapshot as base64
  4178. ,imgData = atob(dataURL.substring(13 + this.getImageType().length)) // convert to binary
  4179. ,filenameTimestamp = (new Date().getTime())
  4180. ,separator = '----------12345-multipart-boundary-' + filenameTimestamp;
  4181. // Javascript munges binary data when it undergoes string operations (such as concatenation), so we need
  4182. // to jump through a bunch of hoops with streams to make sure that doesn't happen
  4183. // Create a string input stream with the form preamble
  4184. var prefixStringInputStream = Components.classes['@mozilla.org/io/string-input-stream;1']
  4185. .createInstance(Components.interfaces.nsIStringInputStream);
  4186. var formData ='--'+ separator +'\\r\\nContent-Disposition: form-data; name="data"; filename="snapshot_'
  4187. + filenameTimestamp + (this.getImageType() =='image/jpeg'?'.jpg':'.png') +'"\\r\\nContent-Type: '
  4188. + this.getImageType() +'\\r\\n\\r\\n';
  4189. prefixStringInputStream.setData(formData, formData.length);
  4190. // write the image data via a binary output stream, to a storage stream
  4191. var binaryOutputStream = Components.classes['@mozilla.org/binaryoutputstream;1']
  4192. .createInstance(Components.interfaces.nsIBinaryOutputStream);
  4193. var storageStream = Components.classes['@mozilla.org/storagestream;1']
  4194. .createInstance(Components.interfaces.nsIStorageStream);
  4195. storageStream.init(4096, imgData.length, null);
  4196. binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
  4197. binaryOutputStream.writeBytes(imgData, imgData.length);
  4198. binaryOutputStream.close();
  4199. // write out the rest of the form to another string input stream
  4200. var suffixStringInputStream = Components.classes['@mozilla.org/io/string-input-stream;1']
  4201. .createInstance(Components.interfaces.nsIStringInputStream);
  4202. formData ='\\r\\n--'+ separator +'\\r\\nContent-Disposition: form-data; name="description"\\r\\n\\r\\n'
  4203. + description +'\\r\\n--'+ separator +'--\\r\\n';
  4204. suffixStringInputStream.setData(formData, formData.length);
  4205.  
  4206. // multiplex the streams together
  4207. var multiStream = Components.classes['@mozilla.org/io/multiplex-input-stream;1']
  4208. .createInstance(Components.interfaces.nsIMultiplexInputStream);
  4209. multiStream.appendStream(prefixStringInputStream);
  4210. multiStream.appendStream(storageStream.newInputStream(0));
  4211. multiStream.appendStream(suffixStringInputStream);
  4212.  
  4213. // post it
  4214. req.open('POST','http://yoursite.com/upload_endpoint', true);
  4215. req.setRequestHeader('Accept','*/*, application/xml');
  4216. req.setRequestHeader('Content-type','multipart/form-data; boundary='+ separator);
  4217. req.setRequestHeader('Content-length', multiStream.available());
  4218. req.setRequestHeader('Authorization','Basic '+ btoa(username +':'+ password));
  4219. req.setRequestHeader('User-Agent','YourUserAgent/1.0.0');
  4220. req.send(multiStream);
  4221. };
  4222. /*
  4223. var addAdReq = new XMLHttpRequest();
  4224. addAdReq.open('POST', postAdUrl, false);
  4225. addAdReq.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary);
  4226. var stringStream = Components.classes["@mozilla.org/io/string-input-stream;1"].createInstance(Components.interfaces.nsIStringInputStream);
  4227. var data = "";
  4228. data += boundary;
  4229. data += "\r\n";
  4230. data += 'Content-Disposition: form-data; name="category_id"\r\n\r\n';
  4231. data += categoryId;
  4232. data += "\r\n";
  4233. data += boundary;
  4234. data += "\r\n";
  4235. .......[и т.д.].......
  4236. data += boundary;
  4237. data += "--\r\n";
  4238. stringStream.setData(data, data.length);
  4239. addAdReq.send(stringStream);//в хедере строка boundary должна содержать на два символа '-' меньше чем в остальных случаях.
  4240.  
  4241. http://igstan.ro/posts/2009-01-11-ajax-file-upload-with-pure-javascript.html */
  4242.  
  4243. var fPanel = $q('form .panel')
  4244. ,formTA;
  4245. if(fPanel)
  4246. for(formTA = fPanel; formTA !=null && !/form/i.test(formTA.tagName); formTA = formTA.parentNode);
  4247. if((comments && comments.length || $q('#post_form') )&& !isRO && h.uName && typeof window.FileReader !=u){
  4248. $e({cl:'habrAjaxInfo droppedF for_authors'
  4249. ,cs:{paddingLeft:'14px'}
  4250. ,ht:'<div style="display:inline-block"><div style="float:left; width:22px; height:12px;"><div class=hAjaxLogo style="float:none; width:32px; top:-15px; left:-12px;border-radius: 5px;'+ (isHLogo ? 'background-image:url('+ metaD.icon +')':'height:auto') +'"></div></div>'
  4251. +'<div class=hoverView style=float:right;padding-bottom:0.2em>(?)</div><div class="hoverView hovered" style=margin-top:1.3em>'
  4252. +'разместить на <a href='+HSO+' target=_blank>habrastorage.org</a>; Макс. ширина без ужатия - 1920'
  4253. +'</div>'
  4254. +'<button>Публиковать</button>'
  4255. +'<div class=fileName>abcde.png</div>'
  4256. +'<div class=imgDimens>1234567 <span style=font-variant:small-caps>б.</span></div>'
  4257. +'<button class=previ>пре-<br>вью</button><button class="previ previCancel" style=float:right title=отмена>X</button>'
  4258. +'<input id=resizeWidth placeholder=1028 title="ресайз до ширины" /><br>'
  4259. +'<input id=resizeHeight placeholder=2006 title="ресайз до высоты" /></div>'
  4260. +''
  4261. ,apT: $e({cs:{position:'relative', height:0}
  4262. ,apT: sidebar})
  4263. });
  4264. $e({cl:'habrAjaxInfo pixList for_authors'
  4265. ,cs:{paddingLeft:'14px'}
  4266. ,ht:'<div style="float:left; width:22px; height:12px;"><div class=hAjaxLogo style="float:none; width:32px; top:-15px; left:-12px;border-radius: 5px;'+ (isHLogo ? 'background-image:url('+ metaD.icon +')':'height:auto') +'"></div></div>'
  4267. +' затащите файл&nbsp;картинки&nbsp;<div class=hoverView>(?)<div class=hovered>'
  4268. +'сюда или в поле ввода комментария (статьи, вопроса, ответа, письма), чтобы разместить на <a href='+HSO+' target=_blank>habrastorage.org</a> (тег появится под курсором).'
  4269. +'<div>Макс. ширина - 1920 без ужатия</div>'
  4270. +'</div></div><br>'
  4271. +' &nbsp; <a href=#>последние</a> (NN),<br>'
  4272. +'&nbsp; <a href=#>избранные</a> (N),<br>'
  4273. +'&nbsp; <a href=#>удалённые</a> (NNN).<br>'
  4274. ,apT: sidebar
  4275. });
  4276. if(formTA){
  4277. var preImgSend = $e({cl:'preImgSend habrAjaxInfo'
  4278. ,ht:'<div class=radios style="position:relative;"><div class=radios2 style="position:absolute;bottom:3px;"><input type=radio name=r1 id=r1n1 /><label for=r1n1>слева</label><input type=radio name=r1 id=r1n2 /><label for=r1n2>по центру</label><input type=radio name=r1 id=r1n3 /><label for=r1n3>справа /</label><input class=rAll type=radio name=r1 id=r1n4 /><label for=r1n4 class=rAll>в строке</label></div></div>'
  4279. +'<button class="previ previCancel" style="float:right; width:7%; height:3.9em" title=отмена>X</button>'
  4280. +'<div class=hoverView style="float:right; text-align:center">'
  4281. +'<div class=imgDimens><span class=weight>-1</span> <span style=font-variant:small-caps>б.</span></div>'
  4282. +'<input id=resizeWidth2 placeholder=width title="ресайз до ширины" /><br>'
  4283. +'<input id=resizeHeight2 placeholder=height title="ресайз до высоты" />'
  4284. +'</div><div class=imgPrevi style="position:relative;float:right;width:94px; height:4.2em">'
  4285. +'<div class=fit style="position:absolute;bottom:0;width:94px; height:94px; border:1px solid #ddd; background:#F0F0F0"></div>'
  4286. +'</div>'
  4287. +'</div><div class=imgPrevi style="position:relative;float:right;width:94px; height:4.2em">'
  4288. +'<div class=centered style="position:absolute;bottom:0;width:94px; height:94px; border:1px solid #ddd; background:#F0F6F0"></div>'
  4289. +'</div>'
  4290. +'<div class=overUrl><div class=imgDate></div><input id=aUrl placeholder=URL title="ссылка на рисунке" style="margin-left:-11px; text-align:left"/></div>'
  4291. +'<span class=overName><span class=fileName>(имя файла)</span> . <img src=/images/favorite.gif style=width:150px;height:1px /></span>'
  4292. +'<a href="#.jpg" class="aPrevi imgL"><button class=previ style="width:10%" title="в плавающем блоке">пре-<br>вью</button></a>'
  4293. +'<button class=publish style="width:30%;height:2.6em" title="центровка по радиокнопкам или Shift/Ctrl+Shift/Ctrl">Публиковать</button>'
  4294. ,bef: fPanel
  4295. });
  4296. }
  4297. var fileDrop3 = $q('#text_textarea')||$q('#comment_text')
  4298. ,centPrevi = $q('.imgPrevi .centered'), fitPrevi = $q('.imgPrevi .fit');
  4299. if(fileDrop3){
  4300. $e({
  4301. el: fileDrop3
  4302. ,on:{
  4303. dragover: function(ev){'dragover0'.wcl();this.classList.add('hover'); $pdsp(ev);}
  4304. ,dragend: function(){'dragend0'.wcl();this.className =''; return!1;}
  4305. ,drop: function(ev){
  4306. this.classList.remove('hover');
  4307. $pdsp(ev);
  4308. var file = ev.dataTransfer.files[0]
  4309. ,reader = new FileReader();
  4310. reader.onload = function(ev){
  4311. 'fileDrop3-target'.wcl(ev.target);
  4312. preImgSend.style.display ='block';
  4313. fileDrop3.style.background = centPrevi.style.background = fitPrevi.style.background ='url('+ ev.target.result +') no-repeat center';
  4314. centPrevi.style.backgroundColor ='#F0F6F0';
  4315. fitPrevi.style.backgroundSize ='contain';
  4316. fitPrevi.style.backgroundColor ='#F0F0F0';
  4317. var resu = ev.target.result;
  4318. handlImgViews(preImgSend,'.aPrevi.imgL');
  4319. var previLink = $q('.aPrevi img', preImgSend)
  4320. previLink &&(previLink.src = resu);
  4321. win.addEventListener('loadImg',function(){
  4322. var dimS = previLink.title.match(/(\d+)x(\d+)$/);
  4323. if(dimS){
  4324. dimS = dimS.slice(1);
  4325. $q('#resizeWidth2', preImgSend).setAttribute('placeholder',dimS[0]);
  4326. $q('#resizeHeight2', preImgSend).setAttribute('placeholder',dimS[1]);
  4327. }},!1);
  4328. $q('.imgDimens .weight',preImgSend).innerHTML = file.size;
  4329. $q('.fileName',preImgSend).innerHTML = file.name;
  4330. var fD = new Date(file.lastModifiedDate);
  4331. $q('.imgDate',preImgSend).innerHTML = fD.getFullYear()
  4332. +'-'+ (fD.getMonth()+1<=9?'0':'') +(fD.getMonth()+1)
  4333. +'-'+(fD.getDate()<=9?'0':'')+ fD.getDate()
  4334. +','+ getDay([0,fD.getDate(),0,fD.getFullYear()], fD.getMonth())
  4335. +' '+ (fD.getHours()<=9?'0':'') + getHourMins(fD)+
  4336. ':'+(fD.getSeconds()<=9?'0':'')+fD.getSeconds();
  4337. };
  4338. var formData = new FormData();
  4339. formData.append('Filedata', file);
  4340. 'fileDrop3-file'.wcl(file.size, file.lastModifiedDate, file.mozFullPath, formData);
  4341. reader.readAsDataURL(file);
  4342. return!1;
  4343. }
  4344. }
  4345. });
  4346. $e({el:'.aPrevi.imgL button', blck: preImgSend
  4347. ,on:{click:function(ev){
  4348. var img = this.parentNode.previousSibling.firstChild
  4349. dimS = img.title.match(/(\d+)x(\d+)$/);
  4350. dimS && addFullImg(img, dimS.slice(1));
  4351. $pdsp(ev);
  4352. return!1}
  4353. } });
  4354. $e({el:'.previCancel', blck: preImgSend
  4355. ,on:{click:function(ev){
  4356. fileDrop3.style.backgroundImage ='none';
  4357. preImgSend.style.display ='none';
  4358. $pdsp(ev);
  4359. }} });
  4360. $e({el:'.publish', blck: preImgSend
  4361. ,on:{click:function(ev){
  4362. openInFrame({clientY: ev.clientY}, {href:HSO+'/'});
  4363. $pdsp(ev);
  4364. }} });
  4365. }
  4366. }
  4367. var menuA = $qA('.main_menu a');
  4368. if(menuA.length ==0)
  4369. menuA = [$q('#navbar .tab_menu .g-icon-burger')];
  4370. menuA && menuA[0] && $e({el: menuA[0]
  4371. ,cl:'date'
  4372. ,at:{title: menuA.length ==1 ?'Разделы':'лента'+(hS.postsLinkNew.val ?'-все-новое':'')}
  4373. ,ht: getHourMins().replace(/(\d\d):/,'$1') +'<br>'+ getDay([0,NOWdate.getDate(),0,NOWdate.getFullYear()], NOWdate.getMonth())});
  4374. $e({el: $q('#navbar .tab_menu')
  4375. ,on:{click: function(){
  4376. var menuTab = $q('#menu_tab')
  4377. ,el = $q('.global_search_form input', menuTab);
  4378. 'menuTab'.wcl(menuTab && /hidden/.test(menuTab.className) && el)
  4379. menuTab && /hidden/.test(menuTab.className) && el && setTimeout(function(){el.focus();},199);}} });
  4380. if(menuA && menuA[0] && hS.postsLinkNew.val || hS.allFeed.val){
  4381. if(menuA[0].href)
  4382. menuA[0].href = ROOT + (/(\/feed\/)/.test(menuA[0].href) ?'/feed/'
  4383. + (hS.allFeed.val ?'/posts/':''): (h.uName ?'':'/posts') + (hS.allFeed.val && hS.postsLinkNew.val ?'/corporative/':'/collective/') );
  4384. if(hS.postsLinkNew.val && menuA[0].href)
  4385. menuA[0].href +='new/'; //ссылки 'Лента", "Посты" - на "новые"
  4386. }
  4387. if(comments && comments.length || fPanel )
  4388. addTaButtons(comments[0] || formTA ); //добавление кнопок над полем ввода
  4389. h.uName2 = $q('.user_header .username') || h.uName; //выбор чужого юзера с приоритетом
  4390. h.uName2 = h.uName2 && h.uName2.innerHTML;
  4391. authorClicks(document); //обраб-к кликов на авторах, избранном, настройках, авторизации
  4392. authorClicks($q('#search_form input[type="submit"][value=""]')); //на кнопке поиска
  4393. handlImgViews(document); //показ увеличенных картинок
  4394.  
  4395. if(inFrame){ //удаление персонального меню в фрейме
  4396. var footer = $q('#footer');
  4397. if(footer) footer.style.display ='none';
  4398. var panelPers = $q('#header .userpanel');
  4399. if(panelPers){
  4400. panelPers.style.display ='none';
  4401. $e({ //кнопка закрывания фрейма
  4402. cl:'closeButt'
  4403. ,ht: '<b style="padding:1px 3px; border:1px solid #bbc; border-bottom-left-radius: 4px; color:#bbc"'
  4404. +' onclick="try{top.location && (top.document.getElementById(&quot;hA_userinfoView&quot;).style.display=&quot;none&quot);}catch(er){alert(er)}">X</b>'
  4405. //document.activeElement.removeChild(document.activeElement.firstChild);
  4406. ,cs:{cssText:'position: fixed; z-index:2; right:0; top:2px; cursor:pointer'}
  4407. ,bef: panelPers.parentNode
  4408. });
  4409. }
  4410. }
  4411. if(win.commentForm)
  4412. win.commentForm.sendOnEnter = function(){}; //убрать отправку по Ctrl+Enter (устарело, но может работать в блогах компаний (?))
  4413. if(hS.innerTab.val){ // ====== вставка спецсимволов =======
  4414. var tArea = $qA('.editor textarea')
  4415. ,inTag = win.habraWYG && win.habraWYG.insertTag;
  4416. if(tArea.length && inTag)
  4417. for(var j in tArea){var taJ = tArea[j]; if(taJ.attributes){
  4418. $e({el: taJ, on:{keydown: function(ev){
  4419. var th = ev.target;
  4420. if(ev.shiftKey && ev.keyCode ==9){ //вставка таба по Shift-Tab
  4421. inTag(th,' ');
  4422. $pd(ev);
  4423. }
  4424. if(ev.ctrlKey && ev.keyCode ==32){ //вставка NBSP по Ctrl-Space
  4425. inTag(th,'&nbsp;');
  4426. $pd(ev);
  4427. }
  4428. }} });
  4429. }}}
  4430. if(hS.autoGrow.val){
  4431. var tAGrow = function(tA){ //авторост-обработчик
  4432. if(!tA) return;
  4433. var tSHPrev =0, tAInh, tATout
  4434. ,maxH = Math.floor(win.innerHeight *0.8)
  4435. ,tAF = function(ev){
  4436. if(tSHPrev < maxH && tAInh)
  4437. win.clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
  4438. var tSH = tA.scrollHeight - (isChrome||isFx?6:win.opera?2:6);
  4439. //'tA'.wcl(tSHPrev, tSH, ev.type, tA.offsetHeight);
  4440. if(win.opera){
  4441. tA.blur();
  4442. tA.style.height = 0;
  4443. tA.style.marginBottom = tSH +'px';
  4444. tSH = tA.scrollHeight -2;
  4445. tA.style.height = tSH +'px';
  4446. tA.style.marginBottom = 0;
  4447. tA.focus();
  4448. }
  4449. if(tSHPrev <= tSH && tSHPrev < maxH){
  4450. tA.style.height = tSH +'px';
  4451. if(tSHPrev < maxH && tAInh)
  4452. win.clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
  4453. }else if(!tAInh)
  4454. win.clearTimeout(tATout), tATout = win.setTimeout(function(){tA.style.overflow ='inherit'; tAInh =1}, 230);
  4455. tSHPrev = tSH;
  4456. };
  4457. tA.addEventListener('keypress',tAF,!1); //контроль за ростом блока данных
  4458. tA.addEventListener('keyup',tAF,!1);
  4459. tA.style.maxHeight = maxH +'px';
  4460. };
  4461. tAGrow($q('.editor #comment_text')||$q('.editor #text_textarea') );
  4462. tAGrow($q('.editor #text') );
  4463. }
  4464. $q('.inbox_page_write')&&($q('.inbox_page_write').className ='inbox_page_write2'); //разблок_ресайза поля ввода в почте
  4465. $q('.inbox_page_read')&&($q('.inbox_page_read').className ='inbox_page_read2');
  4466. if(hS.reformal.val && !inFrame){ // добавление виджета reformal.ru для отправки багрепортов (можно то же из настроек)
  4467. addJs(function reformal_preload(){
  4468. reformal_wdg_w = "713";
  4469. reformal_wdg_h = "460";
  4470. reformal_wdg_domain = "habrajax";
  4471. reformal_wdg_mode = 0;
  4472. reformal_wdg_title ='<a href="https://github.com/spmbt/haPages/tree/gh-pages" target="_blank">HabrAjax</a> - чтобы сайт стал удобным';
  4473. reformal_wdg_ltitle = "БАГИ";
  4474. reformal_wdg_lfont = "";
  4475. reformal_wdg_lsize = "";
  4476. reformal_wdg_color = "#269bd1";
  4477. reformal_wdg_bcolor = "#73859e";
  4478. reformal_wdg_tcolor = "#FFFFFF";
  4479. reformal_wdg_align = "right";
  4480. reformal_wdg_charset = "utf-8";
  4481. reformal_wdg_waction = 0;
  4482. reformal_wdg_vcolor = "#559ecf";
  4483. reformal_wdg_cmline = "#d3d8df";
  4484. reformal_wdg_glcolor = "#105895";
  4485. reformal_wdg_tbcolor = "#FFFFFF";
  4486. reformal_wdg_tcolor_aw4 = "#3F4543";
  4487. reformal_wdg_bimage = "cac7b640e87a20ba02df24d613d54a1d.png";
  4488. reformal_html ='';
  4489. document.write = function(a){reformal_html +=a;};//обход doc.write
  4490. });
  4491. addJs('http://reformal.ru/tabn2v4.js?charset=utf-8' //виджет reformal.ru и его постобработчик
  4492. ,hS.versionNumb
  4493. ,'MyOtziv'
  4494. ,function reformal_postload(){ //загрузка после doc.write и подгонка стилей, текстов
  4495. var elem = document.createElement('DIV');
  4496. elem.id ='reformal_holder';
  4497. elem.innerHTML = reformal_html;
  4498. document.body.insertBefore(elem, document.body.childNodes[0]);
  4499. document.getElementById('myotziv_box').style.zIndex = 3001;
  4500. var reformal_butt = document.querySelector('#reformal_holder .frgtd'); //кнопка открывания виджета, |.frby
  4501. reformal_butt.style.right='-4px';reformal_butt.style.width ='17px';
  4502. reformal_butt.querySelector('img').style.position='relative';
  4503. reformal_butt.querySelector('img').style.left='-4px';
  4504. reformal_butt.style.overflow ='hidden';
  4505. reformal_butt.querySelector('a').title ='Пожелания и баги HabrAjax';
  4506. reformal_butt.querySelector('a').style.marginBottom ='3em';
  4507. var reformal_closeButt = document.querySelector('#reformal_holder .pokusijy'); //кнопка закрытия
  4508. var reformal_goto = document.createElement('DIV');
  4509. reformal_goto.innerHTML ='<a href="http://habrajax.reformal.ru/" target="_blank">смотреть всё</a>';
  4510. reformal_closeButt.parentNode.insertBefore(reformal_goto, reformal_closeButt.nextSibling);
  4511. reformal_goto.style.cssFloat ='right';
  4512. reformal_goto.style.marginRight ='10px';
  4513. var reformal_foot1 = document.querySelector('#reformal_holder .drsdtf');
  4514. reformal_foot1.style.width ='auto';
  4515. var reformal_note1 = document.createElement('DIV');
  4516. reformal_note1.innerHTML ='<span title="скопируйте после клика" onclick="prompt(&quot;'+'скопируйте для сообщения&quot;, &quot;Браузер: '+ navigator.userAgent +'; ОС: '+ navigator.platform +'; HabrAjax v. (@)&quot;)">При баге пишите <u title="'+navigator.userAgent+'">браузер</u>, <u>версию</u>, <u title="'+navigator.platform+'">ОС</u> и версию скрипта (@).</span>';
  4517. reformal_foot1.parentNode.appendChild(reformal_note1);
  4518. reformal_note1.style.padding ='3px 0 0 5px';
  4519. reformal_note1.style.cursor ='pointer';
  4520. });
  4521. }
  4522. if(hS.gPlus.val && !/\/sandbox/.test(location.href && !inFrame)) // добавление скрипта Google+
  4523. addJs('https://apis.google.com/js/plusone.js','{"parsetags": "explicit"}', 'gapi', loadGPlus);
  4524. //linkCommFavor(); //дин.ссылки избранного и комментариев
  4525. var submenu = $q('.submenu')
  4526. ,forSand = $qA('.item a[href*="/sandbox/"],.item a[href*="/notes/"]', submenu);
  4527. //'forSand'.wcl(forSand , !forSand.length , !isCompa)
  4528. if(forSand && !forSand.length && !isCompa)
  4529. $e({cl:'item'
  4530. ,ht:'<a href="http://habrahabr.ru/sandbox/"><span class="name">Песочница</span></a>'
  4531. ,apT: submenu
  4532. });
  4533. $e({cl:'item'
  4534. ,ht:'<a href="http://habrastorage.org/"><span class="name">Storage</span></a>'
  4535. ,apT: submenu
  4536. });
  4537. var userpanel = $q('.userpanel');
  4538. if(userpanel){ //кнопка настроек [и тест ошибок юзерскрипта]
  4539. var hMailLink = $q('a[href*="conversations/"]', userpanel)
  4540. ,favors = $q('a[href*="favorites/"]', userpanel)
  4541. ,trac = $q('a[href*="tracker/"]', userpanel)
  4542. ,nastr = $q('a.nav-settings', userpanel)
  4543. ,exit = $q('a[href*="logout"]', userpanel)
  4544. ,cntTrac = $q('a.count[href*="tracker"]', userpanel)
  4545. ,cntMail = $q('a.count[href*="conversations"]', userpanel)
  4546. ,bottom = $q('.bottom', userpanel);
  4547. if(exit)
  4548. exit.title ='выход';
  4549. if(trac)
  4550. trac.innerHTML ='трек';
  4551. if(cntTrac && trac){
  4552. trac.style.display ='none';
  4553. cntTrac.title ='трекер';
  4554. }
  4555. if(cntMail && hMailLink){
  4556. hMailLink.style.display ='none';
  4557. cntMail.title ='сообщения в почте';
  4558. }
  4559. if(RO){
  4560. RO.title = RO.innerHTML; RO.innerHTML ='RO';}
  4561. if(hMailLink){
  4562. hMailLink.innerHTML ='сооб';
  4563. $e({el: hMailLink, prT: bottom});
  4564. }
  4565. var habrAjaxSettButt = $e({el:'A'
  4566. ,cl:'habrAjaxSettButt'
  4567. ,at:{href: URLCSS, title:'Настройки просмотра сайта'}
  4568. ,ht:'HAjax'
  4569. ,on:{click: hS.edit} });
  4570. h.inZen ? $e({el: habrAjaxSettButt, prT: bottom}) : $e({el: habrAjaxSettButt, apT: bottom});
  4571. if(favors){
  4572. favors.innerHTML ='избр';
  4573. favors.title ='Избранные мною статьи';
  4574. $e({el: favors, prT: bottom});
  4575. }
  4576. var login = $q('.userpanel >a[href*="login/"]');
  4577. if(nastr){
  4578. nastr.innerHTML ='настр';
  4579. nastr.title ='настройки пользователя на сайте';
  4580. $e({el: nastr, prT: bottom});
  4581. }else //для неавторизованных
  4582. login && login.parentNode.insertBefore(habrAjaxSettButt, login);
  4583. if(login && !nastr && /googleusercontent.com/.test(lh))
  4584. login.innerHTML ='googleUserContent';
  4585. var chargeDiv, replaceCharge;
  4586. if( chargeDiv = $q('.charge', userpanel) ){
  4587. (replaceCharge = function(){ //перевод описания оставшихся голосов в иное представление
  4588. var chrgNums = chargeDiv.innerHTML.match(/\d+/g);
  4589. if(chrgNums && !chrgNums[1]) chrgNums[1] ='--';
  4590. chargeDiv.style.fontSize ='12px';
  4591. var dd = $e({ht:'<span title="имеется голосов за статьи и карму">'
  4592. + (chrgNums && chrgNums.length ? chrgNums[0]:'') +'</span> '
  4593. +'<a href="/users/'+ h.uName +'/topics/">&nbsp;Блог&nbsp;</a>'
  4594. +' <a href="/users/'+ h.uName +'/qa/questions/">QAQ</a><br>'
  4595. +'<span title="за комментарии">'
  4596. + (chrgNums && chrgNums.length ? chrgNums[1]:'') +'</span> '
  4597. +'<a href="/users/'+ h.uName +'/comments/">Комм.</a>'
  4598. +' <a href="/users/'+ h.uName +'/qa/answers/">QAA</a>'});
  4599. var chlds = chargeDiv.childNodes;
  4600. //'chlds'.wcl(chlds, chlds.length);
  4601. for(var i in chlds){ var chI = chlds[i]; if(chI.parentNode){
  4602. //'chldsI'.wcl(chI, chI.nodeType, chI.nodeValue)
  4603. if(chI.nodeType ==3 && chI.nodeValue && chI.nodeValue.length >19)
  4604. chargeDiv.replaceChild(dd, chI);
  4605. }}
  4606. })();
  4607. }
  4608. }
  4609. var panelNav = $q('#header .main_menu')
  4610. ,tops = panelNav && $q('a[href*=top]', panelNav)
  4611. ,events = panelNav && $q('a[href*=events]', panelNav);
  4612. if(tops) tops.innerHTML ='хит';
  4613. if(events) events.innerHTML ='соб';
  4614. var contSelect;
  4615.  
  4616. //{ Данные цитаты:
  4617. //contextBefore //примерно строка до выделенного (в письме отображается серым)
  4618. //contextAfter //примерно строка после выделенного
  4619. //author //автор статьи-комментария
  4620. //date //дата (статьи, комментария)
  4621. //title //название статьи (для использ. в письме)
  4622. //link: //ссылка URL на элемент
  4623. //source //источник (перевода, ссылки)
  4624. //sourceLink
  4625. //тип контекста цитаты: статья, коммент, QA, песочн.};
  4626. //(contSelect = function(){ //========== обработка выделения текста ================
  4627.  
  4628. if(hS.contextSelect.val || hS.hQuotes && hS.hQuotes.val || hS.correctCite.val){ //=== контролы на выделения текста ===
  4629. var selectOp = function(ev){ //сбор данных по выдел_
  4630. if(parents('^citeBtns$',ev.target))
  4631. return;
  4632. if(parents('citeBtns', ev.target) && ev.target.tagName !='A'){
  4633. $pdsp(ev);
  4634. }
  4635. if(win.getSelection && hNE && !parents('js-field-data', ev.target) /*&& !parents('topic_add', ev.target)*/ ){
  4636. var sR = win.getSelection();
  4637. //sR.modify && sR.modify("extend", "forward", "word"); //граница слова в конце выделения
  4638. var sRA = sR.anchorNode
  4639. ,sRF = sR.focusNode
  4640. ,commElemStart = parents('^comment_item', sRA)
  4641. ,commElemEnd = parents('^comment_item', sRF)
  4642. ,artiElemStart = parents('^content[^_]', sRA)
  4643. ,artiElemEnd = parents('^content[^_]', sRF)
  4644. ,sel ={commCount: 1 //параметры выделения
  4645. ,elemTop: 9e9, elemRight: -9e9, elemBottom: -9e9, elemLeft: 9e9}
  4646. try{
  4647. var sRR = sR.getRangeAt && sR.getRangeAt(0)
  4648. ,nodeAncestor = sRR.commonAncestorContainer
  4649. ,nodeStart = sRR.startContainer
  4650. ,nodeEnd = sRR.endContainer
  4651. // вычисление текстового сдвига относительно общей ноды, чтобы:
  4652. // 1) найти контекст; 2) отвязаться от пересекающих нод. Корневая нода - сообщение
  4653. ,rAncestorStart = sRR.cloneRange();
  4654. rAncestorStart.selectNodeContents(nodeAncestor);
  4655. //rAncestorStart.setStartAfter(nodeAncestor);
  4656. //rAncestorStart.setEndBefore(nodeStart);
  4657. //,rAncestorEnd = (document.createRange()).selectNode(nodeAncestor);
  4658. //rAncestorStart.setEndBefore(nodeStart);
  4659. //rAncestorEnd.setEndBefore(nodeEnd);
  4660.  
  4661. }catch(er){;}
  4662. if(sRR && sRR.getClientRects && sRR.getClientRects()[0]){ //границы выделения
  4663. var sRRB = sRR.getClientRects();
  4664. for(var i=0, iL = sRRB.length; i < iL; i++){
  4665. if(sRRB[i].top < sel.elemTop) sel.elemTop = sRRB[i].top;
  4666. if(sRRB[i].right > sel.elemRight) sel.elemRight = sRRB[i].right;
  4667. if(sRRB[i].bottom > sel.elemBottom) sel.elemBottom = sRRB[i].bottom;
  4668. if(sRRB[i].left < sel.elemLeft) sel.elemLeft = sRRB[i].left;
  4669. }
  4670. $x(sel, {startX: sRRB[0].left //координаты "старта-конца" (верха-низа)
  4671. ,startY: sRRB[0].top
  4672. ,endX: sRRB[sRRB.length-1].right
  4673. ,endY: sRRB[sRRB.length-1].bottom
  4674. });}
  4675. //TEST
  4676. /*sel.posStart = sRR.startOffset;
  4677. sel.posEnd = sRR.endOffset;
  4678. sel.nodeAncestor = nodeAncestor;
  4679. sel.rAncestorStart = rAncestorStart.startOffset +'/'+ rAncestorStart.endOffset;*/
  4680.  
  4681. if(sRA ==sRF) //направление выделения
  4682. sel.direction = sR.anchorOffset < sR.focusOffset;
  4683. else{
  4684. var posA = getPosition(sRA), posF = getPosition(sRF);
  4685. sel.direction = posA.y == posF.y ? posA.x < posF.x : posA.y < posF.y;
  4686. }
  4687. //'direction'.wcl(sel.direction, sel.elemTop, sel.elemBottom)
  4688. $x(sel, {commElemTop: sel.direction ? commElemStart || commElemEnd
  4689. : commElemEnd || commElemStart //тег с идом первого коммента
  4690. ,commElemBottom: !sel.direction ? commElemStart || commElemEnd
  4691. : commElemEnd || commElemStart
  4692. ,artiElemTop: sel.direction ? artiElemStart || artiElemEnd
  4693. : artiElemEnd || artiElemStart
  4694. ,artiElemBottom: !sel.direction ? artiElemStart || artiElemEnd
  4695. : artiElemEnd || artiElemStart
  4696. });
  4697. sel.postElem = parents('^post($| )', sel.artiElemTop || sel.commElemTop)
  4698. || prev('^post($| )', parents('^(comments_list( )?|comments c2)', sel.artiElemTop || sel.commElemTop)); //тег с идом поста - !!!будет сильно зависеть от вида записи класса!, источник ошибок волатильности
  4699. if(commElemStart && commElemEnd && commElemStart != commElemEnd){
  4700. var commsStart = parents('^(comments_list|comments c2)', sel.commElemTop) || parents('^comments c2$', sel.commElemTop)
  4701. ,commsEnd = parents('^(comments_list|comments c2)', sel.commElemBottom) || parents('^comments c2$', sel.commElemBottom);
  4702. if(commsStart == commsEnd){ //если в одной статье - считать выделенные комм-ы
  4703. var cInArt = $qA('.comment_item', commsStart)
  4704. ,j =0;
  4705. for(var i in cInArt){
  4706. if(j >0)
  4707. j++;
  4708. if(j && cInArt[i] == sel.commElemBottom)
  4709. j = -j;
  4710. if(!j && cInArt[i] == sel.commElemTop)
  4711. j =1;
  4712. }
  4713. sel.commCount = -j; //число выделенных комментариев (для "HQ")
  4714. }
  4715. }
  4716. if(sR)
  4717. var s = '<span class="selText">'+ sR +'</span>'
  4718. ,sTechLen = s.length - (sR+'').length;
  4719. if(s && (sR+'').length >0){
  4720. var sele = $q('.list .sele', hNE) //строка выделения - в список цитат
  4721. ,newSele = $e({el: sele
  4722. ,cl:'sele'
  4723. ,ht: s +' <span style="color:#999">'+ ((sR+'').length||'') +'</span>'});
  4724. if(newSele != sele)
  4725. $q('.list', hNE).appendChild(newSele);
  4726. //'commElemTop'.wcl(sel.commElemTop , sel.artiElemTop)
  4727. var commTime = $q('.info time', sel.commElemBottom) || $q('.info .time', sel.commElemBottom);
  4728. $x(sel, {text: s //выделение; и далее - сопутствующая инф.
  4729. ,textR: sR+'' //чистый текст выделения
  4730. ,dateCopy: +new Date() //дата снятия копии пользователем
  4731. ,articleId: sel.postElem && sel.postElem.id && sel.postElem.id.replace(/\D/g,'')
  4732. ,item: sel.commElemTop || sel.artiElemTop // ссылка на элемент с идом - статью или комментарий
  4733. ,commAuthor: sel.commElemBottom
  4734. ? ($q('.info .username', sel.commElemBottom) || $q('.info a', sel.commElemBottom) ).textContent.trim()
  4735. : undefined
  4736. ,commDate: sel.commElemBottom && commTime
  4737. ? commTime.textContent.trim() + (commTime.title ?', '+ commTime.title.replace(/,/,', ') :'')
  4738. : undefined
  4739. ,author: sel.postElem
  4740. ? $q('.infopanel .author a[href*="/users/"]', sel.postElem) && $q('.infopanel .author a[href*="/users/"]', sel.postElem).textContent.trim()
  4741. : undefined
  4742. ,title: sel.postElem
  4743. ? $q('.title span', sel.postElem) && $q('.title span', sel.postElem).textContent.trim()
  4744. : undefined
  4745. ,date: sel.postElem
  4746. ? $q('.infopanel .published', sel.postElem) && $q('.infopanel .published', sel.postElem).textContent.trim() + ($q('.infopanel .published', sel.postElem).title ?', '+ $q('.infopanel .published', sel.postElem).title :'')
  4747. :undefined
  4748. });
  4749. //'sel'.wcl(sel);
  4750. if(sel.articleId)
  4751. sel.url = ROOT +'/post/'+ sel.articleId +'/';
  4752. if(sel.commElemBottom)
  4753. sel.commId = sel.commElemBottom.id.replace(/\D+/,'');
  4754. //разместить контекстную кнопку
  4755. var edit = $q('.title .edit', sel.postElem); //===== кнопка "Edit" ========
  4756. $q('.edit', hNBs).style.display
  4757. = (!edit || sel.commElemBottom) && !/\/(edit|add)\//.test(lh)
  4758. ?'none':'';
  4759. $x(hNBs.style, {left: ((ev.type=='keyup'&& ev.pageX + sel.endX || ev.pageX) +6) +'px'
  4760. ,top: ((ev.type=='keyup'&& ev.pageY + sel.endY || ev.pageY) +16) +'px'
  4761. ,display:'block'});
  4762. selS.ww && win.clearTimeout(selS.ww);
  4763. var hideNBs;
  4764. selS.ww = win.setTimeout(hideNBs = function(){
  4765. if(!selS.noAutoHide && ! selS.hover) hNBs.style.display ='none';
  4766. }, 2999); //hide
  4767. hNBs.style.display ='block';
  4768. $q('.citeTxTa', hNBs) && ($q('.citeTxTa', hNBs).style.display ='none');
  4769. selS.noAutoHide =0; //автоскрытие через 3 с.
  4770. }else{ //===== сохранение прежде набранного при нулевом выделении =====
  4771. hNBs.style.display ='none';
  4772. if(!selS.prev) selS.prev ={};
  4773. $x(selS.prev, { //сохранение прежде набранного
  4774. citeComm: $q('.ta', hNBs).value
  4775. ,textR: selS && selS.textR ||''
  4776. //TODO и много другого контекста
  4777. });
  4778. $q('.ta', hNBs).value = $q('.taAbs', hNBs).value =''; //очистка по закрытию
  4779. selS.ww && win.clearTimeout(selS.ww);
  4780. }
  4781. $e({el: hNBs, on:{ //поведение автоскрытия кнопки при неактивности
  4782. mouseover: function(){selS.ww && win.clearTimeout(selS.ww); selS.hover =1;}
  4783. ,mouseup: function(){selS.noAutoHide =1;}
  4784. ,mouseout: function(){
  4785. selS.hover =0;
  4786. selS.ww && win.clearTimeout(selS.ww);
  4787. selS.ww = win.setTimeout(hideNBs, 2999);
  4788. }} });
  4789. selS = sel; //всё о выделении
  4790. if(s.replace(/^\s+/,'').length <= sTechLen) //если пустая строка выделения
  4791. hN.retainView(); //скрыть, если внутри нет блоков...
  4792. else
  4793. hNE.style.display ='block';
  4794. hNE.style.opacity = s.length >22 || $q('.hlp', hNE) ? 1 : 0.85;
  4795. }
  4796. }
  4797. $e({el: document.body, on:{mouseup: selectOp, keyup: selectOp} });
  4798. }
  4799. var bt =' <button type="button" title="' //команды работы с цитатой
  4800. ,citeButF = function(ev){ //===== движение - drag =====
  4801. hNBs.style.left = (citeButF.xy.x -= citeButF.mou.x - (citeButF.mou.x = ev.pageX)) +'px';
  4802. hNBs.style.top = (citeButF.xy.y -= citeButF.mou.y - (citeButF.mou.y = ev.pageY)) +'px';
  4803. $pdsp(ev);
  4804. },
  4805. hNBs = $e({cl:'citeBtns',
  4806. ht:'<div class="citeCmdLeft">'
  4807. +bt+'Комментарий с цитатой" data="reply">Ответ</button>'
  4808. +bt+'Начать письмо с цитатой; Ctrl - в новой вкладке" data="letter">Письмо</button>'
  4809. +bt+'Начать письмо выделенному или контекстному автору" data="toUser">Юзеру</button>'
  4810. +'<div class=hov>'+bt+'Поиск по сайту (вывод в фрейме)" data="search" style="display:block">Поиск</button>'
  4811. +bt+'Поиск по сайту через Google; Ctrl - в новой вкладке" data="searchGoo">Goo</button>'
  4812. +bt+'Поиск по сайту через Yandex" data="searchYa">Ya</button></div>'
  4813. +'</div>'
  4814. +(hS.correctCite.val ? '<div class="citeCmdRight">'
  4815. +bt+'Отметить как ошибку" data="mistake" class="pre">Грамматика</button>'
  4816. +bt+'Ошибка в знаках препинания" data="punctuation" class="pre">Пунктуация</button>'
  4817. +bt+'" data="misprint" class="pre">Опечатка</button>'
  4818. +bt+'Ошибка в стилистике" data="stylistic" class="pre">Стиль</button>'
  4819. +'</div>':'')
  4820. +'<div class="citeTxTa">'
  4821. +'<div class="citeTx">'
  4822. +'<div class="citeLst"><span class="citeLst2">'
  4823. +'<b class="cite"></b><b class="cite"></b></span></div>'
  4824. +'<div class="citeTxt"></div></div>'
  4825. +'<div class="citeTa"><textarea class="taAbs"></textarea>'
  4826. +'<textarea class="ta"></textarea></div>'
  4827. +'</div>'
  4828. +'<div class="citeCmdTop" class="pre"></div><div class="citeCmdBase">'
  4829. +bt+'Подготовка цитаты" data="citeComm" class="pre">&lt;_></button>'
  4830. +'<button type=button class=edit title="Редактировать" data="edit">&lt;E></button>'
  4831. +(hS.correctCite.val ? bt+'Ошибка содержания" data="wrongData" class="pre">Ош.</button>':'')
  4832. +(hS.hQuotes && hS.hQuotes.val ? bt+'Отправить в HabraQuotes (выделенные 1-10 комментариев)" data="hQuotes">HQ</button>':'')
  4833. +bt+'восстановить набранное в прежнем контексте" data="repair">&lt;_</button>'
  4834. +'</div>',
  4835. on:{
  4836. mousedown: function(ev){ //перемещение конт.кнопок
  4837. if(ev.target.className =='ta'|| parents('^citeTxTa$',ev.target))
  4838. return;
  4839. document.addEventListener('mousemove', citeButF,!1);
  4840. document.addEventListener('mouseup', function(ev){
  4841. document.removeEventListener('mousemove', citeButF)});
  4842. citeButF.xy = {x: parseInt(hNBs.style.left), y: parseInt(hNBs.style.top)};
  4843. $x(citeButF.mou0={}, citeButF.mou ={x: ev.pageX, y: ev.pageY});
  4844. //'citeButF.mou0'.wcl(citeButF.mou0)
  4845. },
  4846. mouseup: function(ev){
  4847. '33'.wcl(ev.target)
  4848. selS.cmd = ev.target.getAttribute('data'); //имя кликнутой кнопки
  4849.  
  4850. selS.subSelect = parents('^citeTxTa$',ev.target) ?1:0; //выделение в цитате или в поле ввода
  4851. /*return;*/
  4852. //hN.ciCom = {misType: ev.target.getAttribute('data')};
  4853. document.removeEventListener('mousemove', citeButF);
  4854. hN.moveMin =4;
  4855. hNBs.wasMoved = Math.abs(citeButF.mou0.x - ev.pageX) + Math.abs(citeButF.mou0.y - ev.pageY) /*< hN.moveMin*/; //признак перемещения
  4856. '44'.wcl('tx',hNBs.wasMoved)
  4857. },
  4858. click: function(ev){
  4859. selS.hN = hN; //TODO обратная ссылка
  4860. if(!h.uName && !(hS.hQuotes && hS.hQuotes.val))
  4861. hN.addNote(this.title +' - требуется авторизация на сайте.');
  4862. else{ //передвижение или исполнение по кнопке
  4863. selS.ww && win.clearTimeout(selS.ww);
  4864. if(hNBs.wasMoved > hN.moveMin){
  4865. 'moved'.wcl(hNBs.wasMoved);
  4866. }else{
  4867. 'hN.sel0'.wcl(selS, selS.subSelect)
  4868. if(!selS.subSelect)
  4869. cmd[ selS.cmd ](selS, ev); //=== действие (клик кнопки) ===
  4870. }
  4871. }
  4872. }
  4873. },apT: document.body
  4874. }),
  4875. cmd ={ //=== команды обработки выделений ===
  4876. insertComm: function(s, clarifShow){
  4877. var repl = s.commElemBottom
  4878. ? $q('.reply .reply_link', s.commElemBottom) || $q('.reply >a.reply', s.commElemBottom) //цитата из комментария
  4879. : $q('.comments_form .title a'); //..из статьи
  4880. 'isRepl'.wcl(repl, s.commElemBottom)
  4881. var tA = $q('textarea#comment_' +'text')
  4882. , taVal = tA.value;
  4883. if(repl){
  4884. '+|+'.wcl(!$q('textarea', repl.parentNode.parentNode))
  4885. /*if(1 || s.commElemBottom && (!$q('textarea', repl.parentNode.parentNode) || !s.commElemBottom);*/
  4886. tA.value = taVal;
  4887. }
  4888. 'cshow'.wcl(s.commElemBottom)
  4889. tA.value += (/\n$/.test(tA.value) || tA.value.length ==0 ?'':'\n') //с новой строки
  4890. + (s.textR.trim().length <=1 ?'':'<blockquote>'+ s.textR +'</blockquote>\n') //удалять 0-1-символьные цитаты
  4891. + (s.text0 || this.citeComm() ||''); //текст из плавающего комментария
  4892. tA.focus();
  4893. },
  4894. reply: function(s, ev){ //ответ в корневой комм., или раскр.отв. в текущий (последн.выд.), прокрут.
  4895. if(s==0){
  4896. var lStor = getLocStor('composeLetter');
  4897. 'lStor'.wcl(lStor);
  4898. if(lStor){
  4899. var sRF = $q('#reply_comments_'+ lStor.commId) || $q('#comment_'+ lStor.commId);
  4900. s ={
  4901. commElemBottom: parents('^comment_item', sRF)
  4902. ,textR: lStor.cite ||''
  4903. ,text0: lStor.text ||''
  4904. };
  4905. removeLocStor('composeLetter');
  4906. }}
  4907. var tAs = $qA('textarea#comment_text')
  4908. ,clarifShow = null; //в QA открыто уточн.или отв.в комм
  4909. 'repl'.wcl(tAs, s);
  4910. if(s !=0 && (s.commElemBottom && parents('comments c2', s.commElemBottom) //цитата с комм.
  4911. || s.artiElemBottom && /content c2/.test(s.artiElemBottom.className)
  4912. || topics && topics.length && s.artiElemBottom && /^content /.test(s.artiElemBottom.className) ))
  4913. this.letter(s, ev,'comm');
  4914. else if(tAs.length)
  4915. this.insertComm(s, clarifShow);
  4916. },
  4917. letter: function(s, ev, isComm){ //письмо с одиночной цитатой
  4918. if(selS)
  4919. this.initLetter(ev, {to: s.author, subj: s.title ?'Re: '+ s.title :'', cite: s.textR}, isComm);
  4920. else
  4921. this.initLetter(ev,{cite: s.textR}, isComm);
  4922. },
  4923. toUser: function(s, ev){ //письмо пользователю (явное имя или контекстное)
  4924. 'selS'.wcl(selS, s.textR, userNameMaxLen, allASCII(s.textR))
  4925. var shortSel = s.textR.length >2 && s.textR.length <= userNameMaxLen && allASCII(s.textR);
  4926. if(selS){
  4927. '++'.wcl(shortSel ? s.textR.trim().replace(',$','') : s.commAuthor || s.author, s.title ?'Re: '+ s.title :'', !shortSel ? s.textR : null)
  4928. this.initLetter(ev, {to: shortSel ? s.textR.trim().replace(',$','') :'Enter username'
  4929. , subj: s.title ?'Re: '+ s.title :'', cite: !shortSel ? s.textR : null} ); //контекстному автору из преж. команды
  4930. // (оформляются все цитаты и ошибки автора, отмеченные в чекбоксах)
  4931. }else
  4932. this.initLetter(ev, {to: shortSel ? s.textR.trim().replace(',$','') : null
  4933. , cite: !shortSel ? s.textR : null} );
  4934. },
  4935. search: function(s, ev, FFind){
  4936. if(srchBut){
  4937. if(srchField) srchField.value = s.textR;
  4938. var evt = document.createEvent("MouseEvents");
  4939. evt.initMouseEvent('click',!0,!0, window, 0, 0, 0, 0, ev.clientY,
  4940. ev.ctrlKey, !1, ev.shiftKey, !1, 0, null);//(type, canBubble, cancelable, view,
  4941. // detail, screenX, screenY, clientX, clientY,
  4942. // ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget)
  4943. (FFind || srchBut).dispatchEvent(evt);
  4944. }},
  4945. searchGoo: function(s, ev){
  4946. this.search(s, ev, srchButGoo);
  4947. },
  4948. searchYa: function(s, ev){
  4949. this.search(s, ev, srchButYa);
  4950. },
  4951. hQuotes: function(s, ev){ //комментарий - ->на habraQuotes.ru
  4952. 'hQuotes'.wcl(0, win.GM_xmlhttpRequest);
  4953. if(typeof GM_xmlhttpRequest !=u){
  4954. hN.addNote(imgWait +'&nbsp;');
  4955. var itemId = s.item && s.item.id
  4956. ,linkHQ =' <a href="http://habraquotes.ru/fresh/" title="новое окно" target="_blank">Перейти на сайт</a>';
  4957. 'items'.wcl(s, s.postElem, s.articleId, s.commCount, itemId);
  4958. if(itemId){
  4959. var waitHQ = win.setTimeout(function(){ //таймаут по неответу
  4960. //alert(305)
  4961. hN.addNote('Ошибка: нет ответа от habraquotes.ru долгое время. '+ linkHQ);
  4962. }, 14000);
  4963. GM_xmlhttpRequest({ //отправка данных для публикации
  4964. url: 'http://habraquotes.ru/api/2.0/quotes/add'
  4965. ,method:'post'
  4966. ,data:'link='+ ROOT +'/post/'+ s.articleId +'/#'+ itemId +'&count='+ s.commCount +'&is_habrajax=1'
  4967. ,headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With":"XMLHttpRequest"}
  4968. ,onload: function(dat2){
  4969. if(/"url":/.test(dat2.responseText) && !/"error":/i.test(dat2.responseText) ||/{"state":"ok"}/i.test(dat2.responseText) ){
  4970. win.clearTimeout(waitHQ);
  4971. 'dat2'.wcl(dat2.responseText,'{"state":"ok"}'==dat2.responseText)
  4972. if(/"url":/.test(dat2.responseText) || /{"state":"ok"}/i.test(dat2.responseText) ){
  4973. datJson = win.JSON.parse(dat2.responseText);
  4974. hN.addNote('Публикация выполнена успешно. <a href="http://habraQuotes.ru/'+ (datJson.url ? datJson.url+'/':'fresh/') +'" title="новое окно" target="_blank">Посетить сайт с&nbsp;местом публикации</a>');
  4975. }}else if(/"err":/.test(dat2.responseText)){
  4976. win.clearTimeout(waitHQ);
  4977. datJson = win.JSON.parse(dat2.responseText);
  4978. hN.addNote('Ошибка: '+ datJson.error +'. '+ linkHQ);
  4979. }else
  4980. hN.addNote('Неопознанный ответ: ', dat2.responseText, linkHQ);
  4981. }, onerror: function(dat2){
  4982. win.clearTimeout(waitHQ);
  4983. 'Err:'.wcl('habraQuotes ', dat2); //TODO по таймауту - повторить
  4984. hN.addNote('<i>Err: ошибка обмена (2-й запрос) с сервисом habraQuotes</i>'+ linkHQ);
  4985. },
  4986. onreadystatechange: function(datRS){
  4987. if(datRS && datRS.readyState ==4 && datRS.status !='200'&& datRS.status !='304' || /error/i.test(datRS.responseText) ){
  4988. win.clearTimeout(waitHQ);
  4989. 'Error habraquotes.ru: status='.wcl(datRS.status +', ошибка ответа. '+ datRS.responseText +' '+ linkHQ);
  4990. hN.addNote(' Ошибка: статус ответа - '+ datRS.status +'. '+ linkHQ);
  4991. }
  4992. }
  4993. });
  4994. }else
  4995. hN.addNote('<i>(был выбран не комментарий, действия нет)</i>');
  4996. }},
  4997. repair: function(s, ev){ if(selS.prev){ //восст_контекста и набранного, случайно закрытого ранее
  4998. var ss = $q('.ta', hNBs).value;
  4999. s.citeComm = selS.prev.citeComm;
  5000. selS.prev.citeComm = ss; //swap
  5001. ss = s.textR;
  5002. s.textR = selS.prev.textR;
  5003. s.text = '<span class="selText">'+ s.textR +'</span>';
  5004. selS.prev.textR = ss; //swap
  5005. this.citeComm(s, ev,'repair');
  5006. }},
  5007. //Дополненное к цитате:
  5008. //copier //пользователь-копировщик (автор цитаты и дополнений к ней)
  5009. //misType: //тип ошибки (5 типов или просто цитата) - предваряющая или заверш-я кнопка
  5010. //subSels: [] //суб-выделения - детализации ошибок или выделений в цитате
  5011. //removes: [] //удаления (исправления)
  5012. //adds: [] //добавления пользователя (исправления)
  5013. // тип оценки (к цитате): -3 - свернуть и никому не показывать; -2 - свернуть; -1 - не очень; 0 - ну, смотрел; 1 - интересно, 2 - надо вернуться 3 - смотреть всем
  5014. //оценка - эмоции, оценка - содержание
  5015. //userComments: [] //ответы пользователя - текст, дата
  5016. mistake: function(a, b){this.citeComm(a, b)}, //группа обработки ошибок (отмеч-с тип)
  5017. punctuation: function(a, b){this.citeComm(a, b)},
  5018. misprint: function(a, b){this.citeComm(a, b)},
  5019. stylistic: function(a, b){this.citeComm(a, b)},
  5020. wrongData: function(a, b){this.citeComm(a, b)},
  5021. citeComm: function(s, ev, noFill){ //=== комментирование цитаты (и субвыделения) =(s==selS)
  5022. var citeTxTa = $q('.citeTxTa', hNBs) //блок контекстного ввода (общий)
  5023. ,citeTx = $q('.citeTx', citeTxTa) //блок цитат
  5024. ,citeLst = $q('.citeLst', citeTxTa) //список цитат
  5025. ,citeLst2 = $q('.citeLst2', citeLst) //список цитат
  5026. ,citeTxt = $q('.citeTxt', citeTxTa) //цитата
  5027. ,citeTa = $q('.citeTa', citeTxTa) //блок комментария
  5028. ,citeTaT = $q('.ta', citeTa); //поле контекстного комментария
  5029. if(!ev && !s) //вернуть написанное в комментарии
  5030. return citeTaT.value;
  5031. var citeTaA = $q('.taAbs', citeTa)
  5032. ,areaSymb = 140 //средняя площадь символа
  5033. ,areaTaSymb = 130
  5034. ,areaText = s.text && Math.sqrt(areaSymb * s.textR.length) ||0
  5035. ,areaTaText = s.comm && Math.sqrt(areaTaSymb * s.comm.length) || 1;
  5036. s.hN.ciCom ={copier: h.uName, misType: s.cmd} //дополнения копировщика к цитате
  5037. $x(citeTx.style, {width: Math.floor(areaText)+50 +'px'
  5038. ,marginLeft: -Math.floor(areaText /2 -10) +'px'
  5039. ,marginRight: -Math.floor(areaText /2 +10) +'px'
  5040. });
  5041. citeTxt.innerHTML = s.text;
  5042. /*$e({el:'b', cl:'cite'
  5043. ,ht:'='+ s.posStart +'_'+ s.posEnd +';'+ s.nodeAncestor.textContent +';'+ s.rAncestorStart
  5044. ,apT: citeLst2});*/
  5045. //this.normTa(areaTaText, citeTaT);
  5046. //this.normTa(areaTaText, citeTaA);
  5047. $x(citeTxt.style, {textAlign: s.textR.length >13 ?'left':'center'
  5048. ,wordWrap: s.textR.length >13 || /\s/.test(s.text) ?'normal':'break-word'
  5049. });
  5050. $q('.selText', citeTx).style.left = s.textR.length >13 ?'1.1em':'0'
  5051. var hh;
  5052. $x(citeTaT.style, hh={width: Math.floor(areaTaText)+50 +'px'
  5053. //, height:'1em'
  5054. //, marginLeft: -Math.floor(areaTaText /2 -10) +'px'
  5055. //, marginRight: -Math.floor(areaTaText /2 +10) +'px'
  5056. ,overflow:'hidden'
  5057. });
  5058. $x(citeTaA.style
  5059. ,{width: Math.floor(areaTaText)+50 +'px'
  5060. ,height:'1em', overflow:'hidden'});
  5061. var initCite
  5062. ,selC = selS;
  5063. (initCite = function(){ //сброс набора прежней цитаты
  5064. citeTaT.value = citeTaA.value = s.citeComm ||''; //восстановление поля
  5065. if(!selC)
  5066. selC ={chgLenPrev:0};
  5067. selC.taH1 =0;
  5068. })();
  5069. selC.tFI =0; //состояние selC.taFloat[]
  5070. var taH1 = selC.taH1 ||16 //высота _одной_ строки в textarea
  5071. ,taParams;
  5072. (taParams = function(ev){ //подгонка размеров растущей области ввода в контексте
  5073. var tx = selC.val = ev ? citeTaT.value : s.citeComm||''
  5074. ,txL = tx.length
  5075. ,tASH = citeTaA.scrollHeight; //реальная высота введённого текста
  5076. citeTaA.value = tx;
  5077. s.hN.ciCom.userComments = tx; //фиксация набранного
  5078. selC.taFloat =[{h:{n:4,w:50}},{h:{n:10,w:128}},{h:{n:16,w:159}},{h:{n:24,w:238}}
  5079. ,{v:{r:4,w:238}},{v:{r:5,w:375}},{v:{r:12,w:530}},{v:{r:16,w:690}}]; //Правила: 1) сохранять равенство ширин (w) соседних h и v; 2) состояния (h, v) располагать по возрастанию; 3) вначале всегда h (однострочные градации ширины). w - ширина поля, n - число символов, r - число строк
  5080. selC.taFlNmax =0; //поиск максимума .h.n
  5081. for(var i =0, iL = selC.taFloat.length; i < iL; i++)
  5082. if(selC.taFloat[i].h && selC.taFloat[i].h.n > selC.taFlNmax){
  5083. selC.taFlNmax = selC.taFloat[i].h.n;
  5084. selC.taFlImax = i;
  5085. }
  5086. if(!ev && selC){ //начальная установка (taH1 и фокус)
  5087. citeTa.style.left =0;
  5088. selC.lenPrev2 = selC.lenPrev = txL;
  5089. win.setTimeout(function(){
  5090. //citeTaT.focus();
  5091. selC.taH1 = citeTaA.scrollHeight -1 -2*isFx;
  5092. },1);
  5093. }
  5094. //'ev'.wcl(ev, !ev, {tx:tx, tASH:tASH || taH1},selC.tFI)
  5095. if( (function(h2){ //chkGrow=== проверка размеров содержимого поля ввода ===
  5096. var taS = selC.taFloat[selC.tFI];
  5097. for(var j in taS) var taSkey = j; //имя ключа состояния
  5098. if(taSkey !='h' && taSkey !='v')
  5099. wcl('Err: '+ 'ош. в выборе типа поля ввода');
  5100. txL = h2.tx.length;
  5101. taNS = Math.floor((h2.tASH +0.5)/ taH1); //(реальное) чис.строк поля ввода
  5102. //'taNS,tx'.wcl(taNS,tx, selC.taH1, taH1)
  5103. if(txL <= selC.taFlNmax){ //выбор 1-строчного варианта поля
  5104. for(var i =0, iL = selC.taFlImax +1; i < iL; i++)
  5105. if(txL <= selC.taFloat[i].h.n && (i==0 || i >0 && txL > selC.taFloat[i-1].h.n)){
  5106. selC.tFINew = i; break;}
  5107. }else{
  5108. for(var i = selC.taFlImax+1, iL = selC.taFloat.length+1; i < iL; i++)
  5109. if(taNS <= selC.taFloat[i].v.r && (i==selC.taFlImax+1 || i >selC.taFlImax+1 && taNS > selC.taFloat[i-1].v.r) ){
  5110. selC.tFINew = i; break;}
  5111. }
  5112. if(s.citeComm)
  5113. selC.tFI = Math.max(0, selC.tFINew -1);
  5114. //'i,txL,taFlNmax'.wcl(i, txL, selC.taFlNmax)
  5115. if( (selC.lenPrev2 < txL ^ selC.tFINew > selC.tFI) || Math.abs(txL - selC.chgLenPrev) < txL/8){ //консервативность смены
  5116. selC.tFINew = selC.tFI;
  5117. selC.lenPrev2 = selC.lenPrev;
  5118. selC.lenPrev = txL;
  5119. }
  5120. //'taNS'.wcl(h2.tASH, taNS, selC.tFINew)
  5121. if(selC.tFINew != selC.tFI){
  5122. selC.chgLenPrev = txL;
  5123. return!0;}
  5124. })({tx:tx, tASH:tASH || taH1})
  5125. || !ev || Math.abs(tASH - selC.taHprev) < 6 ){ //обновл_ размеров
  5126. var taH2 = tASH ||16; //далее - высота (px) всех строк в поле ввода
  5127. citeTaA.style.height = (taH1 -1) +'px';
  5128. win.setTimeout(function(){
  5129. citeTaT.style.height = citeTa.style.height = ((selC.taHprev = citeTaA.scrollHeight) -1)+'px';
  5130. //'=citeTaA'.wcl(tASH, citeTaA.scrollHeight, citeTaA.value, selC.taHprev
  5131. // ,'||',taS, selC.tFINew);
  5132. citeTa.style.width = (taS && (taS.h && taS.h.w || taS.v.w))+'px';
  5133. citeTx.style.bottom = (selC.taHprev -3) +'px';
  5134. },1);
  5135. citeTa.style.height = (taH2 -1) +'px';
  5136. citeTx.style.bottom = (taH2 -3) +'px';
  5137. //'tFINew==='.wcl(selC.tFINew, taS, tASH, selC.taHprev, tASH / selC.taH1, selC.taH1)
  5138. if(typeof selC.tFINew =='number'&& ev || s.citeComm){
  5139. var taS = selC.taFloat[selC.tFINew];
  5140. citeTaT.style.width = citeTaA.style.width
  5141. = citeTa.style.width = (taS && (taS.h && taS.h.w || taS.v.w))+'px';
  5142. citeTa.style.left = Math.min(-((taS && (taS.h && taS.h.w || taS.v.w))/2 -43),0) +'px';
  5143. selC.tFI = selC.tFINew;
  5144. }
  5145. selC.taHprev = taH2;
  5146. }
  5147. })();
  5148. citeTaT.addEventListener('keypress',taParams,!1); //контроль за вводом символов
  5149. citeTaT.addEventListener('keyup',taParams,!1);
  5150. $x(citeTa.style, hh);
  5151. citeTxTa.style.display ='block';
  5152. $x(citeLst.style, {MaxWidth: Math.floor(areaText)+54 +'px'
  5153. ,top: -citeLst.offsetHeight -2 +'px'});
  5154. },
  5155. normTa: function(s, t){ //нормализация поля ввода: вычисление ширины и высоты по содержимому
  5156. var citeTa = t.parentNode
  5157. ,citeTxTa = citeTa.parentNode;
  5158. if(s !=null)
  5159. t.value = s;
  5160. },
  5161. htmlSelect: function(s, ev){ //===== оформить с захваченным HTML =====
  5162.  
  5163. $sp(ev);
  5164. },
  5165. edit: function(s, ev){ //===== редактировать область цитаты =====
  5166. setLocStor('composeLetter', {cite: s.textR});
  5167. if(/\/topic\/(add|edit)\//.test(lh)){
  5168. win.clearTimeout(wwPrevi);
  5169. fillLetter();
  5170. return;}
  5171. if((ev.ctrlKey || ev.cmdKey) ^ ev.shiftKey)
  5172. win.open(ROOT +'/topic/edit/'+ s.articleId +'/','_blank');
  5173. else
  5174. openInFrame({clientY: ev.clientY},{href: ROOT +'/topic/edit/'+ s.articleId +'/'});
  5175. $sp(ev);
  5176. },
  5177. mis: function(s){ //оформление ошибки
  5178. //hN.selContext = s; //сохранено состояние выделения (для след.оп. типа "письма")
  5179. var misType = s.misType = {mistake: 0, punctuation: 1, misprint: 2, stylistic: 3, wrongData: 4, citeComm: -1}
  5180. ,selField = $q('.sele .selText', hNCiteList)
  5181. ,selText = selField && selField.innerHTML; //текст выделения (возм-о, обраб-ный)
  5182. hNCiteList.removeChild($q('.sele', hNCiteList)); //удалить копию выделения
  5183. if(!hN.misId)
  5184. hN.misId = 1;
  5185. s.misId = hN.misId; //очередной Id выделения
  5186. $e({cl:'item'
  5187. ,ht:'<input type="checkbox" id="mis'+ hN.misId++
  5188. +'" name="'+ s.author +'" value="" checked="checked"/>'
  5189. + '<font style="background-color:#dbb; color:#964">'
  5190. + (misType[s.cmd] >=0 ? misType[s.cmd]:'') +'</font> '
  5191. +'<span class="selText">'+ (selText || s.textR) +'</span>'
  5192. ,apT: hNCiteList });
  5193. },
  5194. initLetter: function(ev, g, isComm){ //===== составить письмо ===== //g:{to,subj,cite}
  5195. //text, addressee, date, title, link, source, sourceLink //загрузить форму отправки письма
  5196. //для публикации письма в другом окне передаётся адрес с меткой времени и создаётся элемент хранилища с той же меткой. По получению элемент проверяется, используется и удаляется. Одновременно существует не более 1 объекта публикации письма. Формирование письма - ПЕРЕД отправкой, поэтому передаются 3 поля и метка времени. На случай отсутствия хранилища передаются 2 поля (укороченный текст и автор) и метка времени.
  5197. g = $x({to:'', subj:'', cite:'' }, g);
  5198. var s = selS
  5199. ,receiver = g.to=='Enter username' || g.to== h.uName ?''
  5200. : (g.to && !g.cite && g.to || s.commAuthor || g.to);
  5201. 'initLet'.wcl(g, receiver)
  5202. setLocStor('composeLetter',
  5203. $x(g, {cite: g.cite
  5204. + (/\n$/.test(g.cite) || g.cite && g.cite.length ==0 || !g.cite ?'':'\n')
  5205. ,noReceiver: !receiver
  5206. ,text: s.val ||'' //введённый комментарий
  5207. ,date: s.date
  5208. ,commDate: s.commDate
  5209. ,url: s.url
  5210. ,commId: s.commId
  5211. ,commAuthor: s.commAuthor}) );
  5212. var timeStmp = (+new Date()+'').replace(/(^\d{3}|\d{3}$)/g,'')
  5213. ,hrf = (!isComm
  5214. ? ROOT +'/conversations/'+(receiver?receiver+'/':'')
  5215. : s.url
  5216. )+'?time33='+ timeStmp
  5217. +(isComm ?'&cmd=insertComm':'')
  5218. +(!win.localStorage?'#'
  5219. +(g.to?'to='+ encodeURIComponent(g.to):'')
  5220. +(g.cite?(g.to?'&':'')+'text='+ encodeURIComponent( g.cite
  5221. +(g.cite && g.cite.length >500?'...':'') ):'')
  5222. :(s.commElemBottom ?'#'+ s.commElemBottom.id :'') );
  5223. 'letter'.wcl(s, hrf)
  5224. if((ev.ctrlKey || ev.cmdKey) ^ ev.shiftKey)
  5225. win.open(hrf,'_blank');
  5226. else
  5227. openInFrame({clientY: ev.clientY},{href: hrf});
  5228. //внести шаблон данных
  5229. },
  5230. buildCite: function(s){
  5231. var cLIs = $qA('.item', hNCiteList);
  5232. for(var i =0, iL = cLIs.length; i < iL; i++)
  5233. $q('input[type="checkbox"][checked="checked"]', cLIs[i]);
  5234. var subj ='Замечания к "'+ s.title.substr(0, 40)+ (s.title.length >40?'...':'')+'"'
  5235. ,foundMulti = 0//более 1 или тип 4
  5236. ,foundSemi = 0 //не по одной ош. в категориях 1-3
  5237. ,foundShe = 0 //1 шт. и ж. рода (тип 1-2)
  5238. ,mistakE = 0
  5239. ,misPrinT = 0
  5240. ,stylisT = 0.0
  5241. ,isSubSel =0 //есть ли суб-селекты
  5242. ,isWrongSel =0 //есть ли механизм подчёркиваний и пометок ошибок
  5243. ,mistSel =['ошибк'+ (mistakE?'а':'и') //перечислитель типов ошибок
  5244. ,'опечатк'+ (misPrinT?'а':'и')
  5245. ,'неверны'+ (stylisT?'й':'е') +' стилистически'+ (stylisT?'й':'е') +' оборот'+ (stylisT?'':'ы')
  5246. ,'неверные данные'];
  5247. for(var i=3; i >= 0; i--) //удаление пустых строк
  5248. if(0)
  5249. mistSel.splice(i, 1);
  5250. var x = '&nbsp; &nbsp; Здравствуйте, '+ s.author +'!\n'
  5251. +'&nbsp; &nbsp; В Вашей статье &quot;<a href="'+ s.link +'"><b>'
  5252. + s.title.substr(0, 60) + (s.title.length >60 ?'...':'')
  5253. +'</b></a>&quot; от <i>'+ s.date +'</i> обнаружен'
  5254. + (foundMulti ?'ы'+ (foundSemi ?':':''):(foundShe ?'а':''))
  5255. + mistSel.split(', ')
  5256. + (isSubSel ?'(выделено синим цветом в цитате)':'') +'.\n'
  5257. +'&nbsp; &nbsp; На мой взгляд, текст следовало бы писать так, как отмечено'
  5258. + (isWrongSel ?' красным цветом или подчёркиванием':'') +' в последующей строке.';
  5259.  
  5260. var aa='текст-цитата скорректированный текст (<текст_дополнительных пояснений>)'
  5261. +'С уважением, <своё_имя>.'
  5262. +'(К|Поправки к) статье|комментарию "<название>", <дата>';
  5263.  
  5264. }
  5265. };
  5266. if(/cmd=insertComm/.test(lh) && !win.opera) //дообработка комментария из localStorage
  5267. cmd.reply(0);
  5268. if(hS.killToTop.val)
  5269. addRules('.to_top{display:none!important}');
  5270. showSourceLang(topic,'add_label_lang'); //только метки языков к блокам кодов
  5271. showSourceLang(comments,'add_label_lang');
  5272.  
  5273. (function(){ //единый таймер контроля: показ оставшихся голосов после отправки оценок и т.д.
  5274. if(chargeDiv && !/</.test(chargeDiv.innerHTML) && replaceCharge)
  5275. replaceCharge(); //восстановить правку описания оставшихся голосов
  5276. win.setTimeout(arguments.callee, 2630);
  5277. })();
  5278. '(endParse)topicTitle'.wcl(topicTitle);
  5279. if($q(doc.body) && $q(doc.body).childNodes.length <=3 ){
  5280.  
  5281. //win.location = 'http://webcache.googleusercontent.com/search?q=cache:'+ win.location;
  5282. }
  5283. //})(); //=======/ end contSelect() ========
  5284.  
  5285. },!1); //=======/ end readyLoad() ========
  5286.  
  5287. if(typeof habrAjax !=u && (!habrAjax.wasLoad||/(Chrome\/|Opera\/)/.test(navigator.userAgent))) //для Хрома: эти события не существуют для юзер-скрипта
  5288. readyLoad();
  5289. }catch(er){
  5290. wcl('~~ER_global: '+ er +' (line '+(er.lineNumber||'')+')')}; //для оповещения об ошибках в Fx
  5291. })(typeof unsafeWindow !='undefined'? unsafeWindow: (function(){return this})(),'undefined')