Skip to content

Instantly share code, notes, and snippets.

@fny
Created February 25, 2012 04:21
Show Gist options
  • Save fny/1906433 to your computer and use it in GitHub Desktop.
Save fny/1906433 to your computer and use it in GitHub Desktop.
Add Bookmark Script
/*!
* Copyright 2006-2011 Dynamic Site Solutions.
* Free use of this script is permitted for non-commercial applications,
* subject to the requirement that this comment block be kept and not be
* altered. The data and executable parts of the script may be changed
* as needed. Dynamic Site Solutions makes no warranty regarding fitness
* of use or correct function of the script. Terms for use of this script
* in commercial applications may be negotiated; for this, or for other
* questions, contact "license-info@dynamicsitesolutions.com".
*
* Script by: Dynamic Site Solutions -- http://www.dynamicsitesolutions.com/
* Last Updated: 2011-03-09
*/
//IE5+/Win, Firefox, Netscape 6+, Opera 7+, Safari, Google Chrome for Windows,
// Konqueror 3, IE5/Mac, iCab 3
var isMSIE=/*@cc_on!@*/false; // http://dean.edwards.name/weblog/2007/03/sniff/
var isIEmac=false; /*@cc_on @if(@_jscript&&!(@_win32||@_win16)&&
(@_jscript_version<5.5)) isIEmac=true; @end @*/
var undefined;
function isEmpty(s){return ((s=='')||/^\s*$/.test(s));}
var addBookmarkObj = {
linkText:'Bookmark This Page',
title:document.title,
URL:location.href,
addTextLink:function(parId){
if(addBookmarkObj.checkMobileDevice()) return;
var a=addBookmarkObj.makeLink(parId,1);
if(a){
jQuery(a).text(addBookmarkObj.linkText);
return;
}
var cont=addBookmarkObj.getParent(parId);
if(!cont) return;
jQuery(cont).append('<span>'+addBookmarkObj.findKeys()+'</span>');
},
addImageLink:function(parId,imgPath){
if(!imgPath || isEmpty(imgPath)) return;
if(addBookmarkObj.checkMobileDevice()) return;
var o=addBookmarkObj,a=o.makeLink(parId),img=document.createElement('img');
img.title=img.alt=o.modal?o.linkText:o.findKeys();
img.src=imgPath;
a.appendChild(img);
},
makeLink:function(parId,isText){
var cont=addBookmarkObj.getParent(parId);
if(!cont) return null;
var a=document.createElement('a');
a.href=addBookmarkObj.URL;
var s=document.createElement('div').style;
var isFx35plus=((navigator.userAgent.toLowerCase().indexOf('firefox')!=-1)
&& (s.wordWrap!==undefined) && (s.MozTransform!==undefined));
if(window.external && isMSIE && !isIEmac){
// IE4/Win generates an error when you
// execute 'typeof(window.external.AddFavorite)'
// In IE7 the page must be from a web server, not directly from a local
// file system, otherwise, you will get a permission denied error.
// Maxthon shows 'typeof(window.external.AddFavorite)' as 'undefined'
// even though it is defined.
a.onclick=function(){ // IE/Win
try {
window.external.AddFavorite(addBookmarkObj.URL,addBookmarkObj.title);
} catch(ex){
addBookmarkObj.displayMsg(addBookmarkObj.findKeys());
}
return false;
}
addBookmarkObj.modal=1;
} else if(window.opera || isFx35plus){ // Opera 7+, Firefox 3.5+
a.title=addBookmarkObj.title,a.rel='sidebar';
addBookmarkObj.modal=1;
} else if(isText) {
return null;
} else {
a.onclick=function(){
addBookmarkObj.displayMsg(this.firstChild.title);
return false;
}
}
return cont.appendChild(a);
},
displayMsg:function(t){
alert('After closing this dialog, '+t.charAt(0).toLowerCase()+t.slice(1));
},
getParent:function(parId){
if(!document.getElementById || !document.createTextNode) return null;
parId=((typeof(parId)=='string')&&!isEmpty(parId))
?parId:'addBookmarkContainer';
return document.getElementById(parId)||null;
},
findKeys:function(){
// user agent sniffing is bad in general, but this is one of the times
// when it's really necessary
var ua=navigator.userAgent.toLowerCase(),Webkit=(ua.indexOf('webkit')!=-1),
Mac=/mac(\s*os|intosh|.*p(ower)?pc)/.test(ua),
str=(Mac?'Command/Cmd':'CTRL');
if(window.opera && (!opera.version || (opera.version()<9))) {
str+=' + T'; // Opera versions before 9
} else if(ua.indexOf('konqueror')!=-1) {
str+=' + B'; // Konqueror
} else if(window.opera || window.home || Webkit || isMSIE || Mac) {
// IE, Firefox, Netscape, Safari, Google Chrome, Opera 9+, iCab, IE5/Mac
str+=' + D';
}
return ((str)?'Press '+str+' to bookmark this page.':str);
},
checkMobileDevice:function(){
var r='iphone|ipod|android|palm|symbian|windows ce|windows phone|iemobile|'+
'blackberry|smartphone|netfront|opera m|htc[-_].*opera';
return (new RegExp(r)).test(navigator.userAgent.toLowerCase());
}
}
jQuery(document).ready(addBookmarkObj.addTextLink);
// to make multiple links, do something like this:
/*
jQuery(document).ready(function(){
var f=addBookmarkObj.addTextLink;
f();
f('otherContainerID');
});
*/
// below is an example of how to make an image link with this
// the first parameter is the ID. If you pass an empty string it defaults to
// 'addBookmarkContainer'.
/*
jQuery(document).ready(function(){
addBookmarkObj.addImageLink('','/images/add-bookmark.jpg');
});
*/
/*!
* Copyright 2006-2011 Dynamic Site Solutions.
* Free use of this script is permitted for non-commercial applications,
* subject to the requirement that this comment block be kept and not be
* altered. The data and executable parts of the script may be changed
* as needed. Dynamic Site Solutions makes no warranty regarding fitness
* of use or correct function of the script. Terms for use of this script
* in commercial applications may be negotiated; for this, or for other
* questions, contact "license-info@dynamicsitesolutions.com".
*
* Script by: Dynamic Site Solutions -- http://www.dynamicsitesolutions.com/
* Last Updated: 2011-03-09
*/
//IE5+/Win, Firefox, Netscape 6+, Opera 7+, Safari, Google Chrome for Windows,
// Konqueror 3, IE5/Mac, iCab 3
var isMSIE=/*@cc_on!@*/false; // http://dean.edwards.name/weblog/2007/03/sniff/
var isIEmac=false; /*@cc_on @if(@_jscript&&!(@_win32||@_win16)&&
(@_jscript_version<5.5)) isIEmac=true; @end @*/
var undefined;
function isEmpty(s){return ((s=='')||/^\s*$/.test(s));}
var addBookmarkObj = {
linkText:'Bookmark This Page',
title:document.title,
URL:location.href,
addTextLink:function(parId){
if(addBookmarkObj.checkMobileDevice()) return;
var a=addBookmarkObj.makeLink(parId,1);
if(a){
a.appendChild(document.createTextNode(addBookmarkObj.linkText));
return;
}
var cont=addBookmarkObj.getParent(parId);
if(!cont) return;
var elm=document.createElement('span');
elm.appendChild(document.createTextNode(addBookmarkObj.findKeys()));
cont.appendChild(elm);
},
addImageLink:function(parId,imgPath){
if(!imgPath || isEmpty(imgPath)) return;
if(addBookmarkObj.checkMobileDevice()) return;
var o=addBookmarkObj,a=o.makeLink(parId),img=document.createElement('img');
img.title=img.alt=o.modal?o.linkText:o.findKeys();
img.src=imgPath;
a.appendChild(img);
},
makeLink:function(parId,isText){
var cont=addBookmarkObj.getParent(parId);
if(!cont) return null;
var a=document.createElement('a');
a.href=addBookmarkObj.URL;
var s=document.createElement('div').style;
var isFx35plus=((navigator.userAgent.toLowerCase().indexOf('firefox')!=-1)
&& (s.wordWrap!==undefined) && (s.MozTransform!==undefined));
if(window.external && isMSIE && !isIEmac){
// IE4/Win generates an error when you
// execute 'typeof(window.external.AddFavorite)'
// In IE7 the page must be from a web server, not directly from a local
// file system, otherwise, you will get a permission denied error.
// Maxthon shows 'typeof(window.external.AddFavorite)' as 'undefined'
// even though it is defined.
a.onclick=function(){ // IE/Win
try {
window.external.AddFavorite(addBookmarkObj.URL,addBookmarkObj.title);
} catch(ex){
addBookmarkObj.displayMsg(addBookmarkObj.findKeys());
}
return false;
}
addBookmarkObj.modal=1;
} else if(window.opera || isFx35plus){ // Opera 7+, Firefox 3.5+
a.title=addBookmarkObj.title,a.rel='sidebar';
addBookmarkObj.modal=1;
} else if(isText) {
return null;
} else {
a.onclick=function(){
addBookmarkObj.displayMsg(this.firstChild.title);
return false;
}
}
return cont.appendChild(a);
},
displayMsg:function(t){
alert('After closing this dialog, '+t.charAt(0).toLowerCase()+t.slice(1));
},
getParent:function(parId){
if(!document.getElementById || !document.createTextNode) return null;
parId=((typeof(parId)=='string')&&!isEmpty(parId))
?parId:'addBookmarkContainer';
return document.getElementById(parId)||null;
},
findKeys:function(){
// user agent sniffing is bad in general, but this is one of the times
// when it's really necessary
var ua=navigator.userAgent.toLowerCase(),Webkit=(ua.indexOf('webkit')!=-1),
Mac=/mac(\s*os|intosh|.*p(ower)?pc)/.test(ua),
str=(Mac?'Command/Cmd':'CTRL');
if(window.opera && (!opera.version || (opera.version()<9))) {
str+=' + T'; // Opera versions before 9
} else if(ua.indexOf('konqueror')!=-1) {
str+=' + B'; // Konqueror
} else if(window.opera || window.home || Webkit || isMSIE || Mac) {
// IE, Firefox, Netscape, Safari, Google Chrome, Opera 9+, iCab, IE5/Mac
str+=' + D';
}
return ((str)?'Press '+str+' to bookmark this page.':str);
},
checkMobileDevice:function(){
var r='iphone|ipod|android|palm|symbian|windows ce|windows phone|iemobile|'+
'blackberry|smartphone|netfront|opera m|htc[-_].*opera';
return (new RegExp(r)).test(navigator.userAgent.toLowerCase());
}
}
// Note: I recommend you use a more comprehensive event management script for
// production (aka "live") pages. Most libaries, such as jQuery, include one.
// Dean Edwards' event manipulation functions is a good example. You can find
// them here: http://dean.edwards.name/weblog/2005/10/add-event2/
var LoadHandler = {
handlers:[],
add:function(fn){
if(window.onload!=LoadHandler.theHandler) LoadHandler._push(window.onload);
LoadHandler._push(fn);
window.onload=LoadHandler.theHandler;
},
_push:function(fn){
if(typeof(fn)!='function') return;
LoadHandler.handlers[LoadHandler.handlers.length]=fn;
},
theHandler:function(){
var handlers=LoadHandler.handlers,i=-1,fn;
while(fn=handlers[++i]) fn();
}
}
LoadHandler.add(addBookmarkObj.addTextLink);
// to make multiple links, do something like this:
/*
LoadHandler.add(function(){
var f=addBookmarkObj.addTextLink;
f();
f('otherContainerID');
});
*/
// below is an example of how to make an image link with this
// the first parameter is the ID. If you pass an empty string it defaults to
// 'addBookmarkContainer'.
/*
LoadHandler.add(function(){
addBookmarkObj.addImageLink('','/images/add-bookmark.jpg');
});
*/
@fny
Copy link
Author

fny commented Feb 25, 2012

How To Use The Script

The script looks for an element with the ID attribute set to "addBookmarkContainer" and appends a new link () element as a child of it. The following code is an example of the elements needed to use this script on a page (change the path as needed).

<script type="text/javascript" src="/js/add_bookmark.js">
</script>
<p id="addBookmarkContainer"></p>

What Makes This Script Different?

This script is written using unobtrusive JavaScript (JS) techniques so that if JS support is not enabled, the link will not be present, thus preventing confusion in any user (of a browser that does not have JS support enabled) who clicks the link with no result.
Another big difference is that it is made to do something useful in more browsers than just IE/Win, Firefox, and/or Opera 7+. It is known to work (to varying degrees) in IE5+/Win, Firefox, Safari, Google Chrome (for Windows), Netscape 6+, Opera 7+, Konqueror 3+, IE5/Mac, and iCab 3.
Many similar scripts use window.sidebar.addPanel() or rel="sidebar" to add a bookmark in Firefox. There's just one problem with those two methods — they add a bookmark that is set to open in the sidebar (panel) by default instead of opening in the window/tab like a normal bookmark. rel="sidebar" works fine in Opera 7+, because in the dialog window there is an option to make the bookmark open in the sidebar or not. Firefox doesn't provide that option in the dialog window; to change it you have to open the properties of the bookmark, which most people won't be aware of or know how to do.

Known IE Issue

When the page is viewed directly from Windows, there's a security limitation on the function used in IE that triggers an error which causes the page to reload. I could add code to prevent the error, but since the script will always be used on a web server, it doesn't seem worth making the script longer to fix it.

@fny
Copy link
Author

fny commented Feb 25, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment