Shopware Knowledgebase

Shopware Labs

Der Bereich Shopware Labs ist die Plattform für alle Entwickler. Hier findet man technische Dokumentationen und zahlreiche Tipps und Tricks rund um das Thema Programmieren. In dieser Rubrik stellen außerdem die Entwickler der shopware AG neue und experimentelle Lösungsansätze vor. Neue Funktionen, die in dieser Rubrik bereitgestellt werden, sind teilweise auch für zukünftige Releases geplant. Die Funktionen können dann ohne Programmierkenntnisse zukünftig direkt im Shopware Backend konfiguriert werden oder werden über Plugins bereitgestellt. Informationen über neue, geplante Funktionen finden Sie in unserer Roadmap.

Bitte beachten Sie, dass die hier bereitgestellten Lösungsansätze nicht offiziell supportet werden und nur eingebaut werden sollten, sofern Sie über das entsprechende, technische Wissen verfügen.

Aufklappbare Bottom-Bar

1 Kommentare

Endergebnis der Bottom Toolbar - shopwaredemo.de

Vorwort

In diesem Tutorial beschreiben wir Ihnen, wie Sie eine aufklappbare Bottom-Bar, ähnlich dem Shopware-Demoshop, erstellen.

Die Grundstruktur anlegen

Wenn Sie bereits über ein eigenes Template und die nötige index.tpl verfügen, können Sie diesen Schritt natürlich ignorieren.

Zunächst legen wir, sofern nicht schon vorhanden, ein eigenes Template und die nötigen Strukturen an:

myTemplate/frontend/index/

myTemplate/frontend/_resources/styles

myTemplate ist natürlich der Name von unserem Template und kann frei gewählt werden.

In dem Ordner index legen wir nun die index.tpl an. Dies ist notwendig, da wir die Standard index.tpl, die immer und überall im Frontend aufgerufen wird, erweitern. Weiterhin ist es wichtig, dass wir eigene Styles einbinden. Dafür legen wir noch die Datei header.tpl an.

Nun fehlt nur noch unsere bottombar.css. Diese legen wir in myTemplate/frontend/_resources/styles an.

Die Bottom-Bar anlegen

Nun geht es an die Erstellung der eigentlichen Bottom-Bar.

Der grobe Aufbau

Hierzu öffnen wir die index.tpl und erweitern zunächst die Standard index.tpl:

{extends file="../_default/frontend/index/index.tpl"}

Ohne diesen Code würden wir die normale index.tpl ersetzen und somit nurnoch die Bottom-Bar sehen. Nun erstellen wir die Bottom-Bar selbst.

Diese kommt in den Block frontend_index_body_inline:

{block name='frontend_index_body_inline'}
{/block}

In diesem Block kommt nun die Bar. Hierzu legen wir einen Div-Container an und geben ihm die Klasse "bottom-bar". In diesen Div-Container kommt noch ein weiterer Container mit der Klasse "container_20", in den wir später unseren Inhalt einfügen. Der "container_20"-Div sorgt dafür, dass die Bottom-Bar nie größer ist als der Shop selbst. Das Ganze sieht nun also so aus:

 
{extends file="templates/_default/frontend/index/index.tpl"}
{block name='frontend_index_body_inline'}
<div class="bottom-bar">
	<div class="container_20">
		Testausgabe
	</div>
</div>
{/block}

Der Style

Nun kümmern wir uns um die bottombar.css. Diese müssen wir erst in unserer header.tpl einbinden. Folgenden Code schreiben wir, wenn nicht schon vorhanden, in die header.tpl:

 
{extends file="../_default/frontend/index/header.tpl"}
 
{block name="frontend_index_header_css_screen" append}
	<link type="text/css" media="screen, projection" rel="stylesheet" href="{link file='templates/myTemplate/frontend/_resources/css/bottombar.css'}" />
 
{/block}
 

Hier muss der Pfad natürlich angepasst werden, also der Template-Name eingetragen werden.

Zunächst müssen wir dafür sorgen, dass die Bottom-Bar fest unten am Browser fixiert ist.

Dazu öffnen wir also die bottombar.css und fügen den folgenden Code ein:

 
.bottom-bar{
	left: 0px;
	bottom: 0px;
	position: fixed;
	border: 1px solid red;
	background-color: #c7c7c7;
	padding: 40px 0 15px;
}
 

