-
This should be easy:
Code:
a = e.target.href || e.target.getElement('a') || e.target.getParents('a') || null;
But Mootools is poorly coded for IE in that if there are no child nodes, getElement throws an error instead of returning a falsy value. And getParents just doesn't seem to work at all for IE, at least not like that. Both are fine in all other browsers I tested though. So we can do some IE gynastics (highlighted and green in the below) to get it to work out in IE and leave others unaffected. The only pitfall in IE is that if there will be nested elements within the element(s) nested within the a tag, more code will be needed. The getParents method in Mootools takes care of that for all others.
Here's the finished code with some other stuff (highlighted and black) added so that on a real page where the domready may take a while to fire, the mainContent will remain unseen until it slides in:
Code:
<script type="text/javascript">
document.write('<style type="text/css">#mainContent {visibility: hidden;}<\/style>');
window.addEvent('domready', function(){
var MC = $('mainContent'), myPanel = new Fx.Slide(MC).hide(), a;
myPanel.addEvent('start', function(){MC.setStyle('visibility', 'visible');});
myPanel.slideIn();
$$('.menu').addEvent('click', function(e){
e.stop();
/*@cc_on @*/
/*@if(@_jscript_version >= 5)
try{
@end @*/
a = e.target.href || e.target.getElement('a') || e.target.getParents('a') || null;
/*@if(@_jscript_version >= 5)
}catch(err){a = e.target.parentNode && e.target.parentNode.href? e.target.parentNode : null;}
@end @*/
if(a){
myPanel.addEvent('complete', function() {
location = a;
});
myPanel.slideOut();
}
});
});
</script>
Also note highlighted and red - a test for all browsers to make absolutely sure we found a link before attempting to proceed with the slide out and page change.
-
Hey John,
Thanks once again. I am really impressed. I am surprised that, with the exception of the green highlighted stuff, I understand almost all of this.
The bit that writes CSS to hide #mainContent until Mootools kicks-in is simple genius. I love it! Hopefully that will do away with the flicker that I was getting on some browsers when going from one page to another.
Could you please tell me a little more about 'e.target.href'. You wrote that 'e' is the event object. In this case it is the thing that gets clicked, right? Until you click something inside '.menu' it could be anything, true? And, 'target' and 'href', how do they differ? In 'e.target.getElement('a')' there is no mention of href so why is it needed in 'e.target.href'?
With more thanks, and best wishes,
Laurence
-
You are right about e and e.target. The href thing too, except there is an oddity about how that works out in javascript that makes the code much shorter than it would otherwise have to be.
I know what you might be thinking - maybe it's this shortcut that doesn't work in IE. Nope, I tested it written out the long way, no help.
Anyways, the trick is that an anchor link tag, unlike all other tags, when viewed by javascript as an object (how it sees all other tags that are part of the DOM), is seen as a string. That string is the anchor link's href. So the first test:
determines whether or not we have a link, as well as returning the href because if it has no href, it's not an anchor link. The second test:
Code:
e.target.getElement('a')
since it can only (when working as expected, and as it does in all non-IE I tested), returns either an a tag or a falsy value, when it returns a truthy value, it will already be the href value.
Similarly for the third test.
As you are probably also interested, this stuff:
Code:
/*@cc_on @*/
/*@if(@_jscript_version >= 5)
when placed around a code block makes that block appear to be a commnet to all but IE 5+.
The code I'm hiding is an ordinary try/catch which catches the errors thrown by IE in some of the situations it may encounter with that line:
Code:
a = e.target.href || e.target.getElement('a') || e.target.getParents('a') || null;
and performs the required actions IE otherwise cannot perform when an error is thrown by it for that line.
-
Ooops! I discovered another problem with IE. If the element that was clicked on (e.target) is an image tag with a src attribute, IE sees that attribute as qualifying as an href property of the image tag. So this messes things up. I've decided to therefore do everything in a manner that IE can handle and that also will work in other browsers:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://mootools.net/download/get/mootools-1.2.4-core-yc.js"></script>
<script type="text/javascript" src="mootools-1.2.4.2-more.js"></script>
<script type="text/javascript">
document.write('<style type="text/css">#mainContent {visibility: hidden;}<\/style>');
window.addEvent('domready', function(){
var MC = $('mainContent'), myPanel = new Fx.Slide(MC).hide(), lnks = $(document.body).getElements('a'), a, t, tp, tc, cn;
myPanel.addEvent('start', function(){MC.setStyle('visibility', 'visible');});
myPanel.slideIn();
$$('.menu').addEvent('click', function(e){
e.stop();
cn = 0;
t = tp = tc = e.target;
while(lnks.indexOf(tp) < 0 && lnks.indexOf(tc) < 0){
tp = tp.parentNode || {parentNode: null};
tc = t.getElementsByTagName('a')[cn++] || null;
}
a = lnks.indexOf(tp) > -1? tp : lnks.indexOf(tc) > -1? tc : null;
if(a && a.href){
myPanel.addEvent('complete', function() {
location = a;
});
myPanel.slideOut();
}
});
});
</script>
</head>
<body>
<ul>
<li class="menu"><a href="page2.html">Page 2</a></li>
<li class="menu"><a href="page3.html"><span>Page 3</span></a></li>
<li class="menu"><a name="ulMenu">Dummy</a></li>
</ul>
<div id="mainContent">content here!</div>
</body>
</html>