EpicWEB.plwebdesign, programowanie, phat lewt!

o autorze / projekty / kontakt

Bezpieczeństwo / CSS / Epic Loot / Flash / Fsck Up / GFX / Google / Gry / Hosting / HTML / JS MySQL / OS / Other / PHP / Praca / Techblog / Web

Ostatni projekt: ddrpl.com

Wykrywanie poziomu powiększenia w przeglądarce.

Gdybym za każdym razem, kiedy źródłem błędnego wyświetlania się strony jest to, że klient ma zwiększony poziom zbliżenia (Ctrl +) dostawał 5 zł miałbym już chyba na parę zgrzewek PEPSI ;-) Przy jednym z ostatnich mini projektów potrzebowałem informacji właśnie o tym - czy osoba odwiedzająca stronę ma ustawiony zoom na wartość inną niż 100%.

Pierwsze próby spełzły na niczym - myślałem, że przy zwiększeniu poziomu zoom-u wymiary obrazków pobierane dynamicznie przez JavaScript będą odzwierciedlał ich nowe proporcje - jednak tak nie jest, podają one wciąż rzeczywiste (ustalone na stronie za pomocą HTML/CSS) wymiary. Okazało się, że jedynym obiektem, który przy zmianie zoom-u potrafi zgłaszać swój nowy wymiar jest Flash. Nie przepadam za Flashem, ale Action Script mam jako-tako opanowany, więc całość zamknęła się w 8 linijkach AS3 i kilku JS. Zacznijmy od Action Script:

stage.scaleMode = "noScale"; #1
import flash.external.ExternalInterface;
import flash.utils.setInterval;
function sendSignal():void {
        ExternalInterface.call("flashSize", stage.stageWidth); #5
}
setInterval(sendSignal, 100);
sendSignal();

