Popups are not all bad
EDIT: I have updated the script again, this time adding a timestamp to the window name in the ‘window.open’ call to avoid popups overwriting each other if multiple links are followed from a page.
Today my good friend Kay asked me if I had time to look at some nifty Javascript fellow web professional Roger Johansson had come up with to make a few modifications to suit her particular needs for a project she is currently working on.
As I am usually very curious regarding any sort of modification or enhancement of any kind of code I said I’d have a look at it.
What Roger has put together is a very well done, easy to use and accessible solution to the "popup problem" - a wild mix of inline javascript code, or onClick functions - by removing all javascript from the markup and therefore separating the presentation from the behavior layer as it should be.
The original version of Roger’s script used a ‘_blank‘ to open a new window, which is obviously sufficient but didn’t do the trick for Kay.
What Kay wanted, was a way to open popups with different dimensions via a couple of pre-defined class names (i.e. popup_small, popup_medium etc.) to get a bit more control. While we were talking about it I thought it would be even more convenient to get custom width and height values from the class names in addition to the pre-defined class names to add greater flexibility.
Modification 1 (pre-defined popup sizes):
For the first step of the modification I simply added a switch to Roger’s ‘openWin‘ function that would act depending on the class name of the object in question. I then simply modified the ‘window.open‘ call removing the ‘_blank‘ and instead assigning a default
window name and passing in ‘strWSize‘ to allow for the window size information to be used.
var strWSize = ”;
switch (className){
case ‘popup_sml’:
strWSize = ‘width=200,height=200′;
break;
case ‘popup_med’:
strWSize = ‘width=300,height=300′;
break;
case ‘popup_lrg’:
strWSize = ‘width=400,height=400′;
break;
default:
strWSize = ‘width=200,height=200′;
break;
}
var oWin = window.open(this.getAttribute(’href’), ‘popup’, strWSize);
Adding the event handler and assigning the class names you wish to filter for works exactly the same as before so there is no need to change anything there.
JSTarget.addEvent(window, ‘load’, function(){JSTarget.init(”class”,”popup_sml”,” (small popup)”);});
JSTarget.addEvent(window, ‘load’, function(){JSTarget.init(”class”,”popup_med”,” (medium popup)”);});
JSTarget.addEvent(window, ‘load’, function(){JSTarget.init(”class”,”popup_lrg”,” (large popup)”);});
Modification 2 (pre-defined & custom sized popups):
The second modification allows the user to specify one base class name when adding the event handler and the ‘init‘ function will then be able to find exactly that class name or any other class name that is constructed in the following manner (omitting the square brackets):
[classname]_[width]x[height] (i.e. popup_250x300)
This means that you can specify popups of any size in the HTML without having to touch the Javascript function to add new event handlers, making it even more flexible in enviroments such as CMS’s where content control might be limited.
To allow for this to work I had to modify the regular expression in the ‘init‘ function to allow for those two patterns to be found instead of just the class name itself.
The original line:
var oRegExp = new RegExp(”(^|\\s)” + strVal + “(\\s|$)”);
(find the class name, or the class name with or without leading or trailing white spaces)
was turned into:
var oRegExp = new RegExp(”(^|\\s)((”+ strVal + “)|(” + strVal + “_(\\d){1,}x(\\d){1,}))(\\s|$)”);
(find the class name OR the class name with the addition of ‘_[a numeric value]x[a numeric value], either with or without leading or trailing white spaces)
The next part of this modification was added to the openWin function adding string manipulation to get the popup dimensions from the class name (where applicable).
//bloody IE6 always needs an extra treatment
var className = (this.getAttribute(’class’)) ? this.getAttribute(’class’): this.getAttribute(’classname’);
var strDim = className.substr(className.lastIndexOf(’_')+1);
var wWidth = strDim.substr(0,strDim.indexOf(’x'));
var wHeight = strDim.substr(strDim.indexOf(’x')+1);
Note: IE uses a different attribute name to access class values, hence we need another conditional to make sure we get the class name on this browser as well.
In addition to this a conditional was added around the switch we saw in modification 1 to ensure that this style of popup was only triggered when dimensions where actually found in the class name.
if (wWidth !== ” && wHeight !== ”){
strWSize = ‘width=’ + wWidth + ‘,height=’ + wHeight;
}
else {
// switch here
}
The last part of this modification is the addition of a ‘base‘ event handler, which specifies the base class name the ‘init‘ function should be looking for in the markup.
JSTarget.addEvent(window, ‘load’, function(){JSTarget.init(”class”,”popup”,” (custom sized popup)”);});
With this last line in place all you need to do in your markup is to use the base class name and add your dimensions of choice.
Due to the fact that both modifications are working together, you can still use the pre-defined class names should you not wish to specify a custom size each time (which is more than likely).
That’s it really. Clean, seperated, accessible, flexible, easy to use.
Big thanks to Roger for knocking the original snippet up in the first place.
The Javascript code and the HTML demo wait behind the cut, and please forgive me but Wordpress and my current styling is giving me the s#$@@ atm, which is why it all looks a little messy.
/*
JSTarget function by Roger Johansson, www.456bereastreet.com
*/
var JSTarget = {
init: function(att,val,warning) {
if (document.getElementById && document.createElement && document.appendChild) {
var strAtt = ((typeof att == ‘undefined’) || (att == null)) ? ‘class’ : att;
var strVal = ((typeof val == ‘undefined’) || (val == null)) ? ‘non-html’ : val;
var strWarning = ((typeof warning == ‘undefined’) || (warning == null)) ? ‘ (opens in a new window)’ : warning;
var oWarning;
var arrLinks = document.getElementsByTagName(’a');
var oLink;
var oRegExp = new RegExp(”(^|\\s)((”+ strVal + “)|(” + strVal + “_(\\d){1,}x(\\d){1,}))(\\s|$)”);
for (var i = 0; i < arrLinks.length; i++) {
oLink = arrLinks[i];
if ((strAtt == 'class') && (oRegExp.test(oLink.className)) || (oRegExp.test(oLink.getAttribute(strAtt)))) {
oWarning = document.createElement("em");
oWarning.appendChild(document.createTextNode(strWarning));
oLink.appendChild(oWarning);
oLink.onclick = JSTarget.openWin;
}
}
oWarning = null;
}
},
openWin: function(e) {
var event = (!e) ? window.event : e;
if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return true;
else {
/*
check for different class names to assign popup sizes.
custom sized popups are also recognised if the class name
is constructed like: popup_[width]x[height]
e.g. popup_400x600
- added by Benjamin Kroll; 15/01/2007
*/
var strWSize;
//bloody IE6 always needs an extra treatment
var className = (this.getAttribute('class')) ? this.getAttribute('class'): this.getAttribute('classname');
var strDim = className.substr(className.lastIndexOf('_')+1);
var wWidth = strDim.substr(0,strDim.indexOf('x'));
var wHeight = strDim.substr(strDim.indexOf('x')+1);
if (wWidth !== '' && wHeight !== ''){
strWSize = 'width=' + wWidth + ',height=' + wHeight;
}
else {
switch (className){
case 'popup_sml':
strWSize = 'width=200,height=200';
break;
case 'popup_med':
strWSize = 'width=300,height=300';
break;
case 'popup_lrg':
strWSize = 'width=400,height=400';
break;
default:
strWSize = 'width=200,height=200';
break;
}
}
// create a timestamp to attach to the window name so we can create a relativly (to the milisecond)
// unique window name to avoid popups from overwriting each other
var dtNow = new Date();
var oWin = window.open(this.getAttribute('href'), 'popup' + dtNow.getTime(), strWSize);
if (oWin) {
if (oWin.focus) oWin.focus();
return false;
}
oWin = null;
return true;
}
},
/*
addEvent function from http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
*/
addEvent: function(obj, type, fn) {
if (obj.addEventListener)
obj.addEventListener(type, fn, false);
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj[type+fn] = function() {obj["e"+type+fn]( window.event );}
obj.attachEvent("on"+type, obj[type+fn]);
}
}
};
JSTarget.addEvent(window, 'load', function(){JSTarget.init("class","popup_sml"," (small popup)");});
JSTarget.addEvent(window, 'load', function(){JSTarget.init("class","popup_med"," (medium popup)");});
JSTarget.addEvent(window, 'load', function(){JSTarget.init("class","popup_lrg"," (large popup)");});
JSTarget.addEvent(window, 'load', function(){JSTarget.init("class","popup"," (custom sized popup)");});


April 1st, 2007 at 17:18:15
[…] http://www.webkroll.com/popups-are-not-all-bad/ […]
February 13th, 2008 at 12:54:34
<a HREF="http://drgonballxxxhentaigokuebulma.askoldant.info/" rel="nofollow">drgon ball xxx hentai goku e bulma</A> http://orkutcom.askoldant.info <a HREF="http://videogratisincesti.askoldant.info/" rel="nofollow">video gratis incesti</A> <a HREF="http://sexisuore.askoldant.info/" rel="nofollow">sexi suore</A> http://sexisuore.askoldant.info <a HREF="http://rompimiilculo.askoldant.info/" rel="nofollow">rompimi il culo</A> http://bellefemmine.askoldant.info <a HREF="http://ispettoratodellavorotorino.askoldant.info/" rel="nofollow">ispettorato del lavoro torino</A> http://pornofotogratis.askoldant.info http://sunporno.askoldant.info