jQuery - Fade In/Out using if/else & rel values - javascript

Here's my fiddle: http://jsfiddle.net/bzoyc64m/
What I'm trying to achieve:
I want the images to fade in and out, right now, it's half working. The initial fades are fine, but when it comes to the second part it just doesn't seem to work.
So if $('.img-' + i + ' .active[rel="1"]') - remove the active class and fade out AND then fade in the next img and add active class - This works
The next stage is the issue - if $('.img-' + i + ' .active[rel="2"]') do the exact same, but for the previous banner. -This doesn't work
Here's my if statement, where I think I'm doing something wrong. I have no idea what though!!
if($('.img-' + i + ' .active[rel="1"]')) {
console.log("1");
$('.img-' + i + ' .active[rel="1"]').fadeOut().removeClass('active').next('img').fadeIn().addClass('active');
}
else if($('.img-' + i + ' .active[rel="2"]')) {
console.log("2");
$('.img-' + i + ' .active[rel="2"]').fadeOut().removeClass('active').prev('img').fadeIn().addClass('active');
}
Also - Out of interest. my i is a random number. Is there any way to prevent that from being the same number twice in a row? So for example, prevent it from doing something like this: 1, 2, 5, 4, 4, 4, 2, 3.
Thanks for any help, it's really appreciated!

The problem is in your if statement. The statement if($('.img-' + i + ' .active[rel="1"]')) {} is always executed. Even though $(selector) does not matches any DOM element, it returns an empty array, which is regarded as true.
if ([])
alert("Empty array is true");
This will show the alert, even if the array is empty. You could check the length of jQuery array instead:
if($('.img-' + i + ' .active[rel="1"]').length>0) {
...
}
For the second part of your question, you can use a shuffling algorithm
How to randomize (shuffle) a JavaScript array?
How can I shuffle an array?
After you consume all indexes, generate a new shuffle. You should pay attention the boundary condition though. The last number of previous shuffle may be equal to the first number of current shuffle.

Related

Trying to use nested if statements inside forEach loop on javascript array

I am trying to use an if statement inside of another if statement and I simply can't figure out how to get the second if statement to work. The second if statement applies all style changes to the first element (school) in the array. I would like the second if statement to apply the correct styling to all items in the array based on the json data ([school.status]).
I've tried switching to a for statement, tried moving the if statements around and nesting them differently, tried async and moving different parts of the formulas in and out of the code blocks. I've tried running a second forEach statement after the append but I couldn't get that to work either. I think I lack an understanding of how this process works, beyond just the code part, but more the logical operator, and after hours of searching for a straight forward answer, and it being almost 4AM, I figured I would just ask here.
schools.forEach(function(school, index) {
dashboardItemStatus = $(".dashboard-item-status");
if (App.hasClass("mainDash")) {
App.append(
'<div class="dashboard-item"><h5 class="mb-1">' +
[school.name] +
"</h5>" +
'<p style="margin-bottom: -2px">' +
[school.address.street] +
"</p>" +
'<p style="margin-bottom: -2px">' +
[school.address.city] +
"," +
" " +
[school.address.state] +
" " +
[school.address.zip] +
"</p>" +
'<p style="margin-bottom: -2px">' +
[school.phone] +
"</p>" +
'<p style="margin-bottom: -2px">' +
[school.principal] +
"</p>" +
'<p style="margin-top: 8px;background-color: #FFF;padding: 8px 14px;border-radius: 5px;" class="dashboard-item-status" id="dashboardItemStatus">' +
[school.status] +
"</p>" +
"</div>"
);
}
if (school.status == "Normal Operation") {
dashboardItemStatus.addClass("dashboard-item-status-normal");
} else if (school.status == "Full Change") {
dashboardItemStatus.addClass("dashboard-item-status-change");
}
});
So, I suppose the expected results are anytime one of the statuses is "Full Change" the dashboard-item-status-change class is applied, and the dashboard-item-status-normal class is applied to any status that has "Normal Operation". That data is an array that is coming from a json file. That part works just fine. The forEach function works fine and the information displays correctly on the screen. Now though, I need to be able to affect the elements that show the status individually based on the status itself. Right now, as stated above, no matter what status I attempt to affect, the channges all occur on the first element in the array, which I guess makes sense, but I have no idea how to fix it. If I console.log() the names and statuses of the schools inside the second if statement, they display correctly so I know I can find the right values, I just don't know how to affect them. Maybe map or something may work but I honestly don't know how to use that correctly. Any help is really appreciated.

jquery dynamically generated .append() sometimes appends to wrong div

I have a block of jquery that builds a form with more than 40 element using a loop to .append() div elements that load .ajax() json.
9 out of 10 times the form renders as expected. However randomly some of the elements will suffer from two types of errors
the dom element will be created but not displayed (does not show in source)(on deeper investigation, it seems the elements are always generated, just wrong parent (2))
the dom element is placed as a child to the wrong parent.
for example below, id3 should be attached to delta[14] but is instead generated at beta[3] OR id3 should be at gamma[6] but does not display at all
the format of build is
hard code
<div id="alpha">
<div id="beta"></div>
<div id="gamma"></div>
<div id="delta"></div>
</div>
doAppendStuff(beta, ajaxUrletc1);
doAppendStuff(beta, ajaxUrletc2);
...
doAppendStuff(gamma, ajaxUrletc10);
doAppendStuff(gamma, ajaxUrletc11);
...
doAppendStuff(delta, ajaxUrletc20);
doAppendStuff(delta, ajaxUrletc21);
dynamic
function randId(baseID) {
return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 555));
}
var id1= randId("myIdOne");
var id2= randId("myIdTwo");
var id3= randId("myIdThree");
function doAppendStuff(elemId, ajaxUrletc){
$('#' + elemId).append(
'<div id="' + id1 + '" >' +
'<div id="' + id2 + '">' +
'<select id="' + id3 + '"></select>' +
'</div>' +
'</div>'
);
... // log id1, id2,id3
... //do .ajax stuff + callback on id3
I have added callbacks to each loop to ensure that the .append is fired and no errors are generated complaining that the element does not exist.
Running a trace I can see the dynamic id for each element is being generated.
The code itself works as expected as the other 9/10 times it renders as expected.
notes
The random errors apply to different elements each time. no particular logic on what element fails.
I have separated the ajax calls from the dom element creation so there should be no bottleneck on the element creation
All ajax calls are initiated as expected in the correct order. Some take longer but the other elements generate as expected without waiting. All data is successfully returned.
Is there any know issues with generating multiple dom elements by calling the same function repeatedly OR is there a listener I could add to ensure the element is correctly generated in the desired position before proceeding to the next call via a callback.
UPDATE
After adding logging of the id1,id2,id3, the logs confirm that the correct dynamic ids are being assigned. It seems however that either the var in memory is being replaced with a previous value or the js engine is placing in the wrong generated position due to timing.
UPDATE 2
After some more debugging, we changed the random string and upped the number from
return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 555));
to
return baseID+"_"+Math.round(new Date().getTime() + (Math.random() * 99999));
and the problem has not reoccurred. So it looks like it could be either a random ID collision with the same string being generated twice or somehow reused when the function is reinitialised. The interesting thing is the ID's are not sequential, it will often skip several rows before reusing the same ID.
So we have cured the problem, but still do not understand what caused the issue, any thoughts are welcome.
If you want a unique value, then we're talking about GUID's.
Create GUID / UUID in JavaScript?
However, if you would have placed an underscore or other value between the time and random number, I'd suspect you'd have seen fewer collisions.
time + random = some future period in time.
Imagine getting a random 100 and then 100 ms later getting a random 0.
"abc1506110581013_100" != "abc1506110581113_0"
while
"abc1506110581113" == "abc1506110581113"

Adding and Displaying Array Issue

var reset = function ()
{
var p = parseFloat($("#IA").val());
var q = parseFloat($("#IB").val());
var m = parseFloat($("#CGCD").val());
var aR = [];
aR += ["GCD(" + p + "," + q + ")=" + m];
document.getElementById("PGCD").innerHTML = aR + "\n";
document.getElementById("IA-error").innerHTML="";
document.getElementById("IB-error").innerHTML="";
$("#IA").focus();
};
The code above is only for a 'reset' function, a part of additional code (not present), the purpose which is to find the Greatest Common Denominator, GCD.
My 'reset' function is connected to a button, #reset, the purpose of which is to do four things:
add and store the string GCD(p,q)=m to the array 'aR'; p/q/m are variable stand-ins for the values of the input text areas #IA, #IB, and #CGCD (the GCD of #IA and #IB);
display the array 'aR' in a text-area #PGCD each time the reset button is clicked; this is why I used an array;
clear the two input text areas #IA and #IB;
clear the one output text area;
As it stands, all four objectives are completed successfully, with one exception: for the second objective, only the most recent GCD calculation is outputted; none of the previous calculations output.
I cannot get the array to list the different saved calculations within it. I think (?) the new calculations are being added to the array, but I am not sure.
I've tried a 'for' statement, and an 'if' statement, neither of which worked. I don't know whether I coded it wrong, or if it wasn't the right solution for my issue.
I tried to search the forums (here) for a solution, but was unable to find one.
Thank you.
If I'm understanding what you are describing, I believe your problem is that you are attempting to use += to add elements to an array. You should use
aR.push("GCD(" + p + "," + q + ")=" + m);
The += operator is used for addition of a value to itself as well as string concatenation.
Edit: per comments below, the main issue was declaration of aR as a local variable. It needs to be either global or declared within the same scope.

