Skip to content

Instantly share code, notes, and snippets.

@haukex
Last active June 9, 2020 09:03
Show Gist options
  • Save haukex/33da4e0d4f3c7a1e2be8d1cffe75dc76 to your computer and use it in GitHub Desktop.
Save haukex/33da4e0d4f3c7a1e2be8d1cffe75dc76 to your computer and use it in GitHub Desktop.
PerlMonks Browser Notifications for New Nodes
"use strict";
// Documented at: https://www.perlmonks.org/?node_id=11116369
$(function () {
var CB_FETCHTIME_MS = 15 * 1000;
var GERNERAL_REFRESHTIME_MS = 60 * 1000;
// AJAX CB Refresh
var refresh = function () {
$.ajax({ url: '/', dataType: 'html',
// testing shows the table rendered here is the same as in the nodelet
data: { node: 'showchatmessages', displaytype: 'raw', ticker: 'yes' } })
.done(function (data) {
var source = $('<div/>').html(data).find('table.cb_table, .cb_quiet');
$('#Chatterbox table.cb_table, #Chatterbox .cb_quiet').replaceWith(source);
$('#Chatterbox table.cb_table + br, #Chatterbox .cb_quiet + br').remove();
$('#Chatterbox .cb_quiet').append('<br/>');
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.warn("AJAX error: " + textStatus + " / " + jqXHR.status + " " + errorThrown);
});
};
// Refresh "Other Users" (followed by CB refresh!)
var refresh_all = function () {
$.ajax({ url: '/', dataType: 'html',
// testing shows the body rendered here is the same as in the nodelet
data: { node: 'showotherusers', displaytype: 'raw', ticker: 'yes' } })
.done(function (data) {
// sadly, the <body> tag is not preserved, so we need to do some funky parsing here
var inSection = false;
var source = $.grep( $('<div/>').html(data).contents().toArray(), function (obj) {
if (inSection) {
if ( $(obj).is('.update-time') ) inSection = false;
return true;
}
else if ( $(obj).is('.other-users-text') )
{ inSection = true; return true; }
return false;
});
$('#Other_Users .nodelet_body').empty();
$('#Other_Users .nodelet_body').append(source);
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.warn("AJAX error: " + textStatus + " / " + jqXHR.status + " " + errorThrown);
})
.always(refresh);
};
// AJAX Message Fetching
var notify_cb = $('<input/>', { type: 'checkbox' });
var ajax_cb = $('<input/>', { type: 'checkbox', checked: !window["AJAXCB_DEFAULTOFF"] });
var fetch_timer;
var fetchit;
var start_fetch = function () {
if ( ajax_cb[0].checked )
fetch_timer = setTimeout(fetchit, CB_FETCHTIME_MS);
};
var lastid;
fetchit = function () {
if (fetch_timer) clearTimeout(fetch_timer);
fetch_timer = null;
if ( !ajax_cb[0].checked ) return;
var query = { node_id: '207304', xmlstyle: 'modern', ticker: 'yes' };
if ( lastid ) query['fromid'] = lastid;
$.ajax({ url: '/', dataType: 'xml', data: query })
.done(function (data) {
var count = parseInt($("info", data).attr("count"));
if ( count>0 ) {
refresh();
if ( notify_cb[0].checked ) {
var authors = {};
$('message author', data).each(function () { authors[ $(this).text() ] = 1; });
authors = Object.keys(authors).sort().join(", ");
var notification = new Notification('New PerlMonks Chatter',
{ body: count+" new messages by "+authors,
tag: "PerlMonksChatter", icon: "/favicon.ico", badge: "/favicon.ico" });
}
}
var li = $("info", data).attr("lastid");
if ( li ) lastid = li;
})
.fail(function (jqXHR, textStatus, errorThrown) {
console.warn("AJAX error: " + textStatus + " / " + jqXHR.status + " " + errorThrown);
})
.always(start_fetch);
};
var all_refresh_timer;
if ( !window["AJAXCB_DEFAULTOFF"] ) {
start_fetch();
all_refresh_timer = setInterval(refresh_all, GERNERAL_REFRESHTIME_MS);
}
// AJAX Form Submission
var form = $('#Chatterbox form');
form.on('submit', function (evt) {
evt.preventDefault();
// use the frame from the FullPage Chat as it renders faster
var thedata = { op: 'message', node_id: '3193',
displaytype: 'raw', message: $('#talkbox').val() };
$(":input",form).prop("disabled", true);
$.ajax({ url: form.attr("action"), method: 'post', data: thedata })
.done(function (data) {
$('#talkbox').val("");
// want to use fetchit() if possible here to update the lastid
if ( ajax_cb[0].checked ) fetchit(); else refresh();
})
.fail(function ( jqXHR, textStatus, errorThrown ) {
alert("CB submission error: "+textStatus+" / "+jqXHR.status+" "+errorThrown);
})
.always(function () {
$(":input",form).prop("disabled", false);
});
});
// Checkboxes
var cb_div = $('<div/>', { style: "font-size: 12px; display: inline-block;" });
cb_div.append( $('<label/>', { text: "AJAX Refresh" }).prepend(ajax_cb) );
form.after($("<br/>"), cb_div);
ajax_cb.change(function () {
if ( this.checked ) {
start_fetch();
all_refresh_timer = setInterval(refresh_all, GERNERAL_REFRESHTIME_MS);
refresh_all();
}
else {
if (fetch_timer) clearTimeout(fetch_timer);
fetch_timer = null;
if (all_refresh_timer) clearInterval(all_refresh_timer);
all_refresh_timer = null;
}
});
if ( "Notification" in window ) {
cb_div.append( $('<label/>', { text: "Notifications" }).prepend(notify_cb) );
notify_cb.change(function () {
if ( !this.checked ) return;
if ( Notification.permission == "default" ) {
notify_cb.attr("disabled", true);
Notification.requestPermission(function (result) {
notify_cb.removeAttr("disabled");
if ( result != "granted" ) notify_cb[0].checked = false;
});
}
else if ( Notification.permission != "granted" ) {
alert("You've denied this page the ability to send notifications, please change this via your browser's settings.");
this.checked = false;
}
});
}
});
"use strict";
// Documented at: https://www.perlmonks.org/?node_id=11116375
$(function () {
$("<style type='text/css'> .CodeMirror { border: 1px solid lightgrey; height: auto; resize: both; } </style>")
.appendTo("body");
var opts = {
lineNumbers: true, indentWithTabs: true, tabSize: 4, indentUnit: 4,
viewportMargin: Infinity, lineWrapping: true,
mode: {
name: "htmlmixed", // text/html
tags: {
style: [ ["type", /^text\/(x-)?scss$/, "text/x-scss"],
[null, null, "css"] ],
script: [[null, null, "text/javascript"]],
c: [[null, null, "text/x-perl"]]
}
}
};
if ( window["CM_THEME"] ) opts.theme = window.CM_THEME;
var opts_codeblock = JSON.parse(JSON.stringify(opts)); // deep copy
opts_codeblock['readOnly'] = true;
opts_codeblock['mode'] = 'text/x-perl';
$('textarea').each(function () {
var myCodeMirror = CodeMirror.fromTextArea(this, opts);
});
$('.codeblock:has(.codetext)').each(function () {
var div = this;
var text = $(div).text().trimEnd();
var myCodeMirror = CodeMirror( function(elt) {
div.parentNode.replaceChild(elt, div);
}, opts_codeblock);
myCodeMirror.setValue(text);
});
});
"use strict";
// Documented at: https://www.perlmonks.org/?node_id=11116359
$(function () {
if ( !("Notification" in window) ) {
console.warn("You've enabled the notifications plugin, but this 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_HIDECB"] ) )
$('#nodelet_container').before(
$('<div/>', { style: "font-size: 12px;" }).append(
$('<label/>', { text: "New Node Notifications" }).prepend(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 PerlMonks 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_seconds")) * 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 notifications, 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");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment