Thema: mehrdimensionales Array

Hallo Gemeinde!

hab schwierigkeiten ein mehrdimensionales array auszulesen.
Langsam dachte ich ja, das ich sowas raushätte...aber naja smile

es geht darum eine Menuestruktur dynamisch zu generieren:

var menu = {
       M1:['Menu1'],
       M2:['Menu2',
                 {M2_1:['Menu2_1','Menu2_2']}
            ],
       M3:['Menu3']
}

^das ist also das array....

dieses Array lese ich wie folgt aus:

var str = "";
    
    function writeList (){
        for (i in menu){
            str += "<div class='first'>"+menu[i][0]+"</div>";
            for (s=1; s<menu[i].length; s++){
                    str += "<div class='second'>"+menu[i][1]+"</div>";
            }
        }
        document.getElementById('container').innerHTML = str;
    }

nun möchte ich die Inhalte des verschachtelten arras auslesen. Zur Zeit liest er da nur das array-object aus.

Mit der 1. Schleife möchte ich das 1. array auslesen und mit der 2. Schleife das verschachtelte array...
wie kann ich das wohl anstellen??

schönen Dank für einfache und konkrete Tipps!!

grüße

2

Re: mehrdimensionales Array

N'abend kaplar,

Ich rätsele nun schon über ne Stunde über der Frage, wozu
Du eine solche Datenstruktur brauchst - bzw. welchem höheren
Zweck die dienen soll.

var menu = {M1 : ['Menu1'],
            M2 : ['Menu2',
                  {M2_1 : ['Menu2_1', 'Menu2_2']}
                 ],
            M3 : ['Menu3']
           };

enthält zum einen Arrays, die genau einen string enthalten, und
zum zwoten anonyme Objecte, die wiederum Arrays enthalten, die
mehrere strings enthalten.

Wenn ich eine solche Unterscheidung machen müsste (also: zwischen
genau einem und eben mehreren strings) würde ich das so schreiben:

var menu = { M1 : 'Menu1',
             M2 : { M2_1 : 'Menu2_1',
                    M2_2 : {M2_2_1 : 'Menu2_2_1',
                            M2_2_2 : 'Menu2_2_2'
                           }
                  },
             M3 : 'Menu3'
};

Dann nämlich kann man sagen:

var str = '';

function writeList(m, c)
 {c++;
  for (var i in m)
   typeof m[i] == 'object' ? writeList(m[i], c) :
   str += "<div class='cl_" + c + "' onclick='alert(this.className)'>" + m[i] + ' => Ebene ' + c + "</div>";
 };

onload = function() {writeList(menu, 0);
                     document.getElementById('container').innerHTML = str};

Wenn Du allerdings Deine Struktur brauchst (vielleicht könntest Du mal näher erläutern, was
genau Dir daran wichtig ist), dann muß man eine zwote Unterscheidung treffen, nämlich die
zwischen typeof irgendwas == 'object', und ob dieses object tatsächlich ein Array ist.

Ich habe Dein Beispiel mal ein wenig erweitert, in der Hoffnung, das wesentliche kapiert
zu haben - bitte sag Bescheid, sollte ich mich irren:

var str = '';

var menu = {M1 : ['Menu1'],
            M2 : ['Menu2',
                  {M2_1 : ['Menu2_1',
                           'Menu2_2'
                          ]
                  }
                 ],
            M3 : ['Menu3',
                  {M3_1 : ['Menu3_1',
                           'Menu3_2',
                           {M3_1_1 : ['Menu3_1_1',
                                      'Menu3_1_2',
                                      'Menu3_1_3'
                                     ]
                           },
                           {M3_2_1 : ['Menu3_2_1',
                                      'Menu3_2_2',
                                      'Menu3_2_3'
                                     ]
                           }
                          ]
                  }
                 ],
            M4 : ['Menu4']
           };

A = function(o){return Object.prototype.toString.apply(o).substr(8, 5) == 'Array'};
O = function(o){return typeof o == 'object'};

 function writeList(m, c)
 {for (var i in m)
   O(m[i]) && !A(m[i]) ? writeList(m[i], c) :
   A(m[i])             ? (c++, writeList(m[i], c), c = 0) :
   str += "<div class='cl_" + c + "' onclick='alert(this.className)'>" + m[i] + ' => Ebene ' + c + "</div>";
 };

onload = function() {writeList(menu, 0);
                     document.getElementById('container').innerHTML = str};

Denn wenn ich's recht begriffen habe, sollen die divs classen zugeordnet werden in
Abhängigkeit davon, welcher Ebene sie zugehörig sind. Korrekt ?

