mirror of https://github.com/zulip/zulip.git
Change the favicon on notification (great for pinned tabs)
(imported from commit 025ad165d15b2e6d979c246776148f13ebc555fb)
This commit is contained in:
parent
c38092424e
commit
d0f422979b
|
@ -44,6 +44,7 @@
|
|||
<script type="text/javascript" src="/static/third/jquery.idle/jquery.idle.js"></script>
|
||||
<script type="text/javascript" src="/static/third/jquery-autosize/jquery.autosize.js"></script>
|
||||
<script type="text/javascript" src="/static/third/spectrum/spectrum.js"></script>
|
||||
<script type="text/javascript" src="/static/third/notificon/notificon.js"></script>
|
||||
{% compressed_js 'app' %}
|
||||
|
||||
{% if debug %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Global variables, categorized by place of definition.
|
||||
var globals =
|
||||
// Third-party libraries
|
||||
' $ jQuery Spinner Handlebars XDate'
|
||||
' $ jQuery Spinner Handlebars XDate Notificon'
|
||||
|
||||
// index.html
|
||||
+ ' initial_pointer email stream_list people_list have_initial_messages'
|
||||
|
@ -87,6 +87,8 @@ var jslint_options = {
|
|||
plusplus: true, // Allow increment/decrement operators
|
||||
regexp: true, // Allow . and [^...] in regular expressions
|
||||
todo: true, // Allow "TODO" comments.
|
||||
newcap: true, // Don't assume that capitalized functions are
|
||||
// constructors (and the converse)
|
||||
|
||||
predef: globals.split(/\s+/)
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@ exports.initialize = function () {
|
|||
window_has_focus = true;
|
||||
new_message_count = 0;
|
||||
document.title = domain + " - Humbug";
|
||||
Notificon("");
|
||||
|
||||
$.each(notice_memory, function (index, notice_mem_entry) {
|
||||
notice_mem_entry.obj.cancel();
|
||||
|
@ -36,6 +37,7 @@ exports.initialize = function () {
|
|||
}).mouseover(function () {
|
||||
new_message_count = 0;
|
||||
document.title = domain + " - Humbug";
|
||||
Notificon("");
|
||||
});
|
||||
|
||||
if (!window.webkitNotifications) {
|
||||
|
@ -183,6 +185,7 @@ exports.received_messages = function (messages) {
|
|||
|
||||
if (title_needs_update) {
|
||||
document.title = "(" + new_message_count + ") " + domain + " - Humbug";
|
||||
Notificon(new_message_count);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
Notificon :: Client-side Favicon Notifications - Usage: Notificon(label='',favicon_url={default_favicon})
|
||||
=========================================================================================================
|
||||
|
||||
Copyright (c) 2011 Matt Williams <matt@makeable.co.uk>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY MATT WILLIAMS ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATT WILLIAMS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those of the
|
||||
authors and should not be interpreted as representing official policies, either expressed
|
||||
or implied, of Matt Williams.
|
||||
|
||||
*/
|
||||
|
||||
(function(){
|
||||
|
||||
var unsupported = false;
|
||||
|
||||
var checkSupport = function checkSupport() {
|
||||
if (unsupported) {
|
||||
return false;
|
||||
}
|
||||
if (!document.createElement('canvas').getContext) {
|
||||
unsupported = true;
|
||||
if (console) {
|
||||
console.log('Notificon: requires canvas support');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var mergeDefaultOptions = function mergeDefaultOptions(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
var defaults = {
|
||||
font: "10px monospace",
|
||||
color: "#000000",
|
||||
stroke: "rgba(255,255,255,0.85)",
|
||||
align: 'right',
|
||||
valign: 'bottom',
|
||||
width: 4,
|
||||
favicon: getExistingFavicon()
|
||||
};
|
||||
for (var key in defaults) {
|
||||
if (!options[key]) {
|
||||
options[key] = defaults[key];
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
|
||||
var findFaviconTag = function findFaviconTag(notificon) {
|
||||
var link_tags = document.getElementsByTagName('link');
|
||||
for (var i=0; i < link_tags.length; i++) {
|
||||
if (notificon && (/\bnotificon\b/i).test(link_tags[i].getAttribute('rel'))) {
|
||||
return link_tags[i];
|
||||
} else if (!notificon && (/\bicon\b/i).test(link_tags[i].getAttribute('rel'))) {
|
||||
return link_tags[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var getExistingFavicon = function getExistingFavicon() {
|
||||
var favicon = findFaviconTag();
|
||||
return favicon ? favicon.getAttribute('href') : '/favicon.ico';
|
||||
};
|
||||
|
||||
var removeNotificon = function removeNotificon() {
|
||||
var notificon = findFaviconTag(true);
|
||||
if (notificon) {
|
||||
notificon.parentNode.removeChild(notificon);
|
||||
removeNotificon();
|
||||
}
|
||||
};
|
||||
|
||||
var changeFavicon = function changeFavicon(uri) {
|
||||
var link = document.createElement('link');
|
||||
link.type = 'image/x-icon';
|
||||
link.rel = 'icon notificon';
|
||||
link.href = uri;
|
||||
removeNotificon();
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
};
|
||||
|
||||
var getCoords = function getCoords(options) {
|
||||
return {
|
||||
x: options.align.toLowerCase() === 'left' ? 0 : 16,
|
||||
y: options.valign.toLowerCase() === 'top' ? 0 : 18
|
||||
};
|
||||
};
|
||||
|
||||
var drawLabel = function drawLabel(canvas, label, options) {
|
||||
var context = canvas.getContext("2d");
|
||||
var coords = getCoords(options);
|
||||
context.font = options.font;
|
||||
context.fillStyle = options.color;
|
||||
context.textAlign = options.align;
|
||||
context.textBaseline = options.valign;
|
||||
context.strokeStyle = options.stroke;
|
||||
context.lineWidth = options.width;
|
||||
context.strokeText(label, coords.x, coords.y);
|
||||
context.fillText(label, coords.x, coords.y);
|
||||
};
|
||||
|
||||
var imgToCanvas = function imgToCanvas(img) {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
var context = canvas.getContext("2d");
|
||||
context.drawImage(img, 0, 0);
|
||||
return canvas;
|
||||
};
|
||||
|
||||
var createNotificon = function createNotificon(label,myOptions) {
|
||||
if (!checkSupport()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var options = mergeDefaultOptions(myOptions);
|
||||
|
||||
label = "" + label;
|
||||
if (!label.length) {
|
||||
return changeFavicon(options.favicon);
|
||||
}
|
||||
|
||||
var img = document.createElement("img");
|
||||
img.src = options.favicon;
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function() {
|
||||
var canvas = imgToCanvas(img);
|
||||
if (label) {
|
||||
drawLabel(canvas, label, options);
|
||||
}
|
||||
try {
|
||||
return changeFavicon(canvas.toDataURL("image/png"));
|
||||
} catch(e) {
|
||||
if (console) {
|
||||
console.log('Notificon: cannot use icons located on a different domain (' + favicon + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
img.onerror = function() {
|
||||
if (console) {
|
||||
console.log('Notificon: image not found (' + options.favicon + ')');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
var Notificon = function(label, options) {
|
||||
createNotificon(label, options);
|
||||
};
|
||||
|
||||
Notificon.reset = function reset() {
|
||||
removeNotificon();
|
||||
};
|
||||
|
||||
if (typeof exports !== 'undefined') {
|
||||
module.exports = Notificon;
|
||||
} else {
|
||||
this.Notificon = Notificon;
|
||||
}
|
||||
})(this);
|
|
@ -0,0 +1 @@
|
|||
(function(){var a=!1,b=function(){return a?!1:document.createElement("canvas").getContext?!0:(a=!0,console&&console.log("Notificon: requires canvas support"),!1)},c=function(a){a||(a={});var b={color:"#000000",stroke:"rgba(255,255,255,0.85)",favicon:e()};for(var c in b)a[c]||(a[c]=b[c]);return a},d=function(a){var b=document.getElementsByTagName("link");for(var c=0;c<b.length;c++){if(a&&/\bnotificon\b/i.test(b[c].getAttribute("rel")))return b[c];if(!a&&/\bicon\b/i.test(b[c].getAttribute("rel")))return b[c]}return!1},e=function(){var a=d();return a?a.getAttribute("href"):"/favicon.ico"},f=function p(){var a=d(!0);a&&(a.parentNode.removeChild(a),p())},g=function(a){var b=document.createElement("link");b.type="image/x-icon",b.rel="icon notificon",b.href=a,f(),document.getElementsByTagName("head")[0].appendChild(b)},h=function(a,b,c,d){var e=a.getContext("2d");e.font="10px monospace",e.fillStyle=c,e.textAlign="right",e.textBaseline="top",e.strokeStyle=d,e.lineWidth=4,e.strokeText(b,16,6),e.fillText(b,16,6)},i=function(a){var b=document.createElement("canvas");b.width=a.width,b.height=a.height;var c=b.getContext("2d");return c.drawImage(a,0,0),b},j=function(a,d){if(!b())return!1;var e=c(d);if(!a.length)return g(e.favicon);var f=document.createElement("img");return f.src=e.favicon,f.onload=function(){var b=i(f);a&&h(b,a,e.color,e.stroke);try{return g(b.toDataURL("image/png"))}catch(c){if(console)return console.log("Notificon: cannot use icons located on a different domain ("+favicon+")"),!1}},f.onerror=function(){if(console)return console.log("Notificon: image not found ("+e.favicon+")"),!1},!0},k=function(a,b){j(a,b)};typeof exports!="undefined"?module.exports=k:this.Notificon=k})(this);
|
Loading…
Reference in New Issue