Seite 1 von 2

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 09.01.2012, 15:24
von ZygmuntDD
Hallo, ich hab in den letzten Wochen ein mittlerweile ziemlich großes dynamisches Formular erstellt. Das ganze mit sehr rudimentären Kenntnissen in Javascript. Dennoch bin ich soweit sehr zufrieden und weit vorangekommen.
Aber nun möchte ich gerne noch etwas einbauen was bisher nicht funktioniert.

Das ganze ist eine Checkliste mit verschiedenen Punkte, und es muss entscheiden werden ob Punkt A oder B vorhanden ist oder nicht und entsprechenden werden Punkte vergeben. Diese Punkte werden in numerische Felder mit der Bezeichnung "NumFeld" eingetragen. Nun wird am Ende alles mit unten stehendem Script zusammengerechnet und mit maximal erreichbaren Punkten verglichen. Das funktioniert soweit super.

Code: Alles auswählen

var nPoints = 0;
    var maxPoints = 0;
    for (var i = 0; i < xfa.host.numPages; i++){
        var oFields = xfa.layout.pageContent(i, "field");
        var nodesLength = oFields.length;
        for (var j = 0; j < nodesLength; j++){
            var oItem = oFields.item(j);
            if(oItem.name == "NumFeld"){
                nPoints += oItem.rawValue;
            }
            if(oItem.name == "MaxPoints"){
                maxPoints += oItem.rawValue;
            }
        }
    }
Nun möchte ich aber gerne, das selbige Rechnung nur für ein bestimmtes Teilformular durchgeführt wird. Ich weiß aber nicht, wie ich das Script auf ein solches Begrenzen kann und wäre sehr froh wenn mir da jemand einen kleinen Tip geben könnte.

Vielen Dank schon einmal.


Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 09.01.2012, 16:38
von radzmar
Hi,

das Skript könnte so aussehen.

Code: Alles auswählen

var nPoints = 0;
var maxPoints = 0;
function findNodes(vNode) {
    if (vNode.className === "field") {
    	if (vNode.name === "NumFeld") {
        	nPoints += vNode.rawValue;
        }
        if (vNode.name === "MaxPoints") {
        	maxPoints += vNode.rawValue;
        }
    }
    for (var i = 0; i < vNode.nodes.length; i++) {
        findNodes(vNode.nodes.item(i));
    }
}
findNodes(xfa.template.Formular1.Seite1.Subform1);

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 10.01.2012, 08:48
von ZygmuntDD
Hallo, und mal wieder vielen Dank für die schnelle Antwort.

Habe aber noch ein zwei Fragen. Im Prinzip dachte ich, das ich das Skript verstanden habe, aber nach genauerem Hinsehen kamen doch Fragen auf.

Das Prinzip scheint klar, man definiert eine Funktion mit dem Parameter vNode.
Die Funktion überprüft Objekt nach ihrer Klasse und ihrem Namen, hat sie das gefunden was wir wollen, addiert sie den Wert eines Objektes zur im Vorfeld definierten Variablen. Und das ganze soll die Funktion natürlich für alle im Teilformular befindlichen Objekte machen.

Was mir aber gänzlich unklar ist, warum innerhalb der Funktion diese schon aufgerufen werden kann und wird. Also die Zeile "findNodes(vNode.nodes.item(i));" im Skript

Code: Alles auswählen

function findNodes(vNode) {
if (vNode.className === "field") {
if (vNode.name === "NumFeld") {
nPoints += vNode.rawValue;
}
if (vNode.name === "MaxPoints") {
maxPoints += vNode.rawValue;
}
}
for (var i = 0; i < vNode.nodes.length; i++) {
findNodes(vNode.nodes.item(i));
}
}
Vielen Dank und Grüße.


Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 10.01.2012, 11:19
von radzmar
Die Funktion ruft sich selbst immer wieder auf, um sich innerhalb der XML-Struktur immer tiefer rein zu arbeiten.

Wenn Du die Funktion mit findNodes(xfa.template.Formular1.Seite1.Subform1); aufrufst, fängt die Suche bei der Node "Formular1.Seite1.Subform1" an.
Damit auch alle untergeordneten Teilformulare und Felder durchsucht werden, muss die Funktion die entsprechenden Childs absuchen.
Das erfolgt den erneuten Aufruf mit findNodes(vNode.nodes.item(i)); innerhalb der Funktion selbst.

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 10.01.2012, 13:38
von ZygmuntDD
Ok, das erscheint logisch. Aber kann es sein, das die Funktion bisher keinen Wert zurückgibt? Mus da nicht noch ein return Befehl in die Funktionsprozedur?

Ich habe das zwar schon selber probiert, aber funktioniert nicht so wie es soll.

Endziel soll es sein, das nPoints mit maxPoints verglichen wird, als: nPoints/maxPoints und das ganze auf ein Textfeld ausgeben.

Code: Alles auswählen

    var nPoints = 0;
    var maxPoints = 0;
        function findNodes(vNode) {
            if (vNode.className === "field") {
                if (vNode.name === "NumFeld") {
                    nPoints += vNode.rawValue;
                }
                if (vNode.name === "MaxPoints") {
                    maxPoints += vNode.rawValue;
                }
            }
            for (var i = 0; i < vNode.nodes.length; i++) {
                findNodes(vNode.nodes.item(i));
            }
        var Ergebnis = nPoints/maxPoints;
        return Ergebnis;
        }

findNodes(xfa.template.Formular1.P1.Bedienen);
Ergebnis.rawValue = Ergebnis;

Da ist sicher irgendwo ein Denkfehler drin!? Und nur noch mal zum generellen Verständnis, wenn unter: Formular1.P1.Bedienen noch mehr als eine ebene an Teilformularen ist, dann findet er auch da die "NumFeld" Objekte?
Der Debugger gibt auch keine Fehlermeldung beim Ausführen aus.

