क्या "शैली परिवर्तन" घटना को सुनना संभव है?


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);
    }
})();

यह आंतरिक प्रोटोटाइप.ऐक्स विधि को अस्थायी रूप से ओवरराइड करेगा और अंत में ट्रिगर के साथ इसे फिर से परिभाषित करेगा। तो यह इस तरह काम करता है:

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

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

हाँ, अच्छा समाधान है, लेकिन एक वास्तविक अनुप्रयोग में, मुझे संदेह है कि इसमें बहुत सारे संसाधन हो सकते हैं, और यहां तक ​​कि ब्राउज़र को उपयोगकर्ता के इंटरैक्शन के साथ रखने के लिए धीमा भी लगता है। मुझे यह जानकर अच्छा लगेगा कि ऐसा है या नहीं।
23

1
@pixeline: मैं यह नहीं देख सकता कि यह इतना धीमा होना चाहिए। jQuery अभी भी वैसे भी css प्रोटोटाइप को कॉल करता है, मैं इसमें केवल एक ट्रिगर जोड़ रहा हूं। तो यह मूल रूप से सिर्फ एक अतिरिक्त विधि कॉल है।
डेविड हेलसिंग

मैं समझता हूं कि: ऐसा लगता है कि किसी अनुप्रयोग के साथ बातचीत करने वाले उपयोगकर्ता के प्रवाह में, css () को बहुत समय कहा जाता है। आप उस ट्रिगर के साथ क्या करते हैं, इसके आधार पर (यदि यह सिर्फ कंसोल लॉग है, तो मुझे लगता है कि आप निश्चित रूप से सुरक्षित हैं), इससे समस्याएँ पैदा हो सकती हैं। मैं ऐसे ही सोच रहा था। यह आवेदन पर भी निर्भर करता है। मैं व्यक्तिगत रूप से अपने सामान में बहुत अधिक दृश्य प्रतिक्रिया करता हूं।
पिक्सलाइन

वहाँ कुछ और बातें करने के लिए इसे करने के लिए मौजूदा jquery सीएसएस कॉल के साथ काम करना है: 1) आप अपने नए सीएसएस फ़ंक्शन से तत्व को वापस करना चाहते हैं अन्यथा यह धाराप्रवाह स्टाइल सीएसएस कॉल को तोड़ देगा। जैसे। $ ('पी')। सीएसएस ('डिस्प्ले', 'ब्लॉक')। सीएसएस ('रंग', 'ब्लैक'); 2)) अगर यह एक संपत्ति मूल्य के लिए एक कॉल है (जैसे। 'obj.css (' ऊंचाई ')?') आप मूल फ़ंक्शन का रिटर्न मान लौटना चाहेंगे - मैं यह जाँच कर रहा हूं कि क्या तर्क सूची है फ़ंक्शन के लिए केवल एक तर्क है।
तेरिंगोस्ट्रारस

1
मैंने इस दृष्टिकोण का एक और अधिक मजबूत संस्करण बनाया, जो तब भी काम करता है जब शैली की विशेषता खुद को हटा दी जाती है। यह प्रत्येक शैली के लिए एक 'शैली' घटना को फेंक देगा जिसे इस तरह से हटाया जा रहा है। gist.github.com/bbottema/426810c21ae6174148d4
बेनी बोटेमा

जवाबों:


19

चूँकि jQuery ओपन-सोर्स है, मुझे लगता है कि आप cssहर बार अपनी पसंद के एक फंक्शन को कॉल करने के लिए फ़ंक्शन को ट्विक कर सकते हैं, जो कि इनवॉइस (jQuery ऑब्जेक्ट को पास करना) है। बेशक, आप यह सुनिश्चित करने के लिए jQuery कोड को परिमार्जन करना चाहते हैं कि सीएसएस गुण सेट करने के लिए आंतरिक रूप से इसका उपयोग करने के अलावा और कुछ नहीं है। आदर्श रूप से, आप jQuery के लिए एक अलग प्लगइन लिखना चाहते हैं ताकि यह स्वयं jQuery पुस्तकालय में हस्तक्षेप न करे, लेकिन आपको यह तय करना होगा कि यह आपकी परियोजना के लिए संभव है या नहीं।


1
लेकिन इस मामले में क्या होगा यदि मैं DOM प्रॉपर्टीज़ के साथ स्टाइल प्रॉपर्टी को सीधे सेट करता हूँ ??
Jaime Hablutzel

इस समाधान का पूरा उदाहरण यहां दिया गया है: gist.github.com/bbottema/426810c21ae6174148d4
बेनी बोटेमा

272

प्रश्न पूछे जाने के बाद से चीजें थोड़ी बढ़ गई हैं - अब एक तत्व की 'शैली' विशेषता में बदलाव का पता लगाने के लिए एक MutationObserver का उपयोग करना संभव है , कोई jQuery की आवश्यकता नहीं है:

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 आपको इस बात का अंदाजा होगा कि इसे कैसे हासिल किया जाए? मैं एक वर्ग के सीएसएस नियमों को एक तत्व पर लागू करने के बाद कुछ js चलाना चाहता हूं।
क्रैग्लोन

आप के getComputedStyleसाथ उपयोग कर सकते हैं , setIntervalलेकिन यह आपकी वेबसाइट को बहुत धीमा कर देगा।
फ्रीगर्ल

नोट: MutationObserver वास्तव में एंड्रॉइड 4.4 के सभी संस्करणों में काम नहीं करता है, इसके बावजूद कि कैनीयूज़ क्या कहता है।
जेम्स गोल्ड

