Как вы определяете тип медиа в Javascript? - PullRequest
15 голосов
/ 30 января 2009

Я оглянулся и еще не видел, чтобы этот вопрос задавался.

Какой надежный способ в Javascript для определения типа носителя (например, экран, печать, карманное устройство) страницы? Я видел ссылки на document.styleSheets[0].media, но мне не повезло, используя либо из-за проблем с поддержкой браузера, либо из-за того, что я чего-то не понимаю.

Я спрашиваю, потому что я хочу, чтобы что-то было скрыто Javascript в представлении экрана, но не в представлении печати. Нельзя полагаться на медиа-зависимые стили, чтобы сделать это, потому что я использую Prototype для запуска переключателя элемента, а Prototype не позволяет переключать элемент в видимый, если он был объявлен невидимым (display: none ) с не встроенным CSS *. Я попытался просто установить специфичные для носителя встроенные стили для элемента (<div style="@media print { foo: bar; } @media screen { blargh: bfargle; }">), но, насколько я могу судить, это не поддерживается.

Я знаю, что могу циклически просматривать таблицы стилей и проверять, активна ли связанная таблица стилей для печати или нет, но в настоящее время я нахожусь в ситуации, когда различные объявления стилей для всех носителей смешаны в одном связана таблица стилей, так что это не хорошо. И да, я могу просто разделить таблицы стилей на разные типы носителей, но сначала я хотел бы выяснить, могу ли я просто надежно извлекать тип носителя из DOM с помощью Javascript, полностью независимо от CSS . О, и я попробовал этот трюк «скрыть элемент для представления печати, а затем проверить, виден ли он с помощью Javascript», но это всегда приводило к (когда я загружаю предварительный просмотр печати) Javascript, определяющему, что предполагаемый к be-скрытые элементы видны и выполняют любую манипуляцию DOM, о которой я говорю, несмотря на тот факт, что эти элементы не видимы. Если кому-то захочется больше подробностей о том, о чем я здесь говорю, я могу уточнить в редакции.

* Это то, что я не поняла и постоянно раздражаюсь. Любой, кто может хоть как-то это понять, получает от меня большое одобрение.

Ответы [ 5 ]

4 голосов
/ 31 января 2009

[..], Prototype не позволит переключать элемент в видимый, если он был объявлен невидимым (display: none) с не встроенным CSS. Это то, что я не поняла и постоянно раздражаюсь. Любой, кто может хоть как-то это понять, получает от меня большое одобрение.

Вы, наверное, уже видели это, но документация, например, show (есть другие связанные функции с той же заметкой), что:

Element.show не может отображать элементы, скрытые с помощью таблиц стилей CSS. Обратите внимание, что это не ограничение Прототипа, а следствие того, как работает свойство CSS display.

Итак, это известная проблема, и они обвиняют CSS. Однако рассмотрим следующий документ (я раньше не использовал Prototype, поэтому я не уверен, является ли это рекомендуемым способом ожидания загрузки DOM, но, похоже, он работает):

<!doctype html>
<script src="prototype.js"></script>
<script>
document.observe("dom:loaded", function() {
  $("victim").show();
});
</script>
<style>
p#victim {display:none;}
</style>
<p id="victim">Hello world!

Как вы уже знаете, это не будет работать. Зачем? Ну, а как бы Prototype узнал, на что «сбрасывать» свойство display, когда вы указываете p#victim на show? (Другими словами: как он может узнать, каким должно было быть значение display, если display: none не присутствовало в наборе правил с селектором p#victim.) Ответ прост: это невозможно. (Подумайте об этом на секунду. Что если другой набор правил изменит значение display, если display: none не присутствует в нашем наборе правил с селектором p#victim? (Т.е. мы не можем предположить, что, например, p всегда должен быть установлен на block, другие наборы правил могли изменить это значение.) Мы не можем удалить свойство display из набора правил в таблице стилей и не можем удалить всю связь между элементом и набор правил, потому что он может содержать другие свойства и т. д. (даже если бы это было возможно, imho, было бы неочевидно найти , с которым набор правил можно сделать). Конечно, мы могли бы продолжить и с этим, но afaik нет никакого известного решения этой проблемы.)

Тогда почему встроенная альтернатива работает? Сначала давайте посмотрим, как реализовано show:

show: function(element) {
  element = $(element);
  element.style.display = ''; // <-- the important line
  return element;
}

Единственное важное, что делает эта функция, - это установить element.style.display в пустую строку (''), которая «удаляет» display из style. Большой! Но что это значит? Почему мы хотим удалить это ?! Сначала мы должны выяснить, что на самом деле element.style представляет и изменяет, когда мы изменяем его значения.

Документация MDC для element.style гласит:

Возвращает объект, который представляет атрибут style элемента.

Обратите внимание на последнее слово: атрибут . element.style ≠ текущий «вычисляемый» стиль для элемента, это просто список свойств в атрибуте style (подробное объяснение см. В MDC).

Рассмотрим следующий документ:

<!doctype html>
<script src="prototype.js"></script>
<script>
document.observe("dom:loaded", function() {
  $("victim").show();
});
</script>
<p id="victim" style="display:none;">Hello world!

style="display:none;" скрывает p#victim, но когда DOM завершит загрузку Prototype, изменит его на style="", и браузер пересчитает значение для свойства display (значение из таблицы стилей браузера по умолчанию в этом случае ).

Но , рассмотрите следующий документ:

<!doctype html>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
  $("#victim").show();
});
</script>
<style>
p#victim {display:none;}
</style>
<p id="victim">Hello world!

jQuery корректно обрабатывает таблицы стилей, в любом случае, в этом случае! Это не так просто объяснить, как решение Prototype, и есть много уровней удивительности, которые я могу прочитать прямо сейчас, и во многих случаях jQuery не может вычислить правильное значение для display. (Быстрое последнее замечание: Firebug ..., но я предполагаю, что он использует некоторые эксклюзивные материалы Firefox или что-то в этом роде.)

1 голос
/ 30 января 2009

РЕДАКТИРОВАТЬ: Извините (Примечание для себя: RTFQ Роб, блин!). Быстрый поиск в Google это вверх и jquery плагин , если это нужно. В основном он использует правила @media, но не встроенный, насколько я могу судить, поэтому поддержка вашего браузера может отличаться, но это лучшее, на что вы можете надеяться, я думаю: (

1 голос
/ 30 января 2009

Посмотрите, работает ли это ... Я думаю, что вы можете сделать это для каждого типа и просто проверить, возвращает ли оператор нуль или эквивалент, затем примените ваши правила.

С этого сайта: http://www.webdeveloper.com/forum/showthread.php?t=82453

IE:

if (document.styleSheets[0].media == 'screen'){...}

FF / NS:

document.getElementsByTagName ('LINK')[0].getAttribute ('media')

или

document.styleSheets[0].media.mediaText

и скрипт для проверки его во всех браузерах (кроме некоторых новых, поэтому будьте осторожны:))

http://student.agh.edu.pl/~marcinw/cssmedia/

этот скрипт работает в операторе if как логическое значение true / false! Надеюсь, вы заставите его работать!

0 голосов
/ 01 апреля 2009

Я протестировал мой скрипт, упомянутый выше - теперь он работает со всеми новыми браузерами, в т.ч. IE8 финал.

Сценарий перенесен сюда: http://cssmedia.pemor.pl/ Не стесняйтесь использовать его, если хотите.

С уважением Марчин Вязовский

0 голосов
/ 30 января 2009
document.getElementsByTagName('link').each(function( link )
{
  //do something with link.media
  //hide whatever you need to hide, etc
});
...