Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.11.2012, 16:09
Аватар для Amphiluke
   ☽
Отправить личное сообщение для Amphiluke Посмотреть профиль Найти все сообщения от Amphiluke
 
Регистрация: 07.01.2011
Сообщений: 254

Динамическое применение стилей к элементу и их отмена
Всем привет. Вопрос по динамическому применению стилей к элементам.

Смоделируем такую ситуацию: некому модулю на языке JavaScript требуется на некоторое время применить ряд стилей к элементу в DOM, а затем отменить действие этих стилей, как будто бы модуль и не касался никогда этого элемента.

Всё просто, если значения CSS-свойств известны «at design time» (т.е. статичны): в таблице стилей создается CSS-класс с перечнем нужных CSS-свойств со статичными значениями, и модуль решает задачу добавлением/удалением имени класса в атрибуте className.
.MyModuleStyle {
    width:150px;
}

elem.classList.add("MyModuleStyle");
// ...
elem.classList.remove("MyModuleStyle");


А что если желаемые значения CSS-свойств становятся известны только во время выполнения? С одной стороны, можно было бы перед применением стиля запомнить прежнее значение свойства, а потом восстановить его.
var desiredWidth = 150, // условно. В действительности значение становится известно in runtime
    oldWidth = window.getComputedStyle(elem, null).width;
elem.style.width = desiredWidth + "px";
// ...
elem.style.width = oldWidth;

Это решение, казалось бы, работает, но оно совершенно неприемлемо для модуля, т.к. возможные последующие попытки пользователя динамически поменять ширину элемента путем назначения какого-нибудь своего CSS-класса при этом будут обречены на провал (стили класса не перекроют инлайновые, которые мы добавили в последней строке примера). Сделать elem.removeAttribute("style") — для модуля тоже не вариант, естественно.

Мне видится только один возможный вариант решения: манипуляции с таблицами стилей напрямую через JavaScript. Из скрипта создаем (CSSStyleSheet.insertRule) CSS-правило для класса, заполняем значения свойств динамически вычисленными значениями и далее оперируем атрибутом className. Но выглядит это решение, на мой взгляд, как «костыль».

Может, кто-нибудь встречался с подобными проблемами? Как выходили из положения?
Ответить с цитированием
  #2 (permalink)  
Старый 26.11.2012, 16:34
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Почему же костыль. Это именно решение проблемы. А как еще можно применить стили, да так, чтоб они были перекрываемы другими стилями? Через атрибут style конечно же будут назначены наиболее приоритетные свойства (я не принимаю во внимание !important). Значит нужно назначать свойства через stylesheet.
Ответить с цитированием
  #3 (permalink)  
Старый 26.11.2012, 17:30
Аватар для Amphiluke
   ☽
Отправить личное сообщение для Amphiluke Посмотреть профиль Найти все сообщения от Amphiluke
 
Регистрация: 07.01.2011
Сообщений: 254

Возможно, с «костылем» погорячился, просто порой используя все возможности DOM и интерфейса CSSStyleSheet, можно довести степень ненавязчивости JavaScript до абсурда, когда, утрируя, скрипт будет создавать под себя всю HTML-разметку, весь CSS (да и свой собственный код заодно).

Впрочем, наверное, вы правы. Если проблема явно ложится в рамки возможностей и предназначения интерфейса CSSStyleSheet, то решение, по-видимому, приемлемо. Жаль, что оно единственно… наверное.
Ответить с цитированием
  #4 (permalink)  
Старый 26.11.2012, 17:36
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Amphiluke
А что если желаемые значения CSS-свойств становятся известны только во время выполнения? С одной стороны, можно было бы перед применением стиля запомнить прежнее значение свойства, а потом восстановить его.
было бы целесообразно генерировать новые правила для таблицы стилей, и потом их убрать, когда они уже не будут нужны.

небольшая выдержка, чтобы не искать самому :

