Replacing dhtml element without using innerHTML - javascript

This seems like it should be easy. I have a html snippet that I wish to locate and modify in place via javascript. But not just the innerHTML; I want to replace the entire element. Example:
<div class="content">
<div class="item">
<img src="images/pic1.jpg" />
<a class="clicker" onclick="javascript:doSomethingUseful(##);">Do ##!</a>
<h3>title</h3>
<p>description</p>
</div>
</div>
After page load, I want to grab the <a class="clicker" ...>Now!</a> and replace it with three instances like:
<div class="content">
<div class="item">
<img src="images/pic1.jpg" />
<a class="clicker" onclick="javascript:doSomethingUseful(1);">Do 1!</a>
<a class="clicker" onclick="javascript:doSomethingUseful(2);">Do 2!</a>
<a class="clicker" onclick="javascript:doSomethingUseful(3);">Do 3!</a>
<h3>title</h3>
<p>description</p>
</div>
</div>
Using prototype.js, I can easily do $$('.clicker') and get an array with the element. I can use .innerHTML and get the 'Do ##!' and change it. But I want, nay, need the entire element to insert it in place. I can go through weird machinations of siblings and parent, and walk back around the nodes to eventually get what I need, and I will do that. It just seems that I am missing something here that would make this easy.

If it is not the only HTML generation you want to run in your page, you may consider a javascript templating engine.
There are several advantages, the main one being a clear cut between the HTML view and the JS logic.
There are plenty of these engines available for every taste.
Here is how it would look with prototype.js and the PURE template engine:
$$('div.content')[0].render([1,2,3], {
'a.clicker':{
'id <-':{
'.':'Do #{id}!',
'#onclick':'javascript:doSomethingUseful(#{id});'
}
}
});

In IE you can set outerHTML. In FF, you can use this:
http://snipplr.com/view/5460/outerhtml-in-firefox/

So the way I would do this is:
Iterate over all the anchors with class clicker that are inside a div with class item which are inside class content
To each one, add a function which will hide that anchor, and then append the 3 anchors you want
So here's what my html chunk looks like:
<div class="content">
<div class="item">
<img src="images/pic1.jpg" />
<a class="clicker" href='#'>Do ##!</a>
<h3>title</h3>
<p>description</p>
</div>
</div>
And I need to include Prototype:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"></script>
And a variable to hold your replacement html, and a dummy function so what we insert works:
var myReplacementHtml = '<a class="clicker" onclick="doSomethingUseful(1);" href="#">Do 1!</a>';
myReplacementHtml += ' <a class="clicker" onclick="doSomethingUseful(2);" href="#">Do 2!</a>';
myReplacementHtml += ' <a class="clicker" onclick="doSomethingUseful(3);" href="#">Do 3!</a>';
function doSomethingUseful(n) {
alert(n);
return false;
}
Then here's my code, you may find it useful to get the backstory on how these work: $$, Element.observe, Element.hide, Element.insert, Event.stop:
<script type="text/javascript">
Event.observe(window, 'load', function(){
$$('.content .item a.clicker').each(function(item){
item.observe('click', function(evt){
item.hide();
Element.insert(item, {after: myReplacementHtml});
});
Event.stop(evt);
});
});
</script>

You can add and append elements.
function doSomethingUseful(val) {
var ele = document.getElementById('myDiv');
var newdiv = document.createElement('div');
var divIdName = 'my'+num+'Div';
newdiv.setAttribute('id',divIdName);
ni.appendChild(newdiv);
}

Related

java script replace for html attributes

I have a html tag like the following:
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1"><p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
</div>
I need to replace {slide_number} with an integer. Whatever I tried the result doesn't replace the {slide_number}
var str = template.replace("{slide_number}", i);
You can use attribute selector contains that will select all elements where id contains {slide_number} and you can replace that part of the id with the number.
document.querySelectorAll("[id*='{slide_number}']").forEach(function(e) {
e.id = e.id.replace("{slide_number}", 1)
})
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1">
<p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
in javascript you can find them from
document.querySelector('[id$="{slide_number}"]').id;
and
document.querySelector('[id*="{slide_number}"]').id;
Please read this
If you use jquery then it can be done like below:
$('#playOptions').attr('id','playOptions88');
But I recommend you to use HTML data attribute to distinguish different element. It is a very nice thing to work with multiple elements that can be needed to change dynamically.
If you change your ID attribute dynamically adding some integer number then it may be harder to catch them. Instead, use data like below code.
You can make any element unique setting the data-SOMETHING.
If you write the code below:
$('#playOptions').data('roll','100');
Then the element will be
<div id="playOptions" data-roll="100" class="playOptions">
If you write the code below:
$('#playOptions').data('name','ahmad');
Then the element will be
<div id="playOptions" data-name="ahmad" class="playOptions">
You can then catch the element by the code below:
var name = $('#playOptions').data('name');
console.log(name) //Output should be 'ahmad'
Similarly,
var roll = $('#playOptions').data('roll');
console.log(roll) //Output should be '100'
To learn more about the data attribute please see the link
https://api.jquery.com/data/
This solution worked:
var find = '{slide_number}';
var re = new RegExp(find, 'g');
str = template.replace(re, i);

