3

I'm running the following code in jQuery to dynamically load a stylesheet. Its purpose is to allow users to load a custom stylesheet and change the look of a JavaScript widget:

this.loadStyleSheet = function(url){
    $("<link rel='stylesheet' type='text/css' />").attr("href", url).appendTo("head");
}

For a split second the screen appears jumpy, since the correct style is applied to the widget only after the dynamic stylesheet is loaded. To solve this issue, I need to know when in fact the dynamic stylsheet has finished loading.

Although this issue has been discussed before, none of the solutions apply in my case:

  1. .load() only fires in IE, not in Firefox. A cross browser solution is required. BTW, .ready() fires off before the stylesheet has finished loading.
  2. .get() only works on the same domain. The stylesheet in my case may come from any given domain.
  3. Can't query for some CSS property to change via setTimeout. The user may point to any custom stylesheet, and there is no way to know what her CSS file will contain.
  4. Waiting for a constant time after loading the stylsheet via setTimeout is obviously a bad solution. There is no way to know in advance how long it will take the stylesheet to load, if it will load at all.

Any new ideas regarding this issue? Your help is much appreciated.

2
  • For now I found a somewhat dirty solution - moving the dynamic CSS load outside $(document).ready, leaving the rest of the code in $(document).ready. Therefore, the rest of the code executes only after the dynamic CSS is loaded. Still, I would love to hear if there is another solution. Commented Oct 20, 2010 at 10:20
  • I'm not really recommending this, but if you never find an answer.. you can still use the .get() method. Just have it pass the stylesheet URL to a php script on your domain, which gets the CSS, and returns it. Commented Oct 20, 2010 at 10:26

3 Answers 3

0

To expand on my comment above if anyone else needs an answer for this:

Your Javascript would look like this:

var style = $('<style type="text/css">');
$(document).append(style);
style.load('/fetchstyle.php', { url: "http://somesite.com/style.css" }, function() {
    // The styles are loaded
});

And the fetchstyle.php script would look like this:

<?php
echo file_get_contents($_GET['url']);

Untested, but the concept should work.

Sign up to request clarification or add additional context in comments.

1 Comment

It would probably work, but I'd be much happier with a client side only solution. Thanks anyway.
0

".load() only fires in IE, not in Firefox. A cross browser solution is required. BTW, .ready() fires off before the stylesheet has finished loading."

This is very strange, .load() works for me in firefox.

"Can't query for some CSS property to change via setTimeout. The user may point to any custom stylesheet, and there is no way to know what her CSS file will contain."

Although certainly not an ideal solution, why not require a certain string to be written into the comments of the css file which you could then regex for?

Other idea: Have you considered using propertychange event?

$(body).bind('propertychange', function(){ show_my_page_after_timeout(); });

This way you could hide the page elements that may change, allow the browser to process the css then show those elements (you could even fade out and in) when the processing is completed. You can do that by having a short timeout which is cancelled if the event handler (saying css property has changed) is called again before the timeout has showed your page.

6 Comments

.load() works for you in Firefox with the above code? It works in general, but when it comes to dynamically adding link tags to the header, it seems to break down.
yup ... just tested it again. One big problem though, is it won't work cross-domain, not allowed because of cross-domain restrictions (chrome & firefox) so that's a non-solution really. I think you will have to stick with binding the propertychange event handler to whatever elements are appropriate and hiding the content for the duration of the changes being applied. It's dirty though, but tbh the requirements themselves are dirty. People should load their stylesheets from the domain the rest of the page comes from, why would you want it any other way?!
Well, as I mentioned shortly the whole bulk of the code I'm writing is a JavaScript widget that users will be able to embed on any site. My client doesn't want to have a custom stylesheet upload service, instead they want to grab a custom stylesheet from any given location. Does that make sense?
"JavaScript widget that users will be able to embed on any site. My client doesn't want to have a custom stylesheet upload service" It does make sense, but surely if they can add the widget then they can also add their own custom css? For example, you could load ./thewidget.css (with option to change path) then user could put their custom css wherever they want within their webroot. What situations of widget use/deployment would this not work with? How is it harder for the widget user?
I was curious and so did some digging. Have you come across YQL? net.tutsplus.com/tutorials/javascript-ajax/… I haven't used it myself, but it definitely seems like it could solve your problem if your client insists the css must be uploadable from anywhere. Good luck! ;-)
|
0

I've recently ran into the same problem. My solution is to hold the ready event and release it after the css page loads. I used the $.holdReady jQuery command outside the document.ready code. So, how can you fire an event on css load? I used the onload command on the link tag. Code:

$.holdReady(true);

$('head').append($('<link rel="stylesheet" type="text/css" 
    onload="$.holdReady(false)"/>').attr('href','myCSS.css'));


$(document).ready(function() {
    ...code here to execute after css loads
})

It works in FF 16. Haven't checked in different versions or browsers. Also, i think that the onload event on the link tag is purely HTML5.

1 Comment

This is an ingenious solution. I didn't even know about holdReady. Unfortunately, it didn't work in Chrome. For whatever reason, the hold is lifted before the stylesheet is actually loaded. Thanks, though for pointing me in the direction of holdReady.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.