var stylesheet = document.createElement("style");
    document.getElementsByTagName("script")[0].parentNode.appendChild(stylesheet);
    stylesheet = stylesheet.sheet || stylesheet.styleSheet;


    /**
     * Добавит правило с указанным селектором и указанным текстом правила.
     * @param selector
     * @param cssText
     * @return {CSSRule} Добавленное правило
     */
    function addRule (selector, cssText) {

        /** @type {CSSRuleList} */
        var rules = stylesheet.cssRules || stylesheet.rules;
        var index = rules.length;

        if (stylesheet.insertRule) {
            stylesheet.insertRule(selector + " " + "{" + cssText + "}", index);
        } else {
            stylesheet.addRule(selector, cssText, rules.length);
        }

        return rules[index];
    }


С удалением правил из таблицы стилей я разбирался в этой теме : Удаление элемента в "жидком" листе..
Ответить с цитированием
  #5 (permalink)  
Старый 26.11.2012, 18:46
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

var desiredWidth = 150, // условно. В действительности значение становится известно in runtime
elem.style.width = desiredWidth + "px"; // переопределяем
// ...
elem.style.width = ''; // отменяем переопределение
__________________
.ня
Ответить с цитированием
  #6 (permalink)  
Старый 26.11.2012, 19:02
Аватар для Amphiluke
   ☽
Отправить личное сообщение для Amphiluke Посмотреть профиль Найти все сообщения от Amphiluke
 
Регистрация: 07.01.2011
Сообщений: 254

tenshi, спасибо, но не подходит. Просто в силу того, что модуль должен сбрасывать только свои собственные стили (в любом окружении). Если пользователь сам пропишет (или CMS сгенерирует) инлайновые стили в теге, мы затрем их, если будем использовать ваш способ.
Ответить с цитированием
  #7 (permalink)  
Старый 26.11.2012, 21:12
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Amphiluke, еще вариант: написать все возможные(требуемые) варианты стилей и подключить их внешним файлом. Так все виджеты делают В итоге, пользователь загрузить его (файл стилей) один раз, а в дальнейшем будет поднимать из кеша.
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #8 (permalink)  
Старый 26.11.2012, 21:36
Аватар для Amphiluke
   ☽
Отправить личное сообщение для Amphiluke Посмотреть профиль Найти все сообщения от Amphiluke
 
Регистрация: 07.01.2011
Сообщений: 254

nerv_, а как быть, если множество вариантов составляет множество мощности континуум? Ну вот как в примере с шириной. Она рассчитывается динамически и зависит, к примеру, от того, каков дизайн и метрика целевой страницы.

P.S. Пример это не надуманный, в реальном проекте проблема стоит как раз примерно так.

P.P.S. В общем, на данный момент реализовал это дело так, как в примере у melky. Видимо, так оно пока и останется до следующей глобальной архитектурной перестройки модуля. Спасибо всем за идеи.

Последний раз редактировалось Amphiluke, 26.11.2012 в 22:14. Причина: post-postscript added
Ответить с цитированием
  #9 (permalink)  
Старый 26.11.2012, 22:25
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

Сообщение от Amphiluke Посмотреть сообщение
tenshi, спасибо, но не подходит. Просто в силу того, что модуль должен сбрасывать только свои собственные стили (в любом окружении). Если пользователь сам пропишет (или CMS сгенерирует) инлайновые стили в теге, мы затрем их, если будем использовать ваш способ.
и правильно сделаем, ибо нефиг)
__________________
.ня
Ответить с цитированием
  #10 (permalink)  
Старый 26.11.2012, 22:26
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

var desiredWidth = 150, // условно. В действительности значение становится известно in runtime
    oldWidth = elem.style.width;
elem.style.width = desiredWidth + "px";
// ...
elem.style.width = oldWidth;
__________________
.ня
Ответить с цитированием
Ответ


Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамическое добавление события keydown элементу body Arigato Events/DOM/Window 3 13.12.2011 22:38
обьект Date применение стилей kamushek Общие вопросы Javascript 5 10.09.2010 13:23
Добавление стилей к вновь созданному элементу alexeews Общие вопросы Javascript 4 29.09.2008 01:40