Расширьте функцию jquery.css, чтобы переопределить важные стили

Я пишу редактор шаблонов почты, пользователи могут импортировать свои существующие шаблоны и перепроектировать шаблон с помощью нашего визуального редактора. Если элемент, измененный пользователем, имеет свойство стиля ! Important; мы должны переопределить свойство с помощью jquery.css.

Пример:

 <div id="sendwrapper">
      <button> Send </button>
 </div>

Стиль

#sendwrapper * {
   color:white !important;
}

Я хочу изменить цвет белый на зеленый. Я пробовал этот плагин https://github.com/premasagar/important/blob/master/important.js. Этот плагин не настолько умен, что он устанавливает ! Important для всех свойств, но я ожидаю, что он должен установить ! Important только для свойств, которые устанавливают ! Important.

Ответ 1

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

if ( // Check browser support
  window.Proxy
  && window.CSSStyleDeclaration
  && CSSStyleDeclaration.prototype.setProperty
) {
  jQuery.cssHooks = new Proxy(jQuery.cssHooks, {
    get: function(hooks, name) {
      return new Proxy(hooks[name] || (hooks[name] = {}), {
        has: function (hook, setget) {
          return setget === 'set' || setget in hook;
        },
        get: function (hook, setget){
          if(setget !== 'set') return hook[setget];
          return function(elem, value, extra) {

            // Use the cssHook setter, if any
            if(hook.set) {
              value = hook.set(elem, value, extra);
              if(value === void 0) return; // No value
            }

            // Set the desired value without !important
            elem.style[ name ] = value;

            // Get the computed value
            var computedValue = jQuery.css(elem, name);

            // Check if the computed value is the desired one
            if(computedValue === value) return; // OK

            // Set the desired value with !important
            elem.style.setProperty(name, value, "important");

            // Check if the computed value has changed
            if(computedValue !== jQuery.css(elem, name)) return; // OK

            // Otherwise !important is not needed, so remove it
            elem.style.setProperty(name, value);
          }
        }
      });
    }
  });
}

// Plugin compiled with Closure Compiler
window.Proxy&&window.CSSStyleDeclaration&&CSSStyleDeclaration.prototype.setProperty&&(jQuery.cssHooks=new Proxy(jQuery.cssHooks,{get:function(f,b){return new Proxy(f[b]||(f[b]={}),{has:function(b,a){return"set"===a||a in b},get:function(e,a){return"set"!==a?e[a]:function(d,c,a){if(e.set&&(c=e.set(d,c,a),void 0===c))return;d.style[b]=c;a=jQuery.css(d,b);a!==c&&(d.style.setProperty(b,c,"important"),a===jQuery.css(d,b)&&d.style.setProperty(b,c))}}})}}));

// The elements in the collection that need !important will use it
$('.color').css('color', 'blue');

// The plugin is compatible with custom cssHooks
$.cssHooks.opacity.set = function(elem, value) { return value/4 + '' };
$('.opacity').css('opacity', .8);
.color {
   color: red;
}
.color.important {
   color: red !important;
}
.opacity.important {
   opacity: 1 !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="color">color: blue</div>
<div class="color important">color: blue !important</div>
<div class="opacity important">opacity: .2 !important</div>

Ответ 2

Не нужно использовать слишком много компилируемого кода. jquery предоставляет вам возможность перезаписывать правило CSS.

Просто используйте это

 $('#sendwrapper').children().css("cssText", "color: green !important;");

Я использую children(), потому что, как я вижу, вы применили свой css следующим образом: #sendwrapper * Итак, чтобы рассмотреть *, я использую children().

И cssText просто перезапишите текущий CSS

А также тот тип модуля, который вы создаете, это наилучший подход.

DEMO: http://jsfiddle.net/6L0p5gk9/

Поэтому нет необходимости расширять функцию jQuery CSS. Функциональность, которую вы ищете, уже существует

Ответ 3

В определении jQuery.style (поиск style: в исходном коде) найдите строку

style[ name ] = value;

После этого добавьте этот код:

// Get the computed value after setting the desired value without !important
var computedValue = jQuery.css(elem, name);

// Check if browser supports adding inline important styles
if(typeof style.setProperty == 'function') {

    // Set the desired value with !important
    style.setProperty(name, value, "important");

    // Check if the computed value is still the same
    if(computedValue === jQuery.css(elem, name)) {

        // Then !important is not needed, so remove it
        style.setProperty(name, value);
    }
}

Ответ 4

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

Короче говоря, он устанавливает важное объявление только в случае необходимости:

$.fn.extend({
    cssi:function(obj){
        var $target=this;
        $.each(obj,function(i,e){
            var initialVal=$target.css(i);
            $target.css(i,e);
            if($target.css(i)===initialVal && initialVal!==e){ //add !important only if the value didn't change and you're not trying to set it to the value it already had
                if(!isNaN(e)) e+="px";
                e+=" !important";
                $target.css(i,""); // clear any prior rules
                $target[0].style.cssText+=camelToDash(i)+":"+e;
            }         
        });
        return this;
    }
});

function camelToDash(str) {
    return str.replace(/\W+/g, '-')
    .replace(/([a-z\d])([A-Z])/g, '$1-$2')
    .toLowerCase();
}




//Demo
$(function(){
    $("div").cssi({
        backgroundColor:"blue",
        height:100,
        width:100,
        color:"red"
    });
});
div{ /*Just something to test it with*/
    height: 50px !important;
    width:50px;
    background-color:red !important;
    color:green !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Hello world!</div>

Ответ 5

//Очистить! important css

$('#elementToChange').css('background-color', '');

$('#elementToChange').css('background-color', 'blue');

Или в одном слое:

$('#elementToChange')
    .css('background-color', '')
    .css('background-color', 'blue');

Или вы можете добавить к нему класс по предопределенному классу в вашем css.