problem: jQuery click event only works on first occurrence in text - javascript

I have this code:
<span id="Santiago4">Santiago</span>
<br>more html code here<br>
<span id="Santiago4">Santiago</span>
<script>
jQuery("#Santiago4").click(function() {alert("blabla")} );
</script>
My problem is that when I click on the html text on first occurence, the click event triggers the alert pops up. But when I click the second occurrence (or any other if Santiago appears a few times in the text) nothing happens.
Why is that? Why when clicking the second span element that it also has the id: Stantiago4 the function's code does not run?
Thanks in advance.

Element ID attributes are intended to be unique. If you want to share attributes, rather use the class attribute:
<span class="santiago4">Santiago</span>
<br/>more html code here<br/>
<span class="santiago4">Santiago2</span>
In other words, instead of id, use class. Then the jQuery would be:
jQuery(".santiago4").click(function() {
alert("clicked!")
});
Now the click event will be bound to all HTML elements with the class 'santiago4', which is what you are looking for.

ID should be unique across the HTML elements.
You can instead assign a common classname to each of the span and the use .classname as jQuery selector.
Try this:
<span class="Santiago4">Santiago</span> <br/>
more html code here<br/>
<span class="Santiago4">Santiago</span>
<script>
jQuery(function(){
jQuery(".Santiago4").click(function() {
alert("blabla")
});
});
</script>

You can't have more than one element with the same Id, these need to be distinct. For the usage you are describing you need to use another selector such as a class:
<span class="Santiago4">Santiago</span>
<br>more html code here<br>
<span class="Santiago4">Santiago</span>
<script>
jQuery(".Santiago4").click(function() {alert("blabla")} );
</script>

Change it to use a class because as Andrew said, you can't have more than one element with the same ID:
<span class="Santiago4">Santiago</span>
<br>more html code here<br>
<span class="Santiago4">Santiago</span>
<script>
jQuery(".Santiago4").click(function() {alert("blabla"); } );
</script>
Working JS Example

They both have the same ID, which isnt' good HTML and will cause problems when trying to manipulate with jQuery. Try using the class name instead:
<span class="Santiago4">Santiago</span> <br>more html code here<br> <span class="Santiago4">Santiago</span> <script>jQuery(".Santiago4").click(function() {alert("blabla")} );</script>

Related

jQuery .Text() function is replacing HTML within element

