This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
i have problem that I can't understand:
var Copyright =
{
onLoad: function () {
this.initCopyrightMoving();
},
initCopyrightMoving: function () {
$(".sidebar_toggle").click(function () {
var copyright = document.getElementById("copyright-text");
if (copyright.className == "copyright-menu-open") {
this.decrease(280, 80, 10, copyright);
}
else
copyright.className = "copyright-menu-open"
});
},
decrease: function (actual_val, stop_val, step, copyright) {
setTimeout(function () {
if (actual_val == stop_val) {
copyright.className = "copyright-menu-closed";
}
actual_val = actual_val - step;
copyright.style.paddingLeft = parseInt(actual_val) + "px";
this.decrease(actual_val, stop_val, step, copyright);
}, 10);
}
};
and when I call initCopyrightMoving in line this.decrease(280, 80, 10, copyright);, I get this error:
copyright.js:14 Uncaught TypeError: this.decrease is not a function
at HTMLAnchorElement.<anonymous> (copyright.js:14)
at HTMLAnchorElement.dispatch (jquery-1.11.2.min.js:3)
at HTMLAnchorElement.r.handle (jquery-1.11.2.min.js:3)
can sm tell me what I did wrong? And also because I can't run next part of script can you tell me if decrease function is written good, I mean will it run properly.
this here is element $(".sidebar_toggle") you clicked.
Try defining var self = this; before jQuery handler and call self.decrease inside handler
this.decrease inside setTimeout will also not work for similar reason. Fix is the same
This is because this (context) changes when it's inside the click callback. One way you can stop the error is by preserving a copy of this and using that inside the callback.
initCopyrightMoving: function() {
var _this = this; // some developers use `self`
$(".sidebar_toggle").click(function() {
var copyright = document.getElementById("copyright-text");
if (copyright.className == "copyright-menu-open") {
_this.decrease(280, 80, 10, copyright);
} else {
copyright.className = "copyright-menu-open"
}
});
},
Here's a useful article on scope and context in JavaScript.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
I'm working on a workaround for another problem I'm having but with this I got a "this.setState is not a function" error. I found this answer which advises to bind it within the constructor, which I did.
This is part of my constructor:
this.newProject = this.newProject.bind(this);
this.openProject = this.openProject.bind(this);
this.saveProject = this.saveProject.bind(this);
And this is my function:
// Open a file, set data as session item and reload page
openProject(FileObject) {
var read = new FileReader();
read.readAsBinaryString(FileObject);
read.onloadend = function() {
//sessionStorage.setItem("reloading", "true");
//sessionStorage.setItem("data", read.result);
//document.location.reload();
// Fix for missing data.
var jsonData = JSON.parse(read.result);
for (var i = 0; i < jsonData.blocks.length; i++) {
var name = jsonData.blocks[i].name;
var id = jsonData.blocks[i].id;
var ip = jsonData.blocks[i].ip;
var port = jsonData.blocks[i].port;
this.setState( { blockCount: (i + 1), });
// Add block to the list
this.setState({
blocks: this.state.blocks.concat({
id: id,
name: name,
ref: React.createRef(),
positionX: window.innerWidth*0.4 - 125 / 2,
positionY: 75 + ( 50 * this.state.blocks.length),
links:[],
requires: this.state.parameters.blockRequires
})
});
}
}
}
What would be a solution to this?
this belongs to the closest function context, which in your case is read.onloadend = function()...NOT the class.
You can solve this problem by assigning the class-level this to a new variable before you enter that ad-hoc function:
openProject(FileObject) {
var read = new FileReader();
read.readAsBinaryString(FileObject);
var that = this;
read.onloadend = function() {
// ...
that.setState(/*... etc*/
And of course you'll want to change all instances of this within your onloadend callback function to that (or whatever variable name you choose).
*Edit: as #MDTabishMahfuz describes, you can also use an arrow function, because unlike the function declaration, an arrow function:
Does not have its own bindings to this or super
Binding this is necessary for functions of the class but you have an additional callback (onloadend function) which is a different function and the component's this is not available there.
Conventional Functions in JS have their on this in their context. You can either use the method suggested by #David784 or use an arrow function for the onloadend handler like so:
read.onloadend = () => {
....
this.setState(....);
....
}
Arrow functions have this from the parent's context, that is the React component in your case.
This question already has answers here:
"this" keyword in event methods when using JavaScript prototype object
(4 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
If a function inside an event listener is called, say for instance, window.load, are all other functions inside said function expected to be ran on load as well? I have an issue with a function being called on window load and that function calling another function. At the last step I want to add an event listener to watch for form submission. However the listener function has no access to the the variables called from the original load listener function.
var Handler = {
ajaxURL: null,
domIDs : null,
httpRequest : null,
init: function(config) {
this.httpRequest = {};
this.initConfig(config);
this.setLoadHandler();
},
initialize: function() {
this.initializeDocumentNodes();
},
setLoadHandler: function(){
var self = this;
this.addEvent(window,'load', function() {
self.initialize();
});
},
initializeDocumentNodes: function() {
this.dom = {};
for(var key in this.domIDs) {
this.dom[key] = document.getElementById(this.domIDs[key]);
}
this.dom['loginForm'].addEventListener("submit", function(ev) {
ev.preventDefault();
console.log(this.dom['userNameLoginInput']);
console.log(this.dom['passwordLoginInput']);
});
},
this.dom is undefined inside the form submit listener.
this.dom['loginForm'].addEventListener("submit", function(ev) {
ev.preventDefault();
console.log(this.dom['userNameLoginInput']);
console.log(this.dom['passwordLoginInput']);
});
Could someone please help me to understand this? Thank you so much.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I'll explain my issue using an example:
I have an object which is called 'ExampleObj' which returns 3 property 'init', 'age', 'weight' and I need to access from age to weight but for some reason i can't do that. Could you explain me why and how can I achieve the correct result?
EDIT: this is the current code, self.tabAnimation() is working on dom ready but... is not working on "click", even if I use (); check the **** in the code, is the line which triggers me error.
return {
init: function() {
var self = this;
tabs.init();
self.tabAnimation();
tabToggler.on('click', self.tabAnimation );
},
tabAnimation: function() {
var self = this;
var activeTabBars = function() {
console.log('lol');
tabItem.find(bars).each(function() {
var me = this;
****self.animateBars(me,1000)****
});
}
animateOnVisible.init(tabItem, activeTabBars);
},
animateBars : function(el, duration) {
var percentage = $(el).data('value') + "%";
$(el).animate({
'width': percentage
}, duration);
}
}
}
Thank you very much
Davide
You have to use this:
age: function() {
console.log('some random log');
var me = this;
me.weight;
me.weight(something);
},
You don't have to assign this to another variable, but it doesn't hurt anything if you do.
Note that in your "init" function,
self.age;
by itself will do nothing. To call the function, you have to write it
self.age();
I am working on a script and everythink worked fine, until a few days ago. I have an object, created with function(), where I work with several methods.
To access properties inside the object, I use the this keyword and that works fine.
As example:
var SeralCore = SeralCore || function ()
{
this.initSeral();
return this;
};
SeralCore.prototype = {
page = null;
initSeral = function ()
{
alert(this.page);
}
}
Full code: http://pastebin.com/81Zn9276
jsFiddle example: https://jsfiddle.net/g2ahu6ob/10/
When I have an event, where a callback is fired and I have to access the property page, I used the following, because I can't use this anymore:
$('.button').click(function () {
SeralCore.page = 'Some value';
});
This worked well, but suddenly there is an error saying I cannot reach an property (or object, in my case*) used like in the exameple above. The output is undefined.
I decided to investigate what the output would be if I log SeralCore. Surprisingly, it says the following:
As you can see, there is a < at the end of SeralCore, which doesn't belong there.
Is this normal? And is this the cause of not being able to access properties using the "full name" (SeralCore.page)? If so, is there a way to fix it?
Many, many thanks in advance because I can't figure out what I am doing wrong.
Snippet:
var SeralCore = SeralCore || function () {
this.initSeral();
return this;
};
window.onload = function () {
this.SeralCore = new SeralCore();
};
SeralCore.prototype = {
page: 'Page',
initSeral: function ()
{
this.registerPage.start();
},
registerPage: {
start: function ()
{
$('.output').text(typeof SeralCore.page + ' (Should show \'String\' when it can read SeralCore.page)');
}
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="output"></span>
I need to know what I am doing wrong because I cannot call the internal functions show or hide?
(function()
{
var Fresh = {
notify:function()
{
var timeout = 20000;
$("#notify-container div").get(0).id.substr(7,1) == "1" && (show(),setTimeout(hide(),timeout));
var show = function ()
{
$("body").animate({marginTop: "2.5em"}, "fast", "linear");
$("#notify-container div:eq(0)").fadeIn("slow");
},
hide = function()
{
$("#notify-container div").hide();
}
}//END notify
}
window.Fresh = Fresh;
})();
Fresh.notify();
thanks, Richard
UPDATE
If you wanted to be able to do something like: Fresh.notify.showMessage(), all you need to do is assign a property to the function notify:
var Fresh = {notify:function(){return 'notify called';}};
Fresh.notify.showMessage = function () { return this() + ' and showMessage, too!';};
Fresh.notify();//notify called
Fresh.notify.showMessage();//notify called and showMessage, too!
This will point to the function object here, and can be called as such (this() === Fresh.notify();). That's all there is too it.
There's a number of issues with this code. First of all: it's great that you're trying to use closures. But you're not using them to the fullest, if you don't mind my saying. For example: the notify method is packed with function declarations and jQuery selectors. This means that each time the method is invoked, new function objects will be created and the selectors will cause the dom to be searched time and time again. It's better to just keep the functions and the dom elements referenced in the closure scope:
(function()
{
var body = $("body");
var notifyDiv = $("#notify-container div")[0];
var notifyDivEq0 = $("#notify-container div:eq(0)");
var show = function ()
{
body.animate({marginTop: "2.5em"}, "fast", "linear");
notifyDivEq0.fadeIn("slow");
};
var hide = function()
{//notifyDiv is not a jQ object, just pass it to jQ again:
$(notifyDiv).hide();
};
var timeout = 20000;
var Fresh = {
notify:function()
{
//this doesn't really make sense to me...
//notifyDiv.id.substr(7,1) == "1" && (show(),setTimeout(hide,timeout));
//I think this is what you want:
if (notifyDiv.id.charAt(6) === '1')
{
show();
setTimeout(hide,timeout);//pass function reference
//setTimeout(hide(),timeout); calls return value of hide, which is undefined here
}
}//END notify
}
window.Fresh = Fresh;
})();
Fresh.notify();
It's hard to make suggestions in this case, though because, on its own, this code doesn't really make much sense. I'd suggest you set up a fiddle so we can see the code at work (or see the code fail :P)
First, you're trying to use show value when it's not defined yet (though show variable does exist in that scope):
function test() {
show(); // TypeError: show is not a function
var show = function() { console.log(42); };
}
It's easily fixable with moving var show line above the point where it'll be called:
function test() {
var show = function() { console.log(42); };
show();
}
test(); // 42
... or if you define functions in more 'traditional' way (with function show() { ... } notation).
function test() {
show();
function show() { console.log(42); };
}
test(); // 42
Second, you should use this instead:
... && (show(), setTimeout(hide, timeout) );
... as it's the function name, and not the function result, that should be passed to setTimeout as the first argument.
You have to define show and hide before, also change the hide() as they said.
The result will be something like this:
(function()
{
var Fresh = {
notify:function()
{
var show = function()
{
$("body").animate({marginTop: "2.5em"}, "fast", "linear");
$("#notify-container div:eq(0)").fadeIn("slow");
},
hide = function()
{
$("#notify-container div").hide();
},
timeout = 20000;
$("#notify-container div").get(0).id.substr(7,1) == "1" && ( show(), setTimeout(hide,timeout) );
}//END notify
}
window.Fresh = Fresh;
})();
Fresh.notify();
I think order of calling show , hide is the matter . I have modified your code . It works fine . Please visit the link
http://jsfiddle.net/dzZe3/1/
the
(show(),setTimeout(hide(),timeout));
needs to at least be
(show(),setTimeout(function() {hide()},timeout));
or
(show(),setTimeout(hide,timeout));