javascript removes only every second element - javascript

I've discovered a Problem ...
I'm writing a userscript for grease- and tampemonkey which should change a websites look.
One of my tasks is to remove every image with the title New Post
(<img src="..." title="New Post" alt="...">)
i have the following snipplet:
elements = document.getElementsByTagName('img');
alert(elements.length); // FIRST
for (i=0; i < elements.length; i++) {
image = elements[i];
if (image.title.search(/New\ Post/) > -1) {
image.remove();
}
}
alert(i); // SECOND
This snipplet removes images, but only every second.
The first alert gives me the number 19 but the second alert gives 10 ...
The script should delete every image tag with the given title.
What i'm doing wrong?

It looks like you're removing elements whilst looping through the list you're removing them from. At the point where you've removed more than are left, i is the same as elements.length so the loop exits before they're all removed.
Try removing them in reverse order:
for (i=elements.length - 1; i >= 0; i--) {
image = elements[i];
if (image.title.search(/New\ Post/) > -1) {
image.remove();
}
}
This way removing elements from the end of the list shouldn't affect your position in the list.

Because document.getElementsByTagName('img') returns a live list, that means when you call remove() on an element in the returned list the removed item will get removed from the array also.
document.getElementsByTagName
Returns an HTMLCollection of elements with the given tag name. The
complete document is searched, including the root node. The returned
HTMLCollection is live, meaning that it updates itself automatically
to stay in sync with the DOM tree without having to call
document.getElementsByTagName() again.
try
var log = (function() {
var $log = $('#log');
return function(msg) {
$('<p/>', {
text: msg
}).appendTo($log)
}
})();
var elements = document.getElementsByTagName('img');
log('initial: ' + elements.length);
for (i = 0; i < elements.length;) {
image = elements[i];
if (image.title.search(/New\ Post/) > -1) {
image.remove();
log('remove: ' + elements.length);
} else {
i++
log('not: ' + elements.length);
}
}
log('end: ' + elements.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img title="New Post" src="//placehold.it/64/fff000" />
<img title="New1 Post" src="//placehold.it/64/000fff" />
<img title="New Post" src="//placehold.it/64/fff000" />
<img title="New1 Post" src="//placehold.it/64/000fff" />
<img title="New Post" src="//placehold.it/64/fff000" />
<img title="New1 Post" src="//placehold.it/64/000fff" />
<div id="log"></div>

Only increment the loop counter if you're not removing an image:
for (i=0; i < elements.length; ) {
image = elements[i];
if (image.title.search(/New\ Post/) > -1) image.remove();
else i++;
}

Related

Using getAttribute with addEventListener in Javascript

In javascript I create some html to display 5 game characters in a div class named 'characters':
var element = document.getElementsByClassName('characters');
for(var i in characters){
// build the character list
element[0].innerHTML += '<div class="char-container"><img
src="'+characters[i].img.default+'" alt="'+characters[i].name+'">
<h2>'+characters[i].name+'</h2><span class="type '+characters[i].type+'">
</span></div>';
}
In Javascript I add a click event that i want to return the game character name:
var element = document.querySelectorAll ('.characters, .char-container');
let index = 0;
console.log ("element "+element.length);
for( index=0; index < element.length; index++ ) {
clickerFn = function(){
var attribute = (this).getAttribute('h2');
alert("Hello World! +name "+attribute);
}
element[index].addEventListener('click', clickerFn, false);
} // for
This returns a null :-(
Question: in Javascript how do I use getAttribute to get 'character.name' ( what's contained in
Thanks
steve
You can't. h2 is not an attribute. <h2> is an element.
this.querySelector('h2').textContent;
See also:
Attribute
Element
querySelector
type selectors
textContent

how to delete any content after jquery prepend() inside a loop

i am doing a search button and each time the user searches for a movie, i prepend the photos api in the html div. All i want to do is when a user searches again for another movie i want the previous content to be deleted, ( any content after the prepended one). Here is how my code looks like:
HTML:
<div id="Search-Results"></div>
jQUERY:
$.ajax(settings).done(function (response) {
for(var i=0; i < results.length; i++)
{
var s = '<span><img src="http://example.com/test.jpg"> </span>';
$("#Search-Results").prepend(s);
}
});
Example:
When the user searches for avatar movie and then for godfather, i want the avatar images to be deleted. The godfather will be pretended into the div and the avatar photos that are next to godfather will be removed.
Note that the code is inside a for loop and i get only 1 image with .html
Try this one
$("#Search-Results").html("");
for(var i=0; i < results.length; i++) {
var s = '<span><img src="http://example.com/test.jpg"> </span>';
if (i == 0){
$("#Search-Results").html(s);
}else {
$("#Search-Results").prepend(s);
}
}
For the very first photo in the loop use .html(), use .prepend() for the rest.
for(var i=0; i < results.length; i++) {
var s = '<span><img src="http://example.com/test.jpg"> </span>';
$("#Search-Results")[ i ? 'prepend' : 'html' ]( s );
}
This function will simply overwrite the innerHTML
$("#Search-Results").html(s);

removing div from html in chrome extension

I am trying to remove the following div from a page with my chrome extension
HTML (TO REMOVE)
<div class="base-popup js-base-popup"><div class="js-obscurity base-popup__obscurity"></div>
<div class="base-popup__indent"></div>
<div class="base-popup__wrap">
<div class="base-popup__container clearfix base-popup__container -decor" style="width:500px;">
<i class="s-icon -m -close base-popup__close js-close"></i>
<div class="base-popup__content js-content"><div><div class="s-text">Sample Text.
<!-- close tag -->
</p>
<!-- close tag in translate -->
</div></div></div>
</div>
Here is the JS in my content script
function removeElementsByClassName(names) {
var els = document.getElementsByClassName(names),
i, element;
for (i = els.count - 1; i > 0; i -= 1) {
element = els[i];
element.parentElement.removeChild(element);
}
}
removeElementsByClassName('base-popup js-base-popup');
getElementsByClassName only accepts a single class name, but you're giving it two. Since the HTML you've shown only has a single element that has either of the two classes you're using, if that's the only element you want to remove, just pick one:
removeElementsByClassName("base-popup");
// or
removeElementsByClassName("js-base-popup");
Alternately, you could use querySelectorAll with a CSS selector:
function removeElementsBySelector(selector) {
var els = document.querySelectorAll(selector),
i, element;
for (i = els.count - 1; i > 0; i -= 1) {
element = els[i];
element.parentElement.removeChild(element);
}
}
Then if you want to remove elements that have either class:
removeElementsBySelector('.base-popup, .js-base-popup');
Or if you only want to remove a single element that has both classes:
removeElementsBySelector('.base-popup.js-base-popup');
And as this is a Chrome extension, you can do that rather more simply with Array.from, forEach, and Element#remove:
function removeElementsBySelector(selector) {
Array.from(document.querySelectorAll(selector)).forEach(element => {
element.remove();
});
}
your javascript is completely wrong. the right way:
function removeElementsByClassName(names){
names=names.split(" ");//you just get elems by one class so you need to split it into multiple operations
for(var a=1;a<names.length;a++){//ability to remove multiple classes
removeElementsByClassName(names[a]);
}
var els = document.getElementsByClassName(names[0]);
for (var i =0; i<els.length ; i++) { // its length not count
var element = els[i];
element.parentElement.removeChild(element);
}
}
removeElementsByClassName('base-popup js-base-popup');
this removes all elements that contain one of these classes, if you wanted sth else see the other solution.

Trouble with finding class element names in Javascript

I'm trying to grab the Names of some Class Elements in a document (there are several of them) and rotate through them.
The HTML code of the site looks like this:
<div class="parent">
<div class="item">
<a class="item-name" href="http://somerandomurl.com">Relevant Item</a>
If I wanted to grab the URL I know the solution already:
function searchItem(itemname) {
listings = $(".item-name");
for(var i = 0; i < links.length; i++) {
element = listing[i];
if(element.href.indexOf(itemname) !== -1) {
return true;
}
}
}
In this case however, I don't want to compare the URL against another URL, I need to grab the Title off the "item-name" class as String and compare it to other Strings.
How can I manage to do this? I have tried a few things already, like listings = $(".market-name market-link").text();.
First, yo are looping through the wrong variable.
You should loop through listing instead of links
Then compare it to the element HTML:
function searchItem(itemname) {
listings = $(".item-name");
for(var i = 0; i < listing.length; i++) {
element = listing[i];
if(element.html().indexOf(itemname) !== -1) {
return true;
}
}
}
function searchItem(itemname) {
if($('a.item-name:contains("' + itemname + '")').length) {
//console.log("true");
return true;
}
}
jsfiddle

Javascript - getAttribute not working with getElementsByTagName

I want to detect the first letter of the src in an img tag with JavaScript and display an alert if the first letter does not match 'l' :
HTML :
<!DOCTYPE html>
<html>
<body>
<script src="imgDetect.js"></script>
<img src="l.jpg" />
<img src="a.jpg" />
</body>
</html>
Javascript :
x = document.getElementsByTagName('img').getAttribute('src');
if (x.charAt(0)!=='l'){
window.alert("message")
}
The problem is that the getAttribute does not work with thegetElementsByTagName.
The alert will show if getElementsByTagName is replaced by getElementById, (for only detecting single elements),
I would like it work across all tags in getElementsByTagName
It is because getElementsByTagName returns a NodeList object, which is an array like object with reference to multiple elements.
So document.getElementsByTagName('img') does not have a method called getAttribute, calling that will result in error. Instead you need to iterate through the list and test each element
x = document.getElementsByTagName('img');
for (var i = 0; i < x.length; i++) {
if (x[i].getAttribute('src').charAt(0) !== 'l') {
window.alert("message")
}
}
Demo: Fiddle
Also in your script, you have included the script in the page header, which when is executed the body of the pages is not yet loaded so, document.getElementsByTagName('img') won't return any elements.
You can use the window's load method to execute your script or move the script to bottom of the page
Using onload
window.onload = function () {
//this part of the script will be executed after the document is loaded completely
var x = document.getElementsByTagName('img');
for (var i = 0; i < x.length; i++) {
if (x[i].getAttribute('src').charAt(0) !== 'l') {
window.alert("message")
}
}
}
Script at the bottom
<img src="l.jpg" />
<img src="a.jpg" />
<script src="imgDetect.js"></script>
getElementsByTagName returns an array. You need to grab the element from the list before further accessing its attributes. Below is the updated code:
var images = document.getElementsByTagName('img');
for(var i = 0; i < images.length; i++) {
if(images[i].getAttribute('src') !== 'l') window.alert("message");
}

Categories