Testing if elements are hidden - javascript

Ok guys so I am testing if elements are hidden, problem is if the parent element is hidden then the children are considered hidden as well so the line that I append is being appending even if the children elements that aren't technically "display:none"
function checkIfVisible() {
var checkLeft= $('#left').children('.module').filter(':hidden');
if(checkLeft.length > 0) {
if(!$('.resetLeft').length) {
left.prepend('<span class="resetLeft">Reset Left Widgets</span>');
}
}
I run this script on page load, and when ever any of the children elements are clicked to be hidden. How do I stop the script from assigning the prepended element from being added if the parent elements is hidden but none of the children are hidden (Display:none) in style?
So basically.
If #left is hidden (parent) and none of the children are I don't want the resetLeft to be prepended. But if #left is hidden and 1 or more of the children of it are display:none then prepended. even if left isn't hidden I need to this work as well.

This should do it:
var visible = $('#left').is(':hidden') && $('#left').children('.module').filter(function() {
return this.style.display === 'none';
}).length === 0;
But this seems like a hack. Why are you forced to do this?

I took what Blender sort of said to do but I changed it around to work just the way I wanted. I used the && and logical operator...
function checkIfVisible() {
var checkLeft=
$('#left').is(':visible')
&&
$('#left').children('.module').filter(':hidden').length > 0;
if(checkLeft) {
if(!$('.resetLeft').length) {
left.prepend('<span class="resetLeft">Reset Left Widgets</span>');
}
}
This worked wonderfully for me, and all I did was add the function to the click function of showing the #left element!

Related

Run a Javascript function when clicking outside div1 AND div2

Trying to run a Javascript function only if click outside div1 AND div2. If clicked inside div1 or div2, nothing should happen. Any idea how I could achieve that? Example: I would need div2 to be set display: noneand additionally add styles to div1 when clicked outside the divs.
var x = document.getElementById("mega-menu");
document.addEventListener('mouseup', function(e) {
if (!(x.contains(e.target) || document.getElementById("menu-item-136").contains(e.target))) {
x.style.display = 'none';
var elem = document.querySelectorAll("#menu-item-136");
elem.forEach((elem) => {
elem.style.backgroundColor = "red";
});
}
});
This is the furthest I could get. But at the moment, div2 (mega-menu) also gets hidden when clicked on the menu item... Hope you understand what I mean...
Thanks
Can you complete your sample code above? I've added elements to your snippet, but can't duplicate your problem. It seems to be working for me.
Also a couple of off-topic best practices:
the HTML standard doesn't allow for elements with duplicate IDs. If you have more than one element with id #menu-item-136, you should be using a class instead of an ID.
Get both elements outside the event listener...more efficient (like you're already doing with #mega-menu)
Instead of having an if statement with a nested block, do an if...return instead. That way your code is less indented.
var x = document.getElementById('mega-menu');
var y = document.getElementById('menu-item-136');
document.addEventListener('mouseup', function(e) {
if (x.contains(e.target) || y.contains(e.target)) return;
x.style.display = 'none';
y.style.backgroundColor = 'red';
});
div { border: 1px solid black; }
<div id='mega-menu'>mega menu</div>
<div id='menu-item-136'>menu 136</div>
Looks like from this code,
document.querySelectorAll("#menu-item-136");
There are multiple elements with id "menu-item-136" as you are looping through the result.
First of all If there are multiple elements with same Id, It is not a valid HTML.
Thats why
document.getElementById("menu-item-136").contains(e.target)
this results in false, as it may have selected wrong element other that what you have clicked.
Even if you use class to get the elements, it may still fail as querySelector based on class will still results in returning multiple elements.
Instead of checking if your target element is contained in the div's - use a check to see if the element parent hierarchy have class name that you add for menu-item div.
if( e.target.closest(".container-class"))
So now you are just checking if current target have any parent with menu-item's class.

Bring to front with appendChild - can't use text field (JavaScript)

I want to use appendChild to bring div elements to front in a simple web application. I listen for click or mousedown (I have tried both) and then reappend whatever has been clicked to the main div container. Like this:
JavaScript
document.querySelector("#container").addEventListener("click", function(event) {
for (var i = 0; i < this.children.length; i += 1) {
if (this.children[i].contains(event.target)) {
this.appendChild(this.children[i]);
}
}
});
However, when I try this in Firefox the text fields in the div elements becomes unselectable. You can't put the marker in the text fields. It works in Chrome but not in Firefox. What could be the cause of this and how can I fix it?
Currently, because of this problem, I am using a different method with z index. But I would prefer to use appendChild as it has other advantages.
Thanks in advance.
This is a direct consequence of the appendChild which temporarily removes from DOM the child that contains the clicked Element (including when clicking to select text or to put caret / focus in a text input field), to re-append it at the end of the div children (but the text selection is now gone).
A simple workaround would be to leave the clicked child in DOM, but move its below siblings up until the clicked one is the last child.
document.querySelector("#container").addEventListener("click", function(event) {
var found,
children = this.children;
for (var i = 0; i < children.length; i += 1) {
if (children[i].contains(event.target)) {
//this.appendChild(children[i]); // Do not detach from DOM.
found = children[i]; // Leave it in place.
} else if (found) {
this.insertBefore(children[i], found); // Swap with found sibling.
}
}
});
Demo: https://jsfiddle.net/x53eh5b3/1/

jQuery: Toggle class on one element, remove same from all other

new here and deeply hoping I'm not missing a stupid syntax flaw. I was thinking that my problem is a fairly common one, but somehow nothing has helped so far in my specific case.
There is a simple inline-block list of Image Galleries which are zoomable to fill the parent width. As soon as one is zoomed through click on a child, the others should unzoom by stripping of the class which maximizes them. Nothing more to it.
I achieved the first part via the following jQuery (where the problem is hidden in the for-loop, I think):
$(".zoom").click(function() {
var target = $(this);
target.closest('div.product-item').toggleClass('maximized');
var ot = document.getElementsByClassName('product-item');
for (var i = 0; i < ot.length; i++) {
if (ot[i] !== target) {
ot[i].removeClass('maximized');
}
}
});
So: Some .zoom classed element is clicked, its parent is toggled to maximize and a for loop checks all other elements of the same class as the parent and removes the .maximized class.
The reason the script is constructed with a for-loop and a removeClass is so that the same .zoom elements are able to minimize their parent elements, not only to maximize them.
Im not a javascript professional, but to my knowledge this should work in principle. Am I missing anything here?
This post from a year ago addressed a similar problem but didn't help in my case: jQuery onClick: How to add class to element and remove from all others
You can find a pen to see the script in action here.
$(".zoom").on('click',function() {
var target = $(this);
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').toggleClass('maximized');
});
you can use
if(target.closest('div.product-item').hasClass('maximized')){
$('div.product-item').removeClass('maximized');
}else{
$('div.product-item').removeClass('maximized');
target.closest('div.product-item').addClass('maximized');
}
JSFIDDLE

Select empty element in TinyMCE on click

I would like to have the behaviour of the img element applied to another inline element: when clicking on it, it should get selected.
Specifically, I'd like to have an empty q or span tag and when the user clicks on it he should be able to add some attributes. I've written a plugin that works similar to the link-button but it doesn't work for empty elements because they never get selected in the first place. The reason for all this is that I want to replace these elements on the server with a footnote generated from the saved attributes.
I found how it's done for the img element, from tinymce/jscripts/tiny_mce_src.js:
// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
// WebKit can't even do simple things like selecting an image
// This also fixes so it's possible to select mceItemAnchors
if (tinymce.isWebKit) {
t.onClick.add(function(ed, e) {
e = e.target;
// Needs tobe the setBaseAndExtend or it will fail to select floated images
if (e.nodeName == 'IMG' || (e.nodeName == 'A' && dom.hasClass(e, 'mceItemAnchor'))) {
t.selection.getSel().setBaseAndExtent(e, 0, e, 1);
t.nodeChanged();
}
});
}
But when I try to copy and adapt this I run into the problem taht e.target is already the surrounding paragraph element instead of the empty q element I clicked on (I've styled it with CSS's :before pseudoclass). At least on WebKit that's what happens. In Firefox it actually works, when using a double click instead of a single click.
Thanks for your help.
I finally got it working! Thank you Thariama for your help :)
Note: important is that the q element is styled with display: inline-block; Otherwise you'll never be able to select it.
//makes an empty q.citation tag selectable
ed.onClick.add(function(ed, e) {
e = e.target;
var dom = tinyMCE.activeEditor.dom;
if (e.nodeName == 'Q' && dom.hasClass(e, 'citation') ) {
ed.selection.select(e);
//add class 'selected' for styling
dom.addClass(e, 'selected');
ed.onNodeChange.add(function(ed, cm, n) {
//remove class 'selected'
dom.removeClass(e, 'selected');
});
}
});

jquery visibility selector

I'd like to know if there's anything incorrect in the following :
if($('#three').is(':visible')) {
alert("visible");
} else {
alert("hidden");
}
Thanks
Your code seems correct to me. However, visible selector on jQuery defines a not visible elements if:
They have a CSS display value of none.
They are form elements with type="hidden".
Their width and height are explicitly set to 0.
An ancestor element is hidden, so the element is not shown on the page.
Is it the case in your test?
Some others importants aspect regarding this selector is that elements with visibility: hidden or opacity: 0 are considered to be visible!
Also, since 1.3.2, this selector has evolved, as stated in the changelog.
Better you check this : :visible Selector
<script>
if( $('#foo').is(':visible') ) {
// it's visible, do something
}
else {
// it's not visible so do something else
}
if( $('#foo').is(':hidden') ) {
// it's hidden, do something
}
else {
// it's not hidden so do something else
}
</script>
Make sure that #three has display attribute set to some default value. E.g. Display="none"

Categories

Resources