I have a function that receives an argument:
function test(arg)
{
alert(this.id);
alert(arg);
}
I want to attach this function to a variable:
variable.addEventListener('mouseup',function (ime_igraca) {
test(ime_igraca);
});
And I want this in function test to refer to the variable on which mouseup happened.
It's just impossible: You can't attach an eventlistener to a variable because a variable that not supports events !
You have more informations here (MDN documentation ;) )
But, why you want to add an addEventListener to your variable ? What is your problem ? And where does the variable ime_igraca come from ?
Edit
Maybe you just want to send existing variable to a listener like that :
JS
let myElement = document.getElementById('myElementId');
let ime_igraca = "Foo";
myElement.addEventListener('mouseup',function () {
test(ime_igraca);
});
function test(arg) {
console.log(arg);
}
HTML
<button id="myElementId">My Button</button>
Related
I have an event listener that is added by another event listener that is added by a function inside a class. I want this event listener to execute once and then remove itself.
To simplify the matter, let's assume I have the following HTML code :
<div class="container">
<div class="redDiv">some html</div>
<div class="blueDiv">some html</div>
</div>
and the following JavaScript code :
class Test {
constructor(_container){
this.container = _container;
}
somefunc(){
// some code here
this.removeEventListener('click',somefunc);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',somefunc);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
The first problem I came across, is that somefunc is not defined at the scope of the second Event Listener. The only solution I have found was to create a new variable fnc in the start function and assign somefunc to it and then call fnc instead of somefunc.
This made adding the event listener work and the code run as expected but then when somefunc() was executed, removing the event listener didn't work because somefunc was undefined at this scope.
I tried to pass somefunc to this scope by changing the code to this :
class Test {
constructor(_container){
this.container = _container;
}
somefunc(func){
return function(){
// some code here
this.removeEventListener('click',func);
}
}
start(){
var fnc = this.somefunc;
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',fnc(fnc));
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
Now, the code doesn't generate any errors but the event listener isn't removed as desired. This has probably something to do with the way JavaScript assigns variables, a subject I don't really understand well. But what I'm interested in is how I can solve this matter and be able to remove the event listener once it is executed.
One solution is to use an arrow function to maintain the reference of this...
class Test {
constructor(_container){
this.container = _container;
}
somefunc(fn){
console.log('clicked blue div')
this.container.querySelector('.blueDiv').removeEventListener('click', fn);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',() => {
console.log('clicked red div')
// Wrap someFunc in an arrow function to have "this" inside somefunc
// reference this class.
const func = () => this.somefunc(func);
container.querySelector('.blueDiv').addEventListener('click', func);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
StackBlitz Example
I am trying to come up with a page on which, when user clicks a file button on the page, I try to execute the JS on the page. And I am trying to use OOP / class so hopefully it can be reused later. Here is my test code:
// This is the "class".
function BearUpload() {
// some values will go here...
}
// Add a few functions
BearUpload.prototype.function1 = function () {
console.log("function1 called");
}
BearUpload.prototype.handleFileSelect = function (evt) {
console.log("handleFileSelect called");
this.function1();
}
var myBear = new BearUpload(); // Create a global variable for the test
$(document).ready(function () {
var some_condition_goes_here = true;
if (some_condition_goes_here) {
$("#my-file-select-button").change(myBear.handleFileSelect);
}
});
However, it gets error like:
TypeError: this.function1 is not a function
this.function1();
Any idea about this?
Thanks!
Bind myBear to your change eventListener
In general when you access this from handleFileSelect, this refers to the html element.
i.e. this = <input type="file" id="my-file-select-button">
$("#my-file-select-button").change(myBear.handleFileSelect.bind(myBear));
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
MDN doc
You are trying to call function1 on DOM object but you have to call on jQuery object
$(this).function1();
That's because when bound as a handler to jQuery events, this would refer to the element on which the event is triggered.
I would rather change your code like this
// Create only one global variable for your app
var APP = {};
// Create class using immediate function/closure
APP.BearUpload = (function(){
//declare private variables here
// Constructor
var bearUpload = function() {
// some values will go here...
}
// Add a few functions
bearUpload.prototype.function1 = function () {
console.log("function1 called");
}
bearUpload.prototype.handleFileSelect = function (evt) {
console.log("handleFileSelect called");
this.function1();
}
return bearUpload;
}());
APP.myBear = new APP.BearUpload();
$(document).ready(function () {
var some_condition_goes_here = true;
if (some_condition_goes_here) {
$("#my-file-select-button").change(function(e){
// do something with event 'e'
APP.myBear.handleFileSelect.call(APP.myBear, e);
});
}
});
do not use "this", it is confusing some time.
BearUpload.prototype ={
function1:function(){
var self = this;
...
},
handleFileSelect:function(e){
var self = this;
...
}
}
I can't figure out how to use a Javascript constructor method in a jQuery .click method. I'm trying to get a button's function to change dynamically based on a constructor. Here's the set up:
<button onclick="">
</button>
needs to call a method that changes depending on another button. The following is my broken code:
function GloveMode (name , array) {
this.colorArray = array;
this.displaySettings = function(){
//Title
$("#displayTitle").text(this.name);
//Display Color Set
$("#displayColors").empty();
//Totally Broken
$("#upArrow").click( function(){
addColor();
});
};
this.addColor = function(){
console.log(this.colorArray.length);
};
};
I can't figure out how to get $("#upArrow").click() to call this.colorArray properly, or how to call this.addColor() in the .click() method! Please help.
Your Problem is that "this" means something different in each function body. So save the wanted "this" to a variable e.g. "self" and use that.
function GloveMode (name , array)
{
var self = this;
this.colorArray = array;
this.displaySettings = function()
{
//Title
$("#displayTitle").text(this.name);
//Display Color Set
$("#displayColors").empty();
//Totally Broken
$("#upArrow").click( function()
{
self.addColor();
});
};
this.addColor = function()
{
console.log(self.colorArray.length);
};
};
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I understand how this works when invoked on an object, but I'm having trouble understanding how this works when called from a "static" context.
Given the following HTML:
<body onload="myOnLoad()">
<div id="someDiv">0</div>
</body>
...and this javascript:
function myOnLoad() {
var inc = new Incrementer();
/*** increase() works fine here, "this" refers to "inc" ***/
inc.increase();
inc.setOnClick();
}
function Incrementer() {
this.value = 0;
}
Incrementer.prototype.setOnClick = function() {
/*** increase fails to update someDiv when clicked.
"this" is not "inc" ***/
document.getElementById("someDiv").onclick = this.increase;
}
Incrementer.prototype.increase = function() {
document.getElementById("someDiv").innerHTML = ++this.value;
}
...clicking on someDiv turns it's innerHTML into NaN. I realize that this is because the onclick event is unaware of the existence of inc, but what I don't understand is how to pass 'inc' into the onclick event.
Do you know how I can access inc's variables from the context of an onclick? Or, is there a more conventional way of doing this?
I'm mostly interested in learning how I can make someDiv's onclick refer to that specific instance, inc.
this refers to the context of where the function being called, e.g. in setOnClick the function this.increase will be called in the context of someDiv, so this.value would be undefined in that case.
try
document.getElementById("someDiv").onclick = this.increase.bind(this);
You may want to learn more about the property of this from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
In event handlers, this is bound to the element that triggered the event. If you want to affix it to your this, you need to use .bind() like so:
Incrementer.prototype.setOnClick = function() {
document.getElementById("someDiv").onclick = this.increase.bind(this);
}
You can try another way. You can avoid to use the property prototype and pass the html element to Incrementer at the declaration :
function myOnLoad() {
var inc = new Incrementer(document.getElementById("someDiv"));
}
function Incrementer(newElement) {
var value = 0;
var element = newElement;
this.increase = function(){
element.innerHTML = ++value;
}
element.onclick = this.increase;
}
Is it possible to change the state of a toggle function? Like:
myDiv.toggle ... function 1 , function 2
I click on the myDiv element, the function 1 executes
I click again, function 2
I click again, function 1
BUT
Change the state
function 1 again
etc.
But I need to be able to change the state from outside the toggle function.
Here is a javascript object that uses closure to track it's state and toggle:
var TOGGLER = function() {
var _state = true;
var _msg = "function1";
var function1 = function() {
_msg = "function1";
}
var function2 = function() {
_msg = "function2";
}
return {
toggle: (function () {
_state = !_state;
if (_state) {
function1();
} else {
function2();
}
return _msg;
})
}
}();
Here is a jsfiddle that shows how to use it to toggle based with the following jquery: http://jsfiddle.net/yjPKH/5/
$(document).ready(function() {
$("#search").click(function() {
var message = TOGGLER.toggle();
$("#state").text(message);
});
});
The toggle function is meant for simple use cases. Changing the state externally is not "simple" anymore.
You cannot easily/safely (it's internal so it may change during minor versions) access the state variable of the toggle function easily as it's stored in the internal dataset of the element.
If you really want to do it, you can try this code though:
$._data(ELEMENT, "lastToggle" + func.guid, 0);
func is the function you passed to .toggle(), so you need to save this function in a variable. Here's a minimal example: http://jsfiddle.net/xqgrP/
However, since inside the function there's a var guid = fn.guid || jQuery.guid++ statement, I somehow think that the devs actually meant to use guid instead of func.guid for the _data key - in that case a minor update is very likely to break things. And after the fix you'd have to iterate over the data set to retrieve the correct key as there is no way to access the guid from outside.