Archive for the 'ie' Category

IE has a problem with getElementsByName

Wednesday, October 3rd, 2007

Yes, it does.

Sometimes it's convenient to use "HTML arrays", meaning to name fields like:
<input name="something[]" />

Then on the server side you loop through the array $_POST['something']

This allows for a flexibility where your app doesn't know the number of inputs in advance, but works fine regardless of the actual number.

Even cooler is that you can generate fields on the client-side, with JavaScript.

The problem is if you want to do some sort of client-side validation after you've generated fields on the fly. If you have:

<input name="something[]" />
<input name="something[]" />
<input name="something[]" />

Then you can access the fields using

document.getElementsByName('something[]')

So in the case above

document.getElementsByName('something[]').length

will give you 3.

Then you add another fields, for example like:

var new_input = document.createElement('input');
new_input.type = 'text';
new_input.name = 'something[]';
document.body.appendChild(new_input);

Now if you try to count the fields with

document.getElementsByName('something[]').length

you'll get 4 in Firefox as you would expect, but still 3 in IE.

Bugs happen, c'est la vie :D

Here's a demo

Tested IE7 only, don't know if the bug exists in earlier versions.

My example was with an HTML array using []s in field names, but the issue remains if you have regular names without brackets, for example you have radio buttons or checkboxes and you want to create more choices dynamically with JavaScript.

 

Order of execution of event listeners

Tuesday, August 14th, 2007

Say you attach several listeners to an event, for example you want a few things to happen on page load. What is the order of execution of the different listeners? You'd think that the listener attached first will execute first, followed by the second and so on… Well, yes, in FF, Opera, Safari on Windows, but not in IE.

The test

  var i = 1, ol = document.getElementById('result');

  for (i; i <= 10; i++) {
      YAHOO.util.Event.addListener(window,'load',
        function(num){
            return function(){
                ol.innerHTML += '<li>' + num + '</li>';
            }
        }(i)
      );
  }

Result in FF, O, Safari

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10

Result in IE

  1. 1
  2. 2
  3. 4
  4. 6
  5. 8
  6. 10
  7. 9
  8. 7
  9. 5
  10. 3

Observation

Here you can try it out yourself

Try in IE. Reload. Reload again. Notice something? The order is not random. Always starts 1, 2, then goes through all even numbers until 10 then backwards - 9, 7, 5, 3 - all odd numbers.

Try with a bigger loop - still the same thing. Hmm, interesting… Maybe not something you'd like to rely on, but still…

 

Two bookmarklets for debugging in IE

Tuesday, February 20th, 2007

Here are two bookmarklets that could make your life easier when trying to figure out why in IE a page behave as wrong as it behaves. For Firefox we have Firebug, so none of this is necessary. For IE we have also Firebug lite (see my post), but you need some setup before you can use it. With this thing here you can mess up any page you see on the web, not only yours :)

Bookmarklet 1 - Eval() textarea

I saw this bookmarklet here and it's beautiful. When you start it, it puts a textarea at the bottom of your page and you can type javascript in it, then eval()-uate it. Perfect! Only … it doesn't work in frames. So I did the same thing but when you have frames (works without frames as well). The way mine works is - you first select some text in a frame, then you click the bookmarklet. A new textarea, ready to execute javascript will be placed in this frame (or iframe) that you selected. Also in this case when you type document.something, it refers to the document in the frame, not the frameset.
If you don't select any text and click the bookmarklet, it will place the textarea in the topmost document, so it will work for frame-free pages as well.

So here's the bookmarklet.

textarea eval

And here's a page where you can test.

Bookmarklet 2 - dump anything

After having my beautiful textarea, I wanted to be able to dump variables, like print_r() or var_dump() but for Javascript. I googled and I found this little script. All I did then is to make it a bookmarklet. How it works? You select the bookmarklet, it gives you a prompt, where you type whatever you want to dump, like document.location for example. Then it shows you an alert with all properties of this thing you typed. (Don't try to dump document though, or something else that recurses, because the script won't handle the recursion and will freeze).

Install it from here:

dump var

While this second bookmarklet will most likely work in FF as well, you don't need it, you have firebug!

 

Dynamic SCRIPT and STYLE elements in IE

Friday, January 26th, 2007

So you know how to add external scripts and styles, using the DOM, after the page is loaded. And what if you don't have external files, but have some style definitions and some JS code as text and you want it inserted and executed into a page.

The DOM way

"Ha! An easy one", you'd say and then go like:

var ss = document.createElement('script');
var scr = 'alert("bah");';
var tt = document.createTextNode(scr);
ss.appendChild(tt);
var hh = document.getElementsByTagName('head')[0];
hh.appendChild(ss);

"Ha!" in turn says IE, "No way!"

The IE way for SCRIPT

The above won't work in IE, but you can use the text property instead of creating a text node. Interestingly enough, this also works in Firefox.

var ss = document.createElement('script');
var scr = 'alert("bah");';
ss.text = scr;
var hh = document.getElementsByTagName('head')[0];
hh.appendChild(ss);

The IE way for STYLE

STYLE, SCRIPT, what's the difference, they are merely elements of the DOM tree. For the normal browsers, yes, so creating a text node with the stylesheet body will work in Firefox. For IE, you need a workaround.

var ss1 = document.createElement('style');
var def = 'body {color: red;}';
ss1.setAttribute("type", "text/css");
ss1.styleSheet.cssText = def;
var hh1 = document.getElementsByTagName('head')[0];
hh1.appendChild(ss1);

Note that while in the SCRIPT case I took the liberty of skipping the type attribute, it's absolutely required here.

So with a bit of object sniffing, we can get a cross-browser solution:

