Teil von SELFHTML aktuell Teil von Artikel Teil von Dynamisches HTML

Lutz Eymers
Sitemap mit JavaScript und Layers

nach unten Lutz Eymers
nach unten Zum Thema
nach unten Das Script
nach unten Ausprobieren und Downloaden

Lutz Eymers

E-Mail: E-Mail lutz@polzin.com
Homepage-URL: deutschsprachige Seite http://www.polzin.com/inet/fset_inet.phtml?w=goodies&cont=cont_download.phtml%3Fid%3D1

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten

Zum Thema

Hierarchische Ordnerstruktur mit Javascript

Wenn man tief verzweigte hierarchische Verzeichnisstrukturen auf übersichtliche Weise darstellen möchte, kommt einem schnell die Darstellungsweise der Desktop Window Manager (Macintosh Finder, Irix 4Dwm, CDE, KDE) oder der MS-Explorer in den Sinn: Ordner werden per Mausklick auf- und zugeklappt, die Verzeichnisstruktur und Verzweigungen werden durch Einrücken dargestellt.

Wir haben ein Javascript Programm entwickelt, das die Darstellungsweise eines Desktop Window Managers oder eines Explorers nachahmt und per Mausklick die Verzeichnisstruktur aufklappt. Dieses Javascript Programm findet unserer Meinung nach die ideale Anwendung als Sitemap.

Voraussetzung für eine einwandfreie Funktionsweise sind Javascript 1.2 und CSS/Layers, also Netscape 4.0 oder höher bzw. MSIE 4.0 oder höher.

nach obennach unten

Das Script

