Seite 1 von 8

neues modul :: splittedNavigation

Verfasst: Mo 28. Nov 2005, 11:27
von kummer
hallo zusammen

hier das neuste elaborat aus unserem haus für die version 4.6.2. es handelt sich dabei um eine geteilte navigation.

hier der code (erkärungen dazu weiter unten):

Code: Alles auswählen

<?php
/**
  * $Revision: 1.22 $
  * $Source: D:/cvs/cvsrepo/test/PPI_Nade/module/mainNavigation/output.php,v $
  * $Date: 2005/11/28 10:20:39 $
  */

/**
 * navigation
 * @author Andreas Kummer
 * @copyright Copyright &copy; 2005 w3concepts AG
 */

if (!class_exists('navigation')) {
	
	class navigation {
		
		/**
		 * Konstruktor der Klasse.
		 * @param Integer  Primärschlüssel der Startkategorie.
		 */
		function navigation($startId) {
			
			global $client, $lang, $idcat;
			
			$this->startId = $startId;
			
			$this->client = $client;
			$this->lang = $lang;
			$this->idcat = $idcat;
			
			$this->before = '';
			$this->beforeEach = '';
			$this->between = '';
			$this->after = '';
			
			$this->db = new DB_Contenido();
	
			$this->setStartIds();
			
			$this->getNavigation();
		}
		
		/**
		 * Auslesen der Navigationsstruktur aus der Datenbank.
		 */
		function getNavigation() {
			
			global $cfg;
			
			if ($this->startId != $this->id[0]) {
				/*
				 * Wenn die StartId nicht identisch ist mit der höchsten Ebene der
				 * aktuell selektierten Kategorie, dann liegt die gewählte Kategorie
				 * folgerichtig ausserhalb des für die Navigation gewählten Baumes.
				 * In diesem Fall ist nur die Hauptnavigation einzublenden.
				 */
				$this->id[0] = $this->startId;
				for ($i = 1; $i <= 3; $i++) {
					$this->id[$i] = -1;
				}
			}
			
			$this->db->query("" .
					"SELECT " .
					"	a.idcat, " .
					"	a.parentid, " .
					"	a.preid, " .
					"	a.postid, " .
					"	a.parentid, " .
					"	b.visible, " .
					"	b.name, " .
					"	b.idlang " .
					"	FROM {$cfg['tab']['cat']} AS a " .
					"LEFT JOIN {$cfg['tab']['cat_lang']} AS b ON a.idcat = b.idcat " .
					"WHERE " .
					"	a.idclient = {$this->client} " .
					"	AND (" .
					"		a.parentid = {$this->id[0]} " .
					"		OR a.parentid = {$this->id[1]} " .
					"		OR a.parentid = {$this->id[2]} " .
					"		OR a.parentid = {$this->id[3]} " .
					"	) " .
					"");
			
			$this->navigationTree = array();
			
			$this->firstId[0] = 0;
			$this->firstId[1] = 0;
			$this->firstId[2] = 0;
			$this->firstId[3] = 0;
			while ($this->db->next_record()) {
				for ($i = 0; $i <= 3; $i++) {
					if (($this->firstId[$i] == 0 && $this->db->f('parentid') == $this->id[$i] && $this->db->f('preid') == 0 && $this->db->f('idlang') == $this->lang) || ($this->firstId[$i] == 0 && $this->db->f('parentid') == $this->id[$i] && $this->db->f('preid') == 0 && $this->db->f('idlang') == null)) {
						$this->firstId[$i] = $this->db->f('idcat');
					}
				}
				$this->navigationTree[$this->db->f('parentid')][$this->db->f('idcat')] = array('preid'=>$this->db->f('preid'), 'postid'=>$this->db->f('postid'), 'visible'=>$this->db->f('visible'), 'name'=>$this->db->f('name'), 'idlang'=>$this->db->f('idlang'));
			}
		}
		
		/**
		 * Ausgabe der Navigation an die Standardausgabe.
		 * @param String  Navigationstyp
		 */
		function showNavigation($type, $next = -1) {
			
			static $first;
			static $output = false;
			
			if ($next == 0) {
				return false;
			}
			
			if ($next == -1) {
				echo $this->before;
				$next = $this->firstId[$type];
				$first = true;
			}
			
			$parentId = $this->id[$type];
			
			$link = 'front_content.php?idcat='.$next;
			
			if ($this->navigationTree[$parentId][$next]['visible'] == 1 && $this->navigationTree[$parentId][$next]['idlang'] == $this->lang) {
				if (!$first) {
					echo $this->between;
				}
				if ($this->isSelected($next)) {
					echo $this->beforeSelected;
				} else {
					echo $this->beforeEach;
				}
				echo '<a href="'.$link.'">'.$this->navigationTree[$parentId][$next]['name'].'</a>';
				$first = false;
				$output = true;
			} elseif (!$output && $this->navigationTree[$parentId][$next]['postid'] == 0) {
				/*
				 * Die Navigation enthält nichts.
				 */
				 echo ' ';
			}
			
			$this->showNavigation($type, $this->navigationTree[$parentId][$next]['postid']);
		}
		
		/**
		 * Ausgabe vor der Navigation
		 * @param String  Ausgabe vor der Navigation.
		 */
		function before($text) {
			$this->before = $text;
		}
		
		/**
		 * Ausgabe vor jedem Eintrag
		 * @param String  Ausgabe vor jedem Eintrag.
		 */
		function beforeEach($text) {
			$this->beforeEach = $text;
		}
		
		/**
		 * Ausgabe vor jedem selektierten Menueintrag
		 * @param String  Ausgabe vor jedem selektierten Menueintrag.
		 */
		function beforeSelected($text) {
			$this->beforeSelected = $text;
		}
		
		/**
		 * Ausgabe zwischen zwei Hauptmenupunkten
		 * @param String  Ausgabe zwischen zwei Hauptmenupunkten.
		 */
		function between($text) {
			$this->between = $text;
		}
		
		/**
		 * Ausgabe nach der Navigation
		 * @param String  Ausgabe nach der Navigation.
		 */
		function after($text) {
			$this->after = $text;
		}
		
		/**
		 * Gibt das Level der Kategorie zurück.
		 * @param Integer  Primärschlüssel der Kategorie.
		 * @return Integer Level der spezifizierten Kategorie.
		 */
		function getLevel($idcat) {
			
			global $cfg;
			
			if (empty($idcat)) {
				return 0;
			}
			
			$this->db->query("" .
					"SELECT level FROM {$cfg['tab']['cat_tree']} " .
					"WHERE " .
					"	idcat = $idcat" .
					"");
			if ($this->db->next_record()) {
				return $this->db->f('level');
			} else {
				return 0;
			}
		}
		
		/**
		 * Gib die Tiefe relativ zum Hauptmenu an.
		 * @param Integer  Primärschlüssel der Kategorie
		 * @return Integer Level relativ zum Hauptmenu
		 */
		function getNetLevel($idcat) {
			
			return $this->getLevel($idcat) - $this->getLevel($this->startId);
		}
		
		/**
		 * Ermittlung des jeweils ersten Kategorieeintrages jeder Ebene. Die
		 * Speicherung dieser Daten erfolgt in das Klassenattribut id.
		 */
		function setStartIds() {
			
			$id = $this->idcat;
			
			$level = $this->getNetLevel($id);
			$this->id[$level] = $id;
			
			while ($level > 0) {
				$this->id[$level-1] = $this->getParentId($id);
				$id = $this->id[$level-1];
				$level = $this->getNetLevel($id);
			}
			
			if (empty($this->id)) {
				$this->id[0] = $this->startId;
			}
			for ($i = 1; $i <= 3; $i++) {
				if (empty($this->id[$i])) {
					$this->id[$i] = -1;
				}
			}
			ksort($this->id);
		}
		
		/**
		 * Ermittlung des Elternelementes der Kategorie mit dem Primärschlüssel
		 * idcat
		 * @param Integer  Primärschlüssel des Kindelementes, dessen Elternelement
		 * ermittelt werden soll.
		 * @return Integer Primärschlüssel des Elternelementes.
		 */
		function getParentId($idcat) {
			
			global $cfg;
			
			$this->db->query("" .
					"SELECT parentid FROM {$cfg['tab']['cat']} " .
					"WHERE " .
					"	idcat = $idcat " .
					"");
			if ($this->db->next_record()) {
				return $this->db->f('parentid');
			} else {
				return 0;
			}
		}
		
		/**
		 * Anzeige, ob eine Navigationsebene Elemente enthält oder nicht.
		 * @param Integer  Navigationsstufe.
		 * @return Boolean True, wenn die Navigationsstufe leer ist (keine Elemente
		 * enhält). Sonst false.
		 */
		function navigationEmpty($level) {
			
			if ($this->firstId[$level] == 0) {
				return true;
			}
			
			return false;
		}
		
		/**
		 * Anzeige, ob eine Kategorie selektiert ist oder nicht. Eine Kategorie gilt
		 * als selektiert, wenn sie die aktuelle Kategorie ist oder ein direktes
		 * oder indirektes Elternelement der aktuellen Kategorie.
		 * @param Integer  Primärschlüssel der Kategorie, deren Status gefragt ist.
		 * @return Boolean True, wenn die gefragte Kategorie mit der aktuellen
		 * Kategorie übereinstimmt oder ein direktes oder indirektes Elternelement
		 * der aktuellen Kategorie darstellt.
		 */
		function isSelected($idcat) {
			
			return in_array($idcat, $this->id);
		}
	}
}

