Pull to refresh

Отборные комментарии хабратопиков

Reading time 10 min
Views 4.4K

Вступление


Хабр мной любим не только за свои посты, но и за комментарии к ним. К некоторым темам набирается слишком много комментариев, поэтому я быстро прокручиваю страницу в поисках самых высокорейтинговых. Чтобы повысить эффективность этого процесса, я написал букмарклет — JavaScript-код, сохраняемый как браузерная закладка (Вики). Нынче же считаю своим долгом поделиться им с сообществом.

Букмарклет



Всё просто. Вы добавляете в закладки страницу, адрес которой выглядит следующим образом:

JavaScript (569 строк)
javascript:
function tImeit(st)
{
	var tim=st.split(" ");
	var tima=580320*(parseInt(tim[2])-2000)+1440*(parseInt(tim[0])-1)+60*(parseInt(tim[4].charAt(0))*10+parseInt(tim[4].charAt(1)))+parseInt(tim[4].charAt(3))*10+parseInt(tim[4].charAt(4));
	for (var i=0;i<12;i++)
	{
		if (mOnths[i]!=tim[1])
		{
			tima+=44640;
		}
		else
		{
			i=13;
		};
	};
	return tima;
};
function cLose()
{
	$("#ComSort").animate({right:"-410px"},500);
}
function fOntlarger()
{
	$(".message,.content").animate({fontSize:"+=2"},0);
}
function sOrt(a, b) 
{
	if (a.k > b.k) 
	{
		return -1;
	}
	else
	{
		if (a.k < b.k)
		{
			return 1;
		}
		else
		{
			if (a.ind>b.ind)
			{
				return 1;
			}
			else
			{
				return -1;
			}
		};
	};
};
function sOrt2(a, b) 
{
	if (a.k > b.k) 
	{
		return -1;
	}
	else
	{
		if (a.k < b.k)
		{
			return 1;
		}
		else
		{
			if (a.k2>b.k2)
			{
				return 1;
			}
			else
			{
				return -1;
			}
		};
	};
};
function bEst()
{
	xX=mB[0].ind;
	gO();
};
function nExtbest()
{
	var i=mA[xX].best;
	if ((i<(mA.length-1)) && ($("#bEst").text().length>0))
	{
		i++;
	}
	else
	{
		if ($("#bEst").text().length>0)
		{
			var obj=$("#wO");
		}
		else
		{
			var obj=$("#bE");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mB[i].ind;
	gO();
};
function wOrst()
{
	xX=mB[mA.length-1].ind;
	gO();
};
function nExtworst()
{
	var i=mA[xX].best;
	if ((i>0) && ($("#bEst").text().length>0))
	{
		i--;
	}
	else
	{
		if ($("#bEst").text().length>0)
		{
			var obj=$("#bE");
		}
		else
		{
			var obj=$("#wO");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mB[i].ind;
	gO();
};

function lAst()
{
	xX=mN[0].ind;
	gO();
};
function nExtlast()
{
	var i=mA[xX].newest;
	if ((i<(mA.length-1)) && ($("#fIrst").text().length>0))
	{
		i++;
	}
	else
	{
		if ($("#fIrst").text().length>0)
		{
			var obj=$("#fI");
		}
		else
		{
			var obj=$("#lA");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mN[i].ind;
	gO();
};
function fIrst()
{
	xX=mN[mA.length-1].ind;
	gO();
};
function nExtfirst()
{
	var i=mA[xX].newest;
	if ((i>0) && ($("#fIrst").text().length>0))
	{
		i--;
	}
	else
	{
		if ($("#fIrst").text().length>0)
		{
			var obj=$("#lA");
		}
		else
		{
			var obj=$("#fI");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mN[i].ind;
	gO();
};

function mOot()
{
	xX=mM[0].ind;
	gO();
};
function nExtmoot()
{
	var i=mA[xX].moot;
	if ((i<(mA.length-1)) && ($("#mOot").text().length>0))
	{
		i++;
	}
	else
	{
		if ($("#mOot").text().length>0)
		{
			var obj=$("#sI");
		}
		else
		{
			var obj=$("#mO");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mM[i].ind;
	gO();
};
function sImple()
{
	xX=mM[mA.length-1].ind;
	gO();
};
function nExtsimple()
{
	var i=mA[xX].moot;
	if ((i>0) && ($("#mOot").text().length>0))
	{
		i--;
	}
	else
	{
		if ($("#mOot").text().length>0)
		{
			var obj=$("#mO");
		}
		else
		{
			var obj=$("#sI");
		}
		obj.removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
	};
	xX=mM[i].ind;
	gO();
};
function gO()
{
	if (mA[xX]) 
	{
		document.location.replace(mA[xX].href);
		$(mA[xX].href+">.comment_body,"+mA[xX].href+">.comment_body>.message").animate(
		{
			backgroundColor:"#f0f0e7"
		},300,function(){$(this).animate({backgroundColor:"none"},500);});
		$("#bEst").text((mA[xX].best+1)+" из "+mA.length);
		$("#fIrst").text((mA.length-mA[xX].newest)+" из "+mA.length);
		$("#mOot").text((mA[xX].moot+1)+" из "+mA.length);
	} 
	else 
	{
		document.location.replace('#');
	};
};

if (typeof(mA) == 'undefined')
{
	var mA=new Array();
	var mB=new Array();
	var mN=new Array();
	var mM=new Array();
	var ind=0;
	var mOnths=["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"];
	$('#comments span.score').each(function()
	{
		var str=$(this).attr('title');
		var up=parseInt(str.substring(str.indexOf('↑')+1,str.indexOf('и')-1));
		var down=parseInt(str.substring(str.indexOf('↓')+1,str.length));
		var ti=tImeit($(this).parent().parent().parent().find('time').text());
		mA.push({ind:ind,up:up,down:down,href:$(this).parent().parent().parent().find('a.link_to_comment').attr('href'),ttime:ti});
		mB.push({ind:ind,k:(up-down)});
		mN.push({ind:ind,k:ti});
		var moot=up;
		if (up>down)
		{
			moot=down;
		};
		mM.push({ind:ind,k:moot,k2:(up-down)});
		ind++;
	});
	if (mA.length==0)
	{
		alert('Комментариев нет');
	}
	else
	{
		mB.sort(sOrt);
		mN.sort(sOrt);
		mM.sort(sOrt2);
		var xX=mB[0].ind;
		for (i=0;i<mA.length;i++)
		{
			mA[mB[i].ind].best=i;
			mA[mN[i].ind].newest=i;
			mA[mM[i].ind].moot=i;
		};
		var table="<style type='text/css'>
#mTable tr{
	height: 20px;
}
#mTable td{
	vertical-align: middle;
	text-align: center;
}
#mTable td.count{
	width: 100px;
}
#mTable .bIg{
	width: 100px;
	font-size: 25px;
	line-height: 50px;
}
#mTable .bR{
	vertical-align: top;
}
#mTable .bL{
	vertical-align: bottom;
}
#mTable .mArker{
	width: 5px;
	height: 5px;
	display: block;
}
#mTable .mL{
	margin-right: 5px;
}
#mTable .mR{
	margin-left: 5px;
}
#mTable .mK{
	margin-top: -5px;
	width: 3px;
}
#mTable .rEset>td{
	border-top: 1px dashed #cccccc;
}
#mTable .rEset,#mTable .pRereset{
	height: 10px;
}
#mTable .sElect{
	box-shadow: 0 0 10px #4d7285;
}
#mTable .sEl{
	transition: all 0.3s;
}
#mTable small{
	font-size: 8px;
	color: #999999;
}
#mTable td>span>a{
	color: #333;
	cursor: pointer;
	line-height: 30px;
	text-decoration: none;
}
#mTable td>span>a:hover{
	text-decoration: underline;
}

