Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Erstellung eines Intranets in ASP (Teil 4) - Mitarbeiter

Geschrieben von: Alexander Zeitler
Kategorie: ASPIntranet.de

Auch heute heiße ich Sie wieder herzlich willkommen - und zwar zum vierten Teil der Artikelserie zur Erstellung eines Intranets mit ASP. Heute werden wir den bereits aus dem zweiten Teil bekannten Setup-Assistenten in abgewandelter Form als Mitarbeiterassitenten bereitstellen. Außerdem werden wir eine Treeview zur Mitarbeiterverwaltung entwickeln. Zur Navigation innerhalb des Intranets werden wir eine Navigationsleiste programmieren.

Beachten Sie bitte, daß alle in diesem (und folgenden) Teil(en) gezeigten Datenbanktabellen in die bereits bestehende Datenbank aspintranet.mdb importiert werden müssen, um zu vermeiden, daß bereits durchgeführte Setups oder angelegte Mitarbeiter überschrieben werden.

Die Treeview

Die erste Erweiterung unseres Intranets, die wir heute schaffen werden, ist die Treeview zur Verwaltung aller mitarbeiterbezogenen Anwendungen. Damit Sie sich ein Bild von dem geplanten Ergebnis machen können, zunächst ein Screenshot:

Die Treeview ist, wie im Bild zu sehen, in zwei Teile untergliedert: den Punkt "Verwaltung" und die Auflistung aller Mitarbeiter (da zur Zeit nur ein Mitarbeiter existiert, ist diese Liste entsprechend kurz). Innerhalb des Menüpunktes "Verwaltung" werden wir Funktionen zur Verwaltung grundlegender, mitarbeiterbezogener Daten integrieren, wie z.B. den bereits angezeigten Menüpunkt "Mitarbeiter bearbeiten". Innerhalb des angezeigten Mitarbeiters werden wir Funktionen integrieren, welche sich ausschließlich auf den jeweiligen Mitarbeiter beziehen - so z.B. allgemeine Informationen (im Screenshot zu sehen).

Um diese Optionen leicht erweitern oder verändern zu können, werden wir diese in einer Tabelle in unserer Datenbank speichern. Später werden wir uns hierfür eine Administrationsseite erstellen, um direktes Arbeiten in der Datenbank zu vermeiden. Die neue Tabelle trägt den Namen "Mitarbeiter_Optionen":

Die Felder sind durch die Beschreibung im Screenshot bereits erklärt. Der Grund für das Feld "OptionTyp" ist folgender: auf einen Mitarbeiter bezogene Funktionen benötigen für den Aufruf diverse Parameter, während Funktionen, die sich auf alle Mitarbeiter beziehen, ohne Parameter aufgerufen werden. Somit ergeben sich zwei Optionstypen, die in dem Feld "OptionTyp" gespeichert werden.

Eine weitere Ergänzung, die Sie zur Integration des Treeviews oder allgemeiner der Mitarbeiterverwaltung benötigen, sind vier neue Unterverzeichnisse innerhalb unseres Intranet-Verzeichnisbaumes:

Die Mitarbeiterverwaltung besteht insgesamt aus 3 Frames, deren Framesets in der Datei default.asp im Verzeichnis "mitarbeiter" definiert werden. Diese Datei beinhaltet keinerlei ASP-Code, ebenso wie die im Frameset aufgerufene Datei "treetitle.asp", die optischen Zwecken dient. Für uns interessant und unser nächstes Ziel ist die Datei tree.asp, welche ebenfalls im Verzeichnis "mitarbeiter" abgelegt wird. Sie beinhaltet die Logik für die Treeview, zu der wir uns bereits eingangs Gedanken gemacht haben. Diese werden wir nun durch eine Kombination von ASP und JavaScript in die Tat umsetzen.

Der Grundgedanke der Treeview ist, möglichst viele Informationen möglichst platzsparend und gut strukturiert darzustellen. Dies wird dadurch erreicht, daß zunächst nur die Hauptpunkte der Verwaltung dargestellt werden. Durch einen Klick auf einen der Punkte wird dieser nach unten "ausgeklappt", so daß die darin enthaltenen Menüpunkte sichtbar werden. Natürlich ist Ihnen dieses Funktion aus unzähligen Windows-Anwendungen bekannt. Um diese Funktion nachzuprogrammieren benötigen wir grundlegend folgendes JavaScript:

<script type="text/javascript" language="JavaScript">
<!--//
function toggle(Tabelle,Node,Buch,Suffix)
    {
    var IsClosed = true;
    IsClosed = Tabelle.style.getAttribute("display")=="none";
    if(IsClosed==false)
    {
    Tabelle.style.setAttribute("display","none");
        ToggleString="images/tree_plus" + Suffix + ".gif";
        Node.src=ToggleString;
        Buch.src="images/tree_buch.gif";
    }
    else
    {
        Tabelle.style.setAttribute("display","inline");
        ToggleString="images/tree_minus" + Suffix + ".gif";
        Node.src=ToggleString;
        Buch.src="images/tree_buch_open.gif";
    }
    }
//-->
</script>

Das HTML-Grundgerüst der Treeview besteht aus mehreren HTML-Tabellen, die numeriert werden, sodaß sie eindeutig identifizierbar und via JavaScript ansprechbar sind. Diese Tabellen enthalten die Grafiken und Texte der Treeview. Um den Ausklappeffekt zu realisieren, müssen Tabellen, die die Hauptmenüpunkte enthalten, sichtbar sein, und Tabellen mit Untermenüpunkten zunächst unsichtbar sein. Beim Klick auf einen Hauptmenüpunkt müssen die darunterliegenden Menüpunkte oder genauer, die Tabellen in denen sie enthalten sind, sichtbar werden. Bei nochmaligem Klick auf den Hauptmenüpunkt sollen die Tabellen mit den Untermenüpunkten wieder unsichtbar werden.

