The Google gadget is back and running
It seems Google has finally gotten around to fixing its Blogs I Follow gadget! The original issue was that it had completely stopped updating. You can read my previous post to see the workaround I used while waiting for the folks at Google to address the problem.
Below is the code I used to bring back the official Blogs I Follow gadget while hiding the temporary HTML/JavaScript fix.
To keep things organized, I saved both code snippets in OpenOffice. That way, if Google's gadget ever breaks again, it’s a quick copy and paste to deploy the temporary fix, and another simple copy and paste to switch back once it's resolved.
Note: The only change you will need to make is replacing my followed blog URLs with your own. I detailed step-by-step instructions on how to do this in the post linked above. Also you do this at your own risk.
HTML
<div style="display: none;">
<div id="blogger-bloglist-feed">
<p style="font-size: 0.9em; color: #ffffff; margin: 0;">Loading blog updates...</p>
</div>
<style>
.bloglist-item {
margin-bottom: 14px !important;
padding-bottom: 10px !important;
border-bottom: 1px dashed rgba(255, 255, 255, 0.3) !important;
font-family: inherit !important;
}
/* Blog Name */
.bloglist-name {
display: block !important;
font-size: 1.05em !important;
font-weight: bold !important;
color: #ffffff !important;
margin-bottom: 4px !important;
line-height: 1.3 !important;
}
/* Article Post Title Link */
a.bloglist-link,
a.bloglist-link:visited {
display: block !important;
font-size: 1.0em !important;
font-weight: normal !important;
color: #ffffff !important;
text-decoration: none !important;
line-height: 1.3 !important;
}
a.bloglist-link:hover {
text-decoration: underline !important;
}
/* Updated Date */
.bloglist-date {
font-size: 0.85em !important;
color: #ffffff !important;
margin-top: 3px !important;
display: block !important;
opacity: 0.9 !important;
}
</style>
<script>
(function() {
var followedFeeds = [
"http://ae5x.blogspot.com/feeds/posts/default",
"https://www.kb6nu.com/feed/",
"http://w2lj.blogspot.com/feeds/posts/default",
"http://pa1b-qrp.blogspot.com/feeds/posts/default",
"https://ve7sar.blogspot.com/feeds/posts/default",
"https://swling.com/blog/feed/",
"https://www.arrl.org/arrl.rss",
"http://ve3clq.blogspot.com/feeds/posts/default",
"https://wb3gck.com/feed/",
"https://tommcquiggan.blogspot.com/feeds/posts/default",
"http://ve3vn.blogspot.com/feeds/posts/default",
"https://ke9v.net/feed.xml",
"https://kg3v.com/feed/",
"http://offgridham.com/feed/",
"http://pe4bas.blogspot.com/feeds/posts/default",
"https://qrper.com/feed/",
"https://www.amateurradio.com/feed/",
"https://k9zw.wordpress.com/feed/"
];
var container = document.getElementById("blogger-bloglist-feed");
var loadedCount = 0;
var items = [];
// Helper function to fetch feeds that rss2json fails to parse
async function fetchXmlFallback(feedUrl) {
try {
var proxyUrl = "https://api.allorigins.win/get?url=" + encodeURIComponent(feedUrl);
var res = await fetch(proxyUrl);
var data = await res.json();
if (!data.contents) return null;
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(data.contents, "text/xml");
var item = xmlDoc.querySelector("item") || xmlDoc.querySelector("entry");
if (!item) return null;
var title = item.querySelector("title") ? item.querySelector("title").textContent : "Untitled";
var link = item.querySelector("link") ? item.querySelector("link").textContent : "#";
if (!link || link.trim() === "") {
link = item.querySelector("link") ? item.querySelector("link").getAttribute("href") : "#";
}
var dateStr = item.querySelector("pubDate") ? item.querySelector("pubDate").textContent :
(item.querySelector("published") ? item.querySelector("published").textContent :
(item.querySelector("updated") ? item.querySelector("updated").textContent : ""));
var blogTitle = (xmlDoc.querySelector("channel > title") ? xmlDoc.querySelector("channel > title").textContent :
(xmlDoc.querySelector("feed > title") ? xmlDoc.querySelector("feed > title").textContent : "Blog"));
var pubDateObj = new Date(dateStr);
return {
blogTitle: blogTitle,
title: title,
link: link,
date: pubDateObj,
dateStr: isNaN(pubDateObj) ? "" : pubDateObj.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
};
} catch (e) {
return null;
}
}
followedFeeds.forEach(function(feedUrl) {
var apiUrl = "https://api.rss2json.com/v1/api.json?rss_url=" + encodeURIComponent(feedUrl);
fetch(apiUrl)
.then(function(res) { return res.json(); })
.then(async function(data) {
if (data.status === "ok" && data.items && data.items.length > 0) {
var blogTitle = data.feed.title || "Blog";
var latestPost = data.items[0];
var pubDateObj = new Date(latestPost.pubDate);
items.push({
blogTitle: blogTitle,
title: latestPost.title,
link: latestPost.link,
date: pubDateObj,
dateStr: isNaN(pubDateObj) ? "" : pubDateObj.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
});
} else {
var fallbackItem = await fetchXmlFallback(feedUrl);
if (fallbackItem) items.push(fallbackItem);
}
})
.catch(async function(err) {
var fallbackItem = await fetchXmlFallback(feedUrl);
if (fallbackItem) items.push(fallbackItem);
})
.finally(function() {
loadedCount++;
if (loadedCount === followedFeeds.length) {
if (items.length > 0) {
items.sort(function(a, b) { return b.date - a.date; });
var htmlBuffer = "";
items.forEach(function(item) {
htmlBuffer += '<div class="bloglist-item">';
htmlBuffer += '<span class="bloglist-name">' + item.blogTitle + '</span>';
htmlBuffer += '<a class="bloglist-link" href="' + item.link + '" target="_blank" rel="noopener">' + item.title + '</a>';
if (item.dateStr) {
htmlBuffer += '<span class="bloglist-date">Updated: ' + item.dateStr + '</span>';
}
htmlBuffer += '</div>';
});
container.innerHTML = htmlBuffer;
} else {
container.innerHTML = "<p style='font-size:0.85em; color: #ffffff;'>No recent updates available.</p>";
}
}
});
});
})();
</script>
</div>
The Google gadget is back and running
It seems Google has finally gotten around to fixing its Blogs I Follow gadget! The original issue was that it had completely stopped updating. You can read my previous post to see the workaround I used while waiting for the folks at Google to address the problem.
Below is the code I used to bring back the official Blogs I Follow gadget while hiding the temporary HTML/JavaScript fix.
To keep things organized, I saved both code snippets in OpenOffice. That way, if Google's gadget ever breaks again, it’s a quick copy and paste to deploy the temporary fix, and another simple copy and paste to switch back once it's resolved.
Note: The only change you will need to make is replacing my followed blog URLs with your own. I detailed step-by-step instructions on how to do this in the post linked above. Also you do this at your own risk.
HTML
<div style="display: none;">
<div id="blogger-bloglist-feed">
<p style="font-size: 0.9em; color: #ffffff; margin: 0;">Loading blog updates...</p>
</div>
<style>
.bloglist-item {
margin-bottom: 14px !important;
padding-bottom: 10px !important;
border-bottom: 1px dashed rgba(255, 255, 255, 0.3) !important;
font-family: inherit !important;
}
/* Blog Name */
.bloglist-name {
display: block !important;
font-size: 1.05em !important;
font-weight: bold !important;
color: #ffffff !important;
margin-bottom: 4px !important;
line-height: 1.3 !important;
}
/* Article Post Title Link */
a.bloglist-link,
a.bloglist-link:visited {
display: block !important;
font-size: 1.0em !important;
font-weight: normal !important;
color: #ffffff !important;
text-decoration: none !important;
line-height: 1.3 !important;
}
a.bloglist-link:hover {
text-decoration: underline !important;
}
/* Updated Date */
.bloglist-date {
font-size: 0.85em !important;
color: #ffffff !important;
margin-top: 3px !important;
display: block !important;
opacity: 0.9 !important;
}
</style>
<script>
(function() {
var followedFeeds = [
"http://ae5x.blogspot.com/feeds/posts/default",
"https://www.kb6nu.com/feed/",
"http://w2lj.blogspot.com/feeds/posts/default",
"http://pa1b-qrp.blogspot.com/feeds/posts/default",
"https://ve7sar.blogspot.com/feeds/posts/default",
"https://swling.com/blog/feed/",
"https://www.arrl.org/arrl.rss",
"http://ve3clq.blogspot.com/feeds/posts/default",
"https://wb3gck.com/feed/",
"https://tommcquiggan.blogspot.com/feeds/posts/default",
"http://ve3vn.blogspot.com/feeds/posts/default",
"https://ke9v.net/feed.xml",
"https://kg3v.com/feed/",
"http://offgridham.com/feed/",
"http://pe4bas.blogspot.com/feeds/posts/default",
"https://qrper.com/feed/",
"https://www.amateurradio.com/feed/",
"https://k9zw.wordpress.com/feed/"
];
var container = document.getElementById("blogger-bloglist-feed");
var loadedCount = 0;
var items = [];
// Helper function to fetch feeds that rss2json fails to parse
async function fetchXmlFallback(feedUrl) {
try {
var proxyUrl = "https://api.allorigins.win/get?url=" + encodeURIComponent(feedUrl);
var res = await fetch(proxyUrl);
var data = await res.json();
if (!data.contents) return null;
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(data.contents, "text/xml");
var item = xmlDoc.querySelector("item") || xmlDoc.querySelector("entry");
if (!item) return null;
var title = item.querySelector("title") ? item.querySelector("title").textContent : "Untitled";
var link = item.querySelector("link") ? item.querySelector("link").textContent : "#";
if (!link || link.trim() === "") {
link = item.querySelector("link") ? item.querySelector("link").getAttribute("href") : "#";
}
var dateStr = item.querySelector("pubDate") ? item.querySelector("pubDate").textContent :
(item.querySelector("published") ? item.querySelector("published").textContent :
(item.querySelector("updated") ? item.querySelector("updated").textContent : ""));
var blogTitle = (xmlDoc.querySelector("channel > title") ? xmlDoc.querySelector("channel > title").textContent :
(xmlDoc.querySelector("feed > title") ? xmlDoc.querySelector("feed > title").textContent : "Blog"));
var pubDateObj = new Date(dateStr);
return {
blogTitle: blogTitle,
title: title,
link: link,
date: pubDateObj,
dateStr: isNaN(pubDateObj) ? "" : pubDateObj.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
};
} catch (e) {
return null;
}
}
followedFeeds.forEach(function(feedUrl) {
var apiUrl = "https://api.rss2json.com/v1/api.json?rss_url=" + encodeURIComponent(feedUrl);
fetch(apiUrl)
.then(function(res) { return res.json(); })
.then(async function(data) {
if (data.status === "ok" && data.items && data.items.length > 0) {
var blogTitle = data.feed.title || "Blog";
var latestPost = data.items[0];
var pubDateObj = new Date(latestPost.pubDate);
items.push({
blogTitle: blogTitle,
title: latestPost.title,
link: latestPost.link,
date: pubDateObj,
dateStr: isNaN(pubDateObj) ? "" : pubDateObj.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
});
} else {
var fallbackItem = await fetchXmlFallback(feedUrl);
if (fallbackItem) items.push(fallbackItem);
}
})
.catch(async function(err) {
var fallbackItem = await fetchXmlFallback(feedUrl);
if (fallbackItem) items.push(fallbackItem);
})
.finally(function() {
loadedCount++;
if (loadedCount === followedFeeds.length) {
if (items.length > 0) {
items.sort(function(a, b) { return b.date - a.date; });
var htmlBuffer = "";
items.forEach(function(item) {
htmlBuffer += '<div class="bloglist-item">';
htmlBuffer += '<span class="bloglist-name">' + item.blogTitle + '</span>';
htmlBuffer += '<a class="bloglist-link" href="' + item.link + '" target="_blank" rel="noopener">' + item.title + '</a>';
if (item.dateStr) {
htmlBuffer += '<span class="bloglist-date">Updated: ' + item.dateStr + '</span>';
}
htmlBuffer += '</div>';
});
container.innerHTML = htmlBuffer;
} else {
container.innerHTML = "<p style='font-size:0.85em; color: #ffffff;'>No recent updates available.</p>";
}
}
});
});
})();
</script>
</div>