#mTable td>a{
display: block;
-moz-user-select: -moz-none;
-o-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
height: 100%;
background-color: #eeeeee;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #cccccc));
background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
background-image: linear-gradient(top, #eeeeee, #cccccc);
border: 1px solid #ccc;
border-bottom: 1px solid #bbb;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
color: #333;
text-align: center;
text-shadow: 0 1px 0 #eee;
outline: none;
cursor: pointer;
transition: all 0.3s;
}
#mTable td>a:hover,#mTable td>a:focus {
background-color: #dddddd;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #bbbbbb));
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
background-image: linear-gradient(top, #dddddd, #bbbbbb);
border: 1px solid #bbb;
border-bottom: 1px solid #999;
text-shadow: 0 1px 0 #ddd;
transition: all 0.3s;
}
#mTable td>a:active {
border: 1px solid #aaa;
border-bottom: 1px solid #888;
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
transition: all 0.3s;
}
</style>
<table id='mTable' style='border:none;' cellpadding='0' cellspacing='0'>
<tr>
	<td colspan='5'><span><a onclick='cLose()'>Закрыть</a></span></td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #339900'></span>	
	</td>
	<td>
		<a onclick='bEst()' id='bE' class='sEl'>Лучший</a>
	</td>
	<td rowspan='4' class='count'>
		<span id='bEst'></span>
	</td>
	<td rowspan='3' class='bIg bR'>
		<a onclick='nExtworst()'>↑</a>
	</td>
	<td><span class='mArker mR' style='background-color: #A9A9A9'></span>	
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #339900'></span>	
	</td>
	<td rowspan='3' class='bIg bL'>
		<a onclick='nExtbest()' id='nExtbe'>↓</a>
	</td>
	<td><span class='mArker mR' style='background-color: #BA9B9B'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #6EA155'></span>		
	</td>
	<td><span class='mArker mR' style='background-color: #CC0000'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #A9A9A9'></span>		
	</td>
	<td>
		<a onclick='wOrst()' id='wO' class='sEl'>Худший</a>
	</td>
	<td><span class='mArker mR' style='background-color: #CC0000'></span>		
	</td>
</tr>
<tr class='pRereset'>
	<td colspan='5'></td>
</tr>
<tr class='rEset'>
	<td colspan='5'></td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #FFFFFF'></span>	
	</td>
	<td>
		<a onclick='fIrst()' id='fI' class='sEl'>Первый</a>
	</td>
	<td rowspan='4' class='count'>
		<span id='fIrst'></span>
	</td>
	<td rowspan='3' class='bIg bR'>
		<a onclick='nExtlast()'>↑</a>
	</td>
	<td><span class='mArker mR' style='background-color: #FFFFFF'></span>	
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #F3F3FF'></span>	
	</td>
	<td rowspan='3' class='bIg bL'>
		<a onclick='nExtfirst()'>↓</a>
	</td>
	<td><span class='mArker mR' style='background-color: #F3F3FF'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #E8E8FF'></span>		
	</td>
	<td><span class='mArker mR' style='background-color: #E8E8FF'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #E8E8FF'></span>		
	</td>
	<td>
		<a onclick='lAst()' id='lA' class='sEl'>Последний</a>
	</td>
	<td><span class='mArker mR' style='background-color: #E8E8FF'></span>		
	</td>
</tr>
<tr class='pRereset'>
	<td colspan='5'></td>
</tr>
<tr class='rEset'>
	<td colspan='5'></td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #CC0000'></span><span class='mArker mK' style='background-color: #339900'></span>
	</td>
	<td>
		<a onclick='mOot()' id='mO' class='sEl'>Спорный</a>
	</td>
	<td rowspan='4' class='count'>
		<span id='mOot'></span>
	</td>
	<td rowspan='3' class='bIg bR'>
		<a onclick='nExtsimple()'>↑</a>
	</td>
	<td><span class='mArker mR' style='background-color: #BA9B9B'></span>	
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #CC0000'></span><span class='mArker mK' style='background-color: #339900'></span>
	</td>
	<td rowspan='3' class='bIg bL'>
		<a onclick='nExtmoot()'>↓</a>
	</td>
	<td><span class='mArker mR' style='background-color: #6EA155'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #BA9B9B'></span><span class='mArker mK' style='background-color: #6EA155'></span>	
	</td>
	<td><span class='mArker mR' style='background-color: #CC0000'></span>
	</td>
