Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Handle dynamic document titles #19

Closed
wants to merge 2 commits into from

3 participants

Peter Baumgartner Tom Moor Simon Gaeremynck
Peter Baumgartner

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
Peter Baumgartner 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
Peter Baumgartner ipmb declare `titleSplit` variable eb26115
Tom Moor
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 :-)

Peter Baumgartner

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.

Simon Gaeremynck

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

Simon Gaeremynck

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 ..

Tom Moor
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.

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

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

Tom Moor
Owner

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

Tom Moor tommoor closed this
Christopher Blum tiff referenced this pull request from a commit in protonet/tinycon
Simon Gaeremynck 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. Peter Baumgartner

    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. Peter Baumgartner

    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
116 tinycon.js
View
@@ -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.