Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Handle dynamic document titles #19

Closed
wants to merge 2 commits into from

3 participants

@ipmb

Adds fallbackMethod option for dynamic document titles

  • static is the traditional behavior based on the original document title
  • dynamic uses a regex to replace the title in the event the original document title changed since the script loaded
ipmb added some commits
@ipmb ipmb Adds `fallbackMethod` option for dynamic document titles
* `static` is the traditional behavior based on the original document title
* `dynamic` uses a regex to replace the title in the event the original document title changed since the script loaded
ed2c2de
@ipmb ipmb declare `titleSplit` variable eb26115
@tommoor
Owner

Hey, can you think of any reason why you would want to use the static method? I'm reluctant to add extra options unless really necessary :-)

@ipmb

This isn't fool-proof. If you started with a page title in the form (20) Some Text it would overwrite the (20) part. You'd need to be smarter about handling the fallback for these instances, probably maintaining some internal state.

@simong

Any progress on this? I'm willing to help out...

@simong

FWIW, I don't see any reason why their needs to be a static v dynamic distinction at all.
The fact that updateTitle doesn't take the current title into account feels like a bug and can be fixed without worrying about backwards compatibility (IMHO) in a major release.

I'd be willing to submit a new PR for that logic if there is interest ..

@tommoor
Owner

Agree with @simong, whilst this would be a great improvement - there shouldn't need to be a distinction and the lib should just be able to handle this situation.

@simong simong referenced this pull request from a commit in simong/tinycon
@simong simong #19 - bugfix for handling dynamic document titles 9cc67d6
@simong

I've submitted a PR at #57 which addresses the issue directly.

@tommoor
Owner

Closed by @simong in 9cc67d6, this implementation was preferred as it requires no extra work on behalf of the user.

@tommoor tommoor closed this
@tiff tiff referenced this pull request from a commit in protonet/tinycon
@simong simong #19 - bugfix for handling dynamic document titles fa2a323
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 8, 2012
  1. @ipmb

    Adds `fallbackMethod` option for dynamic document titles

    ipmb authored
    * `static` is the traditional behavior based on the original document title
    * `dynamic` uses a regex to replace the title in the event the original document title changed since the script loaded
  2. @ipmb

    declare `titleSplit` variable

    ipmb authored
This page is out of date. Refresh to see the latest.
Showing with 60 additions and 56 deletions.
  1. +60 −56 tinycon.js
View
116 tinycon.js
@@ -7,11 +7,12 @@
*/
(function(){
-
+
var Tinycon = {};
var currentFavicon = null;
var originalFavicon = null;
var originalTitle = document.title;
+ var titleRegEx = new RegExp('^\\(\\d+\\) ');
var faviconImage = null;
var canvas = null;
var options = {};
@@ -21,9 +22,10 @@
font: '10px arial',
colour: '#ffffff',
background: '#F03D25',
- fallback: true
+ fallback: true,
+ fallbackMethod: 'static'
};
-
+
var ua = (function () {
var agent = navigator.userAgent.toLowerCase();
// New function has access to 'agent' via closure
@@ -38,35 +40,35 @@
safari: ua('safari') && !ua('chrome'),
mozilla: ua('mozilla') && !ua('chrome') && !ua('safari')
};
-
+
// private
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++) {
if (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';
@@ -74,76 +76,78 @@
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.safari || options.fallback === 'force') {
return updateTitle(num);
}
-
+
var context = getCanvas().getContext("2d");
var colour = colour || '#000000';
var num = num || 0;
-
+
faviconImage = new Image();
faviconImage.crossOrigin = 'anonymous';
faviconImage.onload = function() {
-
- // clear canvas
+
+ // 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();
};
-
+
faviconImage.src = getCurrentFavicon();
};
-
+
var updateTitle = function(num) {
-
- if (options.fallback) {
- if (num > 0) {
- document.title = '('+num+') ' + originalTitle;
- } else {
- document.title = originalTitle;
- }
- }
+ if (options.fallback) {
+ var titleSplit,
+ numText = num > 0 ? '('+num+') ' : '';
+ if (options.fallbackMethod === 'static') {
+ document.title = numText + originalTitle;
+ } else if (options.fallbackMethod === 'dynamic') {
+ titleSplit = document.title.split(titleRegEx);
+ document.title = numText + titleSplit.slice(-1);
+ }
+ }
};
-
+
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);
@@ -155,75 +159,75 @@
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);
+ context.fillText(num, 15, browser.mozilla ? 7 : 6);
};
-
+
var refreshFavicon = function(){
// check support
if (!getCanvas().getContext) return;
-
+
setFaviconTag(getCanvas().toDataURL());
};
-
-
+
+
// public
Tinycon.setOptions = function(custom){
options = {};
-
+
for(var i in defaults){
options[i] = custom[i] ? custom[i] : defaults[i];
}
return this;
};
-
+
Tinycon.setImage = function(url){
currentFavicon = url;
refreshFavicon();
return this;
};
-
+
Tinycon.setBubble = function(num, colour){
-
+
// validate
if(isNaN(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;
-})();
+})();
Something went wrong with that request. Please try again.