gruß

matho

Re: mehrdimensionales Array

Hi Matho!

Denn wenn ich's recht begriffen habe, sollen die divs classen zugeordnet werden in
Abhängigkeit davon, welcher Ebene sie zugehörig sind. Korrekt ?

damit hast du den Nagel auf den Kopf getroffen!! smile

enthält zum einen Arrays, die genau einen string enthalten, und
zum zwoten anonyme Objecte, die wiederum Arrays enthalten, die
mehrere strings enthalten.

Ja, bei meinem rumprobieren sah das Teil immer wieder anders aus...das arrays nur einen String enthalten, ist natürlich unsinn....

...dann muß man eine zwote Unterscheidung treffen, nämlich die
zwischen typeof irgendwas == 'object', und ob dieses object tatsächlich ein Array ist.

das hatte ich auch schon im Kopf, wußte aber nicht wie ich das umsetzten sollte...

Ich habe Dein Beispiel mal ein wenig erweitert, in der Hoffnung, das wesentliche kapiert
zu haben - bitte sag Bescheid, sollte ich mich irren:

das hast Du und ich freue mich das ich das sogar verstehe!!!!!!

schöne Grüße & DANKE

PS: Nur, wie ist das Verhalten von Opera7 zu erklären...der würfelt alles durcheinander..!?

PPS: wie kann ich den einzelnen Einträgen noch Definitionen zuordnen?
zB: Menu 1 -> true, *.html
Menu 2_1 -> false, *.html

oder müßte man die Objekte auslesen und die Arrays dazu hernehmen die Definitionen zu bestimmen?

4

Re: mehrdimensionales Array

N'abend kaplar,

"...wie ist das Verhalten von Opera7 zu erklären...der würfelt alles durcheinander..!? ..."

Ich kenne den Quelltext der opera-implementierung der for-in-Schleife nicht - erklären
kann ich's Dir also nicht. Ich stelle mir das hilfsweise (als Eselsbrücke sozusagen) so vor
wie hashes in perl, alldieweil ich bisher auch noch nie eine für mich nachvollziehbare Ordnung
erkennen konnte in der Art, wie opera damit umgeht (Es ist komischerweise sogar so, daß an
_verschiedenen Tagen_ unterschiedliche Anzeigen zustande kommen - also eher mirakulös...)

"... wie kann ich den einzelnen Einträgen noch Definitionen zuordnen? ..."

Ich würde mal versuchen, das Pferd andersrum aufzuzäumen - soll heißen:
welche Angaben sind für das Menu, das Dir vorschwebt, wichtig ?

Ich weiß nicht, ob Du Dir diesen thread mal angesehn hast:

http://www.devshare.com/forum/viewtopic.php?t=39815

Dabei geht's nämlich um ganz ähnliche Dinge, und ich kann in dieser
Datenstruktur beliebige Angaben unterbringen und auch leicht behandeln.

Versuch doch mal zu beschreiben, wie Dein Menu aussehn soll, bzw. welchen Anforderungen es
genügen muß.

gruß

matho

Re: mehrdimensionales Array

Hi Matho!

Ja, den Thread habe ich gelesen und das Endergebnis hat mich ein wenig erschlagen.

Naja, das Menü soll sich aus den Einträgen aus dem Array generieren, dabei soll abgefragt werden welche Punkte als sichtbar und unsichtbar definiert sind, die entsprechenden Ebenen sollen dann eingeblendet oder ausgeblendet werden. Außerdem soll das Array die Link-infos enthalten.
Die Menütiefe soll variabel bleiben.

Es ist echt Monate her, dass ich mich wieder intensiver mit js beschäftige.
Arrays habe ich in der letzten Zeit nur in PHP erstellt und habe damit auch keine Probleme...aber das Auslesen funkt in js noch ein bisschen anders (kommt mir jdf. so vor...).

Ich bin nicht an einer komplett-Lösung interessiert (da lernt man ja nichts), mir würde es reichen  :twisted:  , wenn du ein vorschlag zu dem Array machen würdest, da steh ich irgendwie voll auf der Leitung....

Ich glaube mein Fehler liegt allgemein darin, mir vorher zu wenig gedanken darum zu machen, was eigentlich meine Anforderungen sind...einen Plan sollte man schon haben smile

schöne Grüße

6

Re: mehrdimensionales Array

N'abend kaplar

"...und das Endergebnis hat mich ein wenig erschlagen...."

Das ist gut (ich meine, daß es Dich nicht ganz erschlagen hat), denn -
wie mein Opa immer gesagt hat: Was Dich nicht umbringt, härtet ab.

1.) "...das Menü soll sich aus den Einträgen aus dem Array generieren..."

eh schon klar, wobei ich's ganz praktisch finde (deshalb vor allem der
Verweis auf diesen andern thread), zum Notieren der Struktur eben
_keine_ Arrays zu verwenden, sondern Objecte.
Arrays kann man nehmen zur Notierung der diversen link-Spezfikationen,
aber genausogut kann man auch, wie in dem Beispiel aus dem andern thread,
komma-separierte strings nehmen, das ist nicht weiter wichtig.

2.) "...Die Menütiefe soll variabel bleiben...."

Das ist, wie bereits gezeigt, überhaupt kein Problem.

3.) "...dabei soll abgefragt werden welche Punkte als sichtbar und unsichtbar definiert sind,
        die entsprechenden Ebenen sollen dann eingeblendet oder ausgeblendet werden..."

Das ist nun ein Punkt, den ich nicht so recht verstehe. Soll das menu im Anfangszustand über
die Hauptkategorien hinaus (teilweise oder vielleicht zur Gänze) bereits aufgeklappt sein ?
Wenn ja, wozu ?

4.) "...Ich bin nicht an einer komplett-Lösung interessiert..."
Ausgesprochen löblich (zumindest im allgemeinen), hier jedoch ein wenig hinderlich (für mich).
Für mich ist's meist einfacher, ein Stückchen code zu posten, als irgendwas verständlich zu
erklären. Aber ich probier's mal:

Stell Dir mal Dein gesamtes Menu als Schachtel vor, also menu = schachtel.
Diese Schachtel kann Dinge enthalten - und zwar im Falle eines menus genau
zwo verschiedene Arten von Dingen: 1.) einfache links, oder 2.) ein Ding, das
ebenfalls eine schachtel ist, eine kleinere zwar, aber immerhin eine, die
genau den gleichen Gesetzmäßigkeiten unterliegt wie die größere - und das im
Prinzip ad infinitum.
Jedes dieser Dinge hat einen Namen - die einfachen Dinge ( die links ), genauso
wie die andern, die schachteln.
Eine Struktur, die diesen Sachverhalt 1:1 abbildet, läßt sich in javascript
sehr schön in object-Notation darstellen.
Besagtes menu = schachtel ist nichts anderes als

var menu = {}

