Wpisy otagowane ‘class’

Ruch na stronie z jQuery

wtorek, 15 Październik 2013

Nie będę pisał o tym, jak zwiększyć ruch na stronie w sensie ilości użytkowników odwiedzających serwis, tylko o wprowadzeniu ruchomych elementów reagujących na określone zachowania użytkownika. Skorzystam przy tym z dobrodziejstw JavaScriptu i biblioteki jQuery. Jeżeli nie znasz jQuery, przeczytaj Co mogę zrobić z jQuery?.

Efekt, którego realizację chcę tu przybliżyć, zaprezentowałem poniżej. Najedź myszą na kolejne grafiki. Dalej znajdziesz kolejne etapy jego realizacji.

Obraz 1.

Obraz 2.

Obraz 3.

Obraz 4.

Obraz 5.

Obraz 6.

Zaczniemy od kodu HTML:

<div id="photos">
<div class="photo">
 	<div class="text"><p>Obraz 1.</p></div>
 	<img src="img1.jpg" id="p1" />
</div>
<div class="photo">
 	<div class="text"><p>Obraz 2.</p></div>
 	<img src="img2.jpg" id="p2" />
</div>
<div class="photo">
 	<div class="text"><p>Obraz 3.</p></div>
 	<img src="img3.jpg" id="p3" />
</div>
<div class="photo">
 	<div class="text"><p>Obraz 4.</p></div>
 	<img src="img4.jpg" id="p4" />
</div>
<div class="photo">
 	<div class="text"><p>Obraz 5.</p></div>
 	<img src="img5.jpg" id="p5" />
</div>
<div class="photo">
 	<div class="text"><p>Obraz 6.</p></div>
 	<img src="img6.jpg" id="p6" />
</div>
</div>

Całość znajduje się w znacznikach div z identyfikatorem photos. W zależności od szerokości tego elementu w jednym wierszu znajdzie się większa lub mniejsza liczba grafik. Każda grafika składa się z dwóch części: górnej – widocznej od razu i dolnej – pokazującej się po najechaniu myszą. Do elementów img dodałem identyfikatory. Grafiki poprzedzone są opisami zawartymi w elementach div klasy text, a łącznie z grafiką w elementach div klasy photo. Te divy służą do ograniczenia widoczności grafik do połowy ich wysokości, co jest realizowane przez definicje styli CSS:

#photos
{
 	width: 750px;
 	margin: 20px auto;
}
.photo 
{
 	width: 350px;
 	height: 350px;
 	overflow: hidden;
 	display: inline-block;
 	position: relative;
}
img 
{
 	display: none;
 	position: relative;
 	top: 0px;
}
.text 
{
 	width: 100%;
 	height: 100px;
 	background: #fff;
 	position: absolute;
 	left: 0px;
 	bottom:-100px;
 	z-index: 100;
}

Div photos swoją szerokością ogranicza ilość grafik w wierszu. Klasa photo definiuje widoczny obszar dla każdego pliku graficznego do kwadratu o boku 350px. Właściwość overflow ustawiona na hidden ukrywa paski przewijania dla zawartości nie mieszczących się w zdefiniowanym obszarze, display: inline-block sprawia, że elementy tej klasy zachowują się na zewnątrz jak elementy liniowe (ustawiają się jeden za drugim), a wewnątrz są elementami blokowymi zachowującymi zdefiniowane wymiary. Pozycjonowanie relatywne pozwoli na użycie tych elementów jako odniesienia dla elementów zawartych wewnątrz nich. Elementy img początkowo nie są widoczne. Za ich pokazanie będzie odpowiedzialny odpowiedni kod jQuery. Pozycjonując te elementy będziemy mogli wpływać na ich wartość top liczoną względem zewnętrznego elementu pozycjonowanego relatywnie. Została nam jeszcze klasa text. Elementy tej klasy ze względu na to, że są mniejsze niż element nadrzędny są pozycjonowane absolutnie, czyli właściwość bottom odnosi się do dolnej krawędzi elementu nadrzędnego, a nie elementu klasy text. Ujemna wartość ukrywa tekst pod dolną krawędzią elementu klasy photo, a z-index z wartością 100 gwarantuje pojawianie się tekstu na, a nie pod grafiką.