Loop Elements in JQuery

I am trying to run a loop over a few elements in JQuery. Before anyone says it, I do not need .each(). I am trying to run through the elements as a genuine loop- once a successful iteration runs, the loop will break and prevent the same action being done on other elements. I looked briefly at the straight JavaScript version, with the .getElement... methods, but it is my understanding that this won't satisfy my other requirement- the list of elements to be iterated over is created via a partial-string JQuery identifier:
rows = $('tr[id^="am_assetRow_' + parentAsset.replace(/ /, "_") + '_' + type + '"]');
Does anyone know of anything that might help me get this working?
EDIT: Just a bit more information on the application: I am checking to see if a value can be inserted into an existing row of a table, and if not, creating a new row and inserting it there. Thus, I need the loop to exit if a suitable fit is found, and after the loop terminates, I need to know whether it terminated in success (placing the value) or failure (no available locations- time to create a new row).
In jquery, if you want a $.each() loop to end immediately, just return false from the function call.
Do do a normal loop without using each() but still using jquery to select the items based on partial string etc...
rows = $('tr[id^="am_assetRow_' + parentAsset.replace(/ /, "_") + '_' + type + '"]');
for (var i = 0; i < rows.length; ++i) {
rows[i]; // The raw element at this index.
$(rows[i]); // jquery collection for this one element.
if (someCondition) {
break; // Break the loop early.
}
}

Returning a string from a parallel array

I am sorry for the very newbie question, but this is driving me mad.
I have a word. For each letter of the word, the characters position in one array is found and then returns the character at the same position found in a parallel array (basic cipher). This is what I already have:
*array 1 is the array to search through*
*array 2 is the array to match the index positions*
var character
var position
var newWord
for(var position=0; position < array1.length; position = position +1)
{
character = array1.charAt(count); *finds each characters positions*
position= array1.indexOf(character); *index position of each character from the 1st array*
newWord = array2[position]; *returns matching characters from 2nd array*
}
document.write(othertext + newWord); *returns new string*
The problem I have is that at the moment the function only writes out the last letter of the new word. I do want to add more text to the document.write, but if I place within the for loop it will write out the new word but also the other text inbetween each word. What i actually want to do is return the othertext + newWord rather than document.write so that I can use it later on. (just using doc.write to text my code) :-)
I know its something really simple, but I cant see where I am going wrong. Any advice?
Thanks
Issy
The solution is to build newWord within the loop using += instead of =. Just set it to an empty string before the loop.
There are other problems with this code. Variable count is never initialized. But let's assume that loops should be using count instead of position as it's principal counter. In that case, if I am not mistaken, this loop will just generate array2 as newWord. First two lines of loop's body cancel each other in a matter of speaking, and position will always be equal to count, so letters from array2 will be used sequentially from beginning to the end.
Could you provide one example of input and desired output, so that we understand what you actually want to accomplish?
A good way of structuring your code and your question is that you define a function that you need to implement. In your case this could look like:
function transcode(sourceAlphabet, destinationAlphabet, s) {
var newWord = "";
// TODO: write some code
return newWord;
}
That way, you clearly state what you want and which parameters are involved. It is also easy to write automatic tests later, for example:
function testTranscode(sourceAlphabet, destinationAlphabet, s, expected) {
var actual = transcode(sourceAlphabet, destinationAlphabet, s);
if (actual !== expected) {
document.writeln('<p class="error">FAIL: expected "' + expected + '", got "' + actual + '".</p>');
} else {
document.writeln('<p class="ok">OK: "' + actual + '".');
}
}
function test() {
testTranscode('abcdefgh', 'defghabc', 'ace', 'dfh');
}
test();

Categories