style-Element erzeugen per Script
MudGuard
- javascript
Hi,
ich versuche, ein style-Element per Javascript zu erzeugen.
var colors = new Array( "red", "blue", "yellow", "green", "teal", "fuchsia", "silver", "gold" );
function restyle()
{
var col = colors[Math.floor(Math.random() * colors.length)];
var mytext = "body { background-color: " + col + "; }";
var textNode = document.createTextNode(mytext);
var headElem = document.documentElement.firstChild;
var styleElem = document.createElement("style");
styleElem.setAttribute("type", "text/css");
styleElem.appendChild(textNode); //hier krachts im IE
headElem.appendChild(styleElem); //hier krachts im IE
}
Das funktioniert in Opera 7.53 und 8.01 sowie in Geckos FF 1.0.6 und Moz 1.7.3 wunderbar.
Im IE bekomme ich beim Einhängen des style-Elements in den Head oder beim Einhängen des Textknotens in das style-Element (je nachdem, welche der beiden Aktionen zuerst stattfinden) eine Fehlermeldung:
Fehler: Unerwarteter Aufruf oder Zugriff
Wie kann ich das im IE hinbekommen?
Da im Echt-Einsatz User-Eingaben in das Stylesheet mit reinsollen (anstelle der jetzt nur zufällig gesetzten Farbe), kann ich das style-Element nicht beim Seitenaufbau per document.write schreiben.
headElem und styleElem enthalten die korrekten Elemente, das hab ich schon überprüft.
cu,
Andreas
Tag MudGuard.
ich versuche, ein style-Element per Javascript zu erzeugen.
[...]
Im IE bekomme ich beim Einhängen des style-Elements in den Head oder beim Einhängen des Textknotens in das style-Element (je nachdem, welche der beiden Aktionen zuerst stattfinden) eine Fehlermeldung:
Wenn ich das MSDN richtig lese, kannst du appendChild nicht auf ein style-Element anwenden:
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/appendchild.asp
(unter "Applies To", da ist style nicht aufgeführt)
Mit einem (hier völlig schwachsinnigen) DIV geht's. Du wirst wohl das style-Objekt verwenden müssen.
Siechfred
Hi,
Wenn ich das MSDN richtig lese, kannst du appendChild nicht auf ein style-Element anwenden:
Was für ein Schwachsinn.
Wie kommen die auf die saudumme Idee, style-Elemente hier anders als andere Elemente zu behandeln?
Mit einem (hier völlig schwachsinnigen) DIV geht's. Du wirst wohl das style-Objekt verwenden müssen.
style-Objekt? Du meinst, für jedes Element, das durch einen der Selektoren ggf. betroffen ist, einzeln sämtliche Eigenschaften setzen?
Sozusagen das ganze Parsen des HTML-Baums sowie des Stylesheets nochmal nachprogrammieren?
cu,
Andreas
Hallo Andreas,
es könnte auch mit der Reihenfolge von setAttribute()-Methode und Einhängen in den Elementbaum zu tun haben.
http://forum.de.selfhtml.org/archiv/2005/7/t111727/#m704488
Gruß Gernot
Hi,
es könnte auch mit der Reihenfolge von setAttribute()-Methode und Einhängen in den Elementbaum zu tun haben.
hat es in diesem Fall aber nicht.
Egal ob mit oder ohne Attribut, egal ob Attribut am Anfang nach dem Kreieren des style-Elements oder nach dessen Einhängen in den head oder wann auch immer, es geht nicht.
mit innerHTML oder innerText statt appendChild() krieg ich es auch nicht hin, gibt auch jeweils so detaillierte Fehlermeldungen wie die erwähnte oder
Unbekannter Laufzeitfehler
Drecksbrowser!
cu,
Andreas
Hallo,
Du meinst, für jedes Element, das durch einen der Selektoren ggf. betroffen ist, einzeln sämtliche Eigenschaften setzen?
Sozusagen das ganze Parsen des HTML-Baums sowie des Stylesheets nochmal nachprogrammieren?
In dem Fall nähme man http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/addrule.asp, mit dem man direkt eine CSS-Regel setzen kann.
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/createstylesheet.asp
http://www.styleassistant.de/tips/tip20.htm
http://www.styleassistant.de/tips/beispiel20.htm
Mathias
P.S. Gecko kann das auch (nur anders, weil standardkonform), das Ganze nennt sich DOM 2 Style bzw. CSS. Speziell insertRule, wobei Gecko kein createStylesheet kennt, in DOM 2 Style ist das anders geregelt, dort muss man style- bzw. link-Elemente einfügen.
Wenn aber schon ein Stylesheet eingebungen ist, kann man dem eine Regel hinzufügen, somit fällt createStylesheet und createElement weg.
Opera ist also derjenige, der einer Extrawurst bedarf. :)
Mathias
Hi,
Opera ist also derjenige, der einer Extrawurst bedarf. :)
Meine Rede!
Gruß, Cybaer
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
Hi,
(irgendwie ist meine Antwort von gestern nachmittag verschwunden ...)
P.S. Gecko kann das auch (nur anders, weil standardkonform)
Das hieße, daß es im Code 2 Zweige gäbe - einmal für Geckos, einmal für IE.
Opera ist also derjenige, der einer Extrawurst bedarf. :)
Also 3 Wege.
Super. Und das nur, weil der IE zu dämlich ist, einem Element einen Textknoten hinzuzufügen.
cu,
Andreas
Hi,
Das hieße, daß es im Code 2 Zweige gäbe - einmal für Geckos, einmal für IE.
Ja, aber prinzipiell identisch, nur mit etwas anderer Syntax. Das ist leicht zu handhaben.
Super. Und das nur, weil der IE zu dämlich ist, einem Element einen Textknoten hinzuzufügen.
Nur weil der Opera zu dumm ist, dafür die DOM-Funktionen bereitzustellen, die dafür gedacht sind. Wieso gibt es die denn, wenn man es ohnehin mit "Standardmitteln" erledigen sollte? ;-)
Gruß, Cybaer
PS: Natürlich ärgerlich, daß sich W3C- & MS-Syntax unterscheiden, aber in diesem Fall war wohl MS diejenigen, die das innovativ und zuerst umgesetzt haben ...
Tag MudGuard.
style-Objekt? Du meinst, für jedes Element, das durch einen der Selektoren ggf. betroffen ist, einzeln sämtliche Eigenschaften setzen?
Ähm, ich dachte, dass es nur um das body-Element geht, da täte es ein
document.getElementsByTagName('body')[0].style.backgroundColor = deineFarbe
auch. Ansonsten ist natürlich molilys Vorschlag der bessere Weg.
Siechfred
Hallo,
Ähm, ich dachte, dass es nur um das body-Element geht, da täte es ein
document.getElementsByTagName('body')[0].style.backgroundColor = deineFarbe
Ich werde nie verstehen, warum man getElementsByTagName benutzt, um das body-Element anzusprechen - es gibt ja document.body. ;)
Mathias
Hi,
Ich werde nie verstehen, warum man getElementsByTagName benutzt, um das body-Element anzusprechen - es gibt ja document.body. ;)
Einheitliche Syntax! :-)
Gruß, Cybaer
hi,
Du wirst wohl das style-Objekt verwenden müssen.
das wird aber vermutlich recht unkomfortabel, sobald damit nicht nur spezielle elemente formatierungen erhalten sollen, sondern beispielsweise auch css-klassen dynamisch hinzugefügt werden sollen.
vielleicht wäre dafür innerHTML eine alternative - da steht nämlich unter applies to auch style aufgeführt.
(bei innerText komischerweise wieder nicht; dabei enthält <style> als kindelement doch lediglich einen textknoten, aber kein weiteres HTML. das ist wohl wieder mal eine der stellen, an denen man microsoft nicht verstehen muss ...)
gruß,
wahsaga
Hi,
das wird aber vermutlich recht unkomfortabel, sobald damit nicht nur spezielle elemente formatierungen erhalten sollen, sondern beispielsweise auch css-klassen dynamisch hinzugefügt werden sollen.
richtig.
vielleicht wäre dafür innerHTML eine alternative - da steht nämlich unter applies to auch style aufgeführt.
Nein. Steht auch dort, weiter oben im Text: für style (und ein paar andere) readonly.
(bei innerText komischerweise wieder nicht; dabei
enthält <style> als kindelement doch lediglich einen textknoten, aber kein weiteres HTML. das ist wohl wieder mal eine der stellen, an denen man microsoft nicht verstehen muss ...)
Mit innerText geht es (ausprobiert) genausowenig wie mit innerHTML.
cu,
Andreas
Hallo Andreas,
Das funktioniert in Opera 7.53 und 8.01
würde mich jetzt nur mal interessieren, ob Du im Opera auch eine Auswirkung erzielst - und wenn ja, wie. _Genau_ das Gleiche hab ich nämlich auch schon vergeblich versucht und im OP keine Reaktion. Dein Script funktioniert auch nur in meinem FF. Übrigens kann man im IE etwas erreichen, wenn man das StyleSheet einfach im Body einsetzt, ist halt IE ;-)
Ich habe von solchem Unfug erstmal Abstand genommen und erledige momentan alles über Styleobjekte der HTML-Nodes. Das ist natürlich erheblich aufwändiger, funktioniert aber in IE, FF und OP.
Gruß, Andreas
Hi,
Das funktioniert in Opera 7.53 und 8.01
würde mich jetzt nur mal interessieren, ob Du im Opera auch eine Auswirkung erzielst -
Das steht doch da, daß es funktioniert.
Würde es keine Auswirkung haben, würde ich nicht von "funktioniert" sprechen.
und wenn ja, wie.
Genau mit der genannten Funktion. Dazu im body noch ein <input type="button" onclick="restyle()">. Fertig.
Gerade nochmal hier zu Hause ausprobiert.
_Genau_ das Gleiche hab ich nämlich auch schon vergeblich versucht und im OP keine Reaktion. Dein Script funktioniert auch nur in meinem FF.
Ist in Deinem Opera Javascript deaktiviert?
Übrigens kann man im IE etwas erreichen, wenn man das StyleSheet einfach im Body einsetzt, ist halt IE ;-)
Pervers.
Funktioniert aber bei mir nicht.
Wenn ich headElem in meinem Script statt mit document.documentElement.firstChild auf document.body setze, bekomme ich dieselben Laufzeitfehler, jeweils beim Versuch, den Text bzw. Textnode ins style-Element reinzubekommen.
cu,
Andreas
Ist in Deinem Opera Javascript deaktiviert?
jaja, und mein Rechner war abgeschaltet ;-) - nein es ist aktiviert. Mein JS-Programm, das ähnlichen Firlefanz macht funktioniert ja wunderbar im OP. Der OP hat bei meinen damaligen Versuchen auch den Style-Bereich korrekt eingesetzt, aber eben optisch keine Auswirkungen gezeigt. Version 7.54
Der IE-Zweig unten funktioniert übrigens in meinem OP. Das kann man testen, wenn man den auskommentierten Teil bezüglich OP wieder einseztz - dann geht es nicht mehr.
Übrigens kann man im IE etwas erreichen, wenn man das StyleSheet einfach im Body einsetzt, ist halt IE ;-)
Pervers.
ja, aber soll das Perverse nicht gerade Lust bereiten? ;-)
Funktioniert aber bei mir nicht.
mach's doch einfach mit innerHTML. Man muß die S/M-Szene mit ihren eigenen Mitteln ködern ;-)
function restyle()
{
var col = colors[Math.floor(Math.random() * colors.length)];
var mytext = "body { background-color: " + col + "; }";
var textNode = document.createTextNode(mytext);
if(document.all) // && !window.opera
{
var style1 = '<style type="text/css">';
var style2 = '</style>';
document.body.innerHTML += style1+mytext+style2;
}
else
{
var headElem = document.documentElement.firstChild;
var styleElem = document.createElement("style");
styleElem.setAttribute("type", "text/css");
styleElem.appendChild(textNode); //hier krachts im IE
headElem.appendChild(styleElem); //hier krachts im IE
}
}
da wird jetzt zwar immer ein neuer Style-Bereich eingesetzt, aber das kannst Du auch wegproggen. Da hab ich jetzt keine Lust zu. Jedenfalls funktionierts.
So, und jetzt beschreib doch mal, was das für ein Programm wird :-)
Gruß, Andreas