Cannot access objects in associative arrays using jQuery - javascript

I am trying to create and array of objects so that I can access them in a for loop in jQuery and I know that this works in Actionscript so what I am trying to do is convert my current knowledge to jQuery that will work.
Please have a look at this and tell me why I cannot access divToShow
Thanks guys
var homeImages = new Array();
homeImages[0] = { hoverImage: ".leftColImage1", divToShow: ".image1", rollOverImg: "img-family-over.jpg" };
homeImages[1] = { hoverImage: ".leftColImage2", divToShow: ".image2", rollOverImg: "img-students-over.jpg" };
homeImages[2] = { hoverImage: ".leftColImage3", divToShow: ".image3", rollOverImg: "img-pros-over.jpg" };
homeImages[3] = { hoverImage: ".leftColImage4", divToShow: ".image4", rollOverImg: "img-retired-over.jpg" };
var hoverImage;
var activeDiv;
var mainContent = ".mainContent";
for (k = 0; k < homeImages.length; k++) {
homeImages[k].id = k;
$(homeImages[k].hoverImage).mouseover(function() {
//alert("divToShow : " + homeImages[this.id].divToShow);
alert("this : " + this.id);
activeDiv = homeImages[k].divToShow;
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/" + homeImages[k].rollOverImg);
$(mainContent).hide();
$(homeImages[k].divToShow).slideDown("slow");
}).mouseout(function() {
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/img-family.jpg");
$(".image1").hide();
$(mainContent).slideDown("slow");
});
}

Ok, try this:
for (k = 0; k < homeImages.length; k++) {
(function(current) {
$(current.hoverImage).hover(function() {
activeDiv = current.divToShow;
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/" + current.rollOverImg);
$(mainContent).hide();
$(current.divToShow).slideDown("slow");
},
function() {
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/img-family.jpg");
$(".image1").hide();
$(mainContent).slideDown("slow");
});
})(homeImages[k]);
}
Or alternatively:
function setUpHover(item) {
$(item.hoverImage).hover(function() {
activeDiv = item.divToShow;
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/" + current.rollOverImg);
$(mainContent).hide();
$(item.divToShow).slideDown("slow");
},
function() {
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/img-family.jpg");
$(".image1").hide();
$(mainContent).slideDown("slow");
});
}
for (k = 0; k < homeImages.length; k++) {
setUpHover(homeImages[k]);
}

//alert("divToShow : " + homeImages[this.id].divToShow);
In that context, this refers to the current HTML element, not the current homeImages element.

You are accessing the variable k from inside the mouseover handler function. But by the time that function is called, the value of k has already changed and is now equal to homeImages.length since the for loop has already run to completion.
One way to solve this is to use $.each instead of the for loop:
$.each(homeImages, function(k, element) {
element.id = k;
$(element.hoverImage).mouseOver(function() {
.... //you can use the value of k or element here
});
});
This will work because the function passed to $.each creates a new closure which remembers the value of k for each iteration.

The reason is the old classic relating to closures: in the mouseover handler, k is always set to its last value of 4 rather than its value when the mouseover handler was created, which is what your code is expecting.
You can fix this by creating the mouseover handler in a function:
function addMouseEventHandlers(imageIndex) {
var homeImage = homeImages[imageIndex];
homeImage.id = imageIndex;
$(homeImage.hoverImage).mouseover(function() {
//alert("divToShow : " + homeImages[this.id].divToShow);
alert("this : " + this.id);
activeDiv = homeImage.divToShow;
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/" + homeImage.rollOverImg);
$(mainContent).hide();
$(homeImage.divToShow).slideDown("slow");
}).mouseout(function() {
$(".leftColImage1 img").attr("src", "/App_Themes/MyChoice2010/Images/img-family.jpg");
$(".image1").hide();
$(mainContent).slideDown("slow");
});
}
for (k = 0; k < homeImages.length; k++) {
addMouseEventHandlers(k);
}

Related

How to mutate an element from the DOM and then return it to its original state in JavaScript?

