Calling functions from within functions JS - javascript

I'm writing a small battleships game, and I'm refactoring my code using Javascript Objects, a tool that I am not very familiar with. I would like to be able to call a function from within a function using objects, and I cannot seem to work out how to do this. The code is here:
<script>
var xPos;
var yPos;
var boatGrid = {
selectPos : function() {
console.log("it works"); //want to try calling function addNumber() here
for (boatNum = 1; boatNum < 4; boatNum++) {
xPos = Math.floor(Math.random() * 8);
yPos = Math.floor(Math.random() * 10 + 1);
}
},
buildBoat : function() {
console.log("this works too");
for (boatLen = 1; boatLen < 4; boatLen++) {
xPos = xPos++;
boatPos = "cell_" + xPos + "_" + yPos;
}
},
addNumber : function() {
document.getElementById("test2").innerHTML = "hello"; //debug line
}
}
The addNum() function is there as a debug.

You are almost there.
In your case boatGrid is an object and addNumber is one of it's method. so use this.addNumber()
var xPos;
var yPos;
var boatGrid = {
selectPos : function() {
console.log("it works"); //want to try calling function addNumber() here
this.addNumber(); // Changed here
for (boatNum = 1; boatNum < 4; boatNum++) {
xPos = Math.floor(Math.random() * 8);
yPos = Math.floor(Math.random() * 10 + 1);
}
},
buildBoat : function() {
console.log("this works too");
for (boatLen = 1; boatLen < 4; boatLen++) {
xPos = xPos++;
boatPos = "cell_" + xPos + "_" + yPos;
}
},
addNumber : function() {
//document.getElementById("test2").innerHTML = "hello"; //debug line
document.write('<pre>Add Number called</pre>')
}
}
boatGrid.selectPos();
jsfiddle

Use
this.addNumber();
Your code should look like this
selectPos : function() {
console.log("it works");
this.addNumber(); //want to try calling function addNumber() here
for (boatNum = 1; boatNum < 4; boatNum++) {
xPos = Math.floor(Math.random() * 8);
yPos = Math.floor(Math.random() * 10 + 1);
}
},

If you want to call boatGrid.selectPos() and call the addNumber function within the selectPos function, just add this.addNumber(); within the selectPos function.
selectPos : function() {
console.log("it works");
this.addNumber(); // <---- boatGrid calls addNumber()
for (boatNum = 1; boatNum < 4; boatNum++) {
xPos = Math.floor(Math.random() * 8);
yPos = Math.floor(Math.random() * 10 + 1);
}
}
When used within an object function, this refers to the object calling the function.
So to go with my original example, boatGrid calls selectPos, so this within the selectPos function refers to boatGrid.
So then this.addNumber() will have that boatGrid object call its addNumber function.

Related

A function inside javascript if condition is not getting called

