molily: style-Element erzeugen per Script

Beitrag lesen

Ein umfassendes Beispiel, das die verschiedenen Möglichkeiten erläutert:

  
function addStyle (selector, declarations) {  
 if (document.styleSheets && document.styleSheets.length > 0) {  
  // alert("use styleSheets[0]");  
  if (document.styleSheets[0].insertRule) {  
   new_rule_number = document.styleSheets[0].insertRule(selector + " {" + declarations + "}", document.styleSheets[0].cssRules.length);  
   if (document.styleSheets[0].cssRules[new_rule_number].cssText.length > 0) {  
    alert("added with styleSheets[0].insertRule");  
    return true;  
   } else {  
    alert("styleSheets[0].insertRule failed - using Konqueror?");  
   }  
  } else if (document.styleSheets[0].addRule) {  
   document.styleSheets[0].addRule(selector, declarations);  
   alert("added with styleSheets[0].addRule");  
   return true;  
  }  
 }  
 if (document.createStyleSheet) {  
  // alert("use createStyleSheet");  
  var stylesheet = document.createStyleSheet();  
  if (stylesheet && stylesheet.addRule) {  
   stylesheet.addRule(selector, declarations);  
   alert("added with createStyleSheet / addRule");  
   return true;  
  }  
 }  
 if (document.createProcessingInstruction && document.insertBefore) {  
  //alert("use createProcessingInstruction");  
  var inserted_node;  
  try {  
   var pi = document.createProcessingInstruction("xml-stylesheet", "type='text/css' href='test.css'");  
   inserted_node = document.insertBefore(pi, document.documentElement);  
  } catch (e) {  
   alert("failed adding with createProcessingInstruction. probably not an XHTML document");  
  }  
  if (pi && inserted_node && pi.sheet) {  
    alert("delay necessary");  
    pi.sheet.insertRule(selector + " {" + declarations + "}", 0);  
    alert("added with createProcessingInstruction / insertRule");  
    return true;  
  }  
 }  
 if (document.getElementsByTagName && document.getElementsByTagName("style").length > 0) {  
  // alert("use getElementsByTagName / appendChild");  
  var style_elements = document.getElementsByTagName("style");  
  var text_node = document.createTextNode(selector + " {" + declarations + "}");  
  style_elements[style_elements.length - 1].appendChild(text_node);  
  alert("added with getElementsByTagName / appendChild");  
  return true;  
 }  
 if (document.getElementsByTagName && document.createElement) {  
  // alert("use createElement / appendChild");  
  var style_element = document.createElement("style");  
  style_element.setAttribute("type", "text/css");  
  var text_node = document.createTextNode(selector + " {" + declarations + "}");  
  style_element.appendChild(text_node);  
  var head_elements = document.getElementsByTagName("head");  
  if (head_elements && head_elements.length == 1) {  
   head_elements[0].appendChild(style_element);  
   alert("added with createElement / appendChild");  
   return true;  
  }  
 }  
 return false;  
}  

Leider funktioniert die DOM-2-CSS-Variante nicht im Konqueror 3.4, weil es insertRule dort zwar gibt, er aber schlichtweg nichts tut, also die Regel nicht anwendet. Sogar cssRules.length wird erhöht. Man kann nur an einem Punkt sehen, dass die Regel nicht eingefügt wird: cssText der neu erzeugten Rule ist leer (String mit Länge 0). Ansonsten stimmt aus der Sicht von document.styleSheets alles (selectorText, rule.style.cssText, rule.style[X], rule.style.getPropertyValue(rule.style[X])). Aus der Sicht des Elementenbaums sieht man, dass sich der Inhalt des style-Elements nicht ändert.

Der Test mit dem Einfügen der Processing Instruction sollte auch bei XML-Dokumenten funktionieren, die nicht XHTML sind. Und es sollte der bevorzugte Weg bei XHTML sein, aber Mozilla braucht eine kleine Verzögerung zwischen dem Einfügen der PI und dem insertRule, ansonsten bricht er mit einer DOM-Exception ab. Opera kann auch createProcessingInstruction fälschlicherweise im HTML-Modus, aber kann DOM 2 CSS (pi.sheet). Konqueror löst eine DOM-Exception nicht beim createProcessingInstruction, aber beim insertBefore darauf aus (HIERARCHY_REQUEST_ERR) - sowohl in HTML- als auch in echten X(H)TML-Dokumenten.

Mathias