Das Script sollte im Kopf der HTML-Datei notiert werden, welche die Sitemap darstellt.

  <SCRIPT language="JavaScript1.2">
  <!--

  /*
   * sitemap.js 1.31 05/02/2000
   *  - Opera 5
   *
   * sitemap.js 1.3 27/11/2000
   *  - Netscape 6
   *
   * sitemap.js 1.2 20/05/2000
   *  - split array tree into arrays for each element old tree
   *  - no mory type flag, an folder is an entry which has sons
   *  - a folder can have an link
   *  - while initing an default layers is shown
   *
   * sitemap.js 1.1 20/10/1999
   *  - showTree only updates and init layers new which have been really changed
   *  - add deep to knot entry
   *  - substitute knotDeep[ id ] w/ tree[ id2treeIndex[ id ] ].deep
   *  - add alignment to img and a &nbsp; at the beginning of eyery line
   *  - add a fake img for bookmarks on top panel
   *
   * sitemap.js 1.02 14/10/1999
   *  - fix bug in initStyles
   *
   * sitemap.js 1.01 06/10/1999
   *  - fix bug in knotDeep for Netscape 4.00-4.0.5
   *
   * sitemap.js 1.0 20/09/1999
   *
   * Javascript function for displaying hierarchic directory structures with
   * the ability to collapse and expand directories.
   *
   * Copyright (c) 1999 Polzin GmbH, Duesseldorf. All Rights Reserved.
   * Author: Lutz Eymers <ixtab@polzin.com>
   * Download: http://www.polzin.com/inet/fset_inet.phtml?w=goodies
   *
   * Permission to use, copy, modify, and distribute this software
   * and its documentation for any purposes and without fee
   * is hereby granted provided that this copyright notice
   * appears in all copies.
   *
   * Of course, this software is provided "as is" without express or implied
   * warranty of any kind.
   *
   */

  window.onError=null;

  var idx=0
  var treeId = new Array();
  var treeP_id = new Array();
  var treeIsOn = new Array();
  var treeTyp = new Array();
  var treeName = new Array();
  var treeUrl = new Array();
  var treeWasOn = new Array();
  var treeDeep = new Array();
  var treeLastY = new Array();
  var treeIsShown = new Array();

  function Note( id,p_id,name,url ) {
    treeId[ idx ] = id
    treeP_id[ idx ] = p_id
    treeIsOn[ idx ] = false
    treeTyp[ idx ] = 'f'
    treeName[ idx ] = name
    treeUrl[ idx ] = url
    treeWasOn[ idx ] = false
    treeDeep[ idx ] = 0
    treeLastY[ idx ] = 0
    treeIsShown[ idx ] = false
    idx++
  }

  function initDiv ( )
  {
    if ( isDOM || isDomIE )
    {
      divPrefix='<DIV CLASS="sitemap" style="position:absolute; left:0; top:0; visibility:hidden;" ID="sitemap'
      divInfo='<DIV CLASS="sitemap" style="position:absolute; visibility:visible" ID="sitemap'
    }
    else
    {
      divPrefix='<DIV CLASS="sitemap" ID="sitemap'
      divInfo='<DIV CLASS="sitemap" ID="sitemap'
    }
    document.writeln( divInfo +  'info">Bitte haben Sie etwas Geduld.<BR>&nbsp;<BR>Es werden die Eintr&auml;ge aus<BR>&nbsp;<BR>der Datenbank initialisiert.</DIV> ' );

    for ( var i=1; i<idx; i++ )
    {
      // linked Name ?
      if ( treeUrl[i] != '' )
        linkedName = '<A HREF="' + treeUrl[i] + '" TARGET="' + defaultTarget + '"><IMG SRC="1w.gif" BORDER="0" WIDTH="3">' + treeName[i] + '</A>'
      else
        linkedName =  '<IMG SRC="1w.gif" BORDER="0" WIDTH="3">' + treeName[i]
      // don't link folder icon if node has no sons
      if ( i == idx-1 || treeP_id[i+1] != treeId[i] ) {
        if ( treeDeep[ i ] == 0 )
          folderImg = '<IMG ALIGN="BOTTOM" SRC="file_empty.gif" BORDER="0" HEIGHT="16" WIDTH="1" HSPACE="0">'
        else
          folderImg = ''
      } else {
        folderImg = '<A HREF="javascript:sitemapClick(' + treeId[i] + ')"><IMG ALIGN="BOTTOM" SRC="folder_off.gif" BORDER="0" NAME="folder' + treeId[i] + '" HEIGHT="16" WIDTH="30" HSPACE="0"></A>'
      }
      // which type of file icon should be displayed?
      if ( treeP_id[i] != 0 )
      {
        if ( lastEntryInFolder( treeId[i] ) )
          fileImg = '<IMG ALIGN="BOTTOM" SRC="file_last.gif" BORDER="0" NAME="file'
            + treeId[i] + '" HEIGHT="16" WIDTH="30" HSPACE="0">'
        else
          fileImg = '<IMG ALIGN="BOTTOM" SRC="file.gif" BORDER="0" NAME="file'
            + treeId[i] + '" HEIGHT="16" WIDTH="30" HSPACE="0">'
      }
      else
        fileImg = ''
      // traverse parents up to root and show vertical lines if parent
      // is not the last entry on this layer
      verticales = ''
      for( var act_id=treeId[i] ; treeDeep[ id2treeIndex[ act_id ] ] > 1;  )
      {
        act_id = treeP_id[ id2treeIndex[ act_id ]]
        if ( lastEntryInFolder( act_id ) )
        {
          verticales = '<IMG ALIGN="BOTTOM" SRC="file_empty.gif" BORDER="0" HEIGHT="16" WIDTH="30" HSPACE="0">' + verticales
        }
        else
        {
          verticales = '<IMG ALIGN="BOTTOM" SRC="file_vert.gif" BORDER="0" HEIGHT="16" WIDTH="30" HSPACE="0">' + verticales
        }
      }


      document.writeln( divPrefix + treeId[i] + '"><NOBR>&nbsp;' + verticales + fileImg + folderImg + linkedName + '</NOBR></DIV><BR>'
      )
    }
  }

  function initStyles ( )
  {
    document.writeln( '<STYLE TYPE="text/css">' + "\n" + '<!--' )
    for ( var i=1,y=y0; i<idx; i++ )
    {
      document.writeln( '#sitemap' + treeId[i] + ' {POSITION: absolute; VISIBILITY: hidden;}' )
      if ( treeIsOn[ id2treeIndex[ treeP_id[i] ] ] )
        y += deltaY
    }
    document.writeln( '#sitemapinfo {POSITION: absolute; VISIBILITY: visible;}' )
    document.writeln( '//-->' + "\n" + '</STYLE>' )
  }



  function sitemapClick( id )
  {
    var i = id2treeIndex[ id ]

    if ( treeIsOn[ i ] )
    // close directory
    {
      // mark node as invisible
      treeIsOn[ i ]=false
      // mark all sons as invisible
      actDeep = treeDeep[ i ]
      for( var j=i+1; j<idx && treeDeep[j] > actDeep; j++ )
      {
        treeWasOn[ j ] = treeIsOn[ j ]
        treeIsOn[ j ]=false
      }
      gif_off( id )
    }
    else
    // open directory
    {
      treeIsOn[ i ]=true
      // remember and restore old status
      actDeep = treeDeep[ i ]
      for( var j=i+1; j<idx && treeDeep[j] > actDeep; j++ )
      {
        treeIsOn[ j ] = treeWasOn[ j ]
      }
      gif_on( id )
    }
    showTree()
  }

  function knotDeep( id )
  {
    var deep=0
    while ( true )
      if ( treeP_id[ id2treeIndex[id] ] == 0 )
        return deep
      else
      {
        ++deep
        id = treeP_id[ id2treeIndex[id] ]
      }
    return deep
  }

  function initTree( id )
  {
    treeIsOn[ id2treeIndex[id] ] = true
    if ( treeTyp[ id2treeIndex[id] ] != 'b' )
      gif_on( id )
    while ( treeP_id[ id2treeIndex[id] ] != 0 )
    {
      id = treeP_id[ id2treeIndex[id] ]
      treeIsOn[ id2treeIndex[id] ] = true
      if ( treeTyp[ id2treeIndex[id] ] != 'b' )
        gif_on( id )
    }
  }

  function lastEntryInFolder( id )
  {
    var i = id2treeIndex[id]
    if ( i == idx-1 )
      return true
    if ( treeTyp[i] == 'b' )
    {
      if ( treeP_id[i+1] != treeP_id[i] )
        return true
      else
        return false
    }
    else
    {
      var actDeep = treeDeep[i]
      for( var j=i+1; j<idx && treeDeep[j] > actDeep ; j++ )
      ;
      if ( j<idx && treeDeep[j] == actDeep )
        return false
      else
        return true
    }
  }

  function showTree()
  {
    for( var i=1, y=y0, x=x0; i<idx; i++ )
    {
      if ( treeIsOn[ id2treeIndex[ treeP_id[i] ] ] )
      {
        // show current node
        if ( !(y == treeLastY[i] && treeIsShown[i] ) )
        {
          showLayer( "sitemap"+ treeId[i] )
          setyLayer( "sitemap"+ treeId[i], y )
          treeIsShown[i] = true
        }
        treeLastY[i] = y
        y += deltaY
      }
      else
      {
        // hide current node and all sons
        if ( treeIsShown[ i ] )
        {
          hideLayer( "sitemap"+ treeId[i] )
          treeIsShown[i] = false
        }
      }
    }
  }

  function initIndex() {
    for( var i=0; i<idx; i++ )
      id2treeIndex[ treeId[i] ] = i
  }

  function gif_name (name, width, height) {
    this.on = new Image (width, height);
    this.on.src = name + "_on.gif"
    this.off = new Image (width, height);
    this.off.src = name + "_off.gif"
  }

  function load_gif (name, width, height) {
    gif_name [name] = new gif_name (name,width,height);
  }

  function load_all () {
    load_gif ('folder',30,16)
    file_last = new Image( 30,16 )
    file_last.src = "file_last.gif"
    file_middle = new Image( 30,16 )
    file_middle.src = "file.gif"
    file_vert = new Image( 30,16 )
    file_vert.src = "file_vert.gif"
    file_empty = new Image( 30,16 )
    file_empty = "file_empty.gif"
  }

  function gif_on ( id ) {
    eval("document['folder" + id + "'].src = gif_name['folder'].on.src")
  }

  function gif_off ( id ) {
    eval("document['folder" + id + "'].src = gif_name['folder'].off.src")
  }

  // global configuration
  var deltaX = 30
  var deltaY = 16
  var x0 = 5
  var y0 = 5
  var defaultTarget = 'examplemain'

  var browserName = navigator.appName;
  var browserVersion = parseInt(navigator.appVersion);
  var isIE = false;
  var isNN = false;
  var isDOM = false;
  var isDomIE = false;
  var isDomNN = false;
  var layerok = false;

  var isIE = browserName.indexOf("Microsoft Internet Explorer" )==-1?false:true;
  var isNN = browserName.indexOf("Netscape")==-1?false:true;
  var isOpera = browserName.indexOf("Opera")==-1?false:true;
  var isDOM = document.getElementById?true:false;
  var isDomNN = document.layers?true:false;
  var isDomIE = document.all?true:false;

  if ( isNN && browserVersion>=4 ) layerok=true;
  if ( isIE && browserVersion>=4 ) layerok=true;
  if ( isOpera && browserVersion>=5 ) layerok=true;


  function hideLayer(layerName) {
    if (isDOM)
      document.getElementById(layerName).style.visibility="hidden"
    else if (isDomIE)
      document.all[layerName].style.visibility="hidden";
    else if (isDomNN)
      document.layers[layerName].visibility="hidden";
  }

  function showLayer(layerName) {
    if (isDOM)
      document.getElementById(layerName).style.visibility="visible"
    else if (isDomIE)
      document.all[layerName].style.visibility="visible";
    else if (isDomNN)
      document.layers[layerName].visibility="visible";
  }

  function setyLayer(layerName, y) {
    if (isDOM)
      document.getElementById(layerName).style.top=y
    else if (isDomIE)
      document.all[layerName].style.top=y;
    else if (isDomNN)
      document.layers[layerName].top=y;
  }

  var id2treeIndex = new Array()

  // the structure is easy to understand with a simple example
  // p_id is the id of the parent
  // E0                                      ( id=0,p_id=-1 )
  //          E11                            ( id=1,p_id=0)
  //                     E111                ( id=2,p_id=1 )
  //                     E112                ( id=3,p_id=1 )
  //          E12                            ( id=4,p_id=0 )
  //                     E121                ( id=5,p_id=4 )
  //          E13                            ( id=6,p_id=0 )
  //                     E131                ( id=7,p_id=6 )
  //                                 E1311   ( id=8,p_id=7 )
  //                     E132                ( id=9,p_id=6 )
  // this is a multinary tree structure which is easy to
  // populate with database data :)

  function initArray()
  {
    Note(0,-1,'','')
    Note(1,0,'Tutorials','')
    Note(8,1,'HTML','')
    Note(10,8,'SelfHtml','http://de.selfhtml.org/')
    Note(3,1,'JavaScript','')
    Note(4,3, 'Netscape Guide 1.3','http://developer.netscape.com/docs/manuals/js/client/jsguide/index.htm')
    Note(7,3, 'Introduction to Javascript','http://rummelplatz.uni-mannheim.de/~skoch/js/script.htm')
    Note(12,1, 'Perl','')
    Note(14,12, 'Perl Tutorial','http://www.awu.id.ethz.ch/~didi/perl/perl_start.html')
    Note(13,1,'SQL','')
    Note(15,13, 'Introduction to SQL','http://w3.one.net/~jhoffman/sqltut.htm')
    Note(2,0, 'Reference Manuals','http://www.cls-online.de/htmlref/index.html')
    Note(11,2, 'HTML Version 3.2 Referenz','http://www.cls-online.de/htmlref/index.htm')
    Note(6,2,'Netscape Reference 1.3','http://developer.netscape.com/docs/manuals/js/client/jsref/index.htm')
    Note(17,2,'PHP Manual','http://www.php.net/manual/html/')
    treeTyp[0] = 'f'
    treeIsOn[0] = true
    treeWasOn[0] = true
  }

  var idx=0
  initArray()
  initIndex()
  load_all()
  for( i=1; i<idx; i++ )
  {
    treeDeep[i] = knotDeep( treeId[i] )
    if ( treeDeep[i] == 0 )
      treeIsShown[i] = true
  }
  if ( isDomNN )
    initStyles();

  //--></SCRIPT>