Was machen wir hier nun?

Zuerst fixieren wir die Bottom-Bar unten links am Browser. Dafür dient uns dieser Teil:

 
	left: 0px;
	bottom: 0px;
	position: fixed;
 

Mittels left und bottom geben wir den Abstand von links und von unten an. Dieser muss natürlich in beiden Fällen 0 sein. Mit position geben wir dann an, wie das Div positioniert werden soll, in unserem Fall eben fest fixiert.

Der nächste Teil dient nur der Übersicht:

 
	border: 1px solid red;
	background-color: #c7c7c7;
 

Anschliessend wird nurnoch ein Padding gesetzt, welches einen Abstand definiert. Dieser wird später von Nützen sein.

Nun speichern wir den Code einmal und schauen, ob wir schon Ergebnisse sehen.

So dürfte das Ergebnis nun in etwa aussehen.

Inhalt und Style

Nun muss die Bottom-Bar über den gesamten Shop gezogen werden, die Ränder links und rechts sollen entfernt werden und unsere Testausgabe hat einen extra Hintergrund, der uns stört. Da wir nun eine Bottom-Bar haben, die aber sonst nichts kann, fehlt natürlich noch die eigentliche Funktionalität.

Weitere Style-Anpassungen

Wir wollen aber mit den Style-Anpassungen anfangen. Daher fügen wir noch weitere Styles hinzu:

 
.bottom-bar{
	left: 0px;
	bottom: 0px;
	position: fixed;
	border: 1px solid red;
	background-color: #c7c7c7;
	
	width: 100%;
	border-left: 0 none;
	border-right: 0 none;
	z-index: 100;
}
 
.bottom-bar div.container_20{
	border: 0 none;
	background-color: #c7c7c7;
}
 
 
 

Zunächst haben wir die Weite auf 100% gesetzt und die Ränder links und rechts entfernt. Davon abgesehen wurde der z-index gesetzt, der dafür sorgt, dass unsere Bottom-Bar immer im Vordergrund steht. Um den verschachtelten "container_20"-Div anzusprechen, haben wir einen neuen Selektor genommen.

 
.bottom-bar div.container_20{
	border: 0 none;
	background-color: #c7c7c7;
}
 

Damit geben wir an, dass wir alle Div-Container mit der Klasse container_20 IN einem Element mit der Klasse bottom-bar verändern wollen. Die Hintergrundfarbe stimmt nun überein und jeglicher Rand wurde entfernt.

Die Funktionalität

Nun kommen wir zum schwierigeren Teil und der eigentlichen Funktionalität.

Hierzu fügen wir erst einmal an dem Anfang der index.tpl zwischen dem Extend und dem Block noch einen anderen Block hinzu, also so:

 
{extends file="templates/_default/frontend/index/index.tpl"}
 
{block name="frontend_index_header_javascript_inline" append}
{/block}
 
{block name='frontend_index_body_inline'}
<div class="bottom-bar">
	<div class="container_20">
		Testausgabe
	</div>
</div>
{/block}

Der neu erstellte Block frontend_index_header_javascript bietet uns nun die Möglichkeit Javascript-Code hinzuzufügen.

Wichtig: Es ist zwingend notwendig, dass hinter dem Blockname ein append gesetzt wird, da wir sonst alle anderen Javascript-Funktionen überschreiben.

In diesem neuen Block fügen wir nun also die eigentliche Funktionalität ein. Daher fügen wir zunächst folgenden Code dem Block hinzu:

 
(function($) {
	$(document).ready(function() {
		alert("Testausgabe");
	});
})(jQuery);
 

Wir machen erst einmal nichts anderes, als eine Testausgabe, sobald die Seite fertig geladen wurde. Hierzu erstellen wir erst einmal eine anonyme Funktion:

 
(function($){
})(jQuery);
 

Eine solche anonyme Funktion hat den Sinn, dass das von jQuery verwendete Dollar-Zeichen nur innerhalb dieser Funktion als jQuery zählt. Dies hat den Grund, dass es noch andere Javascript-Bibliotheken gibt, die das Dollar-Zeichen verwenden, sodass es zu Überschneidungen käme.

