W trzeciej części kursu opiszę metody z grupy Extensibility. Domyślnie podczas tworzenia własnej paczki ta grupa jest ukryta i jeśli chce się mieć dostęp do niej, należy ją ręcznie zaznaczyć.
Modernizr.addTest()
Zacznę od bardzo przydatnej i bardzo prostej w obsłudze funkcji, która służy do dodawania własnych testów.
1 2 3 4 5 | //Przykład 1 Modernizr.addTest('customtest', function() { var result = false; //Pozostała część funkcji return result; }); |
Jako pierwszy argument funkcji podajemy nazwę właściwości pod jaką będzie dostępny wynik naszego testu. Drugim argumentem jest funkcja testująca. Od tego momentu z naszego testu możemy korzystać w następujący sposób:
1 2 | //Przykład 2 Modernizr.customtest; |
Modernizr.prefixed()
Czym są prefiksy w CSS i jak należy je stosować jest zapewne wszystkim wiadome. Oprócz tego, że dzięki nim pliki CSS są większe ten sam los dotyka skrypty JS. Przykładowo mamy następujący fragment CSS:
1 2 3 4 5 6 | //Przykład 3 .wrapper { -moz-column-count:3; -webkit-column-count:3; column-count:3; } |
Teraz załóżmy, że chcemy zmienić wartość column-count na inną za pomocą JS. Problem polega na tym, że aktualna wersja Chrome i Firefoxa nie zrozumie takiego kodu:
1 2 | //Przykład 4 document.querySelector('.content').style.columnCount = 6; |
Kod jak powyżej zrozumie za to IE 11 ;) Można rzecz jasna problem rozwiązać podobnie jak w CSS, czyli dodawać kolejne linie kodu dla poszczególnych przeglądarek. Jest jednak lepsze rozwiązanie, które nazywa się Modernizer.prefixed(). Funkcja ta po podaniu nazwy właściwości w parametrze, zwraca jej wersje poprzedzoną odpowiednim prefiksem zależnym od przeglądarki:
1 2 3 | //Przykład 5 Modernizr.prefixed('columnCount'); // W FF efektem będzie MozColumnCount, w Chrome WebkitColumnCount a w IE 11 columnCount |
Dzięki czemu rozwiązanie naszego problemu sprowadza się do jednej linii kodu:
1 2 | // Przykład 6 document.querySelector('.content').style[Modernizr.prefixed('columnCount')] = num; |
To jednak nie wszystko co potrafi prefixed(). Za pomocą tej metody można także wykrywać funkcje i właściwości DOM. Dla przykładu – mamy funkcję getUserMedia. W momencie kiedy piszę ten artykuł tę funkcję obsługuje Chrome i Friefox. W tym konkretnym przypadku aby wziąć pod uwagę wszystkie możliwe wersje funkcji należało by zrobić coś takiego:
1 2 3 4 5 6 | // Przykład 7 navigator.getUserMedia = ( navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); |
Jednak dzięki Modernizerowi i funkcji prefixed() można ten kod skrócić do jednej linijki:
1 2 | // Przykład 8 navigator.getUserMedia = Modernizr.prefixed('getUserMedia', navigator); |
W przykładzie powyżej, drugi argument to obiekt w którym poszukiwana jest funkcja / właściwość podana w pierwszym parametrze. Jak wspomniałem wcześniej IE 11 nie wspiera tego API, można więc w przypadku zwrócenia przez prefixed() wartości false, podać odpowiedni polyfill w następujący sposób:
1 2 3 | // Przykład 9 navigator.getUserMedia = Modernizr.prefixed('getUserMedia', navigator) || function (options, successCallback, errorCallback) { // polifill } |
Jako ciekawostkę podam, że pod tym adresem można znaleźć bardzo dużą liczbę różnego typu „łatek”, które można zastosować w przypadku, gdy jakaś przeglądarka nie obsługuje natywnie interesującej nas funkcji.
Funkcja prefixed() posiada jeszcze trzeci argument. Przydaje się on wtedy, gdy chcemy aby Modernizer zwrócił nam tylko odpowiednią „wersję” nazwy funkcji lub właściwości. W takim przypadku trzeci argument należy ustawić na false. W przeciwnym wypadku możemy go pominąć.
Modernizr.mq()
Funkcja ta służy to testowania obsługi media queries w przeglądarce. Korzystanie z tej funkcji jest bardzo proste – polega na podaniu w pierwszym argumencie interesującego nas zapytania. W zależności od tego czy dana przeglądarka prawidłowo je obsługuje czy też nie, zostanie zwrócone true lub false. W przypadku gdy przeglądarka nie obsługuje w ogóle media queres – funkcja zawsze będzie zwracać false.
Jeśli chcemy sprawdzić czy dana przeglądarka w ogóle obsługuje media queries to można to zrobić w następujący sposób:
1 2 3 4 | // Przykład 10 Modernizr.load([{ test : Modernizr.mq('only all'), nope : 'respond.js' }]); |
Jedna uwaga co do testowania za pomocą tej funkcji. Przykładowo chcemy przetestować następujący zapytanie:
1 2 3 | // Przykład 11 if (Modernizr.mq("screen and (max-width:480px)")) { console.log("works!"); } |
Na naszej przeglądarce (przykładowo Chrome) takie zapytanie będzie działać. Jednak gdy mamy okno przeglądarki rozszerzone na więcej niż 480px i odpalimy przykład powyżej to funkcja mq() zwróci false i w konsoli nic się nie pojawi. Dopiero gdy zwęzimy okno do 480px lub mniej w konsoli pojawi się napis „works!”.
Modernizr.testStyles()
Funkcja tworzy div’a o id modernizr ze stylem podanym w pierwszym argumencie. Tego div’a dostajemy potem w funkcji anonimowej jako pierwszy argument. Drugi argument to styl jaki podaliśmy w pierwszym argumencie funkcji testStyles(). Możemy teraz przeprowadzić różne operacje na elemencie, który dostaliśmy w funkcji anonimowej. Jeśli coś jest niezrozumiałe, na pewno rozjaśni to przykład poniżej (zaczerpnięty z oficjalnej dokumentacji).
1 2 3 4 | // Przykład 12 Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) { Modernizr.addTest('width', elem.offsetWidth == 9); }); |
W pierwszym argumencie funkcji podajemy cały zestaw reguł CSS. Ważne aby selektor rozpoczynał się od „#modernizr”, ponieważ element jaki dostaniemy w funkcji anonimowej będzie właśnie miał takie id. W funkcji podanej w drugim parametrze tworzymy test, który możemy potem wykorzystać poza funkcją aby odpowiednio zareagować na jego wynik.
Oprócz tych dwóch parametrów możemy podać jeszcze dwa dodatkowe. Pierwszy odpowiada za to ile „dzieci” będzie posiadał element podany w funkcji anonimowej. Elementy te także będą div’ami i będą posiadały id „modernizer1” , „modernizer2” etc. Jeśli natomiast chcielibyśmy im nadać inne id możemy użyć do tego argumentu czwartego, w którym w tablicy możemy podać interesujące nas nazwy.
1 2 3 4 5 6 | // Przykład 13 Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) { Modernizr.addTest('width', elem.offsetWidth == 9); }, 2, ['firstchild', 'secondchild']); |
Modernizr.testProp() i Modernizr.testAllProps()
Funkcja sprawdza czy dana właściwość CSS jest rozpoznawana przez przeglądarkę. Nazwa właściwości, którą chcemy przetestować musi być podana w notacji camelCase. Przykład poniżej:
1 2 3 | // Przykład 14 Modernizr.testProp('boxSizing') // W Chrome zwróci true ale w Firefoxie false ponieważ tam należy użyć właściwości z prefiksem |
Odmianą tej funkcji jest funkcja testAllProps(), która dodatkowo sprawdza czy przeglądarka rozpoznaje wariant właściwości poprzedzonej prefiksami. Tutaj także należy nazwę właściwości podać w notacji camelCase. Przykład poniżej:
1 2 3 | // Przykład 15 Modernizr.testAllProps('boxSizing') // Z kolei ta metoda i w Chrome i Firefoxie zwróci true ale w IE 7 false ponieważ tam ta właściwość nie jest w ogóle obsługiwana |
Modernizr.hasEvent()
Metoda ta sprawdza czy przeglądarka obsługuje dane zdarzenie. Dodatkowo w drugim argumencie można podać element, i sprawdzić czy on obsługuje to zdarzenie. Przykład poniżej zaczerpnięty z dokumentacji:
1 2 3 | // Przykład 16 Modernizr.hasEvent('gesturestart', elem) // true |
Modernizr._prefixes, Modernizr._domPrefixes i _cssomPrefixes
Tu będzie krótko – wszystkie trzy właściwości zwracają tablicę prefiksów. Jakie dokładnie, jest pokazane poniżej:
1 2 3 4 5 6 | Modernizr._prefixes // ["", "-webkit-", "-moz-", "-o-", "-ms-", ""] Modernizr._cssomPrefixes // ["Webkit", "Moz", "O", "ms"] Modernizr._domPrefixes // ["webkit", "moz", "o", "ms"] |
Michał Janicki – programista PHP (okazjonalnie także .NET), bloger, zafascynowany grami video i tym co można teraz zrobić za pomocą JavaScript i HTML 5/CSS 3.
@Michał Janicki Znasz jakiś lepszy sposób (niż ten: https://webroad.pl/javascript/721-responsywne-menu-rozwijane ) na poprawienie błędu z rozpoznaniem ekranów dotykowych na Windows Phone? Konkretnie chodzi o dodanie klasy touch do body.