How to target child div by Javascript?

I want to apply JavaScript on sticky header in my site. For this I want to target a div inside sticky div by JavaScript. Please let me know how to target a dive that is inside some other divs by JavaScript.
var yourHTML = '<div class="mynewdiv">Test</div>';
document.getElementsByClassName('at-sticky' 'custom-logo-link')
[0].innerHTML = yourHTML;
<div class="at-sticky">
<div class="container">
<div class="navbar-header">
<a href="#" class="custom-logo-link"
rel="home" itemprop="url">
<img src="#" class="custom-logo">
</a>
</div>
</div>
</div>
You can try with Document​.query​Selector() which allows CSS like selector:
var yourHTML = '<div class="mynewdiv">Test</div>';
document.querySelector('.at-sticky .custom-logo-link').innerHTML = yourHTML;
<div class="at-sticky">
<div class="container">
<div class="navbar-header">
<a href="#" class="custom-logo-link"
rel="home" itemprop="url">
<img src="#" class="custom-logo">
</a>
</div>
</div>
</div>
Please use querySelector()
var yourHTML = '<div class="mynewdiv">Test</div>';
document.querySelector('.at-sticky .custom-logo-link').innerHTML = yourHTML;
Simplest solution is using querySelector
Example:
document.querySelector('.at-sticky .container .custom-logo-link').innerHTML = yourHTML
Please put the comma in between the class names:
document.getElementsByClassName('at-sticky', 'custom-logo-link')[0].innerHTML = yourHTML;
Ok 2 points:
Firstly when using innerHTML you are inserting text into your element, not the full tag as you have done.
Secondly you only need pass in to ‘document.getElementsByClassnames’ the class name that you are targeting. Dont worry about the parent div, that should work fine as is.
I would have posted a comment but I don’t have enough reputation yet;)
You can use children() function for this.
$('.at-sticky').children();
You can use querySelector for this.
Let's say you have the following HTML structure
<div class="parentDiv">
</div>
Then you can do this in JavaScript
let parentDiv = document.querySelector('.parentDiv')
let childLink = parentDiv.querySelector('a')
console.log(childLink)

Javascript change h1 text not inner other html [duplicate]

This question already has answers here:
How do you select in-line text with Jquery?
(3 answers)
Closed 7 years ago.
I am trying to change the text of h1 tag but not other inner html. Here is my code
document.getElementById("wpbody-content").getElementsByClassName("wrap")[0].getElementsByTagName('h1')[0].innerHTML = 'Candidate Application Forms';
HTML code
<div id="wpbody-content">
<div class="wrap">
<h1>All Forms <a class="title-action" href="">Add New</a></h1>
</div>
</div>
I need to change only <h1>All Forms</h1> text not other inside the tag.
I need to do it without jQuery
Insert an extra span like this:
<div id="wpbody-content">
<div class="wrap">
<h1><span id="allForms">All Forms</span> <a class="title-action" href="">Add New</a></h1>
</div>
</div>
then manipulate it with:
document.getElementById('allForms').innerHTML = 'Candidate Application Forms';
Put All Forms in span with id like
<span id="spanId">All Forms </span>
now change content of span with id
If you want this without changing HTML:
But the best way is probably to wrap All Forms into an element, and change it.
var elt = document.getElementById("wpbody-content")
.getElementsByClassName("wrap")[0].getElementsByTagName('h1')[0];
elt.innerHTML = 'Candidate Application Forms ' + elt.children[0].outerHTML;
<div id="wpbody-content">
<div class="wrap">
<h1>All Forms <a class="title-action" href="">Add New</a></h1>
</div>
</div>
tl;dr jsFiddle
Every chunk of text is actually a TextNode. You can imagine your HTML like this:
<h1>
<text data="All Forms" />
<a class="title-action" href="">
<text data="Add New" />
</a>
</h1>
You can access those elements using HTMLElement.childNodes property:
var children = elm.childNodes;
for(var i=0,l=children.length; i<l; i++) {
if(children[i] instanceof Text)
return children[i];
}
HTMLElement.children is a list without Text nodes.
All you need is to add an id to your element and you can change it as you want.
document.getElementById("change").innerHTML="it is changed";
<div id="wpbody-content">
<div class="wrap">
<h1 id="change">All Forms <a class="title-action" href="">Add New</a></h1>
</div>
</div>
It depends on the HTML in the wrap-html tag, you could use javascript replace function on the innerHTML String, with an easy regular Expression like /<h1>[^<]*/.
/<h1>[^<]*/ matches "<h1>...until next less-then-sign (<)"
here is an example:
var newHeader = 'Candidate Application Forms'
var htmlValue = document.getElementById("wpbody-content").getElementsByClassName("wrap")[0].innerHTML;
document.getElementById("wpbody-content").getElementsByClassName("wrap")[0].innerHTML =
htmlValue.replace(/<h1>[^<]*/,"<h1>" + newHeader);
// Tested with Win7 on Chrome 46+
<div id="wpbody-content">
<div class="wrap">
<h1>All Forms <a class="title-action" href="">Add New</a></h1>
</div>
</div>
If you do not want to change your document's current structure, I suggest you to change only the first child of the H1 node:
var h1=document.getElementById("wpbody-content").getElementsByClassName("wrap")[0].getElementsByTagName('h1')[0];
h1.firstChild.nodeValue='Candidate Application Forms';