I've made a function which cycles through the DOM of a targeted are (via id) to create a rollover functionality.
My problem lies within the rollOver/rollOut function. For some reason the environment where I run this script seems to mess with the srcset attribute.
This is the original:
function rollOver(elem) {
(document.getElementById(elem).srcset =
"https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dw685f8968/images/home-page/desktop/eyes-on-you-desktop-hover-" +
elem.slice(6) +
".jpg?$staticlink$"),
"https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dw685f8968/images/home-page/desktop/eyes-on-you-desktop-2x-hover-" +
elem.slice(6) +
".jpg?$staticlink$ 2x";
}
function rollOut(elem) {
(document.getElementById(elem).srcset =
"https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dw685f8968/images/home-page/desktop/eyes-on-you-desktop-" +
elem.slice(6) +
".jpg?$staticlink$"),
"https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dw685f8968/images/home-page/desktop/eyes-on-you-desktop-2x-" +
elem.slice(6) +
".jpg?$staticlink$ 2x";
}
rollOver:
path/to/image/eyes-on-you-desktop-hover-" + elem.slice(6) + ".jpg?$staticlink$"
rollOut:
path/to/image/eyes-on-you-desktop-" + elem.slice(6) +".jpg $staticlink$"
The elem variable comes from here...
document.addEventListener("DOMContentLoaded", function (event) {
var rollOverCollectionA = document
.getElementById("roll-over-collection-b")
.getElementsByClassName("rollover");
rollOverCollectionA = Array.prototype.slice.apply(rollOverCollectionA);
var l = rollOverCollectionA.length;
for (let i = 0; i < l; i++) {
on("mouseover", `#${rollOverCollectionA[i].id}`, function () {
rollOver(rollOverCollectionA[i].id);
});
on("mouseout", `#${rollOverCollectionA[i].id}`, function () {
rollOut(rollOverCollectionA[i].id);
});
}
});
and its just the #id value on the elem which gets sliced to coincide with the element which is receiving focus.
I tried something like this:
function rollOver(id, elem ) {
elem.srcset = elem.srcset.splice(174, 0, '-hover');
elem.srcset = elem.srcset.splice(362, 0, 'hover-')
document.getElementById(id).srcset = elem.srcset;
}
function rollOut(id, elem) {
document.getElementById(id).srcset = elem.srcset;
}
But what that does is continually add 'hover to the elem.srcset/string !
UPDATE
This is a working demo.
UPDATE
This is an example of what is happening.
The rollover appends hover to the non-hover state, but then the next time you hover the src now has `xxx-1-hover-hover.jpg
Any help would be appreciated!

Trouble clearing object from array using buttons (jquery)

I'm attempting to move an image and data-id attribute from one section of divs, to a placeholder section of divs. I also want to be able to splice out those objects from the array when clicking the 'remove' button from either section.
It's mostly working by targeting the 'data-id' attribute and then performing the actions I want it to - but I'm running into one bug.
https://jsfiddle.net/kgmucdac/
$(document).ready(function() {
var selections = [];
var prodLength = 4;
var arrayVal = "";
$(".killThis").click(function() {
killCount();
});
$("#products").on('click', '.add', function () {
$(this).removeClass('add');
$(this).addClass('removeTop');
$(this).text("remove");
$('.remove').show();
arrayVal = ($(this).data('id'));
if (selections.length <= prodLength) {
selections.push({src: $(this).parent().find('img').attr('src'),vid: $(this).data('id')});
}
addProd();
console.table(selections);
});
$("#products").on('click', '.removeTop', function () {
arrayVal = ($(this).data('id'));
$(this).removeClass('removeTop');
$(this).addClass('add');
$(this).text("add");
nukeProd();
cleanArray();
drawProds();
});
$('#placeholders').on('click', '.remove', function () {
arrayVal = ($(this).data('id'));
console.log(arrayVal);
nukeProdReverse();
cleanArray();
tempClear();
drawProds();
})
function drawProds() {
var prods = $('#placeholders').find('.placeholder');
for (var i = 0; i < prods.length; i++) {
var prod = prods[i];
var selection = selections[i];
if ((selection != undefined)) {
$(prod).find('img').attr('src', selection.src);
$(prod).find('.remove').attr('data-id', selection.vid)
} else {
$(prod).find('img').attr({
'src': 'https://i.imgur.com/D6MQP01.png'
});
$(prod).find('.remove').css('display', 'none');
}
}
}
function addProd() {
drawProds();
}
function nukeProd() {
$('.placeholder[data-id="' + arrayVal + '"]').find('img').attr({
'src': 'https://i.imgur.com/D6MQP01.png'
});
$('.remove[data-id="' + arrayVal + '"]').attr('data-id', '');
}
function cleanArray() {
for(var i = 0; i < selections.length; i++) {
if(selections[i].vid == arrayVal) {
selections.splice(i, 1);
break;
}
}
console.table(selections);
}
function nukeProdReverse() {
$('.placeholder[data-id="' + arrayVal + '"]').find('img').attr({
'src': 'https://i.imgur.com/D6MQP01.png'
});
$('.remove[data-id="' + arrayVal + '"]').removeAttr('data-id');
$('.removeTop[data-id="' + arrayVal + '"]').text("add");
$('.removeTop[data-id="' + arrayVal + '"]').addClass('add');
$('.removeTop[data-id="' + arrayVal + '"]').removeClass('removeTop');
}
function tempClear() {
$('.remove').removeAttr('data-id');
}
function killCount() {
console.log(arrayVal);
}
});
That's my JSFiddle that I've been working on. When I add the products in any order from the top row, I can delete them using the top row's remove buttons, no issues.
However, using the bottom row's 'remove' buttons, I can only remove them all if I start from right to left (4th, 3rd, 2nd, 1st)... If I remove them in any other order, e.g., the 3rd, the one that slides into its place will not work correctly.
I think it has something to do with the index incrementation but I'm kind of at the end of my road on this in terms of what I know how to do/cobble together.

For Loop refusing to Loop; Works Perfectly Fine if Run Manually

Alright, so, hopefully this is a simple enough question. I'm sure that it has to be something simple and stupid that I am not doing right. I'm building an app to program my exercise routine into so I can keep track of it every week (and to learn app development using Cordova). Within the code, each time I come back to the exersetup screen I want to read the saved exercise file, parse it back to an array of objects, convert those objects back into exercise objects, then display them on the screen. I have a loop that is supposed to check each element of the array to process the information, then display, then repeat until it has done this for each element in the array. It works perfectly fine for the first item, then stops. If I manually run the loop multiple times, it functions perfectly. Not listed is the code for the function addRow(), which simply adds a row of formatted dropdown selectors for input, then increments rowNum to keep track of which row it is operating on. Any help you guys can offer is appreciated. If I need to submit more information I would be happy to do so. Here's the loop in question:
EDIT: Fixed some things to the suggestions in the comments below. Code still functions the same. Works perfectly fine on first run through loop, then stops. If I continue to run the loop manually (declaring it over and over again in console) it works fine, but it will not, for some reason, run the "for" loop. I've also included the rest of the function that the for loop is nested in, in case that helps.
function readRout()
{
console.log("Reading routine...");
document.addEventListener('deviceready', getFile, false);
function getFile()
{
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(dir)
{
console.log("got main dir",dir);
dir.getFile("exerciseroutine.txt", {create:true}, function(file)
{
console.log("got the file", file);
exerLog = file;
console.log(exerLog);
});
});
document.addEventListener('deviceready', logOut, false);
}
function logOut()
{
setTimeout(readLog, 50);
}
function readLog()
{
exerLog.file(function(file)
{
var reader = new FileReader();
reader.onloadend = function(e)
{
console.log(this.result);
exerRoutine = JSON.parse(this.result);
//console.log(exerRoutine);
//console.log(exerRoutine[0]);
var looper = exerRoutine.length + 1;
for (var i=0; i<looper; i++)
{
console.log("Loop count is: " + i);
console.log(looper);
exerRoutine[i] = new exercise(exerRoutine[i].type, exerRoutine[i].name, exerRoutine[i].sets, exerRoutine[i].reps, exerRoutine[i].pace);
console.log(exerRoutine[i]);
console.log(exerRoutine[i].description());
console.log(exerRoutine[i].type);
console.log(exerRoutine[i].name);
console.log(exerRoutine[i].sets);
console.log(exerRoutine[i].reps);
console.log(exerRoutine[i].pace);
addRow();
setTimeout(fillExer, 50);
console.log(exerRoutine);
}
console.log(looper);
};
reader.readAsText(file);
}, fail);
}
function fillExer()
{
var typeRow = "typeSel" + rowNum;
console.log(typeRow);
console.log(document.getElementById(typeRow));
var nameRow = "nameSel" + rowNum;
var setsRow = "setsSel" + rowNum;
var repsRow = "repsSel" + rowNum;
var paceRow = "paceSel" + rowNum;
fillType(typeRow);
setTimeout(fillName, 10, nameRow);
fillSets(setsRow);
fillReps(repsRow);
fillPace(paceRow);
}
function fillType(typek)
{
for (var k=0; k<document.getElementById(typek).options.length; k++)
{
//console.log(document.getElementById(typek).options.length);
console.log(exerRoutine[rowNum-1].type);
if(document.getElementById(typek).options[k].value == exerRoutine[rowNum-1].type)
{
document.getElementById(typek).selectedIndex = k;
//console.log(document.getElementById(typei).selectedIndex);
var quer = "#" + typek;
//console.log(query);
var typeInput = document.querySelector(quer);
//console.log(typeInput);
TypeSelect(typeInput);
return;
}
}
}
function fillName(namek)
{
for (var k=0; k<document.getElementById(namek).options.length; k++)
{
//console.log(document.getElementById(namek).options.length);
console.log(exerRoutine[rowNum-1].name);
if(document.getElementById(namek).options[k].value === exerRoutine[rowNum-1].name)
{
document.getElementById(namek).selectedIndex = k;
//console.log(document.getElementById(namei).selectedIndex);
return;
}
}
}
function fillSets(setsk)
{
for (var k=0; k<document.getElementById(setsk).options.length; k++)
{
console.log(exerRoutine[rowNum-1].sets);
if(document.getElementById(setsk).options[k].value === exerRoutine[rowNum-1].sets)
{
document.getElementById(setsk).selectedIndex = k;
//console.log(document.getElementById(setsk).selectedIndex);
return;
}
}
}
function fillReps(repsk)
{
for (var k=0; k<document.getElementById(repsk).options.length; k++)
{
console.log(exerRoutine[rowNum-1].reps);
if(document.getElementById(repsk).options[k].value === exerRoutine[rowNum-1].reps)
{
document.getElementById(repsk).selectedIndex = k;
//console.log(document.getElementById(repsi).selectedIndex);
return;
}
}
}
function fillPace(pacek)
{
for (var k=0; k<document.getElementById(pacek).options.length; k++)
{
console.log(exerRoutine[rowNum-1].pace);
if(document.getElementById(pacek).options[k].value === exerRoutine[rowNum-1].pace)
{
document.getElementById(pacek).selectedIndex = k;
//console.log(document.getElementById(pacek).selectedIndex);
return;
}
}
}
}

Titanium : Attach objects/variables with a view

I am creating some views in a loop iterating over list of objects. Now I want to register event with each view, which does something on the current object of the list.
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
var loopView = Ti.UI.createView({
....
});
loopView.addEventListener("click", function(e) {
var mv = iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
This code is not working, the log which is printed is : Movie: undefined.
So my question is how I can use the loop variable in the event listener?
Try the following code
var loopView - [];
var iMovie;
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
loopView[vs] = Ti.UI.createView({
_iMovie : iMovie
});
loopView[vs].addEventListener("click", function(e) {
var mv = e.source._iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
Well, first I'll start that what you are doing in the code above could potentially cause a memory leak since you are holding a reference to the iMovie variable.
what you should try doing is:
var mv = e.source;
this will return the source object that fired the click event.

How can I make my script work with an array?

This Javascript controls a Monial Content box with forward and back buttons to move forwards or backwards but it only works for 2 DIVs, how can I make this script work with an array so I can add more elements?
e.g.
Current Script Diagram
The Script Code
$(document).ready(function(e) {
showQuote();
$(".left").click(function(e) {
$("#monial_btn_1").trigger("click");
});
$(".right").click(function(e) {
$("#monial_btn_2").trigger("click");
});
$("#monial_btn_1").click(function(e) {
$(".monial_content_1").fadeIn("fast");
$(".monial_content_2").fadeOut("fast");
var obj=$(this);
obj.removeClass();
obj.addClass("monial_btn_selected");
obj=$("#monial_btn_2");
obj.removeClass();
obj.addClass("monial_btn");
});
$("#monial_btn_2").click(function(e) {
$(".monial_content_1").fadeOut("fast");
$(".monial_content_2").fadeIn("fast");
var obj=$(this);
obj.removeClass();
obj.addClass("monial_btn_selected");
obj=$("#monial_btn_1");
obj.removeClass();
obj.addClass("monial_btn");
});
var n = 10
for(i = 1; i < n; i++) {
$("#monial_btn_" + i).click(function(e) {
$(".monial_content_" + i).fadeIn("fast");
$(".monial_content_" + (i + 1)).fadeOut("fast");
var obj=$(this);
obj.removeClass();
obj.addClass("monial_btn_selected");
obj=$("#monial_btn_" + (i + 1));
obj.removeClass();
obj.addClass("monial_btn");
});
}

Categories

Resources