• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Script bringt Browser zum Absturz

J

j-l-n

Guest
Ich möchte durch folgendes Skript einen String nach der Art "margin: auto; text-align: center; -webkit-border-radius: 2px" in ein Objekt (obj.margin = "auto" und so weiter) umformen.
Dies geschieht in 3 Schritten: Trennen nach dem Strichpunkt, Schleife durch die einzelnen Zuordnungen, Schleife durch die Keys, um bspw. "text-align" in "textAlign" umzunennen.

Allerdings bleibt bei folgendem Script der Browser hängen und verbraucht etliche hundert MB Arbeitsspeicher. Warum?

Code:
var style = "margin: auto; text-align: center; -webkit-border-radius: 2px";


var styles = style.split(";");
var obj = {};
				for(var i = 0; i < styles.length; i++){
					var styleAssignement, assignementKey, assignementValue, keyParts;
					styleAssignement = styles[i].split(":"); //split key from value
					if(styleAssignement.length === 2){
						assignementKey = styleAssignement[0].trim();
						assignementValue = styleAssignement[1].trim();
						keyParts = assignementKey.split("-"); //split keys containing a minus
						for(var x = 0; x < keyParts.length; x++){ //convert keys containing a minus to camel case (e.g. "background-color" -> "backgroundColor")
							var keyPart = keyParts[x];
							if(keyPart !== ""){
								if(!keyInCamelCase){
									var keyInCamelCase;
									keyInCamelCase = keyPart;
								}
								else{
									keyInCamelCase += keyPart.charAt(0).toUpperCase() + keyPart.substr(1, keyPart.length); //remove first char and add it again capitalized
								}
							}
						}
						if(keyInCamelCase){
							assignementKey = keyInCamelCase;
						}
						if(assignementValue !== ""){
							obj[assignementKey] = assignementValue;
						}
					}
				}
console.log(obj);
 
Hört sich ja fast wie nach einer Endlosschleife an...

Ich würde das so lösen:
Code:
function elementStyleStringToCssObject(string) {
    var i,
        i_max,
        obj = {},
        property,
        value,
        subStrings,
        delimeterPos = -1;

    subStrings = string.replace(/;(\s+)|:(\s+)/g, function (match, p1) {
        return p1 ? ';' : ':';
    }).split(';');

    i_max = subStrings.length;
    for (i = 0; i < i_max; i += 1) {
        console.log(subStrings[i]);
        delimeterPos = subStrings[i].indexOf(':');
        if (delimeterPos !== -1) {
            property = subStrings[i].substring(0, delimeterPos).replace(/^-([a-zA-Z]+)|-([a-zA-Z])/g, function (match, p1, p2) {
                if (p1) {
                    return p1 === 'ms' ? p1 : p1.replace(/([a-zA-Z])/, function (match, p1) {
                        return p1.toUpperCase();
                    });
                }
                return p2.toUpperCase();
            });
            value = subStrings[i].substring(delimeterPos + 1);
            obj[property] = value;
        }
    }
    return obj;
}

var cssObject = elementStyleStringToCssObject('margin: auto; text-align: center; -webkit-border-radius: 2px');
console.log('cssObject:');
console.log(cssObject);

PS: Soweit ich weiß, wird das Microsoft prefix als ms behandelt, als wie bei den anderen Webkit, Moz, O, Khtml
 
Hört sich ja fast wie nach einer Endlosschleife an...
Joa, ich frag mich bloß, wo...

Ich würde das so lösen:
Code:
[/QUOTE]
Werde ich mir später mal genauer anschauen - danke schon mal!

[QUOTE]
Soweit ich weiß, wird das Microsoft prefix als [B]ms[/B] behandelt, als wie bei den anderen [B]Webkit, Moz, O, Khtml[/B][/QUOTE]
Mh, da hatte ich was falsch in Erinnerung. Bin davon ausgegangen, das man alle Präfixe klein schreibt. Muss aber auch sagen, dass ich mich nicht erinnern kann, in letzter Zeit Styles mit Präfixen per JS gesetzt zu haben.
 
Das Problem dürfte der Inhalt deiner Variablen "style" sein, in der es innerhalb des String mehrfach ; gibt, was dem Interpreter eigentlich sagt, das hier ein Befehl zu Snde geht.
Nein, in einen String kann man sämtliche Zeichen außer der begrenzenden so oft man will verwenden, ohne sie zu escapen. Das ist ja der Sinn eines Strings...
Code:
var string = "();{}";
alert(string);

Übrigens scheint das Problem an anderer Stelle gelegen zu haben, da es jetzt normal klappt, obwohl ich nichts wesentliches geändert habe: jln.js/jln.style.js at master · j-l-n/jln.js
 
Deine Key-Value Trennung kann in bestimmten Fällen noch in die Hose gehen:
Code:
	background-image: url("http://www.wallpaper-area.to/wallpaper/13/323/3D_002.jpg");

Dafür hat String.split() einen zweiten optionalen Parameter.