I am new to Js and trying to develop program which can move object in zig zag format across canvas, i wrote this function but it not getting called when i run program. If anyone can check out my code it would be really helpful, thanks also like to mention that all previous functions in code are working fine but this specific function is not getting called program run until If condition but skip the function part. Also i am not looking to work with Jquery or CSS right now
if (rightPos) {
function myInterval3() {
console.log('hello');
var eLeftPos1 = e.offsetLeft;
//console.log(e.offsetLeft);
e.style.left = (eLeftPos1 + s) + 'px';
//console.log(e.style.left);
}
}
var e = document.getElementById("aDiv");
var s = 1;
function myInterval() {
var eLeftPos = e.offsetLeft;
//console.log(e.offsetLeft);
e.style.left = (eLeftPos + s) + 'px';
//console.log(e.style.left);
leftPos = (eLeftPos + s) >= 300
if (leftPos) {
function myInterval1() {
console.log(leftPos)
var eTopPos = e.offsetTop;
//console.log(e.offsetLeft);
e.style.top = (eTopPos + s) + 'px';
//console.log(e.style.top);
topPos = (eTopPos + s) >= 100
if (topPos) {
clearInterval(internal1)
}
if (topPos) {
function myInterval2() {
var eRightPos = e.offsetLeft;
//console.log(eRightPos)
e.style.left = (eRightPos - 9) + 'px'
/*console.log(e.style.left)*/
rightPos = (eRightPos - 9) <= 20
if (rightPos) {
clearInterval(interal2)
}
}
var interal2 = setInterval(myInterval2, 10)
}
}
var internal1 = setInterval(myInterval1, 100);
if (rightPos) {
function myInterval3() {
console.log('hello');
var eLeftPos1 = e.offsetLeft;
//console.log(e.offsetLeft);
e.style.left = (eLeftPos1 + s) + 'px';
//console.log(e.style.left);
}
}
}
if ((eLeftPos + s) >= 300) {
clearInterval(internal)
}
}
var internal = setInterval(myInterval, 100);
You've defined a function named myInterval3, but you're not calling it. When you write
function myInterval3() { ... }
That defines a function named myInterval3, but that's all that it does. To actually have the code inside the function run, you need to call it.
myInterval3()
To have the function called on a repeating interval, use setInterval (like you have for your other functions:
setInterval(myInterval3, 100)

Bind event listener from outside function

How can I from the outside of my init function, fire off the reset function within init.
I want my reset function to reset all variables set from the collection of the images (3 in this case) which is bound 3 times. My example here isn't working I'm aware.
Here's my code:
document.getElementsByClassName('zoomer-start')[0].addEventListener('click', init);
document.getElementsByClassName('zoomer-reset')[0].addEventListener('click', reset);
function init() {
var images = document.querySelectorAll('.zoomer-img');
for (var i = 0; i < images.length; i++) {
(function() {
var image = images[i];
var zoomer = new Hammer(image);
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
var clicked = false;
var adjustScale = 1;
var adjustDeltaX = 0;
var adjustDeltaY = 0;
var currentScale = null;
var currentDeltaX = null;
var currentDeltaY = null;
zoomer.on('tap', function (e) {
if (!clicked) {
zoomer.get('pinch').set({enable: true});
zoomer.get('pan').set({enable: true, direction: Hammer.DIRECTION_ALL});
clicked = true;
} else {
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
clicked = false;
}
if (currentScale > 1) {
adjustScale = 1;
adjustDeltaX = 0;
adjustDeltaY = 0;
} else {
adjustScale = 2;
}
currentScale = adjustScale * e.scale;
currentDeltaX = adjustDeltaX + (e.deltaX / currentScale);
currentDeltaY = adjustDeltaY + (e.deltaY / currentScale);
image.style.transform = 'scale(' + currentScale + ') translate3d(' + currentDeltaX + 'px, ' + currentDeltaY + 'px, 0)';
});
zoomer.on('pan pinch', function (e) {
currentScale = Math.max(1, Math.min(adjustScale * e.scale, 4));
currentDeltaX = adjustDeltaX + (e.deltaX / currentScale);
currentDeltaY = adjustDeltaY + (e.deltaY / currentScale);
var scaledX = ((((image.width * currentScale) / 2) - (image.width / 2)) / currentScale);
if (currentDeltaX > scaledX)
currentDeltaX = scaledX;
if (currentDeltaX < -scaledX)
currentDeltaX = -scaledX;
var scaledY = ((((image.height * currentScale) / 2) - (image.height / 2)) / currentScale);
if (currentDeltaY > scaledY)
currentDeltaY = scaledY;
if (currentDeltaY < -scaledY)
currentDeltaY = -scaledY;
image.style.transform = 'scale(' + currentScale + ') translate3d(' + currentDeltaX + 'px, ' + currentDeltaY + 'px, 0)';
});
zoomer.on('panend pinchend', function () {
adjustScale = currentScale;
adjustDeltaX = currentDeltaX;
adjustDeltaY = currentDeltaY;
});
function reset() {
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
clicked = false;
adjustScale = 1;
adjustDeltaX = 0;
adjustDeltaY = 0;
currentScale = null;
currentDeltaX = null;
currentDeltaY = null;
image.style.transform = 'scale(' + 1 + ') translate3d(' + 0 + 'px, ' + 0 + 'px, 0)';
}
})();
}
}
To call function(s) from withinn scope you have to pass it somehow to the surronding scope. One possible example for Your code:
var resets = [];
function init() {
[...]
for (var i = 0; i < images.length; i++) {
(function() {
[...]
resets[i]=function reset() {
[...]
})
And then call them naively:
resets[0](); resets[1](); resets[2];
Or via:
resets.forEach(function(f) { f(); } );
Having your functions inside the init function gives them Private SCOPE only (can only be accessed from within the init function) To give them global scope you will have to move them outside of the init function which will require some code restructuring.
With the code as written, you can't. The reset function is entirely private to the code in the anonymous function inside init. Even other code in init can't access it, much less code outside init.
I say "it" above, but really, you have multiple reset functions, one for each image.
You could, of course, move your code trying to use it as a click handler into that anonymous function inside init. That's basically your only real option, other than creating an array or similar of reset functions that you expose outside init.
Thanks guys, I learned something today! Here's my working example. Really really neat:
var resets = [];
document.getElementsByClassName('zoomer-start')[0].addEventListener('click', init);
document.getElementsByClassName('zoomer-reset')[0].addEventListener('click', function () {
var images = document.querySelectorAll('.zoomer-img');
for (var i = 0; i < images.length; i++) {
resets[i]();
}
});
function init() {
var images = document.querySelectorAll('.zoomer-img');
for (var i = 0; i < images.length; i++) {
(function(i) {
var image = images[i];
var zoomer = new Hammer(image);
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
var clicked = false;
var adjustScale = 1;
var adjustDeltaX = 0;
var adjustDeltaY = 0;
var currentScale = null;
var currentDeltaX = null;
var currentDeltaY = null;
zoomer.on('tap', function (e) {
if (!clicked) {
zoomer.get('pinch').set({enable: true});
zoomer.get('pan').set({enable: true, direction: Hammer.DIRECTION_ALL});
clicked = true;
} else {
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
clicked = false;
}
if (currentScale > 1) {
adjustScale = 1;
adjustDeltaX = 0;
adjustDeltaY = 0;
} else {
adjustScale = 2;
}
currentScale = adjustScale * e.scale;
currentDeltaX = adjustDeltaX + (e.deltaX / currentScale);
currentDeltaY = adjustDeltaY + (e.deltaY / currentScale);
image.style.transform = 'scale(' + currentScale + ') translate3d(' + currentDeltaX + 'px, ' + currentDeltaY + 'px, 0)';
});
zoomer.on('pan pinch', function (e) {
currentScale = Math.max(1, Math.min(adjustScale * e.scale, 4));
currentDeltaX = adjustDeltaX + (e.deltaX / currentScale);
currentDeltaY = adjustDeltaY + (e.deltaY / currentScale);
var scaledX = ((((image.width * currentScale) / 2) - (image.width / 2)) / currentScale);
if (currentDeltaX > scaledX)
currentDeltaX = scaledX;
if (currentDeltaX < -scaledX)
currentDeltaX = -scaledX;
var scaledY = ((((image.height * currentScale) / 2) - (image.height / 2)) / currentScale);
if (currentDeltaY > scaledY)
currentDeltaY = scaledY;
if (currentDeltaY < -scaledY)
currentDeltaY = -scaledY;
image.style.transform = 'scale(' + currentScale + ') translate3d(' + currentDeltaX + 'px, ' + currentDeltaY + 'px, 0)';
});
zoomer.on('panend pinchend', function () {
adjustScale = currentScale;
adjustDeltaX = currentDeltaX;
adjustDeltaY = currentDeltaY;
});
resets[i] = function reset() {
zoomer.get('pinch').set({enable: false});
zoomer.get('pan').set({enable: false});
clicked = false;
adjustScale = 1;
adjustDeltaX = 0;
adjustDeltaY = 0;
currentScale = null;
currentDeltaX = null;
currentDeltaY = null;
image.style.transform = 'scale(' + 1 + ') translate3d(' + 0 + 'px, ' + 0 + 'px, 0)';
}
})(i);
}
}

Stop function on dialog open

have a question for you. I am loading a function that I want to stop once they click the sprite, which in turn opens a dialog.
How can I do this?
My jQuery to make a image pop up in specific coordinates:
(function fadeInDiv(){
var divs = $('#showSprite');
var fadeInTime = Math.floor(Math.random()*(3000-1000+1)+1000);
var fadeOutTime = Math.floor(Math.random()*(5000-1000+1)+1000);
var timeThere = Math.floor(Math.random()*(50-25+1)+25);
var elem = divs.eq(Math.floor(Math.random()*divs.length));
var whichCord = Math.floor(Math.random()*(6-1+1)+1);
var arrayDictionary = {
ary1: ["39","141"],
ary2: ["85","27"],
ary3: ["215","166"],
ary4: ["351","13"],
ary5: ["389","168"],
ary6: ["486","32"],
ary7: ["576","150"]
};
if (!elem.is(':visible')) {){
elem.fadeIn(Math.floor(Math.random()*fadeInTime),fadeInDiv);
elem.css({
'position':'absolute',
'left':arrayDictionary["ary"+whichCord][0]+'px',
'top':arrayDictionary["ary"+whichCord][1]+'px'
});
}
else {
elem.fadeOut(Math.floor(Math.random()*fadeOutTime),fadeInDiv)
.delay(timeThere);
}
})();
and my dialog:
$('#clickedSprite').dialog({
autoOpen: false,
title: 'What Do We Have Here?'
});
$('#sprite').click(function() {
var palID = $(this).attr('palID');
var petID = $(this).attr('petID');
var securePass = $(this).attr('securePass');
var timePassed = new Date().getTime() / 1000;
$.cookie("hashing", securePass);
$.cookie("timePassed", Math.round(timePassed));
$('#clickedSprite').dialog('open');
return false;
});
Use !$(".ui-dialog").length to check that there are no dialogs:
(function fadeInDiv() {
if(!$(".ui-dialog").length){
var divs = $('#showSprite');
var fadeInTime = Math.floor(Math.random() * (3000 - 1000 + 1) + 1000);
var fadeOutTime = Math.floor(Math.random() * (5000 - 1000 + 1) + 1000);
var timeThere = Math.floor(Math.random() * (50 - 25 + 1) + 25);
var elem = divs.eq(Math.floor(Math.random() * divs.length));
var whichCord = Math.floor(Math.random() * (6 - 1 + 1) + 1);
var arrayDictionary = {
ary1: ["39", "141"],
ary2: ["85", "27"],
ary3: ["215", "166"],
ary4: ["351", "13"],
ary5: ["389", "168"],
ary6: ["486", "32"],
ary7: ["576", "150"]
};
if (!elem.is(':visible')) {) {
elem.fadeIn(Math.floor(Math.random() * fadeInTime), fadeInDiv);
elem.css({
'position': 'absolute',
'left': arrayDictionary["ary" + whichCord][0] + 'px',
'top': arrayDictionary["ary" + whichCord][1] + 'px'
});
} else {
elem.fadeOut(Math.floor(Math.random() * fadeOutTime), fadeInDiv)
.delay(timeThere);
}
}
})();

Running a function for each element

I am using the Peity js plugin to create donut charts on my page. I am trying to animate the chart for each of the .foo elements:
<span class="foo" data-value="10"></span>
$('.foo').each(function () {
var updateChart = $(this).peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $(this).data("value");
if (i <= maxValue) myLoop();
}, 0.5)
}
myLoop();
});
However it won't work for some reason with no errors in console. If I remove the $('.foo').each(function () { ... } part (and all "this" instances) the code will work. Thanks in advance for any help.
The problem is the context inside the timer handler, the easiest fix here is to use a closure variable
$('.foo').each(function () {
var $this = $(this);
var updateChart = $this.peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $this.data("value");
if (i <= maxValue) myLoop();
}, 0.5)
}
myLoop();
});
When the timeout callback is executed, the this context refer to window, because you are actually calling window.setTimeout method.
Try this:
$('.foo').each(function () {
var updateChart = $(this).peity('donut');
var text = "";
var i = 0;
function myLoop() {
setTimeout($.proxy(function () {
text = i + "/12";
updateChart.text(text)
.change()
i = i + 0.2;
var maxValue = $(this).data("value");
if (i <= maxValue) myLoop();
},this), 0.5)
}
myLoop();
});

Image not switching on hover

Trying to get this image to scroll through images on hover but its not work. Live demo at: http://codepen.io/bskousen/pen/Ksphr
Using jquery
script:
$(document).ready(function() {
$('.imageBox').hover(startScroll, stopScroll);
});
var scrollInterval;
var i = 2;
function startScroll() {
scrollInterval = setInterval(scrollImages(this), 100);
}
function stopScroll() {
i = 2;
$(this).children('img').fadeOut();
$(this).children('img:nth-child(1)').fadeIn();
clearInterval(scrollInterval);
}
function scrollImages(x) {
$('#count').append('running' + i + ' ');
var imageCount = $(x).children('img').length;
$(x).children('img').fadeOut();
$(x).children('img:nth-child(' + i + ')').fadeIn();
if (i == imageCount) {
i = 2;
}
else {
i++;
}
}
The setInterval is not formatted correctly. Try this:
function startScroll() {
me = this;
scrollInterval = setInterval(function(){
scrollImages(me);
}, 100);
}

Categories