Create favicon view
authorVlad Chernushevich <mailbox@happytodesign.com>
Mon, 24 Jun 2013 22:00:52 +0000 (00:00 +0200)
committerVlad Chernushevich <mailbox@happytodesign.com>
Mon, 24 Jun 2013 22:00:52 +0000 (00:00 +0200)
client/assets/src/index.html.tmpl
client/assets/src/views/application.js
client/assets/src/views/favicon.js [new file with mode: 0644]

index cd02cc13606ecc4ec2b559fe9118ef8af41140fe..87d2e2c0429803177e05a61df3875b66c78a8fbe 100644 (file)
                     'src/views/application.js',\r
                     'src/views/apptoolbar.js',\r
                     'src/views/controlbox.js',\r
+                    'src/views/favicon.js',\r
                     'src/views/mediamessage.js',\r
                     'src/views/member.js',\r
                     'src/views/memberlist.js',\r
index bc3e8c15794741cbd058fee1eef9948c26304f6d..f2c2cbddb19be9354de37e75d8cd9e88ac030582 100644 (file)
@@ -27,7 +27,7 @@ _kiwi.view.Application = Backbone.View.extend({
             }
         };
 
-        this.notificationFavicon();
+        this.favicon = new _kiwi.view.Favicon();
         this.initSound();
     },
 
diff --git a/client/assets/src/views/favicon.js b/client/assets/src/views/favicon.js
new file mode 100644 (file)
index 0000000..44077c2
--- /dev/null
@@ -0,0 +1,132 @@
+_kiwi.view.Favicon = Backbone.View.extend({
+       initialize: function () {
+               var that = this,
+                       $win = $(window);
+
+           this.hasFocus = true;
+           this.highlightCount = 0;
+
+           this.originalFavicon = $('link[rel~="icon"]')[0].href;
+
+           $win.on('focus', function () {
+               that.hasFocus = true;
+               that._resetHighlights();
+           });
+           $win.on('blur', function () {
+               that.hasFocus = false;
+           });
+       },
+
+       newHighlight: function () {
+               var that = this;
+           if (!this.hasFocus) {
+               this.highlightCount++;
+               this._drawFavicon(function(canvas) {
+                       var bubbleCanvas = that._drawBubble(that.highlightCount.toString(), canvas);
+                       that._refreshFavicon(bubbleCanvas.toDataURL());
+               });
+           }
+       },
+
+       _resetHighlights: function () {
+               var that = this;
+           this.highlightCount = 0;
+           this._drawFavicon(function(canvas) {
+               that._refreshFavicon(canvas.toDataURL());
+           });
+       },
+
+       _drawFavicon: function (callback) {
+           var that = this,
+               context = this._createCanvas().getContext('2d'),
+               faviconImage = new Image();
+
+           // Allow cross origin resource requests
+           faviconImage.crossOrigin = 'anonymous';
+           // Trigger the load event
+           faviconImage.src = this.originalFavicon;
+
+           faviconImage.onload = function() {
+               // Draw the favicon itself
+               context.drawImage(faviconImage, 0, 0, faviconImage.width, faviconImage.height);
+               callback(canvas);
+           };
+       },
+
+       _drawBubble: function (label, canvas) {
+           var letterSpacing = -1.5,
+               textWidth = 0, textHidth = 0,
+               context = test = canvas.getContext('2d'),
+               canvasWidth = canvas.width,
+               canvasHeight = canvas.height;
+
+           // A hacky solution for letter-spacing, but works well with small favicon text
+           CanvasRenderingContext2D.prototype.renderText = function (text, x, y, letterSpacing) {
+               if (!text || typeof text !== 'string' || text.length === 0) {
+                   return;
+               }
+               if (typeof letterSpacing === 'undefined') {
+                   letterSpacing = 0;
+               }
+               // letterSpacing of 0 means normal letter-spacing
+               var characters = String.prototype.split.call(text, ''),
+                   index = 0,
+                   current,
+                   currentPosition = x,
+                   align = 1;
+
+               if (this.textAlign === 'right') {
+                   characters = characters.reverse();
+                   align = -1;
+               } else if (this.textAlign === 'center') {
+                   var totalWidth = 0;
+                   for (var i = 0; i < characters.length; i++) {
+                       totalWidth += (this.measureText(characters[i]).width + letterSpacing);
+                   }
+                   currentPosition = x - (totalWidth / 2);
+               }
+
+               while (index < text.length) {
+                   current = characters[index++];
+                   this.fillText(current, currentPosition, y);
+                   currentPosition += (align * (this.measureText(current).width + letterSpacing));
+               }
+           }
+
+           // Setup a test canvas to get text width
+           test.font = context.font = 'bold 10px Arial';
+           test.textAlign = 'right';
+           test.renderText(label, 0, 0, letterSpacing);
+
+           // Calculate text width based on letter spacing and padding
+           textWidth = test.measureText(label).width + letterSpacing * (label.length - 1) + 2;
+           textHeight = 9;
+
+           // Set bubble parameters
+           bubbleX = canvasWidth - textWidth;
+           bubbleY = canvasHeight - textHeight;
+
+           // Draw bubble background
+           context.fillStyle = 'red';
+           context.fillRect(bubbleX, bubbleY, textWidth, textHeight);
+
+           // Draw the text
+           context.fillStyle = 'white';
+           context.renderText(label, canvasWidth - 1, canvasHeight - 1, letterSpacing);
+
+           return canvas;
+       },
+
+       _refreshFavicon: function (url) {
+           $('link[rel~="icon"]').remove();
+           $('<link rel="shortcut icon" href="' + url + '">').appendTo($('head'));
+       },
+
+       _createCanvas: function () {
+           canvas = document.createElement('canvas');
+           canvas.width = 16;
+           canvas.height = 16;
+
+           return canvas;
+       }
+});
\ No newline at end of file