Seite 1 von 11

Neues Modul: vpNavigation

Verfasst: Do 7. Jul 2005, 23:19
von Dodger77
Auf der Suche nach einem Dropdown-Menü, das man schön in Contenido integrieren kann, bin ich auf die Suckerfish Dropdown gekommen:

http://www.htmldog.com/articles/suckerfish/dropdowns/

Der notwendige HTML-Code ist sehr einfach und valide(ungeordnete Liste, je nach Bedarf auch über mehrere Ebenen) und es funktioniert ohne Einsatz von JavaScript, wenn man vom Internet Explorer absieht. Aber für den haben wir dann noch einen Workaround parat.

Dies habe ich dann auch gleich mal als Modul für Contenido umgesetzt. Eine Demo findet sich hier:

http://spielwiese.contenido-tutorials.d ... p?idcat=54

Doch nun zur Umsetzung mit Contenido:

1. Neues Modul erstellen mit diesem Input:

Code: Alles auswählen

/***********************************************
* CONTENIDO MODUL - INPUT
*
* Modulname   :	    vpNavigation 0.2
* Author      :     Ingo van Peeren
* Copyright   :     Ingo van Peeren (ingo@van-peeren.de)
* Created     :     30-03-2005
* Modified    :     16-07-2005
************************************************/
?> 
<table cellspacing="0" cellpadding="0" cellpadding="4">

    <tr>
        <td class="text_medium">Baum wählen:</td>
        <td>
            <select name="CMS_VAR[0]">
            <option value="0">-- kein --</option>
            <?php

                $sql = "SELECT
                            A.idcat,
                            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    = '".$lang."' AND
                            B.idclient  = '".$client."' AND
                            C.visible   = 1 AND
                            A.level     = '0'
                        ORDER BY
                            A.idtree";

                $db->query($sql);

                while ( $db->next_record() ) {

                    if ( "CMS_VALUE[0]" == $db->f("idcat") ) {
                        echo '<option selected="selected" value="'.$db->f("idcat").'">'.$db->f("name").'</option>';

                    } else {
                        echo '<option value="'.$db->f("idcat").'">'.$db->f("name").'</option>';

                    }
                }

            ?>
            </select>
        </td>
    </tr>

</table>
<?php
und diesem Output:

Code: Alles auswählen

<?php
/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname   :	    vpNavigation 0.2
* Author      :     Ingo van Peeren
* Copyright   :     Ingo van Peeren (ingo@van-peeren.de)
* Created     :     30-03-2005
* Modified    :     16-07-2005
************************************************/

$hauptkategorie = "CMS_VALUE[0]";

$navitems = array();

function nav_feld ($cat) {
global $client, $lang, $cfg, $idcat;

        if (!is_object($db)) {
            $db = new DB_Contenido;
        } 
        $sql = "SELECT
                     A.idcat,
                     B.parentid, 
                     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
                     B.idclient  = '$client' AND
                     C.idlang    = '$lang'   AND
                     C.visible   = '1'       AND
                     B.parentid  = '$cat'
                  ORDER BY
                     A.idtree";

         $db->query($sql);

         while ( $db->next_record() ) {
            $aktiv = "";
            $sub_feld = nav_feld($db->f("idcat"));
            if ($db->f("idcat") == $idcat) $aktiv = "active";
            elseif ($sub_feld["activepath"]) $aktiv = "activepath";
            $nav_feld[] = array("idcat"      => $db->f("idcat"),
                                "name"       => $db->f("name"),
                                "active"     => $aktiv,
                                "sub"        => $sub_feld);
            if ($aktiv != "") $activepath = $aktiv;
         }
         $rv = array("feld"          => $nav_feld,
                     "activepath"    => $activepath);
         return $rv;
}

function liste ($array, $indent = "  ")
{
global $first;

       if (is_array($array["feld"])) {
         if ($first) {
           echo $indent . "<ul id=\"nav\">\n";
           $first = 0;
         }
         else echo $indent . "<ul>\n";
         foreach ($array["feld"] as $menupunkt) {
           if ($menupunkt["active"] == "active") echo $indent . $indent . "<li id=\"active\">\n";
           elseif ($menupunkt["active"] == "activepath") echo $indent . $indent . "<li class=\"activepath\">\n";
           else echo $indent . $indent . "<li>\n";
           if (is_array($menupunkt["sub"]["feld"])) {
             echo $indent . $indent . $indent . "<a class=\"daddy\" href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
             liste($menupunkt["sub"], $indent."    ");
           }
           else echo $indent . $indent . $indent . "<a href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
           echo $indent . $indent . "</li>\n";
         }
         echo $indent . "</ul>\n";
       }
}

