using objects to get position (x, y) - Javascript - javascript

this code works:
var myElement = document.getElementById("red");
setInterval(function() {
console.log("Left:" + myElement.offsetLeft + "px | Top:" + myElement.offsetTop + "px");
}, 1000);
This prints out the position(x, y) every second
But If I try and change it to using objects:
function Enemy(id){
this.id = getElementById(id);
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + this.id.offsetLeft + "px | Top:" + this.id.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});
It prints out nothing - and I can't see where my mistake is.

In a setInterval or setTimeout (or any event handler like onclick) the this variable refers to the global object. In a browser that's window.
In modern browsers you can do this:
setInterval((function() {
console.log("Left:" + that.id.offsetLeft + "px");
}).bind(this), 1000); // <------- bind
Otherwise all other solutions are basically similar to your first piece of code.
Note that there is an implementation of bind() in pure js from Mozilla that can be ported to older browsers. Search for it on MDN.

The problem is that the value of "this" is changing within the setInterval. The fix is to change it to:
function Enemy(id){
this.id = document.getElementById(id);
var self = this;
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + self.id.offsetLeft + "px | Top:" + self.id.offsetTop + "px");
}, 1000);
}
}

function Enemy(id){
this.id = document.getElementById(id);
this.getCoordinates = function(){
var element = this.id;
setInterval(function() {
console.log("Left:" + element.offsetLeft + "px | Top:" + element.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});

As slebetman said, the 'this' variable is not what you expected. Try saving it in a 'that' variable, which can be accessed in different scopes.
function Enemy(id){
var that = this; // reference to 'this' that can be used in other scopes
that.id = document.getElementById(id);
that.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + that.id.offsetLeft + "px | Top:" + that.id.offsetTop + "px");
}, 1000);
}
return that;
}

Related

change java script anchor scroll to look for array object

I have some JavaScript that currently looks for _target and anchors to target.
I wish to change it to look for a array [_target_index] however I cant seem to get this to work every time I try I get errors.
When I console.log my array I get my expected array output.
Can someone help me addend y code to accept the array rather than just _target ?
What I tried
_scrollTopPixels = (anchorElementArray [_target_index]).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
console error
Uncaught TypeError: anchorElementArray[_target_index].offset is not a function
My full code
_pdpNavigationScrollTo = function () {
_pdpLink.on('click', function (e) {
e.preventDefault();
var _fixedNavHeight, _target, _target_index, _scrollTopPixels;
if (!INFORMA.global.device.isDesktop) {
_target = $(this).data('target');
_target_index = $(this).data('target-index');
$('#pdp-sections').slideUp();
_pdpNavigationHeight = $('#pdp-navigation .nav-pdp-nondesktop').outerHeight();
if (!_pdpFixed)
_pdpSectionsHeight = $('#pdp-sections').height();
else
_pdpSectionsHeight = 0;
_fixedNavHeight = _navHeightMobile;
var anchorElementArray = $("[id='" + _target + "']");
console.log(anchorElementArray[_target_index]);
if (anchorElementArray.length >= [_target_index]) {
//_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
_scrollTopPixels = (anchorElementArray [_target_index]).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
} else {
_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight + _pdpSectionsHeight);
}
$('html, body').stop().animate({
scrollTop: _scrollTopPixels
}, 1000);
} else {
_target = $(this).data('target');
$('#pdp-navigation li').removeClass('selected');
$('#pdp-navigation li').addClass('select-options');
_pdpNavigationHeight = _pdpNavigation.height();
_fixedNavHeight = _navHeight;
_scrollTopPixels = $("#" + _target).offset().top - (_fixedNavHeight + _pdpNavigationHeight);
$('html, body').stop().animate({
scrollTop: _scrollTopPixels
}, 1000);
}
})
};
The jQuery method offset requires a jQuery object to access it, as such you need to change;
(anchorElementArray[_target_index]).offset().top
to
$(anchorElementArray[_target_index]).offset().top

.replace in eval with dynamic variables in javascript?

