Click outside element - JQuery - javascript

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

Related

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/

insert current element before previous one

I'm checking to see if element is last in the container div by getting length on next element with class .item (if there is such element, it means that I am currently not at the end of the container div)
if($(this).next('.item').length < 1) {
console.log('element is last');
}
In case if it is last, I want to move it up, i.e insert it before previous .item so it now becomes second last.
I looked into .insertBefore() , however I don't explicitly know which "before" element to target.
You can use the :last selector to get the last element in a matched set. From there you can use insertBefore() and prev() to move it as required. Try this:
var $last = $('.item:last');
$last.insertBefore($last.prev());
Example fiddle

Check if a div has any children

I have the below code that checks to see if any of my divs has the class "wrong" and if so it shows the jQuery UI dialog box. However i want to extend the code so that it checks those divs and if there are any that are empty it should not show the dialog box.
I've looked around and some people are suggesting using children().length > 0 to accomplish this, but I'm not sure how to write this with my code.
js:
$("#run").click(function() {
if ($("[id^='Drop']").hasClass("wrong")) {
$("#dialog1").dialog("open");
}
});
The following selectors could be used to test if an element is empty or not:
:empty matches elements that have no children (thus, empty)+
:parent matches elements that have children+
Now, rephrasing your statement:
... so that it checks those wrong divs and if
there are any that are empty they are all full it should
not show the dialog box.
You would write:
var $allWrong = $("id[^='Drop'].wrong"),
$notEmpty = $wrong.filter(":parent");
if ($allWrong.length && $allWrong === $notEmpty) {
// show dialog
}
+ Text nodes are counted when counting children. <span> </span> contains a text node which contains a whitespace. Therefore it matches :parent and does not match :empty.
The logic consists of two parts:
Finding elements with id property starting with "Drop" and having the .wrong class.
Checking whether any of those elements are empty.
To do this, I'm saving the first step in an intermediate variable, before doing the final condition:
var $wrongFields = $('[id^="Drop"].wrong');
if ($wrongFields.length && !$wrongFields.filter(':empty').length) {
// at least one field exists with:
// - id starting with "Drop"
// - class of "wrong"
// and none of those fields are empty
$("#dialog1").dialog("open");
}
Demo
This would also work
$("#run").click(function(){
if ($("[id^='Drop']").hasClass("wrong") && $("[id^='Drop'].wrong:empty").length ) {
$( "#dialog1" ).dialog( "open" );
}
});

how to use the closest function using specific div

I need jquery to get the closest id,once the the image is visible.
this is my query so far
(...)
if(isonscreen)
{
//this works, but I need it to find only images inside the content-bubble div tag
// and of course this grabs any image no matter what div the image is inside of
console.log($(this).closest('img').attr('id'));
}
(...)
<div class="content-bubble">
<h2>{{imageTitle}}</h2>
<img src="loading.gif" id="lazyload{{imgId}}" class="content-bubble-img"">
</div>
I've tried this but its not working and returns undefined
console.log($(this).closest('.content-bubble-img').find('img').attr('id'));
console.log($('.content-bubble-img').closest('img').attr('id'));
I thing you want the function find(), not closest().
closest finds the nearest parent of an element, while find().filter(':first') finds the first children inside an element. Or to say it with the doc's words:
closest:
For each element in the set, get the first element that matches the
selector by testing the element itself and traversing up through its
ancestors in the DOM tree.
find:
Get the descendants of each element in the current set of matched
elements, filtered by a selector, jQuery object, or element.
http://api.jquery.com/closest/
http://api.jquery.com/find/
To comment your code:
console.log($(this).closest('img').attr('id'));
This is actually pretty bad since images cant have children, this does only work since closest() returns the selected element itself which is the image when you use $(image).closest(). Replace closest with find and you're good to go.
If u have to find all images inside "content-bubble div" no matter what div the image is inside of then use this :
$('.content-bubble img');
First of all it would be much easier to fully understand what you're trying to achieve if you have added a fiddle of it.
Nevertheless I'm guessing that you're checking whether an image is currently visible - which means that in this piece of code
(...)
if(isonscreen)
{
console.log($(this).closest('img').attr('id'));
}
(...)
$(this) actually refers to the image you're interested in - thus you might want to simply retrieve its id attribute with $(this).attr('id')
Since you want to limit it to images which are placed in divs with a specific class, you might just want to check if one of its parents has class '.content-bubble', by
$(this).parents('.content-bubble').length
You may also use closest, since it actually traverses up the DOM tree from the element you specified, and:
if($(this).closest('.content-bubble').length)
which in this case would return true when $(this) or any of its parent has class .content-bubble
I'm using the espy plugin for jquery
This is how you find the id of the nearest image inside a div tag
once the image is visible
$('.content-bubble-img').espy(function (entered, state) {
if (entered)
{
// element entered the viewport
// state === 'inside'
console.log('element entered viewport');
console.log($(this).closest('img').attr('id'));
}
else
{
// element left the viewport
if (state === 'up')
{
// element is now above the trigger area
console.log('element left the viewport');
}
else if (state === 'down')
{
// element is now below the trigger area
console.log('element below the trigger area');
}
}
});

jQuery if then slideshow issue

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
}

Categories

Resources