Tutorial - Kategoriefilter/Artikelfilter mit Checkboxen umsetzen

Hallo zusammen,

ich hab mir mal gedacht ein kleines Tutorial zu schreiben. Würde mich über Ergänzungen und Verbesserungen freuen. Alle Angaben beziehen sich auf die 4.4.x Version des Shops.

Um den Artikelfilter, basierend auf den Attributen, auf Checkboxen (statt Drop-Down) umzustellen, wie z.B. bei koffer-direkt.de [1] bedarf es ein paar Anpassungen.

  1. Modul erstellen und im Admin einbinden
<?php
/**
 * Reset Filter
 * @file resetfilter/resetfilter.php
 * @core alist.php
 *
 * @installation
 * ADMIN > STAMMDATEN > GRUNDEINSTELLUNGEN > SYSTEM > MODULE add:
 * oxattributelist => resetfilter/resetfilter
 *
 */

class resetfilter extends resetfilter_parent {
    /**
     * Stores chosen category filter into session.
     *
     * Session variables:
     * <b>session_attrfilter</b>
     *
     * @return null
     * @file alist.php
     */
    public function executefilter()
    {
        // store this into session
        $aFilter = oxConfig::getParameter( 'attrfilter', 1 );
        $sActCat = oxConfig::getParameter( 'cnid' );
        $aSessionFilter = oxSession::getVar( 'session_attrfilter' );
        $sDel = oxConfig::getParameter( 'delfilter' ) || oxConfig::getParameter( 'delfilter_x' );
        if ($sDel) {
            unset($aSessionFilter[$sActManu]);
        } else {
            $aSessionFilter[$sActCat] = $aFilter;
        }
        oxSession::setVar( 'session_attrfilter', $aSessionFilter );
    }
}
?>
  1. list.tpl (4.4.x) anpassen (sollte in 4.5.x ähnlich sein)

[{* ORIGINAL MIT SELECT DROPDOWN *}]
[{*
<select name="attrfilter[[{ $sAttrID }]]" onchange="oxid.form.send('_filterlist');">
    <option value="" selected>[{ oxmultilang ident="LIST_PLEASECHOOSE" }]</option>
    [{foreach from=$oFilterAttr->aValues item=oValue}]
    <option value="[{ $oValue->id }]" [{ if $oValue->blSelected }]selected[{/if}]>[{ $oValue->value }]</option>
    [{/foreach}]
</select>
*}]

[{* JETZT MIT CHECKBOXEN *}]
<p>
[{foreach from=$oFilterAttr->aValues item=oValue}]
    <input type="checkbox" value="[{ $oValue->id }]"[{ if $oValue->blSelected }] checked="checked"[{/if}] name="attrfilter[[{ $sAttrID }]]" onclick="oxid.form.send('_filterlist');" /> 
    <label>[{ $oValue->value }]</label>
    <br />
[{/foreach}]
</p>

[{*
<p>
    <input type="submit" name="delfilter" value="Filter löschen">
</p>
*}]


  1. CSS nach Bedarf anpassen

  2. [Filter Reset Button] / [Auswahl zurücksetzen Button]
    list.tpl Code ergänzen (je nach Bedarf anpassen und/oder input-Tag verwenden).


<button type="submit" name="check_all" value="Filter zurücksetzen" title="Filter zurücksetzen">
    Filter zurücksetzen
</button>

Danach muss das JS um die eine Zurücksetzen Funktion erweitert werden. Zunächst gilt es zu prüfen ob jQuery eingebunden wird. Dazu gibt es zwei Möglichkeiten:

a) jQuery von [3] runterladen und in das src Verzeichnis ablegen, oder
b) jQuery von Google AJAX Libraries API [4] laden.

Dazu muss dann zunächst die Template Datei _footer.tpl (unten vor dem schließenden -Tag) um den Aufruf ergänzt werden.

zu a)


[{*
/**
 * jQuery Framework
 * @note selbst gehostet im src/ Verzeichnis
 */
*}]
<script type="text/javascript" src="[{ $oViewConf->getResourceUrl() }]jquery-1.6.2.min.js"></script>

zu b)


[{*
/**
 * jQuery Framework
 * @note von Google geladen
 * 1. immer die neuste Version des 1er Strangs laden > aktuell 1.6.2
 * <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
 * 2. oder eine eindeutige Version laden
 * <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
 */
*}]
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Damit man die oxid.js nicht ändert ist es wichtig im Verzeichnis src/ (wo auch die oxid.js liegt) eine eigene JS Datei anzulegen, z.B. myfunctions.js. In diese Datei wird dann folgender Code eingebunden und kann bei Bedarf immer weiter ergänzt werden. Dabei handelt es sich um sog. unobtrusive JavaScript (bitte googeln). Diese Datei muss dann ebenfalls in der _footer.tpl (nach jQuery) aufgerufen werden.


[{*
/**
 * Meine JavaScript Snippets
 */
*}]
<script type="text/javascript" src="[{ $oViewConf->getResourceUrl() }]myfunctions.js"></script>


// myfunctions.js

// JS nach Singleton Pattern und Namespacing
var MEINOXIDSHOP = {
    // initialisieren
    init: function() {
        MEINOXIDSHOP.resetFilter();
        // ab hier weitere Funktionen aufrufen
    },

    resetFilter: function() {
        var rfbtn = $('button[name="check_all"]');
        if ($(rfbtn).length) {
            $(rfbtn).click(function() {
                if($(this).val()==0) {
                    $(this).parents("form#_filterlist")
                        .find("input:checkbox")
                        .attr("checked","checked")
                        .val("1");
                    } else {
                        $(this).parents("form#_filterlist")
                        .find("input:checkbox")
                        .attr("checked","")
                        .val("0");
                    }
            });
        }
    }

    // ab hier weitere Funktionen definieren und Komma nach Funktionsklammer oben nicht vergessen
}