$navigation = new navigation("CMS_VALUE[0]");
$navigation->between('<img src="/cms/images/templateImages/spacer.png" width="10" height="1"/>');
$navigation->beforeEach('<img src="/cms/images/templateImages/spacer.png" width="10" height="1"/>');
$navigation->beforeSelected('<img src="/cms/images/templateImages/pfeilWeiss.png"/>');
$navigation->showNavigation(0);
?>
die reihenfolge der aufrufe (also ob zuerst hauptnavigation und danach unternavigationen oder umgekehrt) spielt keine rolle. derjenige container, der als erstes abgearbeitet werden wird, sollte einfach die klasseninstantiierung vornehmen. für die folgenden ausgaben reicht dann der aufruf...

Code: Alles auswählen

$navigation->showNavigation(0);
einfach mit den richtigen index (0 = hauptnavigation, 1 = subnavigation, 2 = subsubnavigation usw.).

die werte für beforeEach, beforeSelected und between könne jeweils vor dem aufruf der showNavigation wieder geändert werden.

hope this is usefull!

regards,
andreas

ps: und man braucht für den input natürlich noch die klasse chooseTree:

Code: Alles auswählen

?><?
/**
  * $Revision: 1.7 $
  * $Source: D:/cvs/cvsrepo/test/PPI_Nade/module/articleList/input.php,v $
  * $Date: 2005/11/25 17:41:12 $
  */