I've been trying to fix this for hours now and just can't get it to work. I'm retrieving the name of every activity in the database and for every row it recreates this script with the correct data.
<script>var count = 1;</script>
#foreach($data as $scriptdata)
<script>
eval("var id" + count + " = '{{$scriptdata->activiteit}}';");
eval("var clas" + count + " = '{{$scriptdata->activiteit}}';");
eval("var id" + count + " = id" + count .replace(/[^a-zA-Z]/g, '') + ";");
eval("var clas" + count + " = clas" + count .replace(/[^a-zA-Z]/g, '') + ";");
$("#" + id1).mouseenter(function(event) {
console.log("clicked.");
var target = $('.' + clas1);
if( target.length ) {
$('html, body').animate({
scrollTop: target.offset().top-120
}, 1000);
}
});
count++
</script>
#endforeach
the variables become dynamic without any trouble, I just can't get that .replace to do it's job.
anyone?:p
Either output the variables from the serverside code, use Objects with bracket notation, use common classes so there is no need to have individual selections, or make it so the variables are not in global scope.
Make it so the variable are not in global scope
(function() {
var id = '{{$scriptdata->activiteit}}';
var clas = '{{$scriptdata->activiteit}}';
$("#" + id).mouseenter(function(event) {
var target = $('.' + clas);
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top - 120
}, 1000);
}
});
}());
Now you do not have to worry about count.

How to access jquery taphold inside other function

I have a canvas with objects inside and have a event handler for object:selected. When I select the object, a div (vtover) appears at the mouse/touch pointer by pageX and pageY.
What I want to accomplish is to change the event handler from click to touch taphold using jQuery Mobile. I tried to put all code inside my taphold, but that didnt work.
How can I solve this?
chartdiv is the id of my canvas container
Code
canvas.observe("object:selected", function (e) {
$("#chartdiv").on("taphold", function (a) {
// tried to put below code inside this, but this didnt work out.
});
var obj = e.target;
$("#vtover").show();
$("#vtover").offset({
left: event.pageX,
top: event.pageY - 200
});
$("#vt_vol").val(myvol.toLocaleString("de-DE") + " " + unit);
$("#vt_period").val(myper + " Tage");
$("#vt_sump").val(sumper.toLocaleString("de-DE") + " " + unit);
$("#vt_diffp").val(Math.round((myvol * myper / sumper) * 100) + " %");
});
You can't do that, at least not like that, this should work:
var canvasHandler = {
obj : null
}
canvas.observe("object:selected", function (e) {
canvasHandler.obj = e.target;
});
$(document).on("taphold", "#chartdiv",function (a) {
// Now if you need selected canvas just use canvasHandler.obj
$("#vtover").show();
$("#vtover").offset({
left: event.pageX,
top: event.pageY - 200
});
$("#vt_vol").val(myvol.toLocaleString("de-DE") + " " + unit);
$("#vt_period").val(myper + " Tage");
$("#vt_sump").val(sumper.toLocaleString("de-DE") + " " + unit);
$("#vt_diffp").val(Math.round((myvol * myper / sumper) * 100) + " %");
});

Javascript - Count the number of instances of a particular string from a variable

