Ответ 1
Правильно, javascript не может обнаружить, что ссылка посещена в Firefox или Chrome, - которые являются единственными 2 браузерами, применимыми в этом контексте Greasemonkey.
Это потому, что Firefox и Chrome серьезно относятся к безопасности и конфиденциальности. Из спецификация CSS2:
Примечание. Возможно, авторы стилей могут злоупотреблять псевдонимами: link и: visited, чтобы определить, какие сайты посетил пользователь без согласия пользователя.
Таким образом, UA могут обрабатывать все ссылки как невидимые ссылки или реализовывать другие меры, чтобы сохранить конфиденциальность пользователя при потере посещенных и незатронутых ссылок. См. [P3P] для получения дополнительной информации о конфиденциальности.
См. также Конфиденциальность и селектор посещений
Вы можете увидеть демонстрацию, показывающую, что безопасные браузеры не позволят вам просматривать просмотренные ссылки на jsfiddle.net/n8F9U.
В вашей конкретной ситуации, поскольку вы посещаете страницу и сохраняете ее открытой, вы можете помочь script отслеживать, какие ссылки были посещены. Это не безупречно, но я считаю, что он будет делать то, о чем вы просили.
Во-первых, см. script в действии, выполнив следующие действия:
- Установите script, как есть.
- Перейдите на тестовую страницу, jsbin.com/eledog.
На тестовой странице добавляется новая ссылка, каждый раз, когда она перезагружается или обновляется. -
GM script добавляет 2 кнопки к страницам, на которых он работает. Кнопка "Пуск/Стоп" в верхнем левом углу и кнопка "Очистить" в правом нижнем углу.
Когда вы нажимаете кнопку "Старт", она выполняет следующие действия:
- Все существующие ссылки на странице регистрируются как "посещенные".
- Он запускает таймер (настройка по умолчанию: 3 секунды), когда таймер выключается, он перезагружает страницу.
- Каждый раз, когда страница перезагружается, она открывает все новые ссылки и запускает новый таймер перезагрузки.
- Нажмите кнопку "Стоп", чтобы остановить перезагрузку, список посещенных ссылок сохраняется.
Кнопка "Очистить" , удаляет список посещенных страниц.
ПРЕДУПРЕЖДЕНИЕ: Если вы нажмете "Очистить" , пока цикл обновления активен, то при следующем перезагрузке страницы в новых вкладках будут открываться ссылки all.
Затем использовать script на вашем сайте...
Внимательно прочитайте комментарии в script, вам нужно будет изменить значения @include
, @exclude
и selectorStr
в соответствии с используемым вами сайтом.
Для достижения наилучших результатов отключите любые дополнения "Reload Every" или "Autoupdate".
Важные замечания:
-
script должен использовать постоянное хранилище для отслеживания ссылок.
Возможные варианты: cookie,sessionStorage
,localStorage
,globalStorage
,GM_setValue()
иIndexedDB
.Все они имеют недостатки, и в этом случае (единственный сайт, потенциально огромное количество ссылок, несколько сеансов)
localStorage
- лучший выбор (IndexedDB
может быть, но он все еще слишком нестабилен - FF падает на моей машине).Это означает, что ссылки могут отслеживаться только для каждого сайта, а "утилит", "конфиденциальность" или "чистые" утилиты могут блокировать или удалять список посещенных ссылок. (Точно так же, как очистка истории браузера будет reset любым стилем CSS для посещенных ссылок.)
-
script только для Firefox. Он не должен работать на Chrome, даже с установленным Tampermonkey, без небольшой перестройки.
script:
/*******************************************************************************
** This script:
** 1) Keeps track of which links have been clicked.
** 2) Refreshes the page at regular intervals to check for new links.
** 3) If new links are found, opens those links in a new tab.
**
** To Set Up:
** 1) Carefully choose and specify `selectorStr` based on the particulars
** of the target page(s).
** The selector string uses any valid jQuery syntax.
** 2) Set the @include, and/or, @exclude, and/or @match directives as
** appropriate for the target site.
** 3) Turn any "Auto update" features off. Likewise, do not use any
** "Reload Every" addons. This script will handle reloads/refreshes.
**
** To Use:
** The script will place 2 buttons on the page: A "Start/Stop" button in
** the upper left and a "Clear" button in the lower left.
**
** Press the "Start" button to start the script reloading the page and
** opening any new links.
** When the button is pressed, it is assumed that any existing links have
** been visited.
**
** Press the "Stop" button to halt the reloading and link opening.
**
** The "Clear" button erases the list of visited links -- which might
** otherwise be stored forever.
**
** Methodology:
** Uses localStorage to track state-machine state, and to keep a
** persistent list of visited links.
**
** Implemented with jQuery and some GM_ functions.
**
** For now, this script is Firefox-only. It probably will not work on
** Chrome, even with Tampermonkey.
*/
// ==UserScript==
// @name _New link / visited link, tracker and opener
// @include http://jsbin.com/*
// @exclude /\/edit\b/
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @grant GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
//--- Key control/setup variables:
var refreshDelay = 3000; //-- milliseconds.
var selectorStr = 'ul.topicList a.topicTitle';
//--- Add the control buttons.
$("body") .append ( '<div id="GM_StartStopBtn" class="GM_ControlWrap">'
+ '<button>Start checking for new links.</button></div>'
)
.append ( '<div id="GM_ClearVisitListBtn" class="GM_ControlWrap">'
+ '<button>Clear the list of visited links.</button></div>'
);
$('div.GM_ControlWrap').hover (
function () { $(this).stop (true, false).fadeTo ( 50, 1); },
function () { $(this).stop (true, false).fadeTo (900, 0.8); }// Coordinate with CSS.
);
//--- Initialize the link-handler object, but wait until the load event.
var stateMachine;
window.addEventListener ("load", function () {
stateMachine = new GM_LinkTrack ( selectorStr,
'#GM_StartStopBtn button',
'#GM_ClearVisitListBtn button',
refreshDelay
);
/*--- Display the current number of visited links.
We only update once per page load here.
*/
var numLinks = stateMachine.GetVisitedLinkCount ();
$("body").append ('<p>The page opened with ' + numLinks + ' visited links.</p>');
},
false
);
/*--- The link and state tracker object.
Public methods:
OpenAllNewLinks ()
StartStopBtnHandler ()
ClearVisitedLinkList ()
StartRefreshTimer ();
StopRefreshTimer ();
SetAllCurrentLinksToVisited ()
GetVisitedLinkCount ()
*/
function GM_LinkTrack (selectorStr, startBtnSel, clearBtnSel, refreshDelay)
{
var visitedLinkArry = [];
var numVisitedLinks = 0;
var refreshTimer = null;
var startTxt = 'Start checking for new links.';
var stopTxt = 'Stop checking links and reloading.';
//--- Get visited link-list from storage.
for (var J = localStorage.length - 1; J >= 0; --J) {
var itemName = localStorage.key (J);
if (/^Visited_\d+$/i.test (itemName) ) {
visitedLinkArry.push (localStorage[itemName] );
numVisitedLinks++;
}
}
function LinkIsNew (href) {
/*--- If the link is new, adds it to the list and returns true.
Otherwise returns false.
*/
if (visitedLinkArry.indexOf (href) == -1) {
visitedLinkArry.push (href);
var itemName = 'Visited_' + numVisitedLinks;
localStorage.setItem (itemName, href);
numVisitedLinks++;
return true;
}
return false;
}
//--- For each new link, open it in a separate tab.
this.OpenAllNewLinks = function ()
{
$(selectorStr).each ( function () {
if (LinkIsNew (this.href) ) {
GM_openInTab (this.href);
}
} );
};
this.StartRefreshTimer = function () {
if (typeof refreshTimer != "number") {
refreshTimer = setTimeout ( function() {
window.location.reload ();
},
refreshDelay
);
}
};
this.StopRefreshTimer = function () {
if (typeof refreshTimer == "number") {
clearTimeout (refreshTimer);
refreshTimer = null;
}
};
this.SetAllCurrentLinksToVisited = function () {
$(selectorStr).each ( function () {
LinkIsNew (this.href);
} );
};
this.GetVisitedLinkCount = function () {
return numVisitedLinks;
};
var context = this; //-- This seems clearer than using `.bind(this)`.
this.StartStopBtnHandler = function (zEvent) {
if (inRefreshCycle) {
//--- "Stop" pressed. Stop searching for new links.
$(startBtnSel).text (startTxt);
context.StopRefreshTimer ();
localStorage.setItem ('inRefreshCycle', '0'); //Set false.
}
else {
//--- "Start" pressed. Start searching for new links.
$(startBtnSel).text (stopTxt);
localStorage.setItem ('inRefreshCycle', '1'); //Set true.
context.SetAllCurrentLinksToVisited ();
context.StartRefreshTimer ();
}
inRefreshCycle ^= true; //-- Toggle value.
};
this.ClearVisitedLinkList = function (zEvent) {
numVisitedLinks = 0;
for (var J = localStorage.length - 1; J >= 0; --J) {
var itemName = localStorage.key (J);
if (/^Visited_\d+$/i.test (itemName) ) {
localStorage.removeItem (itemName);
}
}
};
//--- Activate the buttons.
$(startBtnSel).click (this.StartStopBtnHandler);
$(clearBtnSel).click (this.ClearVisitedLinkList);
//--- Determine state. Are we running the refresh cycle now?
var inRefreshCycle = parseInt (localStorage.inRefreshCycle, 10) || 0;
if (inRefreshCycle) {
$(startBtnSel).text (stopTxt); //-- Change the btn lable to "Stop".
this.OpenAllNewLinks ();
this.StartRefreshTimer ();
}
}
//--- Style the control buttons.
GM_addStyle ( " \
.GM_ControlWrap { \
opacity: 0.8; /*Coordinate with hover func. */ \
background: pink; \
position: fixed; \
padding: 0.6ex; \
z-index: 666666; \
} \
.GM_ControlWrap button { \
padding: 0.2ex 0.5ex; \
border-radius: 1em; \
box-shadow: 3px 3px 3px gray; \
cursor: pointer; \
} \
.GM_ControlWrap button:hover { \
color: red; \
} \
#GM_StartStopBtn { \
top: 0; \
left: 0; \
} \
#GM_ClearVisitListBtn { \
bottom: 0; \
right: 0; \
} \
" );