Nun gilt es das Script aufzurufen, sobald die Seite fertig geladen wurde. Dafür fügen wir den folgenden Code hinzu:

 
(function($) {
	$(document).ready(function() {
 
	});
})(jQuery);
 

Alles, was nun eingetragen wird, wird erst nach dem erfolgreichen Laden der Seite ausgeführt. Und schliesslich kommt noch unsere Testausgabe.

Wenn dies klappt, haben wir alles richtig gemacht.

Nun also brauchen wir die eigentliche Funktionalität. Wir erstellen unter unserer Ready-Funktion eine weitere Funktion, die wir bottomBar nennen. In die Ready-Funktion selbst kommt nur der Aufruf der Funktion, dazu aber später mehr.

 
(function($) {
	$(document).ready(function() {
	});
	$.fn.bottomBar = function(settings){
	}
})(jQuery);
 

Dort wird nun folgender Code eingefügt:

 
/** Default configuration */
	var config = {
		'closeCls': 'closed',
		'openCls': 'opened',
		'barHeight': 40,
		'slideInSpeed': 275,
		'slideOutSpeed': 200,
		'fadeSpeed': 300,
		'timeout': 200
	};
 
	/** Extend default config with user settings */
	if(settings) { $.extend(config, settings); }
 
	/** Declaration */
	var $this = $(this),
		bottomHeight = $this.outerHeight(),
		timeout = null;
 
	/** Set height of the bottom height */
	$this.css({
		'bottom': -(bottomHeight - config.barHeight)
	}).addClass(config.closeCls);
 
	/** Add event listeners for the hover event */
	$this.hover(function() {
		timeout = window.setTimeout(function() {
 
			/** Show bottom bar content and fadeout the "show" button */
			$this.animate({
				'bottom': 0
			}, config.slideInSpeed).removeClass(config.closeCls).addClass(config.openCls);
			$header.fadeOut(400);
		}, config.timeout);
	}, function() {
 
		/** Clear delay to prevent flicking bugs */
		if(timeout) {
			clearTimeout(timeout);
			timeout = null;
		}
 
		/** Hide bottom bar content and fadein the "show" buttom */
		$this.animate({
			'bottom': -(bottomHeight - config.barHeight)
		}, config.slideOutSpeed).removeClass(config.openCls).addClass(config.closeCls);
		$header.fadeIn(config.fadeSpeed);
	});
 
	/** Support for jQuery's method chaining */
	return this;
 

Zunächst erstellen wir eine Default-Konfiguration, in der wir bestimmte Einstellungsmöglichkeiten angeben.

 
var config = {
	'closeCls': 'closed',
	'openCls': 'opened',
	'barHeight': 40,
	'slideInSpeed': 275,
	'slideOutSpeed': 200,
	'fadeSpeed': 300,
	'timeout': 200
};
 

Wir haben der Funktion bottomBar den Parameter settings übergeben, sodass eigene Einstellungen möglich sind. Damit diese übernommen werden, müssen wir die Default-Einstellungen mit den Unseren überschreiben.

 
if(settings) { $.extend(config, settings); }
 

Nun gilt es noch andere Werte, wie z.B. die Höhe unserer BottomBar, in Variablen zu speichern.

 
var $this = $(this), 
	$header = $(this).find('.header'),
	bottomHeight = $this.outerHeight(),
	timeout = null;
 

$header können wir erst einmal ignorieren. Nun haben wir die Informationen, die wir zum arbeiten brauchen.

Nun gilt es also den Auf- und zu Zuklapp-Effekt zu erstellen. Die Grundidee ist, dass man den eigentlichen Inhalt unter dem Browser verschwinden lässt. Dafür muss der Abstand von unten, also bottom in den negativen Bereich zu kriegen.

$this.css({
	'bottom': -(bottomHeight - config.barHeight)
}).addClass(config.closeCls);

Mittels $this sprechen wir die Bottom-Bar an, dessen Style wir dann mit css umändern wollen. Der umzuändernde Style ist bottom. Der Wert von bottom entsteht durch die Höhe der Bottom-Bar und der in der Konfiguration angegeben Höhe. Bspw. ist unsere Bottom-Bar 70 Pixel hoch und unsere Konfiguration gibt 40 Pixel an. Nun wird die Bottom-Bar also auf -30 Pixel gesetzt und verschwindet somit leicht unter dem Browser. Weiterhin bekommt die Bottom-Bar die Klasse "closed". Dies biettet noch weitere Style-Möglichkeiten.

