I im quite confused in the negation of the functionality of my function. The original function takes 9 elements starting at nth index and decrease their transform position.
function pushIt(max, target, index, count) {
if (count == max || count == img.children ) {
running = false;
return;
}
var tmp = target[index];
var matrix = window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left = matrix.split(",")[4];
var translate_top = matrix.split(",")[5].split(")")[0]-215;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function(){
pushIt( max, target, index + 1, count + 1 );
},50)
}
What i wanted to do is to negate its functionality , e.g it wont decrease but increase transform position of (nth * 3) - 1 element ( counting down 9 elements )
function pushItDOWN(max, target, index , count) {
if ( count == max || index < 0 ) {
running = false;
return;
}
console.log("down");
var tmp = target[index];
var matrix = window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left = matrix.split(",")[4];
var translate_top = matrix.split(",")[5].split(")")[0]+215;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function(){
pushItDOWN(max, target, index - 1, count + 1 );
},50)
}
}
What second function does is takes elements and set their transform to oblivion (e.g out of viewport) and somehow break the functionality of first function.
Did i overlook some key fact that is causing the problem , i seem to fail to find the root of the problem.
Live demo for better understanding
I'm not 100% sure, but most likely this is your error:
This will result in a string:
matrix.split(",")[5].split(")")[0]
Lets say it is "500", then
matrix.split(",")[5].split(")")[0] + 215
// equals
"500" + 215
// results in (because + is both used as string concatenation as addition)
"500215"
// - will work, because it only has one meaning
"500" - 215 // results in 285
Parse the value as an int (or float if necessary) before adding the 215:
parseInt(matrix.split(",")[5].split(")")[0]) + 215
Related
What is the right way to increment an array in a loop? I'm passing in a non zero based number and want to get the right starting position for the Array.
I can get it to work using eval:
arrayPosition = "articleArray[" + (goTo - 1) + "][0]";
window.scroll(eval(arrayPosition), 0);
But I know this isn't proper coding and now that I'm using //"use strict"; it will no longer run.
I've tried variations of:
var x = arrayPosition[goTo - 1][0];
window.scroll(x,0);
But these don't work.
function scrollToArticle(referrer, goTo, showSection) {
// referrer, goTo are required
var showSection = (typeof showSection) !== "undefined" ? showSection : false;
var tmpNum = Math.round(articleArray.length / 2);
if (goTo !== tmpNum && goTo !== articleArray.length) {
arrayPosition = "articleArray[" + (goTo - 1) + "][0]";
window.scroll(eval(arrayPosition), 0);
} else if (goTo === tmpNum) {
window.scrollTo(mainContentCenterScrollTo - (window.innerWidth / 2), 0);
} else {
arrayPosition = "(articleArray[" + (goTo - 1) + "][0]) + (articleArray[" + (goTo - 1) + "][1])";
window.scrollTo(eval(arrayPosition), 0);
}
}
There should be no need for eval, just a reference to the array:
var arrayPosition = articleArray[goTo - 1][0];
window.scroll(arrayPosition, 0);
Sorry to all it was my on fault as was noted above the value being past into to array was a string and not a number which is why eval worked and [i-1] didn't.
I'm practising writing Javascript by making a Roguelike dungeon game but there is a problem when I want to create monsters. I have written a while loop such as:
this.getRandomCoordinatesInRoom = function(roomNumber) {
var validLocationFound = false;
while (!validLocationFound){
// Generate co-ords in room first
x = Math.floor(Math.random() * (this.roomList[roomNumber].width) + (this.roomList[roomNumber].posX));
y = Math.floor(Math.random() * (this.roomList[roomNumber].height) + (this.roomList[roomNumber].posY));
// Find location of (x,y) in Dungeon Array
//alert(arrayLocation);
var tmpX = ((this.roomList[roomNumber]).posX + x);
var tmpY = ((this.roomList[roomNumber]).posY + y);
var arrayLocation = ((tmpY * 80) + tmpX);
//var arrayLocation = ((this.roomList[roomNumber].posX + x) + (80 * (this.roomList[roomNumber].posY + y)));
if (this.dungeonArray[(tmpY + tmpX)] === "floor") {
validLocationFound = true;
};
if ((x<this.roomList[roomNumber].posX) || (x>(this.roomList[roomNumber].posX + this.roomList[roomNumber].width))){
alert("x out of bounds");
};
if ((y<this.roomList[roomNumber].posY) || (y>(this.roomList[roomNumber].posY + this.roomList[roomNumber].height))){
alert("y out of bounds");
};
writeToScreen("Room upper left corner = " + (this.roomList[roomNumber].posX).toString() + "," + (this.roomList[roomNumber].posY).toString(),10);
return [x,y];
if (!(getTileAt(arrayLocation) === "floor")){
alert("It messed up");
}
};
The code randomly generates an x,y coordinate and converts it to a single number (My dungeon array is one dimensional, 0-79 across and then 80 is a new row). however, even when the code generates a coordinate that isn't valid (!= "floor"), it still finishes the function as though it returned true. Why is this?
Your function returns [x,y] from inside the while loop. Declare the variables outside of the loop and then return the value from outside the loop. Or else, return is when validLocationFound is true.
var x, y ;
while(...) {
...
}
return [x, y];
I am trying to solve this question and I know a way to solve it for number of 0s, but I am unable to solve it for number of 5s
I am trying soemthing like this
function findFive(lastNumber){
var count=1,k;
if(lastNumber<5)
return 0;
else if(lastNumber===5)
return 1;
else{
for(var i=6;i<=lastNumber;i++){
k=i;
while(k>0){
if(k%5==0 && k%10!==0)
count++;
k=k/5;
}
}
return count;
}
}
but this wont work for numbers like 50, 550, 500 etc. So i wanted to know which is the best and efficient way to solve this problem.
Thanks. Any help appreciated
We can see a pattern for the total, as we keep increasing digits.
1 -- 0
5 -- 1
10 -- 0 * 9 + 10^0 = 1
59 -- 1 * 5 + 10^1
60 -- 1 *(6-1)+ 10^1
100 -- 1 * 9 + 10^1 = 19
599 -- 19* 5 + 10^2
600 -- 1 *(6-1)+ 10^2
1000 -- 19* 9 + 10^2 = 271
with this pattern we can get the results by looking at each of the digits in the number
for example:
332 -- 3*19 + 3*1 + 2*0
984 -- [(9-1)*19 + 100] + [(8-1)*1 + 10] + [4*0]
3943 -- 3*271 + ((8-1)*19 + 100) + 4*1 + 3*0
1543 -- 1*271 + (5*1 +44)
then we can write some code.
function findFive(n){
// we'll cast the value to a string, to be able to grab the Most Significant Digit easily
return _findFive(String(n))["t"]
}
// helper function. Returns the integer value of the number without
// the first digit (eg. "3948" returns 948)
function remaining(n){
return n.length > 1 ? parseInt(n.substr(1)) : 0;
}
// Recursive function. Returns the total number of 5s in the range 0 to n, and the multiplier for the next higher digit
function _findFive(n){
if(n.length == 0) return {t:0,m:0};
var result = _findFive(n.substr(1)); // get the total from the less significant digits.
// Also returns the multiplier for the MSD
var msd = n[0]; // Most significant digit
if(msd < 5) total = msd * result["m"] + result["t"];
else if(msd == 5) total = msd * result["m"] + remaining(n) + 1;
else total = (msd-1) * result["m"] + Math.pow(10,n.length-1) + result["t"];
var multiplier = result["m"]* 9 + Math.pow(10,n.length-1); // calculate multiplier for next higher digit
return {t:total,m:multiplier}
}
This code will solve the problem in log(n) time. It's not necessary to process each of the numbers in the range (O(n) time) to get the answer.
To count the number of integers containing a 5, in a range from 0...lastNumber, try something like this:
function findFive(lastNumber){
var count = 0,
str = lastNumber + '';
for(var i = 0; i <= lastNumber; i++){
if((i+'').indexOf('5') !== -1){
count++;
}
}
return count;
}
Results:
findFive(60) // 15
findFive(550) // 146
findFive(550746) // 255502
Just keep in mind that the larger this number gets, the more time it's going to take to calculate the result.
You could make it a string and search on that. Something like,
function findFive(upperBound) {
var count = 0;
for (var i = 0; i < upperBound; ++i) {
if (i.toString().match(/5/)) {
++count;
}
}
return count;
}
To see if this is more efficient than a number parsing approach you should try and benchmark them both.
I have a piece of code that I've written that is supposed to keep track of which image is going to appear next on the page depending on which button is pressed
$(document).ready(function(){
$("#moveleft").click(function(){
var negoff = "false";
$("#slideshow>ul>li").animate({left: '-=' + actualwidth + 'px'}, 500);
$("#slideshow>ul>li:first-child").remove();
offset++;
console.log("Offset: " + offset);
if(offset > 4){
offset = 0;
}
if(offset < 0){
offset = offset * -1;
negoff = true;
}
$("#slideshow>ul").append('<li><img src="images/' +
contentcategories[offset] + '.jpg"/></li>');
$("#slideshow>ul>li:last-child").css({width: picturewidth + "px",
left: + 6 * actualwidth + "px"});
if(negoff){
offset = offset * -1;
negoff = false;
}
});
$("#moveright").click(function(){
var posoff = "false";
$("#slideshow>ul>li").animate({left: '+=' + actualwidth + 'px'}, 500);
$("#slideshow>ul>li:last-child").remove();
offset--;
console.log("Offset: " + offset);
if(offset < -4){
offset = 0;
console.log("Offset: " + offset);
}
if(offset > 0){
offset = offset * -1;
posoff=true;
console.log("Posoff: " + posoff);
}
$("#slideshow>ul").prepend('<li><img src="images/' +
contentcategories[(contentnum - 1) + offset] + '.jpg"/></li>');
$("#slideshow>ul>li:first-child").css({width: picturewidth + "px",
left: + 0 + "px"});
if(posoff){
offset = offset * -1;
posoff = false;
}
});
});
The confusing thing about this is that if I click on the #moveright button 2 times in a row the offset goes to -1 then to 0 and keeps looping through the 2 values. Nearly the same thing happens with the #moveleft button. It cycles through the values 0 and 1.
I am confused by this because the only place where I set the offset variable to 0 is if goes above 4 or goes below -4 and I'm not seeing a reason for it to be set to 0 after it goes to 2 or -2.
Let's take a look at what you're doing here. You're writing a string into a variable, trying to use it as a boolean value, i. e. true and false, and then, in your if statements, you are checking whether or not the variable is: not null, not undefined, not false. The tricky thing here's that it actually is defined, it is not null, and it is a string ("false")
Long story short: Remove the "" around your "false", it should be fine then.
Remove the quotes from var negoff = "false"; and var posoff = "false";.
Your code could be refactored a bit but that's neither here nor there. The crux of the problem is that "false" == true since non-empty strings are truthy values in JavaScript. I assume it's just a typo, but here's what's happening:
offset starts at 0. If #moveLeft is clicked, it gets incremented to 1. Then it gets multiplied by -1 because if(negoff) will be true. So now it's -1 and the next click increments it back to 0. Rinse and repeat. The opposite is happening for #moveRight.
I'm trying to workout an efficient way to cycle though in 25% increments the background image of an element, but when it gets to 100% it would go back to 0% on the next increment.
I can do something like this:
var currentPos = $('.ele1').css('background-position');
var elementPositions = currentPos.split(' ');
var x = Number(elementPositions[0].replace(/[^0-9-]/g, ''));
//var y = Number(elementPositions[1].replace(/[^0-9-]/g, ''));
// only want to do the x axis
x = (x == 100) ? 0 : x += 25;
$('.ele1').css('background-position', x + "%" + " 0");
But I don't like the fact I have to call the element twice. Is there a more efficient way to increment a % with jQuery and have it reset back to 0% after 100%?
I did think to do it with CSS .classes. But I don't really want to be restricted to what's in my style sheet.
You can pass a callback function to jQuery's .css() method:
$('.ele1').css('background-position', function (i, value) {
var x = parseInt(value, 10);
return (x == 100 ? 0 : x + 25) + "%" + " 0";
});
If you're calling this from within a loop/timer/event/whatever, you should cache the $('.ele1') object.