/* Create Navigation Array */
$navitems = nav_feld($hauptkategorie); 

$first = 1;

liste($navitems);

?>

2. Das Modul im Layout vorsehen, z.B. durch:

<div id="vpnavigation">CMS_CONTAINER[x]</div>

Dabei ist die ID "vpnavigation" notwendig, um später die einzelnen Ebenen und Menüpunkte per CSS anzusprechen. Das "x" ist durch eine Ziffer zu ersetzen.

3. In den Templates, wo das Modul verwendet werden soll, muss es bei dem entsprechenden Container angegeben werden.

4. In der verwendeten CSS-Datei die notwendigen CSS-Anweisungen anlegen, z.B.:

Code: Alles auswählen

#vpnavigation, #vpnavigation ul { /* alle Listen */
	padding: 0;
	margin: 0;
	list-style: none;
	line-height: 1;
}

#vpnavigation a {
	display: block;
	width: 10em;
}

#vpnavigation li { /* alle Listenelemente */
	float: left;
	width: 10em;
}

#vpnavigation li ul { /* Listen 2. Ebene */
	position: absolute;
	background: orange;
	width: 10em;
	left: -999em; /* durch "left" außerhalb des sichtbaren Bereichs wird das gleiche erreicht wie durch "display: none", kann aber auch von Textbrowser angezeigt werden */
}

#vpnavigation li li {
	position: relative;
}

#vpnavigation li li a.daddy { /* Listenelemente mit Unterpunkten */
	background: url(../images/rightarrow.gif) center right no-repeat;
}

#vpnavigation li ul ul { /* Listen 3. Ebene und weiter */
	margin: -1em 0 0 10em;
}

#vpnavigation li:hover ul ul, #vpnavigation li.sfhover ul ul {
	left: -999em;
}

#vpnavigation li:hover ul, #vpnavigation li li:hover ul, #vpnavigation li.sfhover ul, #vpnavigation li li.sfhover ul { /* Listen, die unterhalb von "gehoverten" Menüpunkte liegen */
	left: auto;
}

#vpnavigation li#active { /* Listen zur aktuellen Kategorie */
	font-style: italic!important;
}
5. Damit der Spaß auch im Internet Explorer < 7 funktioniert, folgenden JavaScript-Code zwischen den Head-Tags (<head> ... </head>) des entsprechenden Layouts einfügen:

für HTML:

Code: Alles auswählen

<!--[if lt IE 7]>
<script type="text/javascript">
<!--

  sfHover = function() {
	  var sfEls = document.getElementById("nav").getElementsByTagName("LI");
	  for (var i=0; i<sfEls.length; i++) {
		  sfEls[i].onmouseover=function() {
			  this.className+=" sfhover";
	  	}
		  sfEls[i].onmouseout=function() {
		  	this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
	  	}
  	}
  }
  if (window.attachEvent) window.attachEvent("onload", sfHover);

-->
</script>
<![endif]-->
für XHTML:

Code: Alles auswählen

<!--[if lt IE 7]>
<script type="text/javascript">
/* <![CDATA[ */

  sfHover = function() {
	  var sfEls = document.getElementById("nav").getElementsByTagName("LI");
	  for (var i=0; i<sfEls.length; i++) {
		  sfEls[i].onmouseover=function() {
			  this.className+=" sfhover";
	  	}
		  sfEls[i].onmouseout=function() {
		  	this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
	  	}
  	}
  }
  if (window.attachEvent) window.attachEvent("onload", sfHover);

/* ]]> */
</script>
<![endif]-->

Viel Spaß damit! Die Informationen zur aktuellen Version und den o.g. Code auch nochmal zum Download gibt es unter:

http://www.contenido-tutorials.de/front ... p?idcat=58


Gruß

Ingo

Verfasst: Fr 15. Jul 2005, 23:26
von emka
Cooles Modul!!!
:)

Verfasst: Fr 15. Jul 2005, 23:51
von i-fekt
Das Navi-Modul gibt es hier barrierefrei, ohne JavaScript (auch nicht im IE) und mit mehr Einstellmöglichkeiten.

Verfasst: Sa 16. Jul 2005, 09:28
von Dodger77
i-fekt hat geschrieben:Das Navi-Modul gibt es hier barrierefrei, ohne JavaScript (auch nicht im IE) und mit mehr Einstellmöglichkeiten.
Ich bin mir jetzt nicht ganz sicher, warum das eine barrierefreier als das andere sein sollte (du hast dir den Quelltext mal angesehen?). Und das Javascript ist ja lediglich dafür zuständig dem Internet Explorer das CSS-Pseudoelement ":hover" beizubringen, wodurch ein Drop-Down-Menü generiert wird (siehe http://spielwiese.contenido-tutorials.d ... p?idcat=54). Das ist doch eine ganz andere Funktionalität als in deinem Modul.

Zum Thema Barrierefreiheit ist natürlich zu sagen, dass IE-Nutzern, bei den JavaScript ausgeschaltet ist, sicherlich ein Teil der Funktionalität genommen wird. Deshalb muss natürlich auf diesen Fall Rücksicht genommen werden durch den Entwickler, der dafür evtl. ein zweites Navigationsmodul in Kombination mit vpNavigation einsetzen kann. Denn Barrierfreiheit kann ein einzelnes Modul sowieso nicht leisten, das kann höchstens das Gesamtkonzept (Design, valides (X)HTML/CSS und natürlich die Inhalte).

"Das Navi-Modul" ist auch irgendwie ein Alleinstellungsanspruch, der der Flexibilität und Vielfalt innerhalb Contenidos nicht ganz gerecht wird.


Just my 2 €-Cents

Ingo

Verfasst: Sa 16. Jul 2005, 10:45
von Dodger77
emka hat geschrieben:Cooles Modul!!!
:)
Danke schön.

Ich habe das Modul nun noch etwas überarbeitet (aktueller Code siehe oben). Nun können per CSS folgende Punkte angesprochen werden:
  • Klasse "daddy": damit werden alle Links (<a>) ausgezeichnet, die Unterpunkte habe
  • Klasse "activepath": damit werden die Listenelemente (<li>) ausgezeichnet, die die aktuelle Kategorie beinhalten
  • ID "active": damit wird das Listenelement (<li>) ausgezeichnet, das der aktuellen Kategorie entspricht
Gruß

Ingo

Verfasst: Do 6. Okt 2005, 11:37
von Dodger77
Falls die Formatierung mal so gar nicht funktioniert, einfach mal versuchen die ID von "vpNavigation" in "vpnavigation" zu ändern. Das ist nun auch oben geändert.

Verfasst: Do 6. Okt 2005, 13:20
von GOLD
funktioniert ausgezeichnet und auf anhieb. danke!
bevor ich mich jetzt intensiver mit dem code auseinandersetze, frage ich einfach mal vorab: wie kann ich bereits die zweite Ebene nach rechts, also horizontal öffnen lassen und nicht nach unten? bei den vielen css blicke ich nicht durch. :?

Verfasst: Mi 14. Jun 2006, 18:54
von silicone
Hallo,

nun habe ich reichlich versucht, die login-Abfrage in diese wunderbare Navi einzubauen ( Contenido 4.6.8 ), bin aber wieder mal kläglich gescheitert...

Habe mir dazu die Abfrage aus dem Hauptnavigationsmodul angeschaut.
Dort gibt es folgendes:

Code: Alles auswählen