Nun benötigen wir die Möglichkeit die Bottom-Bar wieder aufzuklappen. Dies erledigen wir mit dem Hover-Event, also wenn die Maus über die Bottom-Bar fährt.

 
$this.hover(function() {
	timeout = window.setTimeout(function() {
 
		/** Show bottom bar content and fadeout the "show" button */
		$this.animate({
			'bottom': 0
		}, config.slideInSpeed).removeClass(config.closeCls).addClass(config.openCls);
		$header.fadeOut(400);
	}, config.timeout);
}, function() {
 
	/** Clear delay to prevent flicking bugs */
	if(timeout) {
		clearTimeout(timeout);
		timeout = null;
	}
 
	/** Hide bottom bar content and fadein the "show" buttom */
	$this.animate({
		'bottom': -(bottomHeight - config.barHeight)
	}, config.slideOutSpeed).removeClass(config.openCls).addClass(config.closeCls);
	$header.fadeIn(config.fadeSpeed);
});
 

Zunächst setzen wir einen Timeout. Dies hat den Sinn, dass: a) die Bottom-Bar nicht bei jedem Fahren über Diese sofort aufklappt, ohne, dass dies gewünscht war. Es muss also eine Mindestzeit auf diese Bottom-Bar gezielt werden. b) Es einen unschönen Effekt gibt, wenn man schnell über und von der Bottom-Bar fährt, sodass die sie ständig auf und zuklappt, ohne, dass etwas gemacht wurde.

Nun muss die Animation selbst folgen, also das Aufklappen. Wir setzen den Bottom-Wert auf 0, sodass sie hochfährt mit der in der Konfiguration angegebenen Geschwindigkeit. Die Klasse "closed" wird entfernt und "opened" wird hinzugefügt.

$header können wir wieder erst einmal ignorieren.

Das Ganze geschieht mit einem Timeout von 400 Millisekunden.

Von einem Komma getrennt folgt nun die Funktion, wenn die Maus wieder von der Bottom-Bar runterfährt, also wieder das Zuklappen. Dies funktioniert wie oben beschrieben, nur umgekehrt.

Zum Schluss fügen wir noch folgenden Code ein, um das Chaining von jQuery zu ermöglichen.

In jQuery ist es möglich mehrere Befehle aneinanderzuketten.

 
return this;

Zu guter Letzt muss die gesamte Funktion bottomBar der Bottom-Bar selbst hinzugefügt werden.

Dies erreichen wir, indem wir die Bottom-Bar selektieren und einfach die Funktion anhängen, also:

 
$('.bottom-bar').bottomBar();
 

Zusatzfunktion

Nun kommen wir zu dem mehrfach angesprochenen $header.

In der jQuery-Funktion wird die Möglichkeit geboten einen Header einzubinden, der beim Aufklappen der Bottom-Bar verschwindet. Um diese Funktion auszunutzen, fügen wir in unserem container_20 einen Div mit der Klasse Header.

 
<div class="bottom-bar">
	<div class="container_20">
		<div class="header">TestHeader</div>
		<div>
			Hier kommt unser Inhalt rein.
		</div>
	</div>
</div>

Finishing

Nun haben wir eine soweit funktionierende Bottom-Bar, allerdings ohne Inhalt. Und genau darum soll es nun gehen. Wir wollen nun die Vierspaltigkeit, genau wie im Demoshop, erstellen. Genauso soll das Ganze ein wenig gestylet werden.

Wir fangen nun also damit an, dass wir einen Div-Container für all unseren eigentlichen Inhalt erstellen. Dieser hat die Klasse content. In diesem Container erstellen wir einen weiteren Container mit der Klasse row. Nun haben wir quasi eine Reihe erstellt - fehlen die Spalten. Hierfür erzeugen wir vier weitere Div's mit je der Klasse col, um die Vierspaltigkeit zu erzeugen. Der erste und der letzte Container bekommen noch eine weitere Klasse, in etwa firstCol und lastCol. Dies dient nur Style-Zwecken.

