48

I'm using the .resize() function to detect window re-size events, but this detects both height and width changes.

Is there any way to detect just a width change and not a height change?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
shrewdbeans
  • 11,971
  • 23
  • 69
  • 115

5 Answers5

98
var width = $(window).width();
$(window).on('resize', function() {
  if ($(this).width() !== width) {
    width = $(this).width();
    console.log(width);
  }
});
thecodeparadox
  • 86,271
  • 21
  • 138
  • 164
  • Is there a way to only act when only the width has changed AND when less than a pixel value? E.g. if ($(window).width() < 500) combined with the above? – Dan382 Mar 17 '15 at 09:36
  • 1
    The code above works, but its performance is suboptimal. The jQuery window object is created multiple times even though it could be done just once. Also the new width of the windows is pointlessly calculated multiple times. – Anton Feb 05 '16 at 14:56
  • 1
    Better would be to use a listener that only fires when the user is [_done_ resizing](https://css-tricks.com/snippets/jquery/done-resizing-event/). – Pete Feb 14 '17 at 06:52
  • This doesn't actually check if the window width changes on each resize... it only compares the new window width with the "original" window width. So the 2nd and 3rd time resizing, you're not comparing to the real "last" width. You need to set the current window width into some local state variable and check that each time on resize, and update it when the width does finally change. – TetraDev Dec 16 '19 at 22:46
  • 1
    It should be !== and not != – Wessam El Mahdy Apr 06 '20 at 04:35
22

you can detect both events and just execute code when it's a width change:

var lastWidth = $(window).width();

$(window).resize(function(){
   if($(window).width()!=lastWidth){
      //execute code here.
      lastWidth = $(window).width();
   }
})        

And you might want to check event debouncing.

Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called.


Read more:


Taha Paksu
  • 15,371
  • 2
  • 44
  • 78
5

Even though there are already a couple of answers with working solutions, this kind of task is performance critical (window resize event is triggered many times while a user is resizing the window) so I strongly suggest you to take care of the performance. Please, have a look at the optimized code below:

/* Do not waste time by creating jQuery object from window multiple times.
 * Do it just once and store it in a variable. */
var $window = $(window);
var lastWindowWidth = $window.width();

$window.resize(function () {
    /* Do not calculate the new window width twice.
     * Do it just once and store it in a variable. */
    var windowWidth = $window.width();

    /* Use !== operator instead of !=. */
    if (lastWindowWidth !== windowWidth) {
        // EXECUTE YOUR CODE HERE
        lastWindowWidth = windowWidth;
    }
});

Plus, you might be interested in checking the Debounce / Throttle patterns - they improve performance enormously in cases like this.

Anton
  • 2,458
  • 2
  • 18
  • 30
2

One can also use this tiny jQuery plugin for this: https://github.com/adjohnson916/jquery-resize-dimension

Keeps your own code more readable:

ResizeDimension.bind('width');
$(window).on('resize-width', function () {
  console.log('resize-width event');
});

or just:

$(window).resizeDimension('width', function () {
  console.log('resize-width event');
});
nachtigall
  • 2,447
  • 2
  • 27
  • 35
0

The link provided by @nachtigall is broken, so I found this other with the same library, which helped me to solve my issue: resize-dimension.js

Example of solution is as follow: Import library:

<script src="./resize-dimension.js"></script>

Create script:

<script type="text/javascript">
        ResizeDimension.bind('width');
        $(window).on('resize-width', function () {
            //alert(window);
            ForResize();
        });
 </script>

The function ForResize() gets fired when the browser is resized, though in this case, IE handles it better than the other browsers, however, in my case, it worked fine for mobile devices, which where firing the events when scrolling the page, which depending on the mobile browser, it can hide the address bar, which affects the browser's size. Implementing that library helped!

I used the counter/timer provided here and modified it to my needs. The following are the critical scripts that I had to create:

<script type="text/javascript">
    function RefreshWidth() {
        var _hcontainer = $("#chart_container").width();
        var _hcontainerInt = parseInt(_hcontainer, 10);
        $("#txChartSize").val(_hcontainerInt);
        $("#txChartSize_1").val(_hcontainerInt);
        $("#textWidthFire").val(_hcontainerInt);
        DetectResizeChange();
    }
</script>

<script type="text/javascript">
    var myTimer; //also in C#
    var c = 0;
    //these functions are needed in order to fire RefreshWidth() so it will fire DetectResizeChange() after browser changes size
    function clock() {
        //RefreshWidth();
        myTimer = setInterval(myClock, 1000);
        c = 3;

        function myClock() {
            document.getElementById("loadMsg").innerHTML = "Processing chart, please wait...";
            --c; //--->>counts in reverse to resize
            if (c == 0) {
                RefreshWidth(); //--->>gives enough time for the width value to be refreshed in the textbox
                clearInterval(myTimer);
            }

        }
    }

    //detects size change on the browser
    function DetectResizeChange() {
        var _NoDataAvailable = $('#txNoDataAvailable').val();

        if (_NoDataAvailable != 'NoData') {

            var refLine = $("#refLine").width();

            var _hcontainer = $("#chart_container").width();
            var _width = _hcontainer;

            var _hcontainerInt = parseInt(_hcontainer, 10);

            $("#txChartSize").val(_hcontainerInt);
            $("#textWidthFire").val(_hcontainerInt);
            $('#msgAdjustView').show();

            $("#msgAdjustView").text("Loading data and adjusting chart view, please wait...");
            $('.modal').show();

            var checkOption = document.getElementById('lbViewingData').value;
            var button;
            var btnWidth;
            btnWidth = document.getElementById('btnStopTimer');
            if (checkOption == 'Option 1') {
                button = document.getElementById('firstTab');
            } else if (checkOption == 'Option 2') {
                button = document.getElementById('secondTab');
            } else if (checkOption == 'Option 3') {
                button = document.getElementById('thirdTab');
            }
            button.click();
        }
    }
</script>
        <script type="text/javascript">
            function ForResize() {
                var _NoDataAvailable = $('#txNoDataAvailable').val();

                if (_NoDataAvailable != 'NoData') {
                    clock();
                    document.getElementById('loadMsg').innerHTML = 'Resizing chart in progress...';
                }
            }

</script>

In case that the library's link gets broken again, here is the code from the same source (resize-dimension.js):

(function (root, factory) {
  var moduleName = 'ResizeDimension';
  if (typeof define === 'function' && define.amd) {
    define(['jquery'], function ($) {
        return (root[moduleName] = factory($));
    });
  } else {
    root[moduleName] = factory(root.$);
  }
}(this, function ($) {

  var $window = $(window);

  var ResizeDimension = function ($el, dimension, handler, options) {

    if (! (this instanceof ResizeDimension)) {
      return new ResizeDimension($el, dimension, handler, options);
    }

    this.$el = $el;

    this.init(dimension, handler, options);

    return this;
  };

  /**
   * Stub - overridden on #init()
   */
  ResizeDimension.prototype.onResize = function () {};

  ResizeDimension.bound = {};

  ResizeDimension.bind = function (dimension, options) {
    if (ResizeDimension.bound[dimension]) return;
    ResizeDimension.bound[dimension] = true;
    $window.resizeDimension(dimension, function () {
      $window.trigger('resize-' + dimension);
    }, options);
  };

  ResizeDimension.prototype.init = function (dimension, handler, options) {

    if (typeof dimension === 'object') {
      options = dimension;
      dimension = options.dimension;
      handler = options.handler;
    }

    options = $.extend({}, options);
    options.dimension = dimension;
    options.handler = handler;

    this.options = options;

    if ($.isFunction(options.changed)) {
      this.changed = options.changed;
    }

    this.dimension = this.normalize(options.dimension);
    this.handler = options.handler;
    this.previousValue = this.value();

    var proxied = $.proxy(this.handle, this);
    if (options.throttler) {
      this.onResize = options.throttler(proxied);
    }
    else {
      this.onResize = proxied;
    }
  };

  ResizeDimension.prototype.normalize = function (dimension) {
    return dimension;
  };
  ResizeDimension.prototype.changed = function (previous, current) {
    return previous !== current;
  };

  ResizeDimension.prototype.value = function (e) {
    return this.$el[this.dimension]();
  };

  ResizeDimension.prototype.handle = function (e) {
    var currentValue = this.value();
    if (this.changed(this.previousValue, currentValue)) {
      this.previousValue = currentValue;
      return this.handler.call(this.$el, e);
    }
  };

  var $resizeDimension = function () {
    var args = Array.prototype.slice.call(arguments);
    return this.each( function() {
      var $el = $(this);
      args = [$el].concat(args);
      var instance = ResizeDimension.apply(null, args);
      $el.on('resize', $.proxy(instance.onResize, instance));
    });
  };

  $.fn.resizeDimension = $resizeDimension;

  return ResizeDimension;

}));
Mr. Munoz
  • 69
  • 1
  • 3
  • 13