Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/static/js/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,20 @@
var padutils = require('./pad_utils').padutils;
var padcookie = require('./pad_cookie').padcookie;

require('./tinycon');

var chat = (function()
{
var isStuck = false;
var chatMentions = 0;
var title = document.title;
var self = {
show: function ()
{
$("#chaticon").hide();
$("#chatbox").show();
self.scrollDown();
chatMentions = 0;
document.title = title;
Tinycon.setBubble(0);
},
stickToScreen: function(fromInitialCall) // Make chat stick to right hand side of screen
{
Expand Down Expand Up @@ -126,12 +127,9 @@ var chat = (function()
// chat throb stuff -- Just make it throw for twice as long
if(wasMentioned && !alreadyFocused)
{ // If the user was mentioned show for twice as long and flash the browser window
if (chatMentions == 0){
title = document.title;
}
$('#chatthrob').html("<b>"+authorName+"</b>" + ": " + text).show().delay(4000).hide(400);
chatMentions++;
document.title = "("+chatMentions+") " + title;
Tinycon.setBubble(chatMentions);
}
else
{
Expand All @@ -141,7 +139,7 @@ var chat = (function()
// Clear the chat mentions when the user clicks on the chat input box
$('#chatinput').click(function(){
chatMentions = 0;
document.title = title;
Tinycon.setBubble(0);
});
self.scrollDown();

Expand Down
237 changes: 237 additions & 0 deletions src/static/js/tinycon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/*!
* Tinycon - A small library for manipulating the Favicon
* Tom Moor, http://tommoor.com
* Copyright (c) 2012 Tom Moor
* MIT Licensed
* @version 0.2.6
*/

(function(){

var Tinycon = {};
var currentFavicon = null;
var originalFavicon = null;
var originalTitle = document.title;
var faviconImage = null;
var canvas = null;
var options = {};
var defaults = {
width: 7,
height: 9,
font: '10px arial',
colour: '#ffffff',
background: '#F03D25',
fallback: true
};

var ua = (function () {
var agent = navigator.userAgent.toLowerCase();
// New function has access to 'agent' via closure
return function (browser) {
return agent.indexOf(browser) !== -1;
};
}());

var browser = {
ie: ua('msie'),
chrome: ua('chrome'),
webkit: ua('chrome') || ua('safari'),
safari: ua('safari') && !ua('chrome'),
mozilla: ua('mozilla') && !ua('chrome') && !ua('safari')
};

// private methods
var getFaviconTag = function(){

var links = document.getElementsByTagName('link');

for(var i=0, len=links.length; i < len; i++) {
if ((links[i].getAttribute('rel') || '').match(/\bicon\b/)) {
return links[i];
}
}

return false;
};

var removeFaviconTag = function(){

var links = document.getElementsByTagName('link');
var head = document.getElementsByTagName('head')[0];

for(var i=0, len=links.length; i < len; i++) {
var exists = (typeof(links[i]) !== 'undefined');
if (exists && links[i].getAttribute('rel') === 'icon') {
head.removeChild(links[i]);
}
}
};

var getCurrentFavicon = function(){

if (!originalFavicon || !currentFavicon) {
var tag = getFaviconTag();
originalFavicon = currentFavicon = tag ? tag.getAttribute('href') : '/favicon.ico';
}

return currentFavicon;
};

var getCanvas = function (){

if (!canvas) {
canvas = document.createElement("canvas");
canvas.width = 16;
canvas.height = 16;
}

return canvas;
};

var setFaviconTag = function(url){
removeFaviconTag();

var link = document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'icon';
link.href = url;
document.getElementsByTagName('head')[0].appendChild(link);
};

var log = function(message){
if (window.console) window.console.log(message);
};

var drawFavicon = function(num, colour) {

// fallback to updating the browser title if unsupported
if (!getCanvas().getContext || browser.ie || browser.safari || options.fallback === 'force') {
return updateTitle(num);
}

var context = getCanvas().getContext("2d");
var colour = colour || '#000000';
var num = num || 0;
var src = getCurrentFavicon();

faviconImage = new Image();
faviconImage.onload = function() {

// clear canvas
context.clearRect(0, 0, 16, 16);

// draw original favicon
context.drawImage(faviconImage, 0, 0, faviconImage.width, faviconImage.height, 0, 0, 16, 16);

// draw bubble over the top
if (num > 0) drawBubble(context, num, colour);

// refresh tag in page
refreshFavicon();
};

// allow cross origin resource requests if the image is not a data:uri
// as detailed here: https://github.com/mrdoob/three.js/issues/1305
if (!src.match(/^data/)) {
faviconImage.crossOrigin = 'anonymous';
}

faviconImage.src = src;
};

var updateTitle = function(num) {

if (options.fallback) {
if (num > 0) {
document.title = '('+num+') ' + originalTitle;
} else {
document.title = originalTitle;
}
}
};

var drawBubble = function(context, num, colour) {

// bubble needs to be larger for double digits
var len = (num+"").length-1;
var width = options.width + (6*len);
var w = 16-width;
var h = 16-options.height;

// webkit seems to render fonts lighter than firefox
context.font = (browser.webkit ? 'bold ' : '') + options.font;
context.fillStyle = options.background;
context.strokeStyle = options.background;
context.lineWidth = 1;

// bubble
context.fillRect(w,h,width-1,options.height);

// rounded left
context.beginPath();
context.moveTo(w-0.5,h+1);
context.lineTo(w-0.5,15);
context.stroke();

// rounded right
context.beginPath();
context.moveTo(15.5,h+1);
context.lineTo(15.5,15);
context.stroke();

// bottom shadow
context.beginPath();
context.strokeStyle = "rgba(0,0,0,0.3)";
context.moveTo(w,16);
context.lineTo(15,16);
context.stroke();

// number
context.fillStyle = options.colour;
context.textAlign = "right";
context.textBaseline = "top";

// unfortunately webkit/mozilla are a pixel different in text positioning
context.fillText(num, 15, browser.mozilla ? 7 : 6);
};

var refreshFavicon = function(){
// check support
if (!getCanvas().getContext) return;

setFaviconTag(getCanvas().toDataURL());
};


// public methods
Tinycon.setOptions = function(custom){
options = {};

for(var key in defaults){
options[key] = custom.hasOwnProperty(key) ? custom[key] : defaults[key];
}
return this;
};

Tinycon.setImage = function(url){
currentFavicon = url;
refreshFavicon();
return this;
};

Tinycon.setBubble = function(num, colour){

// validate
if(isNaN(parseFloat(num)) || !isFinite(num)) return log('Bubble must be a number');

drawFavicon(num, colour);
return this;
};

Tinycon.reset = function(){
Tinycon.setImage(originalFavicon);
};

Tinycon.setOptions(defaults);
window.Tinycon = Tinycon;
})();