PDA

View Full Version : Element.update() && styles



vtswingkid
29 Nov 2006, 8:28 AM
I find that IE will not dynamically load styles into the body when innerHTML is used.

Can we add this code or something similar to the end of the update function?


if(YAHOO.ext.util.Browser.isIE /* || YAHOO.ext.util.Browser.isIE7 */){
var re = /(?:<style>)((\n|\r|.)*?)(?:</style>)/img;
var match;
while(match = re.exec(html)){
if(match[1] && (match[1].length != 0)){
var st=document.createElement("style");
st.setAttribute("type", "text/css");
st.styleSheet.cssText=match[1];
dom.appendChild(st);
}
}
}

I am not certain but this may apply to IE7. Can someone test it?

Animal
29 Nov 2006, 8:39 AM
Your stylesheet provides an overall, "house" style.

It should be in the main document header with no need for dynamically loaded style elements.

jbowman
29 Nov 2006, 9:54 AM
document.getElementByTagName('head')[0].appendChild();


will become one of your best friends if you're doing dynamic stylesheet creation :)

vtswingkid
29 Nov 2006, 9:56 AM
I find advantages to dynamic style sheets. Less delay on the front end with loading. Users may have unique style sheets. If you added an id option into the code you could replace pre-existing css. There are plenty of reasons.

vtswingkid
29 Nov 2006, 9:57 AM
the head might be a better place to insert the styles. I just followed the DOM tree of firefox, netscape, and opera.

jbowman
29 Nov 2006, 12:57 PM
I'm in the crowd of dynamically loading javascript and css. The head just seems to be the best place to plop the stylesheets, as the browsers I've tested have then applied it to the view.

vtswingkid
30 Nov 2006, 7:19 AM
Here is my Element.update replacement...
It loads styles into the header for all browsers.
It removes the attached span element when it is finished.
Might want to add code to create Ids for the style tags if Ids are provided.

I have tested this using multiple style and script tags within html with the following browsers:
IE 6.0.2800.1106
Firefox 1.5.0.8
Netscape 8.1.2
Opera 9.0.2



YAHOO.ext.Element.prototype.update = function(html, loadScripts, callback){
if(typeof html == 'undefined'){
html = '';
}

//load styles into the header
var r = /(?:<style>)((\n|\r|.)*?)(?:</style>)/img;
var m;
while(m = r.exec(html)){
if(m[1] && (m[1].length != 0)){
var s=document.createElement("style");
s.setAttribute("type", "text/css");
if(s.styleSheet)s.styleSheet.cssText=m[1]; //IE
else s.appendChild(document.createTextNode(m[1])); //W3C
document.getElementsByTagName("head")[0].appendChild(s);
}
}
html=html.replace(/(?:<style>)((\n|\r|.)*?)(?:</style>)/img, '');

if(loadScripts !== true){
this.dom.innerHTML = html;
if(typeof callback == 'function'){
callback();
}
return this;
}
var id = YAHOO.util.Dom.generateId();
var dom = this.dom;

html += '<span></span>';

YAHOO.util.Event.onAvailable(id, function(){
var hd = document.getElementsByTagName("head")[0];
var re = /(?:<script>)((\n|\r|.)*?)(?:</script>)/img;
var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
var match;
while(match = re.exec(html)){
var srcMatch = match[0].match(srcRe);
if(srcMatch && srcMatch[1]){
var s0 = document.createElement("script");
s0.src = srcMatch[1];
hd.appendChild(s0);
}else if(match[1] && (match[1].length != 0)){
eval(match[1]);
}
}
var el = document.getElementById(id);
if(el){el.parentNode.removeChild(el);}
getEl(id).remove(); //remove the added span element
if(typeof callback == 'function'){
callback();
}
});
dom.innerHTML = html.replace(/(?:<script>)((\n|\r|.)*?)(?:</script>)/img, '');
return this;
};

jack.slocum
30 Nov 2006, 7:25 AM
The problem is this is executed every time you do an update, even when you don't want to process stylesheets.

The 2nd thing, as Animal said, stylesheets should loaded inline with the document. There's no advantage to loading them through XHR. Is there any reason you have to load them through XHR?

vtswingkid
30 Nov 2006, 7:26 AM
Here is my Element.update replacement...
It loads styles into the header for all browsers.
It removes the attached span element when it is finished.
Might want to add code to create Ids for the style tags if Ids are provided.

I have tested this using multiple style and script tags within html with the following browsers:
IE 6.0.2800.1106
Firefox 1.5.0.8
Netscape 8.1.2
Opera 9.0.2



YAHOO.ext.Element.prototype.update = function(html, loadScripts, callback){
if(typeof html == 'undefined'){
html = '';
}

//load styles into the header
var r = /(?:<style>)((\n|\r|.)*?)(?:</style>)/img;
var m;
while(m = r.exec(html)){
if(m[1] && (m[1].length != 0)){
var s=document.createElement("style");
s.setAttribute("type", "text/css");
if(s.styleSheet)s.styleSheet.cssText=m[1]; //IE
else s.appendChild(document.createTextNode(m[1])); //W3C
document.getElementsByTagName("head")[0].appendChild(s);
}
}
html=html.replace(/(?:<style>)((\n|\r|.)*?)(?:</style>)/img, '');

if(loadScripts !== true){
this.dom.innerHTML = html;
if(typeof callback == 'function'){
callback();
}
return this;
}
var id = YAHOO.util.Dom.generateId();
var dom = this.dom;

html += '<span></span>';

YAHOO.util.Event.onAvailable(id, function(){
var hd = document.getElementsByTagName("head")[0];
var re = /(?:<script>)((\n|\r|.)*?)(?:</script>)/img;
var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
var match;
while(match = re.exec(html)){
var srcMatch = match[0].match(srcRe);
if(srcMatch && srcMatch[1]){
var s0 = document.createElement("script");
s0.src = srcMatch[1];
hd.appendChild(s0);
}else if(match[1] && (match[1].length != 0)){
eval(match[1]);
}
}
var el = document.getElementById(id);
if(el){el.parentNode.removeChild(el);}
getEl(id).remove(); //remove the added span element
if(typeof callback == 'function'){
callback();
}
});
dom.innerHTML = html.replace(/(?:<script>)((\n|\r|.)*?)(?:</script>)/img, '');
return this;
};

vtswingkid
30 Nov 2006, 8:22 AM
Too keep things simple...
My styles are created dynamically by and outside program, so I need to be able to load them on the fly. I may be the only one this crazy. If not maybe the style loading should come after the loadscripts variable so that by default it is not done.

Also, the getEl(id).remove() line is probably not a good idea. Safer to leave the span in there in case something else removes it first.

Animal
30 Nov 2006, 9:21 AM
If style rules are created dynamically depending on who's logged in and stuff, just have a servlet (or whatever technology you use.. PHP??? in the server) create the data stream, so in the head you'd have



<link rel="stylesheet" href="mystyle.php" type="text/css" />

vtswingkid
21 Jun 2007, 5:29 AM
I ended up dumping the dynamic style loading a while back.

I am revisiting this for the sake of MS createStyleSheet limits (30) mentioned in this thread:
http://extjs.com/forum/showthread.php?t=6958&highlight=createStyleSheet

Maybe this could provide a work around for us 1.1 users. Will let you know what I come up with.