Jquery assign second child attribute - javascript

Is there a way to assign nested div attribute with variable? Like
<div>
<div>
123456
</div>
</div>
Become
<div>
<div sectionid="123">
123456
</div>
</div>
BTW above component will be created by JavaScript.
I've tried something like this, but it didn't work.
var a = $('<div><div>123456</div></div>');
a.eq(":nth-child(2)").attr("sectionid", "123");

Try this snippet.
//FOR DOM HTML
console.log("FOR DOM HTML");
//1st way
$('#input > div').find('div').attr("sectionid","123");
console.log($('#input').html());
//2nd way
$('#input > div > div').attr("sectionid","321");
console.log($('#input').html());
//JS HTML
console.log("FOR JS OBJECT");
var input = $('<div><div>123456</div></div>');
//1st way
input.eq(0).children().attr('sectionid', '456');
console.log(input[0].outerHTML);
var input = $('<div><div>123456</div></div>');
//2nd way
$(input[0]).children().attr('sectionid', '789');
console.log(input[0].outerHTML);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="input">
<div>
<div>
123456
</div>
</div>
</div>

nth-child(2) maches elements that are the second child element of their parent. This is not the case for your div, it is the first element of the parent div.
.eq finds an element at a specific index. It is not the place to pass a selector.
The child selector, >, will find a child element, i.e. div>div will find a div that is an immediate child of a div.
Note that the code you've provided, $('<div></div>123456<div></div>');, doesn't create a DOM tree like the one you've pasted.
Update, now that the code is edited, the value of a is a div with a child div. Since a.find will perform a search within a, you don't have to use a child selector, but can find the div immediately:
a.find('div')