Wyjaśnię tylko co "trudniejsze" linijki. Pierwsza (#1) informuje nasz obiekt, że w przypadku skalowania strony nie należy skalować zawartości flash - obiekty mają pozostać tej samej wielkości, zmieni się za to wymiar "płótna" (stage). Kolejna (#5) wywołuje poprzez ExternalInterface funkcję flashSize którą definiujemy w naszym HTML jako funkcję JavaScript, przyjmującą jako argument jeden parametr numeryczny - przekazujemy do niej szerokość obiektu flash.

Mając już gotowy Flash, osadzamy go na stronie nadając np. 100px szerokości - domyślnie, pierwsze wywołanie przekaże do funkcji flashSize() właśnie powyższe 100. Przy przeskalowaniu strony (Ctrl +) przekaże już nową wartość, np. 111px - dzięki temu możemy z proporcji (bądź też bez, jeżeli używamy bazowej szerokości 100px) obliczyć procentowy poziom powiększenia i odpowiednio zareagować (zmienić logikę strony, poinformować odwiedzającego).

Próbowałem wywołanie cykliczne (setInterval) zastąpić reakcją na zdarzenie Event.RESIZE, ale zdaje się, że nie jest one sygnalizowane w takiej konfiguracji stąd też setInterval - na szczęście sama funkcja jest na tyle lekka że nie powoduje praktycznie żadnego dodatkowego obciążenia dla CPU.

6 komentarzy | Flash, JS, Techblog 12 marca / 11:37:25
URL Trackback

Internet Explorer i <OBJECT>

<OBJECT> to tag pozwalający na osadzanie np. obiektów multimedialnych na stronach WWW - najczęściej spotykamy się z nim np. na YouTube, gdzie w ten sposób osadzany jest odtwarzacz Flash.

Internet Explorer w wersji 6 radośnie ignoruje sobie ten tag i wymaga zastosowania tagu <EMBED> dlatego często obiekty osadzane są tak jak poniżej:

<object width="480" height="295">
        <param name="movie" value="http://www.youtube.com/v/sDsAPMhuABU&hl=pl_PL&fs=1"></param>
        <param name="allowFullScreen" value="true"></param>
        <param name="allowscriptaccess" value="always"></param>
        <embed src="http://www.youtube.com/v/sDsAPMhuABU&hl=pl_PL&fs=1" type="application/x-shockwave-flash" width="480" height="295" allowscriptaccess="always" allowfullscreen="true"></embed>
</object>

Dzięki zastosowaniu takiej notacji, zarówno IE6 jak i nowsze przeglądarki poprawnie wyświetlają daną treść. Oczywiście, żeby nie było różowo, są i tutaj haczyki - jeden właśnie spowodował zmarnowanie 30 minut mojego życia.

O ile jak już wcześniej wspomniałem IE6 przy napotkaniu tagu <OBJECT> w HTML zignoruje go, o tyle przetworzy jego zawartość i wyświetli dane z <EMBED> o tyle zupełnie inaczej ma się to z obiektami dynamicznie wstawianymi do DOMu poprzez Java Script - w takim wypadku IE6 ignoruje zarówno <OBJECT> jak i całą jego zawartość. Rozwiązaniem w takim wypadku jest "wyłuskanie" <EMBED> ze wstawianego kodu HTML i wyświetlenie tylko tego jednego znacznika dla IE6.

7 komentarzy | Fsck Up, HTML, JS, Techblog 08 stycznia / 10:33:10
URL Trackback

Lightbox - 3 wielkości obrazka.

LightBox 2 to popularne rozwiązanie pozwalające na pokazywanie powiększeń zdjęć bez konieczności otwierania nowego okna. Poprzez osadzenie skryptu i prostą modyfikację już istniejącego kodu otrzymujemy galerię która działa od ręki.

Problemy pojawiają się dopiero kiedy chcemy zmodyfikować działanie. Klient zamówił w firmie wykonanie serwisu dla pośrednika w obrocie nieruchomości. Każda oferta zawiera zdjęcia w 3 wymiarach - miniaturka (1), zdjęcie główne (2) i zdjęcie powiększone. Po kliknięciu w miniaturkę ładuje się jej wersja "główna" w miejsce zdjęcia 2, zaś po kliknięciu w zdjęcie 2 ładuje się powiększenie Lightboxem. Dodatkowo, użytkownik ma możliwość nawigowania pomiędzy zdjęciami w Lightbox za pomocą dostarczanego przezeń interfejsu.

Jak już wspomniałem, Lightbox działa od ręki - wystarczy do linków od powiększeń obrazków dodać atrybut rel="lightbox" dla pojedynczego powiększenia, lub rel="lightbox" dla grupy powiększeń. Niestety, zachowanie do nadpisuje akcję onclick przez co psuje już działający mechanizm przejścia zdjęcia z pozycji 1 na 2. Rozwiązaniem jest modyfikacja pliku lightbox.js, a dokładniej funkcji start() i end() wywoływanych odpowiednio przed i po wyświetleniu powiększenia. Dodatkowo, obrazki, które chcemy umieścić w galerii nie powinny posiadać odnośnika z parametrem rel, akcja podmiany obrazka 2 na 1 powinna znajdować się w onclick obrazka oraz musimy mieć możliwość ich łatwej identyfikacji (np. przez nadanie ich odnośnikom klasy isLightbox). Ok, zabieramy się za modyfikowanie lightbox.js:

//Zmodyfikowana metoda start():

start: function(imageLink) {    
        var im = document.getElementsByTagName('A');
        for(var i = 0, j = im.length ; i < j ; i++) {
                        if(im[i].className == 'isLightbox') im[i].setAttribute('rel', 'lightbox[1]');
        }
        this.updateImageList();
        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
// dalsza część bez zmian
//Zmodyfikowana metoda end():
end: function() {
        var im = document.getElementsByTagName('A');
        for(var i = 0, j = im.length ; i < j ; i++) {
                        if(im[i].className == 'isLightbox') im[i].setAttribute('rel', '');
        }
        this.updateImageList();
// dalsza część bez zmian

Pierwsza dokonana przez nas modyfikacja oznaczy wybrane obrazki jako korzystające z Lightbox oraz zaktualizuje kolekcję zdjęć w galerii. Druga zaś usunie oznaczenia i ponownie zaktualizuje kolekcję, co pozwoli nam na przywrócenie funkcjonalności ładowania powiększenia do widoku 2.

Zapewne jest łatwiejszy sposób na odnalezienie obrazków niż getElementsByTagName ale niestety nie używam Scriptaculous więc zastosowałem proste (i pewnie mało wydajne) rozwiązanie.

3 komentarze | JS, Techblog 20 grudnia / 11:30:58
URL Trackback