Updating the physical position of an object in array using jQuery - javascript

jQuery + JavaScript
var movable = new Array();
movable.push($('#cloud1'));
movable.push($('#comment1'));
if(left == true){
for(i = 0; i < movable.length; i++){
movable[i].position().left += 10;
movable[i].css("left", movable[l].position().left);
}
}
I'm trying to move a set of objects across the screen while the left arrow key is pressed. I've added two objects to an array, and i'm then attempting to loop through the array, increment that objects position, and then update its css. However the position of the object always stays the same which i've checked using:
alert(
"Size: " + movable.length +
"\nIndex 0: " + movable[0] +
"\nLeft: " + movable[0].position().left +
"\nTop: " + movable[0].position().top
);
Can you see why it's not working? Or tell me a better approach. Thanks!
Working code:
for(l = 0; l < movable.length; l++){
var tmpPosX = movable[l].position().left;
tmpPosX += amount * 10;
movable[l].css("left", tmpPosX);
}

.position() is not a 'set' method; you can only use it to get the position.
http://api.jquery.com/position/
movable[i].offset({left:movable[i].position().left+10}) should work, though.
http://api.jquery.com/offset/#offset2

Related

JavaScript - Printing from Array of Objects Not Working

I have this array of objects here that I am traversing and want to display a match if the person at the current index has an age within +/- 10 years of anyone else in the array. However, when I run it, it says "Cannot read property 'age' of undefined." Where did I go wrong?
function findmatches() {
var n = USERS.length;
for (var i = 0; i < n; i++) {
var currName = USERS[i].firstName;
var currAge = USERS[i].age;
var currGender = USERS[i].gender;
for (var c = 0; c < 10; c++) {
if (((USERS[c].age) + 10) <= currAge) {
document.getElementById("showmatches").innerHTML += currName + " matched to >> " + USERS[i].firstName + " " + USERS[i].lastName + " \n";
break;
}
}
}
}
What exactly is your second for loop supposed to do?
In the code you posted, it iterates through first 10 users in the USERS array. I assume it has less users than that, so at some point USERS[c] is undefined, and you're trying to access USERS[c].age.

JavaScript Looping Variables on Left Side of Equal Sign

