views:

476

answers:

2

Anyone want to take a stab at why this bookmarklet fails in IE8? It turns all text uppercase in Friefox and Safari. But in IE8, it simply stalls with "loading..." I've enabled running scriplets and lowered javascript security settings in IE8.

Update 3/19/10: This bookmarklet now works in IE, thanks to sergey.

javascript:
(function(){
  var i,t,D=document,h,f,g=D.getElementsByTagName,ce=D.createElement,c=D.createStyleSheet,ac='appendChild',cn='childNodes',l,s='*{text-transform:uppercase}input,textarea{text-transform:none}';
  for(i=0;t=document.getElementsByTagName('textarea')[i];i++)
    t.value=t.value.toUpperCase();
  if(D.namespaces){
    h=g('head')[0];
    f=h[ac](ce('div'));
    f.innerHTML='b<style type=\'text/css\'>'+s+'</style>';
    h[ac](f[cn][1]);
    f.parentNode.removeChild(f);
  }
  else
    if(c){
      c('javascript:\''+s+'\'')
    }
  else{
    l=document.createElement('link');
    l.rel='stylesheet';
    l.href='data:text/css,'+escape(s);
    D.documentElement[cn][0][ac](l)
  }
}
)()
+1  A: 

For reference, this is the "unminified" code:

javascript:(function () {
var i, t, D = document;
for (i = 0; t = D.getElementsByTagName('textarea')[i]; ++i) {
    t.value = t.value.toUpperCase();
    var newSS, styles = '* { text-transform: uppercase; } input, textarea { text-transform: none}';
    if (D.createStyleSheet) {
        D.createStyleSheet("javascript:'" + styles + "'");
    } else {
        newSS = D.createElement('link');
        newSS.rel = 'stylesheet';
        newSS.href = 'data:text/css,' + escape(styles);
        D.documentElement.childNodes[0].appendChild(newSS);
    }
}
})()

I do not have IE 8 handy on my Mac, but try sprinkling in an alert('here at line XXX'); for poor man's debugging.

Maybe IE 8 does not like a javascript: source for the style sheet?

Also, the loop is adding as many style sheets as there are textareas. That is silly. Move it out of the loop, like so:

javascript:(function () {
var i, t, D = document;
for (i = 0; t = D.getElementsByTagName('textarea')[i]; ++i) {
    t.value = t.value.toUpperCase();
}
var styles = '* { text-transform: uppercase; } input, textarea { text-transform: none}';
if (D.createStyleSheet) {
    D.createStyleSheet("javascript:'" + styles + "'");
} else {
    var newSS = D.createElement('link');
    newSS.rel = 'stylesheet';
    newSS.href = 'data:text/css,' + escape(styles);
    D.documentElement.childNodes[0].appendChild(newSS);
}
})()

There are still some questionable things in that code, mind you. I am not too sure of that loop's condition. What I would do, is get it out of the loop, like this:

javascript:(function () {
var D = document;
var i, t = D.getElementsByTagName('textarea');
for (i = 0; i < t.length; i++) {
    t[i].value = t[i].value.toUpperCase();
}
/* Rest of the code here. */
})()

As an exercise to the reader/asker: this only uppercases textareas, not text inputs.

EDIT: Minify this to stay below the maximum length:

javascript:(function () {
var D = document;
var i, t = D.getElementsByTagName('textarea');
for (i = 0; i < t.length; i++) {
    t[i].value = t[i].value.toUpperCase();
}
D.createStyleSheet('javascript:"* { text-transform: uppercase; } input, textarea { text-transform: none}"');
})()

Result:

javascript:(function(){var D = document;var i,t=D.getElementsByTagName('textarea');for(i=0;i<t.length;i++)t[i].value=t[i].value.toUpperCase();D.createStyleSheet('javascript:"*{text-transform:uppercase;}input,textarea{text-transform:none}"');})()

This only has the IE-specific code.

