Is there a way to tell if an element is either hidden or is currently in the process of hiding (via an animation)? The only way I can think to do it is to store a flag in the element's data when you call show or hide, but I was wondering if there was another way?
Could you do a custom jQuery selector for it
(function($) {
var endOpacity,
oldStep = jQuery.fx.step.opacity;
$.fx.step.opacity = function( fx ) {
endOpacity = fx.end;
return oldStep(fx);
};
$.expr[':'].hiding = function(obj){
var $this = $(obj);
return ($this.is(':hidden') || ($this.is(':animated') && endOpacity === 0));
};
})(jQuery);
This worked for me (it may require some more testing though).
So just add :hiding it will match hidden elements, and elements that are currently being animated to 0. It will now only match elements that are disappearing, not appearing.
You get the hidden one with $(":hidden") and then the animating ones with $(":animated") and with the :animated check the .queue() if it has the hide method inside.
You can check if the element is animated like this:
if( !$('.your-element').is(':animated') ) {
// do animation...
} else {
return false;
}
Related
I try to think up function which can replace links to text. Image inside a tag should be moved to the wrapper, the original a should be removed.
JS:
var selectors = 'a.mark-video;a.sp5;a>img[alt!=""]'
selectors = selectors.split(";").join(", ");
$(selectors).each(function() {
var current = this;
if (this.nodeName == "IMG") {
current = this.parentNode;
if (current.nodeName != "A")
current = this.parentNode;
if (current.nodeName != "A")
return false;
current = $(current);
}
var wrapper = current.parent();
var new_context = $().append(current.html());
current.remove();
wrapper.append(new_context);
}
);
The problem is
1) that the image is not inserted into the wrapper
2) if it would be inserted it would not have correct position.
I am experimenting using webextensions API (Firefox addon) and I injected the code to site:
http://zpravy.idnes.cz/zahranicni.aspx
In the debugger you can see two wrappers with class="art ". I have removed the first link but image is not inserted. The second one has not been removed yet when debugger was paused after first iteraction.
I hope you can find out why the image is not appended and how to append it to the original position of the element a. I need to find out position of the element a first, and then to move the image into to correct position - that is before div.art-info.
Note: please do not change the selectors string. This is the users input from form field.
Edit:
Almost there:
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).html().replaceWith($(this)); // error: html() result does not have replaceWith...
}
Is this what you're looking for?
https://jsfiddle.net/4tmz92to/
var images = $('a > img');
$.each(images, function(key, image) {
$(this).parent().replaceWith(image);
});
First select all the images that you want to remove the link from, then loop through them and simply replace the parent() with the image.
I have finally solved the problem:
$(selectors).each(
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).replaceWith(
$(this).html()
);
}
);
This works similar. Novocaine suggested not to use $(this).html() but this would skip some images so I prefer to use it.
am constructing a slightly more complex drop down menu system using Jquery's slideDown() and slideUp() animations as well as the "hover()" event.
Now I have a certain element which triggers by "hover()", that another element is being displayed. Unfortunately it's not possible to make those two elements, the only childs of another element (since the trigger is in another table).
Still I want this new element which has been displayed, to show until my mouse leaves BOTH the new element as well as the trigger element.
Is there a way to achieve this?
Thanks in advance :)
I used .mouseenter and .mouseleave to achieve what may you want:
jsFiddle
var groups = {};
groups[1] = {
main: false,
sub: false
};
$('.menu').mouseenter(function(e) {
var $target = $(e.target);
var group = $target.attr('data-group');
var type = $target.attr('data-type');
if (!(groups[group].sub || groups[group].main)) {
$('.sub[data-group='+ group +']').toggle(true);
}
groups[group][type] = true;
});
$('.menu').mouseleave(function(e) {
var $target = $(e.target);
var group = $target.attr('data-group');
var type = $target.attr('data-type');
groups[group][type] = false;
if (!(groups[group].sub || groups[group].main)) {
$('.sub[data-group='+ group +']').toggle(false);
}
});
Just track the group of main and sub item. A little ugly, but hope it may helps.
I have a DIV, that is sometimes hidden, and in this case I don't want that google adds appear/are loaded at all inside this DIV.
What is the best practice to make such a check with javascript?
You should look at the computed style of the node you want, via window.getComputedStyle, rather than the style attribute of the node, as css elsewhere may be effecting it too.
Checking whether a node is covered by another node is much more difficult, one way is to use document.elementFromPoint to find out which node is top-most at a specific point, then do this where your node should be until you're satisfied it's visible. For example, check the centre of the node is your node.
function isHidden(node, checkIfCovered) {
var absPosition = function absPosition(node) {
var x = 0, y = 0,
h = node.offsetHeight || 0, w = node.offsetWidth || 0;
do {
node.offsetLeft && (x = x + node.offsetLeft);
node.offsetTop && (y = y + node.offsetTop);
} while (node = node.offsetParent);
return {x: x, y: y, h: h, w: w};
},
o, style;
if (checkIfCovered && document.elementFromPoint) { // only if supported
o = absPosition(node); // get position & size
o.centre = {x: o.x + o.w / 2, y: o.y + o.h / 2}; // centre of node
if (document.elementFromPoint(o.centre.x, o.centre.y) !== node) {
return true; // another node is in the centre => covered
}
}
do { // loop up over parent nodes
if (node.nodeType === 9) break; // skip #document
style = window.getComputedStyle(node);
if ( style.display === 'none'
|| style.visibility === 'hidden'
|| style.opacity === '0'
) {
return true;
}
} while (node = node.parentNode);
// passed all tests, not hidden
return false;
}
Example usage
isHidden(document.getElementById('myDivId')); // true->hidden
isHidden(document.getElementById('myDivId'), true); // true->hidden or covered
Further things to consider
Is the node located where it is possible to scroll into view? See Fabrizio Calderan's comment.
Now edited in. Are the parent nodes hidden? You may want to loop up the DOM tree to find this out. It's okay if they are covered though, obviously. See Loïc Faure-Lacroix's comment.
if your div has an ID, try this:
if((document.getElementById('your_div_id').style.display=='none') || (document.getElementById('your_div_id').style.visibility=='hidden')){
//its hidden
}else{
//its not
}
you can check it by
var div = document.getElementById('div_id');
if( div.style.visibility=="hidden"
|| div.style.display=="none")
{ alert("div is hidden"); }
var isVisible = element.offsetWidth > 0 || element.offsetHeight > 0;
isVisible will give you is the div hidden or visible.
<script>
function isHidden(divId){
styleValue = document.getElementById(divId).style.display;
if(styleValue == 'none'){
return true;
}
else{
return false;
}
}
</script>
returnValue = isHidden(); //return true if hidden
There are a couple of ways to know if an object is hidden or not. There are couple of ways to find out but the truth is that it's much more complicated than most solution out there.
I can't unfortunately mash it up at the moment but I can tell how to do it.
An hidden object may still have display to something different than none or visibility to default. If parent objects are hidden, then child elements are also hidden but the display attributes remain unchanged.
In other word, you'll have to bubble every parent element until you find an hidden element or the root.
That said, css attributes like display and visibility isn't the only way to hide an element. You can also check for overflow: hidden and if the object is outside of the bounding box.
Pseudo code
def visible(initial, element)
if element.invisible or element.hidden
// Element was simply hidden so false
return false
if element != initial and elemen.has_overflow_hidden && initial.outside(element)
// Here we check if our element is inside the bounding box of a overflow hidden
// Parent.
return false
if element.opacity == 0
return false
if element == element.parent
// reached the root
return true
visible(initial, element.parent)
if (visible(element, element))
do something
else
do something else
As far as I can say, it's unfortunately not handling every cases. But it should be more than enough. It doesn't handle z-index, It might not work well with position absolute, relative and fixed.
In jquery:
$('#div').is(':visible');
$('#div').is(':hidden');
You're looking at the DOM elements (in this case) DIV, CSS property. There are two ways to hide an element.
One is display: none, the other is visibility: hidden.
In jQuery you would then do something like:
if !($('#div-id').css('display') == 'none'){
JAVASCRIPT_TO_LOAD_ADS_GOES_HERE
}
In the case of visibility hidden, do the same, but compare .css('visibility') to hidden.
I have a complex structure of many nested, absolutely positioned elements.
These elements may or may not have their z-index set.
They also may or may not have the same parent element.
I am wondering what is the best / simplest way to return which element is on 'top'. Something like the following...
$(".panel").topMost()
Thanks (in advance) for your help
Do you mean the element with highest z-index:
$(document).ready(function() {
var array = [];
$("*").each(function() {
array.push($(this).css("z-index"));
});
var highest = Math.max.apply(Math, array);
console.log(highest);
});
A plugin is there ..topZindex
$.topZIndex("div");
Try this:
var z = [];
$('.panel').each(function(i, el) {
var $panel = $(el),
zindex = $panel.css('z-index');
z[zindex] = $panel;
});
var topMost = z.slice(-1);
See if you don't specify z-index to absolute elems then last of the element will be on top of other elems, means last element will have a greater highest default z-index calculated by browser itself.
Try this fiddle: http://jsfiddle.net/fLB2W/
var array = [];
$("*").each(function () {
if ($(this).css('position') == 'absolute') {
array.push($(this).css("position")+'<--pos & class -->'+$(this).attr('class'));
}
});
console.log(array[array.length-1]);
I faced similar issue with Modal dialog while displaying jQuery UI datepicker and using event parameters to figure out the clicked icon. Modal dialog overlay was preventing the new datepicker from showing on top of the modal dialog.
The best solution worked in three browsers (IE, Firefox, and Chrome) is:
function topZIndex(target, selector) {
var objs = $(target).parents(selector + '[z-index > 0]');
var a1 = -1;
$.each(objs, function (index, z1) {a1=(z1.style.zIndex > a1)? z1.style.zIndex : a1; });
return a1;
};
using event parameters as follows:
var zIndex = topZIndex(event.currentTarget, 'div')+1;
or
var zIndex = topZIndex(event.currentTarget, '*')+1;
Both combinations will generate same result, however it is more efficient to be specific by specifying 'div' instead of '*'
Then assuming my date picker id is datepickerpanel to set the new zIndex for datepicker
$('#datepickerpanel').css('z-index', zIndex);
This solution provides proper z-index value to place the new object on top of modal dialog.
A selector has yielded me a set of elements. Out the set of elements, I have 1 or 2 elements with CSS attribute display:none. I have to remove these elements and get the elements which have display. How can this be done using JQuery?
You can use .filter().
var displayed = $('mySelector').filter(function() {
var element = $(this);
if(element.css('display') == 'none') {
element.remove();
return false;
}
return true;
});
This will return all elements from your selector thats attribute display is not none, and remove those who's are.
$("selector").is(":visible")
You can also filter out the hidden elements in the original selector:
$("selector:visible")
You can use filter()
var listWithoutDisplayNone = elementList.filter(function(){
if($(this).css('display') != 'none')
return $(this);
});