Aus visuellen Gründen ändern sich außerdem zum jeweiligen Zustand passend die Grafiken (auch diese werden numeriert). Das obenstehende Skript erledigt eben diese Aufgaben. Nach dem Aufruf des Skripts (durch den Event-Handler Onclick, dazu später mehr) liest dieses zunächst die Nummer der Tabelle, des Icons für das Expandieren/Schließen des Menüpunkts, des Icons für das angezeigte Buch sowie das Suffix des Icons für das Expandieren/Schließen des Menüpunkts. Der Grund für die Verwendung eines Suffixes für das Icons ist folgender: Hauptmenüpunkte und Untermenüpunkte, welche am Ende der jeweiligen Liste stehen, müssen durch ein anderes Icon dargestellt werden, als solche, die am Anfang oder innerhalb der Liste stehen. Welches Suffix verwendet wird, entscheidet später unser ASP-Skript.

Nach dem Einlesen der Parameter liest das Skript den Display-Status der übergebenen Tabelle aus:

IsClosed = Tabelle.style.getAttribute("display")=="none";

Ist die Tabelle bereits sichtbar, so wird der neue SRC-Parameter des Icons für das Expandieren/Schließen des Menüpunkts so gesetzt, daß das Icon ein Plus-Zeichen darstellt, welches dem Anwender zeigt, daß der Zweig der Treeview ausgeklappt werden kann. Danach wird dieser dem Icon zugewiesen. Ebenso wird der SRC-Tag des zugehörigen Buches geändert, so daß dieses nun geschlossen erscheint.

Ist die Tabelle unsichtbar, so wird der soeben beschriebene Vorgang so ausgeführt, daß der Ausklappeffekt eintritt.

Um das JavaScript zum Leben zu erwecken, müssen wir nun mit ASP die Tabellen, Grafiken und Texte aus den Datenbanktabellen "Mitarbeiter_Optionen" und "Mitarbeiter" generieren lassen.

Zunächst überprüfen wir, ob denn überhaupt Mitarbeiter in der Tabelle "Mitarbeiter" vorhanden sind. Ist dies nicht der Fall, so muß der Hauptmenüpunkt "Verwaltung" zugleich der erste als auch der letze Eintrag im Treeview sein:

StrSQL = "SELECT ID FROM Mitarbeiter ORDER BY Nachname,Vorname"
Set rs = Conn.Execute(StrSQL)
'Nein, dann merken
If rs.Eof Then bNoEntries = True
'Zähler für Toplevel-Nodes initialisieren
IntCountTopNodes = 0
'Zähler erhöhen
IntCountTopNodes = IntCountTopNodes + 1

Der Zähler IntCountTopNodes wird zunächst mit dem Wert "0" initialisiert und dann erhöht. Dieser Zähler ist für die bereits erklärte Numerierung der Tabellen und Grafiken zuständig.

Die Erklärung des nächsten Codeabschnitts steht exemplarisch für diesen und die drei darauffolgenden:

