(If you've already got jQuery loaded from another nodelet hack, you don't need to put that <script> tag twice, of course.)
The notifications are disabled by default because if you have multiple tabs open to PerlMonks, you'd get a notification per tab. If you want to have notifications turned on by default, you can add this before the above <script> tags: "<script> NOTIFICATIONS_ENABLE=true; </script>", and if you additionally want to hide the checkbox, add "NOTIFICATIONS_HIDECB=true;" inside those <script> tags.
I've created a Gist to version-control this code. I'll consider this particular node a "living document", as in I'm not going to add an "Updated" tag every time I make a change - if you want the version history, see the Gist.
"use strict";
$(function () {
if ( !("Notification" in window) ) {
console.warn("You've enabled the notifications plugin, but thi
+s browser doesn't seem to support them.");
return;
}
var DEFAULT_FETCHTIME_MS = 30 * 1000;
var cb = $('<input/>', { type: 'checkbox' });
if ( !( window["NOTIFICATIONS_ENABLE"] && window["NOTIFICATIONS_HI
+DECB"] ) )
$('#nodelet_container').before(
$('<div/>', { style: "font-size: 12px;" }).append(
$('<label/>', { text: "New Node Notifications" }).prep
+end(cb) ) );
var notifications_timer;
var start_notifications = function () {
var lastfetchtime = Math.round((new Date()).getTime() / 1000);
var fetchit = function () {
$.ajax({ url: "/", dataType: "xml",
data: { node_id: '30175', xmlstyle: 'flat',
sinceunixtime: lastfetchtime, ticker: 'yes' }
+})
.done(function (data) {
$("NODE", data).each(function () {
var node = $(this);
var type = node.attr("nodetype");
var author = node.attr("authortitle");
if ( type == "user" || author == "NodeReaper"
+) return;
var text = author + " posted a new " + type +
+": " + node.text(); // node.attr("createtime")
var uri = "/?" + $.param({ node_id: node.attr(
+"node_id") });
console.debug(text, uri);
var notification = new Notification('New PerlM
+onks Node', {
body: text, icon: "/favicon.ico", badge: "
+/favicon.ico",
requireInteraction: true });
notification.onclick = function (event) {
window.location = uri;
};
});
notifications_timer = setTimeout(fetchit,
parseInt($("INFO", data).attr("min_poll_second
+s")) * 1000 + 1000);
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.warn("AJAX error: " + textStatus + " / " +
+ jqXHR.status + " " + errorThrown);
notifications_timer = setTimeout(fetchit, DEFAULT_
+FETCHTIME_MS);
});
lastfetchtime = Math.round((new Date()).getTime() / 1000);
};
notifications_timer = setTimeout(fetchit, DEFAULT_FETCHTIME_MS
+);
console.debug("Notifications initialized. Timer",
notifications_timer, "will fire in", DEFAULT_FETCHTIME_MS,
+ "ms");
}
cb.change(function () {
if ( this.checked ) {
if ( Notification.permission == "default" ) {
cb.attr("disabled", true);
Notification.requestPermission(function (result) {
cb.removeAttr("disabled");
if ( result == "granted" ) start_notifications();
else cb[0].checked = false;
});
}
else if ( Notification.permission == "granted" )
start_notifications();
else {
alert("You've denied this page the ability to send not
+ifications, please change this via your browser's settings.");
this.checked = false;
}
}
else {
clearTimeout(notifications_timer);
console.debug("Notifications stopped.");
}
});
if ( window["NOTIFICATIONS_ENABLE"] )
cb.prop("checked", true).trigger("change");
});