[JS] Function: split->array->for = einzeln abarbeiten

Hallo Forum,

die Syntax von PHP lässt sich zum Glück leicht auf JavaScript übertragen, aber bei einer kleinen Funktion hätte ich doch gerne Euren Rat, da mir zu viele Lösungsmöglichkeiten im Kopf schwirren.

Und zwar:
Ich habe eine und dieses soll onSubmit eine Funktion aufrufen.
Dieser Funktion übergebe ich, mit Kommas voneinander getrennt, IDs der Inputfelder als ein String.
In der JS Funktion splitte ich den String nach dem Trennzeichen Komma und erhalte ein Array.

Je nachdem wie viele IDs ich der Funktion nun übergeben habe, sollen diese IDs der Inputfelder auf Inhalt geprüft werden, nämlich, dass die übergebenen IDs der jeweiligen Inputfelder nicht leer sein dürfen. Falls diese leer sind, soll ein alert stattfinden, das dem User sagt, dass er die Pflichtfelder doch bitte auszufüllen hat.

HTML:
[HTML]

[/HTML][B]JS:[/B] [CODE] function checkInput(input) { var input; // String: mehrere Wörter mit Komma als Trennzeichen var gesplittet = input.split(","); // String nach Trennzeichen splitten in ein Array
for(gesplittet as einzeln) // je nachdem  wie viele keys ein Array hat - was hier zu tun?
{
    // Beispiel: im Array enthalten: "input1"
    // schaue, ob "input1" leer ist, wenn ja, unterbrechen: alert("Nicht ausgefüllt!")
   // wenn alle übergebenen IDs ausgefüllt, Formular abschicken!
}

}
[/CODE]Wie habe ich das zu realisieren?

Danke.

Ich war mal so frei und hab dir das geschrieben :slight_smile:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Cheeeck</title>
        <script type="text/javascript">
            window.onload = function() {
                // Formular holen
                var formul = document.getElementById("formular");
                formul.onsubmit = checkInput;
            };
            
            var checkIds = ["input1","input2","input3"];
            function checkInput() {
                var errors = false;
                var checkAttr = {
                    "input" : "value",
                    "textarea" : "innerHTML",
                    "select" : "value"                    
                };
                
                for(var i=0; i < checkIds.length; i++) {
                    var inp = document.getElementById(checkIds[i]);
                    if(inp) {
                        var val = inp[checkAttr[inp.tagName.toLowerCase()]];
                        if (val == "") {
                            alert("Das Feld " + inp.id + " darf nicht leer sein");
                            errors = true;
                        }
                    }
                }
                if(errors) return false;
                
            }
        </script>
    </head>
    <body>
        <form action="" id="formular" method="post">
        <input type="text" name="input1" id="input1" />
        <input type="text" name="input2" id="input2" />
        <input type="text" name="input3" id="input3" />
        
        <input type="text" name="unwichtig" />
        <input type="submit" value="OK">
        </form>
    </body>
</html>

Ich habe auch mal den ganzen JS Teil aus dem HTML genommen. Ist „hübscher“ so :smiley:

Nebenbei. foreach Schleifen setzt du folgender Maßen um

var array = ["bli","bla","blub"];
for(var teil in array) {
  alert(teil); // Gibt den index aus (0 oder 1 oder 2)
  alert(array[teil]); // entweder bli, bla oder blub
}

Bei assoziativen Array wäre der „Teil“ der Key.

Vielen lieben Dank für deine Mühe.

Ich habe es etwas dynamischer geschrieben, um die Funktion in eine JS-Datei auszulagern und sie in mehrere Scripts leicht einsetzbar zu machen.

[HTML]

// [/HTML][CODE] function checkInput(form,input) { var formul = document.getElementById(form); // Formular holen var input; // String: mehrere Wörter mit Komma als Trennzeichen var IDs = input.split(","); // String nach Trennzeichen splitten in ein Array var errors = false;
            var checkAttr = {
                "input" : "value",
                "textarea" : "innerHTML",
                "select" : "value"                    
            };
            
            for(var i=0; i < IDs.length; i++) {
                var inp = document.getElementById(IDs[i]);
                if(inp) {
                    var val = inp[checkAttr[inp.tagName.toLowerCase()]];
                    if (val == "") {
                        alert("Das Feld " + inp.id + " darf nicht leer sein!");
                        errors = true;
                    }
            }

// if(errors) return false; // Erstmal auskommentiert, damit alle Fehlermeldungen angezeigt werden.
}
}
[/CODE]Ich hätte zwei Dinge noch gerne verbessert, nämlich, dass wenn ein Fehler auftritt, das Formular nicht abgeschickt wird. Wie beim „Abbrechen“ klicken bei einem return confirm.
Ist das möglich?

