3

Our web application started out as a big, honkin' ASP.NET AJAX 'page' with oodles of controls on it. They all shared a small set of large .js and .css files. I need to use some of these controls in other, unrelated pages around our site. The difficulty is in all the other stuff the .css and .js files bring along with them when I try to use those controls elsewhere - too much and there's a lot of bloat, too little and the controls don't work.

So, I've been experimenting with breaking up the .css and .js and writing the controls to register the .js and .css they need. Initially I will end up with many more but smaller .js and .css files, but I can combine them at run-time later. I just want to encapsulate these controls so the pages that use them know less about what it takes to use them.

But I am running into a problem. I am using OnInit or OnLoad to register the .css and .js as needed. Unfortunately, none of these methods is called if the control is not visible the first time you hit the page when all the .css and .js needs to make its way to the client. It isn't until later on that the controls are enabled for thier specific functions that they are visible and could emit the .js or .css. Then it's too late!

Do I have to bite the bullet and hand-include the right .css/.js on the pages I use these controls on, or is there a better way to 'inventory' the controls in use to get them to emit what they need?

n8wrl
  • 19,439
  • 4
  • 63
  • 103
  • How do you "register the .css and .js as needed"? – Dave Thieben Jul 09 '10 at 21:02
  • @dave: For .js I use a variation of Page.ClientScript.RegisterScriptInclude. I cooked up something similar called RegisterStyleSheetInclude that looks for – n8wrl Jul 12 '10 at 11:31

2 Answers2

1

You may be able to include the js and css files in with the rendering for the controls that you are using. Basically adding them into the first line of the html that is generated by the control. I know you should be able to put in the include for the js files anywhere in the html, although I've yet to try it out with the css files.

If that works, you may want to put in some logic to make sure that the files are only included once if you have more than one of those controls. This shouldn't be too hard to do at the javascript level.

I'd be interested to see what you get working, because I've been looking at doing something similiar where I'm currently working.

mwgriffith
  • 550
  • 3
  • 6
  • Chris F hit the nail on the head - my problem isn't controls that are not visible, it is controls that aren't instantiated yet. The control in question is in a repeater template so there's nothing to initialize when the page first loads. I suspect the .js problem is easier to solve than .css. – n8wrl Jul 13 '10 at 11:37
  • You might be able to get away with just loading all of the css up in one file and let the browser cache it. You would have a 1 time load penalty, but if you configure your expires heading correctly for the css file it should be a penalty that isn't repeated very often. – mwgriffith Jul 13 '10 at 12:24
1

I assume that the problem you are facing is that some controls are loaded dynamically (i.e. in an update panel). It is a tricky problem - usually because you don't know in advance what controls you will need and thus what JS + CSS to include.

Perhaps you should consider loading the JS and CSS dynamically using a script loader?
The YUI script loader and the new MS one spring to mind (but I am sure that there are dozens of other equally good ones out there).

See this previous answer for a couple of potentially useful links. Also see here for more about the MS script loader and YUI scriptloader.

Being that you are already using MS stuff I would recommend the MS script loader but as far as I know, the MS script loader does not support managing your dynamically loaded CSS (if anyone knows different please correct me) and so maybe the YUI solution might be more suitable (or maybe you can roll your own way of dynamically adding CSS if it has not already been added - it shouldn't be too hard).

Using a script loader removes the headache of working out up front what you need to include but it may require some changes to your javascript. In particular, if you have any javascript inline in your control's markup that relies on functions declared in the javascript you are dynamically adding.

E.g. If you current have user control markup like this

  <div id="my control">
    <script type="text/javascript>
      foo(); // foo is defined in foo.js, which is included in a script element in the head
      ... more script ...
    </script>
    ....
  </div>

Then using a script loader you must change it to look like this

  <div id="my control">

    <script type="text/javascript>
      var onLoadHandler = function() {
        foo();
        ... more script ...
      };
      Sys.loader.registerScript("foo_package_name", null, onLoadHandler); 
    </script>
  </div>
Community
  • 1
  • 1
Chris Fewtrell
  • 7,555
  • 8
  • 45
  • 63
  • Your comment about loading controls dynamically rang a bell. I did some more testing and you are right - ASP.NET fires OnInit for a control even if it's not visible. In this case, my control is instantiated as content in a repeater so the first time I hit the page there are no controls to Init. – n8wrl Jul 12 '10 at 12:14