I am trying to replace text within an element on the fly, however .text() function is replacing both text and HTML. Any thoughts on how I only edit the actual text?
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>
I want to change the words "My Title" to "My New Title", however whenever I use .text() function, it replaces all of my html and my anchor tag disappears.
Here is my jQuery:
$('h3.titleHeading').text("My New Title")
My output is then - again, the code removes my anchor tag which I need for a tooltip.
<div>
<h3 class="titleHeading">My New Title
<div>
When developing HTML, if you have an element with child HTML elements, it is a bad idea to have it contain plain-text as well. This causes problems like what you see here.
An easy solution is to put your text inside a span. (Note: Don't forget to close your h3.)
<div>
<h3 class="titleHeading">
<span id="titleHeadingText">My Title</span>
<a ng-click="openTooltip('getMoreInfo')">
<span class="toolTip"></span>
</a>
</h3>
<div>
You can change the elements of the text easily, now, without affecting the other elements.
$("#titleHeadingText").text("My New Title");
If you do not have access to the code, loop through only the text nodes and replace their textContent with your new content. This will keep the other existing HTML intact.
Taken from this answer.
$('h3.titleHeading').contents().filter(function() {
return this.nodeType == 3
}).each(function(){
this.textContent = this.textContent.replace('My Title','My New Title');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>
You should do a few things as outlined in the code below
Close the <h3> element
Wrap the text you want to change in a span
Example
<div>
<h3 class="titleHeading">
<span class="titleHeadingText"> My Title</span>
<a ng-click="openTooltip('getMoreInfo')">
<span class="toolTip"></span>
</a>
</h3>
jQuery
$('h3.titleHeadingText').text("My New Title")
To achieve expected result, just update innerText for h3 by contents() data instead of using text()
Jquery contents() will return object of DOM elements
'data' property will provide the innerText of element
$('.titleHeading').contents()[0].data = "My New Title"
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h3 class="titleHeading">My Title <a ng-click="openTooltip('getMoreInfo')"><span class="toolTip"></span></a>
<div>
codepen - https://codepen.io/nagasai/pen/YoXXjd?editors=1010

How do I delete the next two siblings and ONLY the next two siblings in this pop-up using jQuery?

So I have a popup. You click on an "+Add Text" link and it adds a text box to the page, along with another "+Add Text link" and an "x" in a span on the right corner of each textbox. When I click an "x" within this popup, I'd like for it to delete the two siblings that immediately follow it. The HTML generated on the page looks something like this...
<div class="popup">
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
</div>
When I click the divs with the class "delete-text-box-x">, I'd like for the following two siblings to be deleted. That is, the following corresponding textarea and "+Add Text" span.
I almost have it. Here is my jQuery
$('.delete-text-box-x').click(_.bind(function(e){
$('.delete-text-box-x').nextUntil('.add-textbox').remove();
}, this));
}
It's obvious why this doesn't work. The nextUntil method does indeed select and remove the textboxes following the 'X' divs. But the selector selects EVERY 'X' on the page, and therefore deletes EVERY textbox on the page. It also doesn't delete the '+Add Textbox' spans...
So how do I get more specific than the current selector I'm using? So it selects ONLY the specific 'X' I click, rather than every 'X' on the page.
Firstly, you need to base the selector on the element that raised the event using the this keyword. From there you can use nextUntil(), but you should use the selector of the next X so that all the required elements are found. Finally you need to use add() to include the clicked X itself. Try this:
$('.delete-text-box-x').click(function (e) {
$(this).nextUntil('.delete-text-box-x').add(this).remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="popup">
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
<div class="delete-text-box-x">X</div>
<textarea class="textbox"></textarea>
<span class="add-textbox">+Add text</span>
</div>
I also note you're using some odd syntax around the anonymous function in the click handler which I presume this is due to another library. If not you should remove it.
This until works to find another element in the siblings, so in the above code you are selecting the next add-textbox and not the next X icon.
$('.delete-text-box-x').click(function() {
$(this).nextUntil('.delete-text-box-x')add(this).remove();
});

show/hide div with dyamically assigned class

I am dynamically assigning the div id based on the api call back data. For example I have a bunch of data returned which is appended to a div and I can assign the div id with a unique ip address. I have full control over what I can assign i.e. DIV id or class or whatever..
I have attached an example of what the output looks like and hopefully it will clarify what i am looking for.
What I want to be able to achieve is when an endpoint link is clicked, it will show the respective div and hide all other DIV data boxes.. The endpoint links can made clickable and i can add onclick scripts to them or whatever needs to be done
Whether we use the div id or class name i am not fussed.
This should work just fine.
Assign your div with a class, in the demo i'm using EndPoint. The onclick function will use the class to find the div element and hide it. Then it will use this the element used to trigger the function, target the div within that element and show it.
$('.EndPoint').on('click', function () {
$('.EndPoint').find('div').hide();
$(this).find('div').show();
});
.EndPoint div{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="EndPoint">
End Point [0]
<div><b>IP Address:</b> 216.12.145.20</div>
</div>
<div class="EndPoint">
End Point [1]
<div><b>IP Address:</b> 172.230.105.123</div>
</div>
<div class="EndPoint">
End Point [2]
<div><b>IP Address:</b> 206.204.52.31</div>
</div>
If you don't understand anything please leave a comment below and I will get back to you as soon as possible.
Edit - jQuery Append with onclick
var IPs=["216.12.145.20","172.230.105.123","206.204.52.31"];
//Foreach value in array
$.each(IPs, function(i,v) {
//Append to id:container
$('#container').append('<div class="EndPoint">End Point ['+i+']<div><b>IP Address:</b> '+v+'</div></div>');
});
$('.EndPoint').on('click', function () {
$('.EndPoint').find('div').hide();
$(this).find('div').show();
});
.EndPoint div{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"></div>
I hope this helps. Happy coding!
Since elements are dynamically generated it's better to do with classes IMO.
HTML
<div id="endpoint1">
<a href='#' class='clicker'>End Point 1</a>
<p class='hideThis'>1.1.1.1</p>
</div>
<div id="endpoint2">
<a href='#' class='clicker'>End Point 2</a>
<p class='hideThis'>1.1.1.1</p>
</div>
<div id="endpoint3">
<a href='#' class='clicker'>End Point 3</a>
<p class='hideThis'>1.1.1.1</p>
</div>
JavaScript (using JQuery)
$('.clicker').on('click', function () {
$('.hideThis').hide();
$(this).next().show();
});
http://jsfiddle.net/ksvexr40/1
If you want to hide the content initially, just add the following CSS class which hides the content initially.
.hideThis{
display: none;
}

Can't reach element by using a combination of .parent() and .next() methods

I'm binding the following function to a toggle button I have created to hide/unhide content that is located bellow the button, but on an other level in the DOM.
var togglelabel = packagehead.append("<div>").children().last().addClass("togglewrap").append("<label>")
.children().last().addClass("toggle android header-toggle")
.on('click', function(){
$(this).parent().parent().next('.hidable').toggle();
});
The html structure looks like this:
<div>
<div class="packageheader">
<span>Package #1501</span>
<div class="togglewrap">
<label class="toggle android header-toggle">
<input type="checkbox">
<p>
<span>More</span>
<span>Less</span>
</p>
<a class="slide-button">
</a>
</label>
</div>
</div>
<br>
<p class="hidable">
<pre>content here</pre>
</p>
</div>
This code doesn't work to hide the <p> with the class .hidable.
I've tried 'debugging' the code using console.log() to see what element 'this' represents and found that it does, as expected, represent the label element.
So I thought that using the following chain:
$(this).parent().parent().next('.hidable').toggle();
Would correctly go 2 levels up to the <div class="packageheader"> and then take the next sibling with the class hidable, which would be <p class="hidable">
Here is a screenshot of the structure, to be sure I didn't miss anything:
You can do this :
$(this).closest('.packageheader').nextAll('.hidable').first().toggle();
Note that it's slightly preferable to use closest instead of parent().parent() as it won't break as easily when the HTML changes and it's easier for the maintainer to decipher what the code does.
Note also that your HTML is invalid, you can't have a PRE inside a P.
Demonstration

onclick alert jquery html javascript

I have a page so far with:
<div id="x1">Text paragraph 1<link here></div>
<div id="x2">Text paragraph 2<link here></div>
<div id="x3">Text paragraph 3<link here></div>
Where link here is like
google
What I am trying to do is add a link to the bottom of each paragraph of text so that when it is clicked it displays an alert with the div id of that text block.
So for example, if someone clicks on the link at the bottom of text paragraph 2, then they will get an alert saying "x2".
So far, I have only been able to think of a way involving an onclick event for each link in each div. But with 100 paragraphs this could become quite a lot and is messy code.
like
$('#x1').onclick(function(){
alert('x1');
});
How can I do this better?
The page is generated with php so I could put the div id's anywhere in that text block area (even make a new div around the link if required)...
EDIT - Many good answers, I don't know which to pick as best. I actually ended up using Loongawas for my purpose as its easy to make for my beginner level in php.
<div id='a1'>This text <a href="" onclick=tomato(1)>test</a>
</div>
<div id='a2'>This text <a href="" onclick=tomato(2)>test</a>
</div>
<div id='a3'>This text <a href="" onclick=tomato(3)>test</a>
</div>
and
function tomato(test){
alert(test);
};
Some of the others are incredibly interesting as they use higher functions. I'm going to spend the rest of the day looking into them. Thanks to all.
use jQuery's live or delegate functions:
$('div a').live('click', function(ev){
alert($(this).closest('div').attr('id'));
});
The benefit to the live/delegate functions is that there's actually only a single event on the entire page for this (as opposed to one event per link). If you add more links dynamically, this still works without having to attach more events.
The difference between live and delegate is that delegate is specific to a part of the page. If, for instance, you wrapped all of these DIVs in another div, the call would look like:
$('#wrapperDiv').delegate('a', 'click', function(ev){ ...
The advantage to this is that the internal jQuery code that checks to see if the click matches the selector only runs on clicks inside of #wrapperDiv instead of clicks anywhere on the page.
You could make a javascript function that takes a variable and then pass the paragraph number to the function. If the paragraph was number two you could call
myfunction(2);
or is the number not the problem?
$('#x1, #x2, #x3').click(function(){
alert($(this).parents().attr("id"));
});
EDIT:
Better version:
HTML:
<div class="x">Text paragraph 1<link here></div>
<div class="x">Text paragraph 2<link here></div>
<div class="x">Text paragraph 3<link here></div>
$('.x a').click(function(){
alert($(this).parents().attr("id"));
});
Have you considered using a class to name them all as opposed to explicit ids?
<div class="x">Text paragraph 1<link here></div>
<div class="x">Text paragraph 2<link here></div>
<div class="x">Text paragraph 3<link here></div>
so then you would be able to use a single click event for all of them?
$(".x a").click()
{
//Use $(this) to refer to the clicked item.
alert($(this).parents().attr("id"));
});
$('.myDivs').click(function(){
alert($(this).parent().attr("id"));
});
Or select the divs in some other way:
$('#x1').parent().children('div').click(...);
Something along these lines should work:
<div id="x1">Text paragraph 1 <a href='google.com'>google.com</a></div>
<div id="x2">Text paragraph 2 <a href='google.com'>google.com</a></div>
<div id="x3">Text paragraph 3 <a href='google.com'>google.com</a></div>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js'></script>
<script>
$('a').click(function() {
alert($(this).parent().attr('id'))
return false
})
</script>
Add a class to each div, so you can select all of 'em at once.
<div id="x1" class="x">Text paragraph 1 <a>Click</a></div>
<div id="x2" class="x">Text paragraph 2 <a>Click</a></div>
<div id="x3" class="x">Text paragraph 3 <a>Click</a></div>
Then you can do:
$('div.x a').live('click', function(e){
e.preventDefault();
alert($(this).closest('div.x').attr('id'));
});
http://jsfiddle.net/VGh3X/1/
A better approach to this is to make all of the clickable areas share something in common that you can use as a selector. For example, if all of the clickable divs had class='click', you'd be able to select them all using $('.click') and bind to that.
$('.click a').bind('click', function() {
var div = this.closest('.click');
alert(div.attr('id'));
return false;
});
$(document).ready(function() {
var links = $("div[id^='x'] a"); //get the a tags
$.each(links, function(i,v) {
$(v).click(function() { //bind on click
alert(v.parentNode.id); //alert div id
return false; // stop
});
});
});

Categories