Teraz ostatnia i najważniejsza część, czyli kod jQuery:

$(document).ready(function()
{
	$('#p1').fadeIn(1000);
 	$('#p2').delay(200).fadeIn(1000);
 	$('#p3').delay(400).fadeIn(1000);
 	$('#p4').delay(600).fadeIn(1000);
 	$('#p5').delay(800).fadeIn(1000);
 	$('#p6').delay(1000).fadeIn(1000);
 
 	$('.photo').mouseover(function()
 	{
 		if($('img',this).queue('fx').length==0)
		{
			$('img',this).animate({'top':'-350px'},500);
			$('div',this).delay(200).animate({'bottom':'0px'},800);
		}
 	});
 	$('.photo').mouseleave(function()
 	{
 		if($('img',this).queue('fx').length<2)
		{
			$('div',this).animate({'bottom':'-100px'},400);
			$('img',this).delay(200).animate({'top':'0px'},700);
		}
	});
});

Skrypt rozpoczynamy od pokazania kolejnych grafik z efektem fadeIn. Efekt dla każdego kolejnego obrazka odpala się z opóźnieniem 200 ms względem poprzedniego (funkcja delay() z argumentem o 200 wyższym od poprzedniego). Poniżej mamy obsługę dwóch zdarzeń: mouseover i mouseleave. W pierwszym przypadku mamy dwie animacje funkcją animate(). Najpierw przewijamy w górę grafikę, a potem tekst. Całość jest zawarta w instrukcji warunkowej, którą na razie pominę. Warto sprawdzić zachowanie skryptu bez instrukcji if przy jednym i drugim zdarzeniu. W mouseleave najpierw tekst wraca na miejsce początkowe (tuż pod dolną krawędź widocznego obszaru), a następnie grafika zjeżdża w dół.

Ponieważ w jQuery efekty animacji są kolejkowane, to wszystkie zdarzenia powodujące wywołanie animacji, będą dokładały te animacje do kolejki. Szybkie, kilkukrotne najechanie i opuszczenie kursorem myszy tej samej grafiki spowoduje utworzenie kolejki wielu efektów, które będą musiały być wykonane. Użytkownik nie będzie już nic robił, a obrazki będą się przesuwały w górę i w dół tyle razy, ile razy te efekty zostały wcześniej dodane do kolejki. Rozwiązaniem tego problemu jest kontrolowanie ilości efektów w kolejce, co umożliwia nam właściwość length obiektu queue. Właśnie tę funkcję realizują instrukcje warunkowe w obsłudze zdarzeń. W pierwszym przypadku nowe animacje będą dodane tylko w sytuacji gdy kolejka jest pusta. W drugim bierzemy pod uwagę fakt, że pierwsza faza może nie zostać zakończona, więc jeden efekt może jeszcze być obecny w kolejce.

Zaprezentowany w tym artykule przykład nie będzie działał poprawnie w przeglądarkach IE8 i wcześniejszych ze względu na użytą wartość display: inline-block, której wymienione przeglądarki nie obsługują. Jeżeli komuś zależy na tych przeglądarkach powinien wymienić display: inline-block na float: left. Możliwe, że będzie to wymagało dopracowania kilku innych szczegółów.



Interfejs czy abstrakcja?

środa, 24 Listopad 2010

Wielu programistów stawiających pierwsze kroki w programowaniu obiektowym ma problem z decyzją, kiedy stosować dziedziczenie po klasie abstrakcyjnej, a kiedy implementację interfejsu. Dodatkowo dużo zamieszania wprowadza często powtarzane twierdzenie, że mechanizm implementacji interfejsów jest receptą na brak możliwości bezpośredniego dziedziczenia po kilku klasach jednocześnie.

Załóżmy, że mamy dwie klasy abstrakcyjne:

abstract class Uzytkownik
{
  protected $imie='';
  protected $nazwisko='';
 