janmoesen
I really appreciate all the work, but something broke along the way, as now, none of the examples work in Safari or Firefox. I tried minifi-ing them with no luck.
songdogtech
My bad, I had deleted the anonymous function's closing brace. I edited my post.
janmoesen
Also: egads, what on earth would you want this effect for? It's like the whole Internet is shouting! :-)
janmoesen
Cool, that works in Safari and Firefox now, and I should have seen that lost brace. But still get the "Loading..." thing in IE. Yea, it's annoying, but it's for someone who is sight impaired, and all caps is a little easier for them to read.
songdogtech
Actualy, the bookmarklet gets truncated by IE. I'm looking more at it right now...
songdogtech
Just found out that IE has a limit on the overall data length of Favorites - and as a result, bookmarklets - so I have to find a work around for that....
songdogtech
I added a smaller IE-only version. That is as far as I will take it, though. :-)
janmoesen
Jan, I run all of your code snippets and they did not work as supposed in any of IE versions. See the working version in my answer.
Sergey Ilinsky
Jan, Thanks much for your help. IE no longer truncates the bookmarklet, but I still get the "loading..." situation.
songdogtech
@Sergey: that'll teach me for trying to tackle IE without IE. :-)@songdogtech: try Sergey's code. It will need minifying, though.
janmoesen
+1  A: 

Small addition to your code will do the trick:

javascript:(function(){
   var i,t,D=document;
  for(i=0;t=D.getElementsByTagName('textarea')[i];++i)
    t.value=t.value.toUpperCase();
   var newSS,styles='*{text-transform:uppercase}input,textarea{text-transform:none}';
  if (document.namespaces) {
    var head = document.getElementsByTagName("head")[0];
    var factory = head.appendChild(document.createElement("div"));
    factory.innerHTML = '&nbsp;<style type=\'text/css\'>' + styles + '</style>';
    head.appendChild(factory.childNodes[1]);
    factory.parentNode.removeChild(factory);
  }
  else
  if(D.createStyleSheet){
    D.createStyleSheet("javascript:'"+styles+"'");
  }
  else{
    newSS=D.createElement('link');
    newSS.rel='stylesheet';
    newSS.href='data:text/css,'+escape(styles);
    D.documentElement.childNodes[0].appendChild(newSS);
  }
}
)()

Update 17/03/10: I minified the code, created a bookmarklet out of and successfully used it in IE.

Update 18/03/10: I noticed the minified code did not run in other than IE browsers, here is the tested version:

javascript:(function(){var i,t,D=document,h,f,g=D.getElementsByTagName,ce=D.createElement,c=D.createStyleSheet,ac='appendChild',cn='childNodes',l,s='*{text-transform:uppercase}input,textarea{text-transform:none}';for(i=0;t=document.getElementsByTagName('textarea')[i];i++)t.value=t.value.toUpperCase();if(D.namespaces){h=g('head')[0];f=h[ac](ce('div'));f.innerHTML='b<style type=\'text/css\'>'+s+'</style>';h[ac](f[cn][1]);f.parentNode.removeChild(f);}else if(c){c('javascript:\''+s+'\'')}else{l=document.createElement('link');l.rel='stylesheet';l.href='data:text/css,'+escape(s);D.documentElement[cn][0][ac](l)}})()
Sergey Ilinsky
IE doesn't truncate this code, but I still get the "Loading..." situtation. I'm testing under IE8 with medium security settings. This does work under Windows Firefox.
songdogtech
This code does works in IE8 and capitalizes entire page contents. I don't know how to help more than providing a working solution...
Sergey Ilinsky
Still don't know what I'm doing wrong. I minify it and replace the `"` with `%22` and IE8 isn't truncating the code anymore, so it should work.
songdogtech
See update from 17/03/10. Copy/paste minified code and see it working.
Sergey Ilinsky
I have no idea what I'm doing wrong... I had to html encode a < and a > to keep Wordpress from inserting a `<br />`, but my page source and the source of the favorite under IE are the same. Still no luck. The bookmarklet is here: http://markratledge.com/code/
songdogtech
Your wordpress thingy: 1) replaces   sign with " " (empty string) -> resolve the issue by changing " " to a letter, for example "a" 2) it replaces some of the single qoutes ' with alternative single qoutes ‘. Here you see the piece of code corrupted: f.innerHTML=' <style type=\'text/css\'>‘+s+’</style>' (note: some single quotes and   replaced) Fixing problems with your Wordpress is definetly a topic for another thread.
Sergey Ilinsky
Yes, in the snippet I inserted here you do not see a difference between different single quotes, but if you inspect the same fragment on your page, you will indeed notice it.
Sergey Ilinsky
Yes, Wordpress can be a pain in arse when it comes to code and character entities. I had some of the character encoding correct, but not all. I ended up using a page template without the Wordpress "Loop" and that solved the problem. The bookmarklet works great; thanks for all the help!
songdogtech