Passing a DOM element to a javascript function

I want to run a generic javascript function with an element, sometimes multiple elements in the same HTML document. It seems to me the easiest way is to call the function from inside a DOM element. OK here's the problem. "this" refers the window element and I have seen how scope works for functions using "this" but I don't see how to get "this" to refer to an element.
I could do getElementById but I want a fairly generic javascript and not have to come up with unique IDs everytime I want to use it. getElementsByClasses may be a workaround but it just seems there should be an easier way to do this without relying on id's or classes.
The HTML
</HEAD>
<BODY>
<div id="content">
<div class="linksbox">
<a href="https://www.corponline.org" target="_blank">
<div class="linkicon">
<img src="asislink.jpg">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
<script>valignimg();</script>
</div>
</div> <!-- End content -->
</BODY>
</HTML>
The javascript. It's dh and ih that I need to pass to the function.
function valignimg() {
dh = /* div element */
ih = /* image (child element) */
topmargin = (dh.offsetHeight - ih.offsetHeight)/2;
return topmargin;
}
If you're not calling it from one of the elements (i.e. via event handler), you're going to have to use a selector of some kind, either ID or class as you highlighted, or name or tag name if that can work, or some combination. Somewhere along the way it will need to be specified. In even though you weren't keen on using class, that's likely your best option so I've highlighted it in this first example.
//warning - this event isn't supported on some older browsers like IE8
document.addEventListener("DOMContentLoaded", function(event) {
valignAll();
});
function valignimg(dh) {
//Only added the IDs for this purpose, not using them to select elements so there's no functional requirement for them.
console.log(dh.id);
//This supposes that you know the image tag you want is always the first img element among dh's children.
ih = dh.getElementsByTagName('img')[0];
console.log(ih.alt);
var topmargin = (dh.offsetHeight - ih.offsetHeight) / 2;
console.log('dh.offsetHeight = ' + dh.offsetHeight);
console.log('ih.offsetHeight = ' + ih.offsetHeight);
console.log('topmargin = ' + topmargin);
ih.style.marginTop = topmargin + "px";
console.log('ih.style.marginTop = ' + ih.style.marginTop);
}
function valignAll(){
var linkIcons = document.getElementsByClassName('linkicon');
for(i = 0;i < linkIcons.length;i++){
valignimg(linkIcons[i]);
}
}
<BODY>
<div id="content">
<div class="linksbox">
<a href="https://www.corponline.org" target="_blank">
<div id="icon1" class="linkicon">
<img alt="img1" src="http://placehold.it/20x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
<a href="https://www.corponline.org" target="_blank">
<div id="icon2" class="linkicon">
<img alt="img2" src="http://placehold.it/21x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
<a href="https://www.corponline.org" target="_blank">
<div id="icon3" class="linkicon">
<img alt="img3" src="http://placehold.it/22x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
</div>
</div>
<!-- End content -->
</BODY>
You can see, although my usage is pretty rudimentary, I've used getElementsByTagName as well, calling from a parent element other than document. The IDs I've added aren't used for locating anything, I'm just using them so that when I log to console you can see which element it really is, the same as with my horrendous misuse of the alt attribute on the images.
If you know that your only image elements on the page are the ones you're acting on, then maybe starting with document.getElementsByTagName('img') is the approach for you, and then get the div with the .parentNode property. This would remove the reliance on classes, but if you add other img tags to the page then you'd need some way to identify from each one whether it's once you want to run your align function against or not. The img tags you want to access have a common ancestor or parent that no other img tags do. I've added another snippet below that shows this. And you could combine these two approaches with a nest loop to get all img tags within multiple divs that all share a class, for example.
//warning - this event isn't supported on some older browsers like IE8
document.addEventListener("DOMContentLoaded", function(event) {
valignAll();
});
function valignimg(ih) {
//Only added the IDs for this purpose, not using them to select elements so there's no functional requirement for them.
console.log(ih.alt);
//This supposes that you know the image tag you want is always the first img element among dh's children.
dh = ih.parentNode;
console.log(dh.id);
var topmargin = (dh.offsetHeight - ih.offsetHeight) / 2;
console.log('dh.offsetHeight = ' + dh.offsetHeight);
console.log('ih.offsetHeight = ' + ih.offsetHeight);
console.log('topmargin = ' + topmargin);
ih.style.marginTop = topmargin + "px";
console.log('ih.style.marginTop = ' + ih.style.marginTop);
}
function valignAll(){
//if they're the only img tags on the page,
//document.getElementsByTagName('img'); will work fine.
//lets assume they aren't.
var images = document.getElementsByClassName('linksbox')[0].getElementsByTagName('img');
//I can grab the comment parent/ancestor by whatever means available, and then grab just its decendants by tag name.
alert(images);
for(i = 0;i < images.length;i++){
valignimg(images[i]);
}
}
<BODY>
<div id="content">
<img src="http://placehold.it/240x20"><< Some sort of header logo
<div class="linksbox">
<a href="https://www.corponline.org" target="_blank">
<div id="icon1" class="linkicon">
<img alt="img1" src="http://placehold.it/20x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
<a href="https://www.corponline.org" target="_blank">
<div id="icon2" class="linkicon">
<img alt="img2" src="http://placehold.it/21x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
<a href="https://www.corponline.org" target="_blank">
<div id="icon3" class="linkicon">
<img alt="img3" src="http://placehold.it/22x20">
</div>
</a>
<div class="linkblurb">
<h2>National</h2>
<p>Description of link</p>
</div>
</div>
</div>
Sponsor Logos or Site Certs in the footer
<img src="http://placehold.it/20x20"><img src="http://placehold.it/20x20"><img src="http://placehold.it/20x20">
<!-- End content -->
</BODY>