Das Ganze sähe nun so aus:

 
<div class="bottom-bar">
	<div class="container_20">
		<div class="header">TestHeader</div>
		<div class="content">
			<div class="row">
				<div class="col firstCol"> Container 1</div>
				<div class="col"> Container 2</div>
				<div class="col"> Container 3</div>
				<div class="col lastCol"> Container 4</div>
			</div>
		</div>
	</div>
</div>
 

Nun gilt es die Container nicht untereinander, sondern nebeneinander aufzulisten. Dafür öffnen wir unsere bottombar.css und fügen folgenden Code hinzu:

 
.bottom-bar .col{
	float: left;
	width: 220px;
}
 

Das float:left sorgt dafür, dass die Container nebeneinander liegen. Die Weite kann natürlich variieren.

Nun können wir unsere Spalten auch schon mit Inhalt füllen. Dieser ist euch vollkommen überlassen.

Wir gehen nun noch ein wenig mehr auf den Style ein.

Eine Abtrennung der Container wäre uns ganz lieb. Dafür nutzen wir einen Border, also einen Rand, den wir nur auf der rechten Seite eines jeden Containers anbringen.

 
.bottom-bar .col{
	float: left;
	width: 220px;
	border-right: 1px solid #292929;
	padding: 0 20px;
}
 

Neben dem Border haben wir auch das Padding gesetzt. Ohne das Padding würde der Rand direkt anliegen und sieht somit nicht sehr schick aus.

Nach kurzem Testen fällt uns auf, dass einer der Container umgesprungen ist in die nächste Zeile. Dies entsteht durch das Padding. Daher entfernen wir das Padding an Stellen, wo wir es nicht brauchen - am Anfang und am Ende. Davon abgesehen hat der letzte Container einen Rand auf der rechten Seite, den er nicht braucht. Und genau hierfür haben wir den ersten und den letzten Container mit einer weiteren Klassen belegt.

 
.bottom-bar .col{
	float: left;
	width: 220px;
	padding: 0 20px;
	border-right: 1px solid #292929;
}
 
.bottom-bar .col.lastCol{
	border-right: none;
	padding: 0 0 0 20px;
	width: 215px;
}
 
.bottom-bar .col.firstCol{
	padding-left: 0;
}
 

Wir entfernen nun also überflüssige Abstände und Ränder. Nun sieht unsere Bottom-Bar doch schon ganz nett aus. Zum Schluss wollen wir noch pro Container eine Art Überschrift einbauen. Dies funktioniert ganz einfach mit einem h1-Tag.

Diesem geben wir einen Rand an den Boden, sodass er vom eigentlichen Inhalt abgetrennt ist. Dann noch einige wenige farbliche und Größenanpassungen:

 
.bottom-bar h1 {
    border-bottom: 1px solid #555555;
    color: #FFFFFF;
    font-size: 1.2em;
    margin: 0 0 16px;
    padding: 5px 0;
    text-transform: uppercase;
    font-weight: 700;
}
 

Sehr schön! Wer noch eine blaue Leiste über der Bottom-Bar wünscht, der kann dies mit einer Zeile Code umsetzen. Dies trägt man in die Styles der gesamten Bottom-Bar ein.

 
	border-top: 4px solid #00A8E0;
 

Zusammenfassung

Nun sieht es insgesamt so aus:

Index.tpl:

 
{extends file="templates/_default/frontend/index/index.tpl"}
 