I'm looping through results and writing them out to html.
I want to increment the number 1 on the lest side of the equal sign - the binding -
A_Inside_Bus_1_div, A_Inside_Bus_2_div, A_Inside_Bus_3_div etc..
How should I go about that?
for (var i = 0; i <= 4; i++) {
A_Inside_Bus_1_div.innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
A_Inside_Bus_1_Comments_div.innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
Do it like this:
var A_Inside_Bus_div = [];
var A_Inside_Bus_Comments_div = [];
Before you continue the rest, like editing .innerHTML, you need to create those objects. Only after that you can do something like:
for (var i = 0; i <= 4; i++) {
A_Inside_Bus_div[i].innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
A_Inside_Bus_Comments_div[i].innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
This is just an idea how you "should go" about that, as you said.
If those variables are actually the IDs of DIVsm and you're depending on the fact that IDs are turned into global varables, you can use document.getElementById() to access them.
for (var i = 0; i <= 4; i++) {
document.getElementById('A_Inside_Bus_' + (i+1) + '_div').innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
document.getElementById('A_Inside_Bus_' + (i+1) + '_Comments_div').innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
Don't do this. Trying to make variable names to do what you're trying to do just leads to needlessly messy code down the road.
Stick all your elements into arrays:
var elems = [
A_Inside_Bus_1_div
A_Inside_Bus_2_div
...
];
var comments = [
A_Inside_Bus_1_Comments_div
A_Inside_Bus_2_Comments_div
...
];
Then just index the arrays:
for (var i = 0; i <= 4; i++) {
elems[i].innerText = i + ". " + snapshot.child("0/A_Inside_Bus " + i).val();
comments[i].innerText = snapshot.child("0/A_Inside_Bus " + i + " Comments").val();
}
This is an example of how you could do it with your current setup. Note though, it could be cleaned up. If each element of the elems array always has a partner in comments, it would make more sense to group them together in an object, and only have 1 array.
Also note that populating the arrays in a loop makes more sense. I just hardcoded the arrays here for the sake of brevity. I'm not sure how you're creating the elements originally. They should probably be created and put straight into the array instead of naming them and adding them later.
There are a couple ways you could go about doing this, but they tend to involve some pretty bad habits, like using eval or attaching variables to the global object so you can access them with a string:
var a = 1;
window['a']; //1
But there are better alternatives, the most common is probably storing them in equal-length arrays:
var divs = [div1, div2, div3];
var items = ['cat', 'dog', 'fish'];
items.forEach(function(element, index){
divs[index].innerText = items[i];
});
You could also look at building out a single array of objects:
var objects = [{div: div1, item: 'cat'}, {div: div2, item: 'dog'}, {div: div3, item: 'fish'}];
for object in objects {
object.div.innerText = object.item;
}

append() and $(this).addClass() method in jQuery is not working

I am new to jQuery and I am refactoring former JavaScript code into jQuery. I use the append() and $(this).addClass() methods, but it seems they don't work. I don't know what the problem is.
The JavaScript code is about creating a puzzle game (15 puzzles). I am trying to add an element into an HTML file in the jQuery way.
var tile = function(i, j) {
this.seq = i * 4 + j + 1;
this.row = i + 1;
this.column = j + 1;
if (i * 4 + j != 15) {
$(this).addClass("block puzzle row" + this.row + " column" + this.column);
var xPosition = -j * 88;
var yPosition = -i * 88;
$(this).css("backgroundPosition", xPosition + "px " + yPosition + "px");
} else {
$(this).addClass("block row" + this.row + " column" + this.column);
$(this).attr('id', "blank");
}
}
function Init() {
var node = $("#imgContent"); // imgContent is a div
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var t = new tile(i, j);
node.append(t);
}
}
// Generate the original picture before the start
Judge.isStart = false;
}
How do I use these jQuery methods properly?
You're using $(this) incorrectly.
When the tile() function is called with new, it is instantiated as an object and 'this' becomes a reference to that object. In doing so, you can assign values to its internal state using 'this.' syntax.
jQuery is primarily designed to manipulate the Document Object Model (DOM). Usually you'll pass a selector into jQuery which finds the matching HTMLElements from the document and returns them for manipulation. $(this) within the context of tile is passing the this reference which jQuery just returns back to you.
Important part here is that $(this) represents the tile object and not actually an element from the document. The .css .addClass and .append functions aren't applicable, as they work on elements. You need to pass a selector or an element into jQuery to use them.
A solution is to create an element within tile that can be appended to the document.
https://jsfiddle.net/hxqduoef/2/
var tile = function(i, j) {
this.seq = i * 4 + j + 1;
this.row = i + 1;
this.column = j + 1;
// $("<div></div>") creates a new div element wrapped in the jQuery object, it isn't part of the document until it gets appended. saving to this allows further manipulations within this constructor.
this.element = $("<div>Tile at "+ i +" "+ j +"</div>");
if (i * 4 + j != 15) {
this.element.addClass("block puzzle row" + this.row + " column" + this.column);
var xPosition = -j * 88;
var yPosition = -i * 88;
this.element.css("backgroundPosition", xPosition + "px " + yPosition + "px");
} else {
this.element.addClass("block row" + this.row + " column" + this.column);
this.element.attr('id', "blank");
}
}
function Init() {
var node = $("#imgContent"); // imgContent is a div
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var t = new tile(i, j);
node.append(t.element);
}
}
// Generate the original picture before the start
// Judge.isStart = false;
}
This adds the "this.element" property, sets it as a new DIV element and references it instead of the t in the node.append(t.element) statement.
I hope this helps.
context of this is getting changed, keep this to a variable, then use that variable.
var $this = this;
var tile = function(i, j) {
$this.// your code
}
$(this) is actually defined by the invoker of the function, while explicit variables remain intact inside the function declaration block known as the enclosure.
What's happening in your function is tile(i,j), is being called explicitly, this means context or the "this" of the function is the window object.Being specific to your question, this is bound to the global object, that is window.
For example, consider the following function,
function myFunc(){
}
and,
var myObj= { myFunc: myFunc};
If you call using myObj.myFunc(); then this is bound to myObj.
If you call myFunc() directly, such as, myFunc();,
then this is bound to the global object, that is window.
Hence, calling a function without a following parent object will generally get you the global object which in most browsers means the window object.

How to make this JavaScript/jQuery code shorter

