How to find the deepest child of a div with jquery - javascript

I'm trying to find the deepest element in the specified divwith jquery. But the code which used is producing the error TypeError: parent.children is not a function.
I found this code from this link
the code is :
function findDeepestChild(parent) {
var result = {depth: 0, element: parent};
parent.children().each( //Here I getting the error TypeError: parent.children is not a function
function(idx) {
var child = $(this);
var childResult = findDeepestChild(child);
if (childResult.depth + 1 > result.depth) {
result = {
depth: 1 + childResult.depth,
element: childResult.element};
}
}
);
return result;
}
---------------------------------------------------------------------------------------
$(document).on('keypress','#sendComment', function(e) {
if(e.keyCode==13){
var itemId=$('#findbefore').prev('.snew').attr('id');//
var item=findDeepestChild(itemId);
alert(item);
}
});
And my divs are :
<div id="S04" class="snew" style="display: block;">
<div class="author-image"></div>
<span>xyz shared the image xyz</span>
<div class="s-content">
<div class="s-message"></div>
<div class="shpicture">
<img class="SharedImage" width="100%" height="100%" data-shareid="1" data-alid="1" data-id="1" alt="xyz" src="data:image/jpeg;base64,">
</div>
</div>
</div>
<div class="SPcommentbox">
<div class="comment">
<div class="commenter-image"></div>
<div class="addcomment">
<input class="commentbox" type="text" placeholder="Write a comment...">
</div>
</div>
</div>
I need to find the img from these.
please anyone help me .... Thanks ...

To get the deepest nested elements, use
$("#" + parent).find("*").last().siblings().addBack()
http://jsfiddle.net/6ymUY/1/
you can then get the id data attribute with
item.data("id")
http://jsfiddle.net/6ymUY/2/
full code:
function findDeepestChild(parent) {
return $("#" + parent).find("*").last().siblings().addBack();
}
var item=findDeepestChild("S04");
console.log(item)
console.log(item.data("id"));

You're calling it with a string, but it's expecting a jQuery instance.
Instead of
var itemId=$('#findbefore').prev('.snew').attr('id');//
var item=findDeepestChild(itemId);
you probably want
var item=findDeepestChild($('#findbefore').prev('.snew'));

You are passing in itemId, which is the ID attribute of a given element. I think what you meant to pass was the element itself. Just remove the attr call, leaving this:
var item = findDeepestChild($("#findbefore").prev(".snew"));

Related

Cant get CSS property from child?

I have this HTML code here :
<div id="ctr" class="faden-slider-container">
<div class="conteneur-image" ></div>
<div class="conteneur-image" ></div>
<div class="conteneur-image" ></div>
</div>
And I am trying to get the CSS property of the second div which class' name is conteneur-image but I get nothing :
app.controller("slideCtrl",function ($scope) {
alert("hello")
var tab = new Array();
var elements = new Array();
for(var i = 0; i<3 ; i++){
elements[i] = document.getElementById("ctr").children[i]
}
var style = window.getComputedStyle(elements[1])
var message = style.getPropertyCSSValue("background").cssText()
alert("CSS Value is : "+message)
})
Couple of issues there.
getPropertyCSSValue is obsolete and may not work in browsers anymore
id is a selector, not a valid css property
Use getPropertyValue instead,
var message = style.getPropertyCSSValue("background");
Demo
var style = window.getComputedStyle(document.getElementById("ctr").children[1])
var message = style.getPropertyValue("background");
console.log("CSS Value is : " + message)
<div id="ctr" class="faden-slider-container">
<div class="conteneur-image"></div>
<div class="conteneur-image"></div>
<div class="conteneur-image"></div>
</div>
Using jquery,you can get your 2nd HTML element this way:
var element = $("#ctr").children().eq(1);
Then if you want to make some transformation, like applying style:
element.css("background-color", "blue")
Here is a snippet:
var element = $("#ctr").children().eq(1);
element.css("background-color", "blue")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ctr" class="faden-slider-container">
<div class="conteneur-image" >one</div>
<div class="conteneur-image" >second</div>
<div class="conteneur-image" >third</div>
</div>

Jquery find all elements with custom attribute begin with, get rest of it's name and it's value

