Use jQuery to listen for DOM element size changes

  • 2021-01-03 20:48:04
  • OfStack

The cause of

When I was writing the page today, I suddenly had such a requirement. Since the height of the parent element (1 DIV) is a fixed value calculated by javascript, and one more plug-in is added, the height attribute of the child element (DIV) is increased after the user comments, resulting in the overflow of the child element. But I didn't know how to add a callback function to the comment button, so I came up with the idea of recalculating the height of the parent element based on the size change of the child element.

onresize?

Usually, it triggers a callback function to change the layout when the entire browser window changes. The resize event is used for the window object, using:


window.onresize = callback;

To bind. However, according to the target of resize event is defaultView (window), please refer to the resize document of MDN here. That is to say, only window object has resize event, so I think of using jQuery's own event mechanism to simulate the resize event on a common element

Implementation idea using JQUERY events

One simple way can be thought of:

1. Record the width and height of the element when the element binds the resize object
2. Use requestAnimationFrame, setTimeout and setInterval to query their width and height every once in a while. If not the same as the record's width and height, run the callback function and update the record's width as height

JQUERY plug-in

This feature Ben Alman wrote an jQuery plug-in, portal
The code of this plug-in (the core part), please check the Ben Alman blog for the detailed code:


(function($, window, undefined) {
 var elems = $([]),
  jq_resize = $.resize = $.extend($.resize, {}),
  timeout_id,
  str_setTimeout = 'setTimeout',
  str_resize = 'resize',
  str_data = str_resize + '-special-event',
  str_delay = 'delay',
  str_throttle = 'throttleWindow';
 jq_resize[str_delay] = 250;
 jq_resize[str_throttle] = true;
 $.event.special[str_resize] = {
  setup: function() {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var elem = $(this);
   elems = elems.add(elem);
   $.data(this, str_data, {
    w: elem.width(),
    h: elem.height()
   });
   if (elems.length === 1) {
    loopy();
   }
  },
  teardown: function() {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var elem = $(this);
   elems = elems.not(elem);
   elem.removeData(str_data);
   if (!elems.length) {
    clearTimeout(timeout_id);
   }
  },
  add: function(handleObj) {
   if (!jq_resize[str_throttle] && this[str_setTimeout]) {
    return false;
   }
   var old_handler;
   function new_handler(e, w, h) {
    var elem = $(this),
     data = $.data(this, str_data);
    data.w = w !== undefined ? w : elem.width();
    data.h = h !== undefined ? h : elem.height();
    old_handler.apply(this, arguments);
   }
   if ($.isFunction(handleObj)) {
    old_handler = handleObj;
    return new_handler;
   } else {
    old_handler = handleObj.handler;
    handleObj.handler = new_handler;
   }
  }
 };

 function loopy() {
  timeout_id = window[str_setTimeout](function() {
   elems.each(function() {
    var elem = $(this),
     width = elem.width(),
     height = elem.height(),
     data = $.data(this, str_data);
    if (width !== data.w || height !== data.h) {
     elem.trigger(str_resize, [data.w = width, data.h = height]);
    }
   });
   loopy();
  }, jq_resize[str_delay]);
 }
})(jQuery, this);

jQuery provides an interface for developers of jQuery plug-ins to add custom events. For details, please refer to the official documentation of jQuery. Here is the typical jQuery custom event addition method, which has three hooks:

1. setup: The setup the the time event a particular type to an element. The first binding is performed. If false is returned, the default mode is used to bind the event
2. teardown: The teardown hook is called when the final event of a particular type is removed from an element. If this method is specified, it executes before removing the event handler (removeEventListener) and, if false is returned, removes the default bound event
3. add: Each an handler to element element API as on(), jQuery this element an an an an an an an an an an an an an an an an element This method executes every time an event is bound to an element

There are three hooks, setup, teardown, and add.the first thing each hook does is detect if the object is an window object, and then treat it specifically according to the window object, because the window object itself has an resize event

As can be seen from the setup hook, when initializing the whole event processing, 1 element queue is created, width and height are placed in data for every other element in the queue, then loopy function is started every 250ms to determine whether the change is in the loopy function, and if so, the callback function is triggered and the width and height in data are updated

As you can see from the teardown hook, when an element removes an event, you only need to remove the element from the element queue and clear the data data from the element. If it is the last element in the element queue, loopy is not continued

In the add hook, the callback function is wrapped

You can see the implementation mechanism of a simple jQuery custom function


Related articles: