开发者

Javascript Bookmarklet fails in IE8

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='*{te开发者_运维问答xt-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)
  }
}
)()


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)}})()


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