From the given HTML, I am trying to extract the pText array, so that I end up with two <p> items (in this case), from which I can extract the two text strings "link test1" and "link test2", and pop an alert for each of them. Why doesn't the below script work?
HTML:
<div>
<p><a href='/'>link</a> test1</p>
<p><a href='/'>link</a> test2</p>
</div>
Javascript:
var pText = $('div').find('p');
for (i = 0; i < pText.length; i++) {
alert(pText[i].text());
}
Since that you're using jQuery, if you want to use the .text() method you have to extract a jQuery object and use .eq(i) instead of [i], which returns a normal element.
Here's the correct code:
var pText = $('div').find('p');
for (i = 0; i < pText.length; i++) {
alert(pText.eq(i).text());
}
Also, you can simplify your code using the .each() method (instead of the for loop), which calls a given function for every element of your jQuery collection (pText). In my opinion, it's easier, here you go:
var pText = $('div').find('p');
pText.each(function(i, el) {
alert($(el).text());
});
text() is a function for jQuery objects.
Use it by wrapping your element in $(..)
alert($(pText[i]).text());
And a better way is to use .each()
$('div').find('p').each(function(){
alert($(this).text());
});
Try using alert(pText.eq(i).text()); instead of alert(pText[i].text());
The jQuery code will be
var pText = $('div').find('p');
for (i = 0; i < pText.length; i++) {
alert(pText.eq(i).text());
}
$('#x').children('p').each(function() {
alert($(this).text()); // "this" is the current element in the loop
});
JSFiddle
Related
Lets imagine I have the following HTML code.
I need to find the position within the LI elements for the LI which has the class focus applied.
In this example the result should be 2 (if at 0 index). Any idea how to do it?
<ul class="mylist">
<li>Milk</li>
<li>Tea</li>
<li class="focus">Coffee</li>
</ul>
In pure JavaScript:
var index = 0;
var lis = document.getElementsByTagName('li');
for (var len = lis.length; index < len; ++index) {
if (lis[index].className.match(/\bfocus\b/)) {
break;
}
}
(fiddle)
While you've already accepted an answer to your question, I thought I'd put together a simple index() method for HTMLElements:
HTMLElement.prototype.index = function () {
var self = this,
parent = self.parentNode,
i = 0;
while (self.previousElementSibling){
i++;
self = self.previousElementSibling
}
return this === parent.children[i] ? i : -1;
}
var focus = document.querySelector('li.focus'),
i = focus.index();
console.log(i); // 2
JS Fiddle demo.
References:
Element.previousElementSibling
document.querySelector().
Use .index()
var index = $('.focus').index();
DEMO
Specific list
$('.mylist .focus').index()
DEMO
In jQuery, you should be able to get it, via index. With classes, you could run into issues, when having multiple of them.
I prepared a Plunker, where you can see a solution to the problem.
the expanded version (jquery) would be
$(document).ready(function(){
$('li').each(function(){
var cls=$(this).attr('class');
if(cls=='focus'){
alert($(this).index());
}
});
});
I have the following code:
<div class="TopMenu">
<h3>Create an Account</h3>
<h3>yup</h3>
<h3>lol</h3>
yo
<ul>
<li sytle="display:">
start or
finish
</li>
</ul>
and I'm using:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).text();
$(this).text(text.replace('or', 'triple'));
});
It works fine, but suddenly the links aren't active,
how do I fix it?
Thank you very much in advance.
Here's what your jQuery basically translates to when it's being run:
text = this.textContent;
// text = "\n\t\tstart or\n\t\t finish\n\t\t\n";
text = text.replace('or','triple');
// text = "\n\t\tstart triple\n\t\t finish\n\t\t\n";
this.textContent = text;
// essentially, remove everything from `this` and put a single text node there
Okay, that's not a great explanation XD The point is, setting textContent (or, in jQuery, calling .text()), replaces the element's contents with that text.
What you want to do is just affect the text nodes. I'm not aware of how to do this in jQuery, but here's some Vanilla JS:
function recurse(node) {
var nodes = node.childNodes, l = nodes.length, i;
for( i=0; i<l; i++) {
if( nodes[i].nodeType == 1) recurse(node);
else if( nodes[i].nodeType == 3) {
nodes[i].nodeValue = nodes[i].nodeValue.replace(/\bor\b/g,'triple');
}
}
}
recurse(document.querySelector(".TopMenu"));
Note the regex-based replacement will prevent "boring" from becoming "btripleing". Use Vanilla JS and its magic powers or I shall buttbuttinate you!
Change .text() to .html()
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text.replace('or', 'triple'));
});
See Fiddle
Since or is a text node, you can use .contents() along with .replaceWith() instead:
$('.TopMenu li:contains("or")').each(function () {
var text = $(this).text();
$(this).contents().filter(function () {
return this.nodeType === 3 && $.trim(this.nodeValue).length;
}).replaceWith(' triple ');
});
Fiddle Demo
You need to us .html() instead of .text(),
Like this:
$('.TopMenu li:contains("or")').each(function() {
var text = $(this).html();
$(this).html(text('or', 'triple'));
});
Here is a live example: http://jsfiddle.net/7Mamj/
jsFiddle Demo
You are placing the anchors into text by doing that. You should iterate the matched elements' childNodes and only use replace on their textContent to avoid modifying any html tags or attributes.
$('.TopMenu li:contains("or")').each(function() {
for(var i = 0; i < this.childNodes.length; i++){
if(this.childNodes[i].nodeName != "#text") continue;
this.childNodes[i].textContent = this.childNodes[i].textContent.replace(' or ', ' triple ');
}
});
It is a bit more complicated task. You need to replace text in text nodes (nodeType === 3), which can be done with contents() and each iteration:
$('.TopMenu li:contains("or")').contents().each(function() {
if (this.nodeType === 3) {
this.nodeValue = this.nodeValue.replace('or', 'triple');
}
});
All other approaches will either rewrite the markup in the <li> element (removing all attached events), or just remove the inner elements.
As discussed in the comments below, fool-proof solution will be to use replacement with regular expression, i.e. this.nodeValue.replace(/\bor\b/g, 'triple'), which will match all or as standalone words and not as parts of words.
DEMO: http://jsfiddle.net/48E6M/
I'm using an external script on my website with a form.
Some of the css is customizable, but I can't change images for example.
I would like to replace the small image displayed when a field is not completed by an other one using Javascript.
This is the HTML code with the original image :
<img class="incorrect-img" count="1" src="http://www.detailsdetails.eu/images/newimg/incorrect.gif"></img>
I'm trying with this Js code but it's not working...
$(document).ready(function () {
document.getElementsByClassName("incorrect-img").src="MYIMAGE.gif";
});
Does anyone know what I'm doing wrong?
Maybe it's because I'm trying to change an image from a class, maybe it only works with ID ? I can't change the class by ID...
document.getElementsByClassName("incorrect-img") returns an HTMLcollection which is like an array but not quite.
Luckily you can loop over it like you would with an array:
var elems = document.getElementsByClassName("incorrect-img");
for (var i = 0; i < elems.length; i+= 1) {
elems[i].src = "MYIMAGE.gif";
}
If you want to use jQuery
$(document).ready(function () {
$( ".incorrect-img" ).each(function( index ) {
$(this).attr('src', 'MYIMAGE.gif');
});
});
Since you're already using jQuery, instead of:
document.getElementsByClassName("incorrect-img").src="MYIMAGE.gif";
You can use:
$(".incorrect-img").attr("src", "MYIMAGE.gif");
document.getElementsByClassName() returns the elements of array which are matched with class selector, In your case there is only one image so 0 index would be fine for access the first element. like this
document.getElementsByClassName("incorrect-img")[0].src="MYIMAGE.gif";
For inormationa about `getElementsByClassName()
thanks a lot.
I combined your answers.
here is my final code :
$(window).load(function() {
var image = $(".incorrect-img");
for (var i = 0; i < image.length; i++) {
image[i].src="incorrect_2.gif";
}
});
I have some div ids that are generated dynamicly via php
<div id='a<?php echo $gid?>>
How can I access them in JavaScript? All these divs start with "A" followed by a number.
Is there some kind of search function
getElementById(a*)?
Thanks for any help
No generic JavaScript function for this (at least not something cross browser), but you can use the .getElementsByTagName and iterate the result:
var arrDivs = document.getElementsByTagName("div");
for (var i = 0; i < arrDivs.length; i++) {
var oDiv = arrDivs[i];
if (oDiv.id && oDiv.id.substr(0, 1) == "a") {
//found a matching div!
}
}
This is the most low level you can get so you won't have to worry about old browsers, new browsers or future browsers.
To wrap this into a neater function, you can have:
function GetElementsStartingWith(tagName, subString) {
var elements = document.getElementsByTagName(tagName);
var result = [];
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element.id && element.id.substr(0, subString.length) == subString) {
result.push(element);
}
}
return result;
}
The usage example would be:
window.onload = function() {
var arrDivs = GetElementsStartingWith("div", "a");
for (var i = 0; i < arrDivs.length; i++) {
arrDivs[i].style.backgroundColor = "red";
}
};
Live test case.
In case you choose to use jQuery at some point (not worth for this thing alone) all the above code turns to single line:
$(document).ready(function() {
$('div[id^="a"]').css("background-color", "blue");
});
Updated fiddle, with jQuery.
No, you need a fixed id value for getElementById to work. However, there are other ways to search the DOM for elements (e.g. by CSS classes).
You can use querySelectorAll to get all divs that have an ID starting with a. Then check each one to see if it contains a number.
var aDivs = document.querySelectorAll('div[id^="a"]');
for(var index = 0, len = aDivs.length; index < len; index++){
var aDiv = aDivs[index];
if(aDiv.id.match(/a\d+/)){
// aDiv is a matching div
}
}
DEMO: http://jsfiddle.net/NTICompass/VaTMe/2/
Well, I question myself why you would need to select/get an element, that has a random ID. I would assume, you want to do something with every div that has a random ID (like arranging or resizing them).
In that case -> give your elements a class like "myGeneratedDivs" with the random ID (if you need it for something).
And then select all with javascript
var filteredResults=document.querySelectorAll(".myGeneratedDivs").filter(function(elem){
....
return true;
});
or use jQuery/Zepto/YourWeaponOfChoice
var filteredResults=$(".myGeneratedDivs").filter(function(index){
var elem=this;
....
return true;
});
If you plan to use jQuery, you can use following jQuery selectors
div[id^="a"]
or
$('div[id^="id"]').each(function(){
// your stuff here
});
You will have to target the parent div and when someone click on child div inside a parent div then you can catch the child div.
<div id="target">
<div id="tag1" >tag1</div>
<div id="tag1" >tag2</div>
<div id="tag1" >tag3</div>
</div>
$("#target").on("click", "div", function() {
var showid = $(this).attr('id');
alert(showid)
});
getElementById() will return the exact element specified. There are many javascript frameworks including jQuery that allow much more powerful selection capabilities. eg:
Select an element by id: $("#theId")
Select a group of elements by class: $(".class")
Select subelements: $("ul a.action")
For your specific problem you could easily construct the appropriate selector.
I have some data coming from the server in which I fill A Div in the Html page with.
The way I write the div is as follows:
<div class="BigDiv"><label class = "AttList" Std_Id="' + Std_Id + '">' + Std_Name +'</label></div>
Now, I want the data inside this div.
There are some other labels inside the div so I use this.children to access this label.
var labels = $(this).children('div');
var StdName = this.children[0].childNodes[0].nodeValue;
I want to access the Std_Id inside the Std_Id attribute, but I don't know how to do it ... Do you have any ideas?
Thanks.
Assuming that $(this) is a reference to the .BigDiv element:
var StdName = $(this).find('label').attr('Std_Id');
Or, similarly, and with the assumption that this is the .BigDiv element:
var children = this.childNodes;
for (var i=0,len=children.length; i<len; i++){
if (children[i].nodeType == 1 && children[i].tagName.toLowerCase() == 'label'){
var StdName = this.getAttribute('Std_Id');
}
}
References:
jQuery:
attr().
find().
JavaScript
element.getAttribute().
node.nodeType.
tagName.
toLowerCase().
Use getAttribute:
var labels = $(this).children('div');
var StdId = this.children[0].getAttribute("Std_Id");
Note that, according to the HTML5 spec, custom attributes should start with data-, though most browsers can tolerate it.
To save elements, which were selected using a jQuery-Selector, do this:
$labels = $('.BigDiv').find('label');
Now you can loop through each label with jQuery's foreach loop:
$.each($labels, function() {
var std_id = $(this).attr('Std_Id');
// do something with std_id
});
You could use the attr method as such,
var value = $('.AttList').attr('Std_Id');
EDIT
OK, so you for your implementation, you need to do this...
var value = $(this).find('.AttList').attr('Std_Id');
Assuming that this is the div or the parent of that div