  public abstract function zapisz_imie($imie)
  {
    $this->imie=$imie;
  }
 
  public abstract function zapisz_nazwisko($nazwisko)
  {
    $this->nazwisko=$nazwisko;
  }
}
 
abstract class Uprawnienia
{
  protected $poziom=0;
  protected $zakres=array();
 
  public abstract function ustaw_poziom($poziom)
  {
    $this->poziom=$poziom;
  }
 
  public abstract function dodaj_zakres($zakres)
  {
    $this->zakres[]=$zakres;
  }
 
  public abstract function sprawdz_dostep($zakres)
  {
    return in_array($zakres, $this->zakres);
  }
}

Nie możemy utworzyć klas Administrator, Kierownik, Handlowiec itp. dziedziczących po tych klasach. Zapis: „class Admin extends Uzytkownik, Uprawnienia” spowoduje przerwanie programu i wyświetlenie odpowiedniego komunikatu błędu. Próba rozwiązania tego problemu przy pomocy interfejsów wyglądałaby tak:

interface Uzytkownik
{
  public function zapisz_imie($imie);
  public function zapisz_nazwisko($nazwisko);
}
 
interface Uprawnienia
{
  public function ustaw_poziom($poziom);
  public function dodaj_zakres($zakres);
  public function sprawdz_dostep($zakres);
}
 
class Administrator implements Uzytkownik, Uprawnienia
{
  protected $imie='';
  protected $nazwisko='';
  protected $poziom=0;
  protected $zakres=array();
 
  public function zapisz_imie($imie)
  {
    $this->imie=$imie;
  }
 
  public function zapisz_nazwisko($nazwisko)
  {
    $this->nazwisko=$nazwisko;
  }
 
  public function ustaw_poziom($poziom)
  {
    $this->poziom=$poziom;
  }
 
  public function dodaj_zakres($zakres)
  {
    $this->zakres[]=$zakres;
  }
 
  public function sprawdz_dostep($zakres)
  {
    return in_array($zakres, $this->zakres);
  }
}
 
class Kierownik implements Uzytkownik, Uprawnienia
{
  protected $imie='';
  protected $nazwisko='';
  protected $poziom=0;
  protected $zakres=array();
 
  public function zapisz_imie($imie)
  {
    $this->imie=$imie;
  }
 
  public function zapisz_nazwisko($nazwisko)
  {
    $this->nazwisko=$nazwisko;
  }
 
  public function ustaw_poziom($poziom)
  {
    $this->poziom=$poziom;
  }
 
  public function dodaj_zakres($zakres)
  {
    $this->zakres[]=$zakres;
  }
 
  public function sprawdz_dostep($zakres)
  {
    return in_array($zakres, $this->zakres);
  }
}

To co od razu rzuca się w oczy, to identyczne metody w klasach Administarator i Kierownik. Taki zapis jest rozwiązaniem fatalnym i niwelującym większość zalet programowania obiektowego. Na tym przykładzie wyraźnie widać, że interfejsy nie zastąpią dziedziczenia. Zaś na dziedziczenie bezpośrednio po kilku klasach programistom PHP przyjdzie poczekać pewnie jeszcze kilka lat. Są sposoby symulowania takiego dziedziczenia już dzisiaj przy pomocy metod magicznych. Jeden z takich sposobów omawiam w szkoleniu Programowanie Obiektowe w PHP. Nie to jednak jest tematem tego artykułu.

Na podstawie powyższych przykładów mogę stwierdzić, jakie są korzyści z dziedziczenia.

  • Metody zdefiniowane w jednej klasie mogę użyć w innych klasach.
  • Mogę podzielić kod całego elementu na małe części (klasy) zawierające dane i funkcje związane z konkretną częścią systemu lub aspektem działania systemu.

A jakie są zalety interfejsów? Wyjaśnię to na przykładzie poniżej.

interface Cache
{
  public function zapisz($klucz, $dane);
  public function odczytaj($klucz);
}
 
class Pliki implements Cache
{
  public function zapisz($klucz, $dane)
  {
    //zapis danych w plikach na dysku serwera
    //...
  }
 