Und könnte ich die Fehlermeldungen zunächst in eine Variable speichern, damit nur ein Alert mit allen Fehlermeldungen auftaucht? Bestimmt! :smiley:

[CODE]
function checkInput(form,input)
{
var formul = document.getElementById(form); // Formular holen
var input; // String: mehrere Wörter mit Komma als Trennzeichen
var IDs = input.split(„,“); // String nach Trennzeichen splitten in ein Array
var errors = false;

            var checkAttr = {
                "input" : "value",
                "textarea" : "innerHTML",
                "select" : "value"                    
            };
            
            for(var i=0; i < IDs.length; i++) {
                var inp = document.getElementById(IDs[i]);
                if(inp) {
                    var val = inp[checkAttr[inp.tagName.toLowerCase()]];
                    if (val == "") {
                        
                        //inputfelder in ein array packen vielleicht? und am ende ausgeben
                        
                        //alert("Das Feld " + inp.id + " darf nicht leer sein!");
                        errors = true;
                    }
            }
           if(errors) alert("Folgende Felder müssen ausgefüllt werden:\n"+varioak);
        }

}[/CODE]

EDIT:
Scheinbar brauche ich auch kein Formular zu holen oder? Ich übergebe nur die nötigen IDs. Aus welchem Formular sie kommen, scheinen bei mir zumindest egal zu sein. Die Variable wird im weiteren Verlauf gar nicht genutzt.

Zu deinem Problem dass das Formular abgesendet wird. Dafür ist die „if(errors)“ Geschichte da gewesen :smiley:
Das return false bezweckt, dass nicht mit dem ursprünglichen Vorhaben (submit) weiter gemacht wird, sondenr abgebrochen wird.

So sollte dein Script ok sein:

function checkInput(form,input)
{
        var formul = document.getElementById(form); // Formular holen
        var errorMessage = "Folgende Felder dürfen nicht leer sein: ";
        var firstError = true;
        var IDs = input.split(","); // String nach Trennzeichen splitten in ein Array
        var errors = false;
        
                var checkAttr = {
                    "input" : "value",
                    "textarea" : "innerHTML",
                    "select" : "value"                    
                };
                
                for(var i=0; i < IDs.length; i++) {
                    var inp = document.getElementById(IDs[i]);
                    if(inp) {
                        var val = inp[checkAttr[inp.tagName.toLowerCase()]];
                        if (val == "") {
                            errorMessage += (firstError) ? inp.id : ","+inp.id;
                            if(firstError) firstError = false;
                            errors = true;
                        }
                }
               if(errors) { alert(errorMessage); return false;}
               }
            }
}

Super! Danke!

Das return:false; habe ich rausgenommen, weil es nicht funktioniert hat. Und das tut es jetzt auch wieder nicht. Das Formular wird dennoch abgeschickt. Oben war eine Klammer zu viel, die ich entfernt habe.
Wenn ich var formul = document.getElementById(form); // Formular holen auskommentiere, funktioniert alles noch und die Variable formul findet nirgendswo sonst noch seine Verwendung. Kann ich daher darauf verzichten?

Das return false funktioniert, es muss natürlich dem Eventhandler auch mitgeteilt werden, dass ein return false kommen kann.

Auf die IDs würde ich verzichten, da Formularelemente bereits einen Namen haben und diese hier spezifischer sind .

DerInhalt einer Textarea wird auch mit .value ermittelt.

und hier mal ein Code, der auch mit mehreren Formularen in einem Dokument und auch mit Auswahlfeldern zu recht kommt.

So sieht der JS Code aus:

[code]function FormCheck(elements) {
function checkElement(el) {
var t = el.type.toLowerCase();
if(t == ‚text‘ || t == ‚textarea‘) return el.value;
else if(t.indexOf(‚select‘) > -1) return el.options[el.selectedIndex].value;
return null;
}

var c = check[this.name];
var ret = true;
for(var i = 0; i < c.length; i++) {
	if(this.elements[c[i]] && !checkElement(this.elements[c[i]])) {
		alert(c[i] + ' ausfüllen!');
		ret = false;
	}
}
return ret;

}
FormCheck.ini = function() {
var forms = document.forms;
if(!forms) return;
for(var i = 0; i < forms.length; i++) {
var form = forms[i];
if(check[form.name]) form.onsubmit = FormCheck;
}
};
[/code]

Der Code auf der HTML Seite, dann so:
[html]

---- wert1 wert2 wert3 ---- wert1 wert2 wert3 [/html]

Ahh. :smiley: Stimmt.
[HTML][/HTML]

Auf die IDs möchte ich nicht verzichten, da jedes Inputfeld von einem umgeben ist. Ich werde zusehen, wie ich den Inhalt vom dann oben in der Funktion als Parameter nutzen kann.

Danke für Eure Hilfe.

Eine kleine Sache noch? :oops:

