Разве не забавно, что мы играем с новейшими техниками CSS, такими как тени и переходы? Есть только одна проблема: как мы компенсируем или, что более важно, обнаруживаем браузеры, которые их не поддерживают? Ну, есть несколько решений. В этом уроке и скринкасте мы создадим функцию JavaScript, которая будет принимать имя свойства CSS в качестве параметра и будет возвращать boolean
, указывающее, поддерживает ли браузер переданное свойство.
Предпочитаете видеоурок?
Шаг 1
Давайте начнем с определения того, как мы хотим вызвать нашу function
. Здесь все будет просто; что-то вроде следующего должно сделать свое дело:
1
2
3
|
if ( supports(‘textShadow’) ) {
document.documentElement.className += ‘ textShadow’;
}
|
Это должен быть последний вызов function
. Когда мы передаем имя свойства CSS в функцию supports()
, оно возвращает boolean
. Если true
, мы прикрепим className
к documentElement
или <html>
. Затем мы получим новое имя `class` для подключения из нашей таблицы стилей.
Шаг 2
Далее мы создадим supports() function
.
1
2
3
|
var supports = (function() {
})();
|
Почему мы не делаем supports
равной стандартной функции? Ответ в том, что сначала нам нужно немного подготовиться , и нет абсолютно никакой причины повторять эти задачи снова и снова при каждом вызове функции. В подобных случаях лучше сделать supports
равной тому, что возвращается из самовыполняющейся функции.
Шаг 3
Чтобы проверить, поддерживает ли браузер определенные свойства, нам нужно создать элемент * dummy * для тестирования. Этот сгенерированный элемент никогда не будет вставлен в DOM; думать об этом как о манекене!
1
|
var div = document.createElement(‘div’);
|
Как вы, вероятно, знаете, есть несколько префиксов поставщиков, которые мы можем использовать при работе со свойствами CSS3:
- -moz
- -webkit
- -о
- -Миз
- -khtml
Наш JavaScript должен будет отфильтровать эти префиксы и протестировать их. Итак, давайте разместим их в array
; мы назовем это, vendors
.
1
2
|
var div = document.createElement(‘div’),
vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘);
|
Использование функции
split()
для созданияarray
изstring
по общему признанию, лениво, но экономит несколько секунд!
Поскольку мы будем фильтровать этот array
, давайте будем хорошими парнями и девочками, а также кешируем length
array
.
1
2
3
|
var div = document.createElement(‘div’),
vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘),
len = vendors.length;
|
Подготовительная работа, приведенная выше, является статической по своей природе, и ее не нужно повторять каждый раз, когда мы вызываем supports()
. Вот почему мы запускаем его только один раз, когда страница загружается. Теперь давайте return
function
которая будет фактически назначена variable
.
1
2
3
|
return function(prop) {
};
|
Прелесть
closures
в том, что, хотяsupports()
равна возвращаемойfunction
, она все еще имеет доступ к переменнымdiv
,vendors
иlen
.
Шаг 4
Непосредственный тест: если переданное свойство доступно атрибуту style
div
, мы знаем, что браузер поддерживает это свойство; так return true
.
1
2
3
|
return function(prop) {
if ( prop in div.style ) return true;
};
|
Представьте, скажем, свойство CSS3 text-shadow
. Большинство современных браузеров поддерживают его без необходимости использования префикса поставщика. Имея это в виду, зачем фильтровать все префиксы, если нам это не нужно? Вот почему мы размещаем этот чек сверху.
Шаг 5
Скорее всего, вы привыкли вводить имена свойств CSS3, например: -moz-box-shadow
. Однако, если в Firebug вы MozBoxShadow
object
style
, вы обнаружите, что он записан как MozBoxShadow
. Таким образом, если мы проверим:
1
|
‘mozboxShadow’ in div.style // false
|
False
будет возвращена. Это значение чувствительно к регистру.
Это означает, что, если пользователь передаст boxShadow
функции boxShadow
supports()
, boxShadow
сбой. Давайте подумаем и проверим, является ли первая буква аргумента строчной. Если это так, мы исправим ошибку для них.
1
2
3
4
5
6
7
8
|
return function(prop) {
if ( prop in div.style ) return true;
prop = prop.replace(/^[az]/, function(val) {
return val.toUpperCase();
});
};
|
Регулярные выражения на помощь! Выше мы проверяем, есть ли одна строчная буква в начале строки ( ^
). Только при условии, что он найден, мы используем функцию toUpperCase()
чтобы заглавные буквы.
Шаг 6
Затем нам нужно отфильтровать массив vendors
и проверить, есть ли совпадение. Например, если передано box-shadow
, мы должны проверить, содержит ли атрибут style
div
любое из следующего:
- MozBoxShadow
- WebkitBoxShadow
- MsBoxShadow
- OBoxShadow
- KhtmlBoxShadow
Если совпадение найдено, мы можем return true
, потому что браузер действительно предоставляет поддержку для теней блоков!
01
02
03
04
05
06
07
08
09
10
11
12
13
|
return function(prop) {
if ( prop in div.style ) return true;
prop = prop.replace(/^[az]/, function(val) {
return val.toUpperCase();
});
while(len—) {
if ( vendors[len] + prop in div.style ) {
return true;
}
}
};
|
Хотя мы могли бы использовать оператор for
для фильтрации array
, в этом нет особой необходимости.
- Порядок не важен
-
while
операторы быстрее набираются и требуют меньше символов - Есть небольшое улучшение производительности
Не смущайтесь vendors[len] + prop
; просто замените эти имена их реальными значениями: MozBoxShadow
.
Шаг 7
Но что, если ни одно из этих значений не совпадает? В этом случае браузер не поддерживает свойство, и в этом случае мы должны return false
.
1
2
3
4
5
6
|
while(len—) {
if ( vendors[len] + prop in div.style ) {
return true;
}
}
return false;
|
Это должно сделать это для нашей функции! Давайте проверим это, применив className
к элементу html
, если браузер поддерживает, скажем, свойство text-stroke
(что делает только webkit).
1
2
3
|
if ( supports(‘textStroke’) ) {
document.documentElement.className += ‘ textStroke’;
}
|
Шаг 8: Использование
С именем class
которое мы теперь можем подключить , давайте попробуем это в нашей таблице стилей.
01
02
03
04
05
06
07
08
09
10
|
/* fallback */
h1 {
color: black;
}
/* text-stroke support */
.textStroke h1 {
color: white;
-webkit-text-stroke: 2px black;
}
|
Окончательный исходный код
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
var supports = (function() {
var div = document.createElement(‘div’),
vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘),
len = vendors.length;
return function(prop) {
if ( prop in div.style ) return true;
prop = prop.replace(/^[az]/, function(val) {
return val.toUpperCase();
});
while(len—) {
if ( vendors[len] + prop in div.style ) {
// browser supports box-shadow.
// Or use a bang (!) to test if the browser doesn’t.
return true;
}
}
return false;
};
})();
if ( supports(‘textShadow’) ) {
document.documentElement.className += ‘ textShadow’;
}
|
Для более полного решения обратитесь к библиотеке Modernizr .