Calling function from outside window.EventListener

So I am trying to call a function outside of my

window.addEventListener('deviceorientation', function (event) {
            console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma);
            this.adjustHeading(event.alpha);
        })

the function that I am trying to call:

adjustHeading: function (heading) {
        this.map.getModel().setViewRotation(heading, false);
    }

The whole js:

(function ($) {
'use strict';

$.widget("symfony.GpsPosition", {

    //lots of code//

    listenForDeviceOrientation: function() {
       window.addEventListener('deviceorientation', function (event) {
            console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma);
            this.adjustHeading(event.alpha);
        })},

    adjustHeading: function (heading) {
        this.map.getModel().setViewRotation(heading, false);
    }
});

}(jQuery));

My problem is, that the this.adjustHeading(event.alpha); call from the window.eventListener does not work because adjustHeading() is not available in the windows scope.

Is there any way to somehow bypass that and get access to the JS properties in the same file?

I am using smyfony and openlayers for the mapview, if that is helpfull at all.

Answer

The issue is because your code expects this in the event handler function to be a reference to the settings object you provide to $.widget. However in the event handler the scope has been changed so that this refers to the object you attached the event to, the window in this case.

To fix this you could either use an ES6 arrow functions to define the event handlers, as these do not affect the scope of the handler:

listenForDeviceOrientation: () => window.addEventListener('deviceorientation', e => this.adjustHeading(e.alpha)),
adjustHeading: heading => this.map.getModel().setViewRotation(heading, false);

Or alternatively you could ‘cache’ the this reference in a variable declared in the outer scope, to be used within the event handler:

$.widget("symfony.GpsPosition", {
  let _this = this;
    
  // lots of code...

  listenForDeviceOrientation: function() {
    window.addEventListener('deviceorientation', function(event) {
      _this.adjustHeading(event.alpha);
    })
  },
  adjustHeading: function(heading) {
    _this.map.getModel().setViewRotation(heading, false);
  }
});

The former is more succinct but is not supported in IE, so the best choice for you would come down to what browsers you’re required to support.

Leave a Reply

Your email address will not be published. Required fields are marked *