{block name="frontend_index_header_javascript_inline" append}
	(function($) {
		$(document).ready(function() {
			$('.bottom-bar').bottomBar();
		});
 
		$.fn.bottomBar = function(settings) {
 
		/** Default configuration */
		var config = {
			'closeCls': 'closed',
			'openCls': 'opened',
			'barHeight': 40,
			'slideInSpeed': 275,
			'slideOutSpeed': 200,
			'fadeSpeed': 300,
			'timeout': 200
		};
 
		/** Extend default config with user settings */
		if(settings) { $.extend(config, settings); }
 
		/** Declaration */
		var $this = $(this), 
			$header = $(this).find('.header'),
			bottomHeight = $this.outerHeight(),
			timeout = null;
 
		/** Set height of the bottom height */
		$this.css({
			'bottom': -(bottomHeight - config.barHeight)
		}).addClass(config.closeCls);
 
		/** Add event listeners for the hover event */
		$this.hover(function() {
			timeout = window.setTimeout(function() {
 
				/** Show bottom bar content and fadeout the "show" button */
				$this.animate({
					'bottom': 0
				}, config.slideInSpeed).removeClass(config.closeCls).addClass(config.openCls);
				$header.fadeOut(400);
			}, config.timeout);
		}, function() {
 
			/** Clear delay to prevent flicking bugs */
			if(timeout) {
				clearTimeout(timeout);
				timeout = null;
			}
 
			/** Hide bottom bar content and fadein the "show" buttom */
			$this.animate({
				'bottom': -(bottomHeight - config.barHeight)
			}, config.slideOutSpeed).removeClass(config.openCls).addClass(config.closeCls);
			$header.fadeIn(config.fadeSpeed);
		});
 
		/** Support for jQuery's method chaining */
		return this;
	}
	})(jQuery);
{/block}
 
{block name='frontend_index_body_inline'}
<div class="bottom-bar">
	<div class="container_20">
		<div class="header">TestHeader</div>
		<div class="content">
			<div class="row">
				<div class="col firstCol"> 
				<h1>Wichtig!!</h1>
				Container 1</div>
				<div class="col"> Container 2</div>
				<div class="col"> Container 3</div>
				<div class="col lastCol"> Container 4</div>
			</div>
		</div>
	</div>
</div>
{/block}
 

Bottombar.css:

 
.bottom-bar{
	left: 0px;
	bottom: 0px;
	position: fixed;
	border: 1px solid red;
	border-left: 0 none;
	border-right: 0 none;
	width:100%;
	z-index: 100;
	background-color: #191919;
	padding: 40px 0 15px;
	border-top: 4px solid #00A8E0;
}
.bottom-bar div.container_20{
	border: 0 none;
	background-color: #191919;
	height: 200px;
}
.header{
	color: #F5F5F5;
    	font-size: 12px;
    	font-weight: 700;
    	left: 50%;
    	line-height: 20px;
    	margin-left: -100px;
    	position: absolute;
    	text-align: center;
    	top: 11px;
    	width: 200px;
}
.bottom-bar .content{
	margin: 0 auto;
}
 
.bottom-bar .col{
	float: left;
	width: 220px;
	padding: 0 20px;
	border-right: 1px solid #292929;
}
 
.bottom-bar .col.lastCol{
	border-right: none;
	padding: 0 0 0 20px;
	width: 215px;
}
 
.bottom-bar .col.firstCol{
	padding-left: 0;
}
 
.bottom-bar h1 {
    border-bottom: 1px solid #555555;
    color: #FFFFFF;
    font-size: 1.2em;
    margin: 0 0 16px;
    padding: 5px 0;
    text-transform: uppercase;
    font-weight: 700;
}
}

Header.tpl:

 
{extends file="../_default/frontend/index/header.tpl"}
 
{block name="frontend_index_header_css_screen" append}
	<link type="text/css" media="screen, projection" rel="stylesheet" href="{link file='templates/myTemplate/frontend/_resources/css/bottombar.css'}" />
 
{/block}

Artikel-PDF erstellen

Artikel bewerten

Waren diese Informationen hilfreich? Ja Nein


Kommentare:

Scrollen erst nach Klick auf Überschrift - 17. January 2012 - 10:39 Uhr

Von: Holger Voss

Hallo,

wie kann man es denn hinbekommen, dass das Menü erst hochscrollt, wenn man auf "TestHeader" klickt? Das wäre für die Usability besser!

Ansonsten ein sehr schönes Tutorial! Vielen Dank!

Artikel kommentieren


Die mit einem * markierten Felder sind Pflichtfelder.

Weitere interessante Artikel:

Bezeichnung:
Rating:
Klicks:
Datum:

Bestell-Nr.: SW1605

Lieferzeit ca. 5 Tage

€ 1,00

Preise inkl. gesetzlicher
MwSt. zzgl. Versandkosten*

€ 1,00

Preise inkl. gesetzlicher
MwSt. + Versandkosten*

Kategorien: