Can mutation observer listen for changes in “data-” attributes?

走远了吗. 提交于 2019-12-11 01:09:48

问题


So the problem is that I have an html element which has an object in a "data-" attribute (set via jQuery ofc) and I want to listen to changes in that attribute.

I have already tried a lot of things, like setting almost all possible combination values in the MutationObserverInit object, but none of this help.

Does anybody know if it is possible?

$('#some-id').click( function() {
  //$('#some-id').attr('title', 'some-title'); //this works
  $('#some-id').data('foo', 'bar1'); //this don't
});

var functionCallBack = function(mutations) {
  alert('something changed')
}

// select the target node
var target = document.getElementById("some-id");

// create an observer instance
var observer = new MutationObserver(functionCallBack);

// configuration of the observer:
var config = { subtree: true, childList: true , attributes: true};

// pass in the target node, as well as the observer options
observer.observe(target, config);

$('#some-id').data('foo', 'bar');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>

回答1:


New Answer (Based on Oriol's Answer):

I think Oriol provided a better approach but it could be optimized further.

var object = {
  'key': 'value'
};

$('.addObj').click(function() {
  $('#some-id').observeData('foo', object, function() {
    console.log("Object Added");
  });
});

$('.removeObj').click(function() {
  $('#some-id').observeData('foo', null, function() {
    console.log("Object removed");
  });
});


jQuery.fn.observeData = function(name, object, callback) {
  // Get elemenet
  var element = $(this[0]);

  // Add data
  element.data(name, object);

  // Call the callback function
  callback();

  // Return this for a chainable function
  return this;
};
span {
  padding: 10px;
  float: left;
  margin: 5px;
  cursor: pointer;
  background-color: green;
  border: 1px solid black;
  border-radius: 5px;
  transition: all 0.5s;
  color: white;
  font-size: 13px;
}
span:hover {
  opacity: 0.8;
}
#some-id {
  text-align: center;
  width: 100%;
  margin: 10px 0;
  font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>

<span class='addObj'>Add Object</span>
<span class='removeObj'>Remove Object</span>

JSFiddle: https://jsfiddle.net/t012rb9j/1/

Old Answer:

As you stated in your code:

$('#some-id').click(function() {

 // $('#some-id').attr('title', 'some-title'); //this works
 $('#some-id').data('foo', 'bar1'); //this don't
});

.attr() works while .data() is not working. The reason is that .attr() adds an an attribute value to your HTML tag while data stores this data in memory.

From jQuery documentation:

.data(): Store arbitrary data associated with the specified element and/or return the value that was set.

.attr(): Get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.

One way to detect data changes (if you want to store an object) is to combine both functions.

var object = {
  'key': 'value'
};

$('.addObj').click(function() {
  $('#some-id').data('foo', object).attr("data-attached", "true");
});

$('.removeObj').click(function() {
  $('#some-id').data('foo', null).attr("data-attached", "false");
});


var functionCallBack = function(mutations) {
  mutations.forEach(function(mutation) {
    if (jQuery(mutation.target).attr("data-attached") == "true") {
      // Your code here
      console.log("Object Added");
    } else {
      console.log("Object removed");
    }
  });
}

// select the target node
var target = document.getElementById("some-id");

// create an observer instance
var observer = new MutationObserver(functionCallBack);

// configuration of the observer:
var config = {
  subtree: true,
  childList: true,
  attributes: true
};

// pass in the target node, as well as the observer options
observer.observe(target, config);
.addObj, .removeObj {
  padding: 10px;
  float: left;
  margin: 5px;
  cursor: pointer;
  background-color: green;
  border: 1px solid black;
  border-radius: 5px;
  transition: all 0.5s;
  color: white;
  font-size: 13px;
}

.addObj:hover, .removeObj:hover {
  opacity: 0.8;
}

#some-id {
  text-align: center;
  width: 100%;
  margin: 10px 0;
  font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>

<span class='addObj'>Add Object</span>
<span class='removeObj'>Remove Object</span>

JSFiddle: https://jsfiddle.net/9xkb6jv4/




回答2:


If you want to detect new data set with jQuery's data, you can always hijack it.

var functionCallBack;
var $data = jQuery.fn.data;
jQuery.fn.data = function(key, value) {
  var ret = $data.apply(this, arguments);
  if(functionCallBack && this[0] && value !== undefined) {
    functionCallBack(this, key, value);
  }
  return ret;
};

$('#some-id').click( function() {
  $(this).data('foo', 'bar1');
}).data('foo', 'bar');
functionCallBack = function(elements, key, value) {
  console.log('something changed')
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>


来源:https://stackoverflow.com/questions/41538686/can-mutation-observer-listen-for-changes-in-data-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!