Danke und Gruß


Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 11.01.2012, 18:15
von ZygmuntDD
Also mittlerweile hab ich verstanden, das die Funktion auf ein SkriptObjekt gehört, und ich die Funktion dann an ensprechender Stelle über das Skriptobjekt Stelle abrufen kann. Dazu hatte sich noch ein kleiner aber entscheidener Fehler im Skript von radzmar eingeschlichen. Zumindest funktionierte es nicht, bis ich es geändert habe.
Statt:

Code: Alles auswählen

findNodes(xfa.template.Formular1.Seite1.Subform1);
muss es:

Code: Alles auswählen

findNodes(xfa.form.Formular1.Seite1.Subform1);
heißen.

Nun funktioniert das Skript wenn es so aussieht:

Code: Alles auswählen

var nPoints = 0;
var maxPoints = 0;
        
function findNodes(vNode){
    if (vNode.className === "field") {
        if (vNode.name === "NumFeld") {
            nPoints += vNode.rawValue;
        }
        if (vNode.name === "MaxPoints") {
            maxPoints += vNode.rawValue;
        }
    }
    for (var i = 0; i < vNode.nodes.length; i++) {
        findNodes(vNode.nodes.item(i));
    }
    var Punkte = Math.round(nPoints/maxPoints*10000)/100;
    P1.Bedienen.Einzelfunktionen.Zwischenergebnis.Ergebnis.rawValue = Punkte + " %";
}
und ich das ganze über:

Code: Alles auswählen

this.resolveNode("ZwischenErgbenis").findNodes(xfa.form.Formular1.P1.Bedienen);
abbrufe.

Nun würde ich aber gerne diese Funktion mehrmals an verschiedener Stelle verwenden, wodurch ich die Ausgabe noch als Parameter gestalten müßte, aber sobald ich aus dem Skript das mache:

Code: Alles auswählen

var nPoints = 0;
var maxPoints = 0;
        
function findNodes(vNode,Ausgabe){
    if (vNode.className === "field") {
        if (vNode.name === "NumFeld") {
            nPoints += vNode.rawValue;
        }
        if (vNode.name === "MaxPoints") {
            maxPoints += vNode.rawValue;
        }
    }
    for (var i = 0; i < vNode.nodes.length; i++) {
        findNodes(vNode.nodes.item(i));
    }
    var Punkte = Math.round(nPoints/maxPoints*10000)/100;
    Ausgabe.rawValue = Punkte + " %";
}
Und die funktion über

Code: Alles auswählen

this.resolveNode("ZwischenErgbenis").findNodes(xfa.form.Formular1.P1.Bedienen,Ergebnis);
auffrufe, kommt die Fehlermeldung "Ausgabe has no properties".

Kann jemand dem ganzen folgen und mir vielleicht noch einen letzten Tipp geben?

Vielen Dank und Grüße

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 11.01.2012, 18:35
von radzmar
Hi,

mit dem Fehler hast Du Recht, die Node zur Laufzeit heißt "xfa.form" und nicht "xfa.template" :?

Aber der Rest funktioniert so wie anfangs schon beschrieben in click:Event eines Buttons.
Es ist weder erforderlich das Skript in ein Skriptobjekt zu packen, noch eine Variable innerhalb der Funktion für das Ergebnis zu deklarieren.

Code: Alles auswählen

var nPoints = 0;
var maxPoints = 0;

function findNodes(vNode) {
    if (vNode.className === "field") {
        if (vNode.name === "NumFeld") {
            nPoints += vNode.rawValue;
        }
        if (vNode.name === "MaxPoints") {
            maxPoints += vNode.rawValue;
        }
    }
    for (var i = 0; i < vNode.nodes.length; i++) {
        findNodes(vNode.nodes.item(i));
    }
}

findNodes(xfa.form.Formular1.P1.Bedienen);
Ergebnis.rawValue = nPoints / maxPoints;
Hier mal ein Beispiel-Formular.

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 11.01.2012, 21:44
von ZygmuntDD
Mmmh, ich frag mich was ich die anderen 100 male gemacht habt, wo es nicht funktioniert hat, frustrierend. Aber nun geht es.
Nun hab ich aber gleich das nächste Problem gefunden und bräuchte noch ein letztes mal für heute deine Hilfe. :)

Wenn es nun von dem Teilformular in dem die Zwischensumme berechnet wird mehrere Instanzen gibt, dann gibt es logischerweise dann auch mehrere Schaltflächen zum Berechnen und Ergebnisfelder zum Ausgeben. Nun wird aber in jeder einzelnen Instanz die Summe aller Felder in allen existierenden Instanzen summiert.

Man kann ja den Index der aktuellen Instanz auslesen, aber wir kann man ihm in dem Skript sinnvoll unterbringen?

Code: Alles auswählen

var i = Formular1.P1.Bedienen.index;
findNodes(xfa.form.Formular1.P1.Bedienen[i]);
Das funktioniert leider nicht. :(


Grüße

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 12.01.2012, 09:09
von radzmar
Da JavaScript die Instanzen so nicht ansprechen kann, musst Du die resolveNode-Methode einsetzen.

Um z.B. nur die 2. Instanz anzusprechen:

Code: Alles auswählen

findNodes(xfa.resolveNode("xfa.form.Formular1.P1.Bedienen[1]"));

Schleife auf bestimmtes Teilformular begrenzen

Verfasst: 12.01.2012, 09:21
von ZygmuntDD
Ok, aber kann ich so trotzdem über die Variable .index gehen. Denn ich weiß ja nicht wieviele Instanzen ich haben werde. Und in jeder soll die Berechung ja explizit nur innerhalb der Instanz erfolgen?