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

[FRAGE] Inhalt einer Variablen in RegEx nutzen

mactoni

New member
Hallo,
ich möchte einen Wert aus einer Variablen in einer Regel nutzen.
Sieht so aus:

Code:
...
var str = "$1".fontcolor('red');
var count = $('#marker').val(); 
var marker = txt.replace(/^(.{count})/g, str);
...

In Zeile 3 soll der Wert von count eingesetzt werden der mit jQuery ausgelesen wird in der Zeile drüber.
Der Wert wird sauber ausgelesen aber anscheinend nicht korrekt eingesetzt in die Regex.
Wie kann ich hier den Wert von count korrekt einsetzen? Bei der Variablen str gibts keine Probleme. Wenn ich testweise eine Zahl für count direkt einsetzte gehts.

Grüße,
mactoni
 
RegExp-Objekte sind keine Strings die du einfach so verketten kannst. Bau dir dein RegExp-Objekt vorher zusammen:
Code:
var regEx =  new RegExp("^(.{" + count + "})","g")
var marker = txt.replace(regEx , str);
 
Die RegExp ergibt aber prinzipiell keinen Sinn. Du ersetzt hier einfach nur die ersten count Zeichen - das kann man effektiver mit STRING.substr() machen...

Wenn du auf gleiche Zeichen am Anfang testen willst, muss die RegExp anders aussehen:/^((.)\2{count-1})/ - wobei natürlich count-1 ersetzt werden muss (bzw. die RegExp so, wie jspit es geschrieben hat, zusammengebaut werden muss).
 
Die Regex ergibt schon Sinn für meinen Zweck. Per Klick werden die jeweils die ersten x Zeichen (Anzahl der count Variable) eines Textes eingefärbt. Genau das funktioniert damit prima.
 
Für sowas brauchst du aber keine RegExp...
Code:
var text = "alsdjf wqejr sandf oqij sadjf ";
var count = 3;
console.log(text.substring(0, count).fontcolor("red") + text.substring(count));
- ist einfacher zu lesen und schneller. (Und hat den Vorteil, dass auch die ersten Zeichen eingefärbt werden, wenn der Text zu wenig Zeichen hat.)

PS: Ich würde ja STRING.fontcolor() nicht verwenden. Ist deprecated und wirklich flexibel ist es auch nicht.
 
Stimmt, es werden keine Zeichen eingefärbt wenn zu wenige vorhanden sind. Das wäre ein großer Vorteil.
Allerdings habe ich noch zusätzlich ein Multiline drin
Code:
var regEx =  new RegExp("^(.{" + count + "})","mg")
Somit werden im gesamten Text alle Zeilen markiert. Wüsste nicht wie ich es einfacher ohne Regex machen könnte.
 
Du kannst den Text ja vorher an den Zeilenumbrüchen auseinanderschneiden, dann für jede Zeile den Code oben ausführen und dann die Zeilen wieder zusammenfügen:
Code:
var text = "mein test\nmit Zeilenumbrüchehn\nund und und... ";
var count = 3;
console.log(text.split(/\r\n?|\n/).map(function (line){
	return line.substring(0, count).fontcolor("red") + line.substring(count);
}).join("<br>\n"));
 
Prima Lösung, werde ich wohl so machen.
Hänge aber jetzt erstmal am nächsten Problem, dem Zeilenumbruch im Browser.
Kurze Beschreibung:
Das Tool das ich am bauen bin macht eine Textanalyse. Dazu wird der zu untersuchende Text in eine textarea herein kopiert. Von hier können dann verschiedene Analysemethoden gestartet werden.
Um die Funktion mit dem einfärben der ersten x-Zeichen zu realisieren, leite ich den Text in ein neues Fenster um mit einem
Code:
<pre id='poptxt' contenteditable='true'>
Macht der Browser nun einen Umbruch des Textes wird das nicht vom Code erkannt. Nur die Absätze/Zeilenumbrüche, die beim herein kopieren schon im Text vorhanden sind werden erkannt. Habe also immer nur je Absatz oder original Zeilenumbruch die erste Zeile eingefärbt. Würde aber gerne nach den Zeilenumbrüchen die der Browser macht einfärben.
Weiß nicht ob ich das irgendwie verständlich erklären konnte.
Hier mein Testcode der keinen Zeilenumbruch vom Browser erkennt:
Code:
var txt = $("#txtarea").val();
var str = "$1".fontcolor('red');
var count = $('#markierung').val();
var rx = new RegExp('^(.{' + count + '})', "mg");
var markierung = txt.replace(rx, str);

var markWin = window.open("", "", "width=880,height=650");
markWin.document.write("<title>Markierung Textlänge</title><pre id='poptxt' contenteditable='true'>");
markWin.document.write(marker + '</pre>');
 
