"스타일 변경"이벤트를들을 수 있습니까?


206

jQuery에서 스타일 변경에 바인딩 할 수있는 이벤트 리스너를 만들 수 있습니까? 예를 들어, 요소가 치수를 변경하거나 스타일 속성의 다른 변경이있을 때 무언가를 "수행"하려면 다음과 같이하십시오.

$('div').bind('style', function() {
    console.log($(this).css('height'));
});

$('div').height(100); // yields '100'

정말 유용 할 것입니다.

어떤 아이디어?

최신 정보

이 답변에 대해 유감스럽게 생각하지만 다른 사람에게 적합한 깔끔한 솔루션을 작성했습니다.

(function() {
    var ev = new $.Event('style'),
        orig = $.fn.css;
    $.fn.css = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

이것은 내부 prototype.css 메소드를 일시적으로 무시하고 마지막에 트리거로 재정의합니다. 따라서 다음과 같이 작동합니다.

$('p').bind('style', function(e) {
    console.log( $(this).attr('style') );
});

$('p').width(100);
$('p').css('color','red');

예, 좋은 솔루션이지만 실제 응용 프로그램에서는 많은 리소스가 필요할 수 있으며 브라우저가 사용자의 상호 작용을 따라 잡는 데 느리게 보일 수도 있습니다. 그것이 사실인지 아닌지 알고 싶습니다.
pixeline

1
@ pixeline : 너무 느려 야한다는 것을 알 수 없습니다. jQuery는 여전히 CSS 프로토 타입을 호출합니다. 방금 트리거를 추가하고 있습니다. 따라서 기본적으로 하나의 추가 메소드 호출입니다.
David Hellsing

이해합니다 : 응용 프로그램과 상호 작용하는 사용자 흐름에서 css ()는 많은 시간이라고합니다. 해당 트리거로 수행하는 작업에 따라 (단지 콘솔 로그 인 경우 당연히 안전하다고 생각합니다) 문제가 발생할 수 있습니다. 궁금해 응용 프로그램에 따라 다릅니다. 나는 개인적으로 내 물건에 많은 시각적 피드백을하는 경향이 있습니다.
pixeline

기존 jquery CSS 호출에서 작동하도록하기 위해 몇 가지 더 할 일이 있습니다 .1) 새로운 CSS 함수에서 요소를 반환하거나 그렇지 않으면 유창한 스타일의 CSS 호출을 중단합니다. 예. $ ( 'p'). css ( '디스플레이', '블록') .css ( '컬러', '블랙'); 2) 속성 값을 호출하는 경우 (예 : 'obj.css ('height ');') 원래 함수의 반환 값을 반환하려고합니다-인수 목록이 있는지 확인 하여이 작업을 수행합니다 함수에는 하나의 인수 만 포함됩니다.
theringostarrs 2016 년

1
스타일 속성 자체 가 제거 될 때도 작동하는이 접근법의보다 강력한 버전을 만들었습니다 . 이 방법으로 제거되는 각 스타일에 대해 '스타일'이벤트가 발생합니다. gist.github.com/bbottema/426810c21ae6174148d4
Benny Bottema

답변:


19

jQuery는 오픈 소스이기 때문에 css호출 될 때마다 (jQuery 객체를 전달할 때마다) 원하는 함수를 호출 하도록 함수를 조정할 수 있다고 생각합니다 . 물론 CSS 속성을 설정하기 위해 내부적으로 사용하는 다른 것이 없도록 jQuery 코드를 검색해야합니다. 이상적으로는 jQuery 라이브러리 자체를 방해하지 않도록 jQuery 용 별도의 플러그인을 작성하려고하지만 프로젝트에 적합한 지 여부를 결정해야합니다.


1
그러나이 경우 DOM 함수를 사용하여 style 속성을 똑바로 설정하면 어떻게됩니까?
Jaime Hablutzel

이 솔루션의 전체 예는 다음과 같습니다. gist.github.com/bbottema/426810c21ae6174148d4
Benny Bottema

272