/**
  * chooseTree
  * @author Andreas Kummer
  * @copyright Copyright &copy; 2005 w3concepts AG
  */

if (!class_exists('chooseTree')) {

	class chooseTree {
		
		function chooseTree($selected, $index) {
			
			global $lang, $client;
			
			$this->selected = $selected;
			$this->index = $index;
			$this->lang = $lang;
			$this->client = $client;
			
			$this->db = new DB_Contenido();
			$this->queryStructure();
			
			$this->outputInterface();
		}
		
		function queryStructure() {
			
			global $cfg;
			
			$this->db->query("" .
					"SELECT " .
					"	a.idcat, " .
					"	a.level, " .
					"	c.name " .
					"FROM {$cfg['tab']['cat_tree']} AS a, " .
					"{$cfg['tab']['cat']} AS b, " .
					"{$cfg['tab']['cat_lang']} AS c " .
					"WHERE " .
					"	a.idcat = b.idcat " .
					"	AND b.idcat = c.idcat " .
					"	AND c.idlang = '{$this->lang}' " .
					"	AND b.idclient = '{$this->client}' " .
					"	AND c.visible=1 " .
					"ORDER BY " .
					"	a.idtree" .
					"");
					
			$this->structure = array();
			while ($this->db->next_record()) {
				$this->structure[$this->db->f('idcat')] = array('level'=>$this->db->f('level'), 'name'=>$this->db->f('name'));
			}
		}
		
		function outputInterface() {
			
			/*
			 * Tabellenanfang ausgeben
			 */
			echo "<table cellspacing=\"0\" cellpadding=\"10\" border=\"0\">";
			
			/*
			 * Zeilenanfang ausgeben
			 */
			echo "<tr><td>Baum wählen:</td><td>";
			
			/*
			 * Select-Feld ausgeben
			 */
			echo $this->getSelect($this->structure, $this->index);
			
			/*
			 * Zeilenende ausgeben
			 */
			echo "</td></tr>";
			
			/*
			 * Tabellenende ausgeben
			 */
			echo "</table>";
		}
		
		function getSelect($structure, $name) {
			
			$returnValue = '<select size="1" name="'.$name.'" class="text_medium">'."\n";
			
			foreach ($structure as $idcat => $item) {
				if ($idcat == $this->selected) {
					$selected = ' selected = "selected"';
				} else {
					$selected = '';
				}
				
				$spaces = "|";
				for ($i = 0; $i < $item['level']; $i ++) {
					$spaces = $spaces . "--";
				}
				$spaces .= ">";
				
				$returnValue .= '<option value="'.$idcat.'"'.$selected.'>'.$spaces.$item['name'].'</option>';
			}
			
			$returnValue .= '</select>'."\n";
			
			return $returnValue;
		}
	}
}