Just apply attribute to children. No complicated 'find', eq(), etc.
var a = $('<div><div>123456</div></div>');
a.children().attr('sectionid', '123');
$('body').append(a);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Why don't you add it in the first place? Not clear if you add it later!
$(document).ready(function() {
var sectionid = "123";
var a = $('<div><div sectionid="' + sectionid + '">123456</div></div>');
$('body').append(a);
});
div[sectionid]{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Try this - I have added comments to the code to explain what is happening.
Inspect the element to see that the attribute is added
var a = $('<div><div>123456</div></div>'); // change this to match the structure you want
a.children() // .children gets the direct descendant (which should be the nested div
.eq(0) // gets the first in the array that is returned (if there are multiple direct descendents) - it is a 0 based index selector
.attr('sectionid', '123');
$('body').append(a)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
More information about .children()
More information about .eq()

try it :
$(document).ready(function(){
$("div").eq(1).attr("sectionid","123");
})

Related

JQuery clone is not working with class selector

Fiddle
I am trying to clone a span from the onClick() function of a button. First time this works fine but when I try second time it is not cloning. What am I doing wrong?
Here is the essence of my code.
$(document).ready(function(){
$('.addmachinerow').on('click',function(){
var edcname = $('.edc_name option:selected').val();
var machine_description = $("input[name='machine_description'").val();
var capacity = $("input[name='capacity'").val();
var voltage_level = $("input[name='voltage_level'").val();
var powertype = $("select[name='typeofpower'").val();
var edcautovalue = $('.ecaddingspan').attr('data-value');
//if($('#bank_increment').html() == '') $('#bank_increment').html('0'); else $('#bank_increment').html(parseInt($('#bank_increment').html())+1);
//if($('#bank_clickededit').html() == '') var bank_increment = $('#bank_increment').html(); else var bank_increment = $('#bank_clickededit').html();
$('.ecaddingspan').clone().appendTo('.edcparent');
//$('.bankname, .bankbranch , .IFSCcode , .bankaccno , .accsincefrom').val('');
var edc_details = {'edcname' : edcname, 'machine_description' : machine_description, 'capacity' : capacity, 'voltage_level' : voltage_level, 'powertype' : powertype }
//$('.bank_details_array').append(JSON.stringify(bank_details)+'&&');
});
});
Additionally:
How can i clone the entire sets on clicking the Total clone button ?
I need to save the values in array with different names. Is that possible ?
How can i clone the entire sets on clicking the Total clone button ?
You've to use event delagtion on() instead :
$('body').on('click','.addmachinerow', function(){
//Event code
})
Since the new .addmachinerow added to the page dynamically after the clone.
I need to save the values in array with different names is that possible ?
I suggest the use of the array name [] like :
<input name='machine_description[]' />
<input name='voltage_level[]' />
Hope this helps.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$('.cloneitem').not('.cloned').clone().addClass('cloned').appendTo('body');
});
});
</script>
</head>
<body>
<p class="cloneitem">This is a paragraph.</p>
<button>Clone all p elements, and append them to the body element</button>
</body>
</html>
The issue is a common misconception of JQuery selectors. If you play with ID selectors then switch to class selectors then you often don't notice a difference in behaviour. The ID selector doc says
ID Selector: If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM
whilst for the class selector
Class Selector: Selects all elements with the given class.
What this means is that when you clone the target element you get away with a subsequent ID selection (JQuery ignores the duplicates) but a subsequent class selection will trip you up if you were not expecting JQuery to return multiple matches. Class selectors are great for grouping elements but not so great for cloning.
While I am on the soap box - whenever you use the clone function you should consider and fix the potential duplicate ID and un-required class duplicates that you are producing. Duplicate ID's are definitely bad show - duplicate classes may actually be by design but you should still consider them.
In the code sample below I assign the class iAmSpartacus to the original span which the onClick() function then clones. Each clone also gets the iAmSpartacus class so I remove it from each new clone to ensure that the $(".iAmSpartacus") selector always returns a maximum of one element. The spans show their current class property to prove the point.
// this runs one - shows us classes of original span
var origSpan=$(".iAmSpartacus")
origSpan.html("My classes are: " + origSpan.prop("class"))
$("#daButton").on("click", function(e) {
var newSpan = $(".iAmSpartacus").clone();
newSpan.removeClass("iAmSpartacus"); // remove the dup targetting class
newSpan.appendTo('.edcparent');
newSpan.html("My classes are: " + newSpan.prop("class"))
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="daButton">Click me</button>
<div class="edcparent" style="border: 1px solid red;">
<span class="ecaddingspan iAmSpartacus" style="display: block;">I am a span</span>
</div>

How to get class name of element has specific text using javascript/jquery?

I need a JavaScript or jQuery way of extracting the Class name of DIV element by the text it contains.
Let's illustrate. If I had let's say following code:
<div class="_className">UniqueText</div>
I need to to know how to programmatically do something like this:
getClassNameWhereText("UniqueText");
In this case output should be:
_className
Is there a way to do this?
JQuery :contains selector select element has specific text but it isn't exact. For example
$("div:contains(UniqueText)")
Select both of bottom divs
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
You can use .filter() to filter selected element by text.
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
console.log(className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
By getting all the div with each function you can search through all the divs and place a condition in which you the value of the div is equal to the particular text that you want to find. Then get the class name by using .attr('class').
$( "div" ).each(function(){
if($(this).text() == "UniqueText"){
var output = $(this).attr('class');
$(".output").html(output);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_classname">UniqueText</div>
<div class="output"></div>
It might be a bit long for a code but it gets the work done nicely. :)
You can use :contains(word)
var className = $( "div:contains('John')" ).attr("class");
console.log(className)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">John Resig</div>
<div class="bar">George Martin</div>
<div class="foo">Malcom John Sinclair</div>
<div class="baz">J. Ohn</div>
You can keep an id for your div, as per your information your text will be unique.
<div id="UniqueText" class="_className">UniqueText</div>
and the js code will be
function getClassNameWhereText(text){
var className = $('#'+text).attr('class');
console.log(className);
}
UPDATE : if you want to using contains
then you can do this,
function getClassNameWhereText(text){
var val = document.getElementById(text).value;
if(text.indexOf(val)>=0){
var className = $('#'+text).attr('class');
console.log(className);
}
}
This should be faster than using jQuery (but a bit more to type):
var xpath = "//div[text()='UniqueText']";
var result = document.evaluate(xpath,
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);
var node = result.singleNodeValue;
if (node) {
console.log(node.className);
} else {
console.error("Not found!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
The reason is, browser's CSS selectors don't support :contains selector, and jQuery needs to emulate it by checking every node matching the rest of the selector. Ditto for using .filter. But XPath is done natively by the browser.
You also cannot specify exact match using the jQuery :contains, like here. If substring matching was indeed needed, you can change the XPath:
var xpath = "//div[contains(text(),'UniqueText')]";
XPath is very powerful, but a bit finicky and largely unknown, so I find it is very under-utilised, even when its use would be a perfect fit.

jQuery traversing. Find siblings including itself

I'm using jQuery traversing to jump between DOM elements.
First of i have a onClick function:
$(document).on('keyup', '.size, .ant', function(){
Inside of this function I send data about what's clicked, to another function.
sulorTableRowWeight( $(this) );
function sulorTableRowWeight(thisobj){
Now, I'd like to traverse from the clicked element $(this) to its parent. I'd like to find the parent's siblings and then traverse down to a specific sibling.
var inputSize = $(thisobj).parent().siblings('.sizeTd').children('.size');
My problem is when I want to traverse back down to the element I came from, it is not listed as a sibling because it isn't a sibling...
var inputSize = $(thisobj).parent().siblings(); console.log(inputSize)
console will give me the siblings, but not the one U came from...
So, when a user clicks ".size" I'd like to traverse up to the parent and back to size.... When a user clicks ".ant" I'd like to traverse up to the parent and then down to ".size"...
I tried to hardcode the traversing:
var inputSize = $(thisobj).parent().siblings('.sizeTd').children('.size');
But it won't work because it is not actually a sibling.
So what is it? And how can I get back to it?
If it is not possible, I have to run some if/else statements, U guess...
UPDATE
$(document).on('keyup', '.size, .ant', function(){
//Find changed <select> .tbody
var tbodyId = $(this).parent().parent('tr').parent('tbody').attr('id');
//Check <tbody> #id
if(tbodyId === "cpTableBody"){
}
else if(tbodyId === "sulorTableBody"){
sulorTableRowWeight( $(this) );
}
else if(tbodyId === "konturTableBody"){
konturTableRowWeight( $(this) );
}
else if(tbodyId === "kantbalkTableBody"){
kantbalkTableRowWeight( $(this) );
}
})
//Function sulorTableRowWeight
function sulorTableRowWeight(thisobj){
//Find the selected data-weight
var selectedWeightmm3 = $(thisobj).parent().siblings('.selectTd').children('.select').find(':selected').data('weightmm3');
//Find input .size value
var inputSize = $(thisobj).parent().siblings('.sizeTd').children('.size'); console.log(inputSize)
PROBLEM
My var inputSize will return undefined when I click a ".size" element. That´m's because it is not listed as a sibling to itself.
I know it's keyup, not click...
e.target will select the current input
$(document).on('keyup', '.size, .ant', function(e) {
inputSize = $(e.target);
if($(e.target).is('.ant')) {//test if the element is .ant
inputSize = $(e.target).parent().find('.size');//get .size based on .ant
}
console.log(inputSize[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input class="size x1" placeholder="x1">
<input class="ant x1" placeholder="x1 ant">
</div>
<div>
<input class="size x2" placeholder="x2">
<input class="ant x2" placeholder="x2 ant">
</div>
Hmm, if you're passing in $(this) as thisObj I don't think you need to be nesting thisObj in a $(). (See note below)
Anyway, you could try using .parents('<grandparent>').find('<child>') so basically you're traversing one higher level up the tree with <grandparent>, then getting all the descendants that match the child selector. That should include the branch of the three that $(this) represents. But it's hard to say for sure without seeing your HTML.
** A good practice when assigning jQuery objects to variables is to use $ syntax, ie var $this = $(this) so you know anything prepended with a $ is a jQuery object.
inside sulorTableRowWeight , you should have the reference to the clicked element in thisobj variable.

Count number of first layer/set of children in cloned element

I am trying to count the number of it's first layer of children not including it's child of child of child.. This is my codes
HTML
<div class="container">
<div class="row">
<div class="btn-container col-md-12">
Hello
</div>
</div>
</div>
JS
$('a').click(function(){
var c = $(this).closest('.row').clone();
$(this).after( c );
var count = $(this).closest('.row').find('.btn-container').length;
alert(count);
});
The alert should always return 1 since the cloned element is appended inside of it.
jsFiddle
I tried ..
.find() but also as I expected, it will count all inside of it.. Child of child of child and so on...
var parent = $(this).closest('.row');
var count = $('.btn-container', parent).length;
But still can not get what I want.
I already think of adding a name/class specifying to them. Like btn-container first-children ..
But I am wondering if there is a jQuery trick that will make it simplier.
find('.btn-container') will select all descendants .btn-container. You should use direct child selector > like following.
$('a').click(function () {
var c = $(this).closest('.row').clone();
$(this).after(c);
var count = $(this).closest('.row').find('>.btn-container').length;
//---------------------------------------^^--------------------
alert(count);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="btn-container col-md-12">
Hello
</div>
</div>
</div>
Rather than find() you could use children(). From jQuery .children() documentation:
The .children() method differs from .find() in that .children() only
travels a single level down the DOM tree while .find() can traverse
down multiple levels to select descendant elements (grandchildren,
etc.) as well
var count = $(this).closest('.row').children('optional-selector').length;

Check if an element is a child of a parent

I have the following code.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<div id="hello">Hello <div>Child-Of-Hello</div></div>
<br />
<div id="goodbye">Goodbye <div>Child-Of-Goodbye</div></div>
<script type="text/javascript">
<!--
function fun(evt) {
var target = $(evt.target);
if ($('div#hello').parents(target).length) {
alert('Your clicked element is having div#hello as parent');
}
}
$(document).bind('click', fun);
-->
</script>
</html>
I expect only when Child-Of-Hello being clicked, $('div#hello').parents(target).length will return >0.
However, it just happen whenever I click on anywhere.
Is there something wrong with my code?
If you are only interested in the direct parent, and not other ancestors, you can just use parent(), and give it the selector, as in target.parent('div#hello').
Example: http://jsfiddle.net/6BX9n/
function fun(evt) {
var target = $(evt.target);
if (target.parent('div#hello').length) {
alert('Your clicked element is having div#hello as parent');
}
}
Or if you want to check to see if there are any ancestors that match, then use .parents().
Example: http://jsfiddle.net/6BX9n/1/
function fun(evt) {
var target = $(evt.target);
if (target.parents('div#hello').length) {
alert('Your clicked element is having div#hello as parent');
}
}
.has() seems to be designed for this purpose. Since it returns a jQuery object, you have to test for .length as well:
if ($('div#hello').has(target).length) {
alert('Target is a child of #hello');
}
Vanilla 1-liner for IE8+:
parent !== child && parent.contains(child);
Here, how it works:
function contains(parent, child) {
return parent !== child && parent.contains(child);
}
var parentEl = document.querySelector('#parent'),
childEl = document.querySelector('#child')
if (contains(parentEl, childEl)) {
document.querySelector('#result').innerText = 'I confirm, that child is within parent el';
}
if (!contains(childEl, parentEl)) {
document.querySelector('#result').innerText += ' and parent is not within child';
}
<div id="parent">
<div>
<table>
<tr>
<td><span id="child"></span></td>
</tr>
</table>
</div>
</div>
<div id="result"></div>
If you have an element that does not have a specific selector and you still want to check if it is a descendant of another element, you can use jQuery.contains()
jQuery.contains( container, contained )
Description: Check to see if a DOM element is a descendant of another DOM element.
You can pass the parent element and the element that you want to check to that function and it returns if the latter is a descendant of the first.
Ended up using .closest() instead.
$(document).on("click", function (event) {
if($(event.target).closest(".CustomControllerMainDiv").length == 1)
alert('element is a child of the custom controller')
});
You can get your code to work by just swapping the two terms:
if ($(target).parents('div#hello').length) {
You had the child and parent round the wrong way.
Without jquery
target.matches() with :scope
If you want to see if the target element has a parent which matches some selector use the .matches() method on the target and pass the selector followed by the :scope pseudo class.
The :scope here refers to the target element so you can use the in a :where pseudo class to help you write out a clean selector.
In the following example we will match all target elements which are a decedent of an a, button, or summary element.
const app = document.getElementById("app");
app.addEventListener("click", (event) => {
if (
event.target.matches(
":where(a, button, summary) :scope"
)
) {
console.log("click", event.target.parentNode.tagName);
}
});
<div id="app">
<button>
<span>Click Me</span>
</button>
<a href="#">
<span>Click Me</span>
</a>
<details>
<summary>
<span>Click Me</span>
</summary>
</details>
<span>Click Me</span>
<div>
Note the selector :where(a, button, summary) :scope could also have been written as:
a :scope,
button :scope,
summary :scope
parent.contains()
If you are interested in seeing if the target element is a child of a specific element use .contains() on the potential parent element:
const app = document.getElementById("app");
const button = document.getElementById("button");
app.addEventListener("click", (event) => {
if (button.contains(event.target)) {
console.log("click");
}
});
<div id="app">
<button id="button">
<span>Click Me</span>
</button>
<span>Click Me</span>
<div>
In addition to the other answers, you can use this less-known method to grab elements of a certain parent like so,
$('child', 'parent');
In your case, that would be
if ($(event.target, 'div#hello')[0]) console.log(`${event.target.tagName} is an offspring of div#hello`);
Note the use of commas between the child and parent and their separate quotation marks. If they were surrounded by the same quotes
$('child, parent');
you'd have an object containing both objects, regardless of whether they exist in their document trees.
To know more background info on Aleksandr Makov's answer, checking the below page might be helpful.
https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
Node.contains()
The contains() method of the Node interface returns a boolean value indicating whether a node is a descendant of a given node, that is the node itself, one of its direct children (childNodes), one of the children's direct children, and so on.
It means, the answer is not using a reclusive function.

Categories

Resources