</tr>
<tr>
	<td><span class='mArker mL' style='background-color: #A9A9A9'></span>		
	</td>
	<td>
		<a onclick='sImple()' id='sI' class='sEl'>Однозначный</a>
	</td>
	<td><span class='mArker mR' style='background-color: #339900'></span>		
	</td>
</tr>
<tr>
	<td colspan='5'><span><a onclick='fOntlarger()'>Шрифт крупнее</a></span></td>
</tr>
<tr class='pRereset'>
	<td colspan='5'><span><a href='http://NikitaPolunin.ru' target='_blank' style='line-height: 10px;'><small>Никита Полунин</small></a></span></td>
</tr>
</table>";
		$("<div id='ComSort' style='position:fixed;right:-410px;z-index:100;top:10px;border:4px solid #cccccc;background-color: #ffffff;box-shadow: 0 4px 10px #666666;padding: 0 5px;'>"+table+"</div>").appendTo("#layout").animate({right:"10px"},500);
	};
	document.location.replace("#");
}
else
{
	if (mA.length>0)
	{
		$("#nExtbe").removeClass('sElect').addClass('sElect').animate({padding:"0"},400,function(){$(this).removeClass('sElect');});
		$("#ComSort").animate({right:"10px"},500);
		nExtbest();
	}
	else
	{
		document.location.replace("#");
	};
};


Если нет желания выделять код и вставлять его в закладку, можете перетащить специально заготовленную ссылку на панель закладок. Так как здесь её разместить невозможно, пришлось создать отдельную страницу. Короче, ссылка с кодом находится по этой ссылке.
При щелчке по закладке-букмарклету появятся кнопки, смысл которых в следующем:
  • Переход от комментария с наивысшим рейтингом к другим в порядке убывания рейтинга (и наоборот).
  • От первого по дате к последнему (и наоборот).
  • От наиболее «спорного» к наименее спорному (и наоборот).
    Чем больше плюсов (минусов) у отрицательного (положительного) комментария, тем более спорным он считается. При равном значении «рецессивных» голосов более спорным считается комментарий с меньшим рейтингом.

Также можно продолжать щёлкать по закладке, перебирая комментарии от лучшего (согласно рейтингу) к худшему.

Кроссбраузерность


Естественно, Internet Explorer имел возражения относительно моей идеи — он против слишком длинных ссылок в закладках. Договориться можно и с ним, если в закладку добавлять только код для загрузки и вставки в страницу всего скрипта (со стороннего ресурса). Так обычно и делаются эти самые букмарклеты, но ведь скрипт может вдруг исчезнуть со стороннего ресурса или вовсе перейти на сторону зла… Другое дело, когда код целиком у вас в закладке. В общем, я просто передаю привет пользователям IE.
Chrome, Safari, Firefox справляются, в Opera у меня не получилось вывести панель закладок, чтобы проверить.

Заключение


Скрипт может перестать работать после изменения вёрстки комментариев Хабра и т.п., но так как я сам им пользуюсь, буду стараться обновлять. В конце концов, код открыт.

Что скажете?
Only registered users can participate in poll. Log in, please.
Востребованность
30.95% Мне это нужно 91
47.62% Мне это не нужно 140
21.43% Воздержусь 63
294 users voted. 149 users abstained.
Only registered users can participate in poll. Log in, please.
Работает?
19.63% Вполне, добавил в закладки 42
7.94% Работает, но есть нюансы 17
7.94% Не фонтан 17
13.55% Автор, не позорься! 29
50.93% Воздержусь 109
214 users voted. 191 users abstained.
Tags:
Hubs:
+11
Comments 15
Comments Comments 15

Articles