Let's say we have element with custom attribute
... bind-html="varName" ...
I want to find all elements with attribute beginning with "bind-",
then get second part of it's name, which is unknown, in this case "html".
And at last get it's value "varName".
How do i achieved this with Jquery? I don't want to use second attribute to describe attibute to bind (like .. bind="varName" attr="html" ..)
You can use a loop through each object's attributes this.attributes and use the attribute's name and value properties.
Running example:
$("input").each(function() {
$.each(this.attributes, function() {
if (this.name.indexOf('bind-') == 0) {
console.log(this.name + ' has the value: ' + this.value);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<input bind-koby='hello'>
<input bind-douek='stack'>
<input will-not-show='yes'>
<input bind-hello='overflow'>
well that what you are looking for like
<div bind-html="varName">hi there i am </div>
well hi thats me
var namer = $(" *[attr*='bind']").text();
console.log(namer);
<div class="bindable" data-bind="html:varName1"></div>
<div class="bindable" data-bind="css:varName2"></div>
<div class="bindable" data-bind="js:varName3"></div>
<div class="bindable" data-bind="whatEver:varName4"></div>
(function(){
let bindables = $('.bindable');
bindables.each(function(){
let bindData = $(this).data('bind');
let bindDataArray = bindData.split(":");
console.log(bindDataArray);
});
}());
now u will get array with data u want
You can get all elements and their attributes which contain bind- by using jquery .properties and .indexOf() like following example.
// $("*") selects all elements in your html
$("*").each(function() {
$.each(this.attributes, function() {
// checks whether element has an attribute starts with "bind-" or not
if(this.specified && this.name.indexOf("bind-") !== -1) {
console.log("Attr Name: "+ this.name + " Attr Value: " + this.value)
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span bindNot-html="bindNot">element1</span>
<div bind-html="varName1">element2</div>
<a bind-html2="varName2">element3</a>
<div bind-html3="varName3">element4</div>
<span bindNot-html="bindNot">element5</span>

Simplify function for removing duplicate array

I want to find div element that contain custom attribute mod than append that div to list item. But first I have to remove divs that contain duplicate mod value. Here's what I have done
<div class="list"></div>
<div class="container">
<div mod="dog"></div>
<div mod="man"></div>
<div mod="woman"></div>
<div mod="dog"></div>
<div mod="bird"></div>
<div mod="insects"></div>
<div mod="dog"></div>
</div>
this is my script
modArr($('.container').find('[mod]'))
function modArr(el){
var filterArray = [] // store mod
, modNames = [] // store mod value
, arrIndex = [] // store non duplicate index
, li = [] // store
modArray = el
// store mod value
for(var i=0; i < modArray.length; i++){
modNames.push($(modArray[i]).attr('mod')) // get mod value from div
}
// search for non duplicate mod value and get the index of none duplicate mod
for(var i=0; i < modArray.length; i++){
if(filterArray.indexOf(modNames[i]) === -1){
filterArray.push(modNames[i])
arrIndex.push(i) // push non duplicate index value
}
}
filterArray = [] // reset filterArray
// push module from modArray to filterArray using index in arrIndex
for(var i=0; i < arrIndex.length; i++){
filterArray.push(modArray[arrIndex[i]])
}
// push to li array
$.each(filterArray,function(i,el){
li[i] = '<li>'+ el.outerHTML +'</li>'
})
$('<ul></ul>')
.append(li.join(''))
.appendTo('.list')
}
What you can see is that I've used to many loops, is there any simple way to do this. Thanks!
We can use an object as a map for checking duplicates, see comments (I've added text to the mod divs so we can see them):
modArr($('.container').find('[mod]'));
function modArr(elements) {
// A place to remember the mods we've seen
var knownMods = Object.create(null);
// Create the list
var ul = $("<ul></ul>");
// Loop the divs
elements.each(function() {
// Get this mod value
var mod = this.getAttribute("mod");
// Already have one?
if (!knownMods[mod]) {
// No, add it
knownMods[mod] = true;
ul.append($("<li></li>").append(this.cloneNode(true)));
}
});
// Put the list in the .list element
ul.appendTo(".list");
}
<div class="list"></div>
<div class="container">
<div mod="dog">dog</div>
<div mod="man">man</div>
<div mod="woman">woman</div>
<div mod="dog">dog</div>
<div mod="bird">bird</div>
<div mod="insects">insects</div>
<div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
We can also just use the DOM to check for duplicates, but it's a bit slower (not that it matters for the number of elements here):
modArr($('.container').find('[mod]'));
function modArr(elements) {
// Create the list
var ul = $("<ul></ul>");
// Loop the divs
elements.each(function() {
// Get this mod value
var mod = this.getAttribute("mod");
// Already have one?
if (ul.find('div[mod="' + mod + '"]').length == 0) {
// No, add it
ul.append($("<li></li>").append(this.cloneNode(true)));
}
});
// Put the list in the .list element
ul.appendTo(".list");
}
<div class="list"></div>
<div class="container">
<div mod="dog">dog</div>
<div mod="man">man</div>
<div mod="woman">woman</div>
<div mod="dog">dog</div>
<div mod="bird">bird</div>
<div mod="insects">insects</div>
<div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note: I used this.cloneNode(true) rather than outerHTML because there's no need to take a roundtrip through markup. If you want more jQuery there, it's $(this).clone(); ;-) Similarly, if you don't like this.getAttribute("mod"), there's $(this).attr("mod").
I'd be remiss if I didn't point out that mod is an invalid attribute name for div elements. You can use any name you want starting with data-, though, so perhaps use <div data-mod="dog"> instead.
Try this, only adds if an element with mod is not already in list:
$('.list').append('<ul>');
$('.container [mod]').each(function(index, el) {
if($('.list [mod=' + $(el).attr('mod') + ']').length === 0) {
$('.list ul').append($('<li>' + el.outerHTML + '</li>'));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="list"></div>
<div class="container">
<div mod="dog">Dog1</div>
<div mod="man">Man1</div>
<div mod="woman">Woman1</div>
<div mod="dog">Dog2</div>
<div mod="bird">Bird1</div>
<div mod="insects">Insect1</div>
<div mod="dog">Dog3</div>
</div>

Simpler Javascript counter

I need some help with the click event, I'm trying to have an individual counter that is incremented by the click event that I have on the img. I've tried many variations, I want to resolve this without using jQuery.
<script async>
var count = 0;
var clickerCount = document.getElementsByClassName('clicker');
var cat = {
count : 0,
counter: function(){
this.count++;
clickerCount.textContent = "Kitten Click Count :" + this.count;
console.log("counter function working");
console.log(cat.count);
}
};
function modifyNum(){
cat.counter();
console.log("modifyNum function working");
}
</script>
</head>
<body>
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
<div>
<img src="http://placekitten.com/200/296" id='cat1' onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
</div>
For a start, you are using id='clicker' in two places (IDs are supposed to be unique), and then using document.getElementsByClassName, which returns nothing because you used an ID and not a class.
Once you do change it to a class, document.getElementsByClassName will return an array of elements. You'll have to use clickerCount[0] and so on, or loop through the array.
This example should work. I've separated the HTML from the Javascript because it looks clearer for me. You can use it as an example to expand / create your own in your own way.
Hope it help
HTML:
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
JS:
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
document.getElementById("counter-for-" + e.currentTarget.id)
.innerHTML = ++counters[e.currentTarget.id];
}
}
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
var cElem = document.getElementById("counter-for-" + e.currentTarget.id);
cElem.innerHTML = ++counters[e.currentTarget.id];
}
}
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
I have solved this problem in this JSFiddle!
If you can hardcode the IDs then it's easier in my point o view to just manipulate things by ID.
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="counter(0);">
<p id='clicker0'>Kitten Click Count :</p>
<input type="hidden" id="counter0" value="0">
</div>
function counter(id) {
var cnt = parseInt(document.getElementById("counter" + id).value);
cnt++;
document.getElementById("counter" + id).value = cnt;
document.getElementById('clicker' + id).innerHTML = 'Kitten Click Count :' + cnt;
}
It's not the same approach but I find it easy to understand.
Hope it helps.
Ok, so first off you have two elements with the id of 'clicker'. You probably meant for those to be classes and ids. So when you call modifynum() it cant locate those because the class doesn't exists. Second, your JS is loading before your HTML elements. So when the JS gets to this line:
var clickerCount = document.getElementsByClassName('clicker');
It is going to find nothing, even if you correct the class names. So you want to move your JS to the footer of your HTML document, or wrap the code in a method that is called on pageLoad().
I think that should take care of it. Your object, for the most part, looks correct.

Nested dynamically added content

I'm creating a form which allows the users to add additional content on the fly. The structure of the form is such that there are three dimensions to the form data, i.e., like a movie can play at different theatres and each theatre can have different showing times. The form, therefore has grandparent, parent and child divs, and the parent & child divs can be added to on the press of a button.
Here's a slimed-down version of the code for clarity
<div id="grandparent">
<div id="parent">
Parent 1
<div id="child">
Child 1
</div>
</div>
<button id="addChild">Add Child</button>
</div>
<button id="addParent">Add Parent</button>
<script>
$(function() {
var grandparent_div = $('#grandparent');
var parent_div = $('#parent');
var child_div = $('#child');
var p = $('#grandparent div#parent').size() + 1;
var c = $('#parent div#child').size() + 1;
$('#addChild').on('click', function() {
$('<div id="child">Child '+c+'</div>').appendTo(parent_div);
});
$('#addParent').on('click', function() {
$('<div id="parent">Parent '+p+'<div id="child">Child 1</div><button id="addChild">Add Child</button></div>').appendTo(grandparent_div);
});
});
</script>
JSFiddle here: http://jsfiddle.net/u2vUT/
I can create parent nodes fine, and I can even create child nodes of parents on the first level - the problem comes when trying to add children of dynamically-added parents. It's probably because the 'addChild' button is no longer unique, so $('#addChild').on('click') can't reference it. So, is there a way to make this work (preferably elegant!)?
You should not use ids, use class
<div id="grandparent">
<div class="parent">Parent 1
<div class="child">Child 1</div>
</div>
<button class="addChild">Add Child</button>
</div>
<button id="addParent">Add Parent</button>
then
$(function () {
var grandparent_div = $('#grandparent');
var parent_div = $('.parent');
var child_div = $('.child');
var p = grandparent_div.find('.parent').size() + 1;
grandparent_div.on('click', '.addChild', function () {
$('<div id="child">Child ' + ($(this).siblings().length + 1) + '</div>').insertBefore(this);
});
$('#addParent').on('click', function () {
$('<div class="parent">Parent ' + p + '<div class="child">Child 1</div><button class="addChild">Add Child</button></div>').appendTo(grandparent_div);
});
});
Demo: Fiddle

Categories

Resources