$chooseTree = new chooseTree("CMS_VALUE[0]", "CMS_VAR[0]");

Verfasst: Mo 28. Nov 2005, 14:12
von jost
Sehr nützlich, Danke Kummer!!

Verfasst: Mo 28. Nov 2005, 20:01
von Thorsten Gruber
vielleicht irgendein Beispiel zur Hand ? :oops:
das wäre Super denn so ganz versteh ich das gerade nicht. Kennst mich ja :D

Verfasst: Di 29. Nov 2005, 03:09
von mvf
Thorsten Gruber hat geschrieben:vielleicht irgendein Beispiel zur Hand ? :oops:
das wäre Super denn so ganz versteh ich das gerade nicht. Kennst mich ja :D
da schliesse ich mich doch direkt an.

geteilte navi für 4.6.2 klingt suuuuuper,
aber was wenn man blond wie ich ist :oops:

Verfasst: Di 29. Nov 2005, 08:37
von kummer
ok, lasst mich das mal versuchen:

zuerst muss man entscheiden, in welcher reihenfolge die ausgaben gemacht werden. die frage lautet also, was wird zuerst abgearbeitet? die hautpnavi oder die subnavi oder die subsubnavi. denn in derjenigen stufe, die als erstes abgearbeitet wird, muss die klasseninstantiierung erfolgen. folgendes beispiel zeigt die ausgabe der Hauptnavigation:

Code: Alles auswählen

<?php

/*
 * Initialisierung der Navigation
 */
$navigation = new navigation("CMS_VALUE[0]");

/*
 * Festlegung des HTML-Codes, der jeweils zwischen zwei Menupunkten ausgegeben
 * werden soll. Dabei handelt sich sich zum Beispiel um eine Zeilenschaltung.
 */
$navigation->between('<img src="/cms/images/templateImages/spacer.png" width="10" height="1"/>');

/*
 * Festlegung des HTML-Codes, der vor jedem Menupunkt ausgegeben werden soll.
 * Kann durchaus auch mal leer sein.
 */
$navigation->beforeEach('<img src="/cms/images/templateImages/spacer.png" width="10" height="1"/>');

/*
 * Festlegung des HTML-Codes, der vor dem gewählten Menupunkt ausgegeben werden
 * soll. Ich habe da zum Beispiel eine Pfeilgraphik referenziert.
 */