Das kann man nun beliebig erweitern (in diesem Fall sollte man's auch geflissentlich tun):

var menu = { menu_1 : {   link_1 : 'wissenswert.htm',
                          link_2 : 'das_wollen_Sie_auch_wissen.htm',
                          link_3 : 'und_das_wollen_Sie_ganz_bestimmt_wissen.htm',
                          link_4 : ['heinz', 'zwo', 'trullalla', 17],
                        menu_1_1 : { //usw.
                                   },
                        menu_1_2 : { //usf.
                                   }
                      },
             menu_2 : { //etc.
                      },
             menu_3 : { //pp.
                      }
           }

Um nun auf irgendetwas zuzugreifen, sagst Du:

for ( var i in menu ) alert ( i + 'n' + menu[i] )

alert ( 'Bidääschään achtung jeds' )

for ( var i in menu.menu_1 ) alert ( i + 'n' + menu.menu_1[i] )

Ich hatte Deine function writeList als rekursive function geschrieben, damit
alle verschachtelten Ebenen erwischt werden ( man hangelt sich so lange durch
die Verschachtelungstiefen, bis es nix mehr zu hangeln gibt ).

Ein menu ist nun nichts anderes als eine event-gesteuerte rekursive function,
um's mal salopp zu formulieren - und das kannst Du im Beispiel aus dem andern
thread sehen (entweder werden tags erzeugt, oder der übergeordnete tag wird geleert).

Probleme, die bei der konkreten Umsetzung entstehen, haben eigentlich weniger
mit javascript zu tun, sondern, wie so oft, mit den unterschiedlichen Angewohnheiten
der diversen browser (insbesondere den Unterschieden in deren css-Auslegung).

Aufpassen mußt Du natürlich auch bei der Behandlung der verschiedenen events ( click,
oder mouseover-und out, usw.). Denn spätestens da mußt Du Dir sehr genau überlegen,
was denn im einzelnen infolge eines bestimmten events geschehen soll.

Das klingt jetzt notwendigerweise aweng nebulös, aber Du wolltest ja kein ausführliches
Beispiel. Also bin ich mal gespannt, wie's weitergeht.

gruß
matho

Re: mehrdimensionales Array

Hi!

ersteinmal danke ich für die Hilfe...
Bei mir ergeben sich aber gerade andere Sachen (keine Zeit mehr zum tüfteln), so dass ich das hier einstweilen auf Eis lege....

Bisher konnt ich das so umsetzen:

var menu = { Menu1 : {   link_1 : ['eins.html', false],
                         link_2 : ['zwei.html', false], 
                         link_3 : ['drei.html', false], 
                         menu_1_1 : {    link_1_1 : ['1.html', false],
                                         link_1_2 : ['2.html', false], 
                                         link_1_3 : ['3.html', false]
                                   }
                      }, 
             Menu2 : { //etc. 
                      }
           }  

A = function(o){return Object.prototype.toString.apply(o).substr(8, 5) == 'Array'}; 
O = function(o){return typeof o == 'object'}; 

var str = "";
function writeList(m, c) {
         for (var i in menu) {
            str += "<div class='cl1'>"+i+"</div>";
            for (var i in menu[i]){
                alert (i);
                str += "<div class='cl2'>"+i+"</div>"; 
            }
        }
}

werde aber zu gegebener Zeit diesen Thread fortführen...

schöne Grüße

Re: mehrdimensionales Array

werde aber zu gegebener Zeit diesen Thread fortführen...

und das mach ich jetzt auch. habe im Prinzip auch gar keine Fragen mehr, sondern eher ein Ergebnis smile das ich euch nicht vorenthalten will.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
    <title>explorer_menu</title>
<style type="text/css">
a {text-decoration:none;}
.text {font-family:arial,helvetica;font-size:10px;}
.head {font-family:arial,helvetica;font-size:16px;}
.cont {position:absolute;visibility:visible;top:50px;left:20px;width:150px;}

</style>
<script type="text/javascript">

// Browserunterscheidung 
 var name = navigator.appName.toLowerCase();
 var vers = navigator.appVersion.toLowerCase();
 var ua = navigator.userAgent.toLowerCase();
 var op, ko, mo, ns, ns6, ie;

     if (ua.indexOf("opera") != -1) {
        op = true;
    } 
    else if (name == "konqueror") {
        ko = true;
    } 
    else if ((name == "netscape") && (ua.indexOf("netscape") == -1) && (parseFloat(vers) >= 5)) {
        mo = true;
    } 
    else if (name == "netscape") {
        if(document.layers){
            ns = true;
        }
        else 
            ns6 = true;
    } 
    else {
        ie= true;
    }
// Browserunterscheidung    
    
// Konstruktor mit den Definitionen für das Menü wird erstellt
function init_menu(level,css,opened,description,filename){

    // der Level gibt an in welcher Ebene sich der Menüpunkt befinden soll.
    // Vergleiche: 0=1.Ebene;1=2.Ebene usw.
    this.level=level;    
    
    // gibt den Abstand in px nach links an
    this.css=css;    
    
    // Speichert den Sichtbarkeitsstatus. Ist die Ebene sichtbar/unsichtbar (offen/geschlossen)    
    // Ebene ist auf ~ true; Ebene ist zu ~ false
    this.opened=opened;
    
    // damit kann der Titel eines Menüpunktes definiert werden 
    this.description=description;
    
    // hier wird der Link festgelegt
    this.filename=filename;
}
// Konstruktor Ende

    // das Array mit den Objekten wird erstellt
    // Vergleiche mit dem obigen Konstruktor menu[0]:
    // level=0; opened=true; dscription=Bereichsmenue; filename=gruen.html
    // Hier wird also der gesamte Aufbau definiert....
    var menu=new Array;
    menu[0]=new init_menu(0,0,true,"Bereichsmenue","gruen.html");
    menu[1]=new init_menu(1,10,false,"Portfolio","black.html");
    menu[2]=new init_menu(2,20,false,"Vorlagen","farbe.html");
    menu[3]=new init_menu(1,10,false,"Management","farbe.html");
    menu[4]=new init_menu(2,20,false,"Vorstand","black.html");
    menu[5]=new init_menu(2,20,false,"Vorstand3","black.html");
    menu[6]=new init_menu(3,30,false,"Vorstand4","black.html");
    menu[7]=new init_menu(3,30,false,"Vorstand4","black.html");
    menu[8]=new init_menu(2,20,false,"Mitglieder","farbe.html");
    menu[9]=new init_menu(2,20,false,"Struktur","gruen.html");
    menu[10]=new init_menu(1,10,false,"Team","gruen.html");
    menu[11]=new init_menu(2,20,false,"Geist","farbe.html");
    menu[12]=new init_menu(3,30,false,"Kontakt","gruen.html");
    menu[13]=new init_menu(-1,0,false,"E-Mail","farbe.html");
    // Array Ende
    
    
// Variablen werden initialisiert/deklariert
var max=menu.length;
var menufeld;
var menuLaenge = 150;
// Variablen Ende


// print_explorer wertet das Array aus und baut die Grundstruktur auf
function print_explorer(){

    var i=1;
    menufeld ="";
    while (menu[i].level!=-1){
        if (menu[i].level<=max) {
        
            // das Menü wird mittels Tabellen strukturiert:
            menufeld += "<table border=0 cellpadding=0 cellspacing=0 width='100%'><tr><td align='left'>";
            menufeld += "<table border=0 cellpadding=0 cellspacing=0>";
                // wenn der Level=0 ist, dann führe Funktion menuhaupt() aus,
                if (menu[i].level==0){
                menuhaupt();
                }
                
            // hier wird festgelegt welche Menüpunkte Submenüs verbergen;
            else if ((menu[i].description=="Portfolio")||(menu[i].description=="Management")||(menu[i].description=="Team")||(menu[i].description=="Geist")||(menu[i].description=="Vorstand3")){
                menufeld +="<tr>";
                menufolder(i);
                menufeld +="</tr>";
            }
            
            // wenn die 'description' andere Strings enthält, schreibe ebenfalls eine Tabzeile und führe die funktionen menuleer()
            // und menufile() aus
            else {
                menufeld +="<tr>";
                menufile(i);
                menufeld +="</tr>";
            }
            
            // hier endet die Tabelle
            menufeld +="</table>";
            menufeld +="</td></tr></table>";
        }
    i++
    }

    // das menufeld wird in die Ebene geschrieben
    if (ie || op) {document.all.container.innerHTML = menufeld;}
    else {document.getElementById('container').innerHTML  = menufeld;}

}
// print_explorer Ende




// Funktion menuhaupt printet den 1. Navigationspunkt
function menuhaupt(){

    menufeld += "<tr><td><img src='tr.gif' border=0 width='" + menu[0].css +"' height=1></td><td class='head' width='100%'><nobr> <a href='" + menu[0].filename +"'>" + menu[0].description + "</a></nobr></td></tr><tr><td colspan='2'><img src='tr.gif' width='1' height='2'></td></tr>";
    if (menu[0].opened==false){
        max=0;
    }
    
    else {
    max=menu.length;
    }
    
}
// Funktion menuhaupt Ende


// menufolder() printet das Navigationsbildchen und überprüft dabei den Sichtbarkeitsstatus
// schreibt die aufklappbaren Menüpunkte
function menufolder(i){

    // tabWidth ermittelt die Länge der Tabellenspalten
    var tabWidth = menuLaenge - menu[i].css;

    // hier wird das Bild definiert für offene Menüpunkte !!achte auf die korrekte Pfadzuweisung (das gilt natürlich für alle Bilder)!!
    var bild1="orange.gif";
    // hier wird das Bild definiert für geschlossene Menüpunkte
    if (menu[i].opened==false) {bild1="black.gif";}
    
    menufeld +="<td align='right' width='" + menu[i].css +"'><a href='javascript:void(0);' target='inhalt' onclick='unopen(" + i + ");'><img src='" + bild1 + "' border=0></a></td><td class='text' width='" + tabWidth +"' bgcolor='#cccccc'><nobr> <a href='" + menu[i].filename +"' onclick='unopen(" + i + ");'>" + menu[i].description + "</a></nobr></td></tr><tr><td colspan='2'><img src='tr.gif' width='1' height='2'></td></tr>";
    if (menu[i].opened==false){max=menu[i].level;}
    else {max=menu.length;}
    
}
// menufolder Ende


// menufile() schreibt die nicht aufklappbaren Menüpunkte
function menufile (i) {

    menufeld +="<td><img src='tr.gif' width='" + menu[i].css +"' height=1 border=0></td><td class='text' bgcolor='#999999' width='100%'><nobr> <a href='" + menu[i].filename +"'>" + menu[i].description +"</a></nobr></td></tr><tr><td colspan='2'><img src='tr.gif' width='1' height='2'></td></tr>";

}
// menufile Ende


// unopen überprüft die Sichtbarkeit und ändert den Status in das Gegenteil
function unopen (nr) {

    menu[nr].opened=!menu[nr].opened;
    print_explorer();
    
}
// unopen Ende
</script>
</head>

<body bgcolor="#ffffff" alink="#ff0000" vlink="#0000ff" onload="print_explorer();">
<div id="container" class="cont"> </div>
</body>
</html>

vielleicht braucht das ja mal jmd.

tschöö