질문이 제기 된 후 상황이 조금 바뀌 었습니다. 이제 MutationObserver 를 사용하여 jQuery가 필요없는 요소의 'style'속성의 변경 사항을 감지 할 수 있습니다 .

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        console.log('style changed!');
    });    
});

var target = document.getElementById('myId');
observer.observe(target, { attributes : true, attributeFilter : ['style'] });

콜백 함수에 전달되는 인수 는 이전 스타일과 새 스타일 값을 유지할 수 있는 MutationRecord 객체입니다.

IE 11 이상을 포함한 최신 브라우저에서 지원이 좋습니다 .


19
클래스 변경이나 @media변경 의 결과로 스타일이 변경 될 때가 아니라 인라인 스타일에서만 작동합니다 .
fregante

2
@ bfred.it 그것을 달성하는 방법에 대한 아이디어가 있습니까? 클래스의 CSS 규칙이 요소에 적용된 후 일부 js를 실행하고 싶습니다.
Kragalon

getComputedStyle함께 사용할 수는 setInterval있지만 웹 사이트 속도가 느려질 수 있습니다 .
fregante

참고 : MutationObserver는 caniuse의 말에도 불구하고 실제로 모든 버전의 Android 4.4에서 작동하지 않습니다.
제임스 굴드

텍스트 영역의 너비가 300px 이상으로 늘어날 때 텍스트 영역의 배경색을 파란색으로 변경하는 예는이 트위들을 참조하십시오. jsfiddle.net/RyanNerd/y2q8wuf0은 (불행히도에서 스크립트를 중단 FF에서 버그가 수 있도록이 나타납니다HTMLElement.style.prop = "value"
RyanNerd

18

이벤트 객체의 선언은 새로운 CSS 함수 안에 있어야합니다. 그렇지 않으면 이벤트는 한 번만 발생 될 수 있습니다.

(function() {
    orig = $.fn.css;
    $.fn.css = function() {
        var ev = new $.Event('style');
        orig.apply(this, arguments);
        $(this).trigger(ev);
    }
})();

감사합니다 어떤 사람들은 원래 소스를 변경한다고 말하지만 확장 프로그램이 가장 좋습니다. 나는 약간의 문제가 있었지만 마침내 작동합니다.
ccsakuweb

이 코드를 실행 한 후에도 계속 실행되며 요구 결과를 얻지 못합니다.
smkrn110

13

코드가 아니기 때문에 이벤트를 시작할 수없는 경우 Mike의 경우 가장 좋은 대답이라고 생각합니다. 그러나 그것을 사용할 때 약간의 오류가 발생합니다. 그래서 내가 사용하는 코드를 보여주기 위해 새로운 답변을 작성합니다.

신장

// Extends functionality of ".css()"
// This could be renamed if you'd like (i.e. "$.fn.cssWithListener = func ...")
(function() {
    orig = $.fn.css;
    $.fn.css = function() {
        var result = orig.apply(this, arguments);
        $(this).trigger('stylechanged');
        return result;
    }
})();

용법

// Add listener
$('element').on('stylechanged', function () {
    console.log('css changed');
});

// Perform change
$('element').css('background', 'red');

var ev = new $ .Event ( 'style'); 때문에 오류가 발생했습니다. 스타일과 같은 것이 HtmlDiv에서 정의되지 않았습니다.이 스타일을 제거하고 이제 $ (this) .trigger ( "stylechanged")를 시작합니다. 또 다른 문제는 Mike가 $ (css, ..)의 결과를 반환하지 않았다는 것인데, 경우에 따라 문제를 일으킬 수 있습니다. 그래서 결과를 얻고 반환합니다. 이제 작동합니다 ^^ 모든 CSS 변경에는 이벤트를 수정하고 트리거 할 수없는 일부 라이브러리가 포함됩니다.


매우 유용하고 영리한
dgo

5

다른 사람들이 제안했듯이 요소의 스타일을 변경하는 코드를 제어 할 수 있다면 요소의 높이를 변경할 때 사용자 정의 이벤트를 발생시킬 수 있습니다.

$('#blah').bind('height-changed',function(){...});
...
$('#blah').css({height:'100px'});
$('#blah').trigger('height-changed');

그렇지 않으면 리소스를 많이 사용하지만 요소 높이의 변경 사항을 주기적으로 확인하도록 타이머를 설정할 수 있습니다 ...


스타일을 변경하는 코드에 액세스 할 수있는 경우 실제로 매우 깔끔한 솔루션입니다.
Umair Hafeez

2

jQuery 또는 Java 스크립트에서 스타일 변경 이벤트를 기본적으로 지원하지 않습니다. 그러나 jQuery는 커스텀 이벤트 생성 및 청취 지원을 지원하지만 변경이있을 때마다 직접 트리거 할 수있는 방법이 있어야합니다. 따라서 완벽한 솔루션이 아닙니다.


2

Jquery 플러그인을 시도 할 수 있으며 CSS가 변경되고 사용하기 쉬운 이벤트를 트리거합니다.

http://meetselva.github.io/#gist-section-attrchangeExtension
 $([selector]).attrchange({
  trackValues: true, 
  callback: function (e) {
    //console.log( '<p>Attribute <b>' + e.attributeName +'</b> changed from <b>' + e.oldValue +'</b> to <b>' + e.newValue +'</b></p>');
    //event.attributeName - Attribute Name
    //event.oldValue - Prev Value
    //event.newValue - New Value
  }
});

1

흥미로운 질문입니다. 문제는 height ()가 콜백을 수락하지 않으므로 콜백을 실행할 수 없다는 것입니다. animate () 또는 css ()를 사용하여 높이를 설정 한 다음 콜백에서 사용자 정의 이벤트를 트리거하십시오. 다음은 개념 증명으로 animate (), 테스트 및 작동 ( demo )을 사용하는 예제 입니다.

$('#test').bind('style', function() {
    alert($(this).css('height'));
});

$('#test').animate({height: 100},function(){
$(this).trigger('style');
}); 

8
미안하지만 이것이 무엇을 증명 했습니까? 당신 trigger()은 수동으로 이벤트입니다. 스타일 속성이 수정되면 OP가 자동 트리거 이벤트 이후에 있다고 생각합니다.
JPot

@JPot 그는 높이 속성이 변경 될 때 이벤트를 발생시키지 않음을 보여줍니다.
AnthonyJClink

1

위의 @David 솔루션을 추가하고 공식화하면됩니다.

jQuery 함수는 체인 가능하고 'this'를 반환하므로 여러 호출을 차례로 호출 할 수 있습니다 (예 :) $container.css("overflow", "hidden").css("outline", 0);.

따라서 개선 된 코드는 다음과 같아야합니다.

(function() {
    var ev = new $.Event('style'),
        orig = $.fn.css;
    $.fn.css = function() {
        var ret = orig.apply(this, arguments);
        $(this).trigger(ev);
        return ret; // must include this
    }
})();

0

jQuery cssHooks는 어떻습니까?

어쩌면 나는 질문을 이해하지 못하지만 검색중인 것은 기능 cssHooks을 변경하지 않고 쉽게 수행 할 수 있습니다 css().

문서에서 복사 :

(function( $ ) {

// First, check to see if cssHooks are supported
if ( !$.cssHooks ) {
  // If not, output an error message
  throw( new Error( "jQuery 1.4.3 or above is required for this plugin to work" ) );
}

// Wrap in a document ready call, because jQuery writes
// cssHooks at this time and will blow away your functions
// if they exist.
$(function () {
  $.cssHooks[ "someCSSProp" ] = {
    get: function( elem, computed, extra ) {
      // Handle getting the CSS property
    },
    set: function( elem, value ) {
      // Handle setting the CSS value
    }
  };
});

})( jQuery ); 

https://api.jquery.com/jQuery.cssHooks/


-1

나는 같은 문제가 있었으므로 이것을 썼다. 오히려 잘 작동합니다. CSS 전환과 혼합하면 멋지게 보입니다.

function toggle_visibility(id) {
   var e = document.getElementById("mjwelcome");
   if(e.style.height == '')
      e.style.height = '0px';
   else
      e.style.height = '';
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.