Add favicon notifications on private messages
[KiwiIRC.git] / client / assets / src / views / favicon.js
CommitLineData
0b7949de 1_kiwi.view.Favicon = Backbone.View.extend({
bd85cbdb
VC
2 initialize: function () {
3 var that = this,
4 $win = $(window);
5
9e2e2fc5 6 this.has_canvas_support = !!window.CanvasRenderingContext2D;
bd85cbdb
VC
7 this.has_focus = true;
8 this.highlight_count = 0;
9
10 this.original_favicon = $('link[rel~="icon"]')[0].href;
11
12 $win.on('focus', function () {
13 that.has_focus = true;
14 that._resetHighlights();
15 });
16 $win.on('blur', function () {
17 that.has_focus = false;
18 });
19 },
20
21 newHighlight: function () {
22 var that = this;
23 if (!this.has_focus) {
24 this.highlight_count++;
9e2e2fc5
VC
25 if (this.has_canvas_support) {
26 this._drawFavicon(function(canvas) {
27 var bubbleCanvas = that._drawBubble(that.highlight_count.toString(), canvas);
28 that._refreshFavicon(bubbleCanvas.toDataURL());
29 });
30 }
bd85cbdb
VC
31 }
32 },
33
34 _resetHighlights: function () {
35 var that = this;
36 this.highlight_count = 0;
37 this._drawFavicon(function(canvas) {
38 that._refreshFavicon(canvas.toDataURL());
39 });
40 },
41
42 _drawFavicon: function (callback) {
43 var that = this,
44 context = this._createCanvas().getContext('2d'),
45 favicon_image = new Image();
46
47 // Allow cross origin resource requests
48 favicon_image.crossOrigin = 'anonymous';
49 // Trigger the load event
50 favicon_image.src = this.original_favicon;
51
52 favicon_image.onload = function() {
53 // Draw the favicon itself
54 context.drawImage(favicon_image, 0, 0, favicon_image.width, favicon_image.height);
55 callback(canvas);
56 };
57 },
58
59 _drawBubble: function (label, canvas) {
60 var letter_spacing = -1.5,
7c87efb2 61 bubble_width = 0, bubble_height = 0,
bd85cbdb
VC
62 context = test = canvas.getContext('2d'),
63 canvas_width = canvas.width,
64 canvas_height = canvas.height;
65
bd85cbdb
VC
66 // Setup a test canvas to get text width
67 test.font = context.font = 'bold 10px Arial';
68 test.textAlign = 'right';
9e2e2fc5 69 this._renderText(test, label, 0, 0, letter_spacing);
bd85cbdb 70
7c87efb2
VC
71 // Calculate bubble width based on letter spacing and padding
72 bubble_width = test.measureText(label).width + letter_spacing * (label.length - 1) + 2;
73 // Canvas does not have any way of measuring text height, so we just do it manually and add 1px top/bottom padding
74 bubble_height = 9;
bd85cbdb 75
7c87efb2
VC
76 // Set bubble coordinates
77 bubbleX = canvas_width - bubble_width;
78 bubbleY = canvas_height - bubble_height;
bd85cbdb
VC
79
80 // Draw bubble background
81 context.fillStyle = 'red';
7c87efb2 82 context.fillRect(bubbleX, bubbleY, bubble_width, bubble_height);
bd85cbdb
VC
83
84 // Draw the text
85 context.fillStyle = 'white';
9e2e2fc5 86 this._renderText(context, label, canvas_width - 1, canvas_height - 1, letter_spacing);
bd85cbdb
VC
87
88 return canvas;
89 },
90
91 _refreshFavicon: function (url) {
92 $('link[rel~="icon"]').remove();
93 $('<link rel="shortcut icon" href="' + url + '">').appendTo($('head'));
94 },
95
96 _createCanvas: function () {
97 canvas = document.createElement('canvas');
98 canvas.width = 16;
99 canvas.height = 16;
100
101 return canvas;
9e2e2fc5
VC
102 },
103
104 _renderText: function (context, text, x, y, letter_spacing) {
105 // A hacky solution for letter-spacing, but works well with small favicon text
106 // Modified from http://jsfiddle.net/davidhong/hKbJ4/
107 var current,
108 characters = text.split('').reverse(),
109 index = 0,
110 currentPosition = x;
111
112 while (index < text.length) {
113 current = characters[index++];
114 context.fillText(current, currentPosition, y);
115 currentPosition += (-1 * (context.measureText(current).width + letter_spacing));
116 }
117
118 return context;
bd85cbdb 119 }
0b7949de 120});