JQuery find child element inner text and replace with IMG HTML - javascript

I need a little help with a Javascript function I am creating. In essence, I need to loop through a set of DIVs with class .DetailRow and find a child DIV's content (inner text). If this text is matched to a variable, then I need to replace this inner text with an IMG HTML statement.
BTW I am kinda new at this (4 months old!) so apologies if the issue is simple, but I have tried a few combos and I am stuck.
Here's the HTML:
<div class="DetailRow" style="display: ">..</div>
<div class="DetailRow" style="display: ">..</div>
<div class="DetailRow" style="display: ">
<div class="Label">Availability:</div>
<div class="Value">in stock + Free Shipping</div>
</div>
Example, if I find "in stock" in the LABEL inner text, I want to replace it with the value of the variable "instock" which is an IMG HTML statement. See my code attempt below.
<script type="text/javascript">
$(window).load(function(){
var instock = '<img src="https://linktoimgfolder/instock.gif" title="Product available, usually ships 24hrs to 48hrs after order receipt" style="margin-top:-3px;">';
var lowstock = '<img src="https://linktoimgfolder/lowstock.gif" title="Product stcok low, order today so you do not miss out">';
var nostock = '<img src="https://linktoimgfolder/outstock.gif" title="Product out of stock, could ship 1 to 2 weeks after order receipt">';
$('div.DetailRow')each(function(){
if (indexOf($(this).childNodes[1].innerHTML, "in stock") > 0) {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = instock;
} else if (indexOf($(this).childNodes[1].innerHTML, "low stock") > 0) {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = lowstock;
} else {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = nostock;
};
});
});
</script>​
By the way,m I cannot match text exactly as the text beyond the "+" will change from time to time, thus I am trying indexOf.
Many thanks in advance for your assistance!
M

Using the :contains selector
var stock = {'in stock': instock, 'low stock': lowstock, 'no stock': nostock};
Object.keys(stock).forEach(function(key) {
$('div.DetailRow div:contains(' + key + ')').html(stock[key]);
});
jsFiddle Demo
A pure jQuery solution:
$.each(stock, function(key, value) {
$('div.DetailRow div:contains(' + key + ')').html(value);
});