/**
 * Wenn DOM geladen starte Funktionen
 */
$(document).ready(function() {
    // ruft init auf und damit alle Funktionen aus init
    MEINOXIDSHOP.init();
});

Das Ergebnis [2] sieht dann wie in der Abbildung (Anhang) aus.

[1] http://www.koffer-direkt.de/reisegepaeck/trolleys/trolleys-mit-2-rollen/
[2] http://www.weinshop-peth.de/Rotweine/
[3] http://jquery.com/
[4] http://code.google.com/intl/de-DE/apis/libraries/devguide.html#jquery


FAQ: Attribute verwenden
FAQ: Kategorien nach Attributen filtern

Edit:

  • Danke @René, deine [Filter Reset Button] JS-Lösung (weiter unten). Funktioniert einwandfrei!
  • JS Erklärung ergänzt

Der Filter greift dann die Artikel-Attribute ab?

[QUOTE=Hebsacker;62948]Der Filter greift dann die Artikel-Attribute ab?[/QUOTE]
Japp, Topic geändert.

Was den input button angeht, versuche mal Ersatzweise eine weitere selectbox zu verwenden und auf die setzt du folgendes jquery um alle übrigen checkboxen zu deaktiveren:

$("input[name='check_all']").click(function(){
      if($(this).val()==0){
        $(this).parents("form#_filterlist")
               .find("input:checkbox")
               .attr("checked","checked")
               .val("1");
      }
      else{
        $(this).parents("form#_filterlist")
               .find("input:checkbox")
               .attr("checked","")
               .val("0");
      }
    });

Warum funktioniert der input button auf der Weinseite bei den Filter-Attributen, aber nicht auf der Koffer page?

Eine ganz feine Sache wäre es wenn man die Filtermöglichkeit auch bei Verwendung der Suchfunktion hätte.

Mir gefallen übrigens Deine Design ausgezeichnet. :slight_smile:

[QUOTE=beme;62956]Was den input button angeht, versuche mal Ersatzweise eine weitere selectbox zu verwenden und auf die setzt du folgendes jquery um alle übrigen checkboxen zu deaktiveren[/QUOTE]
Funktioniert super, DANKE! Habe es oben ergänzt.

Hat es doch irgendwo geklemmt? Sehe gerade dass Du den Selektor wieder rausgenommen hast.

Hallo,

vielen Dank schon mal für das Tutorial! Genau so etwas habe ich gesucht.

Allerdings klappt bei mir das Zurücksetzen des Formulars nicht. Nur zum sicher gehen:

Die JS-Funktion “resetFilter” kommt einfach ins oxid.js ans Ende? Muss ich die Funktion nicht explizit aufrufen, wenn ich den Button klicke? :confused:

Danke schon mal,
Jochen

Wird sie doch:

click(function())

ok - vorweg vielleicht noch, dass ich nur semi-professionell in JS bin :wink:

Die Funktion resetFilter versteh ich soweit. Meine Frage ist nur: Wird die Funktion resetFilter beim senden des Formulars automatisch aufgerufen? Weil ein expliziter Aufruf ist ja nicht da…

Denn leider funktioniert das Zurücksetzen bei mir nicht :((

Hallo, habe den Text oben erweitert und ergänzt um einige Fragen zu klären.

[QUOTE=kraej;64109]Die Funktion resetFilter versteh ich soweit. Meine Frage ist nur: Wird die Funktion resetFilter beim senden des Formulars automatisch aufgerufen? Weil ein expliziter Aufruf ist ja nicht da… [/QUOTE]
Nein, diese Art der Event-Auslösung nennt sich unobtrusive (unaufdringliches) JS. Es wird zunächst mit .length geprüft ob sich auf der Seite ein HTML-Tag button mit dem Attribut name=“check_all” auf der Seite befindet. Wenn ja, so wird das jQuery-click Event auf dieses Tag angelegt, welches erst ausgelöst wird sobald ein Benutzer auf den Button klickt.

Auch nicht schlecht, aber das ständige Relaod ist echt nervend.

[QUOTE=cottoneyejoe;64142]Auch nicht schlecht, aber das ständige Relaod ist echt nervend.[/QUOTE]
Nächster Schritt: AJAX. Da muss ich aber noch ein wenig basteln :).

Handelt es sich beim Shopinhaber um das ehemalige Weingut Peth-Wetz ?

Super! Vielen Dank!

Das Stichwort jQuery hat den Groschen dann fallen lassen :wink: Hatte vorher noch mit dem Azure-Template rumgespielt, wo jQuery ja schon drin ist und hatte es beim basic als gegeben angenommen :-/

Danke auch noch für den kleinen JS-Exkurs :wink:

Gruß,
Jochen

[QUOTE=rubbercut;64145]Handelt es sich beim Shopinhaber um das ehemalige Weingut Peth-Wetz ?[/QUOTE]
Nein. Die Gemeinde Bermersheim und umliegende haben das Problem vieler Weingüter “Peth’s” und keiner ist mit dem anderen verwandt :D.

Danke für die Info.

Und wie würde das für die Auswahllisten funktionieren?

Hallo Eduard,

danke für das Tutorial. Mittlerweile arbeite ich mit CE 4.7.2 und komme mit der list.tpl nicht klar.
Wo und was muss ich denn dort esetzten? Ich denke dort hat sich einiges geändert…

Könnte jm. das ganze vielleicht auf 4.7.x anpassen? :slight_smile: