How to remove prev . prev object? Javascript .prev().remove(); - javascript

It's like
<input name="fails[]" type="file" size=40 /><br />
<textarea name="apraksts[]">About</textarea>
<a href="#" onclick="remove(this);return false".....>remove</a>
And the javascript:
function remove(obj){
$(obj).prev('textarea').remove();
$(obj).prev('input').remove();
$(obj).remove();
}
Why it doesnt remove INPUT(why it doesnt remove two objects)?
Thanks..

The documentation for prev says it:
Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector.
After you remove the <textarea>, that element is a <br>. Since it doesn't match input, the resulting jQuery object contains no elements. You then remove those 0 objects.
I suspect a better approach to the problem would be to wrap all the elements in a <div> (or a container with more suitable semantics for the context) and remove that (instead of removing each element in turn).

Or you can also use prevAll. That will select all previous sibling elements which are then filtered by your selector:
$(obj).prevAll('input').remove();

Related

Is there a way to skip a specific CSS selector in HTML when using querySelector in JavaScript?

I need to skip this querySelector('input') because in certain instances the input will come second instead of first. Is there a way to label an element in HTML as 'skip this'?
You're free to utilize the full power of CSS syntax there. In your example if you only want to get input if it's the first parent's element then query like this:
querySelector('input:first-child');
Or if you want to get precise use :nth-child selector, or even better, :nth-of-type:
querySelector('input:nth-of-type(1)');
But the best solution would be to mark your input with a class or id and use it instead:
querySelector('.myInput');
You can of course combine it with negation selector:
querySelector('.myInput:not(':nth-child(2)')');
querySelector returns the first Element that matches the selector provided in the method. And why wouldn't it? That's what it's supposed to do.
A.E. the below returns the first input tag it can find on the document from the top-down.
document.querySelector("input");
It will always return the first input tag it can find. You have two options to "skip" the node. You can either write a function to recursively check if the input should be skipped( kind of superfluous and bad looking ) or you can simply be more specific with your selector.
Either way you need to give the input element you want to skip some sort of recognizable trait. That can be a name property or a dataset property or a class or an id - anything that you can programatically check for.
//functional example
function ignoreSkippable() {
let ele, eles = Array.from(document.querySelectorAll("input"));
eles.some(elem => !elem.matches('.skippable') ? ele = elem : false);
return ele;
}
console.log( ignoreSkippable() );
// <input value="second input"></input>
//specific selector example
let ele = document.querySelector("input:not(.skippable)");
console.log(ele); // <input value="second input"></input>
<input class="skippable" />
<input value="second input" />

Get nested element by name

I have a table of elements like this:
<tr id="elementId">
<img name="img" src=""/><br/>
<input name="text" type="text"/><br/>
<input name="button" type="button"/><br/>
</tr>
Each element is exactly the same, except of its id.
I try to update the elements with javascript, but I have no clue how to get the child nodes by their name.
My code:
//get element
var element = list.rows[i];
//update nodes
element.getElementByName("img")[0].src = someImg;
element.getElementByName("text")[0].value = someText;
element.getElementByName("button")[0].value = someOtherText;
The code doesn't work, because element has no function getElementByName.
Is there any other way to get the nodes by their name?
element.querySelector('[name="thename"]') or element.querySelectorAll('[name=2thename"]')
The function is getElementsByName. Elements is plural.
Note that it returns an array-like HTML Collection, so you'll need to grab the first item off it too (with [0]).
Additionally, you might find that your elements aren't actually in your table row as you are missing table cells. Validate your markup: http://validator.w3.org/nu/
In order to select all alements with a tagname in the whole document you may use
listElements = document.getElementsByTagName();
Inside a certain element, you may use
selectedElement = element.getElementsByTagName();
Notice this functions returns an array with the elements selected. If there is only one element, it will be in
listElements[0]
in the first case, or
selectedElement[0]
in the second.

how to use jquery to find an input element with single class

