Setting up event listeners from a string array (using PIXI.js)

Hey there! I've encountered a bit of an interesting challenge that could easily be resolved by duplicating the code, but where's the fun in that? This project is more of an experiment for me, just to prove that I can do it. However, the idea has been nagging at me since its inception.

The Fun Project

Just for kicks, I decided to convert an ActionScript 3 text-based game engine into TypeScript and JavaScript using PixiJS. Currently, I have 20213 errors popping up while running tsc, so I could postpone this task for later. Nonetheless, I started working on the Button class, defined as a subclass of MovieClip. I researched PIXI buttons, which seemed straightforward enough. All I needed to do was add similar lines of code within the button's constructor:

export class Button extends PIXI.Sprite {
    private _callback : Function;
    private _height : number;
    private _width : number;
    public get callback() : Function { return this._callback; }
    public set callback(fn : Function) {this._callback = fn; }
    public get height() : number { return this._height; }
    public set height(h : number) {this._height = h; }
    public get width() : number {return this._width; }
    public set width(w : number) {this._width = w; }
    public constructor(width = 180, height = 90, callback: Function = null){
        super(new PIXI.Texture(new PIXI.BaseTexture(GLOBAL.BTN_BACK, PIXI.SCALE_MODES.NEAREST)));
        this.callback = callback;
        this.width = width;
        this.height = height;
        this.buttonMode = true;
        this.interactive = true;
        this.anchor.set(0.5);
        this.on('mousedown', this.callback)
            .on('touchstart', this.callback);
    }
}

This simplified version differs slightly from the one on Codepen, which utilizes a Container and a private _sprite field instead. Regardless, the essence remains the same.

The Challenge

The issue arises when attempting the following on Codepen:

// assign `this.callback` to each of the following events:
let that = this;
['click','mousedown','touchstart'].map(evt => that.on(evt, that.callback});

I aimed to achieve this with a simple call passed into their constructors elsewhere:

for (let n = 0; n < 5; ++n){
    btnArray.push(new Button(16, 16, () => console.info('You pushed button %d', n)));
}

However, nothing seems to be triggering, even when checking the Chrome Console. I even debugged the ColorMatrixFilter mentioned earlier to ensure the issue isn't related to console.info. As of now, I'm perplexed about where the problem lies. I initially thought of creating a GLOBAL key to iterate through for the events, but it doesn't seem to be functioning correctly.

The Queries

  1. Is my approach feasible, albeit unconventional? Could there be a security feature hindering it, or am I missing something crucial?
  2. Do I really need to stress over setting multiple event handlers, or would listening solely to 'click' suffice?

Answer №1

When executing an arrow function like the event map, the context of this is not defined. Therefore, any code referencing this will retrieve the current value, including functions called within the map.

You can update your event map with the following:

['click', 'mousedown', 'touchstart'].map(function(evt) { that.on(evt, that.callback} } );

Here's a demonstration:

function Named(x) {
    this.name = x;
}
var foo = new Named("foo");
var bar = new Named("bar");

var showFunc = function show() {
    // The context here is dependent on 'this'
    console.log(this.name);
}

var showArrow;
// The context here is the window
showArrow = () => console.log(this.name);

var fooShowArrow;
(function() {
    // The context here is 'foo'
    that = this;
    fooShowArrow = () => console.log(that.name);
}).apply(foo);

var example = function(func) {
    // For demo purposes, at this point, 'this' will always be 'bar'
    func.apply(this, [ "arbitrary value" ]);
}

// Explicitly setting the current "this" to 'bar' for the execution of these functions
example.apply(bar, [showFunc]);  // works
example.apply(bar, [showArrow]);  // fails, 'this' is still the window
example.apply(bar, [fooShowArrow]);   // fails, 'this' is still 'foo'

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to confirm the actual openness of Express app's connection to MongoDB?

I'm currently developing an Angular 7 application that utilizes MongoDB, Node.js, and Express. One issue I encountered is that if I start my Express app (using the npm start command) before connecting to MongoDB (using the mongod command), the Express ...

populate vueJS table with data

I encountered an issue while trying to load data from the database into my table created in VueJS. I have set up my component table and my script in app.js, but I am seeing the following error in the view: [Vue warn]: Property or method "datosUsuario" ...

Ways to reduce lag while executing a for loop

How can I optimize my prime number generation process to avoid lagging? For example, is there a way to instantly display the results when generating primes up to 1000? HTML: <!DOCTYPE html> <html> <meta name="viewport" content="width=dev ...

