How to use button.moussePressed() in an Object ?

Hi,

I didn't succeed in creating a class in which a button from the DOM can call a local function with local variable. For example, with this script...

function setup() {
  myObject = new Test();
}


function Test() {

  this.something = 12345;
  this.button = createButton('Hello');

  this.test = function() {
    println(this.something);

  }

  this.button.mousePressed(this.test);
}

... println says that the argument is undefined

If I put println("123456"); in the test function, it works. But how can I do to use local variable ?

Thank you.

(I've tried with the "prototype way" without success.)

Answers

  • I'm not a JavaScript expert, but the first thing I would try is something like this:

    this.something = 12345;
    this.button = createButton('Hello');
    
    var testSomething = this.something;
    
      this.test = function() {
        println(testSomething);
      }
    
  • edited September 2016

    JS' keyword variable this is tricksy. The object which calls a function becomes its this: @-)
    https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

    In your case above, the object which ends up invoking method test() isn't a Test, i.e. the object created by your myObject = new Test();, but the p5.Element object created by createButton()! b-(

    And when println(this.something); is finally executed, it logs out undefined, b/c the button object doesn't have any property called something. :-B

    But don't fret: In order to counter that issue, all JS functions got methods call(), apply() and bind().

    The 1st 2 are temporary. However bind() creates a wrapper function over the original 1, which then enforces what its this gonna refer to, regardless which object invokes that function: \m/
    https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

  • edited September 2016

    https://alpha.editor.p5js.org/projects/B14hmmI2

    https://forum.Processing.org/two/discussions/tagged?Tag=bind()
    https://forum.Processing.org/two/discussions/tagged/this

    // forum.Processing.org/two/discussion/18165/
    // how-to-use-button-moussepressed-in-an-object#Item_3
    
    // GoToLoop (2016-Sep-13)
    
    // alpha.editor.p5js.org/projects/B14hmmI2
    
    function setup() {
      new Test;
    }
    
    class Test {
      constructor() {
        this.something = 'bind() does work!';
    
        this.button = createButton('Hello')
                     .mousePressed(this.test.bind(this))
                     .size(100, 50);
      }
    
      test() { alert(this.something); }
    }
    
  • edited September 2016 Answer ✓
    • As I've mentioned previously, method bind() creates a wrapper function over the original 1.
    • So as an alternative to bind(), we can define our own wrapper.
    • Not any ordinary function, but newest ES6 JS' arrow function. A.K.A lambdas by other languages:
      https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
    • When creating the fat arrow function, it lexically binds the immediate this automatically! \m/
    • Just replace the expression this.test.bind(this) w/ () => this.test(): :-bd

    https://alpha.editor.p5js.org/projects/Bk_CIU8n

    // forum.Processing.org/two/discussion/18165/
    // how-to-use-button-moussepressed-in-an-object#Item_4
    
    // GoToLoop (2016-Sep-13)
    
    // alpha.editor.p5js.org/projects/Bk_CIU8n
    
    function setup() {
      new Test;
    }
    
    class Test {
      constructor() {
        this.something = 'ES6 JS lambda fat arrow functions are gr8!';
    
        this.button = createButton('Hello')
                     .mousePressed(() => this.test())
                     .size(100, 50);
      }
    
      test() { alert(this.something); }
    }
    
  • Thank you for your extremely well documented answer ! ^:)^

    () => this.test() works fine.

    And I've learnt one more way to make a class... :)

Sign In or Register to comment.