If bNoEntries = True Then
    Response.Write "<img id=""node" & IntCountTopNodes & """ SRC=""images/tree_plus_last.gif"" 
        WIDTH=20 HEIGHT=24 BORDER=0 onclick=""toggle(Tabelle" & IntCountTopNodes & ",node" & 
        IntCountTopNodes & ",treenode" & IntCountTopNodes & ",'_last')"" class=""TreeImgLink"">"
Else
    Response.Write "<img id=""node" & IntCountTopNodes & """ SRC=""images/tree_plus.gif"" 
        WIDTH=20 HEIGHT=24 BORDER=0 onclick=""toggle(Tabelle" & IntCountTopNodes & ",node" & 
        IntCountTopNodes & ",treenode" & IntCountTopNodes & ",'')"" class=""TreeImgLink"">"
End If

Zunächst wird überprüft, ob keine weiteren Hauptmenüpunkte folgen (bNoEntries = True). Entsprechend wird die Grafik mit dem Plus-Zeichen für das Ende der Liste oder den Anfang/Mittelteil der Liste angezeigt. Außerdem wird der Grafik ein eindeutiger Wert mittels "IntCountTopNodes" zugewiesen. Weiterhin wird das Onlick-Event generiert. Zunächst folgt der Aufruf der JavaScript-Funktion "toggle", gefolgt von den Parametern, die wir bei der Definition der JavaScript-Funktion festgelegt hatten. Auch diese werden mit dem Wert von "IntCountTopNodes" versehen. Der letzte Parameter ist das bereits angesprochene Suffix, welches entweder "_last" lautet oder leer ist. "_last" findet sich im Dateinamen der entsprechenden Grafiken wieder.

Nach den folgenden drei identischen If-Abfragen für die weiteren Grafiken und Texte des gleichen Hauptmenüpunkts folgt die Definition der untergeordneten Tabelle (welche ja die Untermenüpunkte beinhaltet):

Response.Write "<table cellspacing=0 cellpadding=0 BORDER=0 id=""Tabelle" & IntCountTopNodes & """ 
    style=""display:none"">" & VbCrLf

Auch hier findet sich die Numerierung mit immer noch dem gleichen Wert von "IntCountTopNodes" wieder. Außerdem wird hier der STYLE der Tabelle definiert, welcher dafür zuständig ist, daß die Tabelle zunächst unsichtbar ist.

Würden wir jetzt auf den Hauptmenüpunkt "Verwaltung" klicken, würden sich bereits die Grafiken entsprechend verändern. Allerdings fehlen uns noch die Einträge für die Untermenüpunkte. Diese lassen wir nun aus der Tabelle "Mitarbeiter_Optionen" generieren:

Set rs1 = Server.CreateObject ("ADODB.Recordset")
rs1.Cursortype = 1 'adOpenKeyset
rs1.Locktype = 3 'adLockOptimistic
rs1.Open "SELECT * FROM Mitarbeiter_Optionen WHERE OptionTyp = 2", Conn
rs1.Movelast
IntLetzter = rs1("id")
rs1.Movefirst
Do While Not rs1.Eof
    Response.Write "<tr>" & VbCrLf
    Response.Write "<td>"
    If IntLetzter = rs("id") Then
        Response.Write "<img src=""images/tree_empty.gif"" width=""20"" 
            height=""24"" border=""0"" alt="""">"
    Else
        Response.Write "<img SRC=""images/tree_ebene1.gif"" 
            WIDTH=20 HEIGHT=24 BORDER=0>"
    End If
    Response.Write "</td>" & VbCrLf
    Response.Write "<td>"
    If IntLetzter = rs1("id") Then
        Response.Write "<img SRC=""images/tree_node_last.gif"" 
            WIDTH=20 HEIGHT=24 BORDER=0>"
    Else
        Response.Write "<img SRC=""images/tree_node.gif"" 
            WIDTH=20 HEIGHT=24 BORDER=0>"
    End If
    Response.Write "</td>" & VbCrLf
    Response.Write "<td>"
    Response.Write "<img SRC=""images/node.gif"" WIDTH=""12"" 
        HEIGHT=""15"" BORDER=""0"" alt="""">"
    Response.Write "</td>" & VbCrLf
    Response.Write "<td class=""TreeNode"">&nbsp;"
    Response.Write "<a href=""" & rs1("url") & """ onFocus=blur()>" & rs1("option") & "</a>"
    Response.Write "</td>" & VbCrLf
    Response.Write "</tr>" & VbCrLf
    rs1.Movenext
Loop

Zunächst lassen wir alle Mitarbeiter-Optionen vom Typ "2" (also alle allgemeinen mitarbeiterbezogenen) aus der Tabelle "Mitarbeiter_Optionen" lesen. Im Anschluß springen wir zum letzten Datensatz, um dessen ID in der Variable "IntLetzter" zu speichern. Nach einem Sprung an den Anfang des Recordsets prüfen wir, ob die ID des Datensatzes identisch ist mit der ID des letzten Datensatzes. Ist dies der Fall muß das Untermenüpunkt-Icon angezeigt werden, das den letzten Eintrag in der Liste der Untermenüpunkte markiert. Sind die IDs verschieden, so wird der Eintrag normal (also am Anfang oder innerhalb der Liste) dargestellt. Danach wird der Titel der aktuellen Option ausgegeben, welchem der entsprechende Link zur Anwendung zugeordnet wird.

Die Treeview für den Bereich "Verwaltung" ist damit bereits voll funktionstüchtig. Der Aufbau für die Auflistung der Mitarbeiter unterscheidet sich nur unwesentlich. Die erste SQL-Abfrage dient nun nicht mehr zur Überprüfung, ob Mitarbeiter vorhanden sind, sondern der Ermittlung des letzten Eintrages und der anschließenden Ausgabe der Mitarbeiter. Die Abfrage aus dem Verwaltungsteil, die auf "bNoEntries = True" prüfte wird hier ersetzt durch "IntLetzter = rs("id")", da hier - wie soeben erwähnt - nicht mehr überprüft wird, ob keine Datensätze vorhanden sind, sondern welcher der letzte Datensatz ist. Die Generierung der eindeutig numerierten Grafiken und Tabellen ist identisch. Wichtig zu erwähnen ist allerdings, daß der Zähler "IntCountTopNodes" nicht mehr mit "0" initialisiert werden darf, sondern bei dem Wert weiterzählt, den er zuletzt für den Bereich "Verwaltung" hatte. Würde er neu initialisiert werden, wäre die Eindeutigkeit der Tabellen und Grafiken nicht mehr gewährleistet und unsere JavaScript-Funktion würde mit Fehlermeldungen den Dienst verweigern.

Der nächste Unterschied zwischen den beiden Teilen des Treeviews liegt in der SQL-Abfrage für die Optionen. Logischerweise müssen nun die auf einen bestimmten Mitarbeiter bezogenen Optionen gelesen werden, der Options-Typ ist also "1":

rs1.Open "SELECT * FROM mitarbeiter_optionen WHERE OptionTyp = 1 ORDER BY Option", Conn

Der letzte Unterschied liegt in der Generierung des Links zur Anwendung. Die auf einen bestimmten Mitarbeiter bezogenen Anwendungen benötigen beim Aufruf dessen ID, damit dieser aus der Datenbank gelesen werden kann. Außerdem übergeben wir den vollständigen Namen des Mitarbeiters (nehmen Sie dies im Moment als gegeben hin - weshalb das so ist, sehen Sie später):

Response.Write "<a href=""" & rs1("url") & "?id=" & rs("id") & "&name=" & 
    Server.UrlEncode(rs("nachname") & "&nbsp;" & rs("vorname")) & """ 
    target=""mitarbeitercontent"" onFocus=blur()>" & rs1("option") & "</a>"

Somit ist die Treeview voll einsetzbar und wir können uns der ersten im Screenshot der Treeview dargestellten Anwendung zuwenden: dem Bearbeiten von Mitarbeitern, im weiteren Verlauf "Mitarbeiterassitent" genannt.

Mitarbeiterassistent

Der Mitarbeiterassistent ist Ihnen in seinen Grundzügen bereits im zweiten Teil unserer Artikelserie begegnet - in Form des "Setupassistenten". Wir werden diesen nun so modifizieren, daß wir in der Lage sind, Mitarbeiter hinzuzufügen, deren Daten zu bearbeiten oder sie zu löschen.

Der erste und einfachste, weil eigentlich schon komplett vorhandene, Teil ist das Anlegen neuer Mitarbeiter. Der Aufruf des Mitarbeiterassistenten erfolgt durch die Funktion "doModalMA()" in der Datei tree.asp, welche wir soeben besprochen hatten. Der Aufbau der Funktion "doModalMA()" ist nahezu identisch mit der Funktion "doModalSetup()" aus dem zweiten Kurs-Teil. Die Erklärungen finden Sie also dort.

Das gleiche gilt auch für die Erläuterungen zum Anlegen eines neuen Mitarbeiters. Die Funktionen bzw. Seiten zum Anlegen der Betriebsdaten wurden komplett entfernt.

Die erste echte Neuerung offenbart sich gleich beim Start des Mitarbeiterassistenten. Dort wurde eine Auswahl für das Anlegen, Ändern und Löschen von Mitarbeitern eingebaut:

Der hierfür notwendige Code befindet sich in der Datei step0.asp und besteht aus HTML-Radio-Feldern . Eine weitere, auf den ersten Blick nicht sichtbare Erweiterung ist, daß alle im Mitarbeiterassistenten vorkommenden Sessionvariablen gelöscht werden. Dies ist notwendig, um zu vermeiden, daß z.B. Daten, die während des Bearbeitens eines Mitarbeiters eingegeben wurden, später bei der Neuanlage eines Mitarbeiters bereits in den entsprechenden Feldern stehen. Das Löschen der Sessionvariablen geschieht, indem man Ihnen den Wert "Null" zuweist.

Die mittels der Radiofelder getroffene Auswahl wird in der Datei "step05.asp" ("05" steht hierbei für einen Zwischenschritt zwischen Schritt "0" und Schritt "1". Genauer wäre "0,5", was jedoch im Filesystem nicht unbedingt günstig ist)ausgewertet:

If Request.Form("action") = "anlegen" Then Response.Redirect("step1.asp")
If Request.Form("action") = "bearbeiten" Then Response.Redirect("stepchange0.asp")
If Request.Form("action") = "loeschen" Then Response.Redirect("stepdel1.asp")

Dort findet dann entsprechend der Auswahl eine Weiterleitung zu den jeweiligen Eingangsseiten der Auswahl statt.

Um Ihnen an dieser Stelle einen Überblick über den Aufbau des gesamten Assistenten zu geben, hier ein Flowchart:

Um zu vermeiden, daß Mitarbeiter, die keine Berechtigung besitzen, den Assistenten bzw. die Mitarbeiterverwaltung aufzurufen, dies über den direkten Aufruf der Seiten im Browser tun, wurde eine Überprüfung der Rechte in alle Seiten des Assistenten implementiert. Diese befindet sich als Funktion "Check_Appl_Right" in der bekannten Datei functions.asp:

Function Check_Appl_Right(ApplID, UserID)
Dim StrSQL
Dim rs
    If (ApplID <> "") AND (IsNumeric(ApplID) = True) AND 
        (UserID <> "") AND (IsNumeric(UserID) = True) Then
        StrSQL = "SELECT COUNT(*) FROM OLMenueRechte WHERE (IDMenuepunkt = " & ApplID & ") 
            AND (IDBenutzer = " & UserID & ")"
        Set rs = Conn.Execute(StrSQL)
        If rs(0) > 0 Then
            Check_Appl_Right = True
        Else
            Check_Appl_Right = False
        End If
    Else
    Response.Write "Keine Parameter übergeben"
    End If
End Function

An diese Funktion werden die IDs der zu prüfenden Anwendung und Benutzers übergeben. Die SQL-Anweisung prüft, ob in der Tabelle "OLMenueRechte" Einträge vorhanden sind, bei denen beide IDs vorhanden, also ob der Benutzer Rechte für diese Anwendung besitzt. Ist dies der Fall, liefert die Funktion "True" zurück. Andernfalls wird "False" zurückgegeben.

Der Aufruf des Sicherheitschecks in den Seiten des Mitarbeiterassistenten sieht dann wie folgt aus:

If Check_User = False Then
    Response.Redirect("/~include/error.asp?Error=5")
    Response.End
Else
    If (Check_Appl_Right(2,Session("Logged_In_User_Id")) = False) Then
        Response.Redirect("/~include/error.asp?Error=5")
        Response.End
    End If
End If

Zunächst wird überprüft, ob ein Mitarbeiter am Intranet angemeldet ist. Ist dies der Fall, wird die Überprüfung der Berechtigung durchgeführt.

Die ID der Anwendung "Mitarbeiter" ist "2". Die ID des Benutzers ist in diesem Fall die ID des eingeloggten Benutzers. Es könnten aber auch andere ID-Werte übergeben werden, was die Funktion "Check_Appl_Right" flexibel einsetzbar macht.

Sollte kein Benutzer angemeldet sein oder "Check_Appl_Right" "False" zurückliefern, wird der "Eindringling" auf seine fehlende Berechtigung hingewiesen. Lieferten hingegeben beide Abfrage "True" wird der Aufbau der Seite fortgesetzt. Diese Prüfung findet sich auch in anderen Anwendungen der Mitarbeiterverwaltung wieder.

Da das Anlegen neuer Mitarbeiter bereits im zweiten Teil der Artikelserie ("Setupassistent") erklärt wurde, wenden wir uns dem Bearbeiten von bestehenden Mitarbeitern zu. Wie aus dem vorangegangenen Code-Snippet ersichtlich ist, startet das Ändern von Mitarbeiterdaten in der Datei stepchange0.asp.

Diese besteht im wesentlichen aus einer Selectbox, in welcher alle Mitarbeiter aufgelistet werden, deren Daten zur Bearbeitung freigegeben sind. Nicht angezeigt werden sollen Benutzer, denen ein nicht löschbarer NetzwerkUser zugewiesen wurde, wie z.B. der beim Setup angelegte Benutzer mit den Rechten, Mitarbeiter zu verwalten. Die hierzu notwendige SQL-Abfrage sieht wie folgt aus:

StrSQL = "SELECT Mitarbeiter.Vorname, Mitarbeiter.Nachname, Mitarbeiter.ID FROM Mitarbeiter INNER JOIN 
    NetzwerkUser ON  Mitarbeiter.NetzwerkUser = NetzwerkUser.ID 
   WHERE NetzwerkUser.IstLoeschbar = True ORDER BY 
    Mitarbeiter.Nachname, Mitarbeiter.Vorname"

Nachdem die Daten in die Selectbox eingetragen wurden, werden diese nach einem Klick auf den "Weiter"-Button mit der bereits bekannten JavaScrip-Routine überprüft. Wurde ein Mitarbeiter zum Bearbeiten ausgewählt, gelangen wir auf die Seite stepchange05.asp. Dort werden alle Daten, die zum ausgewählten Mitarbeiter gehören aus den Tabellen "Mitarbeiter" und "Mitarbeiter_Arbeitszeiten" ausgelesen und in die bekannten Session-Variablen gespeichert. Ebenso wird die ID des Mitarbeiters in der Sessionvariable "MAID" gespeichert. Danach erfolgt eine Weiterleitung auf die Seite stepchange1.asp. Diese und alle weiteren Dateien bis "stepchange6.asp" sind absolut identisch mit den Dateien step1.asp bis step6.asp zum Anlegen neuer Mitarbeiter.

Der letzte Schritt innerhalb des Assitenten, die Datei stepchange7.asp, welche für die Speicherung der geänderten Mitarbeiterdaten zuständig ist, erfuhr einige Änderungen im Vergleich zu step7.asp. So wird zunächst die Sessionvariable "MAID" in eine lokale Variable gespeichert. Diese ID ist notwendig, um nur die Datensätze des bearbeiteten Mitarbeiters in den Tabellen "Mitarbeiter" und "Mitarbeiter_Arbeitszeiten" upzudaten. Die SQL-Anweisungen wurden so modifiziert, daß anstelle der Neuanlage eines Datensatzes (rs.AddNew mit anschließendem rs.Update) ein bestehender Datensatz upgedatet wird (nur rs.Update). Wie Sie sehen, war also auch dieser Vorgang kein Hexenwerk und wir können uns der letzten Option in step0.asp zuwenden: dem Löschen eines Mitarbeiters, was in der Datei stepdel1.asp seinen Anfang nimmt.

Auch hier gelten für die Auswahl der Mitarbeiterdaten aus der Datenbank in die Selectbox die gleichen Bedingungen, wie für das Bearbeiten der Mitarbeiter. Nach der Auswahl eines solchen und dem Klicken auf den "Weiter"-Button" wird die JavaScript-Funktion "delete_submit()" ausgeführt:

<script language="JavaScript">
<!--
function delete_submit() 
    {
if(document.madel.mitarbeiter.selectedIndex==-1)
    {
    alert("Sie haben keinen Mitarbeiter ausgewählt!");
    }
else
    {  
    Check = confirm("Soll der Mitarbeiter wirklich unwiderruflich gelöscht werden?");
if (Check == false)
    {
    }
else
    document.madel.submit();
    }
}// end function delete_submit
//-->
</script>

Auch hier findet zunächst die Prüfung statt, ob ein Mitarbeiter gewählt wurde. Ist dies der Fall, wird mittels der JavaScript-Funktion confirm() abgefragt, ob der Mitarbeiter wirklich gelöscht werden soll. Entsprechend der Eingabe des Benutzers wird entweder die Seite stepdel2.asp aufgerufen oder der Löschvorgang abgebrochen. Da unser Ziel das Löschen eines Mitarbeiters war, gelangen wir auf die besagte Seite stepdel2.asp, deren Kernstück die SQL-Anweisung zum Löschen des ausgewählten Mitarbeiters ist:

ID = Request.Form("mitarbeiter")
StrSQL = "DELETE * FROM mitarbeiter WHERE ID = " & ID & ""
Set rs = Conn.Execute(strSQL)
Set rs = Nothing
Conn.Close

Natürlich wurde auch hier die übergebene ID auf Manipulation geprüft:

If (ID <> "") AND (IsNumeric(ID) = True) Then

und im Fehlerfall entsprechend reagiert:

Else
    Response.Write "<table>" & VbCrLf
    Response.Write "<tr>" & VbCrLf
    Response.Write "    <td class=""assistentheadline"">Fehler</td>" & VbCrLf
    Response.Write "</tr>" & VbCrLf
    Response.Write "<tr>" & VbCrLf
    Response.Write "    <td class=""assistent""><br>Es ist ein schwerwiegender Fehler 
        aufgetreten.<br><br>Starten Sie das Intranet neu."
    Response.Write "</td>" & VbCrLf
    Response.Write "</tr>" & VbCrLf
    Response.Write "</table>" & VbCrLf
End If

Zunächst wird die über das Formular übergebene ID des ausgewählten Mitarbeiters in die lokale Variable "ID" gespeichert, welche dann als Kriterium für die WHERE-Klausel der darauffolgenden SQL-DELETE-Anweisung eingesetzt wird. Nach dem Schließen der Datenbank-Verbindung bleibt dem Benutzer der Klick auf den "Beenden"-Button, welcher den Mitarbeiterassistenten und unsere Erklärungen zu selbigem beenden.

Mitarbeiterübersicht

Natürlich wollen wir die Daten unserer Mitarbeiter, die wir angelegt haben nicht nur bearbeiten oder löschen, sondern irgendwann auch zu Informationszwecken einsehen können und evtl. auch ausdrucken. Wir benötigen also eine Seite, die uns die Informationen zum jeweiligen Mitarbeiter auflistet.

Diesen Anforderungen trägt die Datei maoverview.asp im Verzeichnis "mitarbeiter" Rechnung. Das Ergebnis soll wie folgt aussehen:

Wie Sie vielleicht völlig zu Recht vermuten, hält sich der Aufwand für die eigentliche Anzeige der Daten in Grenzen. Es handelt sich hierbei um eine SQL-Abfrage, die wie folgt aussieht:

If (ID <> "") AND (IsNumeric(ID) = True) Then
    StrSQL = "SELECT * FROM Mitarbeiter WHERE mitarbeiter.id = " & ID & " order by mitarbeiter.nachname"
    Set rs = Conn.Execute(strSQL)

Inzwischen selbstverständlich ist auch die Überprüfung, ob die Eingabe manipuliert wurde.

Im Screenshot ist zu sehen, daß wir Informationen aus mehreren Datenbanktabellen darstellen, so zum Beispiel die Telefonnummer des Mitarbeiters. Diese befindet sich nicht in der Tabelle "Mitarbeiter", sondern in der Tabelle "Telefonnummern". Ähnlich ist es bei den Feldern "Anrede", "Briefanrede", "Telefax", "Mobil", "E-Mail", "Netzwerkuser" sowie den Arbeitszeiten und Pausen. Da die Abfrage hierfür bis auf die Namen der Datenbanktabellen identisch sind, erkläre ich den Vorgang exemplarisch anhand der "Anrede":

StrSQL1 = "SELECT * FROM Anreden WHERE ID = " & rs("Anrede") & ""
Set rs1 = Conn.Execute(StrSQL1)
If Not rs1.Eof Then	Response.Write rs1("Anrede")
rs1.Close
Set rs1 = Nothing

Zunächst lassen wir den Datensatz auslesen, dessen ID identisch ist mit der ID des gewählten Mitarbeiters. Um Fehlermeldungen über nicht gefundene Einträge zu vermeiden, prüfen wir vor der Ausgabe ob Datensätze vorhanden sind.

Damit möchte ich die Erklärungen zur Ausgabe der Mitarbeiter-Informationen abschließen, nicht jedoch zu der Datei maoverview.asp. Diese beinhaltet am Seitenende einen folgenschweren Funktionsaufruf:

DoNav("Mitarbeiterauskunft: " & Request.Querystring("name"))

Wenn Sie vermuten, daß dies mit der im Screenshot zu den Mitarbeiterinformationen oben zu sehenden Navigationsleite zusammenhängt, liegen Sie richtig.

Navigationsleiste

Im ersten Teil unserer Artikelserie hatten wir definiert, daß wir unabhängig von den Möglichkeiten des Browsers innerhalb des Intranets navigieren wollen und Informationen der Anwendungen ohne Browser-Informationen im Ausdruck ausdrucken möchten.

Die komplette Funktionialität dieser Navigationsleiste befindet sich in der Funktion "DoNav()" in der Datei functions.asp, welche sich in unserem "~include"-Verzeichnis befindet.

Das Grundgerüst der Navigationsleiste besteht im wesentlichen aus einer HTML-Tabelle, welche den Titel der Seite (der via Querystring übergeben wird) und drei Grafiken enthält, die die Icons für den Aufruf der folgenden Funktionen darstellen (von links nach rechts in der Navigationsleiste):

  • Home = zur Startseite
  • Drucken = Ausdruck der aktuellen Seite ohne Navigationsleiste und Browserinformationen
  • Aktualisieren: Reload der aktuellen Seite

Entsprechend der Aufzählung werde ich Ihnen nun die einzelnen Funktionen erläutern, beginnend mit dem Titel der Seite. Dieser wird beim Funktionsaufruf, wie in der Datei maoverview.asp zu sehen, übergeben und in der HTML-Tabelle an der hierfür vorgesehenen Position angezeigt.

Das war nicht schwer. Noch einfacher gestaltet sich die Anzeige des "Home"-Icons - hier wird lediglich das Frameset verändert, wie wir es bereits im dritten Teil des Kurses des öfteren verwendet hatten:

Onclick="top.inhalt.frameinhalt.cols='100%'"

Damit wird erreicht, daß der erste Frame (welcome.asp), in dem die Anwendungen dargestellt werden, in seiner vollen Größe angezeigt wird.

Wesentlich aufwendiger ist die Generierung des "Druck"-Icons. Hierzu zunächst etwas Theorie. Die Druckansicht soll aus der jeweils geöffneten Anwendungsseite generiert werden. Hierzu ist es also notwendig, daß die Daten in der Druckansicht zur Verfügung stehen. Der einfachste Weg ist also, die Seite einfach "as is" darzustellen und nur die Navigationselemente auszublenden. Hieraus ergibt sich die Anforderung für eine Variable, die der Seite mitteilt, ob sie normal, also mit Navigationselementen oder in der Druckansicht dargestellt werden soll. Weiterhin benötigen wir eine ActiveX Control, welche es ermöglicht, die Browserinformationen, welche standardmäßig in Ausdrucken erscheinen, zu unterdrücken, ohne daß man diese bei jedem Ausdruck händisch deaktivieren müßte. Hierbei handelt es sich um "MeadCo's ScriptX". Soviel zur Theorie - schreiten wir zur Tat.

Laut Theorie benötigen wir eine Variable, die uns angibt, welche Darstellung verwendet werden soll. Hierbei handelt es sich um die Variable "Do_Print". Diese wird beim Klick auf das "Drucken"-Icon via Querystring an die Seite, die gedruckt werden soll, übergeben:

Response.Write "<a href=""javascript:PrintWindow('"
Response.Write Request.ServerVariables("path_info")
Response.Write "?do_print=1&"

Wie Sie sehen, wird zum Aufruf der Druckansicht die JavaScript-Funktion "PrintWindow" aufgerufen, welche nichts anderes macht, als die Seite in der Druckansicht in einem neuen Fenster zu öffnen. Der übergebene Dateiname wird aus der Servervariable "Path_Info" gelesen. Somit ist gewährleistet, daß die aktuell geöffnete Seite in der Druckansicht angezeigt und gedruckt wird.Eine weitere Notwendigkeit ist, daß alle Variablen, die via Querystring an die Seite übergeben wurden (z.B. ID's), nochmals übergeben werden, damit die Funktionalität der Seite auch in der Druckansicht gewährleistet ist. Folgender Code erledigt diese Aufgabe:

For Each Element In Request.Querystring
    Response.Write Element
    Response.Write "="
    Response.Write Server.URLEncode(Request.QueryString(Element))
    Response.Write "&"
Next

Die "For Each"-Schleife liest alle Einträge, die in der Request.Querystring-Collection gespeichert sind, aus und hängt diese mit ihren jeweiligen Werten an den String an.

Die Variable "Do_Print" steht somit zur Auswertung durch die Funktion "DoNav()" zur Verfügung, welche wie folgt aussieht:

If Do_Print <> 1 Then 

Ist "Do_Print" tatsächlich nicht "1", so soll die Seite normal dargestellt werden, d.h. die Navigationsleiste wird generiert und angezeigt.

Ist "Do_Print" hingegen "1", so wird die Navigationsleiste nicht dargestellt. Statt dessen wird folgender Code abgearbeitet:

Response.Write "<object id=""factory"" classid=""clsid:1663ed61-23eb-11d2-b92f-008048fdd814"""
Response.Write "  viewastext codebase=""/~include/ScriptX.cab#Version=5,0,5,35"">"
Response.Write "  </object>" & VbCrLf
Response.Write "<script defer>" & VbCrLf
Response.Write "function window.onload() {" & VbCrLf
Response.Write "  factory.printing.header = "" """ & VbCrLf
Response.Write "  factory.printing.footer = "" """ & VbCrLf
Response.Write "  factory.printing.Print()" & VbCrLf
Response.Write "  window.close()" & VbCrLf
Response.Write "}" & VbCrLf
Response.Write "</script>" & VbCrLf

Zunächst wird das ActiveX-Control "ScriptX" eingebunden. Sollte es noch nicht installiert sein (was der Normalzustand sein dürfte), erhalten Sie eine Abfrage, ob das Control in Ihrem Browser installiert werden soll. Diese beantworten Sie bitte mit "Ja".

Das darauf folgende Skript übergibt dann notwendige Parameter an "ScriptX", welche dafür sorgen, daß das Skript nach dem Laden der Seite ausgeführt wird. Außerdem werden die Kopf- und Fußzeilen für den Ausdruck gelöscht. Im Anschluß daran wird die Druckfunktion des Browsers aufgerufen.

Nach dem Schließen des Drucken-Dialogs (unabhängig davon, ob die Seite gedruckt wurde) wird die Druckansicht schließlich automatisch geschlossen.

Das Schlüsselwort "defer" im "script"-Tag unterbindet Ausgaben durch das Skript. Dies ist gemäß der Dokumentation von "ScriptX" notwendig.

Kommen wir nun zum letzten Icon in der Navigationsleiste - dem Reload. Dieser besteht, wie auch die "Home"-Funktion nur aus einer JavaScript-Anweisung:

javascript:location.reload()

Am Ende der Definition der Navigationsleiste befindet sich der Aufruf der JavaScript-Funktion "UpdateIt()". Diese sieht wie folgt aus:

<script language="JavaScript">
function UpdateIt()
{
document.all["menu"].style.top = document.body.scrollTop;
setTimeout("UpdateIt()", 0);
}
</script>

Sinn und Zweck dieser Funktion ist, daß die Navigationsleiste immer am oberen Rand der Seite bleibt. Dies wird dadurch erreicht, daß der Layer "menu" ständig (durch den SetTimeout-Befehl mittels body. scrollTop an den oberen Rand verschoben wird, auch wenn der Inhalt der Seite nach unten gescrollt wird.

Wichtig in diesem Zusammenhang ist auch, daß der eigentliche Inhalt der Seite in einem Layer dargestellt werden muß, damit die Funktion "UpdateIt()" korrekt arbeitet. Die Definition des Layers ist in der Seite maoverview.asp zu sehen.

Hiermit haben wir unsere erste einfache Intranet-Anwendung erstellt, die uns basierend auf der Arbeit aus den bisherigen Artikeln eine Übersicht über die Daten zu unseren Mitarbeitern liefert, welche wir auch ausdrucken können.

Administration der Mitarbeiter-Optionen

Zum Abschluß des heutigen Artikels möchte ich Ihnen noch eine Administrationsseite für die eingangs des Artikels besprochenen Mitarbeiter-Optionen erläutern. Diese ist sehr stark an die Administrationsseite für die Outlook-Menüleiste angelehnt. Deshalb möchte ich auch nur grob auf die wesentlichen Änderungen eingehen.

Das Grundgerüst der Seite ist gleich geblieben. Die Administrationsseite für die Mitarbeiter-Optionen befindet sich im Verzeichnis /~admin/ma_opt.

Im linken IFrame wurde die Datei welcome.asp den neuen Funktionen angepasst. Der rechte Iframe trägt nun den Namen "TREE" anstelle von "OLMENU". Wie in der vorangegangenen Administrationsseite basieren auch hier die Seiten im rechten Frameset auf den Dateien, welche im Intranet verwendet werden. In der Datei tree.asp, welche nun im rechten IFrame angezeigt wird, wurde ein neuer Menüpunkt eingeführt, der es ermöglicht, neue Mitarbeiter-Optionen anzulegen. Da diese Funktion bis auf die Feld- bzw. Datenbanktabellennamen identisch ist mit den Funktionen der Administration aus dem dritten Teil, gehe ich hier nicht näher darauf ein.

Eine weitere Erweiterung der Datei tree.asp liegt darin, daß zu Beginn der Seite geprüft wird, ob Optionen für den Punkt "Verwaltung" bzw. mitarbeiterbezogene Optionen vorhanden sind:

StrSQL = "SELECT Count(*) FROM Mitarbeiter_Optionen WHERE OptionTyp = 1"
Set rs = Conn.Execute(StrSQL)
If rs(0) = 0 Then bNoOptions1 = True
StrSQL = "SELECT Count(*) FROM Mitarbeiter_Optionen WHERE OptionTyp = 2"
Set rs = Conn.Execute(StrSQL)
If rs(0) = 0 Then bNoOptions2 = True

Die SQL-Abfragen prüfen die Tabelle "Mitarbeiter_Optionen" mittels einer COUNT-Abfrage mit dem Kriterium des jeweiligen Optionstyps auf das Vorhandensein von Mitarbeiteroptionen. Ist dies der Fall, so werden die Variablen "bNoOptions1" bzw. "bNoOptions" auf "True" gesetzt. Wir verwenden hier eine COUNT-Abfrage, da diese immer nur einen Datensatz liefert (nämlich die Anzahl). Eine normale SELECT-Abfrage würde hier mit steigender Anzahl von Optionen immer mehr Datensätze liefern, was die Abfrage langsamer macht als nötig wäre.

Die hieraus logischerweise resultierende Änderung in dieser Datei ist, daß diese Variablen zu einem späteren Zeitpunkt geprüft werden.

Dies ist immer dann der Fall, wenn ein Grafiksymbol oder Text ausgegeben werden soll, welcher im Onclick-Event die JavaScript-Funktion "toggle()" aufruft. Der Übersicht halber wurde die Onclick-Anweisung in einen String verlagert, der bei jeder Zählererhöhung von IntCountTopNodes neu erzeugt wird. Da wir jedoch zwei Aufrufe für die Funktion "toggle()" haben, benötigen wir zwei Strings, nämlich "StrToggle" und "StrToggleLast", entsprechend, ob der Funktion das Suffix "_last" übergeben werden soll oder nicht:

StrToggleLast=" onclick=""toggle(Tabelle" & IntCountTopNodes & ",node" & IntCountTopNodes 
    & ",treenode" & IntCountTopNodes & ",'_last')"""
StrToggle=" onclick=""toggle(Tabelle" & IntCountTopNodes & ",node" & IntCountTopNodes & ",
    treenode" & IntCountTopNodes & ",'')"""

Examplarisch für alle auftretenden Prüfungen von "bNoOptions(1 oder 2)" hier ein Beispiel:

If bNoEntries = True Then
    Response.Write "<img id=""node" & IntCountTopNodes & """ SRC=""/mitarbeiter/images/tree_plus_last.gif"" 
        WIDTH=20 HEIGHT=24 BORDER=0"
If bNoOptions2 <> True Then Response.Write StrToggleLast
Response.Write " class=""TreeImgLink"">"
Else
    Response.Write "<img id=""node" & IntCountTopNodes & """ SRC=""/mitarbeiter/images/tree_plus.gif"" 
        WIDTH=20 HEIGHT=24 BORDER=0"
If bNoOptions2 <> True Then Response.Write StrToggle
Response.Write " class=""TreeImgLink"">"
End If

Zunächst findet die Überprüfung von "bNoEntries" statt, welche festlegt, ob "toggle()" mit oder ohne Suffix aufgerufen wird. Danach folgt die Prüfung von "bNoOptions2" auf "True" und dem Ergebnis entsprechend wird entweder "StrToggleLast" bzw. "StrToggle" oder kein String ausgegeben. Wird kein String ausgegeben, so existiert in dem betroffenen HTML-Element (hier das Pluszeichen-Icon) kein Onclick-Event, d.h. der Menüpunkt "Verwaltung" (in diesem Fall) lässt sich nicht mehr ausklappen. Das war auch unser Ziel, denn wenn keine Optionen für diesen Menüpunkt existieren, darf dieser nicht ausklappbar sein.

Mit dieser Einschränkung geht auch einher, daß die Abfrage und Ausgabe der Optionen nicht aufgerufen werden darf. Entsprechend wird vor Ausgabe der HTML-Tabelle, welche die Optionen beinhaltet eine entsprechende Abfrage gestartet:

If bNoOptions2 <> True Then

Ist "bNoOptions2" nicht True wird die Tabelle generiert, sonst nicht.

Die soeben beschriebenen Änderungen wurden auch auf die mitarbeiterbezogenen Optionen angewendet oder besser auf den Code, der diese erzeugt.

Die letzte Erweiterung ist die, daß rechts von den Optionen zwei Icons für das Löschen und Ändern von Optionen eingefügt wurden. Auch diese sind Ihnen bereits aus dem dritten Artikel bekannt, ebenso wie die Funktionen, die dahinter stehen.

Schlußbemerkung

Hiermit sind wir am Ende des vierten Teils unserer Artikelserie angelangt. Mit den heutigen Neuerungen haben wir die Grundlagen geschaffen, um weitere Intranet-Anwendungen leicht in das Grundgerüst integrieren zu können und einheitliche Funktionen für alle Anwendungen des Intranets bereitzustellen. Darauf aufbauend werden wir morgen, im letzten Teil des aktuellen Kurses, weitere Anwendungen für unser Intranet erarbeiten.

Redaktioneller Hinweis

Aufgrund des Umfanges des Intranets - und der damit möglichen Fehlerquellen bei der Umsetzung auf den unterschiedlichen Serverkonfigurationen der Leser - bittet der Autor, die Anfragen über öffentliche Foren (so zum Beispiel aspGerman) oder die ASPIntranet Mailingliste abzuwickeln. Fehler in ASPIntranet können Sie auf der Bugreport-Seite von ASPIntranet melden.

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Erstellung eines Intranets in ASP - Grundlagen
Erstellung eines Intranets in ASP (Teil 2) - Setup
Erstellung eines Intranets in ASP (Teil 3) - Navigation
Erstellung eines Intranets in ASP (Teil 5) - Application Day

Links zu anderen Sites

MeadCo's ScriptX
MSDN: scrollTop
selfhtml: confirm
selfhtml: defer
selfhtml: SetTimeout

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.