HabrAjax

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

目前为 2015-01-24 提交的版本,查看 最新版本

  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 141.2015.01.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|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 140 +megamozg.ru; +ввод тега <code>;
  19. // @update 138 всплывающие даты в "Похожих публикациях"; удаление времени в датах "похожих";
  20. // @update 137 namespaces; похожие посты; сайдбар компаний;
  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. ,ROOT = location.protocol +'//'+ location.host
  93. ,URLSCR ='https://greasyfork.org/scripts/'
  94. ,URLCSS ='http://userstyles.org/styles/33690/'
  95. ,HAJAX ='1970-habrajax/'
  96. ,userNameMaxLen = 25
  97. ,isFx = /Firefox/.test(navigator.userAgent)
  98. ,isChrome = /Chrome\//.test(navigator.userAgent)
  99. ,wcl = function(a){ a = a!==undefined ? a :''; //консоль как метод строки или функция, с отключением по hS.noConsole.val ==1
  100. if(win.console && typeof hS !=u && !hS.noConsole.val)
  101. win.console.log.apply(console, this instanceof String
  102. ? ["'=="+ this +"'"].concat([].slice.call(arguments))
  103. : arguments);
  104. }
  105. , strongCutImgMinH;
  106. String.prototype.wcl = wcl;
  107. String.prototype.trim = function(s){var s = this ||s;
  108. return s.replace(/(^\s+|\s+$)/g,'')};
  109. if(win.opera || typeof GM_xmlhttpRequest ==u)
  110. GM_xmlhttpRequest = function(h){
  111. var xhr = new XMLHttpRequest();
  112. xhr.onreadystatechange = function(){
  113. var responseState ={
  114. responseXML: xhr.readyState==4 ? xhr.responseXML :''
  115. ,responseText: xhr.readyState==4 ? xhr.responseText :''
  116. ,readyState: xhr.readyState
  117. ,responseHeaders: xhr.readyState==4 ? xhr.getAllResponseHeaders() :''
  118. ,status: xhr.readyState==4 ? xhr.status : 0
  119. ,statusText: xhr.readyState==4 ? xhr.statusText :''
  120. }
  121. h.onreadystatechange && h.onreadystatechange(responseState);
  122. if(xhr.readyState==4){
  123. if(h.onload && xhr.status>=200 && xhr.status<300)
  124. h.onload(responseState);
  125. if(h.onerror && (xhr.status<200 || xhr.status>=300))
  126. h.onerror(responseState);
  127. }};
  128. try{//cannot do cross domain
  129. xhr.open(h.method, h.url);
  130. }catch(er){
  131. if(h.onerror) //simulate a real error
  132. h.onerror({responseXML:'',responseText:'',readyState:4,responseHeaders:'',status:403,statusText:'Forbidden'});
  133. return;
  134. }
  135. if(h.headers)
  136. for(var prop in h.headers)
  137. xhr.setRequestHeader(prop, h.headers[prop]);
  138. xhr.send((typeof(h.data) !=u) ? h.data : null);
  139. };
  140. try{ //для оповещения об ошибках в Fx
  141. var metaD = readMeta(metaTx, isFxScr) //metaTx == false ||'false'(строка) - если Fx|| строки метаданных
  142. ,gPlusFrame = alienFrame && /plusone/.test(location.host);
  143. win.adriver = function(){};
  144. win.adriver.domReadyQueue ={execute: function(){},Plugin: function(){this.a =1;}};
  145.  
  146. //===============================================
  147. //'testUScr'.wcl({isFxScr:isFxScr, unsafeWindow: typeof unsafeWindow !=u}); //win !==window при Greasemonkey|Scriptish
  148. if(!alienFrame){
  149. //alert(addEventListener)
  150. win.addEventListener('message', function(ev){ //слушать приход данных
  151. //'start_parse'.wcl(win.JSON , win.JSON.parse, win.JSON.decode)
  152. if(win.JSON && !win.JSON.parse && win.JSON.decode) win.JSON.parse = win.JSON.decode; //habr - old //опера требует этого внутри хендлера
  153. //'decode'.wcl(win.JSON , !win.JSON.parse , win.JSON.decode, win.JSON && !win.JSON.parse);
  154. if(/likes/.test(ev.data) && /frme/.test(ev.data) && win.JSON && win.JSON.parse){ //поставить лайки снаружи
  155. var n = JSON.parse(ev.data);
  156. if(n){
  157. //'parsed_data'.wcl(n);
  158. var frs = document.getElementsByTagName('iframe');
  159. for(var i in frs)
  160. if(frs[i].name == n.frme){
  161. frs[i].setAttribute('likes', n.likes);
  162. var x = frs[i].parentNode.parentNode.querySelector('.likes div div');
  163. x && (x.innerHTML = n.likes);
  164. }
  165. }
  166. }
  167. if(/\noperaEmbedMeta$/.test(ev.data) && win.JSON && win.JSON.parse){
  168. //alert(ev.data)
  169. var evt = document.createEvent('Event'); //генерировать для перехвата на приёме файла
  170. evt.initEvent('msg',!0,!0);
  171. evt.data = ev.data;
  172. win.dispatchEvent(evt);}
  173. },!1);
  174. }
  175. if(gPlusFrame){
  176. /**
  177. * evaluate script in window scope
  178. * @param{Function} fs function or string is body of function
  179. * @param{String|Array} s string or array of strings for arguments
  180. * @param{Boolean} noOnce not delete script after exec
  181. */
  182. var winEval = function(fs, s, noOnce){ //exec function/text in other scope
  183. s = (s ||[]) instanceof Array? s ||[] : [s]; //wrap by array
  184. alert(s +' '+ 'fs2')
  185. var fs2 = typeof fs=='function'
  186. ? (fs +'').replace(/(^\s*function\s*\([^\)]*\)\s*\{\s*|\s*\}\s*$)/g,'') //clean wrapper
  187. : fs
  188. ,as ='';
  189. for(var i =0, sL =s.length; i < sL; i++) //sequential array
  190. as += (i?',':'') +"'"+ s[i].replace(/'/g,"\\'").replace(/(\r\n|\r|\n)/g,"\\\n") +"'";
  191. fs = '(function(){'+ fs2 +'}).apply(window,['+ as +']);';
  192. //'fs'.wcl(fs, fs2)
  193. var d = document
  194. ,scr = d.createElement('script');
  195. scr.setAttribute('type','application/javascript');
  196. scr.textContent = fs;
  197. var dPlace = d.body || d.getElementsByTagName('head') && d.getElementsByTagName('head')[0];
  198. dPlace.appendChild(scr);
  199. if(!noOnce) dPlace.removeChild(scr);
  200. };
  201. /**
  202. * check occurrence of third-party event with growing interval
  203. * @constructor
  204. * @param{Number} t start period of check
  205. * @param{Number} i number of checks
  206. * @param{Number} m multiplier of period increment
  207. * @param{Function} check event condition
  208. * @param{Function} occur event handler
  209. */
  210. var Tout = function(h){
  211. var th = this;
  212. (function(){
  213. if((h.dat = h.check() )) //wait of positive result, then occcurense
  214. h.occur();
  215. else if(h.i-- >0) //next slower step
  216. th.ww = win.setTimeout(arguments.callee, (h.t *= h.m) );
  217. })();
  218. };
  219. new Tout({t:320, i:6, m: 1.6
  220. ,check: function(){
  221. return document && document.querySelector('#aggregateCount');
  222. }
  223. ,occur: function(){
  224. var id = location.hash.match(/(\?|#|&)id=([^&]+)/) //frame id [or name]
  225. ,w = win;
  226. id = id && id.length && id[2];
  227. var s = w.JSON && w.JSON.stringify && w.JSON.stringify( //must supported earlier
  228. {likes: this.dat.innerHTML, frme: id}) //data format
  229. ,pHost = (function(a){ //host extract from parameter (#|&)parent
  230. if(!a.match(/^https?\:\/\//)) return'';
  231. var b = document.createElement('a');
  232. b.href = a;
  233. b.pathname = b.search = b.hash ='';
  234. return b.href.replace(/\/\??\#?$/,'')
  235. })( decodeURIComponent( (w.location.href.match(/.*(\?|#|&)parent=([^&]+)/) ||[])[2] ||'') );
  236. try{
  237. if(!isChrome || w.parent && w.parent.postMessage){
  238. s && w.parent.postMessage(s, pHost); //all browsers except Chrome
  239. }else if(s)
  240. winEval(function(args){
  241. var w = window
  242. ,p1 = arguments[0]
  243. ,p2 = arguments[1];
  244. if(w.postMessage && p1 && w != w.parent){
  245. function wpm(){
  246. w.parent.postMessage(p1, p2); //msg with a glance Chrome bug
  247. }
  248. w.document.all ? w.setTimeout(wpm, 0) : wpm();
  249. }
  250. }, [s, pHost]);
  251. }catch(er){wcl(er)}
  252. }
  253. });
  254. }else if(alienFrame){ // для Оперы (только) в фрейме greasyfork.org - отправка метаданных
  255. document.addEventListener('DOMContentLoaded',function(){
  256. var dd = document.querySelector('pre')
  257. ,s = dd && dd.innerHTML;
  258. if(s && win.parent && win.parent.postMessage)
  259. win.parent.postMessage(s +'\noperaEmbedMeta', ROOT);
  260. },!1);
  261. } //(далее выполняется, если не в alienFrame)
  262. if(alienFrame) return;
  263. var setLocStor = function(name, hh){
  264. if(!localStorage) return;
  265. localStorage['habrAjax_'+ name] = JSON.stringify({h: hh});
  266. },
  267. getLocStor = function(name){
  268. return (JSON.parse(localStorage && localStorage['habrAjax_'+ name] ||'{}')).h;
  269. }
  270. ,removeLocStor = function(name){localStorage.removeItem('habrAjax_'+ name);}
  271. ,lh = location.href
  272. ,$q = function(q, f, f2, args){ // контекстный DOM-селектор или условная функция с ним: (elem)q | ((str)q, f, args) | ((str)q, elem) | ((str)q, (elem)context, f, args)
  273. var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelector(q);
  274. return f instanceof Function ? f && Q ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q
  275. : f2 instanceof Function ? f2 && Q ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q }
  276. ,$qA = function(q, f, f2, args){
  277. var Q = q && q.attributes && q || (!(f instanceof Function) && f||document).querySelectorAll(q);
  278. return f instanceof Function ? f && Q.length ? f.apply(Q, f2 instanceof Array && f2 || [f2]) : Q
  279. : f2 instanceof Function ? f2 && Q.length ? f2.apply(Q, args instanceof Array && args || [args]) : Q : Q }
  280. previButt = $q('#post_form .buttons input[name="preview"]')
  281. wwPrevi =0;
  282. previButt && previButt.addEventListener('click',function(ev){
  283. wcl('previclick');
  284. win.clearTimeout(wwPrevi);
  285. textContentPrev ='00';
  286. fillLetter();$pd(ev);
  287. },!1);
  288. var textContentPrev ='00'
  289. ,fillLetter = function(){ //сформировать письмо в ЛС
  290. var aLHash = lh.replace(/^[^#]*#/,'').split('&')
  291. ,hLHash ={}
  292. ,lStor = getLocStor('composeLetter')
  293. ,lStNoBq = lStor && !/<\/?blockquote>/.test(lStor.cite);
  294. if(/\/(add|edit)\//.test(lh)){ //страница редактирования (своей) статьи - по цитате
  295. var ta = $q('#text_textarea')
  296. ,cite = lStor && lStor.cite
  297. ,text = lStor && lStor.text
  298. ,textContentDiv = $q('#preview_placeholder .content');
  299. if(textContentDiv)
  300. var textContent = textContentDiv.innerHTML; //содержимое статьи
  301. if(ta && typeof cite !=u){
  302. var tVal = ta.value
  303. ,iS =[]
  304. ,cL = cite.length;
  305. for(var i =0, tL = tVal.length; i < tL; i++)
  306. if(tVal.substr(i, cL) == cite)
  307. iS.push(i); //все индексы вхождения строк
  308. 'cite'.wcl(iS, cite)
  309. if(iS.length){
  310. if(iS.length >1) //выделить найденное
  311. hN && hN.addNote(nSufRu(iS.length, ['образ','ец','ца','цов'])+' для правки; <a href=# data-match="'+ JSON.stringify(iS) +'" data-patrn="'+ cite.replace(/"/g,'&quot;') +'">следующий</a>',0,0,function(){
  312. var c1 = $q('a', this.o);
  313. c1.addEventListener('click', function(ev){
  314. var i = !c1.getAttribute('data-curr') ? 1: +c1.getAttribute('data-curr')
  315. ,a = JSON.parse(c1.getAttribute('data-match') )
  316. ,cite = c1.getAttribute('data-patrn');
  317. ta && ta.setSelectionRange && ta.setSelectionRange(a[i], a[i] + cite.length);
  318. c1.setAttribute('data-curr', (++i) % a.length);
  319. ta.blur();
  320. ta.focus();
  321. $pd(ev);
  322. },!1);
  323. });
  324. var i1 = iS[0];
  325. 'citeEnd0'.wcl(nSufRu(iS.length, ['образ','ец','ца','цов']) )
  326. ta && ta.setSelectionRange && ta.setSelectionRange(i1, i1 + cL);
  327. 'citeEnd'.wcl(iS, cite)
  328. }else
  329. hN && hN.addNote('не найдено образцов для правки');
  330. 'citeEnd1'.wcl(iS, cite)
  331. ta.focus();
  332. removeLocStor('composeLetter');
  333. }
  334. if(textContentPrev !='00'&& textContent != textContentPrev){ //обработать подгруженное
  335. 'renderOfAvaxTxt'.wcl(textContentPrev && textContentPrev.length, textContent && textContent.length)
  336. authorClicks(textContentDiv); //особые клики по авторам (напр. в фрейм)
  337. //blockBrs(textContentDiv); //сокращение верт.зазоров
  338. extLinks(textContentDiv); //ext.links и подписи к старым местным линкам
  339. handlImgViews(textContentDiv); //images
  340. byTextNodes(textContentDiv, haReplace); // --> XX
  341. //обработка выделения текста
  342. }else
  343. wwPrevi = win.setTimeout(fillLetter, 1499); //проверка обновлений cite
  344. if(textContentPrev =='00')
  345. textContentPrev = textContent;
  346. return;
  347. }
  348. 'conversations'.wcl(lStor, hLHash, lStNoBq, aLHash.length);
  349. if(aLHash[0] ==lh) aLHash =[];
  350. for(var i =0; i < aLHash.length; i++){
  351. var a = aLHash[i].split('=');
  352. hLHash[a[1]!==undefined && a[0]] = decodeURIComponent(a[1]!==undefined && a[1] || a[0]);
  353. }
  354. var fieldTo = $q('.conversation_page input[name="users-suggest"]')
  355. ,fieldTheme ='<b>Тема</b>: '
  356. ,fieldText = $q('#text_textarea');
  357. 'fieldTo'.wcl(fieldTo, fieldTheme, fieldText);
  358. fieldTo &&(fieldTo.value = hLHash.to && hLHash.to.trim() || lStor && lStor.to ||'');
  359. fieldTheme += hLHash.subj && hLHash.subj.trim()
  360. || (lStor ?(lStor.url ?'<a href="'+lStor.url+'">':'<i>')
  361. + lStor.subj +(lStor.url ?'</a>':'</i>'):'<i></i>')
  362. +(!hLHash.subj && lStor && lStor.date && lStor.subj ?' ('+ lStor.date +')':'');
  363.  
  364. if(fieldText) fieldText.value = (fieldTheme ? fieldTheme +'\n':'')
  365. + (aLHash.length && !(/^comment_\d+$/.test(aLHash[0])) && ( //по URL-параметрам
  366. hLHash.cite && ('<blockquote>'+ hLHash.cite +'</blockquote>') ||' '
  367. )|| (lStor ?( //по хранилищу, если нет URL-параметров
  368. (lStor.commId ?' # <a href='+ lStor.url +'#'+ lStor.commId +'>'+ lStor.commId +'</a> '
  369. +'@'+ lStor.commAuthor +'\n':'')
  370. +(lStNoBq?'<blockquote>':'')+ (lStor.cite ||'')
  371. +(lStor.commDate?' <i><font color=#999>('+lStor.commDate+')</font></i>':'')
  372. +(lStNoBq?'</blockquote>':'')
  373. +(lStor.text ? lStor.text :'')
  374. ):'') );
  375. 'lStor.cite'.wcl(lStor && '|'+lStor.cite+'|'+lStor.commAuthor)
  376. if(lStor && !aLHash.length && !lStor.noReceiver)
  377. removeLocStor('composeLetter');
  378. if(lStor && lStor.noReceiver){
  379. if(lStor && lStor.noReceiver ==2)
  380. delete lStor.noReceiver;
  381. 'lStor'.wcl(lStor)
  382. lStor.noReceiver =2;
  383. setLocStor('composeLetter', lStor);
  384. }
  385. if(fieldTo)
  386. fieldTo.focus(),fieldTo.select(); //выделен адресат для быстрой смены
  387. if(fieldText){
  388. fieldText.focus(); //в поле ввода текста
  389. /*var evt = document.createEvent("KeyEvents");
  390. evt.initKeyEvent('keyup',!0,!0, win,!1,!1,!1,!1, 40,0);
  391. fieldText.dispatchEvent(evt);*/
  392. }
  393. },
  394. nSufRu = function(n, vocab){ //числительные склонения слов ("день" и др.)
  395. var an = Math.abs(n)
  396. ,vocab = typeof vocab =='number'? [['д','ень','ня','ней']][vocab] : vocab;
  397. return n +' '+ vocab[0] + (an % 10 >0 && an % 10 <5 && Math.floor(an % 100 / 10) !=1
  398. ? (an % 10 ==1 ? vocab[1] : vocab[2]) : vocab[3]);
  399. };
  400. //===begin from Dollchan Extension Tools=== --группа функций просмотра изображений--
  401. var doc = win.document
  402. ,$pd = function(ev){ev.preventDefault();}
  403. ,$sp = function(ev){ev.stopPropagation();},$pdsp = function(ev){ev.preventDefault();ev.stopPropagation();}
  404. ,$dispTogl = function(el){el.style.display = el.style.display ==='none'?'':'none'; return el;}
  405. ,$offset = function(el){
  406. var box = el.getBoundingClientRect(), aa;
  407. 'offset'.wcl(aa={
  408. top: Math.round(box.top + win.pageYOffset),
  409. left: Math.round(box.left + win.pageXOffset) })
  410. return aa;
  411. },
  412. addFullImg = function(a, sz, x2, isExp){ //построение изображения по клику на ссылке
  413. x2 = x2 || 1;
  414. var newW =''
  415. ,newH =''
  416. ,fullW = x2* sz[0]
  417. ,fullH = x2* sz[1]
  418. ,scrW = doc.documentElement.clientWidth -10
  419. ,scrH = win.innerHeight -3
  420. ,isA = a.tagName =='A'
  421. ,full = isA ? $q('.de-img-full', a) : a.nextSibling;
  422. if(full && /de-img-full/.test(full.className) && isExp || !full && isExp === false)
  423. return;
  424. if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val && !$q('img[style*="fixed"]', a) )
  425. $dispTogl($q('img', a)); //TODO зкспериментально; отключено
  426. if(full && /de-img-full/.test(full.className)){
  427. if(full.moved)
  428. full.moved = false;
  429. else{
  430. $dispTogl(full);
  431. setTimeout(function(){full.parentNode.removeChild(full);},1);
  432. }
  433. return;
  434. }
  435. if(hS.viewImgs && hS.viewImgs.val && !hS.viewImgCenter.val)
  436. scrW -= $offset(a).left + 25; //TODO зкспериментально; отключено
  437. else{
  438. var el = $q('.de-img-center', doc);
  439. el && el.parentNode.removeChild(el);
  440. }
  441. if(fullW && fullH){
  442. newW = Math.min(fullW, scrW);
  443. newH = newW * fullH / fullW;
  444. if(hS.viewImgCenter.val && newH > scrH){
  445. newH = scrH;
  446. newW = newH * fullW / fullH;
  447. }
  448. if(newW/fullW < 1.13 && newW / fullW >0.88){
  449. newW = +fullW;
  450. newH = +fullH;
  451. var title = x2 +'00%';
  452. }
  453. }
  454. if(!title)
  455. title = Math.round(newW / fullW *100)* x2 +'%';
  456. var isViewUrl = !hS.addImgs.val && a.getAttribute('data-viewUrl')
  457. ,url = isA ? a.href : isViewUrl || (a.previousSibling && a.previousSibling.firstChild.src)|| a.src;
  458. if(/#\.jpg/.test(url) )
  459. url = a.firstChild.src;
  460. if(isViewUrl)
  461. title ='100%';
  462. var ht ='<img class="de-img-full" src="'+ url +'" alt="'+
  463. url +'" width="'+(isViewUrl ?'': Math.floor(newW))+'" height="'+(isViewUrl ?'': Math.floor(newH)) +'" title="'+ title +'">'
  464. if(a.insertAdjacentHTML)
  465. a.insertAdjacentHTML(isA ?'beforeend':'afterend', ht); //Fx8+
  466. else
  467. $e( $x(isA?{apT: a}:{aft: a}, {ht:ht}) ); //неточно, и ошибки в Fx3.6
  468. if(hS.viewImgCenter.val){
  469. var resizeImg = function(ev){ //обработчик колеса мыши - масштаб картинки
  470. var curX = ev.clientX
  471. ,curY = ev.clientY
  472. ,oldL = parseInt(this.style.left, 10)
  473. ,oldT = parseInt(this.style.top, 10)
  474. ,oldW = parseFloat(this.style.width || this.width)
  475. ,oldH = parseFloat(this.style.height || this.height)
  476. ,d = isFx ? -ev.detail : ev.wheelDelta
  477. ,newW = oldW * (d >0 ? 1.25 : 0.8)
  478. ,newH = oldH * (d >0 ? 1.25 : 0.8)
  479. ,sizes = full.getAttribute('data-sizes').split('x');
  480. if(newW/sizes[0] < 1.13 && newW / sizes[0] >0.88){
  481. newW = +sizes[0];
  482. newH = +sizes[1];
  483. this.title = x2 +'00%';
  484. }else
  485. this.title = Math.round(newW / fullW *100)* x2 +'%';
  486. $pd(ev);
  487. this.style.width = newW +'px';
  488. this.style.height = newH +'px';
  489. this.style.left = parseInt(curX - (newW/oldW) * (curX - oldL), 10) +'px';
  490. this.style.top = parseInt(curY - (newH/oldH) * (curY - oldT), 10) +'px';
  491. };
  492. full = $e({el: isA ? a.lastChild : a.nextSibling
  493. ,clAdd:'de-img-center'
  494. ,cs: {left: (scrW - newW)/2 +'px', top: (scrH - newH)/2 +'px'}
  495. ,at: {'data-sizes': fullW +'x'+ fullH}
  496. ,on: isFx ? {DOMMouseScroll: resizeImg}:{mousewheel: resizeImg}
  497. });
  498. !isA && full.addEventListener('click',function(ev){
  499. $pdsp(ev);
  500. if(full.moved)
  501. full.moved = false;
  502. else{
  503. $dispTogl(full);
  504. win.setTimeout(function(){full.parentNode && full.parentNode.removeChild(full);},1);
  505. }
  506. },!1);
  507. (function(el){ //makeMoveable --перетаскивание
  508. var elMove = function(ev){
  509. el.style.left = ev.clientX - el.curX +'px';
  510. el.style.top = ev.clientY - el.curY +'px';
  511. el.moved = true;
  512. },
  513. elStop = function(ev){
  514. var t = ev.target;
  515. $e({el: doc.body
  516. ,revent:{mousemove: elMove, mouseup: elStop}});
  517. if(ev.ctrlKey && t.parentNode.tagName=='A')
  518. t.parentNode.click(); //нативный клик вынесен под Ctrl+
  519. if((Math.abs(ev.clientX - el.startX) + Math.abs(ev.clientY - el.startY) ||0) <5 && ev.which ==1){
  520. $dispTogl(t);
  521. win.setTimeout(function(){t.parentNode.removeChild(t);},1);
  522. }
  523. };
  524. el.onmousedown = function(ev){
  525. $pd(ev);
  526. el.curX = (el.startX = ev.clientX) - parseInt(el.style.left, 10);
  527. el.curY = (el.startY = ev.clientY) - parseInt(el.style.top, 10);
  528. $e({el: doc.body
  529. ,on:{mousemove: elMove, mouseup: elStop}});
  530. };
  531. })(full);
  532. }
  533. },
  534. handlImgViews = function(el, selector){ //обработчики просмотров картинок
  535. 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"]'
  536. ,els = $qA(selector, el); //все ссылки на картинки
  537. //'handlImgViews'.wcl(el, selector, els )
  538. for(var i =0, linkImg; linkImg = els[i++];){ //подгрузка картинок в рамках до 200 на 200 по расширениям файлов в ссылках
  539. var a = linkImg.cloneNode(false)
  540. ,imgsInLink = $qA('img', linkImg);
  541. if(imgsInLink && imgsInLink.length !=1 && hS.addImgs.val){ //подгружать картинки-ссылки
  542. var lastLink = linkImg;
  543. $e({el:'img' //малая картинка со ссылкой перед найденной ссылкой
  544. ,cl:'de-img-pre'
  545. ,at:{src: a.href, alt: a.href.substr(0,200)}
  546. ,on:{load: function(){
  547. var t = this
  548. ,fullW = t.width
  549. ,fullH = t.height
  550. ,x2 = hS.viewX2.val && fullW *2 < win.innerHeight -3 ? 2:1; //признак "x2" - удваивать масштаб
  551. t.title = (x2 ==2 ?'/':'')+ fullW +'x'+ fullH;
  552. //'on:{load'.wcl(t.title, lastLink)
  553. if(lastLink.firstChild && lastLink.firstChild.tagName =='BUTTON'){var evt = document.createEvent('Event');evt.initEvent('loadImg',!0,!0); evt.data = t.title; win.dispatchEvent(evt);}
  554. t.style.cursor = x2 ?'ne-resize':'move';
  555. if(/^imgL$/.test(t.parentNode.className)|| t.parentNode.className =='lnk'){ //включить видимость копий, выключить - оригиналы ссылок
  556. t.parentNode.style.display ='inline-block';
  557. t.parentNode.nextSibling.style.display ='none';
  558. t.parentNode.title = t.title;
  559. if(t.parentNode.className =='lnk')
  560. t.parentNode.className ='lnk imgL';
  561. }else
  562. $dispTogl(t.parentNode);
  563. if(fullW <= 200 && fullH <= 200)
  564. return;
  565. var k = fullW/fullH;
  566. t.width = k < 1 ? 200 * k : 200;
  567. t.height = k < 1 ? 200 : 200/k;
  568. }},
  569. apT: $e({el: function(){
  570. var pImg = linkImg.previousSibling;
  571. if(pImg && pImg.className=='aPrevi imgL')
  572. pImg.parentNode.removeChild(pImg);
  573. pImg = linkImg.previousSibling;
  574. if(pImg && pImg.className=='aPrevi imgL')
  575. pImg.parentNode.removeChild(pImg);
  576. return $dispTogl(a);
  577. }
  578. ,at:{target:'_blank'}
  579. ,on:{click: function(ev){ //eventLinkImg(a);
  580. //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1)
  581. if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){
  582. if(ev.ctrlKey)
  583. return;
  584. $pd(ev);
  585. if(showImgMenu(ev, ev.currentTarget.frstChild) ) //по Shift+клик
  586. return;
  587. var titl = this.firstChild.title
  588. ,imgWH = titl.match(/(\d+)x(\d+)$/)
  589. ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2"
  590. if(imgWH && imgWH.length ==3)
  591. addFullImg(this, imgWH.slice(1), x2);
  592. }
  593. }}
  594. ,bef: linkImg
  595. })
  596. });
  597. }else //подготовка тамбнейла для просмотра по клику на нём ссылки
  598. imgsInLink && imgsInLink.length ==1 && $e({el: imgsInLink[0]
  599. ,clAdd:'de-img-thumb'
  600. ,at:{'data-viewUrl': linkImg.href} });
  601. }
  602. if(!(hS.viewImgs && hS.viewImgs.val) && !hS.viewImgCenter.val) //не просматривать картинки в странице
  603. return;
  604. for(var img, i =0, imgs = $qA('.content img:not(._noAddOwnView),.message img:not(._noAddOwnView),.message .text img:not(._noAddOwnView)', el); img = imgs[i++];){
  605. //'12'.wcl(img,img.width , img.height)
  606. if( (img.width >22 || img.height >22 || img.width==0 || img.height==0) && (!img.previousSibling || img.previousSibling && img.previousSibling.className !='de-img-hid') )
  607. (function(img){$e({el:'img' //полная картинка в невидимом диве с overflow
  608. ,cl:'_noAddOwnView'
  609. ,at:{src: hS.addImgs.val && img.getAttribute('data-viewUrl') || img.src}
  610. ,cs:{position:'absolute', left:'-9999px'}
  611. ,on:{load: function(ev){
  612. var fullW = this.width
  613. ,fullH = this.height;
  614. this.title = fullW +'x'+ fullH;
  615. $dispTogl(this.parentNode);
  616. //'WHBig'.wcl(fullW, img.width, fullH, img.height, img);
  617. if(fullW == img.width && fullH == img.height){
  618. img.style.cursor ='ne-resize';
  619. if(hS.viewX2.val)
  620. this.title = '/'+ this.title; //признак "x2" (особый курсор)
  621. }else if(!hS.viewX2.val){
  622. img.style.cursor ='move';
  623. img.setAttribute('data-view',1);
  624. }
  625. }},
  626. apT: img.previousSibling && img.previousSibling.className =='de-img-hid' && img.previousSibling || $e({cl:'de-img-hid'
  627. ,cs:{overflow:'hidden', width:0, height:'8px'}
  628. ,bef: img
  629. })
  630. }) })($e({el: img //обработчик и смена курсора картинки
  631. ,cs: hS.viewX2.val ?{cursor:'move'}:{}
  632. ,on:{click: function(ev){ //eventLinkImg(a);
  633. //'ev.button !==1'.wcl(ev.button,ev.button !==1, (hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1)
  634. var t = ev.currentTarget;
  635. if(!hS.viewX2.val && !t.getAttribute('data-view') )
  636. return; //не просматривать, если размер не изменится
  637. if((hS.viewImgs && hS.viewImgs.val || hS.viewImgCenter.val) && ev.button !==1){
  638. if(ev.ctrlKey)
  639. return;
  640. $pd(ev);
  641. if(showImgMenu(ev, t)) //по Shift+клик
  642. return;
  643. var titl = this.previousSibling.firstChild.title
  644. ,imgWH = titl.match(/(\d+)x(\d+)$/)
  645. ,x2 = titl.charAt(0)=='/'? 2:1; //признак "x2"
  646. if(imgWH && imgWH.length ==3)
  647. addFullImg(this, imgWH.slice(1), x2);
  648. }
  649. }}
  650. }));
  651. }
  652. },
  653. showImgMenu = function(ev, img){ //контекстное меню на картинке - поиск по изображению
  654. if(!ev.shiftKey) return;
  655. else{
  656. var srcD ={TinEye:{url:'tineye.com/search/?url='}
  657. ,Google:{url:'google.com/searchbyimage?image_url='}
  658. ,Yandex: {url:'images.yandex.ru/yandsearch?text=&rpt=imagedups&img_url='}
  659. ,SauceNAO:{url:'saucenao.com/search.php?url='}
  660. ,IQDB:{url:'iqdb.org/?url='} }
  661. ,srcMenu = $e({cl:'de-menu'
  662. ,on:{mouseout: function(){
  663. $dispTogl(srcMenu);
  664. win.setTimeout(function(){srcMenu.parentNode.removeChild(srcMenu);},1); }}
  665. ,cs:{left: ev.pageX -30 +'px', top: ev.pageY -24 +'px'}
  666. ,apT: doc.body
  667. });
  668. for(var i in srcD)
  669. $e({el:'A'
  670. ,cl:'de-src'
  671. ,at:{target:'_blank', href:'http://'+ srcD[i].url + img.src}
  672. ,ht:'<img src="http://'+ srcD[i].url.replace(/\/.*/,'') +'/favicon.ico"> '+ i
  673. ,on:{mouseout: function(ev){ $sp(ev);}}
  674. ,apT: srcMenu
  675. });
  676. }
  677. return 1;
  678. };//===end from Dollchan
  679. var allASCII = function(s){ //все символы строки - ASCII
  680. for(var i =0; i < s.length; i++)
  681. if(s.charCodeAt(i) >127)
  682. return !1;
  683. return!0;
  684. },
  685. $x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el;}, //===extend===
  686. $e = function(g){ //===создать или использовать имеющийся элемент===
  687. //g={el|clone,blck,elA,cl|(clAdd,clRemove),ht,cs,at,atRemove,on,revent,ap,apT,prT,bef,aft,f+fA}
  688. if(typeof g.el =='function') g.el = g.el.apply(g, g.elA);
  689. if(!g.el && g.el !==undefined && g.el !='') return g.el; //null|0|false
  690. 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';
  691. o = g.el = typeof o =='string'? /\W/.test(o) ? $q(o, g.blck) : document.createElement(o) : o;
  692. if(o){ //выполнять, если существует el или clone
  693. if(g.cl)
  694. o.className = g.cl;
  695. else{
  696. if(g.clAdd)
  697. o.classList.add(g.clAdd);
  698. if(g.clRemove)
  699. o.classList.remove(g.clRemove);}
  700. if(g.cs)
  701. $x(o.style, g.cs);
  702. if(g.ht || g.at){
  703. var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;}
  704. if(at)
  705. for(var i in at){
  706. if(i=='innerHTML') o[i] = at[i];
  707. else o.setAttribute(i, at[i]);}
  708. if(g.atRemove)
  709. for(var i in g.atRemove)
  710. o.removeAttribute(g.atRemove[i]);
  711. if(g.htT){ //подготовка шаблона
  712. if(!(typeof g.htTA =='object')) g.htTA =[g.htTA];
  713. for(var i in g.htTA)
  714. g.htT = g.htT.replace(RegExp('\\{\\{'+ i +'\\}\\}','g'), g.htTA[i])
  715. o.innerHTML = g.htT;}
  716. if(g.on)
  717. for(var i in g.on) if(g.on[i])
  718. o.addEventListener(i, g.on[i],!1);
  719. if(g.revent)
  720. for(var i in g.revent) if(g.revent[i])
  721. o.removeEventListener(i, g.revent[i],!1);
  722. if(g.ap){ //добавление нод
  723. if(g.ap instanceof Array){
  724. for(var i in g.ap) if(g.ap[i] && i !='length')
  725. o.appendChild(g.ap[i]);
  726. }else o.appendChild(g.ap);}
  727. g.apT && g.apT.appendChild(o);
  728. g.prT && (g.prT.firstChild
  729. ? g.prT.insertBefore(o, g.prT.firstChild)
  730. : g.prT.appendChild(o) );
  731. g.bef && g.bef.parentNode.insertBefore(o, g.bef);
  732. g.aft && (g.aft.nextSibling
  733. ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling)
  734. : g.aft.parentNode.appendChild(o) );
  735. g.remove && g.remove.parentNode.removeChild(g.remove);
  736. if(typeof g.f =='function')
  737. g.f.apply(g, g.fA); //this - это g
  738. }
  739. return o;
  740. /*
  741. var x=
  742. {cl: function(){o.className = g.cl;}
  743. ,clAdd: function(){o.classList.add(g.clAdd);}
  744. ,clRemove: function(){o.classList.remove(g.clRemove);}
  745. ,cs: function(){$x(o.style, g.cs);}
  746. ,ht: function(){var at = g.at ||{}; at.innerHTML = g.ht;}
  747. ,at: function(){var at = g.at ||{};
  748. for(var i in at){
  749. if(i=='innerHTML') o[i] = at[i];
  750. else o.setAttribute(i, at[i]);}}
  751. ,ap:function(){if(g.ap instanceof Array){
  752. for(var i in g.ap) if(g.ap[i] && i !='length')
  753. o.appendChild(g.ap[i]);
  754. }else o.appendChild(g.ap);}
  755. ,on:function(){for(var i in g.on) if(g.on[i])
  756. o.addEventListener(i, g.on[i],!1);}
  757. ,revent:function(){for(var i in g.revent) if(g.revent[i])
  758. o.removeEventListener(i, g.revent[i],!1);}
  759. ,apT:function(){g.apT.appendChild(o)}
  760. ,prT:function(){g.prT.firstChild
  761. ? g.prT.insertBefore(o, g.prT.firstChild)
  762. : g.prT.appendChild(o)}
  763. ,bef:function(){g.bef.parentNode.insertBefore(o, g.bef)}
  764. ,aft:function(){g.aft.nextSibling
  765. ? g.aft.parentNode.insertBefore(o, g.aft.nextSibling)
  766. : g.aft.parentNode.appendChild(o)}
  767. };
  768. for(var i in g) //проход по числу параметров, проп-о объёму задачи
  769. g[i] && x[i] && x[i]();*/
  770.  
  771. },
  772. addRules = function(css){
  773. if(typeof GM_addStyle !=u) GM_addStyle(css); //Fx,Chr
  774. else if(typeof addStyle !=u) addStyle(css);
  775. else{ //Op
  776. var heads = document.getElementsByTagName('head')
  777. ,node = $e({el:'style'
  778. ,apT: heads.length && heads[0]
  779. });
  780. node.appendChild(document.createTextNode(css)); //не проходит в Опере через $e
  781. }
  782. },
  783. getPosition = function(o){
  784. var x =0, y =0;
  785. while(o){
  786. x += o.offsetLeft ||0;
  787. y += o.offsetTop ||0;
  788. o = o.offsetParent || o.parentNode;
  789. }
  790. return {x:x, y:y};
  791. },
  792. parents = function(cl, elem){
  793. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.parentNode);
  794. return el;
  795. },
  796. parentsPrev = function(cl, elem){
  797. for(var el = elem, pr; el!=null && !RegExp(cl).test(el.className); el = el.parentNode)
  798. pr = el;
  799. el.prev = pr;
  800. return el;
  801. },
  802. prev = function(cl, elem){
  803. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.previousSibling);
  804. return el;
  805. },
  806. next = function(cl, elem){
  807. for(var el = elem; el!=null && !RegExp(cl).test(el.className); el = el.nextSibling); //el.className != cl
  808. return el;
  809. },
  810. evtChangeDom = function(voteA){ //===== сообщение о смене DOM, 'chgDom' ====
  811. var evt = document.createEvent("CustomEvent");
  812. if(evt && evt.initCustomEvent){ //TODO поддержку простых Event через хранилище или GM_setValue
  813. evt.initCustomEvent('chgDom',!0,!0, voteA);
  814. win.dispatchEvent(evt);
  815. return!0;
  816. }};
  817. if(/habrastorage\.org/.test(lh)){
  818. var hsoLogo = $q('.wrapper .header .logo'), hsoCloud = $q('.content #upload_cloud img');
  819. if(hsoLogo && hsoCloud){
  820. 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=';
  821.  
  822. $e({el:hsoLogo
  823. ,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}
  824. });
  825. }
  826. var testLegacyFrame =0;
  827. $e({ht:'<h2>&rarr; Перетащи картинку сюда &larr;</h2>(куда-нибудь в это окно)<br>К сожалению, будет работать только для картинок размером менее 10КБ. Держатели сайта знают, а работа по устранению недостатка через клиент &mdash; ведётся.'
  828. ,apT:$q('#bittonsHolder') });
  829. if(testLegacyFrame) $e({ht:'<iframe src='+ HSO.replace(/\/\/ha/,'//legacy.ha') +'>&rarr; Перетащи картинку сюда &larr;</h2>(куда-нибудь в это окно)'
  830. ,apT:$q('#bittonsHolder') });
  831. addRules('.logo{margin-bottom:0; margin-top: -90px}');
  832. var doDrop //для Chrome
  833. ,getKeyUser = function(){ alert(win.userKey +' '+ win.user); }
  834. ,listenDrag = function(win){ $e({el: win, on:{
  835. dragover: function(ev){hS.noConsole.val =0;'dragover'.wcl();doc.body.style.backgroundColor ='#e8e8f2'; $pdsp(ev);}
  836. ,mouseout: function(ev){doc.body.style.backgroundColor ='#fff';}
  837. ,dragend: function(){'dragend'.wcl();'dragend'.wcl(); return!1;}
  838. ,drop: doDrop = function(ev){'drop'.wcl('window.user');
  839. if(0&& isChrome){
  840. if(window.win != window){
  841. //winEval(getKeyUser);
  842. return;
  843. }
  844. win = window;
  845. }else
  846. $pdsp(ev);
  847. doc.body.style.backgroundColor ='#fff';
  848. if(isChrome) win = (function(){return this})();
  849. 'drop2'.wcl(win.user, win.userKey,win, win.unsafeWindow && unsafeWindow)
  850. if(win.user && win.user.length >0){
  851. var xhr = new XMLHttpRequest()
  852. ,file = ev.dataTransfer.files[0]
  853. ,uploadsCount =0
  854. ,formData = new FormData()
  855. ,reader = new FileReader();
  856. reader.readAsDataURL(file);
  857. reader.onload = function(ev){
  858. 'fileDrop-target'.wcl(ev.target, ev.target.result);
  859. };
  860. 'file'.wcl(file)
  861. xhr.open('POST', (!/legacy\.habrastorage\.org/.test(lh) ? HSO : HSO.replace(/\/\/ha/,'//legacy.ha') ) +'/uploadController/?username=' + win.user + '&userkey=' + win.userKey,!0);
  862. //formData.append('username', win.user);
  863. //formData.append('userkey', win.userKey);
  864. formData.append('Filedata', file);
  865. xhr.setRequestHeader('Origin', HSO);
  866. xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
  867. //xhr.setRequestHeader('Accept-Encoding', 'nogzip, deflate');
  868. xhr.send(formData);
  869. xhr.onreadystatechange = function(){
  870. if(xhr.readyState == 4 && xhr.status == 200){
  871. var mbJson = /\{/.test(xhr.responseText)
  872. ,answer = mbJson && JSON.parse(xhr.responseText)||{}
  873. ,upF = $q('#uploadedFiles'), upFI;
  874. $e({el: upFI = $q('#uploadedFilesItems')
  875. ,ht: upFI.innerHTML +(mbJson ?'<div class="uploaded-item">'
  876. +'<div class="uploaded-thumbnail"><label for="file-name-0"><img src="'
  877. + answer.crop +'" height="96" width="96" title="'+ answer.filename +', '
  878. + file.size +' байт"></label></div>'
  879. +'<div class="uploaded-url"><input size=37 onclick=this.select() value="'
  880. +'&lt;img src=&quot;'+ answer.url +'&quot;/&gt;" id="file-name-0" title="'
  881. + file.mozFullPath +'"><input size=35 onclick=this.select() value="'
  882. + answer.url +'" id="file-name-1" title="'+ file.lastModifiedDate +'"></div></div>': xhr.responseText)
  883. });
  884. upF.style.display ='block';
  885. $e({el:'#divStatus', ht:'Загружено: '+ ++uploadsCount, cs:{display:'block'} });
  886. 'message_0from_storage'.wcl(ev.data, win.parent,'<img src="'+ answer.url +'"/>');
  887. if(isChrome){ win = (function(){return this})();
  888. win.parent.postMessage('<img src="'+ answer.url +'"/>', ROOT);
  889. }else{
  890. wcl(answer.url)
  891. try{
  892. win.parent && win.parent.habraWYG && win.parent.habraWYG.insertTag(/*h.taSaved.el*/ $q('textarea'), '<img src="'+ answer.url +'"/>');
  893. }catch(er){'er'.wcl(er)}
  894. }
  895. }};
  896. }
  897. return!1;
  898. }} }) };
  899. if(0&& isChrome){
  900. //winEval(evtChangeDom,'window');
  901. ;//addEventListener('getWinJs', listenDrag,!1);
  902. }else
  903. listenDrag(win);
  904. }else
  905. win.addEventListener('message', function(ev){ //слушать сторадж для вставки тега в поле ввода
  906. //'message'.wcl(ev.origin);
  907. if(ev.origin !=HSO) return;
  908. 'message_from_storage'.wcl(ev.data);
  909. win.habraWYG.insertTag(/*h.taSaved.el*/ $q('textarea'), ev.data);
  910. },!1);
  911.  
  912. var h = {}
  913. ,hNE, hNCloseButt, hNCiteList,
  914. hN ={ //noteBar
  915. elem: hNE = $e({cl:'noteBar' //сервис замечаний и выделения текста
  916. ,cs: window.innerWidth <600 ?{left:'50px', maxWidth:'85%'}:''
  917. ,ap:[$e({cl:'closeButt'
  918. ,ht:'X'
  919. ,on:{click: function(ev){
  920. parents('^noteBar$', this).style.display ='none';
  921. var notes = $qA('.noteBar .notes .note');
  922. for(var i in notes)
  923. notes[i].parentNode && notes[i].parentNode.removeChild(notes[i]);
  924. }}
  925. })
  926. ,$e({cl:'delim'})
  927. ,hNCiteList = $e({cl:'list'})]
  928. ,apT: document.body})
  929. ,addNote: function(s, type, id, callb){ //==== добавить напоминание в бар ====
  930. var once = !type || type !='*'? 1:0; //noonce if type=='*'
  931. if(win.opera)
  932. $e({el: hNE, apT: document.body}); //т.к. при раннем старте не подгружается в .body
  933. var notes = $e({
  934. el: $q('.notes', hNE) ||''
  935. ,cl:'notes'
  936. ,bef: $q('.delim', hNE)
  937. });
  938. //'.notes'.wcl($q('.notes', hNE))
  939. $e({
  940. el: $q('#'+ (id ||'id0'), notes) ||''
  941. ,at:{id: id ||'id0'}
  942. ,ht:'<span style="color:#a76">('+(once ?'!':'*')+')</span> '+ s
  943. ,cl:'note' +(once?' once':'')
  944. ,apT: notes
  945. ,f: callb
  946. });
  947. hNE.style.display ='block';
  948. },
  949. retainView: function(){ //скрыть нотификатор, если внутри - только блоки однократного показа, + скрыть блоки однократного показа
  950. var t = this
  951. ,notes = $qA('.note', t.elem)
  952. ,noonce;
  953. //wcl(t.elem, notes.length, noonce)
  954. for(var i in notes){
  955. if(!/ once/.test(notes[i].className) && notes.length )
  956. noonce =1;
  957. else
  958. win.setTimeout(function(){notes[i].parentNode && notes[i].parentNode.removeChild(notes[i]);}, 99);
  959. //notes[i].style.display ='none';
  960. }
  961. //'noonce'.wcl(noonce)
  962. var selField = $q('.sele .selText', t.elem);
  963. selField && selField.parentNode.removeChild(selField);
  964. if(noonce) return;
  965. t.elem.style.display ='none';
  966. }
  967. },
  968. hideC2 = function(ev){ //скрыть содержание
  969. var topic = parents('^post($| )', this) || parents('^rotated_posts', this) //на контейнер статьи
  970. ,cont = $q('.content',topic)
  971. ,inln = / inln/.test(cont.className)
  972. ,c2 = $q('.content.c2',topic);
  973. if(/ n2/.test(this.className)) //подкрутка окна
  974. (isChrome?document.body:document.documentElement)['scrollTop'] -= c2.offsetHeight - this.getAttribute('rel') +12; //qa +3
  975. cont.style.display = inln?'inline':'block'; //показать начало статьи (до ката)
  976. if(inln)
  977. cont.className = cont.className.replace(/ content/,'')
  978. $q('.btnBack:not(.showComm)',topic).style.display //скрытие верхнего "Свернуть"
  979. = $q('.btnBack.n2',topic).style.display //скрытие нижнего "Свернуть"
  980. = c2.style.display ='none'; //скрыть полную статью
  981. if(isChrome){
  982. var info = $q('.infopanel', topic);
  983. info.style.top =(h.inZen?'-':'')+'3px';
  984. }
  985. },
  986. hideComm = function(ev){
  987. var topic = parents('^post($| )', this)
  988. ,c2 = $q('.comments.c2', topic);
  989. if(/ n2/.test(this.className)) //подкрутка окна
  990. (isChrome?document.body:document.documentElement)['scrollTop'] -= c2.offsetHeight - this.getAttribute('rel') +8; //QA -2, ес. не перед EV
  991. $q('.showComm.btnBack:not(.inln)', topic).style.display
  992. = $q('.comments.c2', topic).style.display
  993. = $q('.showComm.btnBack.n2', topic).style.display ='none';
  994. },
  995. addTaButtons = function(comms){ //добавление тегов в поле ввода
  996. var panels = $qA('.panel', comms.parentNode)
  997. ,topicAdd = $q('.topic_add') || $q('.qa_add');
  998. //'addTaButtons/comms,panels=='.wcl(comms, panels)
  999. if(panels && panels.length){
  1000. var win = (typeof unsafeWindow !=u)? unsafeWindow: (function(){return this})();
  1001. //в Хроме window не видно, => прих-ся переписывать или вызывать через DOM
  1002. if(!win.habraWYG) win.habraWYG ={};
  1003. win.habraWYG.insertTag = function(link, startTag, endTag){
  1004. var ta = $q('textarea', parents('editor', link));
  1005. endTag = endTag ||'';
  1006. if(ta){
  1007. ta.focus();
  1008. var scrtop = ta.scrollTop
  1009. ,cPos = ta.setSelectionRange
  1010. ?{start: ta.selectionStart, end: ta.selectionEnd}
  1011. :{start:0, end:0}
  1012. ,sTag = ta.value.substring(0, cPos.start)
  1013. + startTag + ta.value.substring(cPos.start, cPos.end) + endTag
  1014. ,newCPos = cPos.start == cPos.end
  1015. ? cPos.start + startTag.length
  1016. : sTag.length;
  1017. ta.value = sTag + ta.value.substring(cPos.end);
  1018. if(ta.selectionStart)
  1019. ta.setSelectionRange(newCPos, newCPos);
  1020. if(scrtop)
  1021. ta.scrollTop = scrtop;
  1022. }
  1023. return!1;
  1024. };
  1025. for(var i in panels){ if(panels[i] && panels[i].appendChild){
  1026. var panel = panels[i]
  1027. ,addBtn = function(tag, tag2, title, view, color, before){
  1028. 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:''});
  1029. };
  1030. addBtn('<blockquote>','</blockquote>','Цитата','Q&nbsp;').className ='spanned quot'; //цитата
  1031. var btnFo = addBtn('<font color=&quot;#223377&quot;>','</font>','Font color','F','a86'); //цветной текст
  1032. var pTmp;
  1033. for(var j in {blockquote:1, insertUser:2, insertSpoiler:3})
  1034. if(pTmp = $q('a[onclick*="'+ j +'"]', panel) )
  1035. pTmp.parentNode.removeChild(pTmp);
  1036. if(pTmp = $q('a[onclick*="insertHabracut"]', panel) )
  1037. pTmp.setAttribute('onclick','return habraWYG.insertTag(this,\'<habracut text=\"\',\'\">\')');
  1038. addBtn('<hh user=&quot;','&quot;/>','User','<img width=12 height=12 src=/i/bg-user2.gif alt=U style="padding:0"/>').className ='spanned user'; //юзер
  1039. addBtn('<spoiler title=&quot;&quot;>','</spoiler>','Спойлер','SP&nbsp;');
  1040. if(topicAdd)
  1041. addBtn('<h3>','</h3>','Заголовок','H3&nbsp;',null,1);
  1042. if(pTmp = $q('a[onclick*="insertLink"]', panel) ) //ссылка; упрощение "a href"
  1043. pTmp.setAttribute('onclick',"return habraWYG.insertTag(this, '<a href=\"\">','</a>');");
  1044. //'pTmp insertImage'.wcl($q('a[onclick*="insertImage"]'), panel) //картинка
  1045. if(pTmp = $q('a[onclick*="insertImage"]'), panel){ //упрощение IMG
  1046. 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>':'') );");
  1047. pTmp.title ='IMG (Shift: left; Ctrl: right; Shift+Ctrl: center)';
  1048. }
  1049. if($q('.g-icon-code', panel))
  1050. $e({el: $q('.g-icon-code', panel).parentNode
  1051. ,at:{onclick:"return habraWYG.insertTag(this, '<code>','</code>');", title:'code'}
  1052. ,cs:{cursor:'pointer'} });
  1053. if(!hS.tagsInput.val) return;
  1054. var hoverMenu = function(btn, ht, type, el){ //всплывание меню
  1055. for(var j =0; j < ht.length; j++)
  1056. ht[j] = ht[j] =='br'?'<br/>': ['<b>','<span>','<span style=color:#'+ ht[j] +'>'][type]
  1057. + ht[j] + ['</b>','</span>','</span>'][type];
  1058. var colrs,ww0,ww1;
  1059. $e({cl: ['langs','langs2','colrs'][type]
  1060. ,ht: ht.join('')
  1061. ,on:{mouseover: colrs=function(ev, ths){
  1062. var panelEcho = ev && parents('panel', ev.target) || ths; //ths - панель
  1063. var colrS = panelEcho && $qA('.'+['langs','langs2','colrs'][type], panelEcho);
  1064. if(ww0) win.clearTimeout(ww1);
  1065. if(ww1) win.clearTimeout(ww1);
  1066. if(colrS){
  1067. colrS[el &&(el-1) || 0].style.display = ev && ev.type=='mouseover'|| ev===0?'block':'none';
  1068. colrS[el &&(el-1) || 0].style.top = -colrS[el &&(el-1) || 0].offsetHeight +2 +'px';
  1069. }
  1070. },
  1071. mouseout: function(){win.clearTimeout(ww1);ww1 = win.setTimeout(function(){colrs(null, panel)}, 300)}
  1072. ,click: function(ev){return win.habraWYG.insertTag(ev.target, type <2
  1073. ?'<source lang="'+ ev.target.innerHTML.replace(/#/,'s') +'">\n'
  1074. :'<font color=#'+ ev.target.innerHTML.replace(/(.)/g,'$1$1') +'>'
  1075. ,type <2 ?'\n</source>':'</font>') }
  1076. }, apT: panel});
  1077. btn && btn.addEventListener('mouseover', colrs,!1);
  1078. btn && btn.addEventListener('mouseout', function(ev){ww1 = win.setTimeout(function(){colrs(null, panel)}, 300)},!1);
  1079. };
  1080. hoverMenu($q('.btn-dropdown ~.btn-dropdown', panel),('bash,lisp,scala,tex,dos,br,ruby,python,php,perl,br,'
  1081. +'xml,javascript,html,css,br,lua,java,cpp,c#,sql').split(','),0);
  1082. hoverMenu($q('a[onclick*="\'video\'"]', panel),('actionscript,apache,cmake,diff,vbscript,br'
  1083. +',coffeescript,django,delphi,erlang,erlang_repl,br'
  1084. +',haskell,go,matlab,mel,markdown,nginx,vala,br'
  1085. +',objectivec,vhdl,smalltalk,rust,axapta,1c').split(','),1);
  1086. hoverMenu($q('.quot', panel), ('000,003,006,009,00c,00f,300,303,306,309,30c,30f,br,'
  1087. +'030,033,036,039,03c,03f,330,333,336,339,33c,33f,br,'
  1088. +'060,063,066,069,06c,06f,360,363,366,369,36c,36f,br,'
  1089. +'090,093,096,099,09c,09f,390,393,396,399,39c,39f,br,'
  1090. +'0c0,0c3,0c6,0c9,0cc,0cf,3c0,3c3,3c6,3c9,3cc,3cf,br,'
  1091. +'0f0,0f3,0f6,0f9,0fc,0ff,3f0,3f3,3f6,3f9,3fc,3ff').split(','),2,1);
  1092. hoverMenu(btnFo, ('600,603,606,609,60c,60f,900,903,906,909,90c,90f,br,'
  1093. +'630,633,636,639,63c,63f,930,933,936,939,93c,93f,br,'
  1094. +'660,663,666,669,66c,66f,960,963,966,969,96c,96f,br,'
  1095. +'690,693,696,699,69c,69f,990,993,996,999,99c,99f,br,'
  1096. +'6c0,6c3,6c6,6c9,6cc,6cf,9c0,9c3,9c6,9c9,9cc,9cf,br,'
  1097. +'6f0,6f3,6f6,6f9,6fc,6ff,9f0,9f3,9f6,9f9,9fc,9ff').split(','),2,2);
  1098. hoverMenu($q('.user', panel), ('c00,c03,c06,c09,c0c,c0f,f00,f03,f06,f09,f0c,f0f,br,'
  1099. +'c30,c33,c36,c39,c3c,c3f,f30,f33,f36,f39,f3c,f3f,br,'
  1100. +'c60,c63,c66,c69,c6c,c6f,f60,f63,f66,f69,f6c,f6f,br,'
  1101. +'c90,c93,c96,c99,c9c,c9f,f90,f93,f96,f99,f9c,f9f,br,'
  1102. +'cc0,cc3,cc6,cc9,ccc,ccf,fc0,fc3,fc6,fc9,fcc,fcf,br,'
  1103. +'cf0,cf3,cf6,cf9,cfc,cff,ff0,ff3,ff6,ff9,ffc,fff').split(','),2,3);
  1104. }}
  1105. }
  1106. },
  1107. settOpera = function(i){
  1108. return i>1||win.opera ?', <a class="ope'+i+'" href="#note">примеч.для Оперы</a>':'';
  1109. },
  1110. getVersionDate = function(vv){if(vv){ //чтение версии из метаданных "@version version_date"
  1111. 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])[_\-\.]?(.*|$)/)
  1112. ,major, minor, date;
  1113. return {major: major = mVer && mVer[1] //версия - основная часть
  1114. ,minor: minor = mVer && mVer[5].replace(/^0+/,'') //минор-версия
  1115. ,version: major + (minor ?'.'+ minor :'')
  1116. ,date: date = mVer && mVer[2] +'-'+ (mVer[3].length <2 ?0:'') + mVer[3] +'-'+ (mVer[4].length <2 ?0:'') + mVer[4] //версия, дата выпуска
  1117. ,days: 1? Math.floor( (new Date() - new Date(date)) /DAY) :'--' //прошло дней
  1118. };
  1119. }else return {};};
  1120. if(typeof metaD !=u && !metaD.version) //для Firefox 3.6
  1121. metaD.version = /@version/.test(metaD[1]) && metaD[1].replace(/^[^\d]+/,'');
  1122. var verDat = getVersionDate(typeof metaD !=u && metaD.version)
  1123. ,hS ={ //настройки скрипта
  1124. 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>')
  1125. +'~ &mdash; версия; '+ verDat.date + ' &mdash; дата версии'
  1126. ,versionNumb: typeof metaD !=u && metaD.version && (metaD.version.replace(/\..*/,'') + metaD.version.replace(/(\.*?\d\d)\d+$/,'$1')) ||'???'
  1127. ,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'
  1128. ,chkUpdNoMinor:'~не уведомлять о <i style="color:#955" title="шаг подверсии не кратен 10">минорных версиях</i>~2012-03-05'
  1129. ,chkUpdPeriod: {val: 3, desc2:'(хранилище - период проверки обновлений, дней)'}
  1130. ,chkFailDate: {val: 0, desc2:'(хранилище - дата неуспешной проверки)'}
  1131. ,chkDate: {val:0, desc2:'дата последней проверки (вычисляемая)'}
  1132. ,noConsole:'1~без сообщений отладочной консоли wcl()~2011-12'
  1133. ,zenPresent:'0~подключены ли ВНЕШНИЕ стили ZenComment в <u>12-й Опере</u> (установить вручную)~2012-10-16'
  1134. //функции и оформление страницы
  1135. ,reformal:'1~<a href="http://habrajax.reformal.ru/" target="_blank" title="открыть в новом окне">идеи и замечания о скрипте</a> (reformal.ru)~2011-07'
  1136. ,inZen:'0~<i style="color:#955" title="встроенная версия стилей &mdash; @">встроенные в скрипт</i> стили <a href="'+ URLCSS +'" target="_blank" title="встроенная версия @; актуальная внешняя версия - в новом окне">ZenComment</a>~2011-08'
  1137. ,regimeNoZen:'1~режим комментариев "Компакт"/"Дзен"</i>~2011-11'
  1138. ,postsLinkNew:'1~сменить ссылку "Лента" на "Лента - новые"~2011-07'
  1139. ,allFeed:'0~-""- на "Все посты" (без компаний)~2012-04-25'
  1140. ,gooYa:'1~поиск Гугла и Яндекса по сайту~2011-10'
  1141. ,killToTop:'0~скрывание поля "Прокрутить наверх"~2012-06-10'
  1142. //оформление аннотаций в ленте
  1143. ,underCut:'1~подгружать статьи без перехода на новую страницу (хабр-аякс)~2011-05'
  1144. ,colorTopic:'1~подкраска переводов, топиков-ссылок, новостей, компаний~2011-08' //с удалением слов "Б.к."
  1145. ,toBK:'1~вид заголовков в ленте: размер шрифта, подсказка ссылки~2011-08'
  1146. ,shortenHub:'1~короткие хабы и компании (до 13 симв.)~2012-10-15'
  1147. ,noBK:'0~свернуть аннотации БК~2011-05'
  1148. ,noPodcast:'1~свернуть подкасты~2011-05'
  1149. ,noNews:'1~свернуть новости~2013-03-01'
  1150. ,listNewsAuthors: {val:'alizar,marks,aleksandrit,ilya42,FakeFactFelis,DaryaZ,mayuxi,shifttstas,wwakabobik,sharamyshara,Captcha,Mairon,ivansychev'.split(','), desc2:'(авторы-новостники)'},a:0
  1151. ,noEvent:'1~сворачивать события в ленте~2012-08-20'
  1152. ,noAuthor:'1~свернуть <a id="showNoAuthor" href="#">по списку авторов</a>~2012-01-15'
  1153. ,listNoAuthor: {val:'', desc2:'(хранилище списка авторов)'}
  1154. ,noContent:'0~свернуть <a id="showNoContent" href="#" title="могут быть регекспы без слешей по краям">по списку содержимого</a>~2012-01-15'
  1155. ,listNoContent: {val:'', desc2:'(хранилище списка тел регекспов для статей)'}
  1156. ,noSmart:'0~... <a id="showNoSmart" href="#" title="могут быть регекспы без слешей по краям">по признакам обзора смартфонов</a>~2013-09-17'
  1157. ,listNoSmart: {val:'Asha,Lumia,HTC,Jolla,Nexus,Alcatel,Xperia,Galaxy,китайс.{1,,33}смартф,LG.{1,,15}Optimus', desc2:'(хранилище списка тел регекспов для признаков обзоров смартфонов)'}
  1158. ,strongCut:'1~принудительный кат, <a href="#" id="strongCutBtn">до высоты</a>~2012-03-05~2012-01-15'
  1159. ,hStrongCut: {val: 120, desc2:'(макс. высота для аннотаций при "StrongCut")'}
  1160. //статья или вопрос и их оформление:
  1161. ,noTwit:'0~не показывать кнопки Твиттера~2011-06'
  1162. ,noVk:'0~не показывать кнопки ВК~2011-06'
  1163. ,noFb:'0~не показывать кнопки ФБ~2011-06'
  1164. ,noGP:'0~не показывать Г+-шаринг~2012-04-19'
  1165. ,gPlus:'0~лайки Google Plus'+settOpera(2)+'~2011-07'
  1166. //тексты статей и комментариев:
  1167. ,shortDates:'1~короткие даты текущего года~2011-09'
  1168. ,extLinks:'1~внешние ссылки &mdash; в новом окне~2012-09-03'
  1169. ,justify:'1~выравнивание колонок в статьях и ответах~2012-01-12'
  1170. //картинки в текстах:
  1171. ,viewImgCenter:'1~<u>просмотр картинок</u> в окне по центру~2013-01-21'
  1172. ,addImgs:'0~подгружать ссылки-картинки (увеличит траффик, будет переспрошено)~2013-01-20'
  1173. ,addImgsOK: 0 //для подтверждений addImgs (только =0)
  1174. ,viewX2:'1~смотреть увеличенные вдвое картинки~2013-01-17'
  1175. ,haReplace:'1~сокращение "хабра-" до "χ"~2012-09-03'
  1176. ,chtoBy:'0~исправление "что бы" на "чтобы"~2014-01-26'
  1177. //заголовок комментариев:
  1178. ,listAuthorsComms:'1~цвета активных комментаторов в начале~2011-09'
  1179. ,similarAfter:'1~похожие посты &mdash; в заголовке комментариев, в виде спадающего списка~2012-10-06'
  1180. ,shortSubscribe:'1~"слеж." вместо "отслеживать новые"~2012-07-22~2011-09'
  1181. ,commInfo:'1~навигатор по веткам комментариев~2012-11-17'
  1182. //отдельный комментарий/ответ:
  1183. ,noAva:'1~без аватаров в ответах~2011-11'
  1184. ,brAsBlock:'1~серые блоки в просветах на месте BR~2011-11'
  1185. ,noExpiredVote:'1~скрыть неактивные стрелки голосования~2012-01-08'
  1186. ,colorAuthorTopic:'0~пометки постов автора (цвет фуксии)~2011-09'
  1187. ,colorAuthorTAH:'1~то же, розовым фоном заголовка~2012-04-14'
  1188. ,colorStyle1:'1~расцветка сообщений по авторам (0/8 цв)~2012-10-22~2011-09'
  1189. ,colorStyle2:'1~расцветка авторов, 2-я часть (20/16 цв.)~2012-10-21'
  1190. ,shortReply:'1~сокращения кнопок "отв|ответ"~2011-08'
  1191. //ввод ответа в поле ввода:
  1192. ,tagsInput:'1~поле ввода &mdash; &lt;source> и &lt;font>~2012-10~2011-09'
  1193. ,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'
  1194. ,autoGrow:'1~авторост полей ввода textarea~2012-07-20'
  1195. ,contextSelect:'1~контекстные кнопки по выделению текста~2013-04-20'
  1196. ,correctCite:'0~контекстный цитатник-корректор [бета]~2012-04-15~2012-01'
  1197. ,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'
  1198. //сайдбар:
  1199. ,hideBest24:'0~скрыть блок "лучшее за 24"~2011-08'
  1200. ,hideDirectBand:'0~скрыть "прямой эфир"~2011-08'
  1201. ,hideEmploy:'0~скрыть "работу"~2012-10-13'
  1202. ,hideFreel:'0~скрыть "фрилансим"~2012-11-07'
  1203. ,hideEve:'0~скрыть блок "события". <i>Если скрыть все 5 и выключен "сайдбар под статьями"...</i>~2011-08'
  1204. ,sidebarDown:'0~сайдбар &mdash; под статьями~2011-08'
  1205. ,noAlienScripts:'1~подавление посторонних виджетов~2011-09'
  1206. ,noSomeSideBlocks:'1~без лишних боковых блоков~2012-10-13'
  1207. //Футер:
  1208. ,underFooter:'1~прибитый к низу футер~2012-09-07'
  1209. ,stru:{ //структурирование настроек и дописывание описаний
  1210.  
  1211. 'Настройки скрипта <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'
  1212. ,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> них. Но не имеется режима с полным отсутствием стилевых модификаций.'
  1213. ,descS:['Версии скрипта пишутся и обновляются, если на сайте произошло обновление, конфликтующее со скриптами, или если появилась новая функция в арсенале скрипта. В среднем получается, что обновляются версии довольно часто &mdash; раз в 5-15 дней.<br><br>Следить за обновлениями можно несколькими способами. Браузеры поддерживают <u>автообновление</u> и ручную проверку обновлений всех скриптов по кнопке.<br><br>HabrAjax имеет встроенную в скрипт <u>проверку обновлений</u>. 1 раз в сутки или реже, в 5 утра или позже он сравнивает версию в браузере с версией на сайте и сообщает, какие изменения произошли &mdash; причины обновления поясняются в специальном комментарии на 1-2 строчки.'
  1214. ,'Слежение скрипта за обновлениями на сайте. Не чаще раза в сутки, но если чтение не удалось, следующая попытка &mdash; через 15 минут. Кликом по ссылке &mdash; ручная проверка обновлений в любое время.'
  1215. ,'Версии, помеченные как минорные, не будут беспокоить сообщениями об обновлениях (на самом деле, <a href="'+HRU+'/post/175187/"target=_blank>механизм минорных версий</a> почти не используется, потому что редко, когда происходят невынужденные изменения скрипта &mdash; даже дополнения новых функций чаще идут вместе с исправлениями замеченных ошибок).'
  1216. ,'Не показывать сообщения отладочной консоли скрипта, которая постоянно используется для отладки и может выводить произвольную отладочную информацию, ненужную для пользователя.'
  1217. ,'Для Оперы 12: требуется установить вручную для корректной работы опознавателя стилей: установлены ли внешние стили ZenComment для сайта. Из-за того, что Опера 12 загружает стили очень рано, страница ещё не может знать этой информации, когда уже нужно делать некоторое форматирование со знанием про стили.']}
  1218. ,'функции и оформление страницы':{sett:'reformal,inZen,regimeNoZen,postsLinkNew,allFeed,gooYa,killToTop'
  1219. ,desc:'Группа настроек относится к почти каждой странице сайта, управляя общими элементами: стили, поля поиска, меню и т.д.'
  1220. ,descS:['Виджет сервиса замечаний и предложений отображается в виде кнопки, висящей справа на каждой странице. Впрочем, можно им пользоваться, переходя по ссылке из настроек, висение кнопки совершенно необязательно.'
  1221. ,'Стили, подгружаемые скриптом, появляются чуть позже (на 0.5-1 сек.), чем стили из Stylish, поэтому лучше включать через аддон Stylish, а здесь &mdash; только примерить для себя, удобны ли они.'
  1222. ,' "Компакт" менее зависим от мыши и отображается менее плотно, на белом фоне (рекомендуется). Чтобы работал режим "дзен", нужно поставить во внешних стилях пробел в 18-й строчке.<br><br>"Дзен" &mdash; это показ комментариев с минимумом лишней информации, на сером фоне страницы. Только имя комментатора и его текст. Существует 4 области размещения мыши, при которых в этом режиме появляется различная информация о комментариях. В целом, он излишне сложный для простого чтения.'
  1223. ,'Первая ссылка в меню сайта ведёт на "захабренные", но не все предпочитают этот режим показа ленты. Чтобы не ходить по цепочке ссылок каждый раз, просто ставим на первую ссылку ленту "Новые-все".'
  1224. ,'Как прежняя настройка, но лента &mdash; без вопросов и блогов компаний'
  1225. ,'К кнопке поиска по сайту добавляются 2 кнопки &mdash; поиск по сайту через Гугл и через Яндекс. Кроме того, смотреть результаты можно в 2-3 модификациях: фрейм половинной высоты, новое окно (Ctrl или Shift) или то же самое окно (только для местного поиска, если ввести Enter).<br><br>Поиск также выполняется через выделение текста и контекстные кнопки поиска (3 кнопки и их модификаторы Ctrl+клик).'
  1226. ,'Убрать навязчивую кнопку-колонку "Наверх". Актуально для неавторизованных, потому что у авторизованных пользователей имеется настройка пользователя для убирания этой кнопки.']}
  1227. ,'оформление аннотаций в ленте':{sett:'underCut,colorTopic,toBK,shortenHub,noBK,noPodcast,noNews,noEvent,noAuthor,noContent,noSmart,strongCut'
  1228. ,desc:'Аннотации (краткие описания) &mdash; это начала статей в списках статей и лентах, фрагменты результатов поиска.<br><br>Лент на сайте имеется несколько видов, и все они поддерживаются общими настройками из этого раздела.'
  1229. ,descS:['Аякс-подгрузка статей и комментариев.<br><br>Появляются дополнительные кнопки возле ссылки "Далее" и комментариев, которые приводят не к переходу, а к подгрузке страницы со статьёй и комментариями.<br><br>После просмотра статью или комментарии можно свернуть, кликнув по специальной широкой кнопке над или под текстом.'
  1230. ,'Фон заголовков особенных статей немного подкрашивается в различные оттенки.'
  1231. ,'Шрифт заголовка становится тем меньше, чем длиннее заголовок, что сбалансирует место, занимаемое слишком длинными названиями.'
  1232. ,'Сокращаются длинные названия компаний и хабов до 13 символов; остальное &mdash; в подсказку.'
  1233. ,'Статьи из блогов компаний сворачиваются до одного названия. Если кликнуть по нему и развернуть, далее показ статьи ничем не отличается от других, отличие &mdash; только в начальном показе лишь одного заголовка статьи в лените.'
  1234. ,'Сворачивание подкастов до видимости одного названия без аннотации.'
  1235. ,'Новости, распознанные по формальным признакам (принадлежат фиксированному в скрипте кругу авторов или не имеют текста под катом), <a href="'+HRU+'/post/168147/"target=_blank>сворачиваются в аннотациях до названия</a>. После клика ведут себя далее как обычные статьи.'
  1236. ,'События в ленте <a href="//toster.ru/q/23089/"target=_blank>сворачиваются до слова "ev"</a> и пустой строки, наведение на которую показывает всё название, а клик делает переход на страницу события.'
  1237. ,'Сворачивание статей по списку авторов, составленному читателем (запоминается в хранилище).'
  1238. ,'Сворачивание <a href="'+HRU+'/post/136301/"target=_blank>по ключевым словам и буквосочетаниям</a> в заголовках и в аннотациях.'
  1239. ,'то же - по признакам обзора смартфонов, составленному читателем (запоминается в хранилище)'
  1240. ,'<a href="'+HRU+'/post/136301/"target=_blank>Ограничение высоты аннотации</a> размером, заданным читателем (выбор по ссылке в настройках).<br><br>Указывается половинная высота блока, потому что она определяет размер (высоту) картинок, получающихся в этом режиме (по умолчанию &mdash; 120 для ZenComment и 170 (но пишется 120) для обычного HabrAjax). Картинки и видео уменьшаются и переносятся вправо или влево от потока текста. Кликом по картинке их можно просматривать в натуральном или увеличенном виде, если включена настройка просмотра картинок ("просмотр картинок в окне по центру").']}
  1241. ,'статья и её оформление':{sett:'noTwit,noVk,noFb,noGP,gPlus'
  1242. ,desc:'Стили и функции для текстов статей.<br><br>Из неотключаемого: дата, автор и автор оригинала (имеется при переводах) дублируются вверху и внизу статьи.'
  1243. ,descS:['Убирание социальных кнопок из подписей к статье: Твиттер'
  1244. ,'','','Убирание соцкнопки расшаривания в Гугл-плюс'
  1245. ,'Добавление кнопки, которой нет на сайте &mdash; <a href="'+HRU+'/post/124057/"target=_blank>лайк Гугл-плюса</a>. Позволяет смотреть, сколько лайков поставили статье читатели и ставить лайки самому, если авторизован в Г+. Выполняет подгрузку множества скриптов (50-100К на кнопку) с серверов Гугла.']}
  1246. ,'тексты статей и комментариев':{sett:'shortDates,extLinks,justify,viewImgCenter,addImgs,viewX2,haReplace,chtoBy'
  1247. ,desc:'действия, применяемые к текстам и картинкам; в отличие от прежней группы, эти настройки относятся не только к текстам статей'
  1248. ,descS:['Отображение дат укорачивается, оставаясь понятным и удобочитаемым: удаляется текущий год или год в датах последних 8 месяцев, добавляются дни недели (2 буквы) для всех дат, кроме "сегодня" и "вчера".'
  1249. ,'На все внешние ссылки ставит открывание в новом окне и специальный символ (двойная стрелка вправо-вверх) в конце ссылки.<br><br>Местные ссылки выдаются <u>с подсказками дат</u> (месяц и год ссылки). Даты вычисляются приблизительно, по номеру статьи или вопроса.'
  1250. ,'Колонка выравнивается стилем justify (левый и правый край текстов в колонке &mdash; ровный, пробелы в строке &mdash; переменной ширины).'
  1251. ,'<a href="'+HRU+'/post/166575/"target=_blank>Показывает картинки на сайте</a> на той же странице с возможностью перемещения и масштабирования (как в имаджбордах).<br><br>Shift+клик &mdash; меню поиска по картинкам на нескольких их сервисах.<br><br>Ctrl-клик — переход по ссылке с картинки.'
  1252. ,'Все ссылки, найденные с расширениями картинок, подгружаются и предварительно просматриваются в размере не более 200 пикс. Таких картинок могут быть многие мегабайты, поэтому на включение этой настройки в скрипте предусмотрено дополнительное подтверждение пользователем, происходящее один раз после установки настройки.'
  1253. ,'Картинки покажутся в удвоенном размере. Колесом мыши их можно и без того увеличить или уменьшить, но настройка нужна для комфортного начального просмотра в зависимости от монитора перед глазами.'
  1254. ,'Заменяет буквосочетания "хабр" греческими буквами "хи".'
  1255. ,'Заменяет грамматическую ошибку (большей частью) "что бы" на слитное написание.']}
  1256. ,'заголовок комментариев':{sett:'listAuthorsComms,similarAfter,shortSubscribe,commInfo'
  1257. ,desc:'Заголовок прячет и содержит ворох полезной информации: распределение популярности авторов комментариев, кнопка просмотра похожих статей, инфографика корневых веток комментариев. Кроме того, он сделан контрастным для лучшей распознаваемости в колонках длинных статей.'
  1258. ,descS:['Список авторов по количеству сделанных комментариев и раздача авторам цветов для расцветки их комментариев.'
  1259. ,'Из сайдбара сюда <a href="'+HRU+'/post/150954/"target=_blank>перенесены "Похожие посты"</a>. Можно отменить перенос и смотреть их традиционно, в сайдбаре.'
  1260. ,'сокращения слов, поясняющих назначения чекбоксов подписки на комментарии'
  1261. ,'Инфографика &mdash; навигатор по веткам комментариев. Показывает объёмы текстов, плюсов и минусов в ветках, ссылки и картинки в них. Появляется при наведении мыши на заголовок комментариев.']}
  1262. ,'отдельный комментарий':{sett:'noAva,brAsBlock,noExpiredVote,colorAuthorTopic,colorAuthorTAH,colorStyle1,colorStyle2,shortReply'
  1263. ,desc:'функции и стили для каждого комментария'
  1264. ,descS:['Аватары появляются при наведении мыши на место расположения аватара, а иначе &mdash; не отвлекают внимание. Размер аватара &mdash; 16х16, хотя на сайте они имеют больший размер.'
  1265. ,'Для более плотного расположения текстов комментариев и слитности комментариев одного человека из них убираются вертикальные пробелы, заменяясь небольшими серыми разделительными блоками высотой 3px, не занимающих высоты строки.'
  1266. ,'Там, где наличие стрелок голосования не имеет смысла, там они убраны, в том числе, с помощью стилей. Если стилей не установлено, можно отключать стрелки скриптом.'
  1267. ,'3 варианта выделения комментариев автора статьи или отключение выделения комментариев автора.<br><br>Первый чекбокс &mdash; выделяется фон под именем автора (площадь подсветки невелика, поэтому цвет фона &mdash; контрастный).'
  1268. ,'Выделение комментария автора статьи фоном заголовка комментария.'
  1269. ,'2 чекбокса &mdash; 4 варианта расцветки авторов комментариев, что, по идее, заменяет различение авторов по аватарам и по именам. по расцветкам видно, разные ли авторы участвуют в диалоге. (Кнопки "ответ" расцвечиваются теми же разными цветами.)<br><br>Если оба чекбокаса выключены, расцветки авторов нет. Если включен первый &mdash; используется палитра в 8 цветов. Они наиболее различимы, но слишком мало авторов выделяется своими цветами.'
  1270. ,'Второй чекбокс выбора палитр. Всего &mdash; 3 палитры: 8, 16 и 20 цветов или отключение расцветки.'
  1271. ,'Сокращения слов-кнопок "ответить". (Нужно для стилей ZenComment, потому что там эти кнопки располагаются вертикально и должны поместиться в высоту сообщения.)']}
  1272. ,'ввод ответа в поле ввода':{sett:'tagsInput,innerTab,autoGrow'
  1273. ,desc:'Ввод текстов &mdash; важные функции сайта, поэтому рядом настроек они сделаны более удобными.<br><br>Из ненастраиваемых: при вводе и редактировании статей размер поля ввода устанавливается размером с весь блок текста, но не более 80% высоты окна. Это же относится и ко всем остальным полям ввода, но более заметно на статьях, так как они обычно объёмны.<br><br>Перейти ко вводу текстов можно и через контекстные кнопки (включаются настройкой "контекстные кнопки"). Они помогают писать комментарии и цитировать прямо в контексте статьи или комментария, писать письма в ЛС, просто выделив цитату (автор определится сам или может быть изменён).<br><br>Для ввода статей модифицируются специфические кнопки: h3 &mdash; ввод тегов &lt;h3> для заголовков; атрибут text="" для ката; позиционирование рисунков слева, справа и по центру.'
  1274. ,descS:['Ввод <a href="'+HRU+'/post/141976/"target=_blank>кодов языков в теге Source</a>.<br>Всего можно указать 1 из более 40 языков для выбора подсветки ключевых слов. Для удобного выбора список языков разбит на 2 и показывается в виде дополнительных списков над баром кнопок.<br><br>Так же организованы и множество ссылок выбора цвета текста в теге FONT, разбитые на 3 подсписка.'
  1275. ,'Ctrl+пробел &mdash; вводится неразрывный пробел &amp;nbsp; в поле ввода. <br><br>Shift+Tab &mdash; вводится символ табуляции (обычно нужен для форматирования кодов программ).'
  1276. ,'Стилями отключена фиксация высоты поля ввода на сайте, поэтому всегда можно увеличить его вручную.<br><br>Но есть и <a href="'+HRU+'/post/148188/"target=_blank>автоматическое увеличение поля ввода</a> со вводом каждой новой строки (уменьшение не предусмотрено).<br><br>Работает для всех полей ввода текстов, кроме страниц настроек пользователя.']}
  1277. ,'контекстные кнопки':{sett:'contextSelect,correctCite,hQuotes'
  1278. ,desc:'Масса функций по вводу текстов добавляется при включении контекстных кнопок.<br><br>После выделения текста рядом с выделением появляется бледная полупрозрачная кнопка "<_>", а по наведению мыши на неё &mdash; остальные 9-15 кнопок-функций. Клик &mdash; выполнение. Модификатор &mdash; удержание Ctrl перед кликом.<br><br>Для правки собственных статей при выделении фрагмента собственной статьи (при условии авторизации на сайте) к контекстным кнопкам добавляется "<Е>", которая помогает <a href="'+HRU+'/post/177427/"target=_blank>редактировать свою статью</a> &mdash; выделяет цитату в поле ввода статьи в фрейме или новом окне.<br><br>Редактирование своей статьи работает и без фрейма, если выделение происходит на странице редактирования или создания статьи. Можно сделать несколько исправлений текста, переходя к фрагментам таким способом, прежде чем отправить его на сервер.'
  1279. ,descS:['Режим <a href="'+HRU+'/post/171777/"target=_blank>работы с контекстной кнопкой </a>"<_>", которая возникает после выделения текста на странице. По наведению мыши вокруг кнопки "<_>" появляются 9-15 других кнопок, помогающих в общении на сайте:<br> *) Ответ на комментарий прямо из места цитирования;<br>*) написание письма или переход к фрейму с формой написания письма автору статьи или комментария;<br>*) выбор имени автора из текста страницы, которому хочется написать письмо;<br>*) поиск по сайту;<br>*) редактирование собственных статей с переходом к месту редактирования.<br><br>Контекстное поле ввода и кнопки можно перемещать по странице перетаскиванием.'
  1280. ,'Функциональность "Корректора" &mdash; в стадии <a href="'+HRU+'/post/169761/"target=_blank>разработки</a>.'
  1281. ,'Быстро публикует копии интересных комментариев на стороннем сервисе, просто по выделению части комментария (опубликуется весь), или группы до 10. Достаточно 1 клика по кнопке "HQ". Успешность сообщается в примечании вверху окна, ссылка на публикацию &mdash; там же.']}
  1282. ,'сайдбар':{sett:'hideBest24,hideDirectBand,hideEmploy,hideFreel,hideEve,sidebarDown,noAlienScripts,noSomeSideBlocks'
  1283. ,desc:'Стилями ZenComment ширина сайдбара несколько уменьшена (до 26%), а настройками его можно вообще убрать или перенести вниз, что могло бы быть удобно на смартфонах и узких окнах менее 1000 пикселей. В зависимости от ширины окна применяется адаптивный дизайн &mdash; уменьшение отступов по краям, начиная с 640 пикс. и меньше. При более 1100 &mdash; наоборот, отступы размещаются несколько свободнее.<br><br>Имеется ненастраиваемая функция заполнения сайдбара блога компании, который обычно пуст, запомненным в прежней странице сайдбаром. Это сохраняет привычный для читателя баланс информации и ссылок справа.<br><br>Чтобы вернуть блок "Похожие посты" в сайдбар, отключают настройку "похожие посты и вопросы" в группе "заголовок комментариев". Сайдбар немного разрастётся, но названия статей будут перед глазами.'
  1284. ,descS:[' Скрывание различных блоков сайдбара. По настройке внизу &mdash; уже скрыты ненужные, остались 6, но и те можно выборочно скрыть.<br><br>Блок "Лучшее за 24 часа" полезен показом ссылок на наиболее популярные статьи за последние сутки. Скрипт <a href="http://spmbt.github.io/haPages/sidebarLive2Dailybest.htm">удаляет дублирующие ссылки</a> из блока "Что обсуждают", но переносит признак обсуждения (число комментариев) в "Лучшее".'
  1285. ,'Показывает самые последние комментарии и их авторов. Блок показывает активность комментаторов и существование статей, которые ещё не стали "Лучшими" за день, но на них отвечают. Обычно содержимое блока очень часто меняется (каждые несколько минут) и может рассматриваться как список случайных комментируемых статей.<br><br>Если дата статьи старее месяца, фон ссылки делается чуть более тёмным, подсвеченным, а в подсказке <a href="//toster.ru/q/23257/"target=_blank>появляется приблизительная дата</a>, вычисленная по номеру статьи или вопроса. (Каждый месяц данные о дате статей дополняются в скрипте вручную.) Выделение показывает, что ответили на старую статью, что бывает нечасто.'
  1286. ,'Если географическая локализованность предлагаемых работ или их тематика неинтересна читателю, есть смысл скрыть блок "Работа". Обычно в нём встречаются предложения из Москвы, Питера, Минска и намного реже &mdash; из других мест.'
  1287. ,'Если блок предложений по фрилансу неинтересен, он скрывается этой настройкой.'
  1288. ,'Если скрыть все 5 блоков и будет выключен "сайдбар под статьями", правый сайдбар будет скрыт; Из побочных эффектов &mdash; скрываются настройки ленты, которые бывают нужны.'
  1289. ,'Если "сайдбар под статьями", то настройки ленты не будут скрываться, а будут отображаться под статьями, лентами.<br><br>Для окон нормальной для десктопов ширины смысла переносить сайдбар особого нет &mdash; колонки становятся широкими и хуже читаемыми. Перенос полезен для окон смартфонов, ширин окна порядка 800 и меньше.'
  1290. ,'Подавление ненужных скриптов в сайдбаре, которые могут устанавливаться компаниями в рекламных целях или просто "потому что есть такая возможность".'
  1291. ,'Из всех блоков остаётся 5 наиболее полезных ("Похожие посты" в сайдбаре не считаются, так как перенесены скриптом в заголовок комментариев).']}
  1292. ,'футер':{sett:'underFooter'
  1293. ,desc:'В футере имеются ещё 3 неотключаемых и удобных функции: подгрузка для чтения 1 из 3 статей в футере, <a href="'+HRU+'/post/152055/"target=_blank>сбалансированное отображение названий</a> этих 3 ссылок, скрывание 4 постоянных ссылок на родственные ресурсы в футере.'
  1294. ,descS:['На коротких страницах располагает футер <a href="'+HRU+'/post/151320/"target=_blank>прилепленным к нижней кромке страницы</a>. В Хроме может работать некорректно, поэтому сделано отключаемым. ']}
  1295. ,desc2:'альтернативный способ просмотра настроек'
  1296.  
  1297. }
  1298. ,defa:{} //для сохр_дефолтных
  1299. ,get: function(ret){ try{ //если настройки записаны, они читаются; иначе используются данные из скрипта
  1300. var s = (function(){return this.GM_getValue('habrAjax_settings','{}')||{};})(); //this -- доступ к текущему window
  1301. if(s !=null && (function(){return this.JSON && JSON.parse;})()){
  1302. var saved = JSON.parse(s)
  1303. ,addSett =0;
  1304. if(ret)
  1305. return saved ||{};
  1306. for(var i in hS){
  1307. var sI = hS[i];
  1308. if(typeof sI !='function'&& typeof sI !='object'&& sI.length >9){
  1309. var sIA = sI.split('~')
  1310. ,vals =['val','desc','date','date0','noChrome'];
  1311. hS[i] ={};
  1312. for(var j =0; j < sIA.length;j++)
  1313. hS[i][vals[j]] = j || i =='version'? sIA[j] : +sIA[j];
  1314. }
  1315. if(sI.val) hS.defa[i] = sI.val;
  1316. }
  1317. if(typeof saved =='object'){
  1318. for(var i in saved){ var hSI = hS[i];
  1319. if(hSI && (hSI.val ===undefined || hSI.val ==-1) || typeof hSI ==u && i!='sHQ'){ //стереть, если настройки нет или пусто, или -1
  1320. delete saved[i];
  1321. addSett =1;
  1322. }
  1323. if(saved[i] !==undefined && i !='version'){
  1324. if(typeof hSI ==u)
  1325. hS[i] ={};
  1326. hS[i].val = saved[i]; //если настройка - другая, использовать из памяти
  1327. }
  1328. }
  1329. if(hS.addImgs && hS.addImgs.val && !saved.addImgsOK)
  1330. if(confirm('Включена настройка "Подгрузка рисунков",\nно не подтверждена. Согласны ли Вы\n'
  1331. +'с увеличением траффика за счёт подгрузки рисунков?')){
  1332. saved.addImgsOK =1; addSett =1;
  1333. }else
  1334. hS.addImgs.val =0;
  1335. if(!saved.a){
  1336. saved.a ={}; saved.a[nameGen()] = Math.floor(NOW/10e6); addSett =1;}
  1337. for(var i in saved.a){sHQ = sHQ.replace(/@/,i).replace(/@/,(saved.a[i]+'').substr(1));/*('sHQ_'+ saved.a[i]).wcl(i,hS);*/}
  1338. if(addSett)
  1339. hS.save(saved);
  1340. }
  1341. }
  1342. }catch(er){'!!err_getSettings()'.wcl(er +' '+ i, er.lineNumber||'')};
  1343. return hS;
  1344. },
  1345. init: function(){ //создать блок для настроек
  1346. var divSett = $e({cl:'habrAjaxSettings', apT: document.body}); //вывод настроек для просмотра
  1347. $e({el:'BUTTON'
  1348. ,cs:{position:'relative', padding:'0 2px'}
  1349. ,ht:'X'
  1350. ,at:{title:'Без сохранения'}
  1351. ,on:{click: hS.edit}
  1352. ,apT: $e({cs:{cssFloat:'right', margin:'-4px 2px 0 -8px', height:'1px'}, apT: divSett})
  1353. });
  1354. var dScroll = $e({cs:{maxHeight: win.innerHeight - 50 - 25 +'px', overflow:'auto', marginBottom:'2px', paddingBottom:'2px'}, apT: divSett }) //ограниченный по высоте див со скроллингом
  1355. ,sGroupS =[], groupI =0;
  1356. for(var i in hS.stru){ var hSSI = hS.stru[i]; //разброс описаний по массиву
  1357. if(hSSI.sett)
  1358. sGroupS.push({name: i, desc: hSSI.desc, settS: hSSI.sett.split(','), descS: hSSI.descS});
  1359. }
  1360. for(var i in hS){var hSI = hS[i];
  1361. //'hSI'.wcl(hSI && hSI.val !==undefined , hSI.desc !==undefined ,!(isChrome && hSI.noChrome), hSI )
  1362.  
  1363. if(hSI && hSI.val !==undefined && hSI.desc !==undefined //генерация списка настроек
  1364. && !(isChrome && hSI.noChrome)){
  1365. //поиск элемента в группах; если в новой группе - выводится заголовок
  1366. if(sGroupS[groupI])
  1367. for(var j =0, sL = sGroupS[groupI].settS.length; j < sL; j++){
  1368. var sGJ = sGroupS[groupI].settS[j];
  1369. if(i == sGJ){
  1370. var sGDJ = sGroupS[groupI].descS && sGroupS[groupI].descS[j];
  1371. //'sGJ, sGDJ'.wcl(sGJ, sGDJ)
  1372. break;}
  1373. if(j == sL -1){ //элемент не найден в текущей группе (группы джб синхронизированы)
  1374. j = -1;
  1375. groupI++;}
  1376. }
  1377. if(j ==0){ var sGI = sGroupS[groupI];
  1378. $e({ht: sGI.name +' ('+ sGI.settS.length +')' //вывод заголовка группы
  1379. ,cl:'group'
  1380. ,on:{mouseover: sGI.desc ? hView :'', mouseout: sGI.desc ? hViewHide :''}
  1381. ,at:{'data-hView': sGI.desc ||''}
  1382. ,apT: dScroll} );
  1383. }
  1384.  
  1385. var dSettingsLine = $e({cl:'sett'
  1386. ,on:{mouseover: sGDJ ? hView :'', mouseout: sGDJ ? hViewHide :''}
  1387. ,at:{'data-hView': sGDJ ||''}
  1388. ,apT: dScroll}) //элемент настройки
  1389. ,isNew = hSI.date && NOW - (new Date(hSI.date)) < 31*DAY + 20*DAY*(!/\-\d+\-/.test(hSI.date))
  1390. ,chk0 = $e({el:'SPAN'
  1391. ,cl: (isNew ?'latest':'')+(hSI.val ==0 ?' notChecked':'')
  1392. ,cs:{verticalAlign:'middle'}
  1393. ,apT: dSettingsLine })
  1394. ,no1_1 = hSI.val !=1 && hSI.val !=0 && hSI.val !=-1
  1395. ,chk = $e({el: no1_1 ?'I':'INPUT'
  1396. ,ht: no1_1 ? hSI.val :''
  1397. ,at:{type:'checkbox'
  1398. ,title: i +(hSI.date?', '+ hSI.date + (isNew?', новое':''):'')
  1399. ,id: i
  1400. ,rel: i}
  1401. ,apT: chk0 })
  1402. if(isNew)
  1403. chk.style.top = !win.opera ?'1px':0;
  1404. if(hSI.val ==-1) chk.setAttribute('disabled','disabled');
  1405. if(hSI.val ==1 || hSI.val ==0) chk.checked = hSI.val;
  1406.  
  1407. $e({el:'LABEL', at:{for: i}, ht: hSI.desc, apT: dSettingsLine});
  1408. }}
  1409. $e({el:'BUTTON', cs:{cssFloat:'right', marginRight:'6px', padding:'0 3px'}
  1410. ,ht:'>', at:{title:'экспорт/импорт/сброс'}
  1411. ,on:{'click': function(){
  1412. var c = hS.save(hS.get(1), 1)
  1413. ,s = prompt('Изменить/сохранить/стереть настройки HabrAjax', c);
  1414. if(s==null)
  1415. return;
  1416. if(s=='')
  1417. s='{}';
  1418. if(s != c){
  1419. hS.save(s); //c проверкой на синтаксис хеша
  1420. divSett.style.display ='none';
  1421. }
  1422. }}, apT: divSett});
  1423. $e({el:'BUTTON', ht:'Сохранить', at:{title:'Изменения вступят в силу после обновления страницы (F5)'}
  1424. , on:{click: hS.saveByHand}, apT: divSett});
  1425. $e({el:'BUTTON', ht:'Без сохранения', at:{title:'закрыть блок'}, on:{click: hS.edit}, apT: divSett});
  1426.  
  1427. for(i =1; i <= 2; i++){ //обработчики на "примеч. для Оперы"
  1428. var dQO = $q('.ope'+i, divSett);
  1429. dQO && dQO.addEventListener('click', function(){
  1430. hN.addNote('<b>Примечание по необходимым настройкам <span class="hlp">браузера Opera</span> для работы отдельных настроек юзерскрипта</b><br>'
  1431. +'&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>'
  1432. +'<div class="hlp"><b>1)</b> Чтобы стали отображаться <i><b>кнопки Google Plus</b> с количеством "лайков"</i> над кнопками, нужно прописать этот юзерскрипт (папку, в которой он расположен у вас на компьютере) <u>в настройках браузера</u> для сайта plusone.google.com:</div>'
  1433. +'<div class="hlp"><b>1:А)</b> Открыть "Инструменты &mdash; Общие настройки &mdash; Расширенные - Содержимое - Настройки для сайтов - Добавить - Сайт - (ввести: "plusone.google.com") - Скрипты - Папка пользовательских файлов Javascript - (установить: каталог, в котором расположен скрипт HabrAjax) - ОК - Закрыть - ОК;</div>'
  1434. +'<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>'
  1435. +'<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>'
  1436. +'&nbsp; &nbsp; Инструкция <a href="'+HRU+'/post/140643/">по установке юзерскриптов в Оперу</a>','*');
  1437. hNE.style.opacity =1;
  1438. },!1); }
  1439. return divSett;
  1440. },
  1441. edit: function(ev){ //показать список настроек
  1442. if(ev.ctrlKey ^ ev.shiftKey){
  1443. window.open(URLSCR + HAJAX,'_blank');return;}
  1444. var sett = $q('.habrAjaxSettings');
  1445. sett.style.display = sett.style.display !='block'?'block':'none';
  1446. $q('.habrAjaxSettings>div+div').style.maxHeight = win.innerHeight - 50 - 25 +'px';
  1447. if(ev.preventDefault) $pd(ev);
  1448. },
  1449. updSettings: function(hh){ //добавить|обновить настройки
  1450. var sSaved = hS.get(1);
  1451. for(var i in hh){
  1452. sSaved[i] = hh[i];
  1453. hS[i].val = hh[i];
  1454. }
  1455. hS.save(sSaved);
  1456. },
  1457. saveByHand: function(){ //сохранить из списка настроек
  1458. var oi = $qA('.habrAjaxSettings input')
  1459. ,s={}, key;
  1460. for(var i in oi){
  1461. key = oi[i].getAttribute && oi[i].getAttribute('rel');
  1462. if(!oi[i].disabled && key) //грузим только 0, 1 и не disabled
  1463. s[key] = oi[i].checked ?1:0;
  1464. }
  1465. var sSaved = hS.get(1) //сохранённое ранее
  1466. ,sNew ={};
  1467. if(typeof sSaved !='object') sSaved ={};
  1468. for(var i in hS) //сохранить все сгенерированные ранее сохранённые настройки
  1469. if(hS[i].desc2 && sSaved[i] !==undefined && hS[i] !==null)
  1470. s[i] = hS[i].val;
  1471. for(i in s) //сохранять ключи с отличными от прежних значениями или сохранённые ранее
  1472. if(s[i] != hS[i].val || sSaved[i] !==undefined)
  1473. sNew[i] = s[i];
  1474. sNew.version = this.versionNumb;
  1475. if(sNew.addImgs ==1)
  1476. sNew.addImgsOK = sSaved.addImgsOK;
  1477. hS.save(sNew);
  1478. $q('.habrAjaxSettings').style.display ='none';
  1479. hN.addNote('Изменения настроек вступят в силу после перезагрузки страницы (или при просмотре новых страниц в этом же браузере)', null,'chgSettings');
  1480. },
  1481. save: function(sett, ret){ try{ //запись настроек
  1482. if( (function(){return this.JSON && JSON.stringify && this.GM_setValue;})() ){
  1483. var s = (typeof sett =='string') && sett || JSON.stringify(sett);
  1484. if(!ret)
  1485. (function(){this.GM_setValue('habrAjax_settings', s);})();
  1486. else
  1487. return s;
  1488. }}catch(er){alert(er +' _saveSettings()')}
  1489. }
  1490. },
  1491. getDay = function(datArr, mon){return 'вспнвтсрчтптсб'.match(/../g)[new Date(datArr[3]
  1492. +'-'+(mon >8?'':0)+(mon +1)+'-'+(datArr[1]>9?'':0)+datArr[1]).getDay()];},
  1493. datesShorten = function(blck, dateSelect){ //переработка вида дат: не показывать текущий год или год за последние 8 месяцев
  1494. var dates = typeof blck=='string'?[{innerHTML:dates}]:$qA(dateSelect, blck) //(на вход - массив DOM-элементов с датами)
  1495. ,thYear = NOWdate.getFullYear()
  1496. ,thMonth = NOWdate.getMonth()
  1497. ,yestDate = new Date(NOW - DAY)
  1498. ,datMonth ={'января':0,'февраля':1,'марта':2,'апреля':3,'мая':4,'июня':5,'июля':6,'августа':7,'сентября':8,'октября':9,'ноября':10,'декабря':11}
  1499. ,monthName = function(m){
  1500. for(var i in datMonth)
  1501. if(datMonth[i] == m) return ' '+ i;
  1502. };
  1503. if(dates && dates.length)
  1504. for(var i in dates){ var dat = dates[i]; if(dat.innerHTML){
  1505. //парсинг дат
  1506. var datKBI = dat.attributes && ($q('.time_changed', dat) || $q('.changed', dat) );
  1507. if(datKBI){
  1508. datKBI.title = datKBI.innerHTML.replace(/( \(|\))/g,'');
  1509. datKBI.innerHTML ='(изм)';
  1510. }
  1511. var datFull = dat.innerHTML
  1512. ,datQaToday = /сегодня/.test(datFull)
  1513. ,datQaYest = /вчера/.test(datFull)
  1514. ,dateText = datFull.replace(/ в /,' ').replace(/(сегодня |вчера )/,'')
  1515. ,datArr = dateText.match(/(\d+)\s+([а-яё]+)\s+(\d{4})?/i)
  1516. ,mon = datArr && datMonth[datArr[2]]
  1517. if(datArr && !datArr[3])
  1518. datArr[3] = thYear;
  1519. var today = datQaToday || thYear == (datArr && datArr[3]) && thMonth == mon && NOWdate.getDate() == datArr[1]
  1520. ,todYest = today || datQaYest || datArr && (yestDate.getFullYear() == datArr[3] && yestDate.getMonth() == mon && yestDate.getDate() == datArr[1])
  1521. ,dateMon = datArr && (datArr[1]+' '+datArr[2]) || (today ? NOWdate.getDate() + monthName(thMonth) : yestDate.getDate() + monthName(yestDate.getMonth()))
  1522. ,day = datArr && !todYest ?','+ getDay(datArr, mon) : today ?'':',';
  1523. if(todYest)
  1524. dateText = dateText.replace(/(\d+)\s+([а-яё]+)\s*/i,'').replace(/$/, today ?'':'вчера');
  1525. if(datArr && (datArr[3] == thYear //текущий год
  1526. || Number(datArr[3]) +1 == thYear && mon && thMonth +12 <= mon +8 ) || todYest) //последние 8 мес
  1527. dateText = dateText.replace(/ ?\d{4}\s*/,'');
  1528. //'datesShorten'.wcl(dateText, dateText.length, datArr, NOWdate.getDate(), thYear)
  1529. dat.innerHTML = dateText.replace(/(.*?)(\d{1,2}:\d\d)(.*)/,'$2#$1$3').replace(/(#|$)/, day);
  1530. if(typeof blck=='string') return dat.innerHTML;
  1531. var dT = dat.getAttribute('datetime') ||''; // 2011-05-13T05:56:14+04:00
  1532. if(!dT)
  1533. dT = dat.title;
  1534. if(todYest)
  1535. dT +=' ';
  1536. if(dT)
  1537. dat.title = dT.replace(/\d*-\d*-\d*T/,'').replace(/:00$/,'').replace(/$/, todYest ?(dT.length >2?', ':'')+ dateMon :'');
  1538. }}
  1539. },
  1540. blockBrs = function(replyM){
  1541. var brs = $qA('br', replyM);
  1542. if(brs && brs.length){
  1543. var prevBR, prevPrevBR;
  1544. for(var j in brs){ if(brs[j].parentNode){ //BR -> DIV + нек.удаления BR в концах сообщ.
  1545. var brn = brs[j].nextSibling
  1546. ,brnn = brn ? brn.nextSibling :null;
  1547. //wcl(!prevBR , brn && brn.tagName =='BR', brnn && brnn.tagName, brn && brn.nodeValue =='\n', brnn && brnn.nextSibling
  1548. // && brnn.nextSibling.nodeValue);
  1549. if(!prevBR && brn && (brn.tagName =='BR'
  1550. || brnn && brnn.tagName =='BR' && brn.nodeValue =='\n' && brnn.nextSibling
  1551. && (!/^\s+$/.test(brnn.nextSibling.nodeValue) || brnn.nextSibling.nextSibling) ) ){
  1552. //wcl('val='+brn.nodeValue.charCodeAt(0)+' '+brn.nodeValue.charCodeAt(1)+' '+brn.nodeValue+' '+brnn.nextSibling.nodeValue)
  1553. prevBR =1;
  1554. $e({cl:'vSpace', bef: brs[j] });
  1555. brs[j].parentNode.removeChild(brs[j]);
  1556. }else{
  1557. var brp = brs[j].previousSibling;
  1558. //wcl(authorCommName, brp && brp.nodeValue, brp && brp.tagName, brn && !/^\s+$/.test(brn.nodeValue), brnn && !/^\s+$/.test(brnn.nodeValue));
  1559. var setV = !prevBR && (brn && !/^\s+$/.test(brn.nodeValue) || brnn && !/^\s+$/.test(brnn.nodeValue))
  1560. && 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');
  1561. if(setV && /powerCut/.test(replyM.className) && (brp.tagName =='IMG' || brp.className =='strongCutImgPlace') ){
  1562. brs[j].parentNode.removeChild(brs[j]);
  1563. //'brs[j].previousSibling'.wcl(brp)
  1564. }else if(setV){
  1565. $e({cl:'vSpace3', bef: brs[j] });
  1566. brs[j].parentNode.removeChild(brs[j]);
  1567. }else if(prevPrevBR)
  1568. brs[j].parentNode.removeChild(brs[j]);
  1569. }
  1570. prevPrevBR = prevBR;
  1571. prevBR =0;
  1572. }}
  1573. }
  1574. },
  1575. correctCommentsBefore = function(comms){ //коррекции комментариев в тексте HTML, после подгрузки
  1576. if(!hS.brAsBlock.val) return comms;
  1577. return (comms.replace(/<br\/>\r?\n?<br\/>(?!\s+<\/div>)/gm, '\n<div class="vSpace"></div>')
  1578. .replace(/<br\/>(?!\s+<\/div>)/gm, '\n<div class="vSpace3"></div>'));
  1579. },
  1580. correctCommentsAfter = function(comms, topic){ //коррекции в DOM после разворота комментов
  1581. //схема цветов: [colors:основные, pastelColors:пастельные, ge2Color:авторские, общие на оставшихся, общие пастельные, colorTAH:автора топика, colorTAHnew:новые от автора топика]
  1582. var scheme ={sch0:'ccc,ebc,ea8,ed8,cf9,9da,9ed,abe,ebe0f5'
  1583. ,sch1:'ccc,ebb,eed5bb,eeedbb,d4eebb,beb,a6dfc1,bee,bbd6ee,bbe,cec0dd,e7c9d9,f5e0e0,f5eae0,f5f5e0,eaf5e0,e0f5e1,d0eddf,e0f5f5,e0ebf5,ebe0f5'
  1584. ,sch2:'ccc,c88fa5,d79a89,a4c57d,78aa8e,dec3ce,edd4ce,d6e3c7,b7cec1,eedae2,f8e7e1,e8f1dd,d3e3da,f2ebee,fcf4f2,f5f9ef,eaf3ee,fbf4f6'},
  1585. pastel = function(colr){ //побледнение цвета
  1586. var pastelK = 0.64
  1587. ,s ='#';
  1588. colr = colr.substr(1).match(/../g);
  1589. for(var i in colr)
  1590. s += (function(x){return (Number(x) <= 9 ?'0':'')+ Number(x).toString(16)})
  1591. (255 - Math.floor((255 - parseInt(colr[i], 16)) * pastelK));
  1592. return s;
  1593. },
  1594. prepColors = function(colr){ //подготовка цветовой схемы //подсветки повторяющихся авторов (избранные цвета, по количеству ответов)
  1595. colr = (colr||'').split(',');
  1596. for(var i in colr){
  1597. var ci = colr[i];
  1598. if(i ==0) //контрастирование автора
  1599. ci = [ci,'eba2eb','f9ddec','f1d0f0'][hS.colorAuthorTAH.val *2 + hS.colorAuthorTopic.val]||[];
  1600. if(ci.length ==3)
  1601. ci = ci.replace(/(.)/g,'$1$1');
  1602. colr[i] ='#'+ ci;
  1603. pastelColors.push(pastel(colr[i]) );
  1604. }
  1605. return colr;
  1606. },
  1607. pastelColors =[]
  1608. ,authorColors = hS.colorStyle2.val *2 + hS.colorStyle1.val
  1609. ,colors = prepColors(scheme['sch'+ (authorColors -(authorColors?1:0)) ]) //цветовая схема (8/20/16 цветов)
  1610. //'pastelColors'.wcl(pastelColors)
  1611. ,ge2Color = colors[colors.length -1] //цвет кнопок для авторов без избранных цветов, но имеющих 2 и более ответа
  1612. ,pastelGe2Color = pastelColors[pastelColors.length -1]
  1613. ,c = comms, n =20, tp = topic
  1614. ,colorTAH ='#fee' //'#fdd' topicAuthorHighlight
  1615. ,colorTAHnew ='#f5ecf5' //'#efd9ef' topicAuthorHighlight New
  1616. ,oneLineHeight =25
  1617. ,newEntity = $q('.comment_item >.comment_body >.message', topic) //новая вёрстка комментариев
  1618. ,topicAuthor = $q('.post .infopanel .author a', topic) //===место автора топика
  1619. ,authorTopicName = topicAuthor ? topicAuthor.innerHTML :'(без автора)';
  1620. (function(s){
  1621. var replyMsgs = $qA('.message, .comment_item >span.text', c) //===сообщения - ответы
  1622. ,hght
  1623. ,authors =[{name: authorTopicName, n: 0}];
  1624. if(!replyMsgs || !replyMsgs.length)
  1625. replyMsgs = $qA('.comment_item', c);
  1626. for(var i in replyMsgs){if(replyMsgs[i].attributes){
  1627. var replyMI = replyMsgs[i]
  1628. ,replyMP = replyMI.parentNode
  1629. ,repInfo = replyMP && $q('.info', replyMP)
  1630. ,replyButt = replyMP && (next('^reply$', replyMI) || $q('a.reply_link',replyMP) || $q('a.reply',replyMP) ) //===поиск кнопки ответа
  1631. ,author = $q('a.username', replyMP); //===поиск автора сообщ.
  1632. if(author && $q('a', author))
  1633. author = $q('a', author);
  1634. var authorCommName = author && author.innerHTML ||'===';
  1635. //'author'.wcl(replyMP, author, replyButt)
  1636. hght = replyMI.offsetHeight;
  1637. if(!hght) continue;
  1638. s += hght ||0; //контроль генерации блока
  1639. if(authorColors){
  1640. if(replyButt && replyButt.tagName !='A')
  1641. replyButt = $q('a.reply_link',replyButt) || $q('a.reply',replyButt);
  1642. //'replyMI, replyButt'.wcl(replyMI, replyButt, replyMP)
  1643. //'BUTT'.wcl(replyButt, authorColors || hS.listAuthorsComms.val, replyMP.className)
  1644. if(!replyButt && authorColors && next('^reply$', replyMI)){ //для неавторизованных - фантомные "ответы" для подсветки кнопок
  1645. replyButt = $e({el:'.reply', blck: replyMP
  1646. ,ht:'<a class="reply_link" href="#" onclick="return!1">ответить</a>'});
  1647. //wcl('reply_fake')
  1648. }
  1649. for(var j = authors.length -1; j >=0; j--) //===сбор данных об авторах
  1650. if(authorCommName == authors[j].name){authors[j].n++; break;}
  1651. if(j < 0)
  1652. authors[authors.length] ={name: authorCommName, n: 1};
  1653. }
  1654. if(authorCommName == authorTopicName && (replyButt) ){ //===подсветка комментариев автора топика
  1655. if(hS.colorAuthorTAH.val){
  1656. repInfo.style.backgroundColor = /is_new/.test(repInfo.className) ? colorTAHnew : colorTAH;
  1657. repInfo.className +=' is_topicAuthor';
  1658. }
  1659. }
  1660. if(authorCommName == authorTopicName && hS.colorAuthorTopic.val){ //цвет авторов по частоте сообщений
  1661. author.style.backgroundColor = pastelColors[0] || pastelGe2Color;
  1662. //author.style.color ='#569';
  1663. if((newEntity) && /message/.test(replyMI.className)){
  1664. replyMI.style.borderLeftWidth ='4px';
  1665. replyMI.style.borderLeftStyle ='solid';
  1666. replyMI.style.marginLeft ='-4px';
  1667. replyMI.style.borderLeftColor = colors[0] || ge2Color;
  1668. }
  1669. }
  1670. if(replyMP)
  1671. var infoButt = prev('info', replyMI);
  1672. if(hS.noAva.val && infoButt) //не показывать уменьшенные аватары
  1673. $q('.avatar', infoButt).style.opacity =0;
  1674. //'replyMsgs'.wcl(replyMI, replyMsgs.length, i)
  1675. //'authorCommName,'.wcl(authorCommName, authors.length, j)
  1676. if(hS.brAsBlock.val) //замена BR и BR-BR на прослойки
  1677. blockBrs(replyMI);
  1678. if(replyButt)
  1679. replyButt.innerHTML = replyButt.innerHTML.replace(/(ответить|комментировать)/, hS.shortReply.val && hght < oneLineHeight ?'отв':'ответ'); //ес.одна строчка; меньше, чем примерно 18 пикс - сокращение высоты кнопок
  1680. //'offsetHeight'.wcl(hS.shortReply.val && replyMI.offsetHeight)
  1681. //=== точка "Каждый комментарий (свои и добавленные)" ===
  1682. byTextNodes(replyMI, haReplace); // обработка слов комментария
  1683. extLinks(replyMI);
  1684. }}
  1685. if(s < 20 && replyMsgs.length && --n >0){ win.setTimeout(arguments.callee, 200); return;} //ожидание генерации DOM-ветви TODO ош.с нулевой выс.
  1686. if(authorColors){ //===== раздача цветов =====
  1687. var k =1, s =' <tt style="background:'+ colors[0] +'" title="'+ authors[0].name +'">'+ authors[0].n +'</tt> '; //счёт цветов
  1688. for(i =1; i < authors.length; i++){ //раздача цветов по количеству сообщений - сортировка
  1689. var nMax =0, betterAuthor =0, aLen = authors.length;
  1690. for(j =0; j < aLen; j++)
  1691. if(authors[j].n > nMax && !authors[j].choice && authors[j].name != authorTopicName){
  1692. nMax = authors[j].n;
  1693. betterAuthor = j;
  1694. }
  1695. authors[betterAuthor].color = colors[k];
  1696. authors[betterAuthor].pColor = pastelColors[k];
  1697. s +='<tt style="background:'+ (colors[k] || (authors[betterAuthor].n >=2 ? ge2Color :'#f2f2f2'))
  1698. +'" title="'+ authors[betterAuthor].name +'">'+ authors[betterAuthor].n +'</tt> ';
  1699. authors[betterAuthor].choice = k++; //выбран наибольший параметр "n" из оставшихся
  1700. if(k >= colors.length +3) break; //ограничение по длине списка
  1701. }
  1702. s +=(authors.length > colors.length +3 ?'<i>...</i>':'')+'<tt>('+ authors.length +')</tt>';
  1703. authors[0].color = colors[0];
  1704. authors[0].pColor = pastelColors[0];
  1705. //for(i =0; i < authors.length; i++)
  1706. // 'authors'.wcl(authors[i].n+' '+authors[i].name+' '+(authors[i].choice||''))
  1707. for(i in replyMsgs){ //2-й проход и расстановка цветов
  1708. var replyMI = replyMsgs[i]
  1709. ,replyMP = replyMI.parentNode;
  1710. //'replyMp'.wcl(replyMP, i)
  1711. if(!replyMP) continue;
  1712. var author = newEntity && $q('a.username', replyMP); //===поиск автора сообщ.
  1713. if(author && $q('a', author))
  1714. author = $q('a', author);
  1715. var authorCommName = author && author.innerHTML ||'===';
  1716. //'author.innerHTML'.wcl(author && author.innerHTML, authors.length)
  1717. if(!hS.colorAuthorTopic.val)
  1718. authors[0].color = colorTAH;
  1719. for(var j = authors.length -1; j >=0; j--){ //счёт всех авторов
  1720. //'=='.wcl(j, authorCommName == authors[j].name , (authors[j].choice || authors[j].n >=2))
  1721. if(authorCommName == authors[j].name && (authors[j].choice || authors[j].n >=2)){ //...и избранный цвет
  1722. var replyButt = replyMP && (next('^reply$', replyMI) || $q('a.reply_link',replyMP) || $q('a.reply',replyMP) );
  1723. //'replyButt'.wcl(replyButt, authorCommName)
  1724. if(replyButt && replyButt.tagName !='A')
  1725. replyButt = $q('a.reply_link',replyButt) || $q('a.reply',replyButt);
  1726. if(replyButt)
  1727. replyButt.style.backgroundColor = authors[j].color || ge2Color;
  1728. if(author){ //цвет авторов по частоте сообщений
  1729. author.style.backgroundColor = (author.parentNode.className=='info'? authors[j].color : authors[j].pColor) || ge2Color;
  1730. }
  1731. var isMsg = /message/.test(replyMI.className);
  1732. if(isMsg){
  1733. replyMI.style.borderLeftStyle ='solid';
  1734. replyMI.style.marginLeft ='-4px';
  1735. }
  1736. replyMI.style.borderLeftColor = authors[j].pColor || ge2Color;
  1737. replyMI.style.borderLeftWidth ='4px';
  1738. break;
  1739. }
  1740. }
  1741. }
  1742. }
  1743. var o = $q('.comments_list .title', tp) || $q('.comments.c2 .title', tp)
  1744. ,oL = o && $q('label', o)
  1745. ,oL2 = o && $q('label + label', o);
  1746.  
  1747. if(hS.shortSubscribe.val && oL){ //укорочение надписи "подписаться на комментарии"
  1748. oL.title ='следить за новыми комментариями через почту';
  1749. var aChilds = oL2 && oL.parentNode.childNodes || oL.childNodes;
  1750. for(var i=0; i < aChilds.length; i++)
  1751. if(/(подпи|отсл)/.test(aChilds[i].nodeValue)) aChilds[i].nodeValue ='слеж.';
  1752. for(var i=0; i < oL.childNodes.length; i++)
  1753. if(/почт/.test(oL.childNodes[i].nodeValue)) oL.childNodes[i].nodeValue ='';
  1754. if(oL2){
  1755. oL2.title ='... через трекер';
  1756. for(var i=0; i < oL2.childNodes.length; i++)
  1757. if(/трек/.test(oL2.childNodes[i].nodeValue)) oL2.childNodes[i].nodeValue ='';
  1758. oL2.style.paddingRight ='6px';
  1759. }
  1760. }
  1761. if(hS.listAuthorsComms.val)
  1762. $e({el:'TT', ht: s, apT: o}); //активные комментаторы (с цветами, в заголовке комментариев)
  1763. if(hS.commInfo && hS.commInfo.val){ //=== навигатор по веткам комментариев ===
  1764. var isMail = /\/conversations\//.test(lh)
  1765. ,commInfo = $e({cl:'commInfo', prT: $q('.title', isMail ? c.parentNode : c)})
  1766. ,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)
  1767. ,branch ={linksTo:[]};
  1768. if(comRoots.length){
  1769. for(var i in comRoots){ var cRI = comRoots[i]; if(cRI.attributes){ //по корневым веткам
  1770. var nCom = $qA('.info', isMail ? cRI.parentNode : cRI.parentNode.parentNode) //число ответов в корневой ветке
  1771. ,nP =0
  1772. ,nM =0
  1773. ,nSym =''
  1774. ,hash = cRI.getAttribute('rel') //якорь корневого коммента
  1775. ,linksRoot = $e({cl:'links root'})
  1776. ,imgsRoot = $e({cl:'imgs root'})
  1777. ,nImg =0
  1778. ,hrf = hash ?'#comment_'+ hash :'#comments';
  1779. for(var j in branch.linksTo){
  1780. $e({el:'a'
  1781. ,cl:'nx branch'
  1782. ,ht:'>'
  1783. ,at:{href: hrf, title:'следующая ветка'}
  1784. ,aft: branch.linksTo[j]
  1785. });
  1786. }
  1787. //'nCom'.wcl(nCom.length, cRI)
  1788. branch.linksTo =[];
  1789. for(var j in nCom){ var nCJ = nCom[j]; if(nCJ.attributes){ //по комментам
  1790. var nCJS = $q('.mark .score', nCJ);
  1791. if(nCJS){
  1792. var nS = nCJS.title && nCJS.title.match(/\d+/g);
  1793. if(nS.length ==3){
  1794. nP += Number(nS[1]);
  1795. nM += Number(nS[2]);
  1796. }}
  1797. var msg = $q(isMail?'.text':'.message', nCJ.parentNode);
  1798. if(msg){
  1799. nSym += msg.innerHTML;
  1800. var kLnk = $qA('a', msg) //подсписок ссылок
  1801. ,kImg = $qA('img:not(._noAddOwnView)', msg); //подсписок рисунков
  1802. for(var k in kLnk){ var kLK = kLnk[k]; if(kLK.attributes){ //ссылки
  1803. if(!$q('img:not(._noAddOwnView)', kLK) )
  1804. $e({el:'a', cl:'lnk'
  1805. ,at:{title: kLK.href.replace(/^https?:\/\/(habrahabr\.ru)?/,'')
  1806. ,href: kLK.href, target:'_blank'}
  1807. ,apT: linksRoot});
  1808. }}
  1809. for(var k in kImg){ var kIK = kImg[k]; if(kIK.attributes){ //рисунки
  1810. if(kIK.parentNode.tagName !='A')
  1811. $e({el:'a', cl:'imgL'
  1812. ,at:{href: kIK.src, target:'_blank'}
  1813. ,apT: imgsRoot});
  1814. else //рисунок с внешней ссылкой
  1815. $e({el:'a', cl:'imgLink'
  1816. ,at:{href: kIK.parentNode.href, target:'_blank'}
  1817. ,apT: imgsRoot});
  1818. nImg++;
  1819. }}
  1820. }
  1821. var toPar = $q('time', nCJ);
  1822. if(!toPar)
  1823. toPar = $q('.to_parent', nCJ);
  1824. if(!toPar)
  1825. toPar = $q('.to_chidren', nCJ);
  1826. if(toPar && hash){ //переход к предыдущей ветке - кнопка
  1827. if(branch.href)
  1828. branch.linksTo.push( $e({el:'a'
  1829. ,cl:'prv branch'
  1830. ,ht:'<'
  1831. ,at:{href: branch.href, title:'предыдущая ветка'}
  1832. ,aft: toPar
  1833. }) );
  1834. }
  1835. }}
  1836. branch.href = hrf;
  1837. if(nImg==0)
  1838. imgsRoot.style.display ='none';
  1839. var overLink = $e({cl:'overLink', apT: commInfo})
  1840. ,hLnk ={el:'a', cl:'root'
  1841. ,at:{href: hrf}
  1842. ,apT: overLink }
  1843. ,nVLink = $e(hLnk) // N's-Votes-link
  1844. ,pMLink = $e(hLnk); //plus-minus-link
  1845. $e({el: linksRoot, apT: overLink});
  1846. $e({el: imgsRoot, apT: overLink});
  1847. if(comRoots.length ==1 && nCom.length ==0)
  1848. break;
  1849. if(nP !=0 || nM !=0){ //минусы +плюсы
  1850. var pluses = boxBuild(nP,'nP',pMLink,'+')
  1851. ,minuses = boxBuild(nM,'nM',pMLink,'-');
  1852. //'m-p'.wcl(parseInt(minuses.style.width), parseInt(pluses.style.width))
  1853. if(parseInt(minuses.style.width) + parseInt(pluses.style.width) > 43){
  1854. var hP = parseInt(pluses.style.height)
  1855. ,hM = parseInt(minuses.style.height)
  1856. minuses.style.marginBottom ='-'+ (hM -3) +'px';
  1857. if(hM - hP -3 >0)
  1858. pluses.style.marginBottom = (hM - hP -3) +'px';
  1859. pMLink.style.lineHeight =overLink.style.lineHeight ='4px';
  1860. }
  1861. }else
  1862. pMLink.style.display ='none';
  1863. //сообщения + объём
  1864. var strings = boxBuild(Math.floor((nSym.length +75)/150),'nLin',nVLink,'"длинных строк" '); //вставка блока графики по объёму байтов
  1865. var msgs = boxBuild(nCom.length,'nCom',nVLink,'Сообщений в ветке: '); //--по числу ответов в ветви
  1866. //'strings'.wcl(parseInt(strings.style.width), parseInt(msgs.style.width))
  1867. if(parseInt(strings.style.width) + parseInt(msgs.style.width) > 43 -4){
  1868. msgs.style.marginBottom ='-'+ (parseInt(msgs.style.height) -3) +'px';
  1869. nVLink.style.lineHeight = overLink.style.lineHeight ='4px';
  1870. }
  1871. if(i==0){ //общий счётчик
  1872. 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';
  1873. overLink.style.marginBottom ='22px';
  1874. nVLink.style.verticalAlign = pMLink.style.verticalAlign
  1875. = linksRoot.style.verticalAlign= imgsRoot.style.verticalAlign ='bottom';
  1876. overLink.title ='комментариев: число, объём (160-симв. строк), минусов, плюсов, ссылки, рисунки';
  1877. }
  1878. }}
  1879. handlImgViews(commInfo,'.commInfo a[href$=".jpg"],.commInfo a[href$=".jpeg"],.commInfo a[href$=".png"],.commInfo a[href$=".gif"]'); //просмотр картинок
  1880. }
  1881. }
  1882. if(hS.shortDates.val)
  1883. datesShorten(c,'.info time');
  1884. })(0);
  1885. },
  1886. boxBuild = function(n, cl, el, def){ //выдача DOM-объекта (блока) по правилам построения инфографики
  1887. // (блок dim*dim есть 150 символов или 1 элемент; ar[ity]-кратное расширение влево, затем вниз)
  1888. var dim = 4
  1889. ,ar = 4
  1890. ,logN2 = 2/ ar /Math.LN2 // 1/log4(1)
  1891. ,log = Math.log(n) *logN2 // log4( n )
  1892. ,flor = Math.floor(log) // [log4( n )]
  1893. ,flor12 = Math.floor((flor +1)/2 )
  1894. ,flor2 = Math.floor(flor /2)
  1895. ,growHoriz = flor12 == flor2 ?1:0 // делать рост по горизонтали/вертикали
  1896. ,fract = log - flor // { log4( n ) }
  1897. ,w = Math.pow(ar, flor12)
  1898. ,h = Math.pow(ar, flor2);
  1899. //'commRootBlks'.wcl(w +' '+ h +' '+ n +' '+ Math.floor(dim*( w + growHoriz*(n-w)/ w )) +' '+ Math.floor(dim*( h + (1- growHoriz)*(n-h)/ w )));
  1900. return $e({cl: cl
  1901. ,cs:{width: Math.floor(w ? dim*( w + growHoriz*(n -w* w)/ w ): 2)+'px'
  1902. ,height: Math.floor(w ? dim*( h + (1- growHoriz)*(n -h* w)/ w ): 3)+'px' //деление на 4 учтено через flor12
  1903. ,color:'#dd3'
  1904. ,verticalAlign:'top'}
  1905. //,ht: '*'
  1906. ,at:{title: def + n}
  1907. ,prT: el
  1908. });
  1909. },
  1910. imgWait = '<img src="data:image/gif;base64,R0lGODlhEAAQAMMGAG6WysLS6pKy2ubu9rXK5oKi0v7+/t7m8p622naezsra7oqq1qa+3u7y+gAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAOACwAAAAAEAAQAAAETNDJSau91SzAgSSEYWmdlADFkBWlo7CFOBHoNhksQW2KRimABYWDIU6MGaSDR2G4ghRa7MjIUXAohaQzpQxYiS1nIbuCxOMyZs2eRAAAIfkECQoADgAsAgAAAAwAEAAABFXQyZGCvNgVsE52BpEA5IANGwkwYANuRQAkjbEUIYA7C/EChAVAISEWOaQPSAUwKElCo8Go4BB0zuCPYCiwGqMAzOlyMJgF02WgSnA/B2FBeQkk1I4IACH5BAkKAA4ALAIAAAAMABAAAART0MnpmqDYBaCoIQsAJKMhDYWoioRjpEV3iElHAIXp3IwedhLCwKW4ATKSFdLAUpgGLYkCsJAYGIDoK+tQkAAHgwJmMq5wQxfpuyDopIAAciJoICMAIfkECQoADgAsAgABAA0ADQAABEXQyUmdMdKQBcAi13I4Q9GdQMEdhlkokmJ2B5FiGUcTCTzptIpQcigWcRUUg6JIEByn5aQFeJ5eF9kNipihCgPJUqP7ICMAIfkECQoADgAsAAACABAADAAABFTQSWfIAmARM3srWAgUQzcxhcIpYMFNJdUZIOGUB8A0phMAiULCcQFuJIoiJvALLRQTQgKzcASngV6DATjcHITRS2LgxMgtlYG1GMNAohGvVylq3BEAIfkECQoADgAsAAACABAADAAABFPQyUkAWMTMaUhwimUVw6YkQGJoYAEUrCACzGa4hNQEqFVOocXGciDkhgAkS2I8WDYLgGIzECUCDeZr6WDMBJLbS6FZoRLTycAlmioymzAhCjhuIgA7" title="подгрузка содержимого...">',
  1911. openInFrame = function(ev, t, blck, Li){ //открывать в фрейме (если ссылка не в фрейме)
  1912. if(ev && ev.shiftKey ^ ev.ctrlKey){
  1913. t.target ='_blank'; //в новой вкладке, если Ctrl+click
  1914. win.setTimeout(function(){t.target ='';},200);
  1915. return;
  1916. }
  1917. if(ev && ev.shiftKey && ev.ctrlKey){
  1918. $pd(ev);
  1919. location.href = t.href;
  1920. return!1;
  1921. }
  1922. try{
  1923. var name ='hA_userinfoView'
  1924. ,uFrm = //document.getElementById(name);
  1925. $e({el:$q('#'+ name)||'iframe'
  1926. ,at:{id: name, name: name, src:''}
  1927. ,cs:{position:'fixed', width: h.uFrmWid, height:'200px', top:'200px', borderWidth:0, backgroundColor:'#f4f6f7', zIndex: 101}
  1928. ,apT: document.body
  1929. });
  1930. if(!uFrm){
  1931. /*uFrm = document.createElement("iframe");
  1932. uFrm.id = uFrm.name = name;
  1933. uFrm.src ='';
  1934. uFrm.style.position ='fixed'; uFrm.style.height ='200px'; uFrm.style.width = h.uFrmWid; uFrm.style.borderWidth =0;
  1935. uFrm.style.backgroundColor ='#f4f6f7';
  1936. uFrm.style.zIndex = 101; uFrm.style.top ='200px';
  1937. document.body.appendChild(uFrm);*/
  1938. if(isChrome)
  1939. win.setInterval(function(){ //опрос ширины фрейма по сообщению изнутри
  1940. var frameWidth = uFrm.contentDocument && uFrm.contentDocument.body && uFrm.contentDocument.body.getAttribute('frameWidth');
  1941. if(frameWidth && uFrm.style.display =='block')
  1942. uFrm.style.width = frameWidth;
  1943. },250);
  1944. }}catch(er){'Err_authorClicks: '.wcl(er)}
  1945. var dFrm = $q('.imgWait');
  1946. if(!dFrm) dFrm = $e({cl:'imgWait'
  1947. ,cs:{position:'fixed',width:'20px', height:'20px', zIndex: 101
  1948. , top: Math.floor(win.innerHeight /2 +3) +'px'}
  1949. ,ht: imgWait
  1950. ,apT: document.body});
  1951. else
  1952. $x(dFrm.style, {display:'block',top: Math.floor(win.innerHeight /2 +3) +'px'} );
  1953. uFrm.style.height = Math.floor(win.innerHeight /2 -20) +'px';
  1954. win.setTimeout(function(){dFrm.style.display ='none';}, 2700);
  1955.  
  1956. var srchField = $q('#search_form input[name="q"]')
  1957. ,noInFrame = Li && srchField && Li.parentNode == srchField.parentNode && srchField.getAttribute('keyLast')==13 //для непоказа фрейма при открывании в том же окне
  1958. ,ifTop = ev.clientY > win.innerHeight /2;
  1959. //'Li'.wcl(ev.clientY)
  1960. uFrm.style.top = ifTop ?'19px':'';
  1961. uFrm.style.bottom = ifTop ?'':'-2px';
  1962. if(h.uFrmPrevClick != t.href) //Url последней кликнутой ссылки, загруженной в фрейм
  1963. uFrm.src = t.href;
  1964. uFrm.style.display = (h.uFrmPrevClick == (t.href ||1) && uFrm.style.display =='block'
  1965. || noInFrame) && !/\/edit\//.test(t.href) ?'none':'block';
  1966. h.uFrmPrevClick = t.href;
  1967. if(Li && Li != blck)
  1968. ev && $pd(ev);
  1969. },
  1970. openInFrmHndl = function(blck, Li){ //Li={href:ссылка, открываемая в фрейме}; {href:1} - признак откр.в фрейме со всеми данными в blck, +блокирование умолчательного поведения клика
  1971. var a = Li.href.match(/(http:\/\/)(\w+)\.(habrahabr\.ru)(.*)/) //замена 3-го уровня на 2-й
  1972. ,c =0 //TEST
  1973. ,linNext;
  1974. if(a && a.length && a[2] !='m')
  1975. Li.href = a[1] + a[3] +'/users/'+ a[2] + a[4];
  1976. else{
  1977. a = Li.href.match(/(\/favorites\/)(.*)/); //замена в избранном //TODO .* -- .+
  1978. //'favorites'.wcl(h.uName , h.uName2, a, Li.next)
  1979. if(a && a.length){
  1980. Li.href = '/users/'+ (linNext? h.uName2 : h.uName) + a[1] + (a[2] ? a[2] :'');
  1981. linNext =1; //чтобы первый линк на избранное был на своё (если авторизован)
  1982. }
  1983. }
  1984. a = Li.href.match(/(http:\/\/)(habrahabr\.ru)(\/users\/|\/job\/|\/tag\/)([^\/]+)(.+)/); //обработчик клика на юзере | */job/7671/ | теги -- открывать в фрейме
  1985. //'a'.wcl(a, blck, Li, !/tab_user/.test(Li.className) );
  1986. if(a && a.length >1 )
  1987. c++; //TEST
  1988. if(a && a.length ==6 && (a[5]=='/'|| a[5]=='/favorites/') && !inFrame && !/tab_user/.test(Li.className)
  1989. || RegExp(SHRU+'/settings/').test(Li.href) || Li.href==1){
  1990. if(Li.href==='1')
  1991. Li = blck; //вешать на кнопку
  1992. Li && Li.addEventListener('click', function(ev){openInFrame(ev, this, blck, Li)},!1);
  1993. //'writeListener'.wcl(a && a.length ==6 && (a[5]=='/'|| a[5]=='/favorites/') && !inFrame
  1994. }
  1995. },
  1996. authorClicks = function(blck){ //расст.обраб.кликов по ссылкам; blck - блок, в кот.ищут ссылки
  1997. if(!blck) return;
  1998. var linx = $qA('a[href]',blck); //все ссылки в блоке
  1999. //'aa'.wcl(blck, linx)
  2000. if(linx || blck.tagName =='INPUT'){
  2001. if(blck.tagName =='INPUT') //для подвешивания открывания поиска в фрейме на кнопке поиска
  2002. linx =[{href:'1'}];
  2003. for(var i in linx)
  2004. if(linx[i].href)
  2005. openInFrmHndl(blck, linx[i]);
  2006. }
  2007. if(win.opera || /Firefox\/[345]\./.test(navigator.userAgent)){
  2008. if(win.addKarmEvent) //показ кармы, если установлен HabraKarmaView.user.js
  2009. win.addKarmEvent(blck);
  2010. if(win.habrPercentageRing)
  2011. win.habrPercentageRing(blck);
  2012. }else
  2013. evtChangeDom(blck); //CustomEvent в блоке
  2014. },
  2015. getHourMins = function(D){
  2016. var date = D || new Date;
  2017. return date.getHours() +':'+ (date.getMinutes()<=9?'0':'') + date.getMinutes();
  2018. },
  2019. showContent = function(ev){ //подгрузить и показать статью
  2020. if(ev.ctrlKey ^ ev.shiftKey) return;
  2021. var URL = location.href
  2022. ,isSearchPage = /\/search/.test(URL)
  2023. ,tLink = this.tagName.toUpperCase() !='SPAN' && this || this.parentNode
  2024. ,inFooter = parents('rotated_posts', tLink)
  2025. ,topic = parents('^post($| )', tLink) || inFooter //топик или блок в футере
  2026. ,info2 = $q('.infopanel', topic)
  2027. ,clickComments = /comments|infopanel/.test(this.parentNode.className); //признак клика по ссылке/кнопке комментариев
  2028. //'~~topic'.wcl(tLink, topic, info2)
  2029. if(!tLink.href && (clickComments || parents('habracut', this)) ) //поправка для малых правых кнопок
  2030. tLink.href = $q('a', prev('comments', this) || parents('habracut', this) ).href;
  2031. var commLink = $q('.comments a', info2);
  2032. if(/ link/.test(topic.className)) //сменить ссылку для подгрузки (на ту, которая в комментариях)
  2033. tLink = commLink;
  2034. var topicTitle = $q('.post_title', topic) || parents('^grey$', tLink); //заголовок статьи
  2035. //if(inFooter && !/infopanel/.test(this.parentNode.className) ) //нажатая кнопка в футере
  2036. // $q('span.inln',tLink).className +=' content';
  2037. if(inFooter && !/^post($| )/.test(inFooter.className))
  2038. inFooter.className ='post content_left '+ inFooter.className;
  2039. if(!/blk2nd/.test(this.className)){ //защита от повторного клика
  2040. this.setAttribute('class', this.className +' blk2nd'); //блокировка повторного клика
  2041. try{
  2042. var cnte = $qA('.content', topic)
  2043. ,topicHaCut = $q('a.habracut', topic)
  2044. ,commC2 = $q('.comments.c2', topic); //комментарии, если есть с прежней подгр.
  2045. //'cnte'.wcl(this.tagName.toUpperCase() !='SPAN', this, this.parentNode, cnte[0],cnte[1],topicHaCut, commLink);
  2046. //'commC2=='.wcl(commC2 && getComputedStyle(commC2, null).getPropertyValue('display'))
  2047. var wasComms = commC2 && getComputedStyle(commC2, null).getPropertyValue('display') =='none'; //"были ли показаны комментарии"
  2048. if(cnte.length >1 && !clickComments && !ev.ctrlKey && !ev.shiftKey){ //просто показать ранее загруженное
  2049. cnte[0].style.display ='none';
  2050. $q('.btnBack:not(.showComm)', topic).style.display //показ верхней кн."Свернуть"
  2051. = cnte[1].style.display //показ статьи
  2052. = $q('.btnBack.n2', topic).style.display ='block'; //показ нижней кн."Свернуть"
  2053. }
  2054. //'commC2,clickComments,wasComms'.wcl(commC2, '/', clickComments, '/', wasComms)
  2055. var isBtnBack = $q('.showComm.btnBack:not(.inln)', topic)
  2056. ,isBtnBack2 = $q('.showComm.btnBack.n2', topic);
  2057. if(commC2 && clickComments && wasComms && !ev.ctrlKey && !ev.shiftKey
  2058. && isBtnBack && isBtnBack2){ //показ комментариев
  2059. isBtnBack.style.display = commC2.style.display = isBtnBack2.style.display = 'block';
  2060. if(/ noShowYet/.test(commC2.className)){ //корректировки отображения после вывода:
  2061. //'>By NoShowYet'.wcl('');
  2062. correctCommentsAfter(commC2, topic); //кнопки "Отв"; расцветка авторов; поправки дат
  2063. authorClicks(commC2); //расст.обраб.кликов по ссылкам
  2064. //'authorClicks2'.wcl(commC2, cnte[1])
  2065. authorClicks(cnte[1]);
  2066. commC2.className = commC2.className.replace(/ noShowYet/,'');
  2067. handlImgViews(commC2); handlImgViews(cnte[1]); //показ увеличенных картинок
  2068. }
  2069. }
  2070. //'cnte=='.wcl(cnte, topic, $q('.btnBack.n2', topic))
  2071. if(cnte.length <=1 || ev.ctrlKey){ //подгрузить или пере-подгрузить страницу по ссылке - только при необходимости нарисовать содержимое (контент .content.c2 и .comments.c2)
  2072. this.innerHTML = imgWait + this.innerHTML; //сигнал об ожидании Ajax
  2073. var xhr = new window.XMLHttpRequest()
  2074. ,reGet = ev.ctrlKey && ev.shiftKey; //режим пере-подгрузки
  2075. if(reGet){ //другой признак пере-подгрузки - $q('.btnBack.n2', topic)
  2076. var cont = inFooter ? $q('.contentCell', inFooter) : topic;
  2077. cont.removeChild($q('.content.c2', cont));
  2078. cont.removeChild($q('.comments.c2', cont)); //контент удалён
  2079. xhr.wasArrows =1; //(стрелки были - и остались)
  2080. }
  2081. //topicTitle && 'tLink'.wcl(topicTitle, tLink.href, topicTitle.link);
  2082. var url = topicTitle && (tLink.href || commLink && commLink.href || topicTitle.link);
  2083. //-обход заголовка-ссылки, не-ссылок, отсутствия ссылки на комментарии
  2084. xhr.open('GET', url.replace(/_/g,'%5F'), true); //странно, но "_" не переваривает (FF)
  2085. xhr.link = this; //активный элемент клика мыши
  2086. xhr.onreadystatechange = function(){ //===показ статьи===
  2087.  
  2088. if(this.readyState !=4) return;
  2089. if(inFooter && !$q('.contentRow',inFooter)){ //область контента-c2 в над-футере для подгрузки
  2090. var cntRow = $e({cl:'contentRow'
  2091. ,cs:{display:'table-row', backgroundColor:'#fff'}
  2092. ,aft: $q('.rotated_posts .rotTRow') });
  2093. $e({cl:'contentCell', el:'td'
  2094. ,cs:{display:'table-cell', padding:'0 13%'}
  2095. ,at:{colspan:3}
  2096. ,ht:'<div class=content></div><div class=infopanel><span class="showComm btnBack inln" title="комментарии; Ctrl+Shift - пере-подгрузка">&rarr;</span></div><div class=clear></div>'
  2097. ,apT: cntRow});
  2098. topic = inFooter = $q('.contentCell', cntRow);
  2099. $q('.showComm', topic).addEventListener('click',showContent,!1);
  2100. }
  2101. xhr.link.removeChild($q('img', xhr.link)); //снять сигнал об ожидании Ajax
  2102. var tContent = !inFooter
  2103. ? cnte[0] || $q('.hubs', topic) || $q('.title', topic)
  2104. : $q('.contentCell .content', topic) //начало статьи (аннотация)
  2105. ,contHeight = tContent.offsetHeight //для будущей подкрутки текста при сворачивании статьи
  2106. ,showComm = clickComments && !wasComms || !topicHaCut && !isSearchPage && !inFooter;
  2107. //'xhr.link'.wcl(xhr.link, tContent)
  2108. //'clickComments'.wcl(clickComments, !wasComms, !topicHaCut);
  2109. /*var state = new defineState();// ALLHIDE;
  2110. stateRoll(state, 0, topicHaCut);*/
  2111. //wcl(tContent.style.display,'/', cnte[1] && cnte[1].style.display,'/', wasComms, 'showComm='+showComm, topicHaCut)
  2112. if(!showComm || inFooter)
  2113. tContent.style.display ='none'; //скрыть начало статьи
  2114. var contEdge = $q(!xhr.wasArrows ?'.tags':'.btnBack.n2', topic); //контекст, перед кот.ставится содержание
  2115. //'contEdge2'.wcl(contEdge, !xhr.wasArrows) || info2; //если нет контекста (блока с тегами)- ориентир.на блок с подписями
  2116. //'contEdge'.wcl(contEdge)
  2117. //=== точка "ajax-парсинг страницы" ===
  2118. var conte = this.responseText.match( // ====== парсинг страницы, шаблон ======
  2119. /<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) //вся статья (до тегов или подписи)
  2120. ,tagPars = conte && conte.length ==5 ? conte[3] :''; //вытаскивание тегов
  2121. //'conte~~'.wcl(conte.length, conte, info2)
  2122. conte = conte ? conte[1] :''; //устранение ошибки пустого ответа
  2123. conte = haReplace(conte); // обработка слов статьи (без комментариев)
  2124. var len2 = !conte ?'1': conte.replace(/<a name="habracut"><\/a>(.*|\r|\n)*/m,'') //статья до ката
  2125. //чтобы было "0%" при отсут.текста
  2126. ,date = getHourMins()
  2127. ,percnt = Math.floor((1- len2.length / (conte.length+1))*100)
  2128. ,percent = '&nbsp;'+ percnt +'%, <i>'+ date +'</i>';
  2129. if(!xhr.wasArrows){ //"Свернуть статью" (полоса внизу)
  2130. var btnBackN2 = $e({cl:'btnBack n2'
  2131. ,ht:'<i>&larr; Свернуть</i><div class="percent" style=float:right>/'+date+'/</div>'
  2132. ,at:{rel: contHeight}
  2133. ,on:{click: hideC2}
  2134. ,aft: tContent});
  2135. if(showComm)
  2136. $q('.btnBack:not(.showComm)', topic).style.display ='none';
  2137. }else //...или показать её
  2138. $q('.btnBack:not(.showComm)', topic).style.display ='block';
  2139. var contC2 = $e({cl:'content c2' // ==== блок с полной статьёй (контентом)
  2140. ,ht: /<a name="habracut"><\/a>/.test(this.responseText)
  2141. ?'<div style="background: #efeff2; padding: 2px 3px 2px 7px; margin: -2px -3px -2px -7px; position: relative">'
  2142. + conte.replace(/<a name="habracut"><\/a>/,'</div>')
  2143. :(!topicHaCut || conte.length >20 || clarif.length >20 ? conte + clarif :'<i style="color: #999">(пустой блок)</i>')
  2144. ,aft: tContent }); //(-бывает, что ката в результирующем блоке нет, а в начальном есть)
  2145. extLinks(contC2);
  2146. authorClicks(contC2); //расст.обраб.кликов по ссылкам
  2147. handlImgViews(contC2); //показ увеличенных картинок
  2148. if(showComm)
  2149. contC2.style.display ='none';
  2150. //wcl('trace_00')
  2151. if(!xhr.wasArrows){
  2152. var btnBack = $e({cl:'btnBack'
  2153. ,ht:'<i>&larr; Свернуть</i> <div class="percent"></div>'
  2154. ,on:{click: hideC2} //"Свернуть статью" (полоса вверху)
  2155. ,aft: tContent});
  2156. if(showComm)
  2157. btnBackN2.style.display = btnBack.style.display ='none';
  2158. else if(isChrome){
  2159. var info = $q('.infopanel', topic);
  2160. info.style.top ='-5px';
  2161. }
  2162. }else if(!showComm) //...или показать контент
  2163. contC2.style.display ='block';
  2164. var tags = $q('.tags', topic);
  2165. if(tags)
  2166. tags.style.display ='block';
  2167. else if(tagPars) //добавление тегов из парсинга, если нет исходных
  2168. $e({el:'ul', cl:'tags'
  2169. ,ht: tagPars
  2170. ,bef: info2});
  2171. //'-*-'.wcl(tags, info2)
  2172. //wcl('trace_01')
  2173. //'!xhr.wasArrows ,showComm ,!topicHaCut'.wcl(!xhr.wasArrows ,showComm ,!topicHaCut)
  2174. if(!xhr.wasArrows && showComm && !topicHaCut) //скрыть статью, если надо только комм.
  2175. hideC2.call(tLink);
  2176.  
  2177. var infoDelim = $q('.infopanel +.clear', topic);
  2178. //'infoDelim'.wcl(infoDelim)
  2179. if(!xhr.wasArrows){ //создание кнопки над комментариями
  2180. $e({cl:'showComm btnBack n2' //созд_кноп.сворач_ под комментариями
  2181. ,ht:'<i>&larr; Свернуть</i> <div class="percent0"><i></i> <div class="percent">/'+date+'/</div></div>'
  2182. ,at:{rel: -26}, on:{click: hideComm}
  2183. ,aft: infoDelim});
  2184. var b = $q('.content_left .posts_list .showComm.btnBack:not(.inln)', topic.parentNode);
  2185. if(b) b.style.marginTop ='25px';
  2186. //'zenPresent'.wcl(hS.zenPresent.val, zenChecked, topic.querySelector('.btnBack:not(.inln):not(.n2)'), topic.querySelector('.comments.c2 ul.hentry'))
  2187. var back1 = $q('.showComm.btnBack:not(.inln):not(.n2)', topic);
  2188. if(!zenChecked && !$q('.comments.c2 ul.hentry', topic) && back1 ) //двигать вверх для новых внутренних вёрсток, но не для новых в старом окружении
  2189. back1.style.top ='-22px';
  2190. }
  2191.  
  2192. if(topicHaCut){ //показ процентов при наличии (и возле) ката
  2193. var prevLastInAnno = $q('.prevLastInAnno',topic)
  2194. ,gPercent = $e({cl:'gPercent'
  2195. ,ht:'<div style="width:'+(100 - percnt)+'px"></div>'
  2196. ,on:{click: showContent}
  2197. ,bef: prevLastInAnno});
  2198. $e({cl:'percent'
  2199. ,ht: percent
  2200. ,bef: prevLastInAnno});
  2201. $q('.btnBack:not(.showComm) .percent', topic).innerHTML = '<div class="gPercent"><div style="width:'+(100 - percnt)+'px"></div></div>'+ percent;
  2202. }
  2203.  
  2204. //wcl('trace_02')
  2205. //шаблон, парсинг, комментарии
  2206. var matchComments = this.responseText.match(/<div( class="comments_list " | )id="comments">([\s\S]*?)<\/div>\s+?<div (id|class)="sidebar/m);
  2207. //'matchComments'.wcl(matchComments);
  2208. if(matchComments.length ==4)
  2209. matchComments[1] = matchComments[2];
  2210. if(matchComments && hS.shortReply.val){ //шаблон, парсинг
  2211. 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"');
  2212. }
  2213. var comms = correctCommentsBefore(matchComments[1])
  2214. ,comments = matchComments
  2215. ? $e({cl:'comments c2 noShowYet', ht: comms}) : null
  2216. ,replyA = $qA('.reply a',comments); //коррекция комментов для FF3.6
  2217. for(var i in replyA){
  2218. if(!replyA.getAttribute) continue;
  2219. replyA[i].setAttribute('onclick','return!1;'+replyA[i].getAttribute('onclick'));
  2220. replyA[i].addEventListener('click', function(ev){
  2221. if(win.commentForm){
  2222. //wcl(win.commentForm)
  2223. win.commentForm.moveForm('reply_form_'+ this.getAttribute('onclick').replace(/\D/g,''));
  2224. }
  2225. $pd(ev);
  2226. },!1);
  2227. }
  2228.  
  2229. //wcl('trace_021');
  2230. if(!xhr.wasArrows){ //=====вывести комментарии=====
  2231. //topic.appendChild(comments);
  2232. $e({el: comments
  2233. ,aft: infoDelim});
  2234. var id = url.replace(/\/([^\/]*)$/g,'').replace(/\D/g,'');
  2235. //'_comment_id'.wcl(id); //номер сообщения (для оценок и комментариев)
  2236. }else if(reGet){ //или вставка перед нижней кнопкой сворачивания
  2237. topic.insertBefore(comments, $q('.showComm .btnBack.n2', topic));
  2238. }
  2239.  
  2240. //wcl(tContent.style.display,'/', cnte[1] && cnte[1].style.display,'/', wasComms, 'showComm='+showComm, topicHaCut)
  2241. //'trace_03: !xhr.wasArrows, win.commentForm:'.wcl(!xhr.wasArrows, win.commentForm)
  2242. win.commentForm ={};
  2243. if(!xhr.wasArrows){ //&& win.commentForm
  2244. //wcl('trace_04', win.commentForm && win.commentForm.reloadCommentsOnload)
  2245. //addTaButtons(comments); //добавл_ кнопок над полем ввода
  2246. $e({cl:'showComm btnBack'
  2247. ,ht:'<i>&larr; Свернуть</i>'
  2248. ,on:{click: hideComm}
  2249. ,aft: infoDelim });
  2250. //'.percent'.wcl(topic.querySelector('.showComm.btnBack.n2 .percent'))
  2251. $q('.showComm.btnBack.n2 .percent', topic) //====подгрузка комментариев (обработчик)====
  2252. .addEventListener('click', function(ev){
  2253. //wcl('trace_05', win.commentForm && win.commentForm.reloadCommentsOnload)
  2254. var fLoadCommentsBack = win.commentForm && win.commentForm.reloadCommentsOnload;
  2255. win.commentForm && (win.commentForm.reloadCommentsOnload = function(data, contxt){ //коллбек - подгрузка комментариев
  2256. var newComms = data.responseText.match(/<comment comment_id=/gm);
  2257. newComms = newComms ? newComms.length :0; //число комментариев в подгрузке
  2258. //wcl('trace_06', getHourMins() +', '+ newComms)
  2259. $q('.showComm.btnBack.n2 .percent0 i', topic).innerHTML //...и выв.дату подгрузки
  2260. = getHourMins() + ', (+'+ newComms+')';
  2261. //wcl('trace_07')
  2262. win.commentForm && fLoadCommentsBack.call(win.commentForm, data, contxt); //продолжение подгрузки
  2263. //wcl('trace_08')
  2264. });
  2265. if(win.commentForm){
  2266. win.commentForm.targetId = id;
  2267. win.commentForm.targetType ='post';
  2268. win.commentForm.reloadComments(); //-updateComments: добавление новых комментариев; далее это не работает, т.к. Mootools
  2269. $sp(ev);
  2270. }
  2271. },!1);
  2272. if(!isChrome)
  2273. win.tm && win.tm.init && win.tm.init.add(function(){ //дубликат tm.init.add(function(){...}) под Greasemonkey для отправки коммента
  2274. var c_form_node = $q('#comment_form', topic);
  2275. //'c_form_node:'.wcl(c_form_node, ' win.commentForm:'+ (win.commentForm ? win.commentForm :'==no=='));
  2276. if(c_form_node){ //если есть форма ответа...
  2277. //c_form_node.input_preview = c_form_node.getElement('input.preview');
  2278. c_form_node.input_preview = $q('input.preview', c_form_node); //определеяем кнопку предпросмотра
  2279. if(c_form_node.input_preview){ //если она есть...
  2280. c_form_node.input_preview.addEventListener('click',function(){ //обработчик клика
  2281. //alert('preview')
  2282. win.commentForm.sendComment(c_form_node, 'preview', $q('input.preview', c_form_node));
  2283. //приход данных есть, но не идёт дальше (.fireEvent)
  2284. },!1);
  2285. }
  2286. var comment_type = $q('#comment_type', c_form_node).getAttribute('title');
  2287. var c_form_submit = function(){
  2288. //'last_text=='.wcl(c_form_node.last_text, c_form_node['comment[message]'] && c_form_node['comment[message]'].value, win.comment_type);
  2289. if(c_form_node.last_text && c_form_node.last_text == (c_form_node['comment[message]'] && c_form_node['comment[message]'].value) ){
  2290. '--fff-найден дубликат сообщения'.wcl('') //(найден дубликат сообщения)
  2291. }else{
  2292. //TODO изолировать все одинаковые структуры по отображению, если есть
  2293. //win.commentForm.sendComment(c_form_node, comment_type, c_form_node);
  2294. 'win.commentForm.sendComment(c_form_node, win.comment_type, c_form_node);'.wcl(comment_type);
  2295. //TODO вернуть всё обратно
  2296.  
  2297. //TODO область Saved_stuff
  2298. }
  2299. return false;
  2300. }
  2301. var postButt = $q('input.post', c_form_node);
  2302. postButt.setAttribute('type','button'); //пассивность кнопки
  2303. postButt.addEventListener('click', c_form_submit,!1); //обработчик клика на отправку
  2304. }
  2305. });
  2306. //'win.commentForm:'.wcl(win.commentForm)
  2307. }
  2308. //'showComm'.wcl(showComm);
  2309. if(showComm){ //показ комментариев
  2310. var commC2 = $q('.comments.c2', topic);
  2311. $q('.showComm.btnBack:not(.inln)', topic).style.display
  2312. = commC2.style.display
  2313. = $q('.showComm.btnBack.n2', topic).style.display = 'block';
  2314. if(/ noShowYet/.test(commC2.className)){// корректировки отображения после вывода:
  2315. //'comments,topic'.wcl(comments, topic)
  2316. correctCommentsAfter(comments, topic); //кнопки "Отв"; расцветка авторов; поправки дат
  2317. //'authorClicks21'.wcl(commC2)
  2318. authorClicks(commC2); //расст.обраб.кликов по ссылкам
  2319. var cont = $q('div.content', topic);
  2320. //'authorClicks22'.wcl(commC2, cont)
  2321. authorClicks(cont); //обраб кликов по созданному контенту
  2322. handlImgViews(commC2); handlImgViews(cont); //показ увеличенных картинок
  2323. //'authorClicks3'.wcl(commC2)
  2324. commC2.className = commC2.className.replace(/ noShowYet/,'');
  2325. }
  2326. }
  2327. xhr.link.setAttribute('class', xhr.link.className.replace(/ blk2nd/,'')); //снять блок повторного клика
  2328. showSourceLang(topic); //показ языка кодов в подгруженном
  2329. };
  2330. xhr.send(null);
  2331. }else
  2332. this.setAttribute('class', this.className.replace(/ blk2nd/, '')); //снять блок повторного клика
  2333. }catch(er){alert('error_HAjax_showContent()_'+url +' '+ er);}
  2334. }
  2335. $pdsp(ev);
  2336. if(!win.comment_show_reply_form)
  2337. win.comment_show_reply_form = function(){};
  2338. //===== место подключения плагинов для showContent() =======
  2339. },
  2340. showSourceLang = function(area, addLabels){ //показать язык кода (в блоке показа кода), и подействовать hljs, ес.не addLabels
  2341. if(!area) return;
  2342. if(!area.length)
  2343. area = [area];
  2344. for(var j in area){if(area[j].childNodes){ //подсветка синтаксиса подгруж. блоков (не-Хром)
  2345. var b0a = area[j].querySelectorAll('pre >code');
  2346. for(var i in b0a){if(b0a[i].childNodes){
  2347. var bi = b0a[i]
  2348. biP = bi.parentNode
  2349. ,bL = document.createElement('DIV');
  2350. if(win.hljs && win.$ && !addLabels)
  2351. win.hljs.highlightBlock(bi,' ');
  2352. bL.className = biP.className ='hALang';
  2353. if(biP.parentNode && /content/.test(biP.parentNode.className) && !/html_format/.test(biP.parentNode.className))
  2354. biP.parentNode.className +=' html_format';
  2355. bL.innerHTML = bi.className;
  2356. biP.insertBefore(bL, bi);
  2357. }}}}
  2358. },
  2359. zenChecked,
  2360. extLinks = function(node, oldChk, tops){ //внешние ссылки в новом окне
  2361. if(!hS.extLinks.val || !node) return;
  2362. var links = $qA('a', node)
  2363. ,monthRu ='январь,февраль,март,апрель,май,июнь,июль,август,сентябрь,октябрь,ноябрь,декабрь'.split(',');
  2364. for(var i in links){var LI = links[i]; if(LI.attributes && LI.attributes['href']){
  2365. var lH = LI.attributes['href'].nodeValue
  2366. ,postMatch, qaMatch;
  2367. if(!RegExp('^('+ HRU.replace(/\/\//,'//(\\w+\\.)*').replace(/ahabr/,'(ahabr)?\\') +'|/(?!\/)|#)','i').test(lH) && !/^textDecorationColor/.test(LI.className) ){
  2368. LI.className ='textDecorationColor'+(LI.className ?' '+ LI.className :'');
  2369. LI.setAttribute('target','_blank');
  2370. $e({el:'SPAN', ht:"⇗", cs:{color:'#248'}, aft: LI}); //стрелк2 верх-прав
  2371. if((qaMatch = lH.match(/\/q\/(\d+)/)) && !/habracut/.test(LI.className)){ //вопросы-даты
  2372. var postNum = qaMatch[1]
  2373. ,postYM =[0,0,0,0,0,0,0,0,1,983,1804,2711 //по 12 чисел с янв 2010
  2374. ,3525,4389,5295,6332,7178,8084,9057,9979,10931,11992,13072,14030
  2375. ,14973,15959,17004,17983,18936,20058,21103,22184,23422,24724,27161,29583
  2376. ,31593,33727,35603,37596,39471,41108,42742,44390,46050,47746,49552,54596
  2377. ,61336,68300,75230,82958,91033,99151,107675,116875,126229,135799,147005,158837
  2378. ,169713,180551]; //фев.2015 qa -прогноз
  2379. for(var j = postYM[postYM.length -1]; --j >=0;) //получение примерной даты - 2-й способ
  2380. if(postNum >= postYM[j]){
  2381. var txt = monthRu[j % 12] +' '+ (2010 + (0|j/12)); break;}
  2382. if(!oldChk){
  2383. if(!/post_name/.test(LI.className) )
  2384. LI.title = LI.title && txt + '; ' + LI.title || txt;
  2385. else
  2386. $e({ht: txt, cl:'when', aft: LI});
  2387. }else if((j < postYM.length -3 || j == postYM.length -3 && NOWdate.getDate() >5)
  2388. && LI.className =='post_name'){
  2389. LI.title = LI.title && txt +'; '+ LI.title || txt;
  2390. LI.style.backgroundColor ='#f2fbf6';}
  2391. }
  2392. }else if((postMatch = lH.match(/\/(post|blog)\/(\d+)/)) && !/habracut/.test(LI.className)){// посты-даты
  2393. var postNum = postMatch[2]
  2394. ,postY =[1,4909,18277,48215]
  2395. ,postYM =[79815,82680,85884,89552,92535,95099,97893,100688,103185,105320,107313,109124
  2396. ,111037,112913,114666,116587,118465,120339,123152,125327,127474,129518,131623,133750
  2397. ,135593,137388,139154,141161,143096,145002,146858,148825,150655,152897,156927,160927
  2398. ,164511,167841,171141,174897,178523,181712,185178,188544,192134,195908,200442,204302
  2399. ,207968,211020,214263,217769,221545,224805,228191,231847,235117,238753,242143,244603
  2400. ,247199,249501]; //фев.2015 -прогноз
  2401. //.!обновлять каждый месяц, писать последнее число как прогноз
  2402. for(var j = postYM[postYM.length -1]; --j >=0;) //получение примерной даты - 2-й способ
  2403. if(postNum >= postYM[j]){
  2404. var month = monthRu[j % 12] +' '+ (2010 + (0|j/12)); break;}
  2405. if(j <0)
  2406. for(var k = postY[3]; --k >=0;)
  2407. if(postNum >= postY[k]){ month = (2006 + k) +'';break;}
  2408. if(!oldChk)
  2409. LI.title = LI.title && month +'; '+ LI.title || month;
  2410. else if(LI.className =='post_name'){
  2411. if(j < postYM.length -3 || j == postYM.length -3 && NOWdate.getDate() >5){ //признак новизны статьи, для отметок в "Прямом эфире" (прошлый месяц и старее, но не моложе 5 дней)
  2412. LI.title = LI.title && month +'; '+ LI.title || month;
  2413. LI.style.backgroundColor ='#f4f4fa';
  2414. }
  2415. if(tops){ //перенос комментария к лучшим
  2416. var topComm = tops['p'+ postNum]
  2417. ,lsiP = parents(/post_item/, LI);
  2418. if(topComm && lsiP){
  2419. $e({el:'span', ht:' ', apT: topComm});
  2420. $e({el:'.count', blck: lsiP, apT: topComm});
  2421. $e({el:'span', ht:' ', apT: topComm});
  2422. $e({el:'.user_name', blck: lsiP, apT: topComm.parentNode});
  2423. lsiP.parentNode.removeChild(lsiP);
  2424. }}
  2425. }
  2426. }
  2427. }}
  2428. },
  2429. nameGen = function(len){ len = len || 6; //ген.имён
  2430. var syl ='a,ab,ba,abb,bab,bba'.split(','),L ={a:'aeiouy',b:'bcdfghjklmnprstvwxz'},s ='',sy =''
  2431. ,rnd = function(n){return Math.floor(Math.random() * n);};
  2432. wh:while(1){ sy = sy.length ==1 ? syl[rnd(syl.length -1) +1] : syl[rnd(syl.length)];
  2433. for(var i =0; i < sy.length; i++){
  2434. var ab = L[sy.charAt(i) ]; //тип буквы
  2435. s += ab.charAt(rnd(ab.length)); //случайная буква
  2436. if(s.length == len) break wh;
  2437. }}
  2438. return s;
  2439. },
  2440. haReplace = function(txt){
  2441. var t = hS.chtoBy.val ? txt.replace(/([Чч])то бы(\s)/gi,'$1тобы$2') : txt;
  2442. t = hS.haReplace.val ? t.replace(/хабра/gi,'χ·').replace(/χ·хабр/gi,'χα').replace(/хабр/gi,'χ·') : t;
  2443. return t;
  2444. },
  2445. byTextNodes = function(node, ff){ //рекурсивный проход по всем текстовым нодам
  2446. if(!hS.haReplace.val)
  2447. return;
  2448. if(node && node.hasChildNodes())
  2449. for(j in node.childNodes){var ch = node.childNodes[j]; if(ch.parentNode){
  2450. if((ch.nodeType ==3 || ch.nodeType ==2 && ch.nodeName =='title') && ch.nodeValue && ch.nodeValue.length >8)
  2451. ch.nodeValue = ff(ch.nodeValue);
  2452. else if(ch.nodeType ==1 || ch.nodeType ==11){
  2453. arguments.callee(ch, ff);
  2454. }
  2455. }}
  2456. };
  2457. var inFrame = top != window,
  2458. scanAliens = function(time){ if(!document && !document.querySelectorAll) return;
  2459. var anyScript = document.querySelectorAll('script'), aL;
  2460. if(anyScript && (aL=anyScript.length))
  2461. for(var i in anyScript) if(anyScript[i].childNodes){
  2462. if(!/(habrahabr.ru\/|apis.google.com\/)/.test(anyScript[i].src))
  2463. anyScript[i].src ='';
  2464. if(/(_gaq|analytics.com|an.yandex.ru|pink.habralab.ru)/.test(anyScript[i].innerHTML))
  2465. anyScript[i].innerHTML ='';
  2466. }
  2467. },
  2468. checkInZen = function(){
  2469. if($q('#header .userpanel'))
  2470. var cssGet = win.getComputedStyle($q('#header .userpanel'), null);
  2471. if(!cssGet && $q('.panel-personal'))
  2472. cssGet = win.getComputedStyle($q('.panel-personal'), null);
  2473. //for(var i in cssGet)
  2474. // 'getComputedStyle'.wcl(i+' = ', cssGet[i], cssGet.getPropertyValue(cssGet[i]))
  2475. var zenChecked = cssGet && (cssGet.getPropertyValue('z-index')=='10026'); //индикатор подключения юзерстилей ZenComment
  2476. return zenChecked;
  2477. },
  2478. wwHV =0, //для setTimeout
  2479. hView = function(ev){ //просмотр блока (подсказки, меню) по наведению, с удержанием, задержкой
  2480. //blckMajor, blckMinr, sett, fClick, fMsMove
  2481. var tg = ev.currentTarget, tgHVi, hView;
  2482. win.clearTimeout(wwHV);
  2483. win.setTimeout(function(){
  2484. if((tgHVi = tg.getAttribute('data-hView')) || tg.className =='habrAjaxSettings hView'){
  2485. var xywh = $x(getPosition(tg), {w: tg.offsetWidth, h: tg.offsetHeight});
  2486. hView = $e({el:$q('.habrAjaxSettings.hView') ||'div'
  2487. ,cl:'habrAjaxSettings hView'+ (tg.className =='group'?' group':'')
  2488. ,ht: tgHVi
  2489. ,cs:{display:'block', left: xywh.x + xywh.w +'px', top: xywh.y + xywh.h /2 +'px'
  2490. ,width: Math.min(320, win.innerWidth - 61 - 320 - 10) +'px'}
  2491. ,on:{mouseover: function(){win.clearTimeout(wwHV)}, mouseout: hViewHide}
  2492. ,apT: document.body
  2493. });
  2494. if(hView)
  2495. 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'
  2496. }
  2497. },100);
  2498. },
  2499. hViewHide = function(ev){
  2500. win.clearTimeout(wwHV);
  2501. wwHV = win.setTimeout(function(){
  2502. $e({el:'.habrAjaxSettings.hView'
  2503. ,cs:{display:'none'} });
  2504. },590);
  2505. }
  2506. ,selS ={} //окружение выделенного текста (всё, что вычислили, исходя из текущего выделения)
  2507. ,citeS =[] //список цитат данной статьи
  2508. ,citeA =[]; //список статей, имеющих цитаты в хранилище
  2509.  
  2510. (function(){ //внедрение функций GM_... для Хрома, FF4+
  2511. if(!this.GM_getValue || this.GM_getValue.toString && /not supported/.test(this.GM_getValue.toString()) ){
  2512. this.GM_getValue = function(key, deflt){ return localStorage[key] || deflt };
  2513. this.GM_setValue = function(key, value){ return localStorage[key] = value };
  2514. this.GM_deleteValue = function(key){ return delete localStorage[key] };
  2515. }})();
  2516.  
  2517. hS = hS.get(); //settings; взять настройки из памяти (GM), если есть
  2518. if(/\/(conversations|edit|add)\//.test(lh) && !win.opera) //заполнение полей письма
  2519. fillLetter();
  2520. var vers = navigator.userAgent.match(/Version\/(\d+)/);
  2521. if(vers && vers[1])
  2522. vers = parseInt(vers[1]);
  2523. if(!(win.opera && vers >11)) //ручной zenPresent - для Оперы 12+, для остальных скрыть в еастройках
  2524. delete hS.zenPresent.desc;
  2525. if(win.getComputedStyle)
  2526. zenChecked = checkInZen();
  2527. h.inZen = (typeof zenChecked!=u ? zenChecked : hS.zenPresent.val) || hS.inZen.val;
  2528. var ZenNCh = h.inZen && !isChrome; //случаи приоритетности стилей из скриптов в Хроме
  2529. //'zenChecked'.wcl(typeof zenChecked, zenChecked && zenChecked.length, hS.zenPresent.val, hS.inZen.val, h.inZen)
  2530. strongCutImgMinH = hS.hStrongCut.val;
  2531. if(!h.inZen)
  2532. strongCutImgMinH +=50;
  2533. var css='body{text-align: inherit!important; font-family: Verdana,sans-serif!important}'
  2534. +'#layout{height: auto!important}.posts_list .blog_title.small{font-size:14px!important}'
  2535. +'.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}'
  2536. +'.content+.btnBack.n2{margin-top:-5px!important}'
  2537. +'.comments.c2{clear: both; position: relative; display:none; border-bottom: 2px solid #fff!important}'
  2538. +'.comments.c2:hover{border-bottom: 2px solid #eee!important}'
  2539. +'.comments.c2:hover >.comment_item:not(:hover){margin-right:-2px!important;border-right: 2px solid #eee!important;background:#eee}'
  2540. +'.comments.c2 .comment_item:hover{background:#fff}'
  2541. +'.comments.c2 >h2.title,.posts_list .comments.c2 >h2.comments-header{'
  2542. +'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}'
  2543. +'.comments.c2 h2.title span,.comments.c2 h2.comments-header span{position: relative;margin-bottom: 32px;height: 34px;font-size: 26px;vertical-align: 0%}'
  2544. +'h2.title .subscribe_comments{font-size: 12px!important}'
  2545. +'#wrapper .comments.c2 >h2.title{margin: 0 0 4px 6px!important;}'
  2546. +'.comments_list .comment_item .reply_comments{margin-top:10px!important}'
  2547. +'.comments.c2 >.comment_item,#wrapper .comments.c2 .reply_comments >.comment_item,.content_left .comments.c2 .reply_comments >.comment_item{'
  2548. +'position:relative;margin-top: 8px!important;margin-left: -4px!important;padding-top: 0!important;padding-left: 24px!important}'
  2549. +'#wrapper .comments.c2 >.comment_item,.content_left .comments.c2 >.comment_item{'
  2550. +'margin-left: -24px!important;border-left: 1px solid #dddde2!important}'
  2551. +'.comments.c2 .info{height:16px}'
  2552. +'.comments.c2 .info a.username{top:-11px!important;margin-top:-5px!important}'
  2553.  
  2554. +'.comments.c2 .info time{position:relative; top:'+(1||h.inZen?-10:0)+'px!important; margin-right:10px!important}'
  2555. +'.comments.c2 >.comment_item:hover .info .voting{display:block!important}'
  2556. +'.comments.c2 >.comment_item:hover .comment_item:not(:hover) .info a.username'
  2557. +',.comments.c2:hover >.comment_item:not(:hover) .info a.username'
  2558. +',.comments.c2 >.comment_item:hover .comment_item:not(:hover) .info time'
  2559. +',.comments.c2:not(:hover) .reply >a.reply_link'
  2560. +',.comments_list:not(:hover) .reply >a.reply_link'
  2561. +',.comments.c2:hover >.comment_item:not(:hover) .reply >a.reply_link'
  2562. +',.comments_list:hover >.comment_item:not(:hover) .reply >a.reply_link'
  2563. +',.comments.c2 >.comment_item:hover .comment_item:not(:hover) a.reply_link'
  2564. +',.comments_list >.comment_item:hover .comment_item:not(:hover) a.reply_link{visibility:hidden}'
  2565. +'.comments.c2 >comment_item_plain >.comment_item .info time'
  2566. +',.comments.c2 >.comment_item:hover .info time'
  2567. +',.comments.c2 >.comment_item:hover .reply a.reply_link{visibility:visible}'
  2568. +'.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}'
  2569.  
  2570. +'.eventLine .eventHid, .eventLine .date{visibility:hidden}.eventLine:hover .eventHid, .eventLine:hover .date{visibility:visible}'
  2571. +'.eventLine .date{color:#999}'
  2572.  
  2573. +'.commInfo{position: absolute; z-index: 4; display: inline-block; visibility:hidden; left:0; max-width:43px; margin-top: 6px; border: 1px dotted #d97;'
  2574. +'-webkit-transition:visibility 0s linear 1s,opacity 1s linear;'
  2575. +'-moz-transition:visibility 0s linear 1s,opacity 1s linear;'
  2576. +'-o-transition:visibility 0s linear 1s,opacity 1s linear;'
  2577. +'opacity: 0;}'
  2578. +'.title:hover .commInfo{visibility:visible; opacity: 1; transition-delay:0s;}'
  2579. +'.commInfo .root{display: inline-block; margin: 1px 0 1px 2px; text-decoration: none; line-height:4px; white-space: normal;}'
  2580. +'.commInfo .overLink{line-height:6px; white-space: nowrap'+(isChrome?';font-size:0':'')+'}'
  2581. +'.commInfo .overLink:hover{background-color:#eee}'
  2582. +'.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}'
  2583. +'.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}'
  2584. +'.commInfo .links.root{min-height: 4px; vertical-align: top}'
  2585. +'.commInfo .imgs.root{min-height: 6px; vertical-align: top}'
  2586. +'.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}'
  2587. +'.commInfo .links.root .imgL,' //перекраска для просмотра
  2588. +'.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}'
  2589. +'.commInfo .links.root .lnk:visited{border:1px solid #e4d}'
  2590. +'.comments .comment_item .info .branch,#comments .comment_item .info .branch{Visibility: hidden; position: relative; top:-11px!important; text-decoration: none}'
  2591. +'.comments .comment_item .info:hover .branch,#comments .comment_item .info:hover .branch{Visibility: visible}'
  2592.  
  2593. +'.post div.btnBack.inln{display: inline-block; vertical-align: middle; overflow: hidden; height: 14px; line-height: 14px!important; margin: 0 2px 3px}'
  2594. +'.post .btnBack:not(.inln):not(.n2){position: relative;z-index: 1}'
  2595. +'.post .content .percent,.post .btnBack .percent,.post .btnBack >i{display: inline-block;vertical-align:top; line-height:10px}'
  2596. +'.post .content .percent{font-size:12px;color:#8ac}'
  2597. +'.post .content .gPercent,.post .btnBack .gPercent'
  2598. +'{display: inline-block; width: 100px; height: 10px; vertical-align: top; margin-left: 9px; border: 1px solid #b3d2ee; background-color: #ecefee; cursor: pointer}'
  2599. +'.post .content .gPercent div,.post .btnBack .gPercent div'
  2600. +'{display: inline-block; height: 10px; vertical-align: top;border-right: 1px solid #b3d2ee; background-color: #e0e5e8}'
  2601. +'.post .content .gPercent div{background-color: #f4f8fb}'
  2602. +'.post .dblAuthor .published{float:none}'
  2603. +'.showComm.btnBack:not(.inln), .showComm.btnBack.n2{display: none; clear: both}'
  2604. +'.showComm.btnBack:not(.inln):not(.n2){margin-top: 22px}'
  2605. +'.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}'
  2606. +'#poxupih a{color:#7ab}.gertuik{font-size: 16px!important;color:#eee}'
  2607. +'#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':'')+'}'
  2608. +'#header .search form input[type="text"]{margin-right: 21px;}'
  2609. +'#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}'
  2610. +'.panel-search .panel-search-label{margin-right: 24px}.panel-search .js-autosuggest-output-container{clear: left!important}'
  2611.  
  2612. +'#layout img[align="middle"],#layout img[align="center"]{display:block;margin:0 auto 2px!important}' //Fx fix
  2613. +'.comments.c2{position: static!important;overflow: visible!important;min-height: 2em; padding-left: 32px!important;border-right: 2px solid #fff!important;background:#fff}'
  2614. +'#header .userpanel:hover .habrauser-newmail{margin-right: -4px!important; margin-left: 6px!important}'
  2615. +'.header .user_panel +.logo{margin:0!important; background-position:0 0!important; width:75px!important; height:71px!important}'
  2616.  
  2617. +'.comments.c2 .info-text{display:none!important}'
  2618. +'.comments.c2 h2.comments-header{margin:0 0 0 -12px!important}'
  2619. +'.comments.c2 .comment-preview{font: 1.08em Verdana,sans-serif!important}'
  2620. +'.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}'
  2621. +'.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}'
  2622.  
  2623. +'.comments.c2 .comment_holder .mark{left:0}'
  2624. +'.g-plusone >iframe[id^="I"][src^="https://plusone.google.com"]{display:block!important;width:width:24px!important; margin-right: 6px!important}'
  2625. +'.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}'
  2626.  
  2627. +'.infopanel >.g-plusone +.likes{position: relative; float: left; left: -33px; width: 0; height: 16px; padding: 0!important; text-align: center}'
  2628. +'.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;}'
  2629. +'.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}'
  2630. +'.infopanel >.g-plusone:hover +.likes{display: none}'
  2631. +'.comment_item .info .comma{display:none!important}'
  2632.  
  2633. +'#comment_form .panel .spanned, #comments_form .panel .spanned, .editor .panel .spanned{display:block; float:left}'
  2634. +'.editor .panel .spanned{padding: 0!important}'
  2635. +'.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}'
  2636. +'.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}'
  2637. +'.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}'
  2638. +'.panel .langs b:hover, .panel .langs2 span:hover{background: #fff} .panel .colrs span:hover{background: #eee}'
  2639. +'.panel .langs i{display: inline-block;}'
  2640. +'.panel .langs2{text-align: left;z-index: 12; white-space: nowrap; opacity:1}'
  2641. +'.panel .langs2 span{padding: 2px; font-weight: normal}.panel .langs2 span:nth-child(even){color:#00a}'
  2642. +'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}'
  2643.  
  2644. +'.powerCut{max-height: '+(strongCutImgMinH*2 +4)+'px; overflow-y: auto!important;padding-right:3px!important; padding-bottom:1px!important}'
  2645. +'.content.powerCut .pressed{line-height: '+(h.inZen ? 1.08 : 1.24)+'!important}'
  2646. +'.content.powerCut .showComm img{margin-top:-1px!important}'
  2647. +'.post .content.powerCut blockquote{clear:none}'
  2648. +'.content.powerCut img{clear:right; max-width: '+(strongCutImgMinH*2)+'px; max-height: '+strongCutImgMinH+'px; margin-top:2px!important}'
  2649. +'.powerCut img:not([align]){float:right; margin-left:6px!important}'
  2650. +'.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}'
  2651. +'.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}'
  2652. +'.powerCut +.tags{max-height: 1.5em; overflow:hidden}.powerCut +.tags:hover{overflow:inherit}.powerCut +.tags li{position:relative; z-index:2}'
  2653. +'textarea{font: 12px/15px Verdana,Arial,Helvetica,sans-serif!important;resize:vertical!important}'
  2654. //нотификатор, панель цитат
  2655. +'.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}'
  2656. +'.noteBar .closeButt{float:right; margin-right:-3px!important; padding: 0 2px!important; border: 1px solid #999!important;border-radius:5px;cursor: pointer}'
  2657. +'.noteBar .list:nth-child(2){margin-right:16px!important}.noteBar .notes{margin:0!important}'
  2658. +'.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}'
  2659. +'.noteBar .hlp{text-indent:2em; margin:0 2px 1px;padding:0 3px; background:#f6f8fa}'
  2660. //контекстное меню для цитат (выделений текста)
  2661. +'.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}'
  2662. +'.citeBtns .citeCmdBase{position: relative; left:-3px;width:2.5em; opacity:0.5}'
  2663. +'.citeBtns:hover .citeCmdBase{opacity:1}'
  2664. +'.citeBtns button{display:none; margin:0!important; padding: 0 2px!important;background-color:#e6dada; border-width: 1px;border-radius:3px}'
  2665. +'.citeBtns button:first-child{display: block}'
  2666. +'.citeBtns .citeCmdBase button{float: left; width: 2.5em; margin: 0 3px}'
  2667. +'.citeBtns .citeTxTa{position: relative; display: none; min-height: 26px; margin:-22px -2em -4px;}' //буфер для перетаскивания
  2668. +'.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}' //блок цитат
  2669. +'.citeBtns .citeLst{position: absolute; left: -1px; text-align: left}'
  2670. +'.citeBtns .citeLst2{border: 1px solid #ddd; background: #f8f7f1}'
  2671. +'.citeBtns .citeLst .cite{margin:0 1px; padding; 1px 2px; border: 1px solid #ddd; background: #f8f7f1}'
  2672. +'.citeBtns .citeTx .selText{position: relative; left: 1.1em; padding: 0 3px!important; background: #fae7e5;}'
  2673. +'.citeBtns .citeTa{position: absolute; bottom:-2px; margin: 0 10px!important; min-height: 1.4em;}' //буфер д.перетаск.
  2674. +'.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}'
  2675. +'.citeBtns .citeTa .taAbs{position: absolute; left: -10098px; opacity:1}'
  2676. +'.citeBtns .citeTx,.citeBtns .citeTa .ta {-webkit-user-select: text; -moz-user-select: text;-o-user-select: text; user-select: text}'
  2677. +'.citeBtns .citeCmdTop{height: 6px; cursor:move}.citeBtns .citeCmdTop:hover{border-color:#137; background-color:#137}'
  2678. +'.citeBtns .pre{border-color:#dae4da; background-color:#dae4da}'
  2679.  
  2680. +'.citeBtns .citeCmdLeft{position:absolute; display:none; float: left; width: 1px}'
  2681. +'.citeBtns .citeCmdLeft button{position:relative; display: block; float: right}'
  2682. +'.citeBtns .citeCmdRight{position:absolute; display:none; float: right; width: 1px; margin-left: '+(isFx?'2.2':'2')+'em}'
  2683. +'.citeBtns .citeCmdRight button{position:relative; display: block; float: left}'
  2684. +'.citeBtns:hover .citeCmdLeft, .citeBtns:hover .citeCmdRight, .citeBtns:hover button{display:block}'
  2685. +'.citeBtns .hov button{display:none}.citeBtns .hov:hover button{display:block}'
  2686. +'.citeCmds2{}' //2-й плавающий блок
  2687. //подсветки выделений текстов для цитирования:
  2688. +(hS.contextSelect.val ?'.content::-moz-selection{background-color: #66e;color:#fff} .content::selection{background-color: #66e;color:#fff}'
  2689. +'.content *::-moz-selection{background-color: #33b;color:#eef} .content *::selection{background-color: #33b;color:#eef}'
  2690. +'.message::-moz-selection{background-color: #c96;color:#fff} .message::selection{background-color: #c96;color:#fff}'
  2691. +'.message *::-moz-selection{background-color: #963;color:#fee}.message *::selection{background-color: #963;color:#fee}'
  2692. +'.comment_item .text::-moz-selection{background-color: #c98;color:#eff}.comment_item .text::selection{background-color: #c98;color:#eff}'
  2693. :'')+'.textDecorationColor{text-decoration: underline;text-decoration-color:#248!important}'
  2694.  
  2695. +'.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}'
  2696. +'.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;}'
  2697. +'.tutor3{color: #d36992;position: absolute;}'
  2698.  
  2699. +'.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}'
  2700. +'.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;}'
  2701. +'.decision3{color: #684;position: absolute;}'
  2702.  
  2703. +'.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}'
  2704. +'.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;}'
  2705. +'.sand3{color: #8c896b;position: absolute;text-decoration:none;border-bottom:1px dotted #aa8}'
  2706.  
  2707. +'.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}'
  2708. +'.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;}'
  2709. +'.trans3{color: #6a7fa3;position: absolute;}'
  2710.  
  2711. +'.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}'
  2712. +'.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;}'
  2713. +'.recov3{color: #a28546;position: absolute;text-decoration:none;border-bottom:1px dotted #b97}'
  2714. +'#write_message_form [name=recipients]::-moz-selection{background-color: #66e;color:#ffa} #write_message_form input[name=recipients]::selection{background-color: #66e;color:#ffa}'
  2715.  
  2716. //поддержка отсутствия стилей:
  2717.  
  2718. +'.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}'
  2719. +'.content_left table.menu .profile a{position:relative; z-index:2; opacity:0.4}'
  2720. +'.content_left table.menu .profile a:hover{opacity:0.9}'
  2721. +'.content_left .post{margin: 12px 0 32px !important;overflow: inherit !important}'
  2722. +'.content_left .company_post .post{margin-bottom: -5px!important}'
  2723. +'.company_header .company_icon img{position: absolute; margin-top:'+(h.inZen?29:43)+'px!important}'
  2724. +'.content_left .post h1.title{margin: 3px 0 -3px!important;font: 16px/188% normal Verdana,Tahoma,sans-serif!important}'
  2725. +'.content_left .post h1.title .post_title{ line-height: 16px;font-size: 16px;text-decoration: none!important;color: #48a!important}'
  2726. +'.post h1.title .locked{background-position: 2px 0px!important}'
  2727. +'.sidebar_right .block .all a:visited,.content_left .post h1.title .post_title:visited{color: #b99!important}'
  2728. +'.content_left .company_post h1.title .post_title{font-size: 18px!important;font-weight: normal}'
  2729. +'.content_left :not(.company_post) .post h1.title .post_title:hover{color: #84b18a!important}'
  2730. +'.content_left .post .hubs{float: right; position: relative; z-index:2; margin: 1px 8px 2px -12px!important;opacity: 0.7; background: 0 0!important; color: transparent!important}.content_left .hubs +.content{clear: both}'
  2731. +'.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}'
  2732.  
  2733. +'.content_left .stats{margin-left: 3em}.content_left .stats .item{display: inline-block}'
  2734. +'.content_left .stats .item a{padding:0 2px; font-style: italic; color:#668}.content_left .stats .item a:hover{color:#4D7285}'
  2735. +'.content a,.content_left .comments_list a,.comments.c2 a{color:#497da5!important}'
  2736. +'.content a:hover,.comments_list a:hover,.comments.c2 a:hover{color:#4d7285!important}'
  2737. +'.comment_item .info .voting{float: right; margin: 2px 0 -6px!important; padding-right: 16px; position: relative}'
  2738. +'.comment_item .info a.avatar{position: relative; float: left; top:-8px; margin: 0 10px -8px 0!important; padding-top: 0!important}'
  2739. +'.comment_item .info a.avatar img{width:24px; height:24px}'
  2740. +'.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}'
  2741. +'.reply .edit_link{position: relative; z-index: 1; top:-5px; margin-top: 0!important}'
  2742. +'.comment_item .reply a.reply_link:hover{opacity:1}'
  2743. +'.vote .positive,.voting .positive{color: #390!important}.vote .negative,.voting .negative{color:#c00!important}'
  2744. +'.comment_holder .vote{top: -3px}.comment_holder .reply{height:0}'
  2745. +'.translation .topic,.podcast .topic,.link .topic{background-position: 0 0!important}'
  2746. +'.search-results{margin: 30px 0 0 -22px!important;padding-left: 22px!important}'
  2747. +'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')+'}'
  2748. +'.comments.c2 .comment_item .info div.voting{top:'+(h.inZen?3:'-2')+'px}'
  2749. +'.comments_list{overflow:visible!important; padding-left:17px!important; padding-right:3px!important}'
  2750. +'.comment_item .info a.favorite{visibility:hidden}'+(h.inZen?'':'.comment_item .info:hover a.favorite,')+'.comment_item .info a.favorite:hover{visibility:visible}'
  2751.  
  2752. +'.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}'
  2753. +'.habrAjaxSettings .group{margin: 1px 1px 1px -6px; padding: 2px 2px 2px 8px; font-weight: bold; background:#ddd}'
  2754. +'.habrAjaxSettings .sett{padding-left:6px}.habrAjaxSettings .sett:hover{background:#f4f4f4}'
  2755. +'.habrAjaxSettings input[type="checkbox"]{position:relative; margin:1px; top:3px}'
  2756. +'.habrAjaxSettings span{border:2px solid transparent; border-radius:2px}'
  2757. +'.habrAjaxSettings span.latest{margin-right:2px; border-color:#ca9!important} .habrAjaxSettings span.latest input{margin-top:-2px!important}'
  2758. +'.habrAjaxSettings span.notChecked ~label{color:#999}'
  2759. +'.habrAjaxSettings >div>div:not(:first-child) label:hover{border-bottom:1px dotted #bbb}'
  2760. +'.habrAjaxSettings.hView{padding-left: 6px}.habrAjaxSettings a{color:#25a}.habrAjaxSettings a:hover{color:#57a}.habrAjaxSettings.hView.group{background: #ddd; padding: 6px 0 8px 7px}'
  2761.  
  2762. +'a.hADotted{text-decoration: none; border-bottom:1px dotted transparent}a.hADotted:hover{border-bottom:1px dotted #69d}.hADotted.note{color:#d00}'
  2763. +'.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}'
  2764. +'.comment_item .message{margin-left:-4px!important;'
  2765. +' margin-right:-3px!important; padding: 0 3px 0!important;border-left:4px solid transparent}'
  2766. +'.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 до починки ввода
  2767. +'.info a.username,.comments >.comment_item span.username a{color: #569!important;letter-spacing: 1px}'
  2768. +'.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}'
  2769. +'#wrapper .comments.c2 .info{position: relative}'
  2770. +'.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;}'
  2771. +'.comments .comment_item >span.info a{padding:0 3px 1px 4px; border-radius:3px; color:#666!important}'
  2772. +'.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}'
  2773. +'.panel-personal dd a.habrAjaxSettButt, #header .userpanel a.habrAjaxSettButt, #header .user_panel a.habrAjaxSettButt{display: none}'
  2774. +'.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}'
  2775. +'.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}'
  2776. +'.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}'
  2777. +'.editor .panel .wysiwyg_wrapper .btn{display: inline-block; height: 20px!important; line-height: 22px!important}'
  2778. +'.editor .panel .wysiwyg_wrapper .btn.btn-dropdown{float: none!important}'
  2779. +'#js-field-holder-with-help{overflow: inherit!important}'
  2780. +'.editor .panel{position: relative!important; overflow: inherit!important; z-index: 11; width: 98%!important; min-height: 22px; padding: 2px 5px 0!important}'
  2781. +'.panel select.with-title{display:none!important}'
  2782. +'.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}'
  2783. +'.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}'
  2784. +'.post .infopanel .original-author,.post .infopanel .author,.post .infopanel .comments{padding-top:2px!important;padding-bottom:3px!important; font-weight:normal!important}'
  2785. +'.infopanel .original-author a{font-size:12px!important; color:#a33!important}.post .infopanel .author a{font-size:12px!important}'
  2786. +'.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}'
  2787. +'.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}'
  2788. +'p img[src*="error-404-monster"]{display:none}#write_message_form, #write_message_form .item{margin-bottom:0!important}'
  2789. +'#write_message_form label[for="text"]{display:none!important}'
  2790. +'.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}'
  2791. +'.rotated_posts .rotated_post{display:none!important}.rotated_posts .rotTRow a span{position:relative}'
  2792. +'.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}'
  2793. +'.sidebar_right .block{font-family:Verdana,Arial,Helvetica,sans-serif!important}'
  2794. +(h.inZen?'':'.sidebar_right .block{border-radius:28px; box-shadow: 0 0 20px #fff inset, 0 0 16px #eed!important}') //размытые границы сайдбара
  2795. +'.sidebar_right .block .all{text-align: right}'
  2796. +'.sidebar_right .block.float_block{position: static!important}'
  2797. +'.sidebar_right .block a{text-decoration: none!important}'
  2798. +'.sidebar_right .block .post_item,'
  2799. +'.vacancies .job_item,'
  2800. +'.tasks .task{margin-left: 1.6ex!important; margin-bottom: 0!important; line-height: 1.18!important; text-indent:-2ex}'
  2801. +'.vacancies .job_item,.tasks .task{margin-left:0!important}'
  2802. +'.sidebar_right .live_broadcast .qa_activity{margin-top: 0.8em!important; display: block!important}'
  2803. +'.sidebar_right .freelansim .title,'
  2804. +'.sidebar_right .block.new_vacanies .title{display:inline-block!important; margin-bottom: 6px!important; opacity:0.3}'
  2805. +'.vacancies .job_item,.freelansim .tasks .task{padding-left:2ex!important}'
  2806. +'.sidebar_right .block.freelansim .tasks .task a,'
  2807. +'.sidebar_right .block.new_vacanies .vacancies .job_item a{font-size: 12px!important}'
  2808.  
  2809. +'.content_left .block_after_post{margin-top: 0!important}'
  2810. +'.content_left .similar_posts,'
  2811. +'.content_left .similar_questions{margin:-4px 0 0!important; padding-top: 0!important}'
  2812. +'.content_left .similar_posts .posts_list,'
  2813. +'.content_left .similar_posts:hover,'
  2814. +'.content_left .similar_questions:hover{position: static; float: none;}'
  2815. +'.content_left .similar_questions .posts_list,'
  2816. +'.rotated_posts{margin-top: 0!important; margin-bottom: 0!important; padding-top: 0!important; border-top: 1px solid #eee!important; background: #f8f8f8}'
  2817. +(isChrome?'.content_left .similar_posts{position:relative!important; top:-1.5em;border-top:0!important}':'')
  2818. +'.content_left .similar_posts .even,'
  2819. +'.content_left .similar_questions .even{width:99%}'
  2820. +'.content_left .similar_posts .even .post_item,'
  2821. +'.content_left .similar_posts .when,'
  2822. +'.content_left .similar_questions .when,'
  2823. +'.content_left .similar_questions .even .post_item{padding: 0 3px; border-radius: 3px; background: #f2f2f2}'
  2824. +'.content_left .similar_posts .even .when,.content_left .similar_questions .even .when{background:#f8f8f8}'
  2825. +'.content_left .similar_posts .posts_list .post_item:nth-child(4n+1),'
  2826. +'.content_left .similar_questions .posts_list .post_item:nth-child(4n+1){clear:none!important}'
  2827. +'.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}'
  2828.  
  2829. +'.block_after_post .block{padding: 3px 15px}'
  2830. +'.block_after_post .block .title{margin-bottom: 0}'
  2831. +'.rotated_posts .rotated_post a,'
  2832. +'.content_left .similar_posts .title,'
  2833. +'.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}'
  2834. +'.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}'
  2835. +'.content_left .similar_posts .title,'
  2836. +'.content_left .similar_questions .title,'
  2837. +'.content_left .similar_posts .post_item .when{padding-bottom: 0!important; font: 12px Arial,Helvetica,sans-serif!important}'
  2838. +'.content_left .similar_posts .posts_list,'
  2839. +'.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}'
  2840. +'.content_left .similar_posts .posts_list{margin-top:'+ (h.inZen ?-0.1:0.9) +'em!important; background: #f8f8f8}'
  2841. +'.content_left .similar_posts:hover .posts_list,'
  2842. +'.content_left .similar_posts .posts_list:hover,'
  2843. +'.content_left .similar_questions:hover .posts_list,'
  2844. +'.content_left .similar_questions .posts_list:hover{display: block}'
  2845. +'.content_left .similar_posts .post_item,'
  2846. +'.content_left .similar_questions .post_item,'
  2847. +'.content_left .similar_posts .post_item .when{margin-bottom: 0!important}'
  2848. +'.content_left .similar_posts .post_item .when,'
  2849. +'.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}'
  2850. +'.content_left .similar_posts .post_item:hover .when,.content_left .similar_questions .post_item:hover .when{display: block}'
  2851. +'.content_left .similar_posts .post_item .post_name,'
  2852. +'.content_left .similar_questions .post_item .post_name{display: inline; text-decoration: none!important}'
  2853. +'.content_left .similar_posts .post_item .post_name{color: #6da3bd!important}'
  2854. +'.content_left .similar_posts .post_item .post_name:hover{color: #4d7285!important}'
  2855. +'.content_left .similar_posts .post_item,'
  2856. +'.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}'
  2857. +'.post .published{float: right; margin: 3px 0 -4px 4px!important}'
  2858. +'.post .content .buttons{display: inline-block!important; padding: 0!important}'
  2859. +'.post .content .buttons a.button,'
  2860. +'.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}'
  2861. +'.buttons a.button{height: 1.3em!important; top:-1px!important; line-height: 1.3em!important}'
  2862. +'.post .content .buttons input[type="button"]{color: #367!important}'
  2863. +'#comment_form #send_msg,'
  2864. +'#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}'
  2865. +'.post .content .buttons a.button:hover{background: #f4f4f9!important}'
  2866. +'.post .content .buttons a.button:visited{color: #b98!important}'
  2867. //футер
  2868. +'.page-nav #nav-pages,.page-nav{margin: 0 40px 0!important;padding: 0 0 1px 1px!important}'
  2869. +'.page-nav ul.next-prev li{padding-right: 0.3em!important}'
  2870. +'.page-nav #nav-pages{position: fixed;z-index: 1001;left: 0;bottom: -1px;margin: 6px 0!important;opacity: 0.5;filter: alpha(opacity=50)}'
  2871. +'.page-nav #nav-pages:hover{opacity: 1; filter:none}'
  2872. +'.page-nav #nav-pages li{margin: 0!important}'
  2873. +'.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}'
  2874. +'.page-nav #nav-pages li em{border: 1px solid #3E8592!important; background-color: #7a9bac}'
  2875. +'.page-nav #nav-pages li a:hover{margin: -1px!important;padding: 3px 26px!important;border: 1px solid #8ab!important;background:#C5DAE5!important}'
  2876. +'#footer{position:relative; width: auto!important;min-width: 314px!important;overflow: visible!important;margin: 0 2px 20px 6px!important;padding: 6px 0 0!important}'
  2877. +'#footer .bottom_menu{width: 100%!important}'
  2878. +'#footer a{text-decoration: none!important}'
  2879. +'#footer dl{width: 50%!important; float:right}'
  2880. +'#footer dl:last-child{display:none}'
  2881. +'#footer dt{float:left; width: 4em; margin: 0!important; line-height: 120%!important}'
  2882. +'#footer dt:after{content:":"}'
  2883. +'#footer dd:not(:last-child):after{content:","}'
  2884. +'#footer dd{float:left; margin: 0 0 0 6px!important; line-height: 120%!important}'
  2885. +'#footer .copyright{position: relative; left: 12px; width: auto!important; float: none!important; margin-right: 12px!important}'
  2886. +'#footer .copyright .footer_logo{margin:0!important; position:absolute; left: -21px!important}'
  2887. +'#footer .copyright .about{float:left!important; width: auto!important; vertical-align: middle!important; margin:0 0 0 2px!important}'
  2888. +'#footer .about br,#footer .copyright .about br,body >img[src*="habr.statis.tk/c?"]{display: none}'
  2889. +'#footer .about >a{margin-left: 10px!important}'
  2890. +'#footer .about div,#footer .social_accounts{display: inline-block; height: 1.2em!important; margin: 0!important}'
  2891. +'#footer .social_accounts a{margin-bottom: -8px!important}'
  2892. //просмотр картинок
  2893. +'.de-img-pre, .de-img-full{border: medium none; cursor: pointer; display: block; margin: 2px 6px; outline: medium none}'
  2894. +'.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}'
  2895. +'.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)}'
  2896. +'.de-img-full{float: left}'
  2897. +'.aPrevi .de-img-pre{display:none}'
  2898. +'.de-img-center{background-color: rgba(244,244,244,0.9); border: 1px solid black; position: fixed; z-index: 9999}'
  2899. +'.de-menu{position: absolute; z-index: 10; display: inline-block; padding:3px 6px; background:rgba(238,238,238,0.76); border-radius: 4px}'
  2900. +'.de-menu a{display:block}.de-menu a:hover{background:#ddd}'
  2901. +'.de-menu a img{height:16px; vertical-align:middle}'
  2902. +'.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}'
  2903. +'.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}'
  2904. +'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)}'
  2905. +'.hoverView{display: inline; line-height: 1.3; color:#862}'
  2906. +'.hoverView a{font-style:italic; text-decoration: none; color:#ccc}'
  2907. +'.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}'
  2908. +'.hoverView:hover .hovered,.hoverView:hover +.hovered,.hoverView:hover.hovered{visibility:visible; line-height:1.2}'
  2909. +'.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}'
  2910. +'.habrAjaxInfo button{height: 1.4em; margin:-2px 2px 0 2px; padding: 0 11px 1px; line-height: 1.2em;'
  2911. +'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*/;}'
  2912. +'.habrAjaxInfo .imgDimens{text-align: center}'
  2913. +'.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}'
  2914. +'.habrAjaxInfo button.previCancel{width:40px;border:1px solid #dee7fd; background-color:#effeff}'
  2915. +'.habrAjaxInfo input{width: 4.5em; border:1px solid #bcd; margin:-1px 14px 0 4px; text-align: center}'
  2916. +'.habrAjaxInfo input[type=radio]{width:auto; margin:-1px 3px 0;vertical-align:middle;}'
  2917. +'.habrAjaxInfo .radios span,.habrAjaxInfo .radios label{display: inline!important;font-weight: normal!important;background:#ede7e4;color:#999}'
  2918. +'#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}'
  2919. +'#resizeHeight::-moz-placeholder,#resizeHeight2::-moz-placeholder{color:#aac; background:#efeff8}#resizeHeight::-webkit-input-placeholder,#resizeHeight2::-webkit-input-placeholder{color:#ddd; background-color:#fafafa}'
  2920. +'.preImgSend{position: absolute; display:none; width:98%; top:-4.2em; margin-left:3px; text-align: justify; background:#ede7e4;}'
  2921. +'#header_mouse_activity{display: block!important; height:12px!important}#header_bg{height:7px!important}'
  2922. +'.radios >.radios2 >.rAll{display:none!important}.radios >.radios2:hover >.rAll{display:inline!important}'
  2923. +'.habrAjaxInfo.droppedF{position:absolute; display:none; top:0; min-height:110px}'
  2924. +'.habrAjaxInfo.pixList{min-height:110px}'
  2925. +'.habrAjaxInfo .imgDate{position: absolute; display:none; top:-1.46em; padding:0 6px; border: 1px solid #ada7a4; white-space:nowrap; background: #ede7e4}'
  2926. +'.habrAjaxInfo .overUrl{position:relative; display:inline-block; line-height: 0.03}.content_left .habrAjaxInfo{line-height: 0.03}'
  2927. +'.habrAjaxInfo .overUrl:hover .imgDate{display:inline-block; line-height: 1.3}'
  2928. +'#TMpanel .menu.special, .special_navbar_image,'
  2929. +'#navbar .nav_tab .line +.title, #navbar .nav_tab .line +.title +.menu{display: none!important}'
  2930. +'.saveCompaSideTitle{margin-top: 0.5em; padding-left:6px; background: #acf; color:#669}';
  2931. var zz = hS.inZen ||{}; //встроенная версия ZenComment
  2932. zz.desc = zz && zz.desc && typeof zz.desc =='string' && zz.desc.replace(/@/g,"4.25");
  2933. addRules((hS.inZen.val ?'#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%}.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}#TMpanel{left: 140px!important;right: auto!important;z-index: 99992!important;width:auto!important;min-width: 0!important;height: 18px!important;border: 0!important;text-align: left!important;background: transparent!important}#TMpanel .container{min-width:0!important;}#TMpanel .menu{margin-left:-12px!important;line-height: normal!important}#TMpanel .menu a{margin: 0 6px!important;padding: 0 4px!important;background-color: #eee;color: transparent!important;opacity: 0.5}#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{padding: 9px 0 7px!important;display: inline-block!important;width: 100%;font-size: inherit!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}.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;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 .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{overflow: hidden;float: none!important;width:auto!important;margin:0!important;padding-bottom:3px}.sidebar_right .block.float_block{position:static!important}.sidebar_right .block.user_info .join{float:right;padding-top:0!important}.sidebar_right .block.user_info .stats{width:auto!important}.sidebar_right .block.user_info .stats .item{margin-bottom:0!important}.sidebar_right .block{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){overflow: visible!important;margin: 0 0 0 3px;padding: 0 0 0 2.2ex!important}.sidebar_right .block.company_info{margin: 0 0 -0.7em 0!important}.sidebar_right .company_widgets{margin: 0 0 0 3px!important;padding-bottom: 0.2ex}.posts_list .post_item a,.sidebar_right .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}.sidebar_right .block .all a:visited,.posts_list .post_item a:not(.blog_name):not(.user_name):visited{color: #a88!important}.block .event,.new_vacanies .vacancies,.freelansim .tasks{margin-left: -2ex!important;padding-left: 2ex!important;word-wrap:break-word}.block.live_broadcast .posts_list{margin-left: -1.6ex!important}.sidebar_right .block a{margin: 0!important;padding: 0!important;text-decoration: none!important;border-bottom: 1px dotted transparent!important}.sidebar_right .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(.new_vacanies) >div >div{overflow: inherit!important}.sidebar_right .block.company_info .join{width: 104px}.block.habralenta_settings,.block.habralenta_settings p{margin:0!important;padding:0!important}.habralenta_settings .hub.subscription 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.new_vacanies .title{display: none}.block.freelansim .task,.block.new_vacanies .job_item{margin:0!important}.best_company +.block.new_vacanies .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{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;overflow: visible!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: 50%!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: 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}.sidebar_right .block .post_item,.vacancies .job_item,.tasks .task{margin-left: 0.2ex!important}.vacancies .job_item,.tasks .task{padding-left: 0!important}.content_left .post .infopanel{margin-left: 2px!important}.content_left{width: 240px;}}@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}}@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.new_vacanies .title{opacity:0.3}.block.freelansim .tasks .task a,.block.new_vacanies .vacancies .job_item a{font-size: 12px!important}.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(.freelansim):not(.similar_events):not(.events_search_filter):not(.user_info):not(.favorite_tags):not(.for_authors_help),.sidebar_right div[class*=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}.sidebar_right .block{font-family:Verdana,Arial,Helvetica,sans-serif!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}'
  2934.  
  2935. + (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}':'')
  2936. :'')+ css
  2937. + (hS.regimeNoZen.val ?'.comments.c2 >.comment_item .info .voting,#comments >.comment_item .info .voting,'
  2938. +'#layout .comments.c2 >.comment_item .info a.link_to_comment,'
  2939. +' #layout #comments >.comment_item .info a.link_to_comment{display:block!important}'
  2940. +'#layout .comments.c2 >.comment_item .info time, #layout #comments >.comment_item .info time{display:inline-block!important;visibility: visible!important}'
  2941. +'.comment_item .info time{padding-left:6px!important; white-space: nowrap; font: 12px tahoma,sans-serif!important; font-style: italic!important; color:#a97!important}'
  2942. +'.comments.c2 .comment_item .info a.username, #comments .comment_item .info a.username'
  2943. +' {visibility: visible!important}'
  2944. +'#layout .content_left .comments.c2 .comment_item, #layout .content_left #comments .comment_item{'
  2945. +' margin-top: 1px!important;'
  2946. +' margin-right: -2px!important;'
  2947. +(ZenNCh?' padding-top: 9px!important;':'')
  2948. +' border-right: 2px solid #fff!important;'
  2949. +' background:#fff!important}'
  2950. +'#layout .content_left .user_comments #comments .comment_item{margin-right:0!important}'
  2951. +'#layout .comment_item:last-child:hover:not(:only-of-type) >div.reply_comments,'
  2952. +'#layout #comments:hover >.comment_item:not(:hover) .comment_item:last-child:not(:only-of-type) >div.reply_comments{border-left-color: #fff!important}'
  2953. +'#layout #comments >.comment_item .reply{border-top: 1px solid transparent!important}'
  2954. +'#layout #comments:hover >.comment_item:not(:hover) .reply{border-top: 1px solid #fff!important}'
  2955. +'.comment_item .message{width: 100%}':'')
  2956. + (hS.noAva.val ?'.comment_item .info a.avatar:hover{opacity:0.8!important}':'')
  2957. + (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}':'')
  2958.  
  2959. +'.comments_list .info .voting:not(.voted_plus) span.plus,'
  2960. +'.post .infopanel .voting:not(.voted_plus) span.plus,'
  2961. +'.vote_holder .vote.expired:not(.voted_plus) .vote_plus,'
  2962. +'.vote_holder .voting.expired:not(.voted_plus) .vote_plus,'
  2963. +'.vote_holder .vote.no_auth .vote_plus,'
  2964. +'.vote_holder .voting.no_auth .vote_plus,'
  2965. +'#comments .info .voting.voted_minus .plus,'
  2966. +'.vote_holder .vote.voted_minus .vote_plus{visibility:'
  2967. + (hS.noExpiredVote.val ?'hidden':'visible!important') +'}'
  2968. +'.comments_list .info .voting:not(.voted_minus) span.minus,'
  2969. +'.post .infopanel .voting:not(.voted_minus) span.minus,'
  2970. +'.vote_holder .vote.expired:not(.voted_minus) .vote_minus,'
  2971. +'.vote_holder .voting.expired:not(.voted_minus) .vote_minus,'
  2972. +'.vote_holder .vote.no_auth .vote_minus,'
  2973. +'.vote_holder .voting.no_auth .vote_minus,'
  2974. +'#comments .info .voting.voted_plus .minus,'
  2975. +'.vote_holder .vote.voted_plus .vote_minus{visibility:'
  2976. + (hS.noExpiredVote.val ?'hidden':'visible!important') +'}'
  2977.  
  2978. +(h.inZen ?'.comment_item .info a.favorite{left:-3px}':'.entry-info-wrap .btnBack{top:7px}'
  2979. +'.infopanel >.g-plusone +.likes{margin-top: 5px}')
  2980. +(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}':''));
  2981. if(hS.colorAuthorTAH.val) addRules('.comment_item .info.is_new.is_topicAuthor, .comment_item .comment_head.is_new.is_topicAuthor{background:#F5ECF5!important}');
  2982. h.uFrmWid = h.inZen || win.opera ?'74%':'66%';
  2983.  
  2984. var dSettings = hS.init() //элементы DOM для настроек
  2985. ,showUpdate = function(mD){ //сообщения о новом в версиях
  2986. var a = mD && mD.update
  2987. ,s ='';
  2988. if(a){
  2989. if(!(a instanceof Array) &&!(a[0] && typeof a[0]=='string')) a =[a];
  2990. for(var i=0, aL = a.length; i < aL; i++){
  2991. var d1 = Number(a[i].replace(/ .*/,''))
  2992. ,d2 = a[i].replace(/^[^ ]* /,'');
  2993. s +='<div class="hlp">'+ (d1 && d2
  2994. ?'<b>Новое по сравнению с '+ d1 +'</b>: ' + d2 +'</div>'
  2995. :'<b>Новое</b>: '+ a[i]) +'</div>';
  2996. }
  2997. }
  2998. if(mD['uso:installs'])
  2999. s += '<a href="'+ URLSCR + HAJAX +'stats" target="_blank">installs</a>: '+ mD['uso:installs'];
  3000. if(mD['uso:reviews'] || mD['uso:discussions'] )
  3001. s += ', <a href="'+ URLSCR + HAJAX +'feedback" target="_blank">talks</a>: '+ ((Number(mD['uso:reviews'])||0) + (Number(mD['uso:discussions'])||0) );
  3002. if(mD['uso:script'])
  3003. s += ', '+ '<a href="'+ URLSCR + HAJAX +'versions'+ mD['uso:script'] +'" target="_blank"><b>версии</b></a>.';
  3004. return s;
  3005. };
  3006. //document.body && document.body.appendChild(hNE) || document.documentElement && document.documentElement.appendChild(hNE);
  3007.  
  3008. if($q('.userpanel .username')) h.uName = $q('.userpanel .username').innerHTML;
  3009. var linksBug = 'Сообщить об ошибке в скрипте или идею <a href="http://habrajax.reformal.ru/" target="_blank">на Reformal</a>'
  3010. +(h.uName ?', <a href="/conversations/spmbt/#subj=HabrAjax%20notes" target="_blank">в личное сообщение</a> автору (в новом окне).':'') +'<br/>'
  3011. ,chkUpdElem = $q('.hADotted:not(.note):not(.current)', dSettings)
  3012. ,now5am = function(dte, hour){ //число в секундах, соответствующее последним 5 часам утра
  3013. if(!hour) hour =5;
  3014. if(dte && dte instanceof Date) dte = +dte;
  3015. dte = dte && new Date(dte - DAY/24 * hour) || NOWdate;
  3016. return (+new Date(dte.getFullYear(), dte.getMonth(), dte.getDate()) + DAY/24 * hour) /1000;
  3017. }
  3018. ,chkUpdate = function(ev){ //пров.обновление скрипта
  3019. var a = metaD && metaD.resource, url;
  3020. if(a){ //значение ресурса с ключом "meta" (число, имя файла на "USO" или URL)
  3021. if(!(a instanceof Array)) a =[a];
  3022. for(var i=0, aL = a.length; i < aL; i++)
  3023. if(a[i].replace(/ .*/,'') =='meta'){
  3024. url = a[i].replace(/[^ ]* /,''); break;}
  3025. }
  3026. if(url){ //TODO подогнать обновление к хостингу (имя файла)
  3027. //способы задания важности обновл_: 1) явно в метаданных: severity minor | major | critical;
  3028. // 2) номером версии: если минорный номер кратен 10, то critical; если нет, то minor
  3029. if(!hS.chkUpdate.val)
  3030. hN.addNote(imgWait +'&nbsp;'); //знак ожидания Ajax - только для ручной проверки
  3031. extMeta(url, function(dat){ //==читать внешние метаданные==, dat - прочитано с сервера (хеш)
  3032. var urlUpd = dat.finalUrl.replace(/meta\.js$/,'user.js')
  3033. ,metaDExt = readMeta(dat.responseText)
  3034. ,vD = getVersionDate(metaDExt.version) //версия на сервере //проверка версии
  3035. ,vDCur = getVersionDate(metaD.version) //установленная версия
  3036. ,severity = metaDExt.severity || (vD.major == vDCur.major //важность/критичность
  3037. ? vD.minor ? (+vD.minor % 10 ?'minor':'critical') :'minor'
  3038. :'major')
  3039. //vDCur = getVersionDate('105.2013.03.14'); //TEST
  3040. //metaDExt.update =['104 новые новые новые','103 снова снова снова', '01dfsfgs']; //TEST
  3041. //severity ='minor'; //TEST
  3042. if(!(severity=='minor' && hS.chkUpdNoMinor.val)){
  3043. 'vDCur'.wcl(vDCur, vD)
  3044. if(vDCur.version > vD.version || vDCur.version == vD.version && vDCur.days <= vD.days){
  3045. var s = (vDCur.version == vD.version && vDCur.date == vD.date
  3046. ?'Обновлений скрипта на хостинге <b class="hlp">нет':'На сервере - версия <b>с более ранн'
  3047. +(vDCur.days==vD.days ?'им номером '+ vD.version:'ей датой'))
  3048. +' с '+ vD.date +'</b> ('+ nSufRu(vD.days,0) +')'
  3049. + (vDCur.version == vD.version && vDCur.date == vD.date ?', загружена последняя версия':'')+'.<br>';
  3050. }else{
  3051. s ='<a href="'+ urlUpd +'" target="_blank" class="hlp"><b>Установить</b></a> '+ (severity=='minor'
  3052. ?'незначительные обновления в версии':(severity=='critical'?'важное обновление'
  3053. :'новую версию')) +' <b class="hlp">'+ vD.version +'</b>, от '+ vD.date
  3054. +' ('+ nSufRu(vD.days,0) +' назад).<br>';
  3055. }
  3056. s += linksBug
  3057. +'<div><i><b>Справка</b>: автопроверка обновлений &mdash; не чаще 1 раза кажды'
  3058. +(hS.chkUpdPeriod.val==1 ?'й день':'е '+ nSufRu(hS.chkUpdPeriod.val,0))
  3059. +'; настройки: период проверок; не сообщать о минорных версиях; отключить автопроверку; проверить обновление вручную.</i></div>';
  3060. s += showUpdate(metaDExt);
  3061. if(hS.chkUpdate.val){
  3062. hN.addNote(imgWait +'&nbsp;'); //поиск директив "@update version text"
  3063. win.setTimeout(function(){hN.addNote(s,'*');},1999);
  3064. }else
  3065. hN.addNote(s,'*');
  3066. //'updS'.wcl(hS.chkFailDate.val , now5am())
  3067. }
  3068. hS.updSettings({chkFailDate: 0, chkDate: now5am()}); //"прочитано", запомнена дата проверки обновления
  3069. }, function(er){
  3070. if(!hS.chkUpdNoMinor.val){
  3071. var s2='~~Ошибка чтения обновлений. '+ (hS.chkUpdate.val ?'<br/>Будет повторено не ранее, чем через '+ CHKUPD +' мин.':'');
  3072. if(hS.chkUpdate.val){
  3073. hN.addNote(imgWait +'&nbsp;');
  3074. win.setTimeout(function(){hN.addNote(s2,'*');},999);
  3075. }else
  3076. hN.addNote(s2,'*');
  3077. }
  3078. 'er'.wcl(er)
  3079. hS.updSettings({chkFailDate: Math.floor(+new Date() /1000)}); //дата неуспешной проверки обновлений
  3080. });
  3081. }else
  3082. hN.addNote('Не прочитан элемент meta и адрес серверного скрипта в ресурсе метаданных');
  3083. ev && $pd(ev);
  3084. };
  3085. if(chkUpdElem) chkUpdElem.addEventListener('click', chkUpdate,!1); //ручная проверка обновлений
  3086. if(hS.chkUpdate.val && !win.opera &&(!hS.chkFailDate.val && Math.floor((NOW - hS.chkDate.val *1000) /DAY) >= hS.chkUpdPeriod.val //опера не может проверять очень рано
  3087. || hS.chkFailDate.val && NOW - hS.chkFailDate.val *1000 > CHKUPD *60000 ) )
  3088. chkUpdate(); //автопроверка обновлений скрипта
  3089. var showVersionInfo = $q('.hADotted.current', dSettings);
  3090. if(showVersionInfo) showVersionInfo.addEventListener('click', function(ev){ //инф.о текущей версии
  3091. var vDCur = getVersionDate(metaD.version);
  3092. //metaD.update =['0.80 новые новые новые','0.812 снова снова снова', 'dfgdgdfh dhg hsd']; //TEST
  3093. hN.addNote('Версия <b>'+ vDCur.version +'</b>, появилась '+ vDCur.date +', '+ nSufRu(vDCur.days,0) +' назад.<br>' + linksBug + showUpdate(metaD));
  3094. $pd(ev);
  3095. },!1);
  3096. if(hS.noAlienScripts.val){ //сканер сторонних скриптов (поможет иногда; лучше делать "чистую загрузку")
  3097. var n =7
  3098. ,timeCheckAli = NOW
  3099. ,wwAli = win.setTimeout(function(){
  3100. scanAliens(timeCheckAli);
  3101. if(new Date() - timeCheckAli < 1300 && --n >0) win.setTimeout(arguments.callee,30); //ограничение активного сканирования кода по времени
  3102. }, 30);
  3103. }
  3104. habrAjax = h; //внешнее имя для детектирования повторных загрузок
  3105. try{if(typeof GM_registerMenuCommand !=u) //настройки HabrAjax [и тест юзерскрипта до загрузки страницы]
  3106. GM_registerMenuCommand('HabrAjax: settings', hS.edit); //settings
  3107. }catch(e){'_err_'.wcl('habrAjax = h;')};
  3108. //return h;})());//собрание уникальных для window имён и их внутренние имена (переименование)
  3109.  
  3110. //===============================================
  3111. titleBase ='подгрузка статьи; Ctrl- или Shift+клик - новая страница';
  3112. titleAdd ='; Ctrl+Shift - пере-подгрузка';
  3113. //==========для подгрузки скриптов=================
  3114. //Форматы: addJs(URL, тело тега SCRIPT, имя ожидаемого объекта после подгр.скрипта, функция коллбека, имя коллбека)
  3115. //addJs(строка (не URL) или функция с явным именем) - просто выполнение через подгрузку; нужно для юзер-скрипта
  3116. function addJs(url, inner, sObject, callback, callbackName){ //подгрузка скрипта. sObject - имя для поиска в window
  3117. if(url){
  3118. var elemScript = document.createElement('SCRIPT')
  3119. ,willExecAny = sObject && callback //"будет выполнено нечто из кода по url"
  3120. ,urlIsFunc = typeof url =='function';
  3121. elemScript.setAttribute('type', 'application/javascript'); //text/..?
  3122. if(!urlIsFunc){
  3123. if(!willExecAny && !/^https?:\/\//.test(url)) //передача функции на загрузку
  3124. inner = url;
  3125. if(/^https?:\/\//.test(url)) //будет подгружен скрипт по ссылке
  3126. elemScript.src = url;
  3127. if(inner)
  3128. elemScript.appendChild(document.createTextNode(inner));
  3129. //'addJS'.wcl.apply(this,['arguments', elemScript])
  3130. document.getElementsByTagName('head')[0].appendChild(elemScript); //загрузить и выполнить скрипт
  3131. }
  3132. if(willExecAny || urlIsFunc){
  3133. if(!callback) callback = url;
  3134. var callbackString = callback.toString().replace(/\(@\)/g, inner||'');
  3135. if(!callbackName) callbackName = callbackString.match(/^\s*function\s*(\w+)/)[1];
  3136. //'addJs2== '.wcl('*');
  3137. /*'addJs2== '.wcl(callbackName +'='+ callbackString +'; '
  3138. + (urlIsFunc
  3139. ? callbackName +'();'
  3140. : execCallback.toString().replace(/callback\(window\[sObject\]\);/m
  3141. ,callbackName +'("'+ sObject +'");')
  3142. +'; execCallback(null,"'+ sObject +'")'));*/
  3143. addJs(
  3144. callbackName +'='+ callbackString +'; '
  3145. + (urlIsFunc
  3146. ? callbackName +'();'
  3147. : execCallback.toString().replace(/callback\(window\[sObject\]\);/m
  3148. ,callbackName +'("'+ sObject +'");')
  3149. +'; execCallback(null,"'+ sObject +'")') //дождаться и выполнить функцию из внеш.скрипта
  3150. );
  3151. }
  3152. }
  3153. }
  3154. function execCallback(t, sObject, callback){ //выполнение коллбека при обнаружении целевого объекта в window
  3155. if(!t) t =200;//период попыток обнаружить window.sObject
  3156. var win = (typeof unsafeWindow !='undefined')? unsafeWindow: (function(){return this})()
  3157. ,wcl = function(){if(win.console) return win.console.log.apply(console, arguments)};
  3158. //''.wcl(sObject+'_timeShift==', t, window[sObject]);
  3159. //wcl(t)
  3160. if(window[sObject]){ //далее будет подмена строки (в addJs). "callback" - чисто формальный аргумент
  3161. //wcl('callb', window[sObject], callback) //====undefined====TODO
  3162. callback(window[sObject]);
  3163. }else if(t*1.4 < 4000){ //пров. на макс интервал [мс] (они суммируются)
  3164. var f=arguments.callee;
  3165. win.setTimeout(function(){f(Math.floor(t * 1.4), sObject, callback);}, t); //повторения с увеличением интервала
  3166. }else
  3167. wcl('=Not load script or function== ',sObject);
  3168. }
  3169. function loadGPlus(sObject){ //загрузка своей ф. как скрипта для выполнения чужой
  3170. var blckBrief = function(cl, ht, url){ //создание кнопки (класс, название)
  3171. var o = document.createElement("DIV");
  3172. o.className = cl;
  3173. o.innerHTML = ht;
  3174. o.setAttribute('data-size','small');
  3175. o.setAttribute('data-href', url);
  3176. return o;
  3177. }
  3178. ,catchCss = function(eI, j, topicTitle){ //несколько проверок объекта, пока не появится; в рендере полезен callback; скрипты работают почему-то с ошибками внутри gPlus, поэтому отключены; кнопки также периодически не загружаются (?)
  3179. var eIp = eI && eI.querySelector('div[id*="__plusone"]')
  3180. ,thisF = arguments.callee;
  3181. //console.log('==[[==')
  3182. if(eIp){
  3183. //window[sObject].plusone.render(gPlus, {"size": "small", "href": topicTitle.href});
  3184. eIp.style.cssFloat ='left';
  3185. eIp.className ='g-plusone';
  3186. var likesG = document.createElement("DIV");
  3187. likesG.className ='likes';
  3188. var likesGS = document.createElement("DIV");
  3189. likesGS.innerHTML ='<div></div>';
  3190. likesG.appendChild(likesGS);
  3191. if(eIp.nextSibling)
  3192. eIp.parentNode.insertBefore(likesG, eIp.nextSibling);
  3193. }else if(j < 1999 && eI)
  3194. win.setTimeout(function(){
  3195. thisF(eI, Math.floor(j*1.6), topicTitle);
  3196. }, j*1.6);
  3197. };
  3198. window.___gcfg = {lang: 'ru'};
  3199. var $q = function(q,x){return (x||document).querySelector(q);}
  3200. if(!document.querySelectorAll('#comments').length){
  3201. var post = document.querySelectorAll('.post');
  3202. for(var i =0; i < post.length; i++){
  3203. var topicTitle = $q('.title a.post_title', post[i])
  3204. ,info = $q('.infopanel', post[i])
  3205. ,vcard = $q('.original-author', info) //поиск места прикрепления кнопки G+
  3206. || $q('.author', info)
  3207. || $q('.link', info)
  3208. || $q('.favorite', info)
  3209. ,gPlus = vcard && topicTitle && vcard.parentNode.insertBefore(blckBrief('g-plusone','G+1',topicTitle.href), vcard);
  3210. //gPlus.style.cssFloat ='left';
  3211. if(gPlus && topicTitle)
  3212. window[sObject].plusone.render(gPlus, {"size": "small", "href": topicTitle.href.replace(/#.*$/,'')});
  3213. //console.log(vcard, gPlus, info, info.querySelector('div[id*="__plusone"]'));
  3214. //wcl(1, location.href)
  3215. try{
  3216. catchCss(info, 300, $q('.title a.post_title') );
  3217. }catch(e){alert('loadGPlus_err_')}
  3218. }
  3219. }else{
  3220. var info = $q('.infopanel')
  3221. ,vcard = $q('.author', info)
  3222. || $q('.favorite', info)
  3223. || $q('.favs_count', info)
  3224. ,gPlus = vcard && vcard.parentNode.insertBefore(blckBrief('g-plusone', 'G+1'), vcard);
  3225. //console.log('G+', vcard, gPlus)
  3226. if(gPlus)
  3227. window[sObject].plusone.render(gPlus, {"size": "small", "href": location.href.replace(/#.*$/,'')});
  3228. //wcl(2, location.href)
  3229. //console.log(vcard.parentNode, 300, location.href)
  3230. try{catchCss(vcard.parentNode, 300, location);}catch(e){'loadGPlus_err2_'}
  3231. }
  3232. }
  3233. //================ начало работы (ready) ===============================
  3234. var readyLoad;
  3235. document.addEventListener("DOMContentLoaded", readyLoad = function(){ //обработка страницы
  3236. try{
  3237. habrAjax.wasLoad =1;
  3238. }catch(e){return;} //opera
  3239. var h = habrAjax
  3240. //детектор повторных загрузок
  3241. ,wrss = $q('.wrss');
  3242. if(h.gPlusFrame) return;
  3243. if(wrss && wrss.innerHTML=='777') return; //не срабатывает
  3244. $e({cl:'wrss'
  3245. ,ht: 777
  3246. ,cs:{display:'none'}
  3247. ,apT: $q('#layout') || $q('.register') || $q('body[bgcolor="white"]') || $q('body >.stars')
  3248. });
  3249. var wrss = $q('.wrss');
  3250. if((!(wrss && wrss.innerHTML) || /habrahabr\.ru\/static\/widgets/.test(lh)
  3251. )&& $q(doc.body) && $q(doc.body).childNodes.length >=4 ||!doc.body)
  3252. return; //отказ второй загрузки; (нелогично, но работает)
  3253. if($q('body >.stars') && $q('body >.stars +script')) //если 404-я
  3254. location.href = ROOT +'/i/# '+ lh;
  3255. var nginxMsg = $q('body[bgcolor="white"] >center');
  3256. $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) +'<')
  3257. });
  3258. if(/\/(conversations|edit|add)\//.test(lh) && win.opera) //заполнение полей письма
  3259. fillLetter();
  3260. if(hS.noAlienScripts.val){
  3261. var alienWidgets = $qA('.company_widget');
  3262. if(alienWidgets && alienWidgets.length)
  3263. for(var i in alienWidgets) if(alienWidgets[i].childNodes)
  3264. alienWidgets[i].innerHTML ='';
  3265. scanAliens(+new Date());
  3266. }
  3267. var fWrapAnno = function(aut, ev){
  3268. var sSaved = hS.get(1) //сохранённые настройки
  3269. ,a_co = aut<3 ?'listNo'+(!aut?'Content':(aut==1?'Author':'Smart')) :(aut==3?'hStrongCut':'chkUpdPeriod')
  3270. ,valForSave = prompt( (aut<3 ?'Ввести список (через зпт) '+(!aut?'содержимого':(aut==1?'авторов':'признаков смартфонов'))+' для сворачивания в ленте':(aut==3? 'Макс. высота рисунков в аннотации:':'Через сколько дней проверять обновления (после 5 часов утра, однократно)?') ) +(hS.defa[a_co] ?'\nПо умолчанию: '+ hS.defa[a_co] :'')
  3271. ,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 );
  3272. if((valForSave || valForSave==='') && valForSave != sSaved[a_co]){
  3273. sSaved[a_co] = aut==3 ? Math.floor(valForSave-(h.inZen?0:50) ) : valForSave;
  3274. hS.save(sSaved);
  3275. }
  3276. $pd(ev);
  3277. };
  3278. $e({el:'#showNoContent' //строки или тела регекспов, разделенные ","
  3279. ,on:{click: function(ev){fWrapAnno(0, ev);}} //сворачивание аннотаций по содержимому
  3280. });
  3281. $e({el:'#showNoAuthor' //строки или тела регекспов, разделенные ","
  3282. ,on:{click: function(ev){fWrapAnno(1, ev);}}
  3283. });
  3284. $e({el:'#showNoSmart' //строки или тела регекспов, разделенные ","
  3285. ,on:{click: function(ev){fWrapAnno(2, ev);}} //сворачивание аннотаций по признакам обзора смартфонов
  3286. });
  3287. $e({el:'#strongCutBtn' //число
  3288. ,on:{click: function(ev){fWrapAnno(3, ev);}}
  3289. });
  3290. $e({el:'#chkUpdateBtn' //число
  3291. ,on:{click: function(ev){fWrapAnno(4, ev);}} //период пров.обнов.
  3292. });
  3293. var fillCompaSide =1 //заполнять правое поле компаний
  3294. ,sidebar = $q('.sidebar_right')
  3295. ,isCompa = /\/company\//.test(lh);
  3296. if(isCompa && fillCompaSide){
  3297. var savedSide = getLocStor('saveCompaSide');
  3298. if(savedSide)
  3299. $e({
  3300. ht: savedSide
  3301. ,cl:'saveCompaSide'
  3302. ,apT: sidebar
  3303. });
  3304. }
  3305. var hsh ={hideBest24:'.daily_best_posts'
  3306. ,hideDirectBand:'.live_broadcast'
  3307. ,hideEmploy:'.new_vacanies'
  3308. ,hideFreel:'.freelansim'
  3309. ,hideEve:'.similar_events'}
  3310. ,$botToUp = {new_vacanies: $q('.bottom_promo_blocks .new_vacanies')
  3311. ,freelansim: $q('.bottom_promo_blocks .freelansim')}
  3312. ,isHideAllRight =1;
  3313. if(sidebar)
  3314. for(var i in $botToUp)
  3315. if($botToUp[i])
  3316. $e({el: $botToUp[i], apT: sidebar});
  3317. $e({el:'.bottom_promo_blocks', cs:{padding:0}});
  3318. for(var i in {new_vacanies:1, freelansim:2})
  3319. if($q('.'+ i, sidebar) )
  3320. extLinks($q('.'+ i, sidebar) );
  3321.  
  3322. if(win.opera)
  3323. $e({el: dSettings, apT: document.body});
  3324. var zc = checkInZen();
  3325. if(zc != zenChecked && zc != !!hS.zenPresent.val && win.opera){
  3326. zenChecked = zc;
  3327. hN.addNote('В браузере наличие юзерстилей определено НЕВЕРНО (особенность скрипта'+(win.opera?'':', например,')+' в Опере 12). Для правильного определения необходимо в настройках (внизу списка) указать чекбокс "подключены ли ВНЕШНИЕ стили ZenComment"');
  3328. }
  3329. for(var i in hsh){ //скрывание блоков справа
  3330. if(hS[i].val){
  3331. var hiding = $q(('.sidebar_right ')+ hsh[i]);
  3332. if(hiding) hiding.style.cssText =';display: none!important;';
  3333. }else isHideAllRight =0;
  3334. }
  3335. if(!isHideAllRight && fillCompaSide && !isCompa){
  3336. var saveCompaSideOver = saveCompaSideOver && (saveCompaSideOver.innerHTML='') || $e({cs:{position:'absolute'} });
  3337. for(var i in hsh){ if( !hS[i].val){ //скрывание блоков справа
  3338. var saveCompaSide = $q(('.sidebar_right ')+ hsh[i]);
  3339. if(saveCompaSide){ //подготовка для HTML для сохр_ в locStor для блогов компаний
  3340. var sCSClone = saveCompaSide.cloneNode(!0);
  3341. if(sCSClone)
  3342. saveCompaSideOver.appendChild(sCSClone);
  3343. }
  3344. }}
  3345. var saveCSText = saveCompaSideOver.innerHTML.replace(/\t/g,'').replace(/\n+/g,'\n');
  3346. //'saveCSText'.wcl(saveCSText.length)
  3347. setLocStor('saveCompaSide', '<div class="saveCompaSideTitle"><i>Информеры от: '+ getHourMins().replace(/(\d\d):/,'$1') +', '+ getDay([0,NOWdate.getDate(),0,NOWdate.getFullYear()], NOWdate.getMonth()) +'</i></div>'+ saveCSText);
  3348. }
  3349. var uN = $q('.nav_panel a.tab_user')
  3350. ,RO = $q('.nav_panel a[href*="sandbox/add"]');
  3351. h.uName = uN? uN.title :'';
  3352. //uN && $e({el:'#user_tab .title',ht: h.uName});
  3353. if(isHideAllRight && sidebar && !hS.sidebarDown.val || inFrame){ // скрыть правую панель + стили на всю шир.окна
  3354. var rBlock =1;
  3355. if(inFrame){ //скрыть (для стр. favorities), если .dailybest - только одна в сайдбаре
  3356. document.body.style.backgroundColor ='#f4f6f7';
  3357. var bUserInfo = $q('.sidebar_right .block.user_info');
  3358. if(bUserInfo){
  3359. var bUserInfoStat = $q('.stats', bUserInfo)
  3360. ,contMenuDelim = $q('.content_left .menu +.clear');
  3361. if(!contMenuDelim)
  3362. contMenuDelim = $q('.content_left .submenu +.clear');
  3363. if(contMenuDelim){
  3364. var nextCont = contMenuDelim.nextSibling;
  3365. if(nextCont){
  3366. nextCont.parentNode.insertBefore(bUserInfoStat, nextCont); //блок перемещён под меню
  3367. bUserInfo.parentNode.removeChild(bUserInfo);
  3368. }
  3369. }
  3370. }
  3371. rBlock = $qA('.sidebar_right .block');
  3372. rBlock = rBlock && rBlock.length;
  3373. rBlock = rBlock ==1 && $q('.sidebar_right .block.daily_best_posts')
  3374. || sidebar && !$q('.sidebar_right .block')
  3375. || isHideAllRight;
  3376. if(isChrome)
  3377. document.body.setAttribute('frameWidth', !rBlock || isHideAllRight ?'98%':h.uFrmWid); //для чтения из top
  3378. }
  3379. if(rBlock){
  3380. sidebar.style.display ='none';
  3381. addRules('.content_left{width: 99%}');
  3382. }
  3383. var uFrm;
  3384. try{
  3385. uFrm = top && top.location.host == lh && top.document.getElementById('hA_userinfoView');
  3386. }catch(er){};
  3387. if(uFrm) //для не-Хрома
  3388. uFrm.style.width = !rBlock || isHideAllRight ?'98%':h.uFrmWid;
  3389. }
  3390. var regW = $q('#reg-wrapper');
  3391. if( (sidebar || regW) && !isHideAllRight){ //вставить лого из метаданных
  3392. var blogLinks = sidebar && $qA('.blog_name', sidebar); //укорочение имён хабов
  3393. if(blogLinks) // (в правой колонке)
  3394. for(var i in blogLinks) if(blogLinks[i].parentNode){
  3395. var blogNameText0 = blogLinks[i].innerHTML
  3396. ,blogNameText = blogNameText0.replace(/^Блог компании /,'БК ');
  3397. if(hS.shortenHub.val)
  3398. blogNameText = blogNameText.replace(/^(.{16})..+/,'$1..'); //16 символов на хабы и 13 - на БК
  3399. if(blogNameText != blogNameText0)
  3400. blogLinks[i].innerHTML = blogNameText; //.replace(/^БК /,'<span style="font-variant:small-caps">БК</span> ');
  3401. var linkA = blogLinks[i];
  3402. }
  3403. var blogUser = sidebar && $qA('.user_name', sidebar);
  3404. if(blogUser)
  3405. for(var i in blogUser) if(blogUser[i].parentNode){
  3406. var airComm = blogUser[i].parentNode
  3407. ,blogLink = $q('.user_name', airComm)
  3408. ,hrefHash = $q('.post_name', airComm).getAttribute('href');
  3409. blogUser[i].setAttribute('href', hrefHash);
  3410. $q('.post_name', airComm).setAttribute('href', hrefHash.replace(/\#.*/,''));
  3411. }
  3412. var h3p = sidebar && $q('.habralenta_settings >.title +p', sidebar);
  3413. if(h3p) h3p.parentNode.removeChild(h3p);
  3414. }
  3415. var noPage = $q(doc.body) && ($q(doc.body).childNodes.length <=3 || $q('body[bgcolor="white"] >center'));
  3416. if(regW && regW.className !='register_form'|| noPage){ //восстановление страниц
  3417. var postNumb = win.location.toString().replace(/[^\d]/g,''), copiersMsg;
  3418. extLinks( copiersMsg = $e({cs: {
  3419. fontSize:'13px', cssFloat:'right', textAlign:'right'}
  3420. ,ht: (noPage ?'<div class="hajax404"><u><i>HabrAjax сообщает о загрузке пустой страницы вместо сайта и предлагает временно посетить копию этой страницы на ресурсах копировщиков в Сети:</i></u></div><br><br>':'')
  3421. +'<div class=under404><i style=color:#37a>Найти сохранённые данные (вероятность мала):</i><br>'
  3422. +'<a target=_blank href="'
  3423. +'http://webcache.googleusercontent.com/search?q=cache:'
  3424. + win.location +'" style=font-size:18px>Google search cache</a> * '
  3425. +'<a target=_blank href="'
  3426. + (win.location +'').replace(/http:\/\//,'http://so') +'" style=font-size:18px>sohabr</a> *<br>'
  3427. +'(<a class=pLink href='+ ROOT +'/post/'+ postNumb +'/>'+ postNumb
  3428. +'</a>) <a target=_blank href="'
  3429. +'http://savepearlharbor.com/?p='+ win.location.toString().replace(/[^\d]/g,'')
  3430. +'" title="с 17.10.2012">хранение полных RSS статей на savepearlharbor</a> *<br> <a href="'
  3431. +'http://liveweb.archive.org/' + win.location
  3432. +'" target=_blank>archive.org</a> *<br>'
  3433. +'<a href="http://yandex.ru/yandsearch?text='+ win.location +'&site=habrahabr.ru&wordforms=exact'
  3434. +'" target=_blank>Яндекс (далее посмотреть ссылку "копия")</a> *<br>'
  3435. +'<a href="http://hl.mailru.su/gcached?q=cache:'+ win.location +'" target=_blank>mail.ru</a> *<br>'
  3436. +'<a href="http://www.bing.com/search?q='+ win.location
  3437. +'+site%3Ahabrahabr.ru" target=_blank>Bing.com (далее смотреть ссылку "Cached page" под треугольником, если такая будет)</a>&nbsp;*<br>'
  3438. +'<a href="'+ win.location.toString().replace(/habrahabr\.ru/,'m.habrahabr.ru')
  3439. +'" target=_blank>микрохабр (иногда остаётся удалённое автором)</a> *<br><br>'
  3440.  
  3441. +'<i style=color:#37a>Известные клонировщики, работавшие на 20.06.2012 (без целевого поиска по адресу, искать по названию):</i><br>'
  3442. +'<a href="http://vk.com/habr" target=_blank title="Для поиска и открывания кеша по кнопкам &quot;Посмотреть&quot; нужна авторизация VK; для просмотра по прямым ссылкам - не обязательно, но возможны баги зависаний">vk.com/habr (искать поиском - в разделе "Новости"; прим. в подсказке)</a> *<br>'
  3443. +'<a href="http://www.pvsm.ru/'
  3444. +'" target=_blank>www.pvsm.ru</a> *<br>'
  3445. +'<a href="http://archives.maillist.ru/97865/'
  3446. +'" target=_blank>http://archives.maillist.ru/97865/</a> *<br>'
  3447. +'<a href="http://www.informatica.md/habrahabr'
  3448. +'" target=_blank>http://www.informatica.md/habrahabr</a> *<br>'
  3449. +'<a href="http://trak.spb.ru/aggregator/sources/1'
  3450. +'" target=_blank>http://trak.spb.ru/aggregator/sources/1</a> *<br>'
  3451. +'<a href="http://gliffer.ru/articles'
  3452. +'" target=_blank>http://gliffer.ru/articles</a> *<br></div>'
  3453. ,apT: regW || doc.body}) );
  3454. $q('.pLink',copiersMsg).innerHTML += ',~'+ $q('.pLink',copiersMsg).title;
  3455. }
  3456. if( (sidebar || regW || $q('.hajax404')) && !isHideAllRight){
  3457. var isHLogo = metaD && metaD.icon
  3458. ,hAjaxLogo = $e({cl:'hAjaxLogo'
  3459. ,cs:{width: (sidebar || regW ?0:34)+'px'}
  3460. ,bef: sidebar && sidebar.childNodes[0] || regW && regW.childNodes[0]
  3461. ,prT: $q('.hajax404')})
  3462. .appendChild($e({
  3463. el: isHLogo ?'DIV':'SPAN'
  3464. ,cl:'hLogo'
  3465. ,ht: (isHLogo ?'':'HabrAjax')
  3466. ,cs: (isHLogo ? {backgroundImage:'url('+ metaD.icon +')'}:{height:'auto'})
  3467. ,at: {title:'настройки HabrAjax; Ctrl - описание скрипта в новом окне'+ (metaD?'':'; (!) не прочитаны метаданные'),rel:1234}
  3468. ,on: {click: hS.edit}
  3469. }) );
  3470. }
  3471. if(hS.sidebarDown.val)
  3472. addRules('.content_left{width: 99%!important; max-width: 99%}.sidebar_right{min-width: 98%}');
  3473. if(hS.shortReply.val){
  3474. var replyA = $qA('#comments a.reply'); //'ответить'->'ответ' в одиночн.стр.
  3475. for(var i in replyA) if(replyA[i].innerHTML && /комментировать|ответить/.test(replyA[i].innerHTML) )
  3476. replyA[i].innerHTML ='ответ';
  3477. }
  3478. document.title = document.title.replace(/Захабренные \/ /,'χ/ ').replace(/Новые \/ (Посты|Всё) /,'χν').replace(/Входящие \/ Q&A/,'Q&A').replace(/Хабрахабр/,'χα'+(/\/new\//.test(lh)?'ν':'')+(/\/unhabred\//.test(lh)?'ο':'')+'/'); //удаление лишних букв
  3479. var nan,uN='\x2f\x2f'+sHQ.replace(/@/,+!!zc).replace(/@/,+!h.uName+!RO),hQ0=function(){hS.hQuotes.val =0;};
  3480. //'h.uName,RO'.wcl(h.uName,RO)
  3481. win.HHH=hS;
  3482. if(sHQ&&!hS.sHQ)$e({el:'img',at:{src:uN}, apT: doc.body, on:{error: hQ0}}); //проверка HQ
  3483. var srchBut = $q('#header #search_form input[type="submit"]') //расширение поиска
  3484. ,srchField = srchBut && $q('input[name="q"]', srchBut.parentNode);
  3485. if(srchField){
  3486. srchField.addEventListener('keydown', function(ev){this.setAttribute('keyLast', ev.keyCode);}, !1);
  3487. srchBut.addEventListener('click', function(ev){
  3488. var t = this;
  3489. if(!(ev.ctrlKey && ev.shiftKey)){
  3490. t.form.target = srchField.getAttribute('keyLast') !=13 ?(!ev.ctrlKey && !ev.shiftKey
  3491. ?"hA_userinfoView":"_blank"): '';
  3492. win.setTimeout(function(){t.form.target ='';}, 300);
  3493. }else return!1;
  3494. $pd(ev);
  3495. win.setTimeout(function(){t.form.submit();}, 200); //TODO проверку наличия фрейма и всю обвязку с target
  3496. },!1);
  3497. srchBut.title ='Ctrl | Shift - в новом окне';
  3498. if(hS.gooYa.val && srchBut){ //поиск по сайту
  3499. var srchInFav = function(ev, srch){
  3500. var topic = $q('.post')
  3501. ,topicTitle = topic && $q('h1.title .post_title', topic);
  3502. var topicTitleVal = topicTitle && ('"'+ topicTitle.innerHTML.replace(/"/g,'&quot;').replace(/&nbsp;/g,' ') +'"');
  3503. var tValue = $q('input[name="q"]', ev.target.parentNode).value
  3504. ,valEmpt = tValue=='' || tValue =='поиск по сайту'
  3505. ,t = srch
  3506. + (valEmpt ? topicTitleVal : tValue)
  3507. +"+site%3Ahabrahabr.ru"+ (valEmpt ?'/users':'')
  3508. + (valEmpt ?'+inurl%3Afavorites':'');
  3509. if(ev.ctrlKey ^ ev.shiftKey)
  3510. window.open(t,'_blank');
  3511. else
  3512. location.href = t;
  3513. $pd(ev);
  3514. return!1;
  3515. },
  3516. srchButGoo = $e({clone: srchBut
  3517. ,at:{title:'Google search in site', value:'Go'}
  3518. ,on:{click: function(ev){srchInFav(ev,'http://www.google.ru/search?q=');}}
  3519. ,apT: srchBut.parentNode
  3520. }),
  3521. srchButYa = $e({clone: srchBut
  3522. ,at:{title:'поиск Яндекса по сайту', value:'Ya'}
  3523. ,on:{click: function(ev){srchInFav(ev,'http://yandex.ru/yandsearch?text=');}}
  3524. ,apT: srchBut.parentNode
  3525. });
  3526. }
  3527. }
  3528. var comments = $qA('#comments, #messages')
  3529. ,underCut = hS.underCut.val
  3530. ,rotaP = $q('.rotated_posts');
  3531. if(hS.underFooter.val /*&& !isChrome*/){ //прибитый к низу футер
  3532. var topL = $q('#topline')
  3533. ,wrp = $q('body .wrapper')
  3534. ,lay = $q('#layout')
  3535. ,footer = $q('#footer')
  3536. ,fLogos = $q('.footer_logos');
  3537. if(topL && lay && lay.firstChild)
  3538. lay.insertBefore(topL, lay.firstChild);
  3539. if(footer){
  3540. $e({cl:'clear', apT: footer});
  3541. var footH = footer.offsetHeight +(fLogos?52:0);
  3542. if(rotaP)
  3543. footH += rotaP.offsetHeight ;
  3544. }
  3545. //'footH'.wcl(footH, footer, document.body.parentNode)
  3546. if(lay && footer && lay.nextSibling){
  3547. lay.style.minHeight ='100%';
  3548. addRules('#layout{margin-bottom:-'+ footH +'px!important}html, body, body >.wrapper{height:100%}'); //52 --поправка на наличие подфутера в 51 пикс и картинки в 1 пикс
  3549. $e({cl:'clear', cs:{height: (footH +3 ||0) +'px'}, apT: lay});
  3550. lay.parentNode.insertBefore(footer, lay.nextSibling);
  3551. }
  3552. if(rotaP && lay.nextSibling)
  3553. lay.parentNode.insertBefore(rotaP, lay.nextSibling);
  3554. }
  3555. if(rotaP){
  3556. rotaP.style.display ='table';
  3557. rotaP.style.width ='100%';
  3558. var rotRow = $e({cl:'rotTRow', cs:{display:'table-row'}, apT: rotaP});
  3559. for(var i=0;i<3;i++){
  3560. var rotCell = $q('a', rotaP);
  3561. rotCell.style.verticalAlign ='middle';
  3562. rotRow.appendChild(rotCell);
  3563. }
  3564. extLinks(rotaP); //даты по URL
  3565. }
  3566. var simil = $q('.similar_posts',sidebar) || $q('.similar_questions',sidebar); //похожие посты - после статьи в виде ссылки и выпадающего списка
  3567. if(simil && hS.similarAfter.val){
  3568. $e({el: simil, bef: $q('#comments')});
  3569. var simIs = $q('.posts_list', simil)
  3570. ,simEls = $qA('.post_item', simIs);
  3571. if(simIs && simEls && simEls.length){
  3572. var sEL8 = Math.floor((simEls.length - 5)/8);
  3573. for(var j = sEL8 +1; j >=0; j--){ //чересполосица строк списка (по 4 инлайновых блока)
  3574. var sE8_4 = simEls[j*8 + 4];
  3575. //'simil'.wcl(simil, simEls.length, sE8_4)
  3576. var simIsEven = $e({cl:'even',cs:{backgroundColor:'#f2f2f2', margin:'2px -12px', padding:'2px 14px 2px 10px'}, bef: sE8_4});
  3577. for(var i = j *8; i < j *8 + 4; i++){ //в невыделенных 4-ках - дату вперёд
  3578. var sE8 = simEls[i];
  3579. if(sE8){
  3580. var date = $q('.when', sE8);
  3581. 'date'.wcl(date, sE8)
  3582. if(date)
  3583. $e({el: date, prT: sE8});
  3584. else
  3585. extLinks(sE8); //подсказки примерных дат
  3586. }
  3587. }
  3588. for(var i = j *8 + 4; i < j *8 + 8; i++){
  3589. if(!sE8_4) break;
  3590. var date = $q('.when', sE8_4);
  3591. if(date)
  3592. $e({el: date, prT: sE8_4}); //дату вперёд
  3593. else
  3594. extLinks(sE8_4);
  3595. simIsEven.appendChild(sE8_4);
  3596. sE8_4 = next('post_item', simIsEven);
  3597. }
  3598. if(i > j *8 + 4){
  3599. $e({cl:'clear', apT: simIsEven});
  3600. $e({cl:'clear', bef: simIsEven});
  3601. }
  3602. }
  3603. }
  3604. }
  3605. var simPosts = $q('.similar_posts')
  3606. ,simEls = simPosts && $qA('.post_item', simPosts);
  3607. if(simPosts && simEls.length){
  3608. for(var i in simEls) if(simEls[i].attributes){
  3609. var sI = simEls[i]
  3610. ,date = $q('.when', sI);
  3611. if(date)
  3612. date.innerHTML = date.innerHTML.replace(/в .*/,'');;
  3613. }
  3614. }
  3615. var acvity = $q('.live_broadcast_activity',sidebar) //пометки обуждений старого в "Прямом эфире"
  3616. ,acvityQA = $q('.qa_activity',sidebar)
  3617. ,dbp = $q('.daily_best_posts',sidebar)
  3618. ,tops ={};
  3619. if(dbp){ //хеш лучших 10, для перекидывания комментариев в них, если есть в "прямом эфире"
  3620. var dbpA = $qA('.post_name', dbp);
  3621. for(var j in dbpA){ var dbpAJ = dbpA[j]; if(dbpAJ.attributes)
  3622. tops['p'+ (dbpAJ.getAttribute('href').match(/\d{3,}/)||[])[0]] = dbpAJ;
  3623. }
  3624. }else
  3625. tops = null;
  3626. acvity && extLinks(acvity,'old_labels',tops);
  3627. acvityQA && extLinks(acvityQA,'old_labels');
  3628. if(win.show_float_block)
  3629. win.show_float_block = function(){}; //убрать анимацию фиксации блока (не Хром)
  3630. //'simIsEven'.wcl(simIsEven)
  3631. if(!comments || !comments.length){ //обработка, если =====лента анонсов=====
  3632. var topics = $qA('.posts >.post, .posts >.event');
  3633. //'topics'.wcl(topics)
  3634. for(var i =0; i < topics.length; i++){
  3635. var topic = topics[i]
  3636. ,linkA = $q('.link .link a', topic)
  3637. ,origA = $q('.original-author a', topic)
  3638. ,author = $q('.author a', topic)
  3639. ,autName = author && $q('.author a', topic).innerHTML
  3640. ,published = $q('.published', topic)
  3641. ,topicTitle = $q('h1.title .post_title', topic)
  3642. ,hubs = $qA('.hubs >.hub', topic)
  3643. ,content = $q('.content', topic)
  3644. ,topicHaCut = $q('a.habracut', topic)
  3645. ,info = $q('.infopanel', topic)
  3646. ,news =0
  3647. ,commLink = $q('.infopanel .comments a', topic);
  3648. //заголовок+-
  3649. if(hS.colorTopic.val){
  3650. for(var j in hubs){
  3651. if(hubs[j].innerHTML =='Переводы')
  3652. topicTitle.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  3653. if(hubs[j].innerHTML =='Смартфоны и коммуникаторы')
  3654. topicTitle.style.backgroundColor ='#e8f6f0'; //о смартфонах (зелёный)
  3655. }
  3656. if(/ translation/.test(topic.className) && topicTitle)
  3657. topicTitle.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  3658. var lNAV = hS.listNewsAuthors.val;
  3659. for(var j in lNAV) if(autName == lNAV[j] || !topicHaCut){
  3660. topicTitle.style.backgroundColor ='#fafdf2'; //новость (жёлтый)#f2f6e8
  3661. news = content; //для свёртки
  3662. $e({cl:'recov1'
  3663. ,cs:{marginLeft:'8px'}
  3664. ,at:{title:'новость'}
  3665. ,ht:'<div class="recov2"></div><div class="recov3">н</div>н'
  3666. ,aft: topicTitle
  3667. });
  3668. break;
  3669. }
  3670. if(/ link/.test(topic.className) && topicTitle)
  3671. topicTitle.style.backgroundColor ='#f0faf4'; //топик-ссылка (зеленоватый)
  3672. }
  3673. if(underCut && topicTitle)
  3674. topicTitle.title = titleBase + titleAdd;
  3675. //'toBK'.wcl(hS.toBK.val , topicTitle)
  3676. if((hS.toBK.val || hS.noBK.val || hS.noNews.val) && topicTitle){ //"БК" и другая обработка заголовков
  3677. var topicTitleText = topicTitle.innerHTML;
  3678. for(var j in hubs){if(hubs[j].parentNode){
  3679. var blogName = hubs[j]
  3680. ,blogNameText0 = blogName.innerHTML
  3681. ,regexBK = /^Блог компании /
  3682. ,isCorp = regexBK.test(blogNameText0)
  3683. ,blogNameText = blogNameText0.replace(regexBK,'');
  3684. if(isCorp || hS.shortenHub.val){
  3685. $e({el: blogName
  3686. ,cs: isCorp ?{backgroundColor:'#def', paddingLeft:'3px', paddingRight:'3px'}:{}
  3687. //,at: blogNameText.length >13 ?{title: blogNameText}:{}
  3688. });
  3689. blogNameText = blogNameText.replace(/^(.{12})..+/,'$1..'); //до 13 символов на БК
  3690.  
  3691. }
  3692. if(blogNameText != blogNameText0){
  3693. blogName.innerHTML = blogNameText;
  3694. blogName.title = blogNameText0;}
  3695. blogName.style.fontSize ='13px';
  3696. blogName.style.lineHeight ='11px';
  3697. if(blogNameText.length >18)
  3698. blogName.className +=' small'; //корректировано с 16px и bold на 15px из-за sans-serif
  3699. if(hS.noBK.val){ //свернуть БК
  3700. var blogNameText0 = blogName.innerHTML;
  3701. if(content && isCorp || regexBK.test(blogNameText0))
  3702. content.style.display ='none';
  3703. var tags = next('tags', content);
  3704. if(tags)
  3705. tags.style.display ='none';
  3706. }
  3707. $e({el: hS.noNews.val && news, cs:{display:'none'}, f:function(){ //свернуть новости
  3708. $e({el: next('tags', content), cs:{display:'none'} });
  3709. } });
  3710. }}
  3711. topicTitle.innerHTML ='<span>'+ topicTitle.innerHTML.replace(/<br>/g,' ') +'</span>';
  3712. var topicTitleSpan = $q('span', topicTitle);
  3713. topicTitleSpan.title = topicTitle.title;
  3714.  
  3715. //wcl(linkA, origA, linkA && linkA.title)
  3716. if(linkA || origA)
  3717. topicTitle.title = linkA ? linkA.title : origA.href;
  3718. var s = linkA && linkA.getElementsByTagName('span')[0]
  3719. ,fromSand = !!$q('a[href*="/sandbox"]', topicTitle.parentNode);
  3720. if(linkA && s){
  3721. linkA.innerHTML ='<span>'
  3722. + s.title.match(/\d+/)[0] +' '
  3723. + linkA.title.replace(/http:\/\//,'')
  3724. .replace(/\/.+/,'') +'</span>';
  3725. s = s.title;
  3726. linkA.getElementsByTagName('span')[0].title = s;
  3727. }
  3728. if(topicTitleText.replace(/<[^>]*>/g,'').length +12* fromSand >40){
  3729. topicTitle.style.fontSize ='13px';
  3730. topicTitleSpan.style.fontSize ='14px';
  3731. topicTitleSpan.style.lineHeight ='14px';
  3732. }else{
  3733. topicTitle.style.cssText +=';font-size:15px!important;line-height:15px';
  3734. topicTitleSpan.style.cssText +=';font-size: 16px!important';
  3735. }
  3736. if(topicTitleText.length +12* fromSand >80 ){
  3737. topicTitle.style.cssText +=';font-size:11px!important;line-height:11px;vertical-align: middle!important';
  3738. topicTitleSpan.style.fontSize ='12px';
  3739. topicTitleSpan.style.lineHeight ='12px';
  3740. }
  3741. }//конец toBK
  3742. if(hS.strongCut.val && $q('.content:not(.c2)', topic)){ //ограничение высоты начал статей (244px)
  3743. topic.querySelector('.content:not(.c2)').className +=' powerCut';
  3744. blockBrs($q('.content:not(.c2)', topic));
  3745. }
  3746. if(underCut && topicTitle)
  3747. (!hS.toBK.val ? topicTitle : topicTitle.getElementsByTagName('span')[0])
  3748. .addEventListener('click', showContent,!1); //показ статьи или комментариев
  3749. if((linkA || origA) && topicTitle){
  3750. topicTitle.setAttribute('target','_blank'); //переход с начала заголовка на ссылку в новом окне
  3751. topicTitle.addEventListener('click', function(ev){
  3752. ev.target.href = ev.target.title;
  3753. },!1);
  3754. }
  3755. var cssSite ='tutorial,solution,sandbox,translation,recovery'.split(',') //смена флагов на чистый CSS
  3756. ,cssHA ='tutor,decision,sand,trans,recov'.split(',')
  3757. ,txtHA ='обуч.,реш.,пес.,перевод,восст.'.split(',');
  3758. for(var j=0; j < 5; j++){
  3759. var flag = $q('.flag_'+ cssSite[j], parents('^title$', topicTitle));
  3760. if(flag){
  3761. var txtHAJ = flag.tagName !='A' ? '<div class='+ cssHA[j] +'3>'+ txtHA[j] +'</div>'
  3762. : '<a class='+ cssHA[j] +'3 href="'+ flag.href +'">'+ txtHA[j] +'</a>';
  3763. $e({cl: cssHA[j] +1
  3764. ,ht:'<div class='+ cssHA[j] +'2></div>'+txtHAJ + txtHA[j]
  3765. ,aft: flag});
  3766. flag.style.display ='none';
  3767. }
  3768. }
  3769. if(origA){
  3770. extLinks(origA.parentNode);
  3771. origA.style.color ='#a33';
  3772. }
  3773. var topicHaCut = $q('a.habracut', topic);
  3774. //''.wcl(underCut, topicHaCut)
  3775. if(underCut && topicHaCut){ //есть хабракат
  3776. topicHaCut.addEventListener('click', showContent,!1); //показ статьи или комментариев
  3777. topicHaCut.title = titleBase;
  3778. $e({cl:'showComm btnBack inln'
  3779. ,ht:'&rarr;'
  3780. ,at:{title: titleAdd}
  3781. ,on:{click: showContent} //показ статьи или комментариев
  3782. ,apT: topicHaCut.parentNode }); //кнопка справа от ката
  3783. }
  3784. if(underCut && commLink){ //ссылка на комментарии
  3785. commLink.addEventListener('click', showContent,!1); //показ комментариев
  3786. commLink.title ='подгрузка комментариев';
  3787. var commSpan = $q('span', commLink);
  3788. if(commSpan && commSpan.innerHTML =='Комментировать')
  3789. commSpan.innerHTML ='Комм.', commSpan.style.fontStyle ='italic';
  3790. }
  3791. if(underCut)
  3792. $e({cl:'showComm btnBack inln' //показ комментариев
  3793. ,ht:'&rarr;'
  3794. ,at:{title: titleAdd}
  3795. ,on:{click: showContent} //показ статьи или комментариев
  3796. ,apT: info }); //кнопка показа комментариев
  3797. var voting = info && $q('.voting', info);
  3798. (function(voteA){if(voteA)
  3799. voteA.addEventListener('click',function(){ //место события "проверка оценок"
  3800. if(!$q('canvas', this))
  3801. win.setTimeout(function(){evtChangeDom(voteA);}, 2499);
  3802. }, !1);})(voting);
  3803. //'chkVote'.wcl(win.habrPercentageRing , !info.querySelector('.voting').querySelector('canvas'))
  3804. if(hS.noPodcast.val || hS.noAuthor.val || hS.noContent.val || hS.noSmart.val || hS.noEvent.val){ //свернуть подкасты, фильтр по авторам, по содержимому
  3805. if(hS.noAuthor.val){
  3806. var aAut = hS.listNoAuthor.val.split(',');
  3807. for(var j =0, aL = aAut.length; j < aL; j++)
  3808. if(aAut[j].replace(/(^ *| *$)/g,'') == autName) break;
  3809. var isToHide = (j!=aL);
  3810. }
  3811. if(hS.noContent.val || hS.noSmart.val){ //"контент" - это заголовок, хабы и текст
  3812. var aAut = hS.noContent.val ? hS.listNoContent.val.split(',') : [];
  3813. if(hS.noSmart.val){
  3814. aAut = aAut.concat(hS.defa.listNoSmart.replace(/([^,]),(?!,)/g,'$1@@').replace(/,,/g,',').split('@@') )
  3815. if(!(hS.listNoSmart.val.split(',').length ==1 && hS.listNoSmart.val.split(',')[0]==''))
  3816. aAut = aAut.concat(hS.listNoSmart.val.replace(/([^,]),(?!,)/g,'$1@@').replace(/,,/g,',').split('@@') );
  3817. }
  3818. var topicTitleI = topicTitle && topicTitle.innerHTML.replace(/<.*?>/g,'');
  3819. var aHubs =[], s =!1;
  3820. for(var j in hubs) //проверка набора хабов на включение строк
  3821. if(hubs[j].parentNode) aHubs[j] = hubs[j].innerHTML;
  3822. for(var j =0, aL = aAut.length, j0 = aL; j < aL; j++){
  3823. var r = RegExp(aAut[j],'im');
  3824. for(var kk=0, aHL = aHubs.length; kk < aHL; kk++)
  3825. s = s || r.test(aHubs[kk]);
  3826. if(r.test(topicTitleI) || s || r.test(content && content.innerHTML)){ //найден фильтр
  3827. var o = document.createElement('SPAN');
  3828. o.innerHTML = '<i style="color:#aaa">/</i>'+ aAut[j] +'<i style="color:#aaa">/i</i>';
  3829. o.title ='стоп-строка (рег. выражение)';
  3830. info.appendChild(o);
  3831. var j0 = j;
  3832. }
  3833. }
  3834. isToHide = isToHide || j0 != aL;
  3835. //'isToHide'.wcl(j, topicTitleI, isToHide)
  3836. }
  3837. //'noContent'.wcl(isToHide, hubs)
  3838. if(hS.noPodcast.val && content || isToHide){
  3839. var isPodcast = /подкаст/i.test(topicTitle.innerHTML); //обнаружение подкаста
  3840. if(isPodcast || isToHide){
  3841. content.style.display ='none';
  3842. var ifrPres = $q('iframe', content);
  3843. if(ifrPres){
  3844. if(!isChrome)
  3845. ifrPres.style.display ='none';
  3846. else{
  3847. ifrPres.style.position ='absolute'; //баг хрома
  3848. ifrPres.style.left ='-999px';}
  3849. }
  3850. var tags = next('tags', content);
  3851. if(tags)
  3852. tags.style.display ='none';
  3853. }
  3854. }
  3855. if(hS.noEvent.val && /event/.test(topic.className) && topicTitle){
  3856. topic.style.display ='none';
  3857. 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');
  3858. }
  3859. isToHide =0;
  3860. }
  3861. if(published && info){
  3862. $e({clone: published, cs:{cssFloat:'none',display:'inline-block'}, apT: info}); //дубль дат
  3863. }
  3864. //=== точка "каждая аннотация" ===
  3865. byTextNodes(topic, haReplace);
  3866. var aut = $q('.author', topic) //округление рейтинга
  3867. ,rating = aut && $q('.rating', aut);
  3868. if(rating)
  3869. rating.innerHTML = Math.round(parseFloat(rating.innerHTML.replace(/,/,'.').replace(/–/,'-') ));
  3870. if(content) //обработчики контента (вызов событием)
  3871. if(win.opera || /Firefox\/[345]\./.test(navigator.userAgent)){
  3872. if(win.addKarmEvent) //показ кармы, если установлен HabraKarmaView.user.js
  3873. win.addKarmEvent(content);
  3874. if(win.habrPercentageRing)
  3875. win.habrPercentageRing(content);
  3876. }else
  3877. evtChangeDom(content); //CustomEvent в блоке
  3878. extLinks(content); //внешние ссылки в подгруженном
  3879. showSourceLang(content); //показ языка кодов в подгруженном
  3880. }
  3881. if(hS.strongCut.val){ //перенос изображений вверх после их загрузки
  3882. var sCutI =0, sCutWw;
  3883. sCutWw = win.setTimeout(function(){
  3884. var imgsUp = function(topic){ //==подъём висящих рисунков==
  3885. var imgs = $qA('img:not(._noAddOwnView)', topic)
  3886. ,prevImg =0;
  3887. for(var j =0, iL = imgs.length; j < iL; j++){ //по картинкам в аннотации
  3888. var img = imgs[j];
  3889. if(img.offsetHeight ==0)
  3890. noAllImgLoaded =1;
  3891. if(img.offsetHeight && (!img.getAttribute('viewed') || img.getAttribute('viewed')==1) && (
  3892. img.offsetTop - topic.offsetTop >= strongCutImgMinH
  3893. || img.offsetHeight + img.offsetTop - topic.offsetTop > tT + 20
  3894. && img.offsetTop - topic.offsetTop >5)){
  3895. var pCut = parentsPrev(' powerCut$', img)
  3896. ,nu = Number(img.getAttribute('number') || j)
  3897. ,c = $e({el:'SPAN' //метка рисунка
  3898. ,cl:'strongCutImgPlace'
  3899. ,ht:'рис.'+ (nu+1)
  3900. ,cs: img.align=='left'|| img.align=='center'|| img.align=='middle'
  3901. ? {cssFloat:'left', margin:'-4px 4px -1px -2px'}
  3902. : {}
  3903. }),
  3904. prevImg0 = parentsPrev(' powerCut$', img).prev;
  3905. if(prevImg0.tagName =='A'){ //перекрашивание метки рисунка, если ссылка
  3906. var a = document.createElement('A');
  3907. a.href = prevImg0.href;
  3908. a.appendChild(c);
  3909. c.style.background ='#9ce';
  3910. c.style.color ='#148';
  3911. c = a;
  3912. }
  3913. if(pCut.prev && pCut.prev.nextSibling){ //вставка метки рисунка
  3914. pCut.insertBefore(c, pCut.prev.nextSibling);
  3915. if(pCut.prev.nextSibling.nextSibling && pCut.prev.nextSibling.nextSibling.tagName=='BR') //удаление лишних BR
  3916. pCut.removeChild(pCut.prev.nextSibling.nextSibling);
  3917. }else
  3918. pCut.appendChild(c);
  3919. var movedHid = prevImg0 && prevImg0.tagName=='IMG' && prevImg0.previousSibling && prevImg0.previousSibling.className =='de-img-hid' && prevImg0.previousSibling; //привязанный к IMG блок для просмотра
  3920. //'movedHid'.wcl(movedHid, prevImg0, prevImg0.previousSibling && prevImg0.previousSibling.tagName)
  3921. if(prevImg0 && pCut && prevImg && prevImg.nextSibling) //поднятие рисунка
  3922. pCut.insertBefore(prevImg0, prevImg.nextSibling);
  3923. else
  3924. pCut.insertBefore(prevImg0, pCut.childNodes[0]);
  3925. if(movedHid) //совместный перенос блока с IMG
  3926. pCut.insertBefore(movedHid, prevImg0);
  3927. img.title = 'рис.'+(nu+1) +' '+ (img.title ||'');
  3928. img.setAttribute('viewed','upped');
  3929. }else{
  3930. if(img.getAttribute('viewed')!='upped')
  3931. img.setAttribute('viewed',1);
  3932. var f2 = function(topic){
  3933. //'22loaded'.wcl(topic);
  3934. return function(){imgsUp(topic);};
  3935. }
  3936. img.addEventListener('load',new f2(topic) ,!1);
  3937. }
  3938. if(!img.getAttribute('number'))
  3939. img.setAttribute('number',j);
  3940. prevImg = prevImg0;
  3941. }
  3942. };
  3943. var topics = $qA('.powerCut')
  3944. ,tO = strongCutImgMinH *2 +4
  3945. ,noAllImgLoaded =0;
  3946. for(var i =0; i < topics.length; i++){
  3947. var topic = topics[i]
  3948. ,ifrs = $qA('iframe[src*="youtube.com/"]', topic);
  3949. if(ifrs.length){
  3950. for(var j=0; j < ifrs.length; j++){
  3951. var ifr = ifrs[j]
  3952. ,srcCode = ifr.getAttribute('src').match(/\/([\w-]*)($|\?)/);
  3953. if(srcCode.length >1){
  3954. srcCode = 'http://i3.ytimg.com/vi/'+ srcCode[1] +(strongCutImgMinH <=120?'/default.jpg':'/sddefault.jpg');
  3955. if(!isChrome)
  3956. ifr.style.display ='none'; //обход бага
  3957. else{
  3958. ifr.style.position ='absolute';
  3959. ifr.style.left ='-999px';}
  3960. $e({el:'IMG' //превью-картинка ютуба
  3961. ,cl:'youtub'
  3962. ,at:{src: srcCode, title:'=youtube=', align:'center'}
  3963. ,apT: $e({el:'A'
  3964. ,at:{href:ifr.getAttribute('src').replace(/embed\//,'watch?v='), target:'_blank'}
  3965. ,bef: ifr}) });
  3966. }
  3967. }
  3968. //youtube.com/watch?v=jq_WaOLjdyQ http://www.youtube.com/embed/jq_WaOLjdyQ
  3969. //i3.ytimg.com/vi/jq_WaOLjdyQ/hqdefault.jpg // /default - 120x90
  3970. }else{
  3971. ifr = $q('object[data*="vimeo.com/"]', topic);
  3972. if(ifr){
  3973. ifr.setAttribute('width', Math.floor(ifr.getAttribute('width')/2) );
  3974. ifr.setAttribute('height', Math.floor(ifr.getAttribute('height')/2) );
  3975. ifr.style.cssFloat ='left';
  3976. ifr.style.marginRight ='6px';
  3977. if(ifr.nextSibling && ifr.nextSibling.tagName=='BR')
  3978. ifr.parentNode.removeChild(ifr.nextSibling);
  3979. }
  3980. }
  3981. $e({cl:'prevLastInAnno'
  3982. ,bef: $q('div.clear', topic) }); //индикатор висящих рис.
  3983. var tT = $q('.prevLastInAnno', topic).offsetTop - topic.offsetTop;
  3984. imgsUp(topic); //подъём висящих рисунков
  3985. var koefPress =1.14; //коэффициент для сжатия интерлиньяжа (захват 2 строк)
  3986. (function(topic2, j){win.setTimeout(function(){
  3987. var tS = topic2.scrollHeight
  3988. ,p = document.createElement('DIV')
  3989. ,tT = $q('.prevLastInAnno', topic2).offsetTop - topic2.offsetTop;
  3990. //'sett-topic2'.wcl(topic2, (+new Date())-j, tO, tT, tS, tT >= tO && tT < tO *koefPress && tS < tO *koefPress, tS - tT);
  3991. if(tT >= tO && tT < tO *koefPress && tS < tO *koefPress){
  3992. p.className ='content powerCut'; //дополнительное сжатие по высоте на 10%
  3993. topic2.className ='pressed';
  3994. topic2.parentNode.insertBefore(p, topic2.nextSibling);
  3995. p.appendChild(topic2);
  3996. }
  3997. imgsUp(topic2); //(повторный) подъём висящих рисунков
  3998. },600);})(topic, +new Date()); //TODO делать по onload рисунков
  3999. }
  4000. if(++sCutI <1 && !noAllImgLoaded) win.setTimeout(arguments.callee, 499 + sCutI *400);
  4001. },499);
  4002. }
  4003. }
  4004. var rotPosts = $q('.rotated_posts .rotTRow');
  4005. if(rotPosts){ //обработка ===== нижних 3 ссылок =====
  4006. var rPostA = $qA('a.grey', rotPosts);
  4007. //'rPost'.wcl(rPostA)
  4008. for(var i in rPostA){ var rPAI = rPostA[i]; if(rPAI.attributes){
  4009. rPAI.innerHTML = '<span>'+ rPAI.innerHTML +'</span> ';
  4010. $e({el:'span'
  4011. ,cl:'showComm btnBack inln'
  4012. ,ht:'&rarr;'
  4013. ,at:{title:'подгрузить статью с комментариями'}
  4014. ,on:{click: showContent} //показ статьи или комментариев
  4015. ,apT: rPAI }); //кнопка справа от ката
  4016. //'rPAI'.wcl(rPAI.innerHTML);
  4017. }}
  4018. }
  4019. //===== далее - простая одиночная страница с комментариями =======
  4020.  
  4021. var lukes = $qA('.i-am-your-father-luke'); //добавление подписей к Вн.Голосу
  4022. if(lukes && lukes.length){
  4023. var o = document.createElement('DIV');
  4024. o.className ='post';
  4025. o.innerHTML ='<div class="infopanel">(это сообщение в формате "<a style="color:#888" target="_blank" href="'+HRU+'/info/help/tools/" title="описание на странице помощи">Внутренний Голос ⇗</a>" от лидера рейтинга пользователей или администрации)</div>';
  4026. for(var i in lukes){ //скрытие ненужных шаринг-кнопок
  4027. var lui = lukes[i];
  4028. if(lui.parentNode)
  4029. lui.appendChild(o);
  4030. }
  4031. }
  4032. var hsh ={noTwit:'twitter', noVk:'vkontakte', noFb:'facebook', noGP:'googleplus'};
  4033. for(var i in hsh){ if(hS[i].val){ //скрытие ненужных шаринг-кнопок
  4034. var shars = $qA('.infopanel .'+ hsh[i]);
  4035. if(shars && shars.length)
  4036. for(var j in shars)
  4037. if(shars[j].style)
  4038. shars[j].style.display ='none';
  4039. }}
  4040. if(hS.shortDates.val) //укорочение дат
  4041. datesShorten(document,'.post .published, .conversation_page .messages .info .time');
  4042. if(comments && comments.length){
  4043. correctCommentsAfter(comments[0], document.body); //==== обработка комментариев ====
  4044. var topic = $q('.post')
  4045. ,panel = $q('.infopanel')
  4046. ,date = topic && $q('.published', topic)
  4047. ,author = panel && $q('.author', panel)
  4048. ,issue = panel && $q('.original-author', panel)
  4049. ,topicTitle = topic && $q('.title', topic)
  4050. ,doubleDataAuthor = document.createElement('SPAN')
  4051. ,voting = panel && $q('.voting', panel)
  4052. ,voteRO = voting && $q('.plus', voting)
  4053. ,isRO = voteRO && /read-only/i.test(voteRO.title);
  4054. //=== точка "одна статья" ===
  4055. byTextNodes(topic, haReplace); // обработка слов статьи (без комментариев)
  4056. extLinks($q('.content', topic));
  4057. extLinks($q('.original-author', topic));
  4058. (function(voteA){if(voteA)
  4059. voteA.addEventListener('click',function(){ //место события "проверка оценок"
  4060. if(!$q('canvas', this))
  4061. win.setTimeout(function(){evtChangeDom(voteA);}, 2999);
  4062. }, !1);})(voting);
  4063. doubleDataAuthor.className ='dblAuthor'; //дублирование даты-автора вверху
  4064. if(date){
  4065. doubleDataAuthor.appendChild($e({clone: date, cs:{display:'inline'} }) );
  4066. $e({el: date
  4067. ,aft: !issue && author ? author : issue && author ? issue : $q('.share', panel) });
  4068. }
  4069. if(author){
  4070. var rating = $q('.rating', author);
  4071. if(rating)
  4072. rating.innerHTML = Math.round(parseFloat(rating.innerHTML.replace(/,/,'.').replace(/–/,'-') ));
  4073. doubleDataAuthor.appendChild(document.createTextNode(' — '));
  4074. doubleDataAuthor.appendChild($e({clone: author, cs:{display:'inline'} }) );
  4075. }
  4076. if(issue){
  4077. $q('a', issue).style.color ='#a33';
  4078. /*issue.querySelector('a').setAttribute('target','_blank'); //ссылка в новое окно*/
  4079. doubleDataAuthor.appendChild(document.createTextNode('; '));
  4080. doubleDataAuthor.appendChild($e({clone: issue, cs:{display:'inline'} }) );
  4081. }
  4082. doubleDataAuthor.style.cssFloat ='right';
  4083. doubleDataAuthor.style.marginLeft ='-100%';
  4084. doubleDataAuthor.style.position ='relative';
  4085. doubleDataAuthor.style.top ='-1.1em';
  4086. topicTitle && topicTitle.parentNode.insertBefore(doubleDataAuthor, topicTitle);
  4087. var lnkA = topic && $qA('.dblAuthor a', topic);
  4088. if(lnkA)
  4089. for(var i =0, lA = lnkA.length; i < lA; i++){
  4090. lnkA[i].style.color = i <1 ?'#cf0000':'#a33';
  4091. lnkA[i].style.textDecoration ='none';
  4092. if(i ==1) lnkA[i].setAttribute('target','_blank'); //ссылка в новое окно
  4093. }
  4094. var topicTitleSpan = topicTitle && $q('span.post_title', topicTitle)
  4095. ,author = topic && $q('.author a', topic)
  4096. ,autName = topic && author && $q('.author a', topic).innerHTML
  4097. ,hubs = topic && $qA('.hubs >.hub', topic);
  4098. //'lNAV'.wcl(autName, topicHaCut, topicTitle, hubs)
  4099. if(hS.colorTopic.val && topicTitle && hubs){
  4100. for(var j in hubs) if(hubs[j].innerHTML =='Переводы'){
  4101. topicTitleSpan.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  4102. break;
  4103. }
  4104. if(topic && / translation/.test(topic.className) && topicTitleSpan){
  4105. topicTitleSpan.style.backgroundColor ='#f0f4fa'; //топик-перевод (светло-синий)
  4106. topicTitleSpan.style.paddingRight ='8px';
  4107. }
  4108. var lNAV = hS.listNewsAuthors.val
  4109. ,topicHaCut = $q('a[name="habracut"]', topic);
  4110. for(var j in lNAV) if(autName == lNAV[j] || !topicHaCut){
  4111. topicTitleSpan.style.backgroundColor ='#fafdf2'; //новость (жёлтый)#f2f6e8
  4112. $e({cl:'recov1'
  4113. ,cs:{marginLeft:'8px'}
  4114. ,at:{title:'новость'}
  4115. ,ht:'<div class="recov2"></div><div class="recov3">н</div>н'
  4116. ,aft: topicTitleSpan
  4117. });
  4118. break;
  4119. }
  4120. if(topic && / link/.test(topic.className) && topicTitleSpan){
  4121. topicTitleSpan.style.backgroundColor ='#f0faf4'; //топик-ссылка (зеленоватый)
  4122. topicTitleSpan.style.backgroundImage ='url(http://456)';
  4123. topicTitleSpan.style.paddingRight ='8px';
  4124. }
  4125. }
  4126. if(isRO){ //скрыть стрелки оцениваний для read-only
  4127. var votes = $qA('.comments_list .info .voting a');
  4128. if(votes) for(var i in votes) if(votes[i].attributes)
  4129. votes[i].style.display ='none';
  4130. }
  4131. }
  4132. var fileBase64Post = function(){
  4133. var dataURL = this.canvas.toDataURL(this.getImageType()) // grab the snapshot as base64
  4134. ,imgData = atob(dataURL.substring(13 + this.getImageType().length)) // convert to binary
  4135. ,filenameTimestamp = (new Date().getTime())
  4136. ,separator = '----------12345-multipart-boundary-' + filenameTimestamp;
  4137. // Javascript munges binary data when it undergoes string operations (such as concatenation), so we need
  4138. // to jump through a bunch of hoops with streams to make sure that doesn't happen
  4139. // Create a string input stream with the form preamble
  4140. var prefixStringInputStream = Components.classes['@mozilla.org/io/string-input-stream;1']
  4141. .createInstance(Components.interfaces.nsIStringInputStream);
  4142. var formData ='--'+ separator +'\\r\\nContent-Disposition: form-data; name="data"; filename="snapshot_'
  4143. + filenameTimestamp + (this.getImageType() =='image/jpeg'?'.jpg':'.png') +'"\\r\\nContent-Type: '
  4144. + this.getImageType() +'\\r\\n\\r\\n';
  4145. prefixStringInputStream.setData(formData, formData.length);
  4146. // write the image data via a binary output stream, to a storage stream
  4147. var binaryOutputStream = Components.classes['@mozilla.org/binaryoutputstream;1']
  4148. .createInstance(Components.interfaces.nsIBinaryOutputStream);
  4149. var storageStream = Components.classes['@mozilla.org/storagestream;1']
  4150. .createInstance(Components.interfaces.nsIStorageStream);
  4151. storageStream.init(4096, imgData.length, null);
  4152. binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
  4153. binaryOutputStream.writeBytes(imgData, imgData.length);
  4154. binaryOutputStream.close();
  4155. // write out the rest of the form to another string input stream
  4156. var suffixStringInputStream = Components.classes['@mozilla.org/io/string-input-stream;1']
  4157. .createInstance(Components.interfaces.nsIStringInputStream);
  4158. formData ='\\r\\n--'+ separator +'\\r\\nContent-Disposition: form-data; name="description"\\r\\n\\r\\n'
  4159. + description +'\\r\\n--'+ separator +'--\\r\\n';
  4160. suffixStringInputStream.setData(formData, formData.length);
  4161.  
  4162. // multiplex the streams together
  4163. var multiStream = Components.classes['@mozilla.org/io/multiplex-input-stream;1']
  4164. .createInstance(Components.interfaces.nsIMultiplexInputStream);
  4165. multiStream.appendStream(prefixStringInputStream);
  4166. multiStream.appendStream(storageStream.newInputStream(0));
  4167. multiStream.appendStream(suffixStringInputStream);
  4168.  
  4169. // post it
  4170. req.open('POST','http://yoursite.com/upload_endpoint', true);
  4171. req.setRequestHeader('Accept','*/*, application/xml');
  4172. req.setRequestHeader('Content-type','multipart/form-data; boundary='+ separator);
  4173. req.setRequestHeader('Content-length', multiStream.available());
  4174. req.setRequestHeader('Authorization','Basic '+ btoa(username +':'+ password));
  4175. req.setRequestHeader('User-Agent','YourUserAgent/1.0.0');
  4176. req.send(multiStream);
  4177. };
  4178. /*
  4179. var addAdReq = new XMLHttpRequest();
  4180. addAdReq.open('POST', postAdUrl, false);
  4181. addAdReq.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary);
  4182. var stringStream = Components.classes["@mozilla.org/io/string-input-stream;1"].createInstance(Components.interfaces.nsIStringInputStream);
  4183. var data = "";
  4184. data += boundary;
  4185. data += "\r\n";
  4186. data += 'Content-Disposition: form-data; name="category_id"\r\n\r\n';
  4187. data += categoryId;
  4188. data += "\r\n";
  4189. data += boundary;
  4190. data += "\r\n";
  4191. .......[и т.д.].......
  4192. data += boundary;
  4193. data += "--\r\n";
  4194. stringStream.setData(data, data.length);
  4195. addAdReq.send(stringStream);//в хедере строка boundary должна содержать на два символа '-' меньше чем в остальных случаях.
  4196.  
  4197. http://igstan.ro/posts/2009-01-11-ajax-file-upload-with-pure-javascript.html */
  4198.  
  4199. var fPanel = $q('form .panel')
  4200. ,formTA;
  4201. if(fPanel)
  4202. for(formTA = fPanel; formTA !=null && !/form/i.test(formTA.tagName); formTA = formTA.parentNode);
  4203. if((comments && comments.length || $q('#post_form') )&& !isRO && h.uName && typeof window.FileReader !=u){
  4204. $e({cl:'habrAjaxInfo droppedF for_authors'
  4205. ,cs:{paddingLeft:'14px'}
  4206. ,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>'
  4207. +'<div class=hoverView style=float:right;padding-bottom:0.2em>(?)</div><div class="hoverView hovered" style=margin-top:1.3em>'
  4208. +'разместить на <a href='+HSO+' target=_blank>habrastorage.org</a>; Макс. ширина без ужатия - 1920'
  4209. +'</div>'
  4210. +'<button>Публиковать</button>'
  4211. +'<div class=fileName>abcde.png</div>'
  4212. +'<div class=imgDimens>1234567 <span style=font-variant:small-caps>б.</span></div>'
  4213. +'<button class=previ>пре-<br>вью</button><button class="previ previCancel" style=float:right title=отмена>X</button>'
  4214. +'<input id=resizeWidth placeholder=1028 title="ресайз до ширины" /><br>'
  4215. +'<input id=resizeHeight placeholder=2006 title="ресайз до высоты" /></div>'
  4216. +''
  4217. ,apT: $e({cs:{position:'relative', height:0}
  4218. ,apT: sidebar})
  4219. });
  4220. $e({cl:'habrAjaxInfo pixList for_authors'
  4221. ,cs:{paddingLeft:'14px'}
  4222. ,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>'
  4223. +' затащите файл&nbsp;картинки&nbsp;<div class=hoverView>(?)<div class=hovered>'
  4224. +'сюда или в поле ввода комментария (статьи, вопроса, ответа, письма), чтобы разместить на <a href='+HSO+' target=_blank>habrastorage.org</a> (тег появится под курсором).'
  4225. +'<div>Макс. ширина - 1920 без ужатия</div>'
  4226. +'</div></div><br>'
  4227. +' &nbsp; <a href=#>последние</a> (NN),<br>'
  4228. +'&nbsp; <a href=#>избранные</a> (N),<br>'
  4229. +'&nbsp; <a href=#>удалённые</a> (NNN).<br>'
  4230. ,apT: sidebar
  4231. });
  4232. if(formTA){
  4233. var preImgSend = $e({cl:'preImgSend habrAjaxInfo'
  4234. ,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>'
  4235. +'<button class="previ previCancel" style="float:right; width:7%; height:3.9em" title=отмена>X</button>'
  4236. +'<div class=hoverView style="float:right; text-align:center">'
  4237. +'<div class=imgDimens><span class=weight>-1</span> <span style=font-variant:small-caps>б.</span></div>'
  4238. +'<input id=resizeWidth2 placeholder=width title="ресайз до ширины" /><br>'
  4239. +'<input id=resizeHeight2 placeholder=height title="ресайз до высоты" />'
  4240. +'</div><div class=imgPrevi style="position:relative;float:right;width:94px; height:4.2em">'
  4241. +'<div class=fit style="position:absolute;bottom:0;width:94px; height:94px; border:1px solid #ddd; background:#F0F0F0"></div>'
  4242. +'</div>'
  4243. +'</div><div class=imgPrevi style="position:relative;float:right;width:94px; height:4.2em">'
  4244. +'<div class=centered style="position:absolute;bottom:0;width:94px; height:94px; border:1px solid #ddd; background:#F0F6F0"></div>'
  4245. +'</div>'
  4246. +'<div class=overUrl><div class=imgDate></div><input id=aUrl placeholder=URL title="ссылка на рисунке" style="margin-left:-11px; text-align:left"/></div>'
  4247. +'<span class=overName><span class=fileName>(имя файла)</span> . <img src=/images/favorite.gif style=width:150px;height:1px /></span>'
  4248. +'<a href="#.jpg" class="aPrevi imgL"><button class=previ style="width:10%" title="в плавающем блоке">пре-<br>вью</button></a>'
  4249. +'<button class=publish style="width:30%;height:2.6em" title="центровка по радиокнопкам или Shift/Ctrl+Shift/Ctrl">Публиковать</button>'
  4250. ,bef: fPanel
  4251. });
  4252. }
  4253. var fileDrop3 = $q('#text_textarea')||$q('#comment_text')
  4254. ,centPrevi = $q('.imgPrevi .centered'), fitPrevi = $q('.imgPrevi .fit');
  4255. if(fileDrop3){
  4256. $e({
  4257. el: fileDrop3
  4258. ,on:{
  4259. dragover: function(ev){'dragover0'.wcl();this.classList.add('hover'); $pdsp(ev);}
  4260. ,dragend: function(){'dragend0'.wcl();this.className =''; return!1;}
  4261. ,drop: function(ev){
  4262. this.classList.remove('hover');
  4263. $pdsp(ev);
  4264. var file = ev.dataTransfer.files[0]
  4265. ,reader = new FileReader();
  4266. reader.onload = function(ev){
  4267. 'fileDrop3-target'.wcl(ev.target);
  4268. preImgSend.style.display ='block';
  4269. fileDrop3.style.background = centPrevi.style.background = fitPrevi.style.background ='url('+ ev.target.result +') no-repeat center';
  4270. centPrevi.style.backgroundColor ='#F0F6F0';
  4271. fitPrevi.style.backgroundSize ='contain';
  4272. fitPrevi.style.backgroundColor ='#F0F0F0';
  4273. var resu = ev.target.result;
  4274. handlImgViews(preImgSend,'.aPrevi.imgL');
  4275. var previLink = $q('.aPrevi img', preImgSend)
  4276. previLink &&(previLink.src = resu);
  4277. win.addEventListener('loadImg',function(){
  4278. var dimS = previLink.title.match(/(\d+)x(\d+)$/);
  4279. if(dimS){
  4280. dimS = dimS.slice(1);
  4281. $q('#resizeWidth2', preImgSend).setAttribute('placeholder',dimS[0]);
  4282. $q('#resizeHeight2', preImgSend).setAttribute('placeholder',dimS[1]);
  4283. }},!1);
  4284. $q('.imgDimens .weight',preImgSend).innerHTML = file.size;
  4285. $q('.fileName',preImgSend).innerHTML = file.name;
  4286. var fD = new Date(file.lastModifiedDate);
  4287. $q('.imgDate',preImgSend).innerHTML = fD.getFullYear()
  4288. +'-'+ (fD.getMonth()+1<=9?'0':'') +(fD.getMonth()+1)
  4289. +'-'+(fD.getDate()<=9?'0':'')+ fD.getDate()
  4290. +','+ getDay([0,fD.getDate(),0,fD.getFullYear()], fD.getMonth())
  4291. +' '+ (fD.getHours()<=9?'0':'') + getHourMins(fD)+
  4292. ':'+(fD.getSeconds()<=9?'0':'')+fD.getSeconds();
  4293. };
  4294. var formData = new FormData();
  4295. formData.append('Filedata', file);
  4296. 'fileDrop3-file'.wcl(file.size, file.lastModifiedDate, file.mozFullPath, formData);
  4297. reader.readAsDataURL(file);
  4298. return!1;
  4299. }
  4300. }
  4301. });
  4302. $e({el:'.aPrevi.imgL button', blck: preImgSend
  4303. ,on:{click:function(ev){
  4304. var img = this.parentNode.previousSibling.firstChild
  4305. dimS = img.title.match(/(\d+)x(\d+)$/);
  4306. dimS && addFullImg(img, dimS.slice(1));
  4307. $pdsp(ev);
  4308. return!1}
  4309. } });
  4310. $e({el:'.previCancel', blck: preImgSend
  4311. ,on:{click:function(ev){
  4312. fileDrop3.style.backgroundImage ='none';
  4313. preImgSend.style.display ='none';
  4314. $pdsp(ev);
  4315. }} });
  4316. $e({el:'.publish', blck: preImgSend
  4317. ,on:{click:function(ev){
  4318. openInFrame({clientY: ev.clientY}, {href:HSO+'/'});
  4319. $pdsp(ev);
  4320. }} });
  4321. }
  4322. }
  4323. var menuA = $qA('.main_menu a');
  4324. if(menuA.length ==0)
  4325. menuA = [$q('#navbar .tab_menu .g-icon-burger')];
  4326. menuA && menuA[0] && $e({el: menuA[0]
  4327. ,cl:'date'
  4328. ,at:{title: menuA.length ==1 ?'Разделы':'лента'+(hS.postsLinkNew.val ?'-все-новое':'')}
  4329. ,ht: getHourMins().replace(/(\d\d):/,'$1') +'<br>'+ getDay([0,NOWdate.getDate(),0,NOWdate.getFullYear()], NOWdate.getMonth())});
  4330. $e({el: $q('#navbar .tab_menu')
  4331. ,on:{click: function(){
  4332. var menuTab = $q('#menu_tab')
  4333. ,el = $q('.global_search_form input', menuTab);
  4334. 'menuTab'.wcl(menuTab && /hidden/.test(menuTab.className) && el)
  4335. menuTab && /hidden/.test(menuTab.className) && el && setTimeout(function(){el.focus();},199);}} });
  4336. if(menuA && menuA[0] && hS.postsLinkNew.val || hS.allFeed.val){
  4337. if(menuA[0].href)
  4338. menuA[0].href = ROOT + (/(\/feed\/)/.test(menuA[0].href) ?'/feed/'
  4339. + (hS.allFeed.val ?'/posts/':''): (h.uName ?'':'/posts') + (hS.allFeed.val && hS.postsLinkNew.val ?'/corporative/':'/collective/') );
  4340. if(hS.postsLinkNew.val && menuA[0].href)
  4341. menuA[0].href +='new/'; //ссылки 'Лента", "Посты" - на "новые"
  4342. }
  4343. if(comments && comments.length || fPanel )
  4344. addTaButtons(comments[0] || formTA ); //добавление кнопок над полем ввода
  4345. h.uName2 = $q('.user_header .username') || h.uName; //выбор чужого юзера с приоритетом
  4346. h.uName2 = h.uName2 && h.uName2.innerHTML;
  4347. authorClicks(document); //обраб-к кликов на авторах, избранном, настройках, авторизации
  4348. authorClicks($q('#search_form input[type="submit"][value=""]')); //на кнопке поиска
  4349. handlImgViews(document); //показ увеличенных картинок
  4350.  
  4351. if(inFrame){ //удаление персонального меню в фрейме
  4352. var footer = $q('#footer');
  4353. if(footer) footer.style.display ='none';
  4354. var panelPers = $q('#header .userpanel');
  4355. if(panelPers){
  4356. panelPers.style.display ='none';
  4357. $e({ //кнопка закрывания фрейма
  4358. cl:'closeButt'
  4359. ,ht: '<b style="padding:1px 3px; border:1px solid #bbc; border-bottom-left-radius: 4px; color:#bbc"'
  4360. +' onclick="try{top.location && (top.document.getElementById(&quot;hA_userinfoView&quot;).style.display=&quot;none&quot);}catch(er){alert(er)}">X</b>'
  4361. //document.activeElement.removeChild(document.activeElement.firstChild);
  4362. ,cs:{cssText:'position: fixed; z-index:2; right:0; top:2px; cursor:pointer'}
  4363. ,bef: panelPers.parentNode
  4364. });
  4365. }
  4366. }
  4367. if(win.commentForm)
  4368. win.commentForm.sendOnEnter = function(){}; //убрать отправку по Ctrl+Enter (устарело, но может работать в блогах компаний (?))
  4369. if(hS.innerTab.val){ // ====== вставка спецсимволов =======
  4370. var tArea = $qA('.editor textarea')
  4371. ,inTag = win.habraWYG && win.habraWYG.insertTag;
  4372. if(tArea.length && inTag)
  4373. for(var j in tArea){var taJ = tArea[j]; if(taJ.attributes){
  4374. $e({el: taJ, on:{keydown: function(ev){
  4375. var th = ev.target;
  4376. if(ev.shiftKey && ev.keyCode ==9){ //вставка таба по Shift-Tab
  4377. inTag(th,' ');
  4378. $pd(ev);
  4379. }
  4380. if(ev.ctrlKey && ev.keyCode ==32){ //вставка NBSP по Ctrl-Space
  4381. inTag(th,'&nbsp;');
  4382. $pd(ev);
  4383. }
  4384. }} });
  4385. }}}
  4386. if(hS.autoGrow.val){
  4387. var tAGrow = function(tA){ //авторост-обработчик
  4388. if(!tA) return;
  4389. var tSHPrev =0, tAInh, tATout
  4390. ,maxH = Math.floor(win.innerHeight *0.8)
  4391. ,tAF = function(ev){
  4392. if(tSHPrev < maxH && tAInh)
  4393. win.clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
  4394. var tSH = tA.scrollHeight - (isChrome||isFx?6:win.opera?2:6);
  4395. //'tA'.wcl(tSHPrev, tSH, ev.type, tA.offsetHeight);
  4396. if(win.opera){
  4397. tA.blur();
  4398. tA.style.height = 0;
  4399. tA.style.marginBottom = tSH +'px';
  4400. tSH = tA.scrollHeight -2;
  4401. tA.style.height = tSH +'px';
  4402. tA.style.marginBottom = 0;
  4403. tA.focus();
  4404. }
  4405. if(tSHPrev <= tSH && tSHPrev < maxH){
  4406. tA.style.height = tSH +'px';
  4407. if(tSHPrev < maxH && tAInh)
  4408. win.clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
  4409. }else if(!tAInh)
  4410. win.clearTimeout(tATout), tATout = win.setTimeout(function(){tA.style.overflow ='inherit'; tAInh =1}, 230);
  4411. tSHPrev = tSH;
  4412. };
  4413. tA.addEventListener('keypress',tAF,!1); //контроль за ростом блока данных
  4414. tA.addEventListener('keyup',tAF,!1);
  4415. tA.style.maxHeight = maxH +'px';
  4416. };
  4417. tAGrow($q('.editor #comment_text')||$q('.editor #text_textarea') );
  4418. tAGrow($q('.editor #text') );
  4419. }
  4420. $q('.inbox_page_write')&&($q('.inbox_page_write').className ='inbox_page_write2'); //разблок_ресайза поля ввода в почте
  4421. $q('.inbox_page_read')&&($q('.inbox_page_read').className ='inbox_page_read2');
  4422. if(hS.reformal.val && !inFrame){ // добавление виджета reformal.ru для отправки багрепортов (можно то же из настроек)
  4423. addJs(function reformal_preload(){
  4424. reformal_wdg_w = "713";
  4425. reformal_wdg_h = "460";
  4426. reformal_wdg_domain = "habrajax";
  4427. reformal_wdg_mode = 0;
  4428. reformal_wdg_title ='<a href="https://github.com/spmbt/haPages/tree/gh-pages" target="_blank">HabrAjax</a> - чтобы сайт стал удобным';
  4429. reformal_wdg_ltitle = "БАГИ";
  4430. reformal_wdg_lfont = "";
  4431. reformal_wdg_lsize = "";
  4432. reformal_wdg_color = "#269bd1";
  4433. reformal_wdg_bcolor = "#73859e";
  4434. reformal_wdg_tcolor = "#FFFFFF";
  4435. reformal_wdg_align = "right";
  4436. reformal_wdg_charset = "utf-8";
  4437. reformal_wdg_waction = 0;
  4438. reformal_wdg_vcolor = "#559ecf";
  4439. reformal_wdg_cmline = "#d3d8df";
  4440. reformal_wdg_glcolor = "#105895";
  4441. reformal_wdg_tbcolor = "#FFFFFF";
  4442. reformal_wdg_tcolor_aw4 = "#3F4543";
  4443. reformal_wdg_bimage = "cac7b640e87a20ba02df24d613d54a1d.png";
  4444. reformal_html ='';
  4445. document.write = function(a){reformal_html +=a;};//обход doc.write
  4446. });
  4447. addJs('http://reformal.ru/tabn2v4.js?charset=utf-8' //виджет reformal.ru и его постобработчик
  4448. ,hS.versionNumb
  4449. ,'MyOtziv'
  4450. ,function reformal_postload(){ //загрузка после doc.write и подгонка стилей, текстов
  4451. var elem = document.createElement('DIV');
  4452. elem.id ='reformal_holder';
  4453. elem.innerHTML = reformal_html;
  4454. document.body.insertBefore(elem, document.body.childNodes[0]);
  4455. document.getElementById('myotziv_box').style.zIndex = 3001;
  4456. var reformal_butt = document.querySelector('#reformal_holder .frgtd'); //кнопка открывания виджета, |.frby
  4457. reformal_butt.style.right='-4px';reformal_butt.style.width ='17px';
  4458. reformal_butt.querySelector('img').style.position='relative';
  4459. reformal_butt.querySelector('img').style.left='-4px';
  4460. reformal_butt.style.overflow ='hidden';
  4461. reformal_butt.querySelector('a').title ='Пожелания и баги HabrAjax';
  4462. reformal_butt.querySelector('a').style.marginBottom ='3em';
  4463. var reformal_closeButt = document.querySelector('#reformal_holder .pokusijy'); //кнопка закрытия
  4464. var reformal_goto = document.createElement('DIV');
  4465. reformal_goto.innerHTML ='<a href="http://habrajax.reformal.ru/" target="_blank">смотреть всё</a>';
  4466. reformal_closeButt.parentNode.insertBefore(reformal_goto, reformal_closeButt.nextSibling);
  4467. reformal_goto.style.cssFloat ='right';
  4468. reformal_goto.style.marginRight ='10px';
  4469. var reformal_foot1 = document.querySelector('#reformal_holder .drsdtf');
  4470. reformal_foot1.style.width ='auto';
  4471. var reformal_note1 = document.createElement('DIV');
  4472. 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>';
  4473. reformal_foot1.parentNode.appendChild(reformal_note1);
  4474. reformal_note1.style.padding ='3px 0 0 5px';
  4475. reformal_note1.style.cursor ='pointer';
  4476. });
  4477. }
  4478. if(hS.gPlus.val && !/\/sandbox/.test(location.href && !inFrame)) // добавление скрипта Google+
  4479. addJs('https://apis.google.com/js/plusone.js','{"parsetags": "explicit"}', 'gapi', loadGPlus);
  4480. //linkCommFavor(); //дин.ссылки избранного и комментариев
  4481. var submenu = $q('.submenu')
  4482. ,forSand = $qA('.item a[href*="/sandbox/"],.item a[href*="/notes/"]', submenu);
  4483. //'forSand'.wcl(forSand , !forSand.length , !isCompa)
  4484. if(forSand && !forSand.length && !isCompa)
  4485. $e({cl:'item'
  4486. ,ht:'<a href="http://habrahabr.ru/sandbox/"><span class="name">Песочница</span></a>'
  4487. ,apT: submenu
  4488. });
  4489. $e({cl:'item'
  4490. ,ht:'<a href="http://habrastorage.org/"><span class="name">Storage</span></a>'
  4491. ,apT: submenu
  4492. });
  4493. var userpanel = $q('.userpanel');
  4494. if(userpanel){ //кнопка настроек [и тест ошибок юзерскрипта]
  4495. var hMailLink = $q('a[href*="conversations/"]', userpanel)
  4496. ,favors = $q('a[href*="favorites/"]', userpanel)
  4497. ,trac = $q('a[href*="tracker/"]', userpanel)
  4498. ,nastr = $q('a.nav-settings', userpanel)
  4499. ,exit = $q('a[href*="logout"]', userpanel)
  4500. ,cntTrac = $q('a.count[href*="tracker"]', userpanel)
  4501. ,cntMail = $q('a.count[href*="conversations"]', userpanel)
  4502. ,bottom = $q('.bottom', userpanel);
  4503. if(exit)
  4504. exit.title ='выход';
  4505. if(trac)
  4506. trac.innerHTML ='трек';
  4507. if(cntTrac && trac){
  4508. trac.style.display ='none';
  4509. cntTrac.title ='трекер';
  4510. }
  4511. if(cntMail && hMailLink){
  4512. hMailLink.style.display ='none';
  4513. cntMail.title ='сообщения в почте';
  4514. }
  4515. if(RO){
  4516. RO.title = RO.innerHTML; RO.innerHTML ='RO';}
  4517. if(hMailLink){
  4518. hMailLink.innerHTML ='сооб';
  4519. $e({el: hMailLink, prT: bottom});
  4520. }
  4521. var habrAjaxSettButt = $e({el:'A'
  4522. ,cl:'habrAjaxSettButt'
  4523. ,at:{href: URLCSS, title:'Настройки просмотра сайта'}
  4524. ,ht:'HAjax'
  4525. ,on:{click: hS.edit} });
  4526. h.inZen ? $e({el: habrAjaxSettButt, prT: bottom}) : $e({el: habrAjaxSettButt, apT: bottom});
  4527. if(favors){
  4528. favors.innerHTML ='избр';
  4529. favors.title ='Избранные мною статьи';
  4530. $e({el: favors, prT: bottom});
  4531. }
  4532. var login = $q('.userpanel >a[href*="login/"]');
  4533. if(nastr){
  4534. nastr.innerHTML ='настр';
  4535. nastr.title ='настройки пользователя на сайте';
  4536. $e({el: nastr, prT: bottom});
  4537. }else //для неавторизованных
  4538. login && login.parentNode.insertBefore(habrAjaxSettButt, login);
  4539. if(login && !nastr && /googleusercontent.com/.test(lh))
  4540. login.innerHTML ='googleUserContent';
  4541. var chargeDiv, replaceCharge;
  4542. if( chargeDiv = $q('.charge', userpanel) ){
  4543. (replaceCharge = function(){ //перевод описания оставшихся голосов в иное представление
  4544. var chrgNums = chargeDiv.innerHTML.match(/\d+/g);
  4545. if(chrgNums && !chrgNums[1]) chrgNums[1] ='--';
  4546. chargeDiv.style.fontSize ='12px';
  4547. var dd = $e({ht:'<span title="имеется голосов за статьи и карму">'
  4548. + (chrgNums && chrgNums.length ? chrgNums[0]:'') +'</span> '
  4549. +'<a href="/users/'+ h.uName +'/topics/">&nbsp;Блог&nbsp;</a>'
  4550. +' <a href="/users/'+ h.uName +'/qa/questions/">QAQ</a><br>'
  4551. +'<span title="за комментарии">'
  4552. + (chrgNums && chrgNums.length ? chrgNums[1]:'') +'</span> '
  4553. +'<a href="/users/'+ h.uName +'/comments/">Комм.</a>'
  4554. +' <a href="/users/'+ h.uName +'/qa/answers/">QAA</a>'});
  4555. var chlds = chargeDiv.childNodes;
  4556. //'chlds'.wcl(chlds, chlds.length);
  4557. for(var i in chlds){ var chI = chlds[i]; if(chI.parentNode){
  4558. //'chldsI'.wcl(chI, chI.nodeType, chI.nodeValue)
  4559. if(chI.nodeType ==3 && chI.nodeValue && chI.nodeValue.length >19)
  4560. chargeDiv.replaceChild(dd, chI);
  4561. }}
  4562. })();
  4563. }
  4564. }
  4565. var panelNav = $q('#header .main_menu')
  4566. ,tops = panelNav && $q('a[href*=top]', panelNav)
  4567. ,events = panelNav && $q('a[href*=events]', panelNav);
  4568. if(tops) tops.innerHTML ='хит';
  4569. if(events) events.innerHTML ='соб';
  4570. var contSelect;
  4571.  
  4572. //{ Данные цитаты:
  4573. //contextBefore //примерно строка до выделенного (в письме отображается серым)
  4574. //contextAfter //примерно строка после выделенного
  4575. //author //автор статьи-комментария
  4576. //date //дата (статьи, комментария)
  4577. //title //название статьи (для использ. в письме)
  4578. //link: //ссылка URL на элемент
  4579. //source //источник (перевода, ссылки)
  4580. //sourceLink
  4581. //тип контекста цитаты: статья, коммент, QA, песочн.};
  4582. //(contSelect = function(){ //========== обработка выделения текста ================
  4583.  
  4584. if(hS.contextSelect.val || hS.hQuotes && hS.hQuotes.val || hS.correctCite.val){ //=== контролы на выделения текста ===
  4585. var selectOp = function(ev){ //сбор данных по выдел_
  4586. if(parents('^citeBtns$',ev.target))
  4587. return;
  4588. if(parents('citeBtns', ev.target) && ev.target.tagName !='A'){
  4589. $pdsp(ev);
  4590. }
  4591. if(win.getSelection && hNE && !parents('js-field-data', ev.target) /*&& !parents('topic_add', ev.target)*/ ){
  4592. var sR = win.getSelection();
  4593. //sR.modify && sR.modify("extend", "forward", "word"); //граница слова в конце выделения
  4594. var sRA = sR.anchorNode
  4595. ,sRF = sR.focusNode
  4596. ,commElemStart = parents('^comment_item', sRA)
  4597. ,commElemEnd = parents('^comment_item', sRF)
  4598. ,artiElemStart = parents('^content[^_]', sRA)
  4599. ,artiElemEnd = parents('^content[^_]', sRF)
  4600. ,sel ={commCount: 1 //параметры выделения
  4601. ,elemTop: 9e9, elemRight: -9e9, elemBottom: -9e9, elemLeft: 9e9}
  4602. try{
  4603. var sRR = sR.getRangeAt && sR.getRangeAt(0)
  4604. ,nodeAncestor = sRR.commonAncestorContainer
  4605. ,nodeStart = sRR.startContainer
  4606. ,nodeEnd = sRR.endContainer
  4607. // вычисление текстового сдвига относительно общей ноды, чтобы:
  4608. // 1) найти контекст; 2) отвязаться от пересекающих нод. Корневая нода - сообщение
  4609. ,rAncestorStart = sRR.cloneRange();
  4610. rAncestorStart.selectNodeContents(nodeAncestor);
  4611. //rAncestorStart.setStartAfter(nodeAncestor);
  4612. //rAncestorStart.setEndBefore(nodeStart);
  4613. //,rAncestorEnd = (document.createRange()).selectNode(nodeAncestor);
  4614. //rAncestorStart.setEndBefore(nodeStart);
  4615. //rAncestorEnd.setEndBefore(nodeEnd);
  4616.  
  4617. }catch(er){;}
  4618. if(sRR && sRR.getClientRects && sRR.getClientRects()[0]){ //границы выделения
  4619. var sRRB = sRR.getClientRects();
  4620. for(var i=0, iL = sRRB.length; i < iL; i++){
  4621. if(sRRB[i].top < sel.elemTop) sel.elemTop = sRRB[i].top;
  4622. if(sRRB[i].right > sel.elemRight) sel.elemRight = sRRB[i].right;
  4623. if(sRRB[i].bottom > sel.elemBottom) sel.elemBottom = sRRB[i].bottom;
  4624. if(sRRB[i].left < sel.elemLeft) sel.elemLeft = sRRB[i].left;
  4625. }
  4626. $x(sel, {startX: sRRB[0].left //координаты "старта-конца" (верха-низа)
  4627. ,startY: sRRB[0].top
  4628. ,endX: sRRB[sRRB.length-1].right
  4629. ,endY: sRRB[sRRB.length-1].bottom
  4630. });}
  4631. //TEST
  4632. /*sel.posStart = sRR.startOffset;
  4633. sel.posEnd = sRR.endOffset;
  4634. sel.nodeAncestor = nodeAncestor;
  4635. sel.rAncestorStart = rAncestorStart.startOffset +'/'+ rAncestorStart.endOffset;*/
  4636.  
  4637. if(sRA ==sRF) //направление выделения
  4638. sel.direction = sR.anchorOffset < sR.focusOffset;
  4639. else{
  4640. var posA = getPosition(sRA), posF = getPosition(sRF);
  4641. sel.direction = posA.y == posF.y ? posA.x < posF.x : posA.y < posF.y;
  4642. }
  4643. //'direction'.wcl(sel.direction, sel.elemTop, sel.elemBottom)
  4644. $x(sel, {commElemTop: sel.direction ? commElemStart || commElemEnd
  4645. : commElemEnd || commElemStart //тег с идом первого коммента
  4646. ,commElemBottom: !sel.direction ? commElemStart || commElemEnd
  4647. : commElemEnd || commElemStart
  4648. ,artiElemTop: sel.direction ? artiElemStart || artiElemEnd
  4649. : artiElemEnd || artiElemStart
  4650. ,artiElemBottom: !sel.direction ? artiElemStart || artiElemEnd
  4651. : artiElemEnd || artiElemStart
  4652. });
  4653. sel.postElem = parents('^post($| )', sel.artiElemTop || sel.commElemTop)
  4654. || prev('^post($| )', parents('^(comments_list( )?|comments c2)', sel.artiElemTop || sel.commElemTop)); //тег с идом поста - !!!будет сильно зависеть от вида записи класса!, источник ошибок волатильности
  4655. if(commElemStart && commElemEnd && commElemStart != commElemEnd){
  4656. var commsStart = parents('^(comments_list|comments c2)', sel.commElemTop) || parents('^comments c2$', sel.commElemTop)
  4657. ,commsEnd = parents('^(comments_list|comments c2)', sel.commElemBottom) || parents('^comments c2$', sel.commElemBottom);
  4658. if(commsStart == commsEnd){ //если в одной статье - считать выделенные комм-ы
  4659. var cInArt = $qA('.comment_item', commsStart)
  4660. ,j =0;
  4661. for(var i in cInArt){
  4662. if(j >0)
  4663. j++;
  4664. if(j && cInArt[i] == sel.commElemBottom)
  4665. j = -j;
  4666. if(!j && cInArt[i] == sel.commElemTop)
  4667. j =1;
  4668. }
  4669. sel.commCount = -j; //число выделенных комментариев (для "HQ")
  4670. }
  4671. }
  4672. if(sR)
  4673. var s = '<span class="selText">'+ sR +'</span>'
  4674. ,sTechLen = s.length - (sR+'').length;
  4675. if(s && (sR+'').length >0){
  4676. var sele = $q('.list .sele', hNE) //строка выделения - в список цитат
  4677. ,newSele = $e({el: sele
  4678. ,cl:'sele'
  4679. ,ht: s +' <span style="color:#999">'+ ((sR+'').length||'') +'</span>'});
  4680. if(newSele != sele)
  4681. $q('.list', hNE).appendChild(newSele);
  4682. //'commElemTop'.wcl(sel.commElemTop , sel.artiElemTop)
  4683. var commTime = $q('.info time', sel.commElemBottom) || $q('.info .time', sel.commElemBottom);
  4684. $x(sel, {text: s //выделение; и далее - сопутствующая инф.
  4685. ,textR: sR+'' //чистый текст выделения
  4686. ,dateCopy: +new Date() //дата снятия копии пользователем
  4687. ,articleId: sel.postElem && sel.postElem.id && sel.postElem.id.replace(/\D/g,'')
  4688. ,item: sel.commElemTop || sel.artiElemTop // ссылка на элемент с идом - статью или комментарий
  4689. ,commAuthor: sel.commElemBottom
  4690. ? ($q('.info .username', sel.commElemBottom) || $q('.info a', sel.commElemBottom) ).textContent.trim()
  4691. : undefined
  4692. ,commDate: sel.commElemBottom && commTime
  4693. ? commTime.textContent.trim() + (commTime.title ?', '+ commTime.title.replace(/,/,', ') :'')
  4694. : undefined
  4695. ,author: sel.postElem
  4696. ? $q('.infopanel .author a[href*="/users/"]', sel.postElem) && $q('.infopanel .author a[href*="/users/"]', sel.postElem).textContent.trim()
  4697. : undefined
  4698. ,title: sel.postElem
  4699. ? $q('.title span', sel.postElem) && $q('.title span', sel.postElem).textContent.trim()
  4700. : undefined
  4701. ,date: sel.postElem
  4702. ? $q('.infopanel .published', sel.postElem) && $q('.infopanel .published', sel.postElem).textContent.trim() + ($q('.infopanel .published', sel.postElem).title ?', '+ $q('.infopanel .published', sel.postElem).title :'')
  4703. :undefined
  4704. });
  4705. //'sel'.wcl(sel);
  4706. if(sel.articleId)
  4707. sel.url = ROOT +'/post/'+ sel.articleId +'/';
  4708. if(sel.commElemBottom)
  4709. sel.commId = sel.commElemBottom.id.replace(/\D+/,'');
  4710. //разместить контекстную кнопку
  4711. var edit = $q('.title .edit', sel.postElem); //===== кнопка "Edit" ========
  4712. $q('.edit', hNBs).style.display
  4713. = (!edit || sel.commElemBottom) && !/\/(edit|add)\//.test(lh)
  4714. ?'none':'';
  4715. $x(hNBs.style, {left: ((ev.type=='keyup'&& ev.pageX + sel.endX || ev.pageX) +6) +'px'
  4716. ,top: ((ev.type=='keyup'&& ev.pageY + sel.endY || ev.pageY) +16) +'px'
  4717. ,display:'block'});
  4718. selS.ww && win.clearTimeout(selS.ww);
  4719. var hideNBs;
  4720. selS.ww = win.setTimeout(hideNBs = function(){
  4721. if(!selS.noAutoHide && ! selS.hover) hNBs.style.display ='none';
  4722. }, 2999); //hide
  4723. hNBs.style.display ='block';
  4724. $q('.citeTxTa', hNBs) && ($q('.citeTxTa', hNBs).style.display ='none');
  4725. selS.noAutoHide =0; //автоскрытие через 3 с.
  4726. }else{ //===== сохранение прежде набранного при нулевом выделении =====
  4727. hNBs.style.display ='none';
  4728. if(!selS.prev) selS.prev ={};
  4729. $x(selS.prev, { //сохранение прежде набранного
  4730. citeComm: $q('.ta', hNBs).value
  4731. ,textR: selS && selS.textR ||''
  4732. //TODO и много другого контекста
  4733. });
  4734. $q('.ta', hNBs).value = $q('.taAbs', hNBs).value =''; //очистка по закрытию
  4735. selS.ww && win.clearTimeout(selS.ww);
  4736. }
  4737. $e({el: hNBs, on:{ //поведение автоскрытия кнопки при неактивности
  4738. mouseover: function(){selS.ww && win.clearTimeout(selS.ww); selS.hover =1;}
  4739. ,mouseup: function(){selS.noAutoHide =1;}
  4740. ,mouseout: function(){
  4741. selS.hover =0;
  4742. selS.ww && win.clearTimeout(selS.ww);
  4743. selS.ww = win.setTimeout(hideNBs, 2999);
  4744. }} });
  4745. selS = sel; //всё о выделении
  4746. if(s.replace(/^\s+/,'').length <= sTechLen) //если пустая строка выделения
  4747. hN.retainView(); //скрыть, если внутри нет блоков...
  4748. else
  4749. hNE.style.display ='block';
  4750. hNE.style.opacity = s.length >22 || $q('.hlp', hNE) ? 1 : 0.85;
  4751. }
  4752. }
  4753. $e({el: document.body, on:{mouseup: selectOp, keyup: selectOp} });
  4754. }
  4755. var bt =' <button type="button" title="' //команды работы с цитатой
  4756. ,citeButF = function(ev){ //===== движение - drag =====
  4757. hNBs.style.left = (citeButF.xy.x -= citeButF.mou.x - (citeButF.mou.x = ev.pageX)) +'px';
  4758. hNBs.style.top = (citeButF.xy.y -= citeButF.mou.y - (citeButF.mou.y = ev.pageY)) +'px';
  4759. $pdsp(ev);
  4760. },
  4761. hNBs = $e({cl:'citeBtns',
  4762. ht:'<div class="citeCmdLeft">'
  4763. +bt+'Комментарий с цитатой" data="reply">Ответ</button>'
  4764. +bt+'Начать письмо с цитатой; Ctrl - в новой вкладке" data="letter">Письмо</button>'
  4765. +bt+'Начать письмо выделенному или контекстному автору" data="toUser">Юзеру</button>'
  4766. +'<div class=hov>'+bt+'Поиск по сайту (вывод в фрейме)" data="search" style="display:block">Поиск</button>'
  4767. +bt+'Поиск по сайту через Google; Ctrl - в новой вкладке" data="searchGoo">Goo</button>'
  4768. +bt+'Поиск по сайту через Yandex" data="searchYa">Ya</button></div>'
  4769. +'</div>'
  4770. +(hS.correctCite.val ? '<div class="citeCmdRight">'
  4771. +bt+'Отметить как ошибку" data="mistake" class="pre">Грамматика</button>'
  4772. +bt+'Ошибка в знаках препинания" data="punctuation" class="pre">Пунктуация</button>'
  4773. +bt+'" data="misprint" class="pre">Опечатка</button>'
  4774. +bt+'Ошибка в стилистике" data="stylistic" class="pre">Стиль</button>'
  4775. +'</div>':'')
  4776. +'<div class="citeTxTa">'
  4777. +'<div class="citeTx">'
  4778. +'<div class="citeLst"><span class="citeLst2">'
  4779. +'<b class="cite"></b><b class="cite"></b></span></div>'
  4780. +'<div class="citeTxt"></div></div>'
  4781. +'<div class="citeTa"><textarea class="taAbs"></textarea>'
  4782. +'<textarea class="ta"></textarea></div>'
  4783. +'</div>'
  4784. +'<div class="citeCmdTop" class="pre"></div><div class="citeCmdBase">'
  4785. +bt+'Подготовка цитаты" data="citeComm" class="pre">&lt;_></button>'
  4786. +'<button type=button class=edit title="Редактировать" data="edit">&lt;E></button>'
  4787. +(hS.correctCite.val ? bt+'Ошибка содержания" data="wrongData" class="pre">Ош.</button>':'')
  4788. +(hS.hQuotes && hS.hQuotes.val ? bt+'Отправить в HabraQuotes (выделенные 1-10 комментариев)" data="hQuotes">HQ</button>':'')
  4789. +bt+'восстановить набранное в прежнем контексте" data="repair">&lt;_</button>'
  4790. +'</div>',
  4791. on:{
  4792. mousedown: function(ev){ //перемещение конт.кнопок
  4793. if(ev.target.className =='ta'|| parents('^citeTxTa$',ev.target))
  4794. return;
  4795. document.addEventListener('mousemove', citeButF,!1);
  4796. document.addEventListener('mouseup', function(ev){
  4797. document.removeEventListener('mousemove', citeButF)});
  4798. citeButF.xy = {x: parseInt(hNBs.style.left), y: parseInt(hNBs.style.top)};
  4799. $x(citeButF.mou0={}, citeButF.mou ={x: ev.pageX, y: ev.pageY});
  4800. //'citeButF.mou0'.wcl(citeButF.mou0)
  4801. },
  4802. mouseup: function(ev){
  4803. '33'.wcl(ev.target)
  4804. selS.cmd = ev.target.getAttribute('data'); //имя кликнутой кнопки
  4805.  
  4806. selS.subSelect = parents('^citeTxTa$',ev.target) ?1:0; //выделение в цитате или в поле ввода
  4807. /*return;*/
  4808. //hN.ciCom = {misType: ev.target.getAttribute('data')};
  4809. document.removeEventListener('mousemove', citeButF);
  4810. hN.moveMin =4;
  4811. hNBs.wasMoved = Math.abs(citeButF.mou0.x - ev.pageX) + Math.abs(citeButF.mou0.y - ev.pageY) /*< hN.moveMin*/; //признак перемещения
  4812. '44'.wcl('tx',hNBs.wasMoved)
  4813. },
  4814. click: function(ev){
  4815. selS.hN = hN; //TODO обратная ссылка
  4816. if(!h.uName && !(hS.hQuotes && hS.hQuotes.val))
  4817. hN.addNote(this.title +' - требуется авторизация на сайте.');
  4818. else{ //передвижение или исполнение по кнопке
  4819. selS.ww && win.clearTimeout(selS.ww);
  4820. if(hNBs.wasMoved > hN.moveMin){
  4821. 'moved'.wcl(hNBs.wasMoved);
  4822. }else{
  4823. 'hN.sel0'.wcl(selS, selS.subSelect)
  4824. if(!selS.subSelect)
  4825. cmd[ selS.cmd ](selS, ev); //=== действие (клик кнопки) ===
  4826. }
  4827. }
  4828. }
  4829. },apT: document.body
  4830. }),
  4831. cmd ={ //=== команды обработки выделений ===
  4832. insertComm: function(s, clarifShow){
  4833. var repl = s.commElemBottom
  4834. ? $q('.reply .reply_link', s.commElemBottom) || $q('.reply >a.reply', s.commElemBottom) //цитата из комментария
  4835. : $q('.comments_form .title a'); //..из статьи
  4836. 'isRepl'.wcl(repl, s.commElemBottom)
  4837. var tA = $q('textarea#comment_' +'text')
  4838. , taVal = tA.value;
  4839. if(repl){
  4840. '+|+'.wcl(!$q('textarea', repl.parentNode.parentNode))
  4841. /*if(1 || s.commElemBottom && (!$q('textarea', repl.parentNode.parentNode) || !s.commElemBottom);*/
  4842. tA.value = taVal;
  4843. }
  4844. 'cshow'.wcl(s.commElemBottom)
  4845. tA.value += (/\n$/.test(tA.value) || tA.value.length ==0 ?'':'\n') //с новой строки
  4846. + (s.textR.trim().length <=1 ?'':'<blockquote>'+ s.textR +'</blockquote>\n') //удалять 0-1-символьные цитаты
  4847. + (s.text0 || this.citeComm() ||''); //текст из плавающего комментария
  4848. tA.focus();
  4849. },
  4850. reply: function(s, ev){ //ответ в корневой комм., или раскр.отв. в текущий (последн.выд.), прокрут.
  4851. if(s==0){
  4852. var lStor = getLocStor('composeLetter');
  4853. 'lStor'.wcl(lStor);
  4854. if(lStor){
  4855. var sRF = $q('#reply_comments_'+ lStor.commId) || $q('#comment_'+ lStor.commId);
  4856. s ={
  4857. commElemBottom: parents('^comment_item', sRF)
  4858. ,textR: lStor.cite ||''
  4859. ,text0: lStor.text ||''
  4860. };
  4861. removeLocStor('composeLetter');
  4862. }}
  4863. var tAs = $qA('textarea#comment_text')
  4864. ,clarifShow = null; //в QA открыто уточн.или отв.в комм
  4865. 'repl'.wcl(tAs, s);
  4866. if(s !=0 && (s.commElemBottom && parents('comments c2', s.commElemBottom) //цитата с комм.
  4867. || s.artiElemBottom && /content c2/.test(s.artiElemBottom.className)
  4868. || topics && topics.length && s.artiElemBottom && /^content /.test(s.artiElemBottom.className) ))
  4869. this.letter(s, ev,'comm');
  4870. else if(tAs.length)
  4871. this.insertComm(s, clarifShow);
  4872. },
  4873. letter: function(s, ev, isComm){ //письмо с одиночной цитатой
  4874. if(selS)
  4875. this.initLetter(ev, {to: s.author, subj: s.title ?'Re: '+ s.title :'', cite: s.textR}, isComm);
  4876. else
  4877. this.initLetter(ev,{cite: s.textR}, isComm);
  4878. },
  4879. toUser: function(s, ev){ //письмо пользователю (явное имя или контекстное)
  4880. 'selS'.wcl(selS, s.textR, userNameMaxLen, allASCII(s.textR))
  4881. var shortSel = s.textR.length >2 && s.textR.length <= userNameMaxLen && allASCII(s.textR);
  4882. if(selS){
  4883. '++'.wcl(shortSel ? s.textR.trim().replace(',$','') : s.commAuthor || s.author, s.title ?'Re: '+ s.title :'', !shortSel ? s.textR : null)
  4884. this.initLetter(ev, {to: shortSel ? s.textR.trim().replace(',$','') :'Enter username'
  4885. , subj: s.title ?'Re: '+ s.title :'', cite: !shortSel ? s.textR : null} ); //контекстному автору из преж. команды
  4886. // (оформляются все цитаты и ошибки автора, отмеченные в чекбоксах)
  4887. }else
  4888. this.initLetter(ev, {to: shortSel ? s.textR.trim().replace(',$','') : null
  4889. , cite: !shortSel ? s.textR : null} );
  4890. },
  4891. search: function(s, ev, FFind){
  4892. if(srchBut){
  4893. if(srchField) srchField.value = s.textR;
  4894. var evt = document.createEvent("MouseEvents");
  4895. evt.initMouseEvent('click',!0,!0, window, 0, 0, 0, 0, ev.clientY,
  4896. ev.ctrlKey, !1, ev.shiftKey, !1, 0, null);//(type, canBubble, cancelable, view,
  4897. // detail, screenX, screenY, clientX, clientY,
  4898. // ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget)
  4899. (FFind || srchBut).dispatchEvent(evt);
  4900. }},
  4901. searchGoo: function(s, ev){
  4902. this.search(s, ev, srchButGoo);
  4903. },
  4904. searchYa: function(s, ev){
  4905. this.search(s, ev, srchButYa);
  4906. },
  4907. hQuotes: function(s, ev){ //комментарий - ->на habraQuotes.ru
  4908. 'hQuotes'.wcl(0, win.GM_xmlhttpRequest);
  4909. if(typeof GM_xmlhttpRequest !=u){
  4910. hN.addNote(imgWait +'&nbsp;');
  4911. var itemId = s.item && s.item.id
  4912. ,linkHQ =' <a href="http://habraquotes.ru/fresh/" title="новое окно" target="_blank">Перейти на сайт</a>';
  4913. 'items'.wcl(s, s.postElem, s.articleId, s.commCount, itemId);
  4914. if(itemId){
  4915. var waitHQ = win.setTimeout(function(){ //таймаут по неответу
  4916. //alert(305)
  4917. hN.addNote('Ошибка: нет ответа от habraquotes.ru долгое время. '+ linkHQ);
  4918. }, 14000);
  4919. GM_xmlhttpRequest({ //отправка данных для публикации
  4920. url: 'http://habraquotes.ru/api/2.0/quotes/add'
  4921. ,method:'post'
  4922. ,data:'link='+ ROOT +'/post/'+ s.articleId +'/#'+ itemId +'&count='+ s.commCount +'&is_habrajax=1'
  4923. ,headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With":"XMLHttpRequest"}
  4924. ,onload: function(dat2){
  4925. if(/"url":/.test(dat2.responseText) && !/"error":/i.test(dat2.responseText) ||/{"state":"ok"}/i.test(dat2.responseText) ){
  4926. win.clearTimeout(waitHQ);
  4927. 'dat2'.wcl(dat2.responseText,'{"state":"ok"}'==dat2.responseText)
  4928. if(/"url":/.test(dat2.responseText) || /{"state":"ok"}/i.test(dat2.responseText) ){
  4929. datJson = win.JSON.parse(dat2.responseText);
  4930. hN.addNote('Публикация выполнена успешно. <a href="http://habraQuotes.ru/'+ (datJson.url ? datJson.url+'/':'fresh/') +'" title="новое окно" target="_blank">Посетить сайт с&nbsp;местом публикации</a>');
  4931. }}else if(/"err":/.test(dat2.responseText)){
  4932. win.clearTimeout(waitHQ);
  4933. datJson = win.JSON.parse(dat2.responseText);
  4934. hN.addNote('Ошибка: '+ datJson.error +'. '+ linkHQ);
  4935. }else
  4936. hN.addNote('Неопознанный ответ: ', dat2.responseText, linkHQ);
  4937. }, onerror: function(dat2){
  4938. win.clearTimeout(waitHQ);
  4939. 'Err:'.wcl('habraQuotes ', dat2); //TODO по таймауту - повторить
  4940. hN.addNote('<i>Err: ошибка обмена (2-й запрос) с сервисом habraQuotes</i>'+ linkHQ);
  4941. },
  4942. onreadystatechange: function(datRS){
  4943. if(datRS && datRS.readyState ==4 && datRS.status !='200'&& datRS.status !='304' || /error/i.test(datRS.responseText) ){
  4944. win.clearTimeout(waitHQ);
  4945. 'Error habraquotes.ru: status='.wcl(datRS.status +', ошибка ответа. '+ datRS.responseText +' '+ linkHQ);
  4946. hN.addNote(' Ошибка: статус ответа - '+ datRS.status +'. '+ linkHQ);
  4947. }
  4948. }
  4949. });
  4950. }else
  4951. hN.addNote('<i>(был выбран не комментарий, действия нет)</i>');
  4952. }},
  4953. repair: function(s, ev){ if(selS.prev){ //восст_контекста и набранного, случайно закрытого ранее
  4954. var ss = $q('.ta', hNBs).value;
  4955. s.citeComm = selS.prev.citeComm;
  4956. selS.prev.citeComm = ss; //swap
  4957. ss = s.textR;
  4958. s.textR = selS.prev.textR;
  4959. s.text = '<span class="selText">'+ s.textR +'</span>';
  4960. selS.prev.textR = ss; //swap
  4961. this.citeComm(s, ev,'repair');
  4962. }},
  4963. //Дополненное к цитате:
  4964. //copier //пользователь-копировщик (автор цитаты и дополнений к ней)
  4965. //misType: //тип ошибки (5 типов или просто цитата) - предваряющая или заверш-я кнопка
  4966. //subSels: [] //суб-выделения - детализации ошибок или выделений в цитате
  4967. //removes: [] //удаления (исправления)
  4968. //adds: [] //добавления пользователя (исправления)
  4969. // тип оценки (к цитате): -3 - свернуть и никому не показывать; -2 - свернуть; -1 - не очень; 0 - ну, смотрел; 1 - интересно, 2 - надо вернуться 3 - смотреть всем
  4970. //оценка - эмоции, оценка - содержание
  4971. //userComments: [] //ответы пользователя - текст, дата
  4972. mistake: function(a, b){this.citeComm(a, b)}, //группа обработки ошибок (отмеч-с тип)
  4973. punctuation: function(a, b){this.citeComm(a, b)},
  4974. misprint: function(a, b){this.citeComm(a, b)},
  4975. stylistic: function(a, b){this.citeComm(a, b)},
  4976. wrongData: function(a, b){this.citeComm(a, b)},
  4977. citeComm: function(s, ev, noFill){ //=== комментирование цитаты (и субвыделения) =(s==selS)
  4978. var citeTxTa = $q('.citeTxTa', hNBs) //блок контекстного ввода (общий)
  4979. ,citeTx = $q('.citeTx', citeTxTa) //блок цитат
  4980. ,citeLst = $q('.citeLst', citeTxTa) //список цитат
  4981. ,citeLst2 = $q('.citeLst2', citeLst) //список цитат
  4982. ,citeTxt = $q('.citeTxt', citeTxTa) //цитата
  4983. ,citeTa = $q('.citeTa', citeTxTa) //блок комментария
  4984. ,citeTaT = $q('.ta', citeTa); //поле контекстного комментария
  4985. if(!ev && !s) //вернуть написанное в комментарии
  4986. return citeTaT.value;
  4987. var citeTaA = $q('.taAbs', citeTa)
  4988. ,areaSymb = 140 //средняя площадь символа
  4989. ,areaTaSymb = 130
  4990. ,areaText = s.text && Math.sqrt(areaSymb * s.textR.length) ||0
  4991. ,areaTaText = s.comm && Math.sqrt(areaTaSymb * s.comm.length) || 1;
  4992. s.hN.ciCom ={copier: h.uName, misType: s.cmd} //дополнения копировщика к цитате
  4993. $x(citeTx.style, {width: Math.floor(areaText)+50 +'px'
  4994. ,marginLeft: -Math.floor(areaText /2 -10) +'px'
  4995. ,marginRight: -Math.floor(areaText /2 +10) +'px'
  4996. });
  4997. citeTxt.innerHTML = s.text;
  4998. /*$e({el:'b', cl:'cite'
  4999. ,ht:'='+ s.posStart +'_'+ s.posEnd +';'+ s.nodeAncestor.textContent +';'+ s.rAncestorStart
  5000. ,apT: citeLst2});*/
  5001. //this.normTa(areaTaText, citeTaT);
  5002. //this.normTa(areaTaText, citeTaA);
  5003. $x(citeTxt.style, {textAlign: s.textR.length >13 ?'left':'center'
  5004. ,wordWrap: s.textR.length >13 || /\s/.test(s.text) ?'normal':'break-word'
  5005. });
  5006. $q('.selText', citeTx).style.left = s.textR.length >13 ?'1.1em':'0'
  5007. var hh;
  5008. $x(citeTaT.style, hh={width: Math.floor(areaTaText)+50 +'px'
  5009. //, height:'1em'
  5010. //, marginLeft: -Math.floor(areaTaText /2 -10) +'px'
  5011. //, marginRight: -Math.floor(areaTaText /2 +10) +'px'
  5012. ,overflow:'hidden'
  5013. });
  5014. $x(citeTaA.style
  5015. ,{width: Math.floor(areaTaText)+50 +'px'
  5016. ,height:'1em', overflow:'hidden'});
  5017. var initCite
  5018. ,selC = selS;
  5019. (initCite = function(){ //сброс набора прежней цитаты
  5020. citeTaT.value = citeTaA.value = s.citeComm ||''; //восстановление поля
  5021. if(!selC)
  5022. selC ={chgLenPrev:0};
  5023. selC.taH1 =0;
  5024. })();
  5025. selC.tFI =0; //состояние selC.taFloat[]
  5026. var taH1 = selC.taH1 ||16 //высота _одной_ строки в textarea
  5027. ,taParams;
  5028. (taParams = function(ev){ //подгонка размеров растущей области ввода в контексте
  5029. var tx = selC.val = ev ? citeTaT.value : s.citeComm||''
  5030. ,txL = tx.length
  5031. ,tASH = citeTaA.scrollHeight; //реальная высота введённого текста
  5032. citeTaA.value = tx;
  5033. s.hN.ciCom.userComments = tx; //фиксация набранного
  5034. selC.taFloat =[{h:{n:4,w:50}},{h:{n:10,w:128}},{h:{n:16,w:159}},{h:{n:24,w:238}}
  5035. ,{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 - число строк
  5036. selC.taFlNmax =0; //поиск максимума .h.n
  5037. for(var i =0, iL = selC.taFloat.length; i < iL; i++)
  5038. if(selC.taFloat[i].h && selC.taFloat[i].h.n > selC.taFlNmax){
  5039. selC.taFlNmax = selC.taFloat[i].h.n;
  5040. selC.taFlImax = i;
  5041. }
  5042. if(!ev && selC){ //начальная установка (taH1 и фокус)
  5043. citeTa.style.left =0;
  5044. selC.lenPrev2 = selC.lenPrev = txL;
  5045. win.setTimeout(function(){
  5046. //citeTaT.focus();
  5047. selC.taH1 = citeTaA.scrollHeight -1 -2*isFx;
  5048. },1);
  5049. }
  5050. //'ev'.wcl(ev, !ev, {tx:tx, tASH:tASH || taH1},selC.tFI)
  5051. if( (function(h2){ //chkGrow=== проверка размеров содержимого поля ввода ===
  5052. var taS = selC.taFloat[selC.tFI];
  5053. for(var j in taS) var taSkey = j; //имя ключа состояния
  5054. if(taSkey !='h' && taSkey !='v')
  5055. wcl('Err: '+ 'ош. в выборе типа поля ввода');
  5056. txL = h2.tx.length;
  5057. taNS = Math.floor((h2.tASH +0.5)/ taH1); //(реальное) чис.строк поля ввода
  5058. //'taNS,tx'.wcl(taNS,tx, selC.taH1, taH1)
  5059. if(txL <= selC.taFlNmax){ //выбор 1-строчного варианта поля
  5060. for(var i =0, iL = selC.taFlImax +1; i < iL; i++)
  5061. if(txL <= selC.taFloat[i].h.n && (i==0 || i >0 && txL > selC.taFloat[i-1].h.n)){
  5062. selC.tFINew = i; break;}
  5063. }else{
  5064. for(var i = selC.taFlImax+1, iL = selC.taFloat.length+1; i < iL; i++)
  5065. if(taNS <= selC.taFloat[i].v.r && (i==selC.taFlImax+1 || i >selC.taFlImax+1 && taNS > selC.taFloat[i-1].v.r) ){
  5066. selC.tFINew = i; break;}
  5067. }
  5068. if(s.citeComm)
  5069. selC.tFI = Math.max(0, selC.tFINew -1);
  5070. //'i,txL,taFlNmax'.wcl(i, txL, selC.taFlNmax)
  5071. if( (selC.lenPrev2 < txL ^ selC.tFINew > selC.tFI) || Math.abs(txL - selC.chgLenPrev) < txL/8){ //консервативность смены
  5072. selC.tFINew = selC.tFI;
  5073. selC.lenPrev2 = selC.lenPrev;
  5074. selC.lenPrev = txL;
  5075. }
  5076. //'taNS'.wcl(h2.tASH, taNS, selC.tFINew)
  5077. if(selC.tFINew != selC.tFI){
  5078. selC.chgLenPrev = txL;
  5079. return!0;}
  5080. })({tx:tx, tASH:tASH || taH1})
  5081. || !ev || Math.abs(tASH - selC.taHprev) < 6 ){ //обновл_ размеров
  5082. var taH2 = tASH ||16; //далее - высота (px) всех строк в поле ввода
  5083. citeTaA.style.height = (taH1 -1) +'px';
  5084. win.setTimeout(function(){
  5085. citeTaT.style.height = citeTa.style.height = ((selC.taHprev = citeTaA.scrollHeight) -1)+'px';
  5086. //'=citeTaA'.wcl(tASH, citeTaA.scrollHeight, citeTaA.value, selC.taHprev
  5087. // ,'||',taS, selC.tFINew);
  5088. citeTa.style.width = (taS && (taS.h && taS.h.w || taS.v.w))+'px';
  5089. citeTx.style.bottom = (selC.taHprev -3) +'px';
  5090. },1);
  5091. citeTa.style.height = (taH2 -1) +'px';
  5092. citeTx.style.bottom = (taH2 -3) +'px';
  5093. //'tFINew==='.wcl(selC.tFINew, taS, tASH, selC.taHprev, tASH / selC.taH1, selC.taH1)
  5094. if(typeof selC.tFINew =='number'&& ev || s.citeComm){
  5095. var taS = selC.taFloat[selC.tFINew];
  5096. citeTaT.style.width = citeTaA.style.width
  5097. = citeTa.style.width = (taS && (taS.h && taS.h.w || taS.v.w))+'px';
  5098. citeTa.style.left = Math.min(-((taS && (taS.h && taS.h.w || taS.v.w))/2 -43),0) +'px';
  5099. selC.tFI = selC.tFINew;
  5100. }
  5101. selC.taHprev = taH2;
  5102. }
  5103. })();
  5104. citeTaT.addEventListener('keypress',taParams,!1); //контроль за вводом символов
  5105. citeTaT.addEventListener('keyup',taParams,!1);
  5106. $x(citeTa.style, hh);
  5107. citeTxTa.style.display ='block';
  5108. $x(citeLst.style, {MaxWidth: Math.floor(areaText)+54 +'px'
  5109. ,top: -citeLst.offsetHeight -2 +'px'});
  5110. },
  5111. normTa: function(s, t){ //нормализация поля ввода: вычисление ширины и высоты по содержимому
  5112. var citeTa = t.parentNode
  5113. ,citeTxTa = citeTa.parentNode;
  5114. if(s !=null)
  5115. t.value = s;
  5116. },
  5117. htmlSelect: function(s, ev){ //===== оформить с захваченным HTML =====
  5118.  
  5119. $sp(ev);
  5120. },
  5121. edit: function(s, ev){ //===== редактировать область цитаты =====
  5122. setLocStor('composeLetter', {cite: s.textR});
  5123. if(/\/topic\/(add|edit)\//.test(lh)){
  5124. win.clearTimeout(wwPrevi);
  5125. fillLetter();
  5126. return;}
  5127. if((ev.ctrlKey || ev.cmdKey) ^ ev.shiftKey)
  5128. win.open(ROOT +'/topic/edit/'+ s.articleId +'/','_blank');
  5129. else
  5130. openInFrame({clientY: ev.clientY},{href: ROOT +'/topic/edit/'+ s.articleId +'/'});
  5131. $sp(ev);
  5132. },
  5133. mis: function(s){ //оформление ошибки
  5134. //hN.selContext = s; //сохранено состояние выделения (для след.оп. типа "письма")
  5135. var misType = s.misType = {mistake: 0, punctuation: 1, misprint: 2, stylistic: 3, wrongData: 4, citeComm: -1}
  5136. ,selField = $q('.sele .selText', hNCiteList)
  5137. ,selText = selField && selField.innerHTML; //текст выделения (возм-о, обраб-ный)
  5138. hNCiteList.removeChild($q('.sele', hNCiteList)); //удалить копию выделения
  5139. if(!hN.misId)
  5140. hN.misId = 1;
  5141. s.misId = hN.misId; //очередной Id выделения
  5142. $e({cl:'item'
  5143. ,ht:'<input type="checkbox" id="mis'+ hN.misId++
  5144. +'" name="'+ s.author +'" value="" checked="checked"/>'
  5145. + '<font style="background-color:#dbb; color:#964">'
  5146. + (misType[s.cmd] >=0 ? misType[s.cmd]:'') +'</font> '
  5147. +'<span class="selText">'+ (selText || s.textR) +'</span>'
  5148. ,apT: hNCiteList });
  5149. },
  5150. initLetter: function(ev, g, isComm){ //===== составить письмо ===== //g:{to,subj,cite}
  5151. //text, addressee, date, title, link, source, sourceLink //загрузить форму отправки письма
  5152. //для публикации письма в другом окне передаётся адрес с меткой времени и создаётся элемент хранилища с той же меткой. По получению элемент проверяется, используется и удаляется. Одновременно существует не более 1 объекта публикации письма. Формирование письма - ПЕРЕД отправкой, поэтому передаются 3 поля и метка времени. На случай отсутствия хранилища передаются 2 поля (укороченный текст и автор) и метка времени.
  5153. g = $x({to:'', subj:'', cite:'' }, g);
  5154. var s = selS
  5155. ,receiver = g.to=='Enter username' || g.to== h.uName ?''
  5156. : (g.to && !g.cite && g.to || s.commAuthor || g.to);
  5157. 'initLet'.wcl(g, receiver)
  5158. setLocStor('composeLetter',
  5159. $x(g, {cite: g.cite
  5160. + (/\n$/.test(g.cite) || g.cite && g.cite.length ==0 || !g.cite ?'':'\n')
  5161. ,noReceiver: !receiver
  5162. ,text: s.val ||'' //введённый комментарий
  5163. ,date: s.date
  5164. ,commDate: s.commDate
  5165. ,url: s.url
  5166. ,commId: s.commId
  5167. ,commAuthor: s.commAuthor}) );
  5168. var timeStmp = (+new Date()+'').replace(/(^\d{3}|\d{3}$)/g,'')
  5169. ,hrf = (!isComm
  5170. ? ROOT +'/conversations/'+(receiver?receiver+'/':'')
  5171. : s.url
  5172. )+'?time33='+ timeStmp
  5173. +(isComm ?'&cmd=insertComm':'')
  5174. +(!win.localStorage?'#'
  5175. +(g.to?'to='+ encodeURIComponent(g.to):'')
  5176. +(g.cite?(g.to?'&':'')+'text='+ encodeURIComponent( g.cite
  5177. +(g.cite && g.cite.length >500?'...':'') ):'')
  5178. :(s.commElemBottom ?'#'+ s.commElemBottom.id :'') );
  5179. 'letter'.wcl(s, hrf)
  5180. if((ev.ctrlKey || ev.cmdKey) ^ ev.shiftKey)
  5181. win.open(hrf,'_blank');
  5182. else
  5183. openInFrame({clientY: ev.clientY},{href: hrf});
  5184. //внести шаблон данных
  5185. },
  5186. buildCite: function(s){
  5187. var cLIs = $qA('.item', hNCiteList);
  5188. for(var i =0, iL = cLIs.length; i < iL; i++)
  5189. $q('input[type="checkbox"][checked="checked"]', cLIs[i]);
  5190. var subj ='Замечания к "'+ s.title.substr(0, 40)+ (s.title.length >40?'...':'')+'"'
  5191. ,foundMulti = 0//более 1 или тип 4
  5192. ,foundSemi = 0 //не по одной ош. в категориях 1-3
  5193. ,foundShe = 0 //1 шт. и ж. рода (тип 1-2)
  5194. ,mistakE = 0
  5195. ,misPrinT = 0
  5196. ,stylisT = 0.0
  5197. ,isSubSel =0 //есть ли суб-селекты
  5198. ,isWrongSel =0 //есть ли механизм подчёркиваний и пометок ошибок
  5199. ,mistSel =['ошибк'+ (mistakE?'а':'и') //перечислитель типов ошибок
  5200. ,'опечатк'+ (misPrinT?'а':'и')
  5201. ,'неверны'+ (stylisT?'й':'е') +' стилистически'+ (stylisT?'й':'е') +' оборот'+ (stylisT?'':'ы')
  5202. ,'неверные данные'];
  5203. for(var i=3; i >= 0; i--) //удаление пустых строк
  5204. if(0)
  5205. mistSel.splice(i, 1);
  5206. var x = '&nbsp; &nbsp; Здравствуйте, '+ s.author +'!\n'
  5207. +'&nbsp; &nbsp; В Вашей статье &quot;<a href="'+ s.link +'"><b>'
  5208. + s.title.substr(0, 60) + (s.title.length >60 ?'...':'')
  5209. +'</b></a>&quot; от <i>'+ s.date +'</i> обнаружен'
  5210. + (foundMulti ?'ы'+ (foundSemi ?':':''):(foundShe ?'а':''))
  5211. + mistSel.split(', ')
  5212. + (isSubSel ?'(выделено синим цветом в цитате)':'') +'.\n'
  5213. +'&nbsp; &nbsp; На мой взгляд, текст следовало бы писать так, как отмечено'
  5214. + (isWrongSel ?' красным цветом или подчёркиванием':'') +' в последующей строке.';
  5215.  
  5216. var aa='текст-цитата скорректированный текст (<текст_дополнительных пояснений>)'
  5217. +'С уважением, <своё_имя>.'
  5218. +'(К|Поправки к) статье|комментарию "<название>", <дата>';
  5219.  
  5220. }
  5221. };
  5222. if(/cmd=insertComm/.test(lh) && !win.opera) //дообработка комментария из localStorage
  5223. cmd.reply(0);
  5224. if(hS.killToTop.val)
  5225. addRules('.to_top{display:none!important}');
  5226. showSourceLang(topic,'add_label_lang'); //только метки языков к блокам кодов
  5227. showSourceLang(comments,'add_label_lang');
  5228.  
  5229. (function(){ //единый таймер контроля: показ оставшихся голосов после отправки оценок и т.д.
  5230. if(chargeDiv && !/</.test(chargeDiv.innerHTML) && replaceCharge)
  5231. replaceCharge(); //восстановить правку описания оставшихся голосов
  5232. win.setTimeout(arguments.callee, 2630);
  5233. })();
  5234. '(endParse)topicTitle'.wcl(topicTitle);
  5235. if($q(doc.body) && $q(doc.body).childNodes.length <=3 ){
  5236.  
  5237. //win.location = 'http://webcache.googleusercontent.com/search?q=cache:'+ win.location;
  5238. }
  5239. //})(); //=======/ end contSelect() ========
  5240.  
  5241. },!1); //=======/ end readyLoad() ========
  5242.  
  5243. if(typeof habrAjax !=u && (!habrAjax.wasLoad||/(Chrome\/|Opera\/)/.test(navigator.userAgent))) //для Хрома: эти события не существуют для юзер-скрипта
  5244. readyLoad();
  5245. }catch(er){
  5246. wcl('~~ER_global: '+ er +' (line '+(er.lineNumber||'')+')')}; //для оповещения об ошибках в Fx
  5247. })(typeof unsafeWindow !='undefined'? unsafeWindow: (function(){return this})(),'undefined')