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

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...

Related

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

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();

How to retrieve an attr value from an nextAll() retrieved list from one element?

Here's the deal: I need to look up for an element, on a list of others HTMLElements, for the next one that has the class '.wanted-class'. I fire/capture a click event in one of the elements from the same class. I ended up with a solutions that looks like this:
$('#id-element-0000').nextAll('.wanted-class');
This should return a list of all the elements that belongs to this class that are after the one I clicked. Something like this:
<div class=​"wanted-class" id=​"id-element-1111" data-wanted=​"6127">​…​</div>
<div class=​"wanted-class" id=​"id-element-2222" data-wanted=​"6128">​…​</div>
<div class=​"wanted-class" id=​"id-element-3333" data-wanted=​"6129">​…​</div>
<div class=​"wanted-class" id=​"id-element-4444" data-wanted=​"6130">​…​</div>​
But, I only want the first one. I don't need the others. So I came up (AKA: found on google) a solution that was simply:
$('#id-element-0000').nextAll('.wanted-class')[0];
This obviously return this:
<div class=​"wanted-class" id=​"id-element-1111" data-wanted=​"6127">​…​</div>
That solves the first element problem. But, I can't access the data-wanted attribute on the element. Something like:
$('#id-element-0000').nextAll('.wanted-class')[0].attr('data-wanted');
...or...
$('#id-element-0000').nextAll('.wanted-class')[0].data('wanted');
...simply don't work. And I don't seem to be able to put it into a variable too.
QUESTION: does anyone know how to retrieve the data-wanted attribute from the first element from this list?
UPDATE
Obviously, the better way of doing it was to use next intead of nextAll, BUT I have others elements between elements from this same class. So, next function doesn't apply in this case. And, YES... I've tried.
Wrap it with $() to convert it to jQuery object:
$($('#id-element-0000').nextAll('.wanted-class')[0]).attr('data-wanted');
Or simply use
$('#id-element-0000').nextAll('.wanted-class').first().attr('data-wanted');
When you index over jQuery objects, you will get HTMLElement which doesn't have methods that jQuery has.
You are accessing the first element in the jQuery wrapper set. You should convert it to jQuery object again, or get the first item with .eq method which return jQuery object:
$('#id-element-0000').nextAll('.wanted-class').eq(0).attr('data-wanted');
jsFiddle Demo.

How to access this element with jQuery

I've got this element that's not precisely defined as a div or anything but just white space popping up inside the html. Can't get to it with jQuery to remove it.
Type of element is highlighted in the screenshot.
Im not expert, but maybe you could use .prev() method.
Something like
$('#main .content').prev();
Pure Javascript to select it:
var textNode = document.getElementById("main").getElementsByClassName("filter-navigation")[0].nextSibling;
and remove it:
textNode.parentElement.removeChild(textNode);
jQuery simplifies the selection a bit, but the removal has to be done the same way since jQuery doesn't like removing text nodes:
var textNode = $("#main").find("filter-navigation")[0].nextSibling;
textNode.parentElement.removeChild(textNode);
The answer is not simply.
jQuery can map objects with structure. It's very hard to catch just whitespaces as DOM elements and remove them.
I cant suggest 2 alternatives:
Use jQuery to get parent tag, extract innerHTML and user regex to remove "extra whitespaces" between tags:
$(document).ready(function(){
var container = $('.product-container');
container.html(container.html().replace(/>\s+</i, '><'))
});
Use css to clean how looks my content inside that tag as suggests thirtydog here
Hope this help!

JavaScript String .replace method is replacing all my content?