if (checkCatPermission($data['idcatlang'],$data['public'])) {  
Wenn ich diese Abfrage in die VPNavi einbauen will, zeigt Contenido mir grundsätzlich gar keine Navi. Hab versucht, die Abfrage vor den verschiedenen echos zu platzieren, aber immer das gleiche Ergebnis :-(

Kann mich jemand auf den richtigen Pfad schubsen?

Gruß,
Tom

Verfasst: Mi 14. Jun 2006, 19:06
von Dodger77
silicone hat geschrieben:nun habe ich reichlich versucht, die login-Abfrage in diese wunderbare Navi einzubauen ( Contenido 4.6.8 ), bin aber wieder mal kläglich gescheitert...

Habe mir dazu die Abfrage aus dem Hauptnavigationsmodul angeschaut.
Dort gibt es folgendes:

Code: Alles auswählen

if (checkCatPermission($data['idcatlang'],$data['public'])) {  
Wenn ich diese Abfrage in die VPNavi einbauen will, zeigt Contenido mir grundsätzlich gar keine Navi. Hab versucht, die Abfrage vor den verschiedenen echos zu platzieren, aber immer das gleiche Ergebnis :-(

Kann mich jemand auf den richtigen Pfad schubsen?
mvf hat etwas ähnliches bei vpSitemap umgesetzt:

http://www.contenido.org/forum/viewtopi ... 0266#80266

Vielleicht hilft dir das weiter.

Verfasst: Do 15. Jun 2006, 08:22
von silicone
Hallo Dodger77,

leider ist der Ansatz von mvf der Gleiche wie in der Hauptnavigation.

Code: Alles auswählen

$visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
      if ($visible) { 
Wenn ich die Abfrage einbaue, habe ich gar keine Navigation mehr.

Verfasst: Fr 16. Jun 2006, 08:36
von HerrB
a) Ist denn das FrontendLogic-Plugin installiert (siehe contenido/plugins). Wenn nein: Contenido V4.6.8.5 nehmen, siehe Misc. V4.6
b) Wurde denn eine Frontend User Group definiert und diese für die Kategorie berechtigt? (Administration -> Frontend -> Gruppen -> Gruppe anklicken -> rechts auf Category)
c) Fehlermeldungen?
d) Bei Fehlermeldungen: Debugging aktivieren: In contenido/includes/config.misc.php den Wert für debugoutput auf true setzen.

Gruß
HerrB

Verfasst: Fr 16. Jun 2006, 09:11
von silicone
Hallo HerrB,

a) Ja, ist drin (Con 4.6.13)
b) Ja
c) Nein
d)...


Nun ist es so, dass ich die Navi erhalte, wenn ich als Frontenduser eingeloggt bin, aber sobald ich mich auslogge, verschwindet die komplette navi.

Hier der Output:

Code: Alles auswählen

<?php
/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname   :	    vpNavigation 0.2
* Author      :     Ingo van Peeren
* Copyright   :     Ingo van Peeren (ingo@van-peeren.de)
* Created     :     30-03-2005
* Modified    :     16-07-2005
************************************************/


#Includes
cInclude("frontend", "includes/functions.navigation.php");
cInclude("classes", "class.frontend.permissions.php");
cInclude("classes", "class.frontend.groups.php");
cInclude("classes", "class.frontend.users.php");


$hauptkategorie = "CMS_VALUE[0]";

$navitems = array();

function nav_feld ($cat) {
global $client, $lang, $cfg, $idcat;

        if (!is_object($db)) {
            $db = new DB_Contenido;
        }
        $sql = "SELECT
                     A.idcat,
                     B.parentid,
                     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
                     B.idclient  = '$client' AND
                     C.idlang    = '$lang'   AND
                     C.visible   = '1'       AND
                     B.parentid  = '$cat'
                  ORDER BY
                     A.idtree";

         $db->query($sql);

         while ( $db->next_record() ) {
                     $visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
      if ($visible) {
            $aktiv = "";
            $sub_feld = nav_feld($db->f("idcat"));
            if ($db->f("idcat") == $idcat) $aktiv = "active";
            elseif ($sub_feld["activepath"]) $aktiv = "activepath";
            $nav_feld[] = array("idcat"      => $db->f("idcat"),
                                "name"       => $db->f("name"),
                                "active"     => $aktiv,
                                "sub"        => $sub_feld);
            if ($aktiv != "") $activepath = $aktiv;

         }
         }
         $rv = array("feld"          => $nav_feld,
                     "activepath"    => $activepath);

         return $rv;

}

function liste ($array, $indent = "  ")
{

global $first;

       if (is_array($array["feld"])) {
         if ($first) {
           echo $indent . "<ul id=\"nav\">\n";
           $first = 0;
         }
         else echo $indent . "<ul>\n";
         foreach ($array["feld"] as $menupunkt) {

           if ($menupunkt["active"] == "active") echo $indent . $indent . "<li id=\"active\">\n";
           elseif ($menupunkt["active"] == "activepath") echo $indent . $indent . "<li class=\"activepath\">\n";
           else echo $indent . $indent . "<li>\n";
           if (is_array($menupunkt["sub"]["feld"])) {
             echo $indent . $indent . $indent . "<a class=\"daddy\" href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
             liste($menupunkt["sub"], $indent."    ");
           }
           else echo $indent . $indent . $indent . "<a href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
           echo $indent . $indent . "</li>\n";

         }
         echo $indent . "</ul>\n";
       }
}

