How do I remove non-visible elements from an entire document? - javascript

I want to use Javascript and JQuery to make a copy of the web page's entire html and remove all elements that are not visible to the user. This is what I've tried so far:
$('html').not(':visible').remove()
However, it does not seem to work. Does anyone know how I can accomplish this?

Right now you are only targeting the <html> element with your selector. You need to iterate through all the elements and check their visibility like this:
$('*').each(function(){
if($(this).not(':visible')){
$(this).remove();
}
});
Even more concise would be to just target hidden elements and remove them as such:
$('*:hidden').remove();
The jQuery API reference states that elements are considered visible if they take up space in the document. So elements that have a height and width greater than 0 are considered visible. This means we should instead look at the computed CSS if you are having issues with the above code removing things that are visible.
$('*').each(function(){
if($(this).css('visibility') == 'hidden' || $(this).css('display') == 'none'){
$(this).remove()
}
});

you are removing html elements which are not visible. you should remove its children.
try this
$('html').children().not(':visible').remove()
EDIT:
as Barmar said this only removes immediate children of html. use other answers to remove all elements.

This should do it:
$("body :hidden").remove();

Related

Determine which element is first and do this

I need to set focus on the first form element or class of ".focus"; whichever is visible or first.
This does not seem to sort through each to determine which comes first?
http://jsfiddle.net/infatti/tdvHJ/1/
$('.focus:visible:first, body:not(:has(.focus:visible)) input:visible:first, body:not(:has(.focus:visible)) textarea:visible:first').focus();
This will locate all visible input elements, textarea elements and .focus elements:
$('input:visible, .focus:visible, textarea:visible')
It will also have them ordered according to their order in the DOM, so the first of those elements in the document will be the first in the jQuery object. To access the first:
$('input:visible, .focus:visible, textarea:visible').eq(0);
and to focus on it:
$('input:visible, .focus:visible, textarea:visible').eq(0).focus();
Note that, as I just found out, jQuery considers elements to be 'visible' if they take up space in the document. So elements with visibility:hidden or opacity:0 will still be considered visible:
http://api.jquery.com/visible-selector/
Like this ?
$('.focus:visible:first, body:not(:has(.focus:visible)) input:visible:first, body:not(:has(.focus:visible)) textarea:visible:first').eq(0).focus();
Fiddle :
http://jsfiddle.net/infatti/tdvHJ/1/
Eq(0) select the first element... ;)
Try:
$('.focus:visible:first').filter(":input").focus();
jsFiddle example
im not sure what you are trying to achieve as there isnt any elements with the class focus. Simply add the class focus to your input element and then us
$('.focus').focus();

Hiding the <p> and showing the <textarea> on a <a> click