Aus der Textarea kopiere ich den "Original" Text heraus und schreibe ihn im neuen Fenster in ein <pre>.
Auch mit deinem Code gehts nicht.
Getestet habe ich mit Chrome, Safari und Firefox. Opera und IE/Edge spielen keine Rolle.
 
Du willst also, dass in dem <pre> automatisch die ersten n Buchstaben angefärbt werden, wenn du im <pre> einen Umbruch machst?
 
Ich möchte im <pre> die ersten n-Zeichen einfärben, so wie der Browser den Umbruch gemacht hat.
Das neue Fenster hat eine vorgegebene Breite von 880px. Demnach bricht der Browser den Text auch um. Nach diesem Umbruch vom Browser soll sich dann auch das einfärben richten.
Also so wie der Browser den Text darstellt, sollen die jeweils ersten n-Zeichen rot eingefärbt werden.
 
Ach so... das ist ziemlich kompliziert. Warum willst du das denn überhaupt machen? Vielleicht gibt es für dein Problem eine elegantere Lösung.
 
Nach langer Durststrecke steht die Lösung, zwar wollte ich es in einem neuen Window anstatt einem Div anzeigen, dies war aber noch umständlicher.
Code:
var range = document.createRange();

function getPositions(p, txt) {
	var node = p.childNodes[0];
	var startOffset = 0;
	var endOffset = 0;
	var rect;
	var top = -1;
	var lines = [];
	//replace newline characters
	XRegExp.forEach(txt, /\s+/g, function (match, idx) {
		endOffset = match.index;
		range.setStart(node, startOffset);
		range.setEnd(node, endOffset);
		rect = range.getBoundingClientRect();
		if (rect.top > top) {
			top = rect.top;
			lines.push(startOffset);
		}
		startOffset = endOffset + 1;
	});
	endOffset = txt.length;
	if (endOffset > startOffset) {
		range.setStart(node, startOffset);
		range.setEnd(node, endOffset);
		rect = range.getBoundingClientRect();
		if (rect.top > top) {
			top = rect.top;
			lines.push(startOffset);
		}
	}
    markChars(p, lines, txt);
}

function markChars(p, lines, txt) {
    var x, tempCount;
	var previousX = txt.length;
    var count = parseInt($('#cvalue').val());
    var rx;
    while (lines.length > 0) {
        x = lines.pop();
		tempCount = count;
		if (x + count > previousX) {
			tempCount = previousX - x;
		}
		previousX = x;
		rx = XRegExp("^(.{" + x + "})(.{" + tempCount + "})", "s");
        txt = XRegExp.replace(txt, rx, "$1<span style='color: red'>$2</span>");
    }
	$(p).html(txt);
}
 
Das scheint mir sehr umständlich zu sein.

Code:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fenstertitel</title>
<style type="text/css">
#output {
	white-space: pre-wrap;
	position: relative;
}
#output span.marked {
	color: red;
}
</style>
</head>
<body>
<input type="number" min="0" id="markLength">
<textarea id="input"></textarea>
<div id="output"></div>
<script type="text/javascript" src="http://kkjs.kkapsner.de/modules/kkjs.load.js"></script>
<script type="text/javascript">
function mark(span, markLength, notFirst){
	if (span && (!notFirst || span.offsetLeft !== 0) && markLength > 0){
		var str = span.firstChild.nodeValue;
		kkjs.node.clear(span);
		var frag = kkjs.node.create({
			tag: "fragment",
			childNodes: [
				{
					tag: "span",
					className: "marked",
					childNodes: [str.substring(0, markLength)]
				},
				str.substring(markLength)
			]
		});
		span.appendChild(frag);
		mark(span.nextElementSibling, markLength - str.length, true);
	}
}
function updateOutput(){
	var output = kkjs.$("output");
	kkjs.node.clear(output);
	var frag = kkjs.node.create({tag: "fragment"});
	var spans = kkjs.$("input").value.split(/(\s)/).map(function(str){
		return kkjs.node.create({tag: "span", childNodes: [str], parentNode: frag});
	});
	output.appendChild(frag);
	
	var markLength = parseInt(kkjs.$("markLength").value, 10);
	spans.forEach(function(span, i){
		if (span.offsetLeft === 0){
			mark(span, markLength);
		}
	});
}
kkjs.event.add(kkjs.css.$("#input, #markLength"), "input", updateOutput);
kkjs.event.add(window, "resize", updateOutput);
</script>
</body>
</html>

PS: Was ist denn XRegExp? Und warum verwendest du wieder eine RegExp, wo ein STRING.substr() besser wäre?
 
Zurück
Oben