  public function odczytaj($klucz)
  {
    //odczyt danych z plików serwera
    //...
  }
}
 
class Baza_danych implements Cache
{
  public function zapisz($klucz, $dane)
  {
    //zapis danych w bazie danych
    //...
  }
 
  public function odczytaj($klucz)
  {
    //odczyt danych z bazy danych
    //...
  }
}

Dzięki zastosowaniu interfejsu możemy tworzyć program, a na samym końcu zdecydować czy będziemy korzystać z cachowania w plikach czy bazie danych. Implementacja tego samego interfejsu przez klasy Pliki i Baza_danych wymusza na nich posiadanie metod o takich samych nazwach i tej samej liczbie argumentów. Korzyści prezentuję na poniższym przykładzie

//$cache = new Pliki;
$cache = new Baza_danych;
 
$cache->zapisz('czas', '11:20');
//...
$czas=$cache->odczytaj('czas');

Możemy dowolnie wybrać jakiej klasy ma być obiekt $cache bez wpływu na dalszy kod. Ponadto możemy zlecić innemu programiście napisanie klasy, która będzie implementowała interfejs Cache i ona również będzie pasowała do napisanego wcześniej kodu.



Zabezpieczony: Programowanie obiektowe w PHP – lekcje 8-9

środa, 17 Listopad 2010

Ten wpis jest zabezpieczony hasłem. Aby go zobaczyć, proszę wprowadzić poniżej swoje hasło:



Zabezpieczony: Programowanie obiektowe w PHP – lekcje 6 i 7

wtorek, 16 Listopad 2010

Ten wpis jest zabezpieczony hasłem. Aby go zobaczyć, proszę wprowadzić poniżej swoje hasło:



Programowanie obiektowe w PHP – lekcje 4 i 5.

poniedziałek, 15 Listopad 2010

Poniżej prezentuję kolejne fragmenty szkolenia Programowanie obiektowe w PHP. Jutro następna część, a za kilka dni pełne szkolenie znajdzie się w ofercie Serwan.pl.

Słowniczek

pole klasy / właściwość klasy
zmienna dowolnego typu zawarta w klasie. Polem klasy może być również tablica lub obiekt.
metoda
funkcja zawarta w klasie
konstruktor
Metoda klasy uruchamiana automatycznie podczas tworzenia obiektu danej klasy. Do konstruktora można przekazywać argumenty. Ten temat poruszam w lekcjach 6-8.
destruktor
Metoda klasy uruchamiana automatycznie podczas usuwania obiektu danej klasy. Do destruktora nie przekazuje się argumentów. Destruktor omawiany jest w lekcji 9.

Dla większej wygody można powiększyć nagranie klikając ikonkę w prawym dolnym rogu filmu. Klip wymaga wtyczki Adobe Flash Player.

Ostatnia instrukcja powyższego przykładu jest trochę dziwna. Do metody „metoda1″ obiektu „obiekt” jest przekazywane pole tego samego obiektu, chociaż byłoby ono dostępne wewnątrz klasy poprzez referencję $this. Przekazanie tej wartości jawnie na liście argumentów jest spowodowane tym, by można było do tej metody przekazywać również inne wartości np. pola innych obiektów, wyniki działania dowolnej funkcji zwracającej liczbę, lub jawnie konkretną wartość. Ten ostatni przypadek realizowany jest w przykładzie poniżej.

Oczywiście wszelkie komentarze są mile widziane.



Programowanie obiektowe w PHP – lekcja 3.

niedziela, 14 Listopad 2010

Poniżej prezentuję trzeci fragment szkolenia Programowanie obiektowe w PHP. Jutro kolejna część, a w przyszłym tygodniu pełne szkolenie znajdzie się w ofercie Serwan.pl.

Słowniczek

