Strona początkowa

Latający boxik

Temat głupkowaty, ale dzięki niemu poznamy kilka ciekawych rzeczy.
Często na stronach widać przesuwający się wraz z stroną box, który po kliknięciu wjeżdża na stronę. Oczywiście najłatwiej użyć jednego z milionów pluginów do tego służących, my jednak standardowo jesteśmy zachłanni na wiedzę, więc nie pisząc więcej głupot bierzemy się do pracy.

Pierwszą rzeczą jaką zrobimy, to napisanie kodu boxa:

		<div class="box">
			<div class="content">
				<input type="text" />
			</div>
		</div>
	

No prościej się prawie nie da :).
Wsadziłem do niego input, żebyśmy mogli sprawdzić czy wszystko działa dobrze nawet przy elementach formy.

Poruszanie za stroną osiągniemy w najprostszy możliwy sposób, czyli poprzez wykorzystanie CSS, a dokładnie z wykorzystaniem pozycjonowania Fixed:

	.page_hover_box {
		padding:5px;
		position:fixed;
		right:-250px;
		top:125px;
		background:#687BC3;
		overflow:hidden;
		width:300px;
		height:150px;
		z-index:9999;
		-moz-border-radius:5px;
		-webkit-border-radius:5px;
		-border-radius:5px;
		-moz-box-shadow:0 1px 2px #333;
		-webkit-box-shadow:0 1px 2px #333;
		-box-shadow:0 1px 2px #333;
	}
	

Banalna sprawa, ale jak zawsze znajdą się pewne "ale" (i bynajmniej nie chodzi o piwo). Ale IE6 nie obsługuje pozycjonowania fixed. Dlatego dla tej przeglądarki wstawimy do naszego kodu stylowanie objęte stosownym komentarzem warunkowym. Stylowaniem tym będzie równanie wyliczające na bierząco pozycję boxa. Aby znaleźć wzór dla tego równania, skorzystamy z Google, wy wynaleźć rozwiązanie dla "IE6 position fixed". Zwróć uwagę, że tutaj także podajemy pozycję top (u nas 125):

	<!--[if lt IE 7 ]>
		<style>
			.box {
				position:absolute;
				top: expression( ( 125 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
			}
		</style>
	<![endif]-->
	

W tym momencie mamy przygotowane stylowanie, które zaaplikujemy wybranemu elementowi (w naszym przykładzie to .box).

Pluginy pisać już potrafimy, tak więc skrypt napiszemy w formie pluginu. Zaczynamy:

	(function($){
		$.fn.followBox = function(options) {
			options = $.extend({
				min	: -10 //po wysunięciu będzie lekko schowany za stronę
			}, options);

			return this.each(function() {
				var $box = $(this);
				//...
			});
		}
	})(jQuery);
	

Konstrukcję jest już nam znana, więc nie będziemy się nad nią rozwodzić. Parametr, który będziemy mogli ustawiać przy wywoływaniu pluginu to "min", w którym przekażemy pozycję boxa po wysunięciu (czyli pozycję fixed "right" boxa). Parametr określający pozycję schowaną (max) już mamy określony - jest nim przecież pozycja right naszego boxa podana w stylach (za chwilę ją pobierzemy)

Animacja boxika

Pierwsze czynności jakie wykonamy to zaaplikowanie wybranemu elementowi naszego stylowania (jak założyliśmy przed chwilą).
Stworzymy też zmienną przechowującą aktualny stan boxa (wysunięty, schowany):

	var $box = $(this);
	
	$box.addClass('page_hover_box'); //dodajemy klasę
	var boxHide = 1; //aktualny stan boxa
	var posRight = $box.css('right'); //pozycja po schowaniu
	var posLeft =  options.min; //pozycja po wysunięciu
	

Kolejną rzeczą będzie podpięcie do naszego boxa zdarzenia click, które będzie pokazywało lub chowało naszego bohatera: Jeżeli box jest schowany, wtedy kliknięcie na nim będzie go wysuwało.
Jeżeli blok jest już wysunięty, wtedy dla dokumentu podepniemy zdarzenie "mousedown", które będzie nasz box chowało.

	$box.click(function() {
		if (boxHide!=1) return; //jeżeli box jest wysunięty, nic nie rób
		//jeżeli był schowany, to go wysuwamy w lewo na ekran (animujemy)
		$box.not(':animated').animate({
			'right' : posLeft
		},500, function() {
			boxHide = -boxHide //przełączamy stan boxa
			$(document).bind('mousedown', checkOuterBox); //podpinamy zdarzenie mousedown do dokumentu
		});
	});
	

Nasz boxik wyjechał na ekran. Do dokumentu podpinamy więc dokumentu zdarzenie, które będzie go chowało. Tworzymy więc kolejną metodę "checkOuterBox":

		checkOuterBox = function(event) {
			if ($(event.target).closest('.page_hover_box').length!=1) {
				hideBox();
			}
		}
	

Jej działanie jest bardzo proste. Każde zdarzenie zawiera pewne informacje o sobie. Więcej informacji o tym pisałem w dziale o zdarzeniach :). W naszym przypadku skorzystaliśmy z właściwości .target, która zawiera aktualnie obsługiwany przez to zdarzenie element (w naszym przypadku kliknięty - bo przecież zdarzenie jest click). Wystarczy więc podstawić tą właściwość do jQuery, a następnie skorzystać z metody closest, która sprawdza, czy dany element jest we wnętrzu innego (nie musi leżeć bezpośrednio w nim). Nie jest to może najsprawniejsza metoda, ale działa i jest prosta.
Jeżeli kliknięty element nie znajduje się w boxie, oznacza to, że kliknięcie nastąpiło poza boxem - czyli możemy go schować. Aby to zrobić, napiszmy kolejną metodę - chowającą nasze pudełko.

		hideBox = function() {
			//przesuwamy boxa w prawo
			$box.not(':animated').animate({
					'right': posRight
			},500, function() {
				//po skończonej animacji ustawiamy jego stan na schowany
				boxHide = 1;
				//wyłączamy zdarzenie click dla dokumentu
				$(document).unbind('mousedown', checkOuterBox);
			});
		}
	

W tym momencie nasz plugin ma postać:

	(function($){
		$.fn.followBox = function(options) {
			options = $.extend({
				min	: -10
			}, options);

			return this.each(function() {
				var $box = $(this);
					$box.addClass('page_hover_box');
				var boxHide = 1;
				var posRight = $box.css('right');
				var posLeft =  options.min ;

				hideBox = function() {
					$box.not(':animated').animate({
						'right': posRight
					},500, function() {
						boxHide = 1;
						$(document).unbind('mousedown', checkOuterBox);

					});
				}

				checkOuterBox = function(event) {
					if ($(event.target).closest('.page_hover_box').length!=1) {
						hideBox();
					}
				}

				$box.click(function() {
					if (boxHide!=1) return;
					$box.not(':animated').animate({
						'right' : posLeft
					},500, function() {
						boxHide = -boxHide
						$(document).bind('mousedown', checkOuterBox);
					});
				});
			});
		}
	})(jQuery);
	

I w zasadzie jest to końcowa postać naszego dzieła. Oczywiście można dodać kilka dodatkowych opcji takich jak np. parametr czasu wysuwania/chowania, lub po wysunięciu dodawanie do boxa dodatkowej klasy zmieniającej jego wygląd (np. dodającej cień). Usprawnienia jednak pozostawiam jako pracę domową :)

A gdzie demo? A gdzieś tam sobie lata z prawej strony :)