$navigation->beforeSelected('<img src="/cms/images/templateImages/pfeilWeiss.png"/>');

/*
 * Und last not least: die Ausgabe der Navigation. Die 0 entspricht dem
 * Hauptlevel (also der Hauptnavigation). Eine 1 entspricht einer Ebene tiefer.
 * Also der Subnavigation. Eine 2 entspräche der Subsubnavigation usw.
 */
$navigation->showNavigation(0);

?>
will man nun die subnavi ausgeben, muss man dazu ein weiteres modul machen. die instantiierung ist ja bereits erfolgt. man kann also ein klitzekleines modülchen machen, das wie folgt aussieht:

Code: Alles auswählen

<?php
$navigation->showNavigation(1);
?>
selbstverständlich bleibt es dem anwender unbenommen, die werte für before, after, beforeEach und beforeSelected neu zuzuweisen. in diesem fall kämen die einfach vorne dran.

will man nun noch eine weitere ebene einbauen, sieht das dann wie folgt aus (wieder ein eigenes kleines modülchen):

Code: Alles auswählen

<?php
$navigation->showNavigation(2);
?>
all clear?

für die gestaltung der navigation haben wir folgende methoden zur verfügung:

before()
der nhalt wird vor der navigationsebene genau einmal ausgegeben.
after()
der inhalt wird nach der navigationsebene genau einmal ausgegeben.
beforeEach()
der inhalt wird vor jeden menupunkt gesetzt (ausser vor den aktiven menupunkt)
beforeSelected()
der inhalt wird vor den aktiven menupunkt gesetzt.
between()
der inhalt wird zwischen zwei menupunkte gesetzt.


wenn man eine navigation möchte, die in etwa wie folgt aussieht (in HTML):

Code: Alles auswählen

<div id="mainNavi"><a href="">menupunkt1</a> | <a href="">menupunkt2</a></div>
dann müsste before() so aussehen

Code: Alles auswählen

$navigation->('<div id="mainNavi">');
aftter() entsprechend

Code: Alles auswählen

$navigation->after('</div>');
between() enthält dann das pipe

Code: Alles auswählen

$navigation->between('|');
all clear? sonst einfach nochmals fragen.

gruss,
andreas[/b]

Verfasst: Di 29. Nov 2005, 11:05
von MyAccount
Sehr gut. Funktioniert einwandfrei bei mir. Aber was ist denn aus den guten alten Templates geworden? Laß mich raten. Damit bekommst Du das between nicht hin, was?! :-)

Bei mir (mit Templates!) sah das immer so aus:
main 1 | main 2 | main 3 |
Es war also eher ein after oder ein before als ein between. ;-) Gibt es da eine Lösung?

Verfasst: Di 29. Nov 2005, 17:00
von kummer
einfach als between in pipe angeben und für after ebenfalls. dann hast du das resultat, das du gehabt hast.

allerdings - nebenbei bemerkt - wäre natürlich schöner, wenn das letzte pipe nicht ausgegen würde. deshalb unterscheidet das modul auch zwischen between und after.

Verfasst: Di 29. Nov 2005, 21:55
von mvf
hervorragend, genau das habe ich als laie mir umständlich über das standard hauptmodul zusammengstrickt, aber eben auch nur für die erste ebene ;)

besten dank

*sichmitaufrechtemrespectverneigendrückwärtsentfernend*

;)

Verfasst: Fr 9. Dez 2005, 11:19
von rene04
hallo,

bin da auch interressiert dran. was davon muss in den Eingabe Bereich und was in den Ausgabe Bereich des Moduls?

gruesse rene

Bug, oder bin ich blind

Verfasst: Do 15. Dez 2005, 08:12
von blauer Engel
Hallo,

ich will die gesplittete Navigation auf meiner Website einsetzen.
Funzt soweit auch ganz gut.
Kann es aber sein, das:
$navigation->after();
garnicht abgearbeitet wird?
Ich krieg das jedenfalls in meiner Website nicht zum anzeigen.