An diesem Beispiel:
[HTML]

NAME

ADRESSE

[/HTML][B]JS: [/B][CODE] function checkInput(input) { var errorMessage = "Folgende Felder dürfen nicht leer sein: \n"; var firstError = true; var errors = false; var input; // String mit mehrere IDs mit Komma als Trennzeichen var IDs = input.split(","); // String nach Trennzeichen in ein Array splitten
            var checkAttr = {
                "input" : "value",
                "textarea" : "innerHTML",
                "select" : "value"                    
            };

    for(var i=0; i < IDs.length; i++) {
        var inp = document.getElementById(IDs[i]);
            if(inp) {
                var val = inp[checkAttr[inp.tagName.toLowerCase()]];
                    if (val == "") {
                        errorMessage += (firstError) ? inp.id : ", "+inp.id;
                        if(firstError) firstError = false;
                        errors = true;
                    }
            }
    }   
    if(errors) {alert(errorMessage); return false;}        

}
[/CODE]Es klappt alles wunderbar.
Ein schönes Feature allerdings wäre folgendes:

Wenn ein Pflichtfeld nicht ausgefüllt wird, gibt es ein alert - allerdings mit dem tagname bzw. der ID des Feldes. Schön und gut, aber es würde einfach besser aussehen, wenn statt der ID das Wort im -Tag zum dazugehörigen Inputfeld ausgegeben werden würde. So würde der User gleich sehen, welches Feld gemeint ist.

Also wenn, zum Beispiel, das Feld mit der ID „input1“ leer ist, soll nicht das ausgegeben werden, sondern das, was im dazugehörigen -Tag steht. In dem Falle „NAME“.
Die Ausgabe im alert wäre:
Folgende Felder dürfen nicht leer sein:
NAME

Über document.getElementbyID komme ich ja nur zum Inhalt des Inputfeldes, nicht des label Tags.

Wäre sehr dankbar. =)

PS: Meine Versuche scheitern bisher mit einem leeren Alert.

Die Inputelemente sollten besser innerhalb von dem Label stehen, dadurch sparst du dir die unnötige ID und der Text wird dadurch anklickbar, was die Nutzerfreundlichkeit verbessert, vor allem bei Radio- und Checkboxen.

Du hast vermutlich mein Codebeispiel auf der ersten Seite übersehen, ich hab es nochmal an deine Vorgaben angepaßt und eine entsprechende Markierung eingebaut.

[html]

Formcheck form .pflicht { background-color:yellow; } form .error { background-color:red; }

Beispiel

---- wert1 wert2 wert3 Text1: Text2: ---- wert1 wert2 wert3 [/html]

Ich habe es gesehen, aber dann müsste ich die header Datei neu schreiben. Die wird eben in jedes Template includet.
Danach kommt der Inhalt. [I]

[/I] gehört ja eigentlich in den Bereich. :-/ Das ist das Einzige, was mich semantisch und optisch stört. Vielleicht hast du noch eine Idee? Sonst werde ich das Templatesystem umschreiben müssen. Danke dir. Edit: Es sei denn, ich schaue mir heute Abend deine markierten Stellen genauer an. :D Danke.

Der Script Teil kann durchaus in den Header verschoben werden (was aber egal ist, script darf sowohl dort als auch im body stehen)

EDIT: … und der beste Platz für ein Skript ist vor dem schliessendem Bodytag.

Das meine ich ja. Das macht mir Umstände, dass der Script Teil eigentlich oben hingehört.
Deswegen wollte ich es über ein einfaches onSubmit=„return funktion“ machen.
Heute Abend habe ich wieder Zeit dafür.

Das meinte ich aber nicht. Dem Skript von mir ist es egal ob es im head oder body oder extern steht. Und wie gesagt, eigentlich gehören Skripte vor dem Tag

EDIT: Das Skript fügt automatisch das onsubmit Event dem Formular hinzu

Ach so, vielleicht verstehst du das ja nicht, du musst die Variabel

FormCheck.check = { Formular: ['text1', 'auswahl', 'area'], einAnderesFormular: ['text2', 'auswahl'] };
Für dein Formular entsprechend befüllen. Also nach diesem Schema:

FormCheck.check = { Name_des_Formular: ['element1', 'element2', 'element3'], einAnderesFormular: ['element1', 'element2'] };
element1…3 sind die Namen der Elemente im Formular

So, tut mir leid für die Verspätung. Ich habe deinen Script jetzt eingefügt. Ein paar kleine Sachen werde ich noch ändern müssen, aber könntest du mir einen Tipp geben, wie ich statt den Namen des Elemetes auszugeben dann doch das zwischen ausgeben kann?

[HTML]
Dein Name

[/HTML]
„Dein Name“ sollte dann alertet werden, nicht „einfeld“.