Die JavaScript Funktion muß innerhalb derselben Datei im Body-Tag initialisiert werden.

<BODY VLINK="#000000" LINK="#000000" BGCOLOR="#ffffff" TEXT="#000000"
 onLoad="if (layerok) showTree();">
<SCRIPT language="JavaScript1.2">
<!--
  initDiv()
  hideLayer("sitemapinfo")
//--></SCRIPT>
</BODY>

Wenn die Sitemap in einem eigenen Fenster geöffnet werden soll, kann man das Fenster mit folgender Funktion referenzieren. Die Funktion kann wahlweise im Body-Tag über onLoad oder innerhalb des Bodies als Link eingesetzt werden.

<SCRIPT LANGUAGE="Javascript">
<!--
  var lastopen = "quot;"quot;;
  var sitemapwin;
  var bver = "quot;nn2"quot;;
  var browserName = navigator.appName;
  var browserVersion = parseInt(navigator.appVersion);

  var isIE = browserName.indexOf("quot;Microsoft Internet Explorer"quot; )==-1?false:true;
  var isNN = browserName.indexOf("quot;Netscape"quot;)==-1?false:true;
  var isOpera = browserName.indexOf("quot;Opera"quot;)==-1?false:true;
  var isDOM = document.getElementById?true:false;
  var isDomNN = document.layers?true:false;
  var isDomIE = document.all?true:false;

  if ( isNN && browserVersion >gt;= 3) bver = "quot;nn3"quot;;
  if ( isNN && browserVersion >gt;= 4) bver = "quot;nn4"quot;;
  if ( isNN && browserVersion >gt;= 5) bver = "quot;nn5"quot;;
  if ( isIE && browserVersion >gt;= 3) bver = "quot;ms3"quot;;
  if ( isIE && browserVersion >gt;= 4) bver = "quot;ms4"quot;;
  if ( isIE && browserVersion >gt;= 5) bver = "quot;ms5"quot;;
  if ( isOpera && browserVersion >gt;= 5) bver = "quot;op5"quot;;

  function openmap(startpage) {
    if (bver == "quot;nn4"quot; || bver == "quot;nn5"quot; || bver == "quot;op5"quot;) {
      sitemapwin=window.open(startpage,'polzinsitemap','resizable=no,scrolling=no,status=no,location=no,menubar=no,toolbar=no,width=300,height=400');
      sitemapwin.focus();
    }
    if (bver == "quot;ms4"quot; || bver == "quot;ms5"quot; ) {
      sitemapwin=window.open(startpage,'polzinsitemap','resizable=no,scrolling=no,status=no,location=no,menubar=no,toolbar=no,width=300,height=388');
       setTimeout('sitemapwin.focus()',200);
    }
  }

  function openorfocus ( startpage ) {
    if ( typeof( sitemapwin ) != 'undefined' ) {
      if ( ! sitemapwin.closed && startpage==lastopen ) sitemapwin.focus();
        else openmap( startpage );
    }
    else openmap( startpage );
    lastopen = startpage
  }

  function closesitemap() {
    if ( typeof( sitemapwin ) != 'undefined' )
      if ( ! sitemapwin.closed )
        sitemapwin.close()
  }
