Undefined $(this) on nested functions - javascript

So basically I have two functions on my click() trigger.
var firstFunction = function() {
var id = $(this).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction();
secondFunction();
});
On firstFunction() I'm trying to get $(this).attr('id') but it's returning undefined.
I know it has something two do with calling multiple functions because it works when I only call one function
$('#trigger').click(firstFunction);
Sample Fiddle here

As per your existing approach this refers to Window object not the element which invoke the event.
You can use .bind()
The bind() method creates a new function that, when called, has its this keyword set to the provided value,
$('#trigger').click(function() {
firstFunction.bind(this)();
secondFunction.bind(this)();
})
var firstFunction = function() {
var id = $(this).attr('id');
console.log(id);
};
var secondFunction = function() {
//something here
var id = $(this).attr('id');
console.log(id);
};
$('#trigger').click(function() {
firstFunction.bind(this)();
secondFunction.bind(this)();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>
Fiddle

It's returning undefined because you aren't applying the same this as the event. You can achieve this by using call or apply instead of calling it directly.
$('#trigger').click(function() {
firstFunction.call(this);
secondFunction.call(this);
});

The this inside the firstFunction will be the window object itself - pass this to the function to fix it - see demo below:
var firstFunction = function(el) {
var id = $(el).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction(this);
secondFunction(this);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>
Another way is to use Function.prototype.call to bind a this argument to the funciton:
var firstFunction = function() {
var id = $(this).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction.call(this);
secondFunction.call(this);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Click Me</button>

You can pass the jQuery object element and than only use it in your function:
var firstFunction = function($el) {
var id = $el.attr('id');
console.log(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function() {
firstFunction($(this));
secondFunction();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="trigger">Button</button>

click() handler receives event as parameter. Pass it because this is not available in the scope of firstFunction().
Like this:
var firstFunction = function(target) {
var id = $(target).attr('id');
alert(id);
};
var secondFunction = function() {
//something here
};
$('#trigger').click(function(e) {
firstFunction(e.target);
secondFunction();
});

Nothing to do major, it's quite simple.
If you are calling a function and into that function you need an event to be used, then pass a reference in the function parameter.
I have updated the code in your Fiddle and updated with Mine:
Step 1:
$('#trigger').click(function(event) {
var that = this;
firstFunction(that);
secondFunction(that);
});
Created a variable that assigned this to that and passed into function parameter.
Note that, writing event in the click function is required to define this as a local click reference (Not a window)
Step 2:
Passed that rather than this, to make sure the reference is from click function only not of window.
var firstFunction = function(that) {
var id = $(that).attr('id');
alert(id);
};
Updated Fiddle

Related

How bind a event and use apply/call to change the scope

+function ($) {
'use strict';
var popup = {
init: function(element) {
this._active = 'products__popup--active';
this._product = $('.products__popup');
this._element = $('[data-popup-to]');
this._TIME = 500;
popup.attachEvt();
},
attachEvt: function() {
var that = this;
that._element.bind('click', popup.handlerEvt.call(that));
},
handlerEvt: function() {
console.log(this);
console.log('test');
}
};
$(window).on('load', function() {
popup.init();
});
}(jQuery);
I have this script, and is not working yet, I cant show you a working example because it is not ready, I'm organizing the code first.
And there is a problem with the attachEvt function, inside it I want to call another function of my object, this function will bind a click in the that._element, but I want pass to the handlerEvt the scope of this (the clicked element) and the that (the object), but this is not working:
that._element.bind('click', popup.handlerEvt.call(that));
I'm just passing the that scope and when the script loads, the element will be clicked without click, I want avoid this.. this is possible?
UPDATE:
Resuming:
I want be able to use the scope of the object (that) and the scope of the clicked element (this) inside the handlerEvt function, but without make the event click when the script loads.. :B
Try utilizing .bind() , with this set to that._element , that passed as parameter to handlerEvent . Note order of parameters at handlerEvent: obj: that first , evt event object second
+function ($) {
'use strict';
var popup = {
init: function(element) {
this._active = 'products__popup--active';
this._product = $('.products__popup');
this._element = $('[data-popup-to]');
this._TIME = 500;
popup.attachEvt();
},
attachEvt: function() {
var that = this;
that._element.bind('click', popup.handlerEvt.bind(that._element, that));
},
handlerEvt: function(obj, evt) {
console.log(evt, obj, this);
console.log('test');
}
};
$(window).on('load', function() {
popup.init();
});
}(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div data-popup-to="true">click</div>

how to get last clicked event data in entire javascript scope

function my_fun(){
var data = $(this).data();
// this is undefined
console.log(data.crm);
}
$(document).on('click', '#add_image', (function() {
var data = $(this).data();
// this works
console.log(data.crm);
my_fun();
}));
<a class="add_img" href="#" data-crm="1" id="add_image">Add Image</a>
Basically I want to access html link set data (i.e. value of dataset crm) in my_fun() without sending parameter to my_fun().
How to access click events html set data in the entire scope of javascript.
javascript.
Global variable in javascript
function my_fun() {
console.log(data.crm);
}
$(document).on('click', '#add_image', (function(e) {
e.preventDefault();
data = $(this).data();
console.log(data.crm);
my_fun();
}));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a class="add_img" href="#" data-crm="1" id="add_image">Add Image</a>
function my_fun(event){
var data = $(event.target).data();
console.log(data.crm);
}
$(document).on('click', '#add_image', my_fun);
or
function my_fun(event){
var data = $(event.target).data();
console.log(data.crm);
}
$(document).on('click', '#add_image', function(e){
my_fun(e);
});
You have to pass a context to your function by call method:
my_fun.call(this);
jsFiddle
There's a limited number of ways to do this. One is to pass arguments to the called function.
Another is to just reference the function, and you'll keep the this value
function my_fun(){
var data = $(this).data();
// this is undefined
console.log(data.crm);
}
$(document).on('click', '#add_image', my_fun);
Lastly, there's bind, apply or call
my_fun.bind(this)();
// or
my_fun.call(this);
// or
my_fun.apply(this, arguments);

how to call the function knockout

var ViewModel = function(){
var self = this;
self.Check = function(){
alert('ok');
}
};
$(function () {
ko.applyBindings(new ViewModel());
});
** how to call a function Check() in normal script from knockout**
Just keep a reference to your view model:
var myVM = new ViewModel();
ko.applyBindings(myVM);
Now you can call the function:
myVM.Check();
But if you want to be able to use it outside the doc ready, you'll need to return it from there and assign it to a variable, or use a global variable.
So you could do something like this:
var myVM = new ViewModel();
$(function() {
ko.applyBindings(myVM);
});
//...
myVM.Check();
If you wanted to use this function as an event handler (for example, to handle a click) you'd do something like this (in HTML):
<a data-bind="click: Check">Click me to check!</a>
For other events, you'd use the event binding.
If you want to bind it to a function do this:
js:
var ViewModel = function(){
var self = this;
self.Check = function(){
return "Ok";
}
};
$(function () {
ko.applyBindings(new ViewModel());
});|
markup
<span data-bind="text:Check()" />
See fiddle:
http://jsfiddle.net/P4bP7/

Javascript .setTimeout() how to refer to a function

I have these codes:
$(function(){
$('.btn').click(function(){
$title = $(this).attr('title');
$.get('getOutput', {}, function(){
// success ajax get
// how to refer again to this function? Doing again the $('.btn').click event
setTimeout(// $('.btn').click(), 100);
});
});
})
I want to repeat the click event of the button. But my main question is, how would you refer the right function or event in setTimeout() ??
You can wrap it into an anonymous function.
setTimeout(function() {
$('.btn').click();
}, 100);
In case you want to trigger the event in the specific element you've clicked before, you'll need to store the current element in a variable since this value inside the anonymous function would be different.
$('.btn').click(function() {
var $el = $(this);
// ...your code...
setTimeout(function() {
$el.click();
}, 100);
});
You could wrap the time out call back in an anonymous function and just real call the click function in there.
setTimeout(function() {
$(".btn").click();
}, 100);
You can bind this inside the anonymous function with $.proxy() to be compatible with IE8 or use .bind() for modern browers.
setTimeout($.proxy(function(){
// this.click(); // if this = $(".btn")
}, this), 100);
To explain it properly:
$(function(){
var btn = $('.btn');
btn.click(function(ev){
var el = $(ev.currentTarget), // same as $(this) but too many "thisses" can be confusing ^^
title = el.prop('title');
$.get('getOutput', {}, function(){
// success ajax get
// how to refer again to this function? Doing again the $('.btn').click event
setTimeout($.proxy(function(){
this.click();
}, el), 100);
});
});
});
Instead of triggering the click event again, you may be better off naming the click event handler function and calling it again from within your setTimeout.
var handleButtonClick = function() {
$title = $(this).attr('title');
$.get('getOutput', {}, function() {
// success ajax get
setTimeout(handleButtonClick , 100);
});
};
$(function() {
$('.btn').click(handleButtonClick);
});

How to get outer element value in JavaScript

I have the following jQuery code:
$('.active #search').on('mouseout', function () {
$('#search_box #search').not('.active').each(function(){
this.value = $('.active #search')[0].value;
})
});
It works, but I have to call $('.active #search') twice. How can I refer to the $('.active #search') array from within my inner function?
P/S: I know I'll be complained about giving multiple elements same ID, but this seem to be generated by Rails automatically (text_field_tag).
I think this is what you're looking for:
$('.active #search').on('mouseout', function () {
var val = $(this)[0].value; //cache value of $('.active #search').
$('#search_box #search').not('.active').each(function () {
this.value = val;
})
});
You can do something like below. I added self = $(this)
$('.active #search').on('mouseout', function () {
var self = $(this);
$('#search_box #search').not('.active').each(function(){
this.value = self[0].value;
});
});
Here is a link to very good explanation of 'this' keyword, explained by Jeffrey Way
tutsplus.com/lesson/the-this-keyword
Therese several ways of achieving this:
var activeSearch = $('.active #search');
activeSearch.on('mouseout', function () {
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.val();
})
});
notice that since this is an id you are querying for you should have only one element so you can replace activeSearch[0].value with activeSearch.val();
second way:
$('.active #search').on('mouseout', function () {
var activeSearch = $(this);
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.val();
})
});
when in an event handler $(this) will give you a jquery object of the event sender. you can further simplify it by ignoring jquery and just using plain elements by doing the following:
$('.active #search').on('mouseout', function () {
var activeSearch = this;
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.value;
})
});
this is the same as above but you arent dealing with jquery objects.
What you end up using depends on you but the final code snippet would be my preferred way.
You can use $(this) instead of using the $('.active #search')

Categories