I have successfully implemented finding and replacing some text with something else in the following way:
$(".class").html($(".class").html().replace(/\text\b/g, '<span class="newclass newclass2">new text</span>'));
When I apply this to my element 'class' it finds all the 'text' and replaces with 'new text' and everything relating to the new classes.
However, if I have more than one element on the page with the same class, it replaces all the classes with whatever text is in the first class.
For example, if my first class has the content "Hello everyone", when the script is applied to this class, it works fine. Any subsequent class of the same name is then replaced with "Hello everyone". These also have the function applied in the same way as the first occurrence of that class.
IE, it applies the script, then replicates this in every single class of the same name on the page.
I do not understand why it would do this, and rather renders the function pointless in many ways if it can't be used to change text throughout different sections without setting up new scripts and different classes.
Hopefully there is something simple at work here that I am not aware of, any help would be much appreciated.
Many thanks
Richard
That is the nature of class selectors--the .html(...) will replace the HTML of everything that matches the .class selector.
If you want to replace text in each individual .class element, you can use the .each function. (There are probably jQuerier ways, too.)
$(`.class`).each(function(n, el) {
var myHtml = $(this).html();
myHtml = mungeIt(myHtml);
$(this).html(myHtml);
});
If you want to select only an individual .class element, then you either (a) don't really want to be using classes, but IDs, or (b) need to understand enough of your structure or the context you wish to operate in to select only the targeted DOM element.
(And hope the structure or context doesn't change without a corresponding code update.)
You're specifying a class with the jQuery selector $(".class") That's what the period indicates. jQuery has a ton of selectors to choose from. A list is provided in the documentation here: http://api.jquery.com/category/selectors/
Also, I'd look at http://api.jquery.com/hasClass/ for your problem as you could then use if...then statements to not run into others
Dave is right about needing to use the .each method. We need to loop through each element at a time because .html() will only return the first element when there are multiple matches.
Try:
$('.class').each(function() {
$(this).html($(this).html().replace(/someWord/g,'withAnother'));
});

Prototype.js get text from an element

I'm new to Protoype.JS and just testing it a bit because I heard it was good, but I'm stuck quite quickly.
As easy as this is with jQuery, it seems to be the end of the world to get the text in an element. I've tried innerHTML in multiple ways but the only thing I can get is "undefined".
alert($$('.mnu_item').innerHTML);
alert($('content').innerHTML);
None of these work.
Content is a div with id "content" and .mnu_item is an anchor tag with class ".mnu_item".
I don't get what the problem is, probably something stupid but it would be great if somebody could point me in the right direction!
EDIT: I've found that it isn't the innerHTML that doesn't work but it's the class selector. The second line in the code above does work. How can I select an element by its class in the latest Prototype version if this isn't the correct way?
Has the DOM loaded when you run your script? If you're not running this code in a window.onload or by placing it at the end of the body, then the elements by not exist when it runs.
Try placing your script just inside the closing </body> tag.
<body>
<!-- my content -->
<script type="text/javascript">
alert($('content').innerHTML);
</script>
</body>
Also, your first line is selecting correctly, but will return an Array of elements, so innerHTML will be undefined.
To iterate the Array, you can do this:
$$('.mnu_item').each(function(val,i) {
alert(val.innerHTML);
});
or if you want to end up with an Array of the innerHTML values, do this:
var values = $$('.mnu_item').map(function(val,i) {
return val.innerHTML;
});
Make sure the DOM is loaded before you run these tests:
$(document).on('dom:loaded', function () {
/* code to execute after dom has loaded */
})
The first line of code $$('.mne_item') doesn't work because $$ gives back an array of all elements matching the css rule. So $$('.mne_item') gives an array of all dom elements which has the class mne_item. You can ask the first one by using the first method or iterate over all items like this:
$$('.mne_item').each(function(elem) {
// elem is the li elements extended by all Element methods of prototype
});
If you use $ in jQuery, it actually uses a similar pattern but hides the each construct. It just applies the chained method to all elements or just the first.
The second line of code $('content').innerHTML should work. $ is a shortcut for document.getElementById so it should give you a DOM node back. The reason why this doesn't work is there is no node where id = content, probably because the dom isn't loaded yet.
For more info about the methods of prototype look at the api: http://api.prototypejs.org/
Also check the default DOM methods: http://quirksmode.org/dom/w3c_core.html
$('content').innerHTML should work. Check your HTML, ensure the ID is unique.
var text = $$('label[for="display_on_amazon"]').first().textContent;
Above code worked for me.
Regarding, $$('.mnu_item').innerHTML
When you are trying to fetch with class selector, prototype returns array of multiple elments, by using [0] or first() method system will point at the first element in that array, after that you can use innerHtml (to get html inside the element) or textContent (to get text content of that element, native javascript method)

Categories