19

I'm using Angular & Bootstrap, with the nav tab control to switch visibility of divs. In one div, I have a large img (CAD drawing of building). I also then overlay markers on the image. I want to scale the x/y position of the markers based on the image width & image naturalWidth. I'm using a resize directive to detect changes and update my scope.

My problem is that if user switches tabs and switches back to the div with the CAD img, the refresh doesn't happen until I resize the browser (or surprisingly if I press the CMD key on Mac).

Is there an angular way to trigger the resize event to force my markers to be recalculated. Or is there an event I can tap into that is fired when the is fully displayed ?

Or is there a more refined angular approach I should take?

This is the HTML, the resize directive I've written is on the tag.

<div id="imageDiv" style="position: relative;"  ng-show="selectedLocation"  >
  <img ng-src="../maps/image/{{selectedLocation}}" 
       style=" max-width: 100%; max-height: auto; border:solid 1px black" resize  imageonload />
</div>

And this is the resize directive (adapted from http://jsfiddle.net/jaredwilli/SfJ8c/)

directive('resize', function($window) {
  return function(scope, element) {
    var w = angular.element($window);

    scope.imgCadImage = element;

    scope.getWindowDimensions = function() {
      return {
        'h' : scope.imgCadImage[0].width,
        'w' : scope.imgCadImage[0].height
      };
    };
    scope.$watch(scope.getWindowDimensions, function(newValue, oldValue) {
      if (scope.imgCadImage[0].naturalWidth)
        scope.imgScale = newValue.w / scope.imgCadImage[0].naturalWidth;
      else
        scope.imgScale = 1;
      console.log("watched resize event - scale = "+scope.imgScale)
      scope.updateCADMarkersAfterResize();
    }, true);
    w.bind('resize', function() {
      console.log("'resize' - scale = "+scope.imgScale)
      scope.$apply();
    });
  };
}).
4
  • Have you tried adding a attribute based behavioral directive to the div containing the image which calls the resize in it's link function? Commented May 13, 2014 at 17:38
  • @MarcKline - what's the div link function? Can you point me at some more info about it. Google search isn't too helpful. Commented May 13, 2014 at 18:39
  • Let me actually first ask you this: is your resize directive a) attached to the image or its container and b) is it bound/triggered only by the window.resize event? It would be most helpful if you could provide some pseudocode demonstrating what you've described, but if you can answer those questions I might be able to take a guess at a solution. Commented May 13, 2014 at 19:21
  • Code attached - I confess I don't have the fullest understanding of the directive I adopted for my use. I tried adding the resize directive to the containing div, but it didn't anything. Commented May 13, 2014 at 20:18

3 Answers 3

22

This worked for me when the above did not.

$timeout(function() {
    $window.dispatchEvent(new Event("resize"));
}, 100);

I had to also use $timeout with a delay in my case to prevent errors about digest cycles already being in progress. Not all uses cases may need this.

dispatchEvent is well supported http://caniuse.com/#feat=dispatchevent

However, it you need IE9 and IE10 support you'll have to use their propritary method: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/fireEvent

Sign up to request clarification or add additional context in comments.

2 Comments

using a >0 timeout delay in this scenario is almost certainly a bad idea. >0 timeouts shouldn't be used to solve timing problems, they should only be used when you actually want something to happen in that much time (e.g. an animation). You have absolutely no guarantee that 100ms is the appropriate amount of time to avoid a timing issue on any device.
Worked for me without the delay, putting the timeout there just forces it onto the next digest cycle
12

Try injecting $timeout into the resize directive:

directive('resize', function($window, $timeout) {

... then add the following line to the bottom of it:

$timeout(function(){ w.triggerHandler('resize') });

This should trigger the handler you have bound to $window.resize just after the browser renders.

2 Comments

This did the trick, thanks. I also had to add the call to $timeout(function(){ w.triggerHandler('resize') }); in areas where I change tab control too.
slight gotcha: triggerHandler only triggers events that are added by jqLite/jQuery. If your event is added with pure javascript (ie. addEventListener), you're SOL. See this question and this question for more info.
1

The accepted answer did not work for me - w is undefined.

This did:

$timeout(function(){
    $(window).trigger('resize');
});

1 Comment

$(window).trigger('resize') is not AngularJS way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.