Gruß

des Ängelche[/quote]

Verfasst: Mo 19. Dez 2005, 16:10
von derSteffen
Hallo

Habe ich das richtige verstanden? Diese Modul dient dazu ein Navigation zu zerstückeln, d.h. Menuepunkte der ersten Ebene z.B. links, die Menuepunkte der zweiten Ebene z.B. oben und die der dritten ganz rechts z.B?

Wei das würde ich gerne machen!! HAbe wie beschrieben das Modul angelegt (Input & Output-Text und das Modul geteilte Navi genannt)

Muss ich in den Modulen irgendwas anpassen? Ich meine das bevor und after swoeit sind doch nur grafische Sachen, oder?

Und was bedeutet:

Ein klitzekleines modülchen machen?

Ich habe das so verstanden, das ich jetzt ein Modul anlege und das geteilte Navi 1 nenne und im Output folgendes reinschreibe:

<?php
$navigation->showNavigation(1);
?>

Oder kommt dieser Dreizeiller in Layout?

Ist das falsch? Weil wenn ich jetzt im Templeate das Modul "geteilte Navi 1" auswähle bekomme ich eine Fehlermeldung!

Oder liegt hier schon mein Fehler?

Wie gesagt momentan habe ich zwei Bäume in der Kategorie angelegt! Das eine Menue ist das Hauptmenue (Ebene 0) und das zweite ist ein Menue "Rückblick" (Ebene 0) ! Nun soll unter "Rückblick" die geteilte Navi eingesetzt werden, sprich die erste Ebene (Ebene 1).

Ich verwende eine lokale Umgebung mit 4.6.4

Vielen Dank für eure Hilfe!

Verfasst: Mo 19. Dez 2005, 16:14
von mvf
derSteffen hat geschrieben: Oder liegt hier schon mein Fehler?

Wie gesagt momentan habe ich zwei Bäume in der Kategorie angelegt! Das eine Menue ist das Hauptmenue (Ebene 0) und das zweite ist ein Menue "Rückblick" (Ebene 0) ! Nun soll unter "Rückblick" die geteilte Navi eingesetzt werden, sprich die erste Ebene (Ebene 1).
würde ich so sehen, das modul splitted die ebenen eines kategoriebaumes wenn ich es recht verstehe.
ich denke der 'request' aus dem das modul entstand war schon in der 4.old ;) die erste ebene im header horizontal, ab der 2. ebene links vertikal die haputnavi zu teilen

Verfasst: Mo 19. Dez 2005, 16:33
von derSteffen
Ja aber das ist ja keine Antwort auf meine Fragen! Aber trotzdem Danke!

Ich will ja wissen wie ich das zuordne? Wie sage ich denn das in meinem Menue "Rückblick" meine Ebene 0 in dem Container" "A" ist und wenn mein Menue "Rückblick" eine zweite Ebene hat wie sage ich das diese Punkte in Container "B" liegen sollen?

Verfasst: Mo 19. Dez 2005, 16:42
von mvf
nun wenn man weiter oben genau liest, ...

dann kannst du deine ebenen beliebieg aufteilen. der container der im layout als erstes abgearbeitet wird muss die instatiierung entahlten, also den langen outputcode die anderen dann nur noch den 3 zeiler. inputcode ist immer der selbe.

hoffe dich richtig verstanden zu haben. :?

Verfasst: Mo 19. Dez 2005, 16:59
von derSteffen
Ja jetzt wurde ich richtig verstanden! Also muss ich einmal diesen großen Outputext anlegen (inkl. Inputtext), diese Modul habe ich ja geteilte Navi genannt! Und dann lege ich weitere Module an? Nur mit dem Dreizeiller? Und dieser Dreizeiler kommt in den Outputtext? Und hier gibt es keinen Inputtext?

Und dann lege ich ein Templeate an wo sich dann z.B. das modul geteilte Navi 1 integriert ist? Und hier müßten dann die Menuepunkte meiner zweiten Ebene zu sehen sein?

Ist das so richtig?