If an input element has multiple classes assigned as below(form-control and hide). How can we find it using single class
e.g. <tr id="10"><td><input class="form-control hide" name="[0].Items" type="number" value="1" /></td></tr>
I've tried the following but it does not work
$('tr#10').find("input[class='hide']").addClass('show').removeClass('hide')
but the following does work
$('tr#10').find("input[class='form-control hide']").addClass('show').removeClass('hide')
But I don't want to use find with multiple classes
$('tr#10 input.hide').toggleClass('show hide');
http://api.jquery.com/toggleClass/
If you insist on using the attribute selector, it has to be this:
$("tr#10 input[class~='hide']").toggleClass('show hide');
which matches input elements amongst whose classes is an exact match 'hide'.
https://css-tricks.com/attribute-selectors/
Simpy refer to the desired classes with a .
$('tr#10').find(".form-control")
or
$('tr#10').find(".hide")
or
$('tr#10').find(".form-control.hide")

Is there a method in jQuery that will traverse up the dom tree from an element and check selectors before its parent element

For example:
<div class="mainWrapper">
<div class="FirstLayer">
<input class="foo" value="foo" />
</div>
<div class="SecondLayer">
<div class="thirdLayer">
<input class="fee" />
</div>
</div>
</div>
Lets say I have the input.fee as a jQuery object and I also need to get the value of input.foo.
Now I know I can use a multitude of approaches such as $(this).parents(':eq(2)').find('.foo') but I want to use this one method on layouts which will have varying levels and numbers of nodes.
So I am wondering if there is a method which will simply start from .fee and just keep going up until it finds the first matching element, .prevAll() does not appear to do this. There are many .foo and .fee elements and I need specifically the first one above the .fee in context.
How about this:
$('input.fee').closest(':has("input.foo")')
.find('input.foo').val();
Here's JS Fiddle to play with. )
UPDATE: Kudos to #VisioN - of course, parents:first is well replaced by closest.
This will select the previous input.foo
// self might have siblings that are input.foo so include in selection
$( $("input.fee").parentsUntil(":has(input.foo)").andSelf()
// if input.off is sibling of input.fee then nothing will
// be returned from parentsUntil. This is the only time input.fee
// will be selected by last(). Reverse makes sure self is at index 0
.get().reverse() )
// last => closest element
.last()
//fetch siblings that contain or are input.foo elements
.prevAll(":has(input.foo), input.foo")
// first is closest
.first()
// return jQuery object with all descendants
.find("*")
// include Self in case it is an input.foo element
.andSelf()
.filter("input.foo")
// return value of first matching element
.val()
jQuery.closest() takes selector and does exactly what you need - finds the first matching element that is parent of something. There's also jQuery.parents() that does take a selector to filter element ancestors. Use those combined with find method and you're set.
$('input.fee').closest('.mainWrapper").find('.foo') does the trick, doesn't it?

Can anyone explain this bizarre behavior in jQuery next?

It works:
<div class="xpav">
Create
</div>
<div class="apr" style="display: none;">
sometext
</div>
<script>
$('.xpav').click(function() {
$(this).next(".apr").slideDown("fast");
})
</script>
It doesn't:
<div class="xpav">
Create
</div>
<br />
<div class="apr" style="display: none;">
sometext
</div>
<script>
$('.xpav').click(function() {
$(this).next(".apr").slideDown("fast");
})
</script>
Why breaks it?
.next() only looks at the element that comes after the given element, then checks that element against the selector if it's provided. In your second example, since the br is there and doesn't have the apr class, it isn't picked up. From the API docs:
Description: Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector.
Your second example requires the use of .nextAll() instead to search through all the next siblings:
$('.xpav').click(function() {
$(this).nextAll(".apr").slideDown("fast");
});
To pick up only the first .apr that's matched, use .eq(0):
$('.xpav').click(function() {
$(this).nextAll(".apr").eq(0).slideDown("fast");
});
under my impression next() only works if the sibling objuect is the same DOM tage,
what does work is:
$('.xpav').click(function() {
console.log($(this).next(".apr"));
$(this).siblings(".apr").slideDown("fast");
})
It's exactly that what the documentations says: "Description: Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector."
http://api.jquery.com/next/
Because next() takes you to the immediate next DOM element which is <br />. Why not use this:
$(".apr").slideDown("fast");
Simply because you are using the next() method in your code. The next DOM element from $('.xpav') in the second version of your code is a <br />, and since that doesn't match the filter, it doesn't slide anything down!
If you want it to work, you should consider using nextAll() instead of next(), as the latter ONLY gets the very next DOM element, where the former gets all siblings that are after itself in the DOM.

Categories