之前介紹過Feedly Duplicate Remover以及後來的Chrome Extension - Reader Filter。
前者已經失效而且沒有更新,後者有效但只限Chrome,而且hidden後的feeds,會保留空白,很愚蠢的設計。
持續多個月,實在忍無可忍,還是又要自己出手寫個小品程式去一己私慾。
這個Userscript很簡單,以標題對比方法找出重複的,你可以選擇以Hide方式還是Highlight方式去標示。
打開Config方法是在Greasemonkey的圖示下會找到按鈕。
我測試過Chrome+Tampermonkey都可以完美運作的。
大家可以由此下載Feedly Duplicate Filter 2014
https://dl.dropboxusercontent.com/u/19160547/Files/Feedly_Duplicate_Filter.user.js



Source Code:
// ==UserScript==
// @name Feedly Duplicate Filter 2014
// @version 1.0.4
// @description Remove the Feedly duplicate entry. For more detail please visit http://tatmingstudio.blogspot.com/2014/01/Feedly-Duplicate-Filter-2014.html
// @require https://raw.github.com/sizzlemctwizzle/GM_config/master/gm_config.js
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_log
// @grant GM_registerMenuCommand
// @icon https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUXiOFwqPSFXDJ6xU1SE4hHUwfwA4-s3FnIfRGTxKKKIBygT-m238M11Ze5-2bvehSMaxqtwleaEBAEEp1u4RzN7C9AC2MoQ5vuyRal_eYHVE5asjvgC2gZoROeUtC-3iDIcpb3kVuuFSw/s800/feedly-icon.png
// @include http*://*feedly.com/*
// @namespace http://tatmingstudio.blogspot.com/2014/01/Feedly-Duplicate-Filter-2014.html
// @run-at document-end
// @downloadURL https://dl.dropboxusercontent.com/u/19160547/Files/Feedly_Duplicate_Filter.user.js
// @updateURL https://dl.dropboxusercontent.com/u/19160547/Files/Feedly_Duplicate_Filter.user.js
// ==/UserScript==
/*
Version History:
2012-01-29 v1.0.4
Fix Bug: The snuggled duplicate items not filtering..
2012-01-29 v1.0.3
Improve performace.
Fix regex match accidentally.
Add Threshold setting, the number of items to compare, reduce the number will improve memory usage but also reduce accuracy.
Add GM_config save() event.
2012-01-23 v1.0.2
Add regex support with default value: match all title only contain domain name.
2014-01-20 v1.0.1
Fixed memory leak because uncomment console.log() accidentally.
2014-01-13 v1.0
Initial release.
*/
// Add config style
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
}
addGlobalStyle('#GM_config_Feedly_Duplicate_Filter { width: 450px ! important; height: 330px ! important; }');
GM_config.init(
{
'id': 'GM_config_Feedly_Duplicate_Filter', // The id used for this instance of GM_config
'title': 'Feedly Duplicate Filter Settings', // Panel Title
'fields': // Fields object
{
'FilterMode':
{
'label': 'Filter Mode :', // Appears next to field
'type': 'radio', // Makes this setting a series of radio elements
'options': ['Hide', 'Highlight'], // Possible choices
'default': 'Hide' // Default value if user doesn't change it
},
'Threshold':
{
'label': 'Threshold :', // Appears next to field
'type': 'text', // Makes this setting a series of radio elements
'title': 'Number of items to compare, reduce the number will improve memory usage but also reduce accuracy.', // Add a tooltip (hover over text)
'size': 5, // Limit length of input (default is 25)
'default': '200' // Default value if user doesn't change it
},
'HighlightBackgroundColor':
{
'label': 'Highlight Background Color :', // Appears next to field
'type': 'text', // Makes this setting a text input
'title': 'Color HEX format. (e.g. #3366AA)', // Add a tooltip (hover over text)
'size': 8, // Limit length of input (default is 25)
'default': '#EBCBCB' // Default value if user doesn't change it
},
'HighlightFontColor':
{
'label': 'Highlight Font Color :', // Appears next to field
'type': 'text', // Makes this setting a text input
'title': 'Color HEX format. (e.g. #3366AA)', // Add a tooltip (hover over text)
'size': 8, // Limit length of input (default is 25)
'default': '#797979' // Default value if user doesn't change it
},
'Regex':
{
'label': 'Match by Regular expressions :', // Appears next to field
'type': 'textarea', // Makes this setting a text input
'title': 'Please be careful to use this field, if you don\'t sure, just leave it blank.', // Add a tooltip (hover over text)
'default': '' // Please be careful to use this.
}
},
'events':
{
'open': function (doc) {
var config = this;
doc.getElementById(config.id + '_field_Regex').cols = 65;
doc.getElementById(config.id + '_field_Regex').rows = 5;
doc.getElementById(config.id + '_field_Regex').style = "font-size:12px;";
},
'save': function(values) {
GM_config.close();
}
}
});
GM_registerMenuCommand( "Open Config", function(){
GM_config.open();
});
var box = document.getElementById("box");
box.addEventListener("DOMNodeInserted", function(){
var filtermode = GM_config.get('FilterMode').toUpperCase();
var threshold = GM_config.get('Threshold');
var bgcolor = GM_config.get('HighlightBackgroundColor');
var fontcolor = GM_config.get('HighlightFontColor');
var regex = GM_config.get('Regex');
var a=document.getElementsByClassName("u0Entry");
var uEntry=a.length>0?a:null;
var arr = new Array();
var idx = new Array();
var endto = (uEntry.length >= threshold ? (uEntry.length - threshold) : 0);
for(var y=uEntry.length-1; y>=endto; y--) {
//Comment for v1.0.4 fix.
/*if (uEntry[y].style.display == 'none' || uEntry[y].style.backgroundColor == bgcolor) {
arr.push("[Filtered]");
idx.push("");
}
else {*/
arr.push(uEntry[y].attributes["data-title"].value);/*data-alternate-link*/
idx.push(y);
//}
}
var i = arr.length, j, val;
while (i--) {
val = arr[i];
j = i;
while (j--) {
if (arr[j] === val || (regex != '' && regexMatch(val, regex)) ) {
//console.log("[Duplicate found] " + "Reference : " + val + " | " + "Value : " + arr[j]);
if (filtermode == 'HIDE')
uEntry[idx[i]].setAttribute("style","display:none"); /*To hide the duplicate.*/
else if (filtermode == 'HIGHLIGHT') {
/* Or you may want to highlight the duplicate instead of hide. */
uEntry[idx[i]].setAttribute("style","background-color: " + bgcolor);
uEntry[idx[i]].getElementsByTagName("div")[4].getElementsByTagName("a")[0].setAttribute("style","color: " + fontcolor);
}
}
}
}
}, false);
function replaceAll(find, replace, str) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
function regexMatch(str, regex)
{
if (regex == '')
return false;
try{
return (str.match(regex) != null);
} catch (ex)
{
return false;
}
}
how can i use this on cards view mode?
回覆刪除It support the title view (like Google Reader) only. Due to i suppose this temporary solution and feedly should do it soon...
刪除火狐31、油猴子2.1。
回覆刪除腳本好像對臉書粉絲團無效,對新聞網站有效。