var ss1 = document.createElement('style');
var def = 'body {color: red;}';
ss1.setAttribute("type", "text/css");
if (ss1.styleSheet) {   // IE
    ss1.styleSheet.cssText = def;
} else {                // the world
    var tt1 = document.createTextNode(def);
    ss1.appendChild(tt1);
}
var hh1 = document.getElementsByTagName('head')[0];
hh1.appendChild(ss1);
 

User stylesheet in IE

Saturday, January 20th, 2007

Let's say you want to quickly try out some small stylesheet changes, but you don't want to (or prefer not to, or for some reason temporarily you just can't) modify your application's CSS file(s). In FF it's easy - you have Firebug and you can play with styles until blue in the face. And in case you do get blue in the face and start making so many changes that you get lost, you can create a new clean and tidy CSS file, place it on your hard drive and use Web Developer extension to load it (Menu CSS->Add User Style Sheet). With WebDev Extension you can also Edit CSS right there, although unfortunatelly it's not always working when you have frames.

OK, there are options for Firefox. But how about IE?

In IE you have IE Developer Toolbar, definitelly helpful, but you can only modify element styles, not the stylesheet rules. So? A tiny little bookmarklet to the rescue!

My bookmarklet assumes you have a file called C:\user.css and loads this stylesheet on demand in your page, in every frame, just in case you use frames. Simple, yet useful, I hope. Here's the (readable) code:

javascript:
var css_file = prompt('Which CSS file you want to load today?','c:/user.css');
function addcss(w) {
    var html_doc = w.document.getElementsByTagName('head')[0];
    var css = w.document.createElement('link');
    css.setAttribute('rel', 'stylesheet');
    css.setAttribute('type', 'text/css');
    css.setAttribute('href', css_file);
    html_doc.appendChild(css);
}
var errors = 0;
function checkFrames(w) {
  if(w.frames && w.frames.length>0){
    for(var i=0;i<w.frames.length;i++){
      var fr=w.frames[i];
      try {
        addcss(fr);
      } catch (e) {
        errors++;
      }
      checkFrames(fr);
    }
  }
}
checkFrames(window);
addcss(window);
if (errors > 0) {
    alert('Could not access ' + errors + ' frame(s)');
}

To install and play around

Right-click this link and add it to your favourites:

Add User StyleSheet

Have in mind that this is IE-only (tested IE7). I don't think FF will allow you to access files on your local drive like this. But for FF you have the tools to do this anyway.

Another option to load local stylesheets in IE is to use the user CSS capability built in the browser, you can find it under Tools/Internet Options/Accessibility, but this will load your user CSS first (as opposed to last as the case is with my bookmarklet), so the "real" style definitions will overwrite yours, unless you always use !important and the "real" styles don't.

Thanks!

Have fun with the custom CSS and let me know how you find it.

 

Firebug console for IE

Wednesday, December 6th, 2006

Update: A better version of what I was trying to do is here. It works around the cross-domain permission problems in IE by not loading a page in the frame, but putting there the actual content.

Firebug - no words to describe how cool it is, really. After the recent new release (1.0. beta) the number of features is overwhelming. I for one can't live anymore without it, seriously.

One of the things I noticed on the website is the ability to use the Firebug console in other browsers than Firefox. I don't know if this existed before version 1.0 but if it did, it was the best kept secret. I am so addicted to the console in Firefox, I use it all the time to tweak a few things here and there when I'm working on a page. Recently I was looking for something similar for IE, but couldn't find it. Lo and behold, it was right under my nose.

So, here's the page that describes how to use Firebug in IE (and others). Basically you unzip the Firebug Lite files somewhere on your server and then you include firebug.js in your pages. But why stop there? And isn't it possible to avoid including this script on every page (and forgetting to remove once you're done, or removing it prematurelly since a page, just like a painting, is never really finished). Bookmarklets to the rescue!

I wanted to host the Firebug files on my hard-drive and then use a javascript dynamic include to load firebug.js via a bookmarklet. This way I would be able to load the firebug console every time I want it, on any page. Unfortunatelly IE's security policy won't allow it. Then?

Solution

The solution I came up with is:

  1. you copy the Firebug Lite files somewhere on your server
  2. you call a bookmarklet that will load firebug.js
  3. you hit F12 and you have a console!

This procedure has to be repeated for every domain you're working on, because of the security policy that won't allow cross-domain frame scripting. You can have one copy for your http://localhost and one for every domain. To ease the creation of bookmarklets that load firebug.js, I came up with a Firebug bookmarklet generator.

In action

  1. I copied Firebug Lite files (get the .zip) on this server (phpied.com), they are here.
  2. I (and you can try the same) generate a bookmarklet, using the bookmarklet tool
  3. Add the generated bookmarklet to the favorites
  4. Go to any page on phpied.com
  5. Click the new favorite
  6. Hit F12 to show/hide the console

Here's how (a readable version of) the generated code looks like:

javascript:(function(){
  var firebug_js = document.createElement('script');
  firebug_js.setAttribute('type', 'text/javascript');
  firebug_js.src = 'http%3A//www.phpied.com/files/firebug/firebug.js';
  document.getElementsByTagName('head')[0].appendChild(firebug_js);
  firebug_js.onreadystatechange = function () {
    if (firebug_js.readyState == 'complete') {
      console.open()
    }
  }
})()

Minor improvement to the console

The Firebug Lite console executes the code you type, but doesn't show it again when you use the up/down arrows, the way it does in Firefox. So I added this feature (copying from myself), you can replace the firebug.js you download with my version.

Not sold yet?

Here's a screenshot of the console in action, I used it to change my photo on the homepage.

firebug-ie-console.png

Go ahead, please

I strongly encourage everyone to try this out. Firebug is a beautiful thing and using even a bit of it in IE is great.