Bei der Trennung am Semikolon hast du das gleiche Problem, aber das ist nicht so leicht zu lösen - dafür bräuchtest du dann wirklich einen Parser. Aber ob das wirklich dafür steht...

PS: Im IE kann du Styleattribute auch über ihre Namen mit Bindestring und Schema 4 zugreifen:
Code:
document.body.style["-ms-animation"]
 
Zuletzt bearbeitet:
Deine Key-Value Trennung kann in bestimmten Fällen noch in die Hose gehen:
Code:
	background-image: url("http://www.wallpaper-area.to/wallpaper/13/323/3D_002.jpg");
Dafür habe ich eine RegExp: styleAssignements[i].split(/\:(.+)/)

Bei der Trennung am Semikolon hast du das gleiche Problem, aber das ist nicht so leicht zu lösen
Inwiefern - hättest du da ein Beispiel?

PS: die Verlinking zu String.split() ist kaputt, da ist hinten ein Anführungszeichen zuviel.

Aber woran hat es denn nun gelegen?
Dafür müsste ich mal genau vergleichen, was ich alles verändert habe; vermutlich lag es sowieso an irgendeiner anderen Stelle...
 
Dafür habe ich eine RegExp: styleAssignements[i].split(/\:(.+)/)
Äh... das kommt im Code oben aber nicht vor... ich weiß auch nicht, wie das genau helfen soll.

Inwiefern - hättest du da ein Beispiel?
Naja - in einer URL kann auch ein Semikolon vorkommen. Eigentlich in allem, wo man selbst gewählten Text reinschreiben kann

PS: die Verlinking zu String.split() ist kaputt, da ist hinten ein Anführungszeichen zuviel.
Nö - da war ein Anführungszeichen am Anfang zu wenig ;)
 
j-l-n schrieb:
Dafür müsste ich mal genau vergleichen, was ich alles verändert habe; vermutlich lag es sowieso an irgendeiner anderen Stelle...
Man kann doch in der Chrome Konsole breakpoints setzen.

Du musst nur darauf achten das jetzt Funktionierende Skript einzubinden und dann erst vai copy/paste das nicht funktionierende Skript in die Konsole einfügen.
dann breakpoints setzen und das Skript zeilenweise durchgehen.

Ps.: Habe mit deinem Skript keine Probleme, getestet Chrome/FF/IE, in win7 64Bit.
 
Äh... das kommt im Code oben aber nicht vor... ich weiß auch nicht, wie das genau helfen soll.
Ich rede von dem Code auf Github. Dadurch wird jeweils nur nach dem ersten Doppelpunkt gespalten.

Naja - in einer URL kann auch ein Semikolon vorkommen.
Habe ich geändert, nun wird nur nach dem Semikolon getrennt, wenn darauf ein Leerzeichen folgt.

- - - Aktualisiert - - -

Ps.: Habe mit deinem Skript keine Probleme, getestet Chrome/FF/IE, in win7 64Bit.
Ja, wie gesagt: ich denke, dass das Problem wahrscheinlich an anderer Stelle lag.

PS: danke für den Hinweis mit dem Chrome-Debugging. Allerdings ist es mir ehrlich gesagt völlig egal, woran's jetzt gelegen hat - Hauptsache, es funktioniert. ;)
 
Julian, was hälst du davon, das Thema "breakpoints setzen" in dem von dir gemachten Thread mit der Konsole zu ergänzen? Das richtet sich dann halt an Fortgeschrittene.
 
Ich bin mir nicht sicher, ob das wirklich alle Fälle abdeckt... es gibt ja noch andere CSS-Attribute, bei dennen man beliebigen Text eingeben kann.
Hm, mir fällt allerdings gerade keine bessere Lösung ein. Hättest du eine Idee? Wenn nicht, ist erst mal relativ egal, da das Problem vermutlich nur äußerst selten auftreten würde...
 
Man könnte sowas machen:
Code:
var text = '  background-image: url("http://google.dejd\\"lskj; jdlskjdj"); margin: 20px; -ms-animation: 2  ;-moz-animation-duration: 4; ';
var keyValue = /^\s*([a-z\-]+)\s*:\s*((?:[^;"]|"(?:\\.|[^"])*")*?)\s*(?:;|$)\s*/i;
var style = {};
var match;
while ((match = keyValue.exec(text)) !== null){
	var key = match[1].replace(/-(.)/g, function(m, c){return c.toUpperCase()});
	if (key.match(/^Ms[A-Z]/)){
		key = "m" + key.substring(1);
	}
	style[key] = match[2];
	text = text.substring(match[0].length);
}
if (text){
	throw new Error("Unable to parse: " + text);
}
console.log(style);
 
Ist aber wahrscheinlich ein bisschen langsamer als der .split()-Ansatz. Und ich glaube auch nicht, dass das angesprochene Problem häufig auftritt - aber es kann trotzdem auftreten.
 
Zurück
Oben