/* Create Navigation Array */
$navitems = nav_feld($hauptkategorie);

$first = 1;

liste($navitems);

?>


Verfasst: Fr 16. Jun 2006, 10:21
von HerrB
Na ja, es könnte helfen, wenn Du c.idcatlang mit in die Liste der Felder, die aus dem SQL-Statement geliefert werden, aufnimmst... :wink:

Und c.public...

Gruß
HerrB

Verfasst: Fr 16. Jun 2006, 11:09
von silicone
Und schon geht's :D

Ich danke dir recht herzlich.

Für alle, die es gebrauchen können:
(gehört ja eigentlich in den 4.6er Bereich...)

VPNavigation 0.2 mit Beachtung geschützter Bereiche

Input bleibt original.

Output:

Code: Alles auswählen

<?php
/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname   :	    vpNavigation 0.2
* Author      :     Ingo van Peeren
* Copyright   :     Ingo van Peeren (ingo@van-peeren.de)
* Created     :     30-03-2005
* Modified    :     16-07-2005
************************************************/


#Includes
cInclude("frontend", "includes/functions.navigation.php");
cInclude("classes", "class.frontend.permissions.php");
cInclude("classes", "class.frontend.groups.php");
cInclude("classes", "class.frontend.users.php");


$hauptkategorie = "CMS_VALUE[0]";

$navitems = array();

function nav_feld ($cat) {
global $client, $lang, $cfg, $idcat;

        if (!is_object($db)) {
            $db = new DB_Contenido;
        }
        $sql = "SELECT
                     A.idcat,
                     B.parentid,
                     C.name,
                     C.public,
                     C.idcatlang
                   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
                     B.idclient  = '$client' AND
                     C.idlang    = '$lang'   AND
                     C.visible   = '1'       AND
                     B.parentid  = '$cat'
                  ORDER BY
                     A.idtree";

         $db->query($sql);

         while ( $db->next_record() ) {
                     $visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
      if ($visible) {
            $aktiv = "";
            $sub_feld = nav_feld($db->f("idcat"));
            if ($db->f("idcat") == $idcat) $aktiv = "active";
            elseif ($sub_feld["activepath"]) $aktiv = "activepath";
            $nav_feld[] = array("idcat"      => $db->f("idcat"),
                                "name"       => $db->f("name"),
                                "active"     => $aktiv,
                                "sub"        => $sub_feld);
            if ($aktiv != "") $activepath = $aktiv;

         }
         }
         $rv = array("feld"          => $nav_feld,
                     "activepath"    => $activepath);

         return $rv;

}

function liste ($array, $indent = "  ")
{

global $first;

       if (is_array($array["feld"])) {
         if ($first) {
           echo $indent . "<ul id=\"nav\">\n";
           $first = 0;
         }
         else echo $indent . "<ul>\n";
         foreach ($array["feld"] as $menupunkt) {

           if ($menupunkt["active"] == "active") echo $indent . $indent . "<li id=\"active\">\n";
           elseif ($menupunkt["active"] == "activepath") echo $indent . $indent . "<li class=\"activepath\">\n";
           else echo $indent . $indent . "<li>\n";
           if (is_array($menupunkt["sub"]["feld"])) {
             echo $indent . $indent . $indent . "<a class=\"daddy\" href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
             liste($menupunkt["sub"], $indent."    ");
           }
           else echo $indent . $indent . $indent . "<a href=\"front_content.php?idcat=" . $menupunkt["idcat"] . "\">" . $menupunkt["name"] . "</a>\n";
           echo $indent . $indent . "</li>\n";

         }
         echo $indent . "</ul>\n";
       }
}

/* Create Navigation Array */
$navitems = nav_feld($hauptkategorie);

$first = 1;

liste($navitems);

?>
Gruß,
Tom

Verfasst: Mo 30. Okt 2006, 09:55
von silicone
Hallo,

jetzt habe ich ein weiteres Problem...
Ich möchte gerne, dass das Modul keine Menüpunkte ausgibt, wenn die Kategorie keinen Startartikel hat.

Könnt ihr mir dabei helfen?