jQuery if then slideshow issue - javascript

I've got a slideshow that's manually controlled with previous and next buttons. It works fine, but using insertBefore and insertAfter feels sloppy, so I'd like to explore some other methods. Instead, I'm thinking "if this is the last image, go back to the first + the opposite for going backwards.
Here's my code, but I'm not getting the desired result when it hits the last image (where it should fade in the first and start all over.
Syntaxual? if (slide == $('.z:last')) looks fishy to me.
Test site: http://brantley.dhut.ch/
Thanks!
Here's my JavaScript:
$('#next').click(function() {
var slide = $('.z:visible'),
next = $('.z:visible').next();
slide.fadeOut(400, function() {
slide.removeClass('active');
if (slide == $('.z:last')) {
$('.z:first').addClass('active');
bromance();
$('.z:first').fadeIn(400);
} else {
next.addClass('active');
bromance();
next.fadeIn(400);
}
});
return false;
});

Try this:
if (slide[0] == $('.z:last')[0]) { ...
jQuery doesn't return a reference to a DOM element directly, it returns an object that is array-like, where each array element is a DOM element matching the selector you used. This means comparing the results from two selectors is comparing two different array-like objects which isn't ever going to match even if they contain the same elements. Compare the first element in each array instead (because in your case you're expecting only one element anyway).

why don't you use slide = $('.active') and try :first-child instead of :first

next = $('.z:visible').next();
check the below condition and specify the next image accordingly.
if($('.z:last')){
next = $(".z:first")
}
else{
next = $('.z:visible').next();
}

I would compare element ids for equality.
Change if (slide == $('.z:last')) to if (slide.attr('id') === $('.z:last').attr('id')).
Or, you can test to see if the last slide is visible like so:
if ($('.z:last:visible')) {
// last slide is visible
}

Related

How to iterate over elements of same class to find first visible

If I had multiple objects of a class present, but only some are visible, what would be the best way to find the first visible one. I currently try:
browser.waitForElementVisible('.myClass', timeOut)
which sees all of the elements, but will only act on the first found. OR
browser.waitForElementVisible('(//div[#class="myClass"])[1]')
which specifies an index, but that may or may not be visible, since new data is loaded every time the page refreshes.
I need to loop through all present and just click on the first instance of one that is visible. I know I can achieve this through custom commands, but I'm new to js and nightwatch, so I'm not sure how to go about it.
I think I would probably use .elementIdDisplayed() to accomplish this.
The snippet below should help you
get a list of the elements
check if one is displayed
If displayed, click on the element
Usually I would use a forEach loop but since you can't break out of that without doing some hacky stuff just use a regular old for loop like this:
browser.elements('css selector', '.myClass', function(elements) {
for(let i = 0; i < elements.value.length; i++) {
browser.elementIdDisplayed(elements.value[i].ELEMENT, function(isDisplayed) {
if(isDisplayed.value) {
browser.elementIdClick(element.value[i].ELEMENT);
break; //this will break out of the loop when you find the first displayed element
}
});
}
});

jQuery .remove() Not Working After Valid Selection of Element

JSFiddle: https://jsfiddle.net/coh1xr77/5/
I need to delete an <LI> DOM Element correctly selected with a Selector based on its exact content. My list contains a set of Time LI's and my choice is to delete the first one in the list, 12:15am, based on the exact text match, when I click the button.
I can see that my selection is correct because I'm getting an [Object] reference in the alert box, rather than "Undefined".
However, the subsequent remove() on this element does nothing: the element remains.
var myselection = '12:15am';
$('#remove').click(function() {
var current = $('.ui-timepicker-list li').filter(function() {
return $(this).text() === myselection;
});
alert('current = ' + current); // This works, element found
$(current).remove(); // This does nothing (or doesn't remove properly)
});
You need to change the condition to check if the li's innerText starts with the selected time string. Like: $(this).text().indexOf(myselection) == 0
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/11/
Update
Considering that all time values have the bracketed relative time strings at the end, you could try splitting based on that bracket (, and compare with the first part of that string. Like: $(this).text().split('(')[0].trim() == myselection
Here's the fiddle with that: https://jsfiddle.net/coh1xr77/12/
Update 2
If you are absolutely certain that the structure of li elements will not change, you could access the text using the childNodes. Like: $(this)[0].childNodes[0].textContent == myselection;
Here's the updated fiddle: https://jsfiddle.net/coh1xr77/14/

Click outside element - JQuery

I'm looking to understand how to hide an element when you click outside.
Here's one from:
https://css-tricks.com/dangers-stopping-event-propagation/
$(document).on('click', function(event) {
if (!$(event.target).closest('#menucontainer').length) {
// Hide the menus.
}
});
Could someone break this down for me please? I don't understand why we need to use the length property?
Also does closest traverse up to the top of the DOM from wherever it starts and then stop one it reaches the top?
Cheers
You need to check the length because jQuery queries always return a result, which is empty if nothing was found. Once you check the length you can tell if the click is inside (length > 0, an element was found) or outside (length === 0, no element was found)
Here is a break down:
line 1:
$(document).on('click', function(event) { ... });
binds on any click made in your document (DOM). make use that you unbind (.off('click', .....); after you used it. Otherwise it will be endlessly executing on every click.
line 2:
if (!$(event.target).closest('#menucontainer').length) {
event.target ===(equals) the element that is click in the dom.
.closest('#menucontainer') = get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. Meaning: when there is clicked inside MenuContainer it will return an array with the first '#menucontainer' element. When there is click outside the MenuContainer it will return an Empty array. (no element found).
.length = The default behavior from JQuery is to return an empty array when nothing is found. If you put and empty array in a If statement it will return true. because its an Defined Object. Its defined as an Array. however the number 0 == false. thats with they put .length on the array. It will return 0 (false) when its empty of > 0 (true) when it found an element.
In JavaScript, everything is 'truthy' or 'falsy', and for numbers 0 (and NaN) means false, everything else true.
check NickG his link( Is there an "exists" function for jQuery? )
A jQuery selector will return an array with all the matched elements. If you use an ID as selector such as ('#menucontainer') the length will be 0 or 1. The closest menu will not be found, if we click something outside of the menu, the negation will be true and menu can be hidden.
// Get the current clicked element
!$(event.target)
// Get closest container with this id, bubbling up the DOM
.closest('#menucontainer')
// returns 1 if we clicked something inside the menu and 0 if we clicked something outsite
.length

Element still child of previous parent after moving it

Answer in short: insertAfter() is to be used on the element that you are inserting after another element, not on the element that you want to insert something after. For full code, scroll down.
I have a situation where when the user clicks a button, certain elements get moved to a hidden container, and when the user clicks another button, those elements need to get moved back to their original position.
I do it (in short) like this:
Moving to hidden container:
element.data('original_parent', original_parent);
element.data('original_index', original_parent.index());
element.appendTo(hidden_container);
Moving the items back to their original container:
element.data('original_parent').children().eq(element.data('original_index')).prev().insertAfter(element);
But somehow this isn't working. When I output the children of the original parent to the console, it also lists the elements that are currently in the hidden container as children. Anyone have an idea of how I could fix this?
Your logic may not be not correct as the order in which it is removed and added might deffer – Arun P Johny 1 min ago
You are right. The elements are output to the console first, then I move them, which is why it seemd like an uncorrect parent was being listed as their parent.
Are you sure you're getting any element with doing element.data('original_parent')? – Dhaval Marthak 5 mins ago
An element is being returned for sure.
I have already found out what is happening here. I use the insertAfter function on the original element that I want to insert the element after instead of on the element that I want to insert after the original element. Got my jQuery functions mixed up a bit.
The rest of the code works, though! Full code for those that want to use the idea and come across this post:
function hideNonMatchingLevelElements(jquery_selector) {
var elements = $(jquery_selector);
if (!elements.length)
return false;
var target = $('#js-hidden-level-elements');
if (!target.length) {
console.error('Cannot hide non matching level elements because target cannot be found.');
return false;
}
elements.each(function() {
$(this).data('original_parent', $(this).parent());
$(this).data('original_index', $(this).index());
$(this).appendTo(target);
});
}
function showMatchingLevelElements(jquery_selector) {
var elements = $(jquery_selector);
if (!elements.length)
return false;
elements.each(function() {
// Only show elements that are in the "hidden elements" container.
if ($(this).parent().attr('id') != 'js-hidden-level-elements')
return true; // Continue;
if (!$(this).data('original_parent'))
return true; // Continue.
$(this).insertAfter($(this).data('original_parent').children().eq($(this).data('original_index')).prev());
});
}

executing function if siblings are not ":active"

How would one go about executing a function if an objects siblings do not have the pseudo class ":active" using jQuery? The reason for this question is that I would like to execute that function when the cursor is hovering the certain object and NONE of its siblings are ":active" (basic meaning: I want it to execute when the mouse is hovering the object and is not clicking down on any sibling).
To get the idea:
HTML:
<div class="tobehovered">...</div>
<div class="sibling">...</div>
...
JQuery:
function theOneToBeExecutedOnHover(){...}
$(".tobehovered").mouseenter(function(){
if( ... /* calculation???-ish */) theOneToBeExecutedOnHover();
}
The jQuery doesn't have to be formatted exactly that way. My example is just for principle.
From your hovered element $(this), find the siblings .siblings(), filter the active ones .filter(':active'), and check if you have none left .length === 0
That can be shortened like this:
if ($(this).siblings(':active').length === 0) {
Try this one
$(".tobehovered").mouseenter(function(event){
if(event.target.className == 'active'){
return;
}
//here execute function
}

Categories

Resources