I am having trouble getting my code to count the number of times the word 'Yes' appears in a variable. It works if I replace the variable with the string 'YesYesYes.' The result is 3. I want to do the same, but from a variable instead.
Here is my code.
function getAllAnswers() {
var var_allAnswers = document.querySelector('input[name="Q1"]:checked').value + document.querySelector('input[name="Q2"]:checked').value + document.querySelector('input[name="Q3"]:checked').value + document.querySelector('input[name="Q4"]:checked').value + document.querySelector('input[name="Q5"]:checked').value + document.querySelector('input[name="Q6"]:checked').value + document.querySelector('input[name="Q7"]:checked').value + document.querySelector('input[name="Q8"]:checked').value + document.querySelector('input[name="Q9"]:checked').value + document.querySelector('input[name="Q10"]:checked').value + document.querySelector('input[name="Q11"]:checked').value + document.querySelector('input[name="Q12"]:checked').value + document.querySelector('input[name="Q13"]:checked').value + document.querySelector('input[name="Q14"]:checked').value + document.querySelector('input[name="Q15"]:checked').value + document.querySelector('input[name="Q16"]:checked').value + document.querySelector('input[name="Q17"]:checked').value + document.querySelector('input[name="Q18"]:checked').value + document.querySelector('input[name="Q19"]:checked').value + document.querySelector('input[name="Q20"]:checked').value;
document.getElementById("AllAnswers").innerHTML = var_allAnswers;
}
function yesCount() {
var var_yesCount = var_allAnswers.split("Yes").length - 1;
document.getElementById("YesCount").innerHTML = var_yesCount;
}
function noCount() {
var var_noCount = var_allAnswers.split("No").length - 1;
document.getElementById("NoCount").innerHTML = var_noCount;
}
Here is my markup.
<button onclick="yesCount()">Yes Count</button><br/>
Yes Count: <p id="YesCount"></p><br/><br/>
<button onclick="noCount()">No Count</button><br/>
No Count: <p id="NoCount"></p><br/><br/>
All Answers: <p id="AllAnswers"></p><br/><br/>
Does anyone have any ideas?
The variable var_allAnswers called in the yesCount and noCount functions is out of scope, meaning it's inaccessible to your functions. A somewhat hackish fix:
(function()
{
var var_allAnswers;
function getAllAnswers() {
var_allAnswers = document.querySelector('input[name="Q1"]:checked').value + document.querySelector('input[name="Q2"]:checked').value + document.querySelector('input[name="Q3"]:checked').value + document.querySelector('input[name="Q4"]:checked').value + document.querySelector('input[name="Q5"]:checked').value + document.querySelector('input[name="Q6"]:checked').value + document.querySelector('input[name="Q7"]:checked').value + document.querySelector('input[name="Q8"]:checked').value + document.querySelector('input[name="Q9"]:checked').value + document.querySelector('input[name="Q10"]:checked').value + document.querySelector('input[name="Q11"]:checked').value + document.querySelector('input[name="Q12"]:checked').value + document.querySelector('input[name="Q13"]:checked').value + document.querySelector('input[name="Q14"]:checked').value + document.querySelector('input[name="Q15"]:checked').value + document.querySelector('input[name="Q16"]:checked').value + document.querySelector('input[name="Q17"]:checked').value + document.querySelector('input[name="Q18"]:checked').value + document.querySelector('input[name="Q19"]:checked').value + document.querySelector('input[name="Q20"]:checked').value;
document.getElementById("AllAnswers").innerHTML = var_allAnswers;
}
function yesCount() {
var var_yesCount = var_allAnswers.split("Yes").length - 1;
document.getElementById("YesCount").innerHTML = var_yesCount;
}
function noCount() {
var var_noCount = var_allAnswers.split("No").length - 1;
document.getElementById("NoCount").innerHTML = var_noCount;
}
})();
Though you should really be passing the var_allAnswers variable around in your function calls as an argument.
The local variable var_allAnswers you declared in getAllAnswers() can't be used in another function, instead you shoud declare your variable as Global or create a function that returns the variable to deal with. Ex:
var var_allAnswers;
function getAllAnswers() {
var_allAnswers = document.querySelector('...
document.getElementById("AllAnswers").innerHTML = var_allAnswers;
}
getAllAnswers();
It appears you have a problem of scope here.
A var defines a varable which is available only in the block containing it { }
So, when you exit getAllAnswers() your variable var_allAnswers is discarded.
You need to reinitialize it before you could reuse it
function yesCount() {
var_allAnswers = document.querySelector('input[name="Q1"]:checked').value
var var_yesCount = var_allAnswers.split("Yes").length - 1 ;
document.getElementById("YesCount").innerHTML = var_yesCount;
}
I also think it's a problem of scope. In the yesCount() and noCount() functions, the variable var_allAnswers cannot be referred. Marcel's answer is right.
You may want to learn about the block scope in javascript. Here is an article about that:
http://danbeam.org/blog/2011/05/23/turns-out-there-is-block-scope-in-javascript-kinda/

Javascript Argument

I type in scroll(0,10,200,10);
But when it runs it passes the string "xxpos" or "yypos" and I did try it without the appostraphes, but it just didn't work.
scroll = function(xpos,ypos,time,rounds){
var xxpos = xpos*1;
var yypos = ypos*1;
var rrounds = rounds*1;
var ttime = time*1;
x = 0;
xyz=window.setInterval("scroller('xxpos','yypos','ttime','rrounds')",ttime);
}
function scroller(xpos,ypos,time,rounds){
alert(xpos + ypos + time + rounds);
}
Don't use strings, use closures (anonymous functions).
window.setTimeout(function() {
scroller(xxpos, yypos, ttime, rrounds);
}, ttime);
It should be like this:
xyz=window.setInterval("scroller(" + xxpos + "," + yypos + "...
otherwise you just pass strings xxpos, yypos etc.
do you happen to know that in your code, each call to scroll() builds a timer?
do you mean to do it like it was a loop? then:
xyz = window.setTimeout(function(){
scroller(xxpos,yypos,ttime,rrounds)
},ttime);
You should use closure:
...
xyz = window.setInterval(function() { scroller(xxpos,yypos,ttime,rrounds); }, ttime);
...
That's because the string does not become the variable.
This would work:
window.setInterval("scroller("+ xxpos + "," + yypos + "," + ttime + "," + rrounds + ")",ttime);
Or better:
window.setInterval(function() { scroller(xxpos, yypos, ttime, rrounds); }, ttime);

Categories