I know the title sounds quite easy but the real problem is the markup. I have a link in a div which also in another div but the textarea and the paragraph are in another div so that's why I am having problem on how to show and hide elements in a completely different markuped div from a completely different markuped div.
I saw .parent() and .children() and .siblings(). But they couldn't help me or I think that I was not able to take help of those.
Here's the fiddle.
Here is the JS I tried:
$(".no_link").click(function(e) {
e.preventDefault();
});
$(".edit_offer").on('click', function() {
$(this).parent().parent().siblings().children("textarea").toggle();
});
You can use these selectors, but it will rely on the class username being in the heirarchy as you have in your code:
$(".edit_offer").on('click', function () {
$(this).closest('.username').find("textarea").toggle();
});
jsFiddle example
.closest() will traverse up the DOM until it hits the element with class username, then .find() will go down through the children looking for the textarea.
I did it using find(). http://jsfiddle.net/SZUT8/2/ To make the script more accurate and future-proof you could consider adding a class to the paragraph and matching it, as in here: http://jsfiddle.net/SZUT8/4/
You could always assign an ID (or a class, for multiple) to each of the desired elements ("p" and "textarea" in your case). Then use your ID/class to reference them for the show() or hide() methods, rather than navigating the DOM via parent(), sibling() and children().
Then your click handler will only need the line:
$('#idOfElement).toggle();

Quick way around JQuery's .remove() leaving whitespace in the DOM?

I'm using JQuery's .append() and .remove() functions to add and remove variables from a div.
So the div looks a little like this when things are inside:
<div id="list">
<a>var1</a>
<a>var2</a>
<a>var3</a>
</div>
The problem is when I use .remove() on something in the div, it leaves a space in the DOM. So it looks like this:
var1
var3
I understand why this is happening but is there a simple way to solve this with another JQuery function that might make the div output like this after I use .remove():
var1
var3
Or do I neeed to do something more complicated?
Because your element is actually surrounded in text nodes containing a newline, as it's what your html says. If you don't believe me: http://tinker.io/7f667/1
\n<a>var1</a>\n<a>var2</a>\n<a>var3</a>\n
You don't notice them in display because html isn't (usually) whitespace sensitive.
If you want to remove the surrounding newlines, then tell the DOM to remove them: http://tinker.io/7f667/2
//assuming `list` is your container, and `toRemove` is the element to be removed
list.removeChild(toRemove.previousSibling);
list.removeChild(toRemove.nextSibling);
list.removeChild(toRemove);
Should be trivial to turn that into jquery code if you choose. Just pay attention that the surrounding text nodes are not elements.
The simplest way would be to insert parent() in there to remove the parent container rather than only removing the variable.
So if your code was like this:
$(myVar).remove();
... change it to this:
$(myVar).parent().remove();
Something else you could do if you need to preserve the existance of that particular parent container (like you may be adding something back into it) is to append a class to the parent that hides the container (and consequently the variable you want to remove) but can be repopulated and made visible again later.
.deactivated { display:none; }
$(myVar).parent().addClass('deactivated');
... then later you could do this:
$(myVar).parent().html(newValue).removeClass('deactivated');
Having written all that, you should REALLY probably cache the parent itself as a separate variable.. but you get the idea.
<div id="list">
<a>var1</a>
<a>var2</a>
<a>var3</a>
</div>
<script type='text/javascript'>
var var_to_remove = "var2";
//the anchor with var2 should be removed
$("#list > a").each(function()
{
if($(this).text() == var_to_remove)
{
$(this).detach();
}
});
</script>
You would obviously probably want to change the jquery to make the var_to_remove not hard-coded..and I'm assuming you want it to be on a click handler or something but this is another way to do it...

Will jQuery select hidden elements

If I call .hide() on an element, will/can jQuery select it in a normal dom selector.
If jQuery does normally select hidden elements, what is the proper way to select only visible elements. Can I use a css selector, or is there a more valid way of doing this?
Yes. The hide function only stores the current value of the display css property of your element, then set it to none. So the dom selectors will not be affected by it unless they try to match elements with a particular display css value.
Check it here.
Have a look at the jQuery hide function documentation.
Yes it will count hidden elements.
Yes, it just adds a display:none style to the element... .remove() on the other hand will not show up in counts. But that completely gets rid of it, and unless you store the value somewhere it is not retrievable.
What I'm assuming you want to do is to count the visible items. I would instead do the following:
$('.element').addClass('hide');
var count_of_visible_items = $('.element:not(".hide")').length;
console.log(count_of_visible_items);

jquery .after deleting entire li or table element

I'm seeing a problem using jquery .after to insert a div into an li. Essentially, the action is deleting the entire li...and I'm not sure why. I also saw this kind of problem using .after on different table elements which makes more sense to me because I can see that would break a table.
Take a look at this jsfiddle: http://jsfiddle.net/XrUtq/
The reason I have to do it this way is because I have to come up with a generic way to be able to put a div as CLOSE in the dom as possible to another element which I don't have control over (could be any kind of element). The div will then be relatively/absolutely positioned on the page to go over top the element which it is going after. I'm doing this because we need a solution instead of appending the div to the body, because if the view is changed then that appended element will stay on the page instead of dissapearing with the content which it is supposed to.
I hope I have made the problem clear enough. I've tried approaches like this:
if (nodeName === 'td' || nodeName === 'tr' || nodeName === 'th' || nodeName === 'tbody'){
popover.appendTo(editable.closest(':visible:not(tr):not(td):not(table):not(tbody)'));
}
else if(editable.is(':visible')){
popover.after(editable);
}
else{
$('body').append(popover);
}
but this is not accounting for the current problem with li.
Thanks for help/suggestions!
You're using slightly incorrect syntax (sort of backwards), use this instead:
Change this:
$('<div>Blabablabla</div>').after($('.editable'));
To this:
$('.editable').after('<div>Blabablabla</div>');
Working fixed example
jQuery .after(CONTENT) inserts the supplied content after the element you have selected. The after method should be appended to your jQuery selector. In your code you were placing the selector inside the after method.
I think you were intending to use .insertAfter() which would have worked with your original syntax.
http://jsfiddle.net/XrUtq/1/
$('li').click(function(){
$('.editable').after('<div>Blabablabla</div>');
});
jQuery .after() inserts a target element (the div) after each element in the matched set (the .editable items). The syntax you were using is for jQuery .insertAfter(), an alternative method for doing a similar thing.
$('li').click(function(){
$('<div>Blabablabla</div>').insertAfter('.editable');
});

Categories