2
\$\begingroup\$

Here is the pertinent code:

index.html

<!--  DOM INITIALIZATION -->
<script type="text/javascript">
$().ready(function() {

getThemeInfo();

if (themeSelect==2) {
   ReplaceJSCSSFile("css/skin1.css", "css/skin2.css", "css");   // overwrite CSS
}

AJAX_LoadResponseIntoElement("skinContainer", "skin" + themeSelect + ".txt", function() {
    AJAX_LoadResponseIntoElement("contentdiv", "index.txt", initPage);
    });

});
</script>

funcs.js

function initPage()
{
    setContentDimensions();
    replaceCSSMenu();
    showContainer();
    setContentPositions();
}

function setContentPositions()
{
    var contentTop = findTop(document.getElementById('NavMenu')) + 4;
    var contentLeft = findLeft(document.getElementById('kwick1')) + 226;

    document.getElementById('contentdiv').style.top = (contentTop)+ "px";
}

Quick recap: It fetches the theme selection, and if it's not the default (1), then it changes the CSS file to skin2.css. Then, it fetches the page with AJAX and initializes it, and part of initialization is setting the div dimensions and positions.

Although the theme swap works perfectly through the button (code not shown here,) it does not work in Opera if the theme setting, stored in cookies, is a non-default theme, causing the CSS to be swapped during the loading of the page (i.e. this code here.) For whatever reason, the .top and .left of my "contentdiv," which is set in ContentPositions() function, is wrong.

I'd assumed this was happening because the CSS styles were not loaded prior to the JavaScript attempting to set contentdiv's position. To test this theory, I put an alert() in setContentPositions() to test that contentTop & contentTop were indeed wrong (they were,) and then another alert() after the DOM init line that changes the CSS file. With the addition of the alert() after the CSS change within DOM init, it loads perfectly.

Why is the CSS file not processed by the time it does two AJAX fetches? Is a callback function the proper way to fix this?

Edit...

The code for some of the functions used in the above code was requested. Here it is:

function ReplaceJSCSSFile(oldfilename, newfilename, filetype){
 var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none";
 var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none";
 var allElements=document.getElementsByTagName(targetelement);

 for (var i=allElements.length; i>=0; i--){
  if (allElements[i] && allElements[i].getAttribute(targetattr)!=null && allElements[i].getAttribute(targetattr).indexOf(oldfilename)!=-1){
   var newelement=CreateJSCSSFile(newfilename, filetype);
   allElements[i].parentNode.replaceChild(newelement, allElements[i]);
  }
 }
}

function CreateJSCSSFile(filename, filetype){
 if (filetype=="js"){
  var fileref=document.createElement('script');
  fileref.setAttribute("type","text/javascript");
  fileref.setAttribute("src", filename);
 }
 else if (filetype=="css"){
  var fileref=document.createElement("link");
  fileref.setAttribute("rel", "stylesheet");
  fileref.setAttribute("type", "text/css");
  fileref.setAttribute("href", filename);
 }
 return fileref;
}



function AJAX_LoadResponseIntoElement (elementId, fetchFileName, cfunc) {
  var XMLHRObj;
  if (window.XMLHttpRequest) { XMLHRObj=new XMLHttpRequest(); }
    else { XMLHRObj=new ActiveXObject("Microsoft.XMLHTTP"); }

  XMLHRObj.onreadystatechange=function()
    {
    if (XMLHRObj.readyState==4 && XMLHRObj.status==200)
      {
      document.getElementById(elementId).innerHTML=XMLHRObj.responseText;
      cfunc();
      }
    }
  XMLHRObj.open("GET",fetchFileName,true);
  XMLHRObj.send();
}
\$\endgroup\$
  • \$\begingroup\$ We are missing relevant details: please include the code of the functions used to fetch CSS from server. I noticed that script.readyState was not reliable in some versions of Opera: stackoverflow.com/questions/1929742/…. There might be something similar for CSS. \$\endgroup\$ – Eric Bréchemier Feb 13 '11 at 13:00
  • \$\begingroup\$ The CSS swap code has been added, along with the AJAX code. \$\endgroup\$ – Michael Feb 13 '11 at 13:39
1
\$\begingroup\$

I would suggest to take a different approach. It is complicated to get a callback for the complete loading of a CSS stylesheet loaded dynamically: see this Stack Overflow question for reference:

Is there anyway to listen to the onload event for a element?

Do not use JavaScript to set the content position: it is part of styling and should be done in CSS instead. Isn't the role of your CSS skins to modify the appearance of the page?

\$\endgroup\$
  • \$\begingroup\$ Hmmm... I suppose, in this case, it isn't needed since the position will be static. Good call. \$\endgroup\$ – Michael Feb 14 '11 at 13:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.