I encounter obstacles when trying to execute various tasks through npm, such as downloading packages

Currently, I am facing an issue while trying to set up backend development using node.js on my personal computer. The problem lies with the npm command as it is not functioning correctly. Despite successfully installing a file without any errors, I am unab ...

Angular is failing to retrieve data from FS.readFile using promises

My goal is to utilize an Angular service to decide whether to call fs.readFile or fs.writeFile based on the button pressed, in order to explore the interaction between node and angular promises. Although I have managed to read and write files, I am facing ...

I successfully converted a d3 chart to a base64 image format and now I am looking to share it on Facebook using either client-side JavaScript or Angular

After generating a base64 image from a cool d3 chart, my next challenge is figuring out how to share it on Facebook using either client-side javascript or Angular. Any suggestions? ...

React-onclickoutside does not function properly within an iframe

I have developed a custom drop-down list using reactjs. I utilized react-onclickoutside to recognize clicks outside the list and close it. While this method works effectively, it does not respond to clicks within an iframe. import onClickOutside from &apo ...

Angular 6 Subscription Service Does Not Trigger Data Sharing Events

Is there a way to set a value in one component (Component A) and then receive that value in another component (Component B), even if these two components are not directly connected as parent and child? To tackle this issue, I decided to implement a Shared ...

Is there a way to verify the phone number input field on my registration form along with the country code using geolocation

I'm currently working on a registration form that includes an input field for telephone number. I'd like to implement a feature where, upon filling out the form, the telephone input field automatically displays the country code by default. Would ...

Tips for handling the accent mark (diacritic mark)

My primary language is Spanish, which means I use accent marks quite frequently (á, é...). When I need to type them out, I resort to using &aacute;, &eacute;, and so on. However, I'm facing an issue when trying to compare two sentences in m ...

How to resolve TypeScript error TS2322 when a function returns an interface

export interface AWSTags { CreatedBy: string; Environment: EnvironmentMap; Name: string; OwnedBy: string; Platform: string; Product: string; Runbook: string; Service: string; } Another script contains the following function to generate an ...

TypeScript class that utilizes internal functions to implement another class

In my journey of exploration, I decided to try implementing a class within another class in TypeScript. Here is the code snippet I came up with and tested on the Playground link: class A { private f() { console.log("f"); } public g() { console.lo ...

Is it possible for a Vue component to contain both data and props simultaneously?

How does a standard Vue component look? Vue.component('blog-post', { // camelCase in JavaScript props: ['postTitle'], template: '<h3>{{ postTitle }}</h3>' }) The basic documentation on components does not us ...

What is the best way to calculate the number of days that have passed since a certain

Hey there, I've got this 10 Dec, 2019T14:07:21 date format from the backend. My goal is to determine how many days ago it was. For example, today is the 20th, so if the date is today's date, it should show as 0 days ago. ...

How to use Express Validator to validate both email and username within a single field?

I am currently developing an application using the Express (Node.js framework) and I want to allow users to log in with either their email address or username. My question is, how can I implement validation for both types of input on the same field using e ...

Exploring the foundations of web development with html and stylus

If you have experience with the roots platform, you are familiar with its default stack including jade, stylus, and coffee script. The documentation provides some information on using HTML, CSS, and pure JavaScript instead of the compiled languages, but d ...

Having an issue with utilizing the useState hook in ReactJS for implementing pagination functionality

I'm struggling to resolve an issue with the React useState. What I'm trying to achieve is making an API call to fetch movies with pagination, but for some reason one of my states is showing up as undefined and it's puzzling me. The component ...

What is causing ngResource to change the saved object to something like "g {0: "O", 1: "K", ..} once it receives a response?

In my current setup, I have a default ngResource that is defined in the following way: var Posts = $resource('/posts/'); Once I retrieve a blog post from my nodejs server using the code below: $scope.post = Posts.get({_id:query._id}); The use ...

Updating a div's border using JavaScript

I recently generated a div element dynamically through code. var Element; Element = document.createElement('div'); My goal now is to modify the right and bottom borders to "#CCCCCC 1px solid". I aim to achieve this without relying on any exte ...

Adding a unique key to every element within a JavaScript array

I am working with the array provided below which contains simple values. My goal is to add a key id before each value in the array, resulting in something like this: ["id:a", "id:b","id:c","id:d"]. Is there an easy way to achieve this? Any assistance would ...