इस पाठ को एक textarea की पृष्ठभूमि का रंग बदलकर नीला करने के उदाहरण के लिए देखें जब textarea की चौड़ाई 300px तक खिंच जाती है। jsfiddle.net/RyanNerd/y2q8wuf0 (दुर्भाग्यवश FF में एक बग प्रतीत होता है जो स्क्रिप्ट को HTMLElement.style.prop = "value"
लटकाता है

18

आपके ईवेंट ऑब्जेक्ट की घोषणा आपके नए सीएसएस फ़ंक्शन के अंदर होनी चाहिए। अन्यथा घटना केवल एक बार निकाल दी जा सकती है।

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

बहुत बहुत धन्यवाद। कुछ लोग मूल स्रोत को बदलने के बारे में बताते हैं लेकिन आपका विस्तार सबसे अच्छा है। मुझे कुछ समस्याएं थीं लेकिन आखिरकार यह काम करता है।
ccsakuweb

इस कोड को अंजाम देने के बाद भी यह लगातार फायरिंग करता है और अपेक्षित परिणाम भी हासिल नहीं करता है।
smkrn110

13

मुझे लगता है कि यदि आपका कोड आपके कोड से नहीं है तो आप माइक से सबसे अच्छा जवाब दे सकते हैं। लेकिन मुझे कुछ त्रुटियां आती हैं जब मैंने इसका उपयोग किया। इसलिए मैं आपके द्वारा उपयोग किए जाने वाले कोड को दिखाने के लिए एक नया उत्तर लिखता हूं।

एक्सटेंशन

// 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 ('स्टाइल'); HtmlDiv में शैली की तरह कुछ भी परिभाषित नहीं किया गया था .. मैंने इसे हटा दिया है, और मैं अब $ (यह) .trigger ("स्टाइलकेंज") लॉन्च करता हूं। एक और समस्या यह थी कि माइक ने $ (css, ..) का परिणाम वापस नहीं किया, तो यह कुछ मामलों में समस्याएँ खड़ी कर सकता है। इसलिए मुझे इसका परिणाम मिलता है और मैं इसे वापस करता हूं। अब ^ ^ काम करता है। हर सीएसएस में बदलाव में कुछ ऐसे लिबास शामिल हैं जिन्हें मैं किसी घटना को संशोधित और ट्रिगर नहीं कर सकता।


बहुत उपयोगी और चतुर
dgo

5

जैसा कि दूसरों ने सुझाव दिया है, यदि आपके पास नियंत्रण है कि जो भी कोड उस तत्व की शैली को बदल रहा है, जब आप तत्व की ऊंचाई को बदलते हैं तो आप एक कस्टम घटना को आग लगा सकते हैं:

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

अन्यथा, हालांकि बहुत संसाधन-गहन, आप समय-समय पर तत्व की ऊंचाई में बदलाव के लिए एक टाइमर सेट कर सकते हैं ...


यह वास्तव में एक बहुत साफ समाधान है अगर किसी के पास कोड तक पहुंच है जो शैलियों को बदल रहा है।
उमैर हाफ़िज़

2

JQuery में या जावा स्क्रिप्ट में शैली परिवर्तन घटना के लिए कोई इनबिल्ट समर्थन नहीं है। लेकिन jQuery कस्टम इवेंट बनाने और इसे सुनने का समर्थन करता है लेकिन हर बार जब कोई बदलाव होता है, तो आपके पास इसे स्वयं पर ट्रिगर करने का एक तरीका होना चाहिए। तो यह पूर्ण समाधान नहीं होगा।


2

आप Jquery प्लगइन की कोशिश कर सकते हैं, यह घटनाओं को ट्रिगर करता है जब सीएसएस परिवर्तन होता है और इसका उपयोग करना आसान होता है

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

दिलचस्प सवाल। समस्या यह है कि ऊंचाई () कॉलबैक को स्वीकार नहीं करती है, इसलिए आप कॉलबैक को फायर नहीं कर पाएंगे। ऊंचाई निर्धारित करने और फिर कॉलबैक में कस्टम इवेंट को ट्रिगर करने के लिए या तो चेतन () या css () का उपयोग करें। यहाँ एक उदाहरण का उपयोग कर चेतन (), परीक्षण और कार्य ( डेमो ), अवधारणा के प्रमाण के रूप में किया गया है:

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

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

8
क्षमा करें, लेकिन यह साबित क्या हुआ? आप trigger()मैन्युअल रूप से घटना। मुझे लगता है कि ओपी कुछ ऑटो-ट्रिगर इवेंट के बाद होता है जब एक शैली विशेषता को संशोधित किया जाता है।
जेपीओट

@JPot वह दिखा रहा है कि ऊँचाई की विशेषता घटनाओं को बदलने पर नहीं फेंकती है।
एन्थोनीजेलिंक

1

बस ऊपर से @David के समाधान को जोड़ना और औपचारिक बनाना:

ध्यान दें कि jQuery फ़ंक्शंस चेनेबल हैं और 'यह' लौटाते हैं ताकि कई इनवोकेशन को एक के बाद एक (जैसे $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

मुझे भी यही समस्या थी, इसलिए मैंने यह लिखा। यह अच्छी तरह से काम करता है। बहुत अच्छा लगता है अगर आप इसे कुछ सीएसएस बदलावों के साथ मिलाते हैं।

function toggle_visibility(id) {
   var e = document.getElementById("mjwelcome");
   if(e.style.height == '')
      e.style.height = '0px';
   else
      e.style.height = '';
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.