From: Vlad Chernushevich Date: Mon, 24 Jun 2013 22:00:52 +0000 (+0200) Subject: Create favicon view X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=0b7949deddfdda3aa56c28c6c19d533e25300475;p=KiwiIRC.git Create favicon view --- diff --git a/client/assets/src/index.html.tmpl b/client/assets/src/index.html.tmpl index cd02cc1..87d2e2c 100644 --- a/client/assets/src/index.html.tmpl +++ b/client/assets/src/index.html.tmpl @@ -356,6 +356,7 @@ 'src/views/application.js', 'src/views/apptoolbar.js', 'src/views/controlbox.js', + 'src/views/favicon.js', 'src/views/mediamessage.js', 'src/views/member.js', 'src/views/memberlist.js', diff --git a/client/assets/src/views/application.js b/client/assets/src/views/application.js index bc3e8c1..f2c2cbd 100644 --- a/client/assets/src/views/application.js +++ b/client/assets/src/views/application.js @@ -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 index 0000000..44077c2 --- /dev/null +++ b/client/assets/src/views/favicon.js @@ -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(); + $('').appendTo($('head')); + }, + + _createCanvas: function () { + canvas = document.createElement('canvas'); + canvas.width = 16; + canvas.height = 16; + + return canvas; + } +}); \ No newline at end of file