how to catch up a html element with same class which is under different parent using jQuery?

My markup is as follows:
<li class="item">
<div class="quickview-btn" data-pid="147" style="opacity: 0;">Quick View</div>
<a class="product-image" title="xyz" href="http://def.com/xyz"><img alt="xyz" src="http://def.com/asdf">xyz</a>
<h2 class="product-name"><a title="xyz" href="http://def.com/xyz">22" Syncmaster LCD Monitor</a></h2>
<div class="price-box">something</div>
</li>
<li class="item">
<div class="quickview-btn" data-pid="163" style="opacity: 0;">Quick View</div>
<a class="product-image" title="abc" href="http://def.com/abc"><img alt="abc" src="http://def.com/ghjk">abc</a>
<h2 class="product-name"><a title="abc" href="http://def.com/abc">Another Product</a></h2>
<div class="price-box">something</div>
</li>
I want to get the data-pid value of the second quickview-btn div on clicking the first quickview-btn div.
I used the .parent(), .next(), and .closest() methods in jQuery, but I'm not able to get it.
I tried:
$(this).parent('.item').next('.item').next('.quickview-btn').data('pid');
$(this).parent('.item').next('.item').child('.quickview-btn').data('pid');
$(this).parent('.item').next('.item').closest('.quickview-btn').data('pid');
but none of them worked for me.
$(this).parent('.item').next('.item').hide(); //this works
$('.quickview-btn').on('click',function(){
var pid = $(this).closest('.item').next('.item').find('.quickview-btn').data('pid');
})
Demo ----> http://jsfiddle.net/qSe6t/4/
Try
$('li.item').closest('.item').find('.quickview-btn').data('pid');
For direct access on load you can use this way. This is not recommended but one of the ways.
$("li:nth-child(2) .quickview-btn").data('pid');
Try the following:
$('.quickview-btn').on('click',function(){
var pid = $(this).parent().next().find('.quickview-btn').attr('data-pid');
});
You could simplify your code in addition to using the proper selectors, as follows:
$('li:first-child').find('.quickview-btn').on('click', function () {
var nextData = $(this).parent().next().children('.quickview-btn').data('pid');
console.log(nextData);
});
Demo

Categories

Resources