You have typo in this line $('div.DetailRow')each(function(){ and then you can use jQuery .text() and .html() to check value and update.
Try:
$('div.DetailRow').find("div").each(function(){
if($(this).text().indexOf("in stock")!=-1){
$(this).text("");
$(this).html(instock);
}else if($(this).text().indexOf("low stock")!=-1){
$(this).text("");
$(this).html(lowstock);
}else{
$(this).text("");
$(this).html(nostock);
}
});
DEMO FIDDLE
NOTE: Updated code to find div inside div.DetailsRow. Change it according to your requirement.

Related

How to select and change text using jquery [duplicate]

I have a HTML structure like this:
<div class="votes">
<b>5</b> Votes
<a id="vote-' + element_id +'" href="#" class="vote-btn"></a>
</div>
I have manage to get the text after 5 i.e. votes using:
var voteTextNode = $(this).parent('div').contents().filter(function() {
return this.nodeType == 3;
});
var voteText = voteTextNode.text();
now i want to change this text to vote which is respective number of votes . I have tried this:
voteNewText = ( newCount == '1' ) ? 'Vote' : 'Votes';
voteTextNode.text(voteNewText);
but it does not work for me. I have also tried the code from this link:
How can I get, manipulate and replace a text node using jQuery?
but it also wont work for me tell me where i am doing wrong
As you have seen, jQuery is not really made for handling text nodes. Your var voteTextNode will be a jQuery instance, holding a set of text nodes. You can hardly manipulate them using .text(), which would add some new TextNodes into them.
Yet, this should work:
$(this).parent('div').contents().each(function() {
// iterate over all child nodes
if (this.nodeType == 3)
this.data = "Vote";
});
But with plain dom methods it may be clearer:
var countTextNode, voteTextNode;
$(this).parent('div').find('b').each(function() {
countTextNode = this.firstChild;
voteTextNode = this.nextSibling;
});
return function setVotes(num) {
countTextNode.data = num;
votTextNode.data = num == 1 ? 'Vote' : 'Votes';
};
put it in a span
<div class="votes">
<b>5</b> <span id="votesTxt">Votes</span>
<a id="vote-' + element_id +'" href="#" class="vote-btn"></a>
</div>
and then
$("#votesTxt").text(( newCount == '1' ) ? 'Vote' : 'Votes');
EDIT if you don't wish to use span then just change the text for the element after the b tag:
$("#votes b:first")[0].nextSibling.data = (( newCount == '1' ) ? 'Vote' : 'Votes');
Treat it as the DOM tree it is: what you probably want is to get the first <b> element inside each <div> with class "votes" and then change the text in the text node that immediately follows it. jQuery is good at selecting and iterating over elements so use it for this part if you want. Once you've got the <b> elements, switch to regular DOM. Here's an example:
Demo: http://jsfiddle.net/Qq3T7/
Code:
$("div.votes").find("b:first").each(function() {
this.nextSibling.data = ($(this).text() == "1") ? " Vote" : " Votes";
});
Can you change the initial markup? You'll have a much easier time doing this if you just wrap the text you want to change in a tag:
<span id="votetext">Vote</span>
And then you can easily set the text:
$('#votetext').text('Votes');

Get multiple elements same class - JavaScript (getElementsByClass)

I have an 'a href' that is a title.
Vendor1 product title
I want to display an image based on the first word of the title.
Vendor1 product title
<div class="logo"></div>
Vendor2 product title
<div class="logo"></div>
Vendor3 product title
<div class="logo"></div>
These are item cells and they use the same template to be generated so the classes are always the same. There are many of them.
The script I have so far is working but only for the first product in the list (shows correct logo).
function getlogo() {
var string1 = document.getElementsByClassName('title')[0].innerHTML;
var vendor = string1.replace(/([a-z]+) .* ([a-z]+)/i, "$1").toLowerCase();
document.getElementsByClassName('logo')[0].innerHTML = '<img src="/myimages/' + vendor + '.jpg" width="100px" height="50px" onerror="imgError(this);">';
function imgError(image) {
image.onerror = "";
image.src = "default.jpg";
return true;
}
}
getlogo();
I've looked around but sure how to loop this or even if that is the solution.
http://jsfiddle.net/W7bm5/
It's easy if you use jQuery each function.
function imgError(image) {
image.onerror = "";
image.src = "default.jpg";
return true;
}
$(document).ready(function() {
$(".title").each(function() {
var string1 = $(this).text();
var vendor = string1.replace(/([a-z]+) .* ([a-z]+)/i, "$1").toLowerCase();
$(this).html('<img src="/myimages/' + vendor + '.jpg" width="100px" height="50px" onerror="imgError(this);">');
});
});
or you can do it with the pure javascript, but put your logics in a loop, with [0] replaced to the loop index.
Update - here's how to keep the current text links:
function imgError(image) {
image.onerror = "";
image.src = "default.jpg";
return true;
}
$(document).ready(function() {
$(".title").each(function() {
var string1 = $(this).text();
var vendor = string1.replace(/([a-z]+) .* ([a-z]+)/i, "$1").toLowerCase();
var html = $(this).parent().html();
$(this).parent().html(html + '<br /><img src="/myimages/' + vendor + '.jpg" width="100px" height="50px" onerror="imgError(this);">');
});
});
You could use a for loop to run through the code you have for a different index of the getElementsByClassName results. See your jsFiddle
You could also ditch the getElementByClassName, which I think has spotty support in some browsers and isn't especially good performance, and navigate the DOM using JavaScript if your structure is always the same, or even jQuery if you'd like a library to make it easier.
But by far the best is if you did it when it was generated in the first place. How are you generating the code and could you not use that to achieve what you are trying to achieve?

Add Html to Text without children element

I am very confused on how to get this work, did a lot of research online to help find a solution to this, but got nothing. Found this link here: http://viralpatel.net/blogs/jquery-get-text-element-without-child-element/ but still didnt help much
This is what I am trying to accomplish, the system is outputting text like this, I have no control over the html.
<div class="myclass">
Text 1
Text 2
Text 3
</div>`
but would like to use jquery to insert html around those text
For example:
<div class="myclass">
<span>Text 1 </span>
<span> Text 2 </span>
<span> Text 3</span>
</div>
any help is appreciated
thank you very much
$('.myclass').html(function(i, v){
return '<span>' + $.trim(v).split('\n').join('</span><span>') + '</span>';
});
http://jsfiddle.net/vDp6A/
There are other ways. This would satisfy the question.
$(function(){
stuff=$('.myclass').text().split("\n");
newhtml='';
$.each(stuff, function(i,o){
if (o!=''){
newhtml +='<span>' + o + '</span>'."\n";
}
});
$('.myclass').html(newhtml);
});
This should sort it:
var theDivs = document.getElementsByClassName('myclass');
for(var i in theDivs)
{
if(parseInt(i)==i)
{
var div = theDivs[i];
var text = div.innerHTML.split("\n");
for(var k in text)
{
var trimmed = text[k].replace(/^\s+|\s+$/,'');
if(trimmed != '') text[k] = '<span>'+trimmed+'</span>';
else text[k] = trimmed;
}
div.innerHTML = text.join("\n");
}
}

add what contains in element along with array

I'm trying to add the content of each span along with the value in the title attribute.
<div id="group-wrap" class="group">
<span class="lbracket" title="&f">(</span>
<span class="grouptitle" title="&f"> Group </span>
<span class="rbracket" title="&f">) </span>
<span class="username" title="&f"> Username </span>
<span class="col" title="&f">:</span>
<span class="text" title="&f"> Helo There! </span>
</div>
Here is what I have so far:
var str = [];
$('#group-wrap span').each(function(){
str.push($(this).attr('title'));
});
alert(str.join(''));
});
http://jsfiddle.net/B9QeK/3/
The output is &f&f&f&f&f (the value of each title attribute), but the expected output has the value, plus the content that is in the span. The value of the attribute should be appended before the content.
&f(&fGroup&f)&fUsername: &f text
How can I get this result?
Looks like you are looking for
str.push( this.getAttribute('title'), this.textContent || this.text );
As for performance reasons, you should not re-create a jQuery object for every single iteration. Even better, don't use jQuery at all to receive those values.
JSFiddle
And by the way, you can make usage of jQuerys .map() to do it a bit more elegant:
jQuery(function($){
var str = $('#group-wrap span').map(function(){
return this.getAttribute('title') + this.textContent || this.text;
}).get();
alert(str.join(''));
});
JSFiddle
Reference: .map()
jQuery(function($){
var str = [];
$('#group-wrap span').each(function(){
str.push($(this).attr('title') + $(this).text());
});
alert(str.join(''));
});
Working JSFiddle
text:
Description: Get the combined text contents of each element in the set of matched elements, including their descendants.
docs
Just use the text method to get the text content of each span:
var str = [];
$('#group-wrap span').each(function(){
//Push value of title attribute and text content into array:
str.push($(this).attr('title') + $(this).text());
});
alert(str.join(''));
});
Your line
str.push($(this).attr('title'));
Should look like:
str.push($(this).attr('title') + $(this).text());
Although, this is making two identical calls $(this), so you might consider caching:
var $this = $(this)
str.push($this.attr('title') + $this.text());
var str = "";
$('#group-wrap span').each(function(){
str+=$(this).attr('title')+$(this).text();
});
alert(str);
});

Pass variable in document.getElementByid in javascript

I have a variable account_number in which account number is stored. now i want to get the value of the element having id as account_number. How to do it in javascript ?
I tried doing document.getElementById(account_number).value, but it is null.
html looks like this :
<input class='transparent' disabled type='text' name='113114234567_name' id='113114234567_name' value = 'Neeloy' style='border:0px;height:25px;font-size:16px;line-height:25px;' />
and the js is :
function getElement()
{
var acc_list = document.forms.editBeneficiary.elements.bene_account_number_edit;
for(var i=0;i<acc_list.length;i++)
{
if(acc_list[i].checked == true)
{
var account_number = acc_list[i].value.toString();
var ben_name = account_number + "_name";
alert(document.getElementById("'" + ben_name.toString() + "'").value);
}
}
}
here bene_account_number_edit are the radio buttons.
Thanks
Are you storing just an integer as the element's id attribute? If so, browsers tend to behave in strange ways when looking for an element by an integer id. Try passing account_number.toString(), instead.
If that doesn't work, prepend something like "account_" to the beginning of your elements' id attributes and then call document.getElementById('account_' + account_number).value.
Why are you prefixing and post-fixing ' characters to the name string? ben_name is already a string because you've appended '_name' to the value.
I'd recommend doing a console.log of ben_name just to be sure you're getting the value you expect.
the way to use a variable for document.getElementById is the same as for any other function:
document.getElementById(ben_name);
I don't know why you think it would act any differently.
There is no use of converting ben_name to string because it is already the string.
Concatenation of two string will always give you string.
var account_number = acc_list[i].value.toString();
var ben_name = account_number + "_name";
try following code it will work fine
var ben_name=acc_list[i]+ "_name";
here also
alert(document.getElementById("'" + ben_name.toString() + "'").value);
try
alert(document.getElementById(ben_name).value);
I have tested similar type of code which worked correctly. If you are passing variable don't use quotes. What you are doing is passing ben_name.toString() as the value, it will definitely cause an error because it can not find any element with that id viz.(ben_name.toString()). In each function call, you are passing same value i.e. ben_name.toString() which is of course wrong.
I found this page in search for a fix for my issue...
Let's say you have a list of products:
<div class="rel-prod-item">
<img src="assets/product-photos/title-of-the-related-product_thumbnail.jpg" alt="Western Digital 1TB" />
<p class="rel-prod-title">Western Digital 1TB</p>
<p class="rel-prod-price" id="price_format_1">149.95</p>
add to cart
</div>
<div class="rel-prod-item">
<img src="assets/product-photos/title-of-the-related-product_thumbnail.jpg" alt="Western Digital 1TB" />
<p class="rel-prod-title">Western Digital 1TB</p>
<p class="rel-prod-price" id="price_format_2">139.95</p>
add to cart
</div>
<div class="rel-prod-item">
<img src="assets/product-photos/title-of-the-related-product_thumbnail.jpg" alt="Western Digital 1TB" />
<p class="rel-prod-title">Western Digital 1TB</p>
<p class="rel-prod-price" id="price_format_3">49.95</p>
add to cart
</div>
The designer made all the prices have the digits after the . be superscript. So your choice is to either have the cms spit out the price in 2 parts from the backend and put it back together with <sup> tags around it, or just leave it alone and change it via the DOM. That's what I opted for and here's what I came up with:
window.onload = function() {
var pricelist = document.getElementsByClassName("rel-prod-price");
var price_id = "";
for (var b = 1; b <= pricelist.length; b++) {
var price_id = "price_format_" + b;
var price_original = document.getElementById(price_id).innerHTML;
var price_parts = price_original.split(".");
var formatted_price = price_parts[0] + ".<b>" + price_parts[1] + "</b>";
document.getElementById(price_id).innerHTML = formatted_price;
}
}
And here's the CSS I used:
.rel-prod-item p.rel-prod-price b {
font-size: 50%;
position: relative;
top: -4px;
}
I hope this helps someone keep all their hair :-)
Here's a screenshot of the finished product

Categories