JQuery - get first occurence of class travelling upwards anywhere in the DOM - javascript

I have several instances of class="reply_count", most embedded inside other elements. I would like a method to traverse upward anywhere in the DOM to get the first instance of, and get the text value.
In the example below, I tried using prevAll, and getting the first of them. However, it does not recognize the one that is within a DIV. That is the one I want to select. I assume prevAll works for the same level elements, but not nested ones?
My actual code is much more complex, but below is just a simple example of the intent.
What is another method of accessing the first occurrence of a class going upwards regardless of where it is and how it is nested in other elements?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="reply_count">15</div>
<div class="reply_count">10</div>
<div><span class="reply_count">5</span></div>
<div id="click" style="cursor: pointer;">Click Here</div>
<div class="reply_count">2</div>
<div class="reply_count">1</div>
<script>
$("#click").click(function(){
value = $(this).prevAll( ".reply_count:first" ).text();
alert(value);
});
</script>
</body>
</html>
The result is: 10. I wanted 5.

You can do something like this:
$(".click").click(function() {
var c = $(this).parent().find(".reply_count").add(this);
var t = $(c).index(this);
var value = $(c).eq((t-1)).text();
console.log(value);
});
Demo I've added multiple <div class="click" so you can see it working just fine.
$(".click").click(function() {
var c = $(this).parent().find(".reply_count").add(this);
var t = $(c).index(this);
var value = $(c).eq((t-1)).text();
console.log(value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reply_count">15</div>
<div class="reply_count">10</div>
<div>4</div>
<div class="click" style="cursor: pointer;">Click Here</div>
<div><span class="reply_count">5</span></div>
<div class="click" style="cursor: pointer;">Click Here</div>
<div><span class="reply_count">1</span></div>

you can use closest method. It traverses upwards through the ancestors in the DOM tree and returns the closest parent matching your selector

Related

Downshift remaining IDs after function remove()

I'm using Javascript and I'm having problems trying to remove several elements.
Each div has a specific ID, like this:
<div id='1'></div>
<div id='2'></div>
<div id='3'></div>
<div id='4'></div>
Each div has a button that fires the remove() function
document.getElementById(count).remove()
Count is a variable that is increased whenever I create a new div
The remove() function works, but it creates a gap. IF i remove the div with id=2, then:
<div id='1'></div>
<div id='3'></div>
<div id='4'></div>
But I would like that the remaining IDs could downshift like this:
<div id='1'></div>
<div id='2'></div>
<div id='3'></div>
I guess I need a for loop but I can't understand how to make it
Use a class on each element, like this:
<div class="a" id='1'></div>
<div class="a" id='2'></div>
<div class="a" id='3'></div>
<div class="a" id='4'></div>
And call the following function after each removal:
function resetId(){
const list = document.getElementsByClassName("a")
for(let i = 0; i < list.length; i++){
list[i].id = i + 1
}
}
However, it might be better to just not use IDs in this case. By applying the same class to all your elements, there's no need to readjust the numbering, and you can select (or remove) the nth element using:
document.getElementsByClassName("a")[n]
This would probably be best achieved using jquery.
Here is the working code below:
$("div").each(function(i) {
$(this).attr('id', ++i);
});
$("#remove").click(function() {
$("#2").remove();
$("div").each(function(i) {
$(this).attr('id', ++i);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=""><span>0</span></div>
<div id=""><span>0</span></div>
<div id=""><span>0</span></div>
<div id=""><span>0</span></div>
<div id=""><span>0</span></div>
remove
How it works
First $(this).attr('id', ++i); this line here is used to add a number to div id. Ive repeated it in the remove function [("#remove").click(function()] This is because once a div has been removed the will be a number change.
This in affect is a loop. Without all the lines of code. Which is why i like jquery :)
The div id name is found here after they have been written $("#2").remove(); #2 refers to the <div id="2"> As you would in css.
If you notice, with an inspection the numbers down shift as 1 is removes as per your request.
In order to use jquery you have to link the library. <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
A Pure Javascript Version
function resetId(){
var div=document.getElementsByClassName("div")
for(i in div){
div[i].id=i++
}
}
function clicked() {
var elem = document.getElementById("1");
elem.parentNode.removeChild(elem);
resetId();
}
<div class="div" id="0">div</div>
<div class="div" id="1">div</div>
<div class="div" id="2">div</div>
<div class="div" id="3">div</div>
Remove
How it Works
This section here is your loop:
for(i in div){
div[i].id=i++
}
This section quite simply rewrites the numbers 0 - 4 after one has been removed.
The reason it starts from 0, is because in programming we start counting from 0. Hay 0 is a number too guys :).
The i++ Is a basically a mini int [ish] that is increased as the loop counts through how many divs there are.
This var elem = document.getElementById("1"); & this elem.parentNode.removeChild(elem); Is why I find jquery more acceptable in this situation. Its a bit less faf.
Finally resetId(); We have to call the function otherwise it doesn't that anything has changed, because computers are silly and need to be told.
Furter Reading
https://api.jquery.com/
http://www.lucemorker.com/blog/javascript-vs-jquery-quick-overview-and-comparison
Sounds like you should be using classes and referencing elements by index instead. IDs should remain persistent for clarity.
document.getElementsByClassName('my-class')[2].remove();
<div class="my-class" id="thing1">One</div>
<div class="my-class" id="thing2">Two</div>
<div class="my-class" id="thing3">Three</div>
<div class="my-class" id="thing4">Four</div>

Select only the text inside div of sibling with class name, having many families of same class names

I wanted to copy the texts when the copy button is clicked. But, it copies the last(3rd) paragraph text when pressing any of the three buttons. It suppose to find previous sibling and copy that text when that particular button is clicked.
Here's my code. I think, I went wrong in the sibling thing. Let me know what I did wrong here:
//finding text to copy
$(document).ready(function(){
$(document).on('click', '.phc-hashtags-box-button', function () {
$(this).closest('.phc-hashtags-box').find('.phc-hashtags-box-tags');
copy = copy +$(this).text();
});
});
function copyToClipboard(element) {
var $temp = $('<input>');
$('body').append($temp);
$temp.val($(element).text()).select();
document.execCommand('copy');
$temp.remove();
}
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="phc-home-hashtags">
<div class="container">
<div class="phc-hashtags-box">
<h3 class="phc-hashtags-box-title">Dog1</h3>
<p class="phc-hashtags-box-tags">#dog #dogstagram #instadog #dogsofinstagram #worldofdogs #dogslove #cutedog #doggy #igdogs #dogs #pet #dogoftheday #myfriend #doglover #ilovemydog #ilovedog #doglove #doglife #mydog #happydog #1st</p>
<button onclick="copyToClipboard('.phc-hashtags-box-tags')" class="phc-hashtags-box-button">Copy</button>
</div>
<div class="phc-hashtags-box">
<h3 class="phc-hashtags-box-title">Dog2</h3>
<p class="phc-hashtags-box-tags">#dog #dogstagram #instadog #dogsofinstagram #worldofdogs #dogslove #cutedog #doggy #igdogs #dogs #pet #dogoftheday #myfriend #doglover #ilovemydog #ilovedog #doglove #doglife #mydog #happydog #2nd</p>
<button onclick="copyToClipboard('.phc-hashtags-box-tags')" class="phc-hashtags-box-button">Copy</button>
</div>
<div class="phc-hashtags-box">
<h3 class="phc-hashtags-box-title">Dog3</h3>
<p class="phc-hashtags-box-tags">#dog #dogstagram #instadog #dogsofinstagram #worldofdogs #dogslove #cutedog #doggy #igdogs #dogs #pet #dogoftheday #myfriend #doglover #ilovemydog #ilovedog #doglove #doglife #mydog #happydog #3rd</p>
<button onclick="copyToClipboard('.phc-hashtags-box-tags')" class="phc-hashtags-box-button">Copy</button>
</div>
</div>
</div>
</body>
</html>
Instead of picking by class which gets all of the element with that class, limit your find to the parent() div of the button and it will only get the relevant text:
$(document).ready(function(){
$(document).on('click', '.phc-hashtags-box-button', function () {
$(this).parent().find('.phc-hashtags-box-tags'); // notice the change on this line.
copy = copy +$(this).text();
});
});
EDIT:
Working solution:
Now i noticed - you are not passing a single element to copyToClipboard.
<button onclick="copyToClipboard('.phc-hashtags-box-tags')" class="phc-hashtags-box-button">Copy</button>
is sending the saving to copy the last element from 3 found with this. Try instead:
<button onclick="copyToClipboard($(this).parent())" class="phc-hashtags-box-button">Copy</button>
I believe that when you pass '.phc-hashtags-box-tags' to the onclick attr of the button elements, it is matching all of the elements with that class and returning the last match for the value of your function.
Instead, try changing the button onclick handler to:
copyToClipboard($this)
That said, the execCommand function is not working in the provided snippet so verifying is difficult.
Perhaps try passing IDs or try to architect a more elegant solution. So many relative jQuery selectors will inevitably cause bugs as complexity grows.

AppendChild a element above a cerain element

So i have a div element which will be filled dynamically with others divs using the appendChild Method, this should display a list. The User is now able to sort that list with the JqueryUI Sortable option.I also added some sortable option attribues like follows:
Options:
$("#NameContainer").sortable("option", "axis", "y");
$("#NameContainer").sortable( "option", "containment", "parent" );
LIST
<div id="NameContainer" class="ui-widget">
<div id="Name_1">John</div>
<div id="Name_2">Jack</div>
<div id="Name_3">Charlie</div>
<div id="Name_4">Sawyer</div>
<div id="Name_5">Yin</div>
<div id="Name_6">Ben</div>
</div>
Now comes my problem. The appendChild always inserts the new div at the bottom of the container but i want to to add some space at the bottom of to the Container Div with a "br" or something like that. I want to add that space to make sure that when the user sorts the last item of that list it will get sorted correctly because the "containment" bounds sometimes wont allow to sort under the last item.
<div id="NameContainer" class="ui-widget">
<div id="Name_1">John</div>
<div id="Name_2">Jack</div>
<div id="Name_3">Charlie</div>
<div id="Name_4">Sawyer</div>
<div id="Name_5">Yin</div>
<div id="Name_6">Ben</div>
<br><!--SPACEHOLDER-->
</div>
So here comes my Question is there away to appendChild above a certain element? Like a "br" "div" or "p"?
Try this instead of appendChild:
Please note I have used random value to add in div as I don't have your dynamic value.
check fiddle: https://jsfiddle.net/dqx9nbcy/
<div id="NameContainer" class="ui-widget">
<div id="divspacer"></div>
</div>
<button id="btn">ADD Element</button>
$(document).ready(function(){
$("#btn").click(function(){
var parentnode = document.getElementById("NameContainer");
var existnode = document.getElementById("divspacer");
var rand = Math.floor((Math.random() * 10) + 1);
var newName = document.createElement("div");
newName.setAttribute("id", rand);
newName.setAttribute("value", rand);
newName.setAttribute("class","ui-widget-content");
newName.innerHTML = rand;
parentnode.insertBefore(newName,existnode);
});
});
refer http://api.jquery.com/appendto/ but you need to make sure that your are targeting right tag.
You can try with this code snippet.
HTML Snippet
<div id="NameContainer" class="ui-widget">
<div id="Name1">Name1</div>
<div id="Name2">Name2</div>
<div id="Name3">Name3</div>
<div id="Name4">Name4</div>
<br>
<br>
</div>
Javascript Snippet
$(document).ready(function(){
$("#btn").click(function(){
var containerDiv= $("#NameContainer");
var childList = containerDiv.children("div");
var newElementid = childList.length;
var newName = document.createElement("div");
newName.setAttribute("id", "Name"+(newElementid+1));
newName.setAttribute("value", "Name"+(newElementid+1));
newName.setAttribute("class","ui-widget-content");
newName.innerHTML = "Name"+(newElementid+1);
$(childList[childList.length-1]).after(newName);
});
});
This is specific to a situation where there are some elements in the initial list. The same can be modified for dynamic list of implementation by validating that childList.length is != 0 before using the same.

I converted text data to jquery object but the created one was not what I expected

I want to convert text data to jquery object and want to use 'find()' method or 'filter()' method or some other methods which jquery has.
But somehow, the innerHtml of the converted jquery object is not what I expected..
I want to know what is going on.
http://jsfiddle.net/LxXtz/14/
<!DOCTYPE html>
<html>
<head>
<script src="lib/jquery-2.0.3.min.js"></script>
<style type="text/css">
<!--
#parts{
display: none;
}
-->
</style>
<script>
$(function () {
$('#execution').on('click', function () {
var parts = $('#parts').html(); //Parts is text data. I create the data from html just for this demo.
var partsobj = $(parts); // Convert to jQuery object.
console.log(partsobj.html()); // Why not be outputted innerHtml of #parts??
});
});
</script>
</head>
<body>
<input type="button" id="execution" value="Execute" />
<div id="parts">
<div id="div1">
<div>This is in Div1</div>
</div>
<div id="div2">This is Div2</div>
</div>
</body>
</html>
You are getting below from $('#parts').html()
<div id="div1">
<div>This is in Div1</div>
</div>
<div id="div2">This is Div2</div>
Then when you converts it to jquery object, it turns to array containing 3 elements,
Object[div#div1, <TextNode textContent="\n ">, div#div2]
So using the .html() gives the first element innerHTML only. That's
<div>This is in Div1</div>
Check this http://jsfiddle.net/LxXtz/16/. Check the console.
http://api.jquery.com/html/ states:
"Description: Get the HTML contents of the first element in the set of matched elements."
"If the selector expression matches more than one element, only the first match will have its HTML content returned."
Your partsobj matches 3 entries; div, textnode, div. One way to resolve it is to loop through them with each.
partsobj.each(function(){
if($(this).html())
$('#result').text($('#result').text()+$(this).html())
})
var parts = $('#parts').children();
console.log(parts);
that will give you an array of the html elements. If you want the raw html of those children elements.
var parts = $('#parts').children();
$.each({parts, function() {
console.log($(this).html());
});
so you want the html of div#execution, then to insert it into div#result. if you want to move it then
$('#execution').on('click', function () {
$('#result').append($('#parts').html())
});
is this what you mean?

Traversing DOM from span in / out of divs

I'm adding a click event to a span that is within a div. The target of this event, which will become visible, is a first div that is within a div, two divs down. How can I traverse the DOM to find it?
Perhaps it'll be clearer with the code:
<div a>
<h2>
<span id="here">Click</span>
</h2>
</div>
<div></div>
<div>
<div class="targetDiv">This is the div we need to find</div>
<div class="targetDiv">There are other divs with the same id, but we don't need to find those</div>
<div class="targetDiv">Not looking for this one </div>
<div class="targetDiv">Or this one either</div>
</div>
I've searched left and right and cannot find an answer. It's important to restrict the event ONLY to the first div immediately after the span.
Any help would be much appreciated.
As shown, the code would look like this:
$('span#here').on('click', function() {
$(this).closest('div').siblings(':contains(.targetDiv)').children().eq(0).show();
}
Here's a sample of the fish we caught
$(function() {
$('#here').on('click', function() {
var div = $(this) //the element clicked
.closest('div') //find nearest parent div
.nextAll(':eq(1)') //find the second next div
.children(':eq(0)') //find the first child of it
.show(); //remove invisible cloak
});
});​
This works. I provided an example you can just save to a html file and test it yourself
<style>
.targetDiv{display:none;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#here').click(function(){
$('.targetDiv').first().show(); // or whatever you want
});
});
</script>
<div a>
<h2>
<span id="here">Click</span>
</h2>
</div>
<div></div>
<div>
<div class="targetDiv">This is the div we need to find</div>
<div class="targetDiv">There are other divs with the same id, but we don't need to find those</div>
<div class="targetDiv">Not looking for this one </div>
<div class="targetDiv">Or this one either</div>
</div>

Categories

Resources