Is there a way to loop this four times to make it shorter? I am trying to change the class from standing to sitting and then back again one at a time.
if(sitting > 0) {
$('.standing:first-of-type').removeClass('standing').addClass('sitting');
} else {
$('.sitting:first-of-type').removeClass('sitting').addClass('standing');
}
if(sitting > 1) {
$('.standing:nth-of-type(2)').removeClass('standing').addClass('sitting');
} else {
$('.sitting:nth-of-type(2)').removeClass('sitting').addClass('standing');
}
if(sitting > 2) {
$('.standing:nth-of-type(3)').removeClass('standing').addClass('sitting');
} else {
$('.sitting:nth-of-type(3)').removeClass('sitting').addClass('standing');
}
if(sitting > 3) {
$('.standing:nth-of-type(4)').removeClass('standing').addClass('sitting');
} else {
$('.sitting:nth-of-type(4)').removeClass('sitting').addClass('standing');
}
You can use :lt and :gt selectors.
:lt(index) select all elements at an index less than index within the matched set. :gt(index) select all elements at an index greater than index within the matched set.From jQuery Docs
As the class sitting should be added to all the elements having class .standing whose index is less than the sitting variable value, :lt selector can be used with the variable sitting to select such elements. Then addClass() and removeClass() can be used on the jQuery set of elements to add and remove the passed classes respectively.
$('.standing:lt(' + sitting + ')').removeClass('standing').addClass('sitting');
$('.sitting:gt(' + sitting + ')').removeClass('sitting').addClass('standing');
Well, you can do with an ugly for-loop:
function toggleSitting(sitting){
var initial = 0;
var final = 3;
for(var i = initial; i <= final; i++){
$('.standing:nth-of-type(' + (i+1) +')')
.toggleClass('standing', sitting < i)
.toggleClass('sitting', sitting > i);
}
}
toggleSitting(sitting);
This is just a draft and it's untested, but there is a logic in what you are trying to do. Once you find the logic, you just have use it in a loop. Like that :
var condition;
for(var i = 0; i < 4; i++){
condition = sitting > i;
$('.standing:nth-of-type(' + (i + 1) + ')').toggleClass('standing', !condition).toggleClass('sitting', condtion);
}
Maybe Something like this:
var numberOfPlaces = 4;
for(var i=0; i<sitting && i<numberOfPlaces ; i++){
$('.standing:nth-of-type(' + (i+1) + ')').removeClass('standing').addClass('sitting');
}
for(var i=sitting; i<numberOfPlaces ; i++){
$('.sitting:nth-of-type(' + (i+1) + ')').removeClass('sitting').addClass('standing');
}
or this:
var numberOfPlaces = 4;
for(var i=0; i<numberOfPlaces; i++){
if(i<sitting){
$('.standing:nth-of-type(' + (i+1) + ')').removeClass('standing').addClass('sitting');
}else if(i>=sitting){
$('.sitting:nth-of-type(' + (i+1) + ')').removeClass('sitting').addClass('standing');
}
}
Do you have HTML and CSS to accompany that ?
You can use a variable to specify the 'nth' of type:
$('.standing:nth-of-type(' + i + ')')
although not sure that that works for the case where i = 1. You might need first-of-type there.
Without the CSS and HTML it isn't clear exactly what you want to do.
You might want to look at this also:
https://css-tricks.com/almanac/selectors/n/nth-of-type/

loop created element's value always 5

Can someone please tell me why when I click on the [s] href created next to the list of names (myhand) generated it always says selection and i are 5?
var printDD = function(myhand, mydiv){
var dtext = "";
for(var i = 0; i < myhand.length; i++){
dtext += '[s]' + myhand[i] + ', ';
}
mydiv.html(dtext);
for(var i = 0; i < myhand.length; i++){
$('#dd'+i).click(function(){
selection = i;
console.log("sel: " + selection + " i: " + i);
});
}
}
You want to take a look at JavaScript closure inside loops – simple practical example. As the answer to that question says, you can create a function to return one, or you can use inline function invocation in the for loop like so:
for(var i = 0; i < myhand.length; i++) {
$('#dd'+i).click((function(x) {
return function () {
selection = x;
console.log("sel: " + selection + " x: " + x);
}
}(i)));
}
Because the value of i is determined at the time the click handler is run. So it will always have the value of myhand.length - 1, which is the state you left i in after the for-loop.

Categories

Resources