Как определить браузер js
Теперь давайте более внимательно взглянем на DOM-узлы.
В этой главе мы подробнее разберём, что они собой представляют и изучим их основные свойства.
Классы DOM-узлов
У разных DOM-узлов могут быть разные свойства. Например, у узла, соответствующего тегу <a> , есть свойства, связанные со ссылками, а у соответствующего тегу <input> – свойства, связанные с полем ввода и т.д. Текстовые узлы отличаются от узлов-элементов. Но у них есть общие свойства и методы, потому что все классы DOM-узлов образуют единую иерархию.
Каждый DOM-узел принадлежит соответствующему встроенному классу.
Корнем иерархии является EventTarget, от него наследует Node и остальные DOM-узлы.
На рисунке ниже изображены основные классы:
Существуют следующие классы:
-
– это корневой «абстрактный» класс. Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события», о которых мы поговорим позже. – также является «абстрактным» классом, и служит основой для DOM-узлов. Он обеспечивает базовую функциональность: parentNode , nextSibling , childNodes и т.д. (это геттеры). Объекты класса Node никогда не создаются. Но есть определённые классы узлов, которые наследуют от него: Text – для текстовых узлов, Element – для узлов-элементов и более экзотический Comment – для узлов-комментариев. – это базовый класс для DOM-элементов. Он обеспечивает навигацию на уровне элементов: nextElementSibling , children и методы поиска: getElementsByTagName , querySelector . Браузер поддерживает не только HTML, но также XML и SVG. Класс Element служит базой для следующих классов: SVGElement , XMLElement и HTMLElement . – является базовым классом для всех остальных HTML-элементов. От него наследуют конкретные элементы:
- …и т.д, каждому тегу соответствует свой класс, который предоставляет определённые свойства и методы.
- HTMLInputElement – этот класс предоставляет специфичные для элементов формы свойства,
- HTMLElement – предоставляет общие для HTML-элементов методы (и геттеры/сеттеры),
- Element – предоставляет типовые методы элемента,
- Node – предоставляет общие свойства DOM-узлов,
- EventTarget – обеспечивает поддержку событий (поговорим о них дальше),
- …и, наконец, он наследует от Object , поэтому доступны также методы «обычного объекта», такие как hasOwnProperty .
- console.log(elem) выводит элемент в виде DOM-дерева.
- console.dir(elem) выводит элемент в виде DOM-объекта, что удобно для анализа его свойств.
- elem.nodeType == 1 для узлов-элементов,
- elem.nodeType == 3 для текстовых узлов,
- elem.nodeType == 9 для объектов документа, можно посмотреть остальные значения.
- Свойство tagName есть только у элементов Element .
- Свойство nodeName определено для любых узлов Node :
- для элементов оно равно tagName .
- для остальных типов узлов (текст, комментарий и т.д.) оно содержит строку с типом узла.
Другими словами, свойство tagName есть только у узлов-элементов (поскольку они происходят от класса Element ), а nodeName может что-то сказать о других типах узлов.
Например, сравним tagName и nodeName на примере объекта document и узла-комментария:
Если мы имеем дело только с элементами, то можно использовать tagName или nodeName , нет разницы.
Имена тегов (кроме XHTML) всегда пишутся в верхнем регистреВ браузере существуют два режима обработки документа: HTML и XML. HTML-режим обычно используется для веб-страниц. XML-режим включается, если браузер получает XML-документ с заголовком: Content-Type: application/xml+xhtml .
В HTML-режиме значения tagName/nodeName всегда записаны в верхнем регистре. Будет выведено BODY вне зависимости от того, как записан тег в HTML <body> или <BoDy> .
В XML-режиме регистр сохраняется «как есть». В настоящее время XML-режим применяется редко.
innerHTML: содержимое элемента
Свойство innerHTML позволяет получить HTML-содержимое элемента в виде строки.
Мы также можем изменять его. Это один из самых мощных способов менять содержимое на странице.
Пример ниже показывает содержимое document.body , а затем полностью заменяет его:
Мы можем попробовать вставить некорректный HTML, браузер исправит наши ошибки:
Если innerHTML вставляет в документ тег <script> – он становится частью HTML, но не запускается.
Будьте внимательны: «innerHTML+=» осуществляет перезапись
Мы можем добавить HTML к элементу, используя elem.innerHTML+="ещё html" .
На практике этим следует пользоваться с большой осторожностью, так как фактически происходит не добавление, а перезапись.
Технически эти две строки делают одно и то же:
Другими словами, innerHTML+= делает следующее:
- Старое содержимое удаляется.
- На его место становится новое значение innerHTML (с добавленной строкой).
Так как содержимое «обнуляется» и переписывается заново, все изображения и другие ресурсы будут перезагружены.
В примере chatDiv выше строка chatDiv.innerHTML+="Как дела?" заново создаёт содержимое HTML и перезагружает smile.jpg (надеемся, картинка закеширована). Если в chatDiv много текста и изображений, то эта перезагрузка будет очень заметна.
Есть и другие побочные эффекты. Например, если существующий текст выделен мышкой, то при переписывании innerHTML большинство браузеров снимут выделение. А если это поле ввода <input> с текстом, введённым пользователем, то текст будет удалён. И т.д.
К счастью, есть и другие способы добавить содержимое, не использующие innerHTML , которые мы изучим позже.
outerHTML: HTML элемента целиком
Свойство outerHTML содержит HTML элемента целиком. Это как innerHTML плюс сам элемент.
Посмотрим на пример:
Будьте осторожны: в отличие от innerHTML , запись в outerHTML не изменяет элемент. Вместо этого элемент заменяется целиком во внешнем контексте.
Да, звучит странно, и это действительно необычно, поэтому здесь мы и отмечаем это особо.
Какая-то магия, да?
В строке (*) мы заменили div на <p>Новый элемент</p> . Во внешнем документе мы видим новое содержимое вместо <div> . Но, как видно в строке ( ** ), старая переменная div осталась прежней!
Это потому, что использование outerHTML не изменяет DOM-элемент, а удаляет его из внешнего контекста и вставляет вместо него новый HTML-код.
То есть, при div.outerHTML=. произошло следующее:
- div был удалён из документа.
- Вместо него был вставлен другой HTML <p>Новый элемент</p> .
- В div осталось старое значение. Новый HTML не сохранён ни в какой переменной.
Здесь легко сделать ошибку: заменить div.outerHTML , а потом продолжить работать с div , как будто там новое содержимое. Но это не так. Подобное верно для innerHTML , но не для outerHTML .
Мы можем писать в elem.outerHTML , но надо иметь в виду, что это не меняет элемент, в который мы пишем. Вместо этого создаётся новый HTML на его месте. Мы можем получить ссылки на новые элементы, обратившись к DOM.
nodeValue/data: содержимое текстового узла
Свойство innerHTML есть только у узлов-элементов.
У других типов узлов, в частности, у текстовых, есть свои аналоги: свойства nodeValue и data . Эти свойства очень похожи при использовании, есть лишь небольшие различия в спецификации. Мы будем использовать data , потому что оно короче.
Прочитаем содержимое текстового узла и комментария:
Мы можем представить, для чего нам может понадобиться читать или изменять текстовый узел, но комментарии?
Иногда их используют для вставки информации и инструкций шаблонизатора в HTML, как в примере ниже:
…Затем JavaScript может прочитать это из свойства data и обработать инструкции.
textContent: просто текст
Свойство textContent предоставляет доступ к тексту внутри элемента за вычетом всех <тегов> .
Как мы видим, возвращается только текст, как если бы все <теги> были вырезаны, но текст в них остался.
На практике редко появляется необходимость читать текст таким образом.
Намного полезнее возможность записывать текст в textContent , т.к. позволяет писать текст «безопасным способом».
Представим, что у нас есть произвольная строка, введённая пользователем, и мы хотим показать её.
- С innerHTML вставка происходит «как HTML», со всеми HTML-тегами.
- С textContent вставка получается «как текст», все символы трактуются буквально.
Сравним два тега div:
- В первый <div> имя приходит «как HTML»: все теги стали именно тегами, поэтому мы видим имя, выделенное жирным шрифтом.
- Во второй <div> имя приходит «как текст», поэтому мы видим <b>Винни-пух!</b> .
В большинстве случаев мы рассчитываем получить от пользователя текст и хотим, чтобы он интерпретировался как текст. Мы не хотим, чтобы на сайте появлялся произвольный HTML-код. Присваивание через textContent – один из способов от этого защититься.
Свойство «hidden»
Атрибут и DOM-свойство «hidden» указывает на то, видим ли мы элемент или нет.
Мы можем использовать его в HTML или назначать при помощи JavaScript, как в примере ниже:
Технически, hidden работает так же, как style="display:none" . Но его применение проще.
Другие свойства
У DOM-элементов есть дополнительные свойства, в частности, зависящие от класса:
- value – значение для <input> , <select> и <textarea> ( HTMLInputElement , HTMLSelectElement …).
- href – адрес ссылки «href» для <a href=". "> ( HTMLAnchorElement ).
- id – значение атрибута «id» для всех элементов ( HTMLElement ).
- …и многие другие…
Большинство стандартных HTML-атрибутов имеют соответствующее DOM-свойство, и мы можем получить к нему доступ.
Если же нам нужно быстро что-либо узнать или нас интересует специфика определённого браузера – мы всегда можем вывести элемент в консоль, используя console.dir(elem) , и прочитать все свойства. Или исследовать «свойства DOM» во вкладке Elements браузерных инструментов разработчика.
Итого
Каждый DOM-узел принадлежит определённому классу. Классы формируют иерархию. Весь набор свойств и методов является результатом наследования.
Главные свойства DOM-узла:
nodeType Свойство nodeType позволяет узнать тип DOM-узла. Его значение – числовое: 1 для элементов, 3 для текстовых узлов, и т.д. Только для чтения. nodeName/tagName Для элементов это свойство возвращает название тега (записывается в верхнем регистре, за исключением XML-режима). Для узлов-неэлементов nodeName описывает, что это за узел. Только для чтения. innerHTML Внутреннее HTML-содержимое узла-элемента. Можно изменять. outerHTML Полный HTML узла-элемента. Запись в elem.outerHTML не меняет elem . Вместо этого она заменяет его во внешнем контексте. nodeValue/data Содержимое узла-неэлемента (текст, комментарий). Эти свойства практически одинаковые, обычно мы используем data . Можно изменять. textContent Текст внутри элемента: HTML за вычетом всех <тегов> . Запись в него помещает текст в элемент, при этом все специальные символы и теги интерпретируются как текст. Можно использовать для защиты от вставки произвольного HTML кода. hidden Когда значение установлено в true , делает то же самое, что и CSS display:none .
В зависимости от своего класса DOM-узлы имеют и другие свойства. Например у элементов <input> ( HTMLInputElement ) есть свойства value , type , у элементов <a> ( HTMLAnchorElement ) есть href и т.д. Большинство стандартных HTML-атрибутов имеют соответствующие свойства DOM.
Впрочем, HTML-атрибуты и свойства DOM не всегда одинаковы, мы увидим это в следующей главе.
Как-то потребовалось создать функцию, принимающую объект json со следующим форматом записи: "браузер":то, что следует вернуть, иначе говоря такую функцию, которая бы возвращала указанный объект в зависимости от браузера пользователя.
ТЗ, которое я для себя определил:
- браузеры можно группировать, указывая их через пробел
- браузерам можно задавать версию (ie6,opera10)
- браузерам можно задавать полную версию (opera10.15)
- поддержка самых популярных браузеров
Мой способ гарантированно не самый точный, так как он используют свойство userAgent объекта navigator, которое при желании подделывается, но с другой стороны любой способ проверки клиента как серверный, так и клиентский можно обойти. Так же встает вопрос о надобности такой "подделки", тем более мало какие роботы исполняют javascript код.
В случае если ни одного выражение не совпадает с браузером пользователя, возвращается "none", которое можно также указать как свойство передаваемого объекта.
Пример использования: (данный код повернет на 25 градусов все содержимое страницы в любом современном браузере)
Название браузера нужно вводить в следующем формате : ie, firefox, opera, chrome, safari, konqueror, iceweasel, seamonkey. Регистр неважен. Версия пишется слитно с название, пример: ie7. Если для нескольких браузеров должно возвратиться одно и тоже значение, вы просто указываете их через пробел, как
на примере ("chrome safari":"WebkitTransform"). В качестве возвращаемого значения может выступать любой объект JavaScript (строка, число, функция, логическое значение и т.д.)Зачем проверять версию браузера и юзерагент, когда надо проверять то, что он умеет. Тем более, что ваш код даст огромную погрешность. Да и многие браузеры неправильно отдают свой агент.
Я перечислил какие браузеры поддерживаются, они не будут "неправильно" отдавать свой юзер-агент. И версия для каждого браузера определяется по индивидуальному правилу. Мне так же интересно, как вы будете проверять то, что умеет браузер, с большей пользой, когда любое свойство можно подменить, как и юзер-агент.
Это они на текущий момент не будут неправильно отдавать юзер-агент. Но никто не может поручиться за то, что будет завтра.
Конечно, проверять надо поддержку браузером конкретных свойств и методов. Путаница в юзер-агентах — правило, а неправильное определение стандартных свойств и методов — редкое исключение и косяк.юзерагент без затей меняется, например в фаерфоксе без всяких бубнов, в системных параметрах браузера. к сожалению предложенный вами способ ненадежен и необъективен
В Opera он тоже легко подменяется в параметре Custom User Agent в opera:config. Там же меняется и navigator.appName.
судя по скрипту, он ищет непонятно где, не ясно что. где сам источник версии браузера, откуда берутся аргументы?
Спасибо! Везде работает кроме IE. :D (ie 6-ка)
IE Стабилен, как всегдаСпасибо за понятный и прозрачный код.
Не понимаю зачем было разводить флейм на тему ненадежности метода. 90% пользователей вообще не знают про строку юзерагента, а те, кто знают, изменяя эту строку, сами себе становятся злобными буратинами.
Автору зачет, респект и уважуха.
Все течет, все меняется - в IE10 данная функция работать не будет, потому что она ищет в userAgent подстроку "MSIE", а десятый ослик userAgent отдает вот такой: "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; rv:11.0) like Gecko". Т.е. надо добавить поиск по названию IE-шного движка - Trident.
Спс большое за мануал!
вах вах вах. в IE10 зер гуд как работает у меня. Вот в IE11 не работает. Пришлось немного отсебятины сделать.
Author thank you very much!
Вот, переделал под современные реалии и улучшил юзабилити:
Результат выполнения функции:
Определение мобильных браузеров не поддерживается, но для них возвращается platform: "mobie".
Konqueror, Iceweasel, SeaMonkey выкинул за ненадобностью. Кому нужно их определять в 2016 году даже представить не могу.
Существует достаточно большое количество браузеров, а также их версий. И проблема в том, что одни браузеры позволяют выполнить определённый скрипт, а другие не позволяют. Встаёт вопрос: а как узнать браузер пользователя в JavaScript, чтобы через условие решить: надо выполнять скрипт или нет. И о том, как определить имя и версию браузера пользователя я и напишу в этой статье.
Для таких целей существует объект Navigator, а точнее два его свойства: appName и appVersion. Давайте для начала выведем название браузера пользователю:
document.write("Вы используете браузер " + navigator.appName);
В результате Вы увидите имя браузера пользователя. Также огромное значение оказывает не только сам браузер, но и его версия. И для таких случаев используется свойство appVersion:
document.write("Версия Вашего браузера " + navigator.appVersion);
Свойства appName и appVersion доступны только для чтения (это и логично), поэтому изменить их у Вас не получится. Теперь встаёт вопрос, а как использовать их в операторе IF:
var browser = navigator.appName;
if (browser == "NetScape")
document.write("Тут можно выполнять скрипты для обладателей браузеров NetScape");Надеюсь, что я ответил на Ваш вопрос: "Как узнать имя и версию браузера в JavaScript".
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновленияЕсли у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
Комментарии ( 10 ):
И для FFox напишет Netscape
Проблем при определении браузера много, чтобы узнать, что это chrome, нужно анализировать navigator.appVersion. Для других браузеров могут быть другие свойства (appName или appCodeName).
Ну и как это сделать?
Выведите сначала, посмотрите на значение, а дальше используйте функции для работы со строками.
Ну я уже понял как.
Как бы это странно не казалось, но ещё существуют пользователи, которые отключают JavaScript. И большинство Web-мастеров просто "забивают" на них, однако, иногда хочется дать совет, чтобы пользователь включил JavaScript. И вот как сделать проверку: "Включён ли JavaScript", и если нет, то вывести строку с просьбой включить, я расскажу в этой статье.
Код, приведённый ниже, необходимо разместить внутри тега body:
<script type="text/javascript">
document.write("У Вас включён JavaScript!");
</script>
<noscript><span>У Вас отключён JavaScript. </span></noscript>Немного поясню этот код. Если у пользователя JavaScript включён, то метод write() сработает и выведет строку. Если же JavaScript отключён, то весь тег script будет проигнорирован. Однако, дальше идёт тег noscript. Данный тег содержит элементы, которые будут показаны браузером, если JavaScript отключён. То есть содержимое тега noscript показывается, когда отключён JavaScript, а когда включён, то пользователь noscript не видит.
Именно таким нехитрым образом, Web-мастера часто пишут: "Включите, пожалуйста, JavaScript", либо выводят какие-то красивые картинки с аналогичной просьбой, либо ещё что-нибудь, ведь внутри тега noscript можно помещать любые HTML-теги. И теперь Вы можете применить полученные знания и на своём сайте, ведь не секрет, что сейчас не так просто найти сайт, который бы вообще не использовал JavaScript.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновленияЕсли у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
Комментарии ( 9 ):
Большое спасибо за эту статью!
Михаил спасибо! Новичкам типа меня приятно понимать, что есть люди, которые заботятся о них :)
Михаил, А вы используете библиотеку JQuery для JavaScript" Не могли бы вы сделать уроки по ней в будущем?
Возможно, в дальнейшем такой урок появится.
Привет Если пишу скрипты в голове, то все браузеры работают нормально. Стоит только переместить скрипты в файл "js", ОПЕРА перестает восмпринимать скрипты, а хром продолжает работать коректно. Что это?
Читайте также:
-
– класс для тега <input> , – класс для тега <body> , – класс для тега <a> ,
Таким образом, полный набор свойств и методов данного узла собирается в результате наследования.
Рассмотрим DOM-объект для тега <input> . Он принадлежит классу HTMLInputElement.
Он получает свойства и методы из (в порядке наследования):
Для того, чтобы узнать имя класса DOM-узла, вспомним, что обычно у объекта есть свойство constructor . Оно ссылается на конструктор класса, и в свойстве constructor.name содержится его имя:
…Или мы можем просто привести его к строке :
Проверить наследование можно также при помощи instanceof :
Как видно, DOM-узлы – это обычные JavaScript объекты. Для наследования они используют классы, основанные на прототипах.
В этом легко убедиться, если вывести в консоли браузера любой элемент через console.dir(elem) . Или даже напрямую обратиться к методам, которые хранятся в HTMLElement.prototype , Element.prototype и т.д.
Большинство браузеров поддерживают в инструментах разработчика две команды: console.log и console.dir . Они выводят свои аргументы в консоль. Для JavaScript-объектов эти команды обычно выводят одно и то же.
Но для DOM-элементов они работают по-разному:
Попробуйте сами на document.body .
В спецификации для описания классов DOM используется не JavaScript, а специальный язык Interface description language (IDL), с которым достаточно легко разобраться.
В IDL все свойства представлены с указанием их типов. Например, DOMString , boolean и т.д.
Небольшой отрывок IDL с комментариями:
Свойство «nodeType»
Свойство nodeType предоставляет ещё один, «старомодный» способ узнать «тип» DOM-узла.
Его значением является цифра:
В современных скриптах, чтобы узнать тип узла, мы можем использовать метод instanceof и другие способы проверить класс, но иногда nodeType проще использовать. Мы не можем изменить значение nodeType , только прочитать его.
Тег: nodeName и tagName
Получив DOM-узел, мы можем узнать имя его тега из свойств nodeName и tagName :
Есть ли какая-то разница между tagName и nodeName ?
Да, она отражена в названиях свойств, но не очевидна.