//-->
</SCRIPT>

<A HREF="javascript:openorfocus()">Sitemap öffnen</A>

Es folgt eine kurze Übersicht über die definierten Funktionen

nach obennach unten

Ausprobieren und Downloaden

Der Inhalt für die Sitemap wird in dem linearen Array tree[] gespeichert und implementiert eine q-näre Baumstruktur. Jeder Knoten dieses Baums kann beliebig viele Söhne haben. Der oberste Knoten ist der mit dem Index 0. Beim Auffüllen dieses Array ist zu beachten, das eine festgelegte Reihenfolge beachtet werden muß. Man könnte die zu erwartende Struktur durch eine zusätzliche JavaScriptfunktion ein wenig verallgemeinern. Allerdings stellt die vorliegende Struktur keine inhaltliche Einschränkung dar. Idealerweise werden die zu ladenden Daten nicht manuell eingetragen, sondern mit einer serverseitigen rekursiven Funktion sortiert, z.B. wenn man das Array mit Werten aus einer Datenbank auffüllt.

Man trägt einfach von oben nach unten Zeile für Zeile einer vollaufgeklappten Sitemap Knoten für Knoten nacheinander in das Array ein, wie es im Beispiel auch getan wird. Wenn man für den Index immer den Wert i++ verwendet, läßt sich auf diese Weise elegant und ohne zusätzlichen Aufwand ein neuer Folder oder Bookmark an einer beliebigen Stelle nachträglich hinzufügen.

Seite Die Sitemap im Explorer- bzw. Streifenlayout öffnen.
(JavaScript-Verweise - bitte normal mit linker Maustaste anklicken!)

ZIP-Datei sitemap.zip downloaden
(enthält alle erforderlichen Dateien)

Teil von SELFHTML aktuell Teil von Artikel Teil von Dynamisches HTML

© 2007 bereichsübergreifende Seite Impressum