abstrakcja
klasa może być modelem abstrakcyjnym dla innych klas dziedziczących po niej. Pojęcie to jest blisko związane z dziedziczeniem w szczególności po klasach abstrakcyjnych. Klasy i metody abstrakcyjne omawiam w lekcjach 35-39. Czasami abstrakcją nazywane jest też odwzorowanie rzeczywistych modeli w strukturze klasy (abstrakcja danych i procesów). Klasa samochód byłaby abstrakcją rzeczywistego samochodu, zawarta w klasie właściwość silnik byłaby abstrakcją części samochodu, a metoda jedź – abstrakcją funkcji samochodu.
przesłanianie pól i metod
Jest to redefiniowanie / nadpisywanie pól i metod klasy bazowej w klasie pochodnej. Ten temat poruszam w lekcjach 11 i 12.
metody wirtualne
W PHP każda metoda, która została przesłonięta w klasie pochodnej staje się metodą wirtualną. W innych językach wymagałoby to zastosowania specjalnej techniki (np. poprzedzenie definicji metody słowem virtual) w PHP mamy to z automatu. Ten temat poruszam w lekcji 11.
polimorfizm (wielopostaciowość)
mechanizm który pozawala wywołanie metod o takiej samej nazwie zawartych w różnych obiektach w zależności od kontekstu wywołania metody. Przykład polimorficznego wywołania metody zawiera lekcja 11.

Dla większej wygody można powiększyć nagranie klikając ikonkę w prawym dolnym rogu filmu. Klip wymaga wtyczki Adobe Flash Player.

Oczywiście wszelkie komentarze są mile widziane.



Programowanie obiektowe w PHP – lekcja 2.

sobota, 13 Listopad 2010

Poniżej prezentuję drugi fragment szkolenia Programowanie obiektowe w PHP. Jutro kolejna część, a w przyszłym tygodniu pełne szkolenie znajdzie się w ofercie Serwan.pl.

W komentarzach pod wczorajszą lekcją pojawiły się pojęcia:

  • izolacja kodu
  • dziedziczenie
  • klonowanie

Te i wiele innych pojęć omawiam w kolejnych lekcjach choć nie zawsze muszą być tak nazwane. Dla większej przejrzystości i wygody będę umieszczał po kilka definicji przy każdej lekcji.

hermetyzacja/enkapsulacja (izolacja kodu, kapsułkowanie, ukrywanie informacji)
zamknięcie i ukrycie przed kodem zewnętrznym kodu i pól wewnątrz klas. Klasy udostępniają jedynie swój interfejs, za pośrednictwem którego możliwe jest wykorzystanie kodu zawartego w metodach klas i użycie pól tych klas. Technicznie służą temu omawiane w lekcji poniżej kwalifikatory dostępu. Hermetyzacja uodparnia program na błędne użycie obiektów oraz umożliwia podział procesów na prostsze czynności.
dziedziczenie
mechanizm który pozawala na tworzenie hierarchii klas od najbardziej ogólnych do szczegółowych. Wspólna funkcjonalność jest zawarta w klasach ogólnych. Klasy dziedziczące są wzbogacane o indywidualne pola i metody. Dzięki temu mechanizmowi zachodzi specjalizacja klas potomnych. Więcej na ten temat wyjaśniam w lekcji 10.
klonowanie
Ponieważ obiekty nie mogą być kopiowane w ten sam sposób co inne typy danych, stworzono mechanizm klonowania do tworzenia niezależnych kopii obiektu. Ten temat poruszam w lekcji 22.

Dla większej wygody można powiększyć nagranie klikając ikonkę w prawym dolnym rogu filmu. Klip wymaga wtyczki Adobe Flash Player.

Oczywiście wszelkie komentarze są mile widziane.



Programowanie obiektowe w PHP – lekcja 1.

piątek, 12 Listopad 2010

Poniżej prezentuję fragment szkolenia Programowanie obiektowe w PHP. Jutro kolejna część, a w przyszłym tygodniu pełne szkolenie znajdzie się w ofercie Serwan.pl.

Dla większej wygody można powiększyć nagranie klikając ikonkę w prawym dolnym rogu filmu. Klip wymaga wtyczki Adobe Flash Player.

Oczywiście wszelkie komentarze są mile widziane.