How to target Elements specifically in DOM - javascript

<html>
</head>
<body>
<div class="class1">
<p>text to change1</p>
<p>text to change2</p>
<p> </p>
</div>
<div class="class2">
<p>text to change1</p>
<p>text to change2</p>
<p> </p>
</div>
<button onclick="obj1.changehtml()">changehtml</button>
<script type="text/javascript">
var change= function()
{
}
change.prototype.changehtml=function()
{
// targeting specific elements positions
var paragraph=document.getElementsByClassName("class1");
paragraph[0].innerHTML="hello";
paragraph[1].innerHTML="hell1";
var addthem = paragraph[2].innerHTML = second;
}
var obj1= new change;
</script>
</body>
In the above program I am facing an error
Uncaught TypeError: Cannot set property 'innerHTML' of undefined
when trying to change the second paragraph[1].innerHTML element in first class(Class1) using property.
How do I proceed here?

in your code you were missing [0].children after getting the `.class1' elements. Also you should note this returns a NodeList of matched elements not individial elements.
If you have used jQuery before this can make you feel that this would be the native javascript functionality allowing you to chain dom methods to the NodeList but unfortunately it is not.
var change = function(){}
change.prototype.changehtml = function(){
// targeting specific elements positions
// okay selector
// var paragraphs = document.getElementsByClassName("class1")[0].children;
// okayer selector
// var paragraphs = document.getElementsByClassName('class1')[0].getElementsByTagName('p')
// better more explicit selector
var paragraphs = document.querySelectorAll('.class1 > p');
console.log( paragraphs )
paragraphs[0].innerHTML="hello";
paragraphs[1].innerHTML="hello1";
// second is not defined
var addthem = (paragraphs[2].innerHTML = second);
}
var obj1= new change;
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
<div class="class1">
<p>text to change1</p>
<p>text to change2</p>
<p> </p>
</div>
<div class="class2">
<p>text to change1</p>
<p>text to change2</p>
<p> </p>
</div>
<button onclick="obj1.changehtml()">changehtml</button>

Related

Count and display most recent blog posts in javascript

What is the javascript in order to only display posts 3 & 4 in order???
Also I need it be dynamic so if I put a 5th post it will only display 4th and 5th posts... I was thinking about something like a date function or a simple incrementor but can't seem to figure it out. I'm new to javascript and have been trying different things but no avail... Thanks in advance...
<!DOCTYPE html>
<html>
<body>
<div id="posts-div">
<h1 class="post-title">post4</h1>
<p class="post">post4</p>
</div>
<div id="posts-div">
<h1 class="post-title">post3</h1>
<p class="post">post3</p>
</div>
<div id="posts-div">
<h1 class="post-title">post2</h1>
<p class="post">post2</p>
</div>
<div id="posts-div">
<h1 class="post-title">post1</h1>
<p class="post">post1</p>
</div>
<script>
// ???
</script>
</body>
</html>
You dont need script for that. You can do it with CSS.. I have changed your html little bit (made posts-div class in html).
.posts-div{
display:none;
}
.posts-div:nth-child(-n+2) {
display:block;
}
<!DOCTYPE html>
<html>
<body>
<div class="posts-div">
<h1 class="post-title">post5</h1>
<p class="post">post5</p>
</div>
<div class="posts-div">
<h1 class="post-title">post4</h1>
<p class="post">post4</p>
</div>
<div class="posts-div">
<h1 class="post-title">post3</h1>
<p class="post">post3</p>
</div>
<div class="posts-div">
<h1 class="post-title">post2</h1>
<p class="post">post2</p>
</div>
<div class="posts-div">
<h1 class="post-title">post1</h1>
<p class="post">post1</p>
</div>
<script>
// ???
</script>
</body>
</html>
You can test it on JSfiddle as well.. https://jsfiddle.net/nimittshah/b5eL3ykx/6/
$('.posts-div:gt(1)').hide()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<body>
<div class="posts-div">
<h1 class="post-title">post4</h1>
<p class="post">post4</p>
</div>
<div class="posts-div">
<h1 class="post-title">post3</h1>
<p class="post">post3</p>
</div>
<div class="posts-div">
<h1 class="post-title">post2</h1>
<p class="post">post2</p>
</div>
<div class="posts-div">
<h1 class="post-title">post1</h1>
<p class="post">post1</p>
</div>
</body>
Try this:
<script>
document.addEventListener("DOMContentLoaded", function () {
var allPosts = document.querySelectorAll(".posts-div");
// This is the number of posts you want displayed
var numberOfPostsToShow = 2;
for (var i = 0; i < allPosts.length; i++) {
if(i > numberOfPostsToShow - 1) {
allPosts[i].style.display = "none";
}
}
});
</script>
This way you will choose how many posts you want to be shown with the numberOfPostsToShow variable.
Let me know if this worked. Regards.
The way I interpreted your question, you need a way to:
show only the first n elements;
add new elements to the top of the list of posts, dynamically;
when you add them, update the visible elements.
Assuming a slightly modified version of your code, which corrects the id/class issue and adds a container for all the posts (this time with a proper id):
<!DOCTYPE html>
<html>
<body>
<div id="posts-container">
<div class="posts-div">
<h1 class="post-title">post4</h1>
<p class="post">post4</p>
</div>
<div class="posts-div">
<h1 class="post-title">post3</h1>
<p class="post">post3</p>
</div>
<div class="posts-div">
<h1 class="post-title">post2</h1>
<p class="post">post2</p>
</div>
<div class="posts-div">
<h1 class="post-title">post1</h1>
<p class="post">post1</p>
</div>
</div>
<script>
// ???
</script>
</body>
</html>
this code will do the trick and manage both the addition and the updates to the visibility of the posts:
function showOnly(visible, query){
var elements = document.querySelectorAll(query);
for (var i = 0; i < elements.length; i++){
if (i < visible - 1){
elements[i].style.display = 'block';
} else {
elements[i].style.display = 'none';
}
}
}
function publishPost(element, visible){
showOnly(visible, '#posts-container .posts-div')
var elements = document.querySelectorAll('#posts-container .posts-div');
element.style.display = 'block';
if (elements.length > 0) {
document.querySelector('#posts-container').insertBefore(element, elements[0]);
} else {
document.querySelector('#posts-container').appendChild(element);
}
}
The showOnly function (to be called with the number of elements to be shown and the string that identifies the elements with querySelectorAll) will only make visible the first n elements identified by the string. You can use it independently of the rest of the code if needed.
The publishPost function, on the other hand, is strictly dependent on the modified html above (to use it elsewhere you will need to adjust the strings fed to querySelector and querySelectorAll). It takes the element to be published as the first argument, the number of elements that need to be visible as the second. Then it updates the list of posts prepending the new one to it, and it also updates which posts are visible.
This is a code sample that uses it:
var elDiv = document.createElement('div');
var elH1 = document.createElement('h1');
var elP = document.createElement('p');
elDiv.classList = 'posts-div';
elH1.classList = 'post-title';
elP.classList = 'post';
elH1.innerText = 'some title';
elP.innerText = 'some text for the post';
elDiv.appendChild(elH1).appendChild(elP);
publishPost(elDiv, 2);
showOnly
This function starts by getting a list of the elements whose visibility must be managed:
var elements = document.querySelectorAll(query);
then it loops through the list and examines each element:
for (var i = 0; i < elements.length; i++){
if it has to be visible, it sets the style.display property to 'block':
if (i < visible){
elements[i].style.display = 'block';
otherwise it sets it to 'hidden':
else {
elements[i].style.display = 'none';
publishPost
This function starts by showing only n-1 elements (because it will need to add a new, visible element to the top of the list):
showOnly(visible - 1, '#posts-container .posts-div')
then it retrieve the current posts:
var elements = document.querySelector('#posts-container .posts-div');
it makes the new element visible:
element.style.display = 'block';
finally, it adds the element to the top of the list (the different syntax depends on wether the list is empty):
if (elements.length > 0) {
document.querySelector('#posts-container').insertBefore(element, elements[0]);
} else {
document.querySelector('#posts-container').appendChild(element);
}

Wrap two elements in HTML with javascript

I have this code that is generated by php:
<div class="fusion-post-content post-content">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
<div class="fusion-post-content-container"></div>
</div>
I need to wrap two elements by using javascript so the code would look like this:
<div class="fusion-post-content post-content">
<div class="class">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
</div>
<div class="fusion-post-content-container"></div>
</div>
This will do what you want. Isn't it better to change the code on server-side??
// Select the first element found
var parent = document.querySelector('.fusion-post-content');
console.log('Old child-length', parent.children.length);
console.log('Old:', parent.innerHTML);
// *You don't need the timeout
setTimeout(function () {
var h2 = parent.firstElementChild;
var p = parent.firstElementChild.nextElementSibling;
// Remove cildren
parent.removeChild(h2);
parent.removeChild(p);
// Insert the new child
parent.insertAdjacentHTML('afterbegin', '<div class="class"></div>');
// Insert the other children (old) in the new child
parent.firstElementChild.insertAdjacentElement('beforeend', h2);
parent.firstElementChild.insertAdjacentElement('beforeend', p);
// Gets one less, since we put to children in one (3 - 1 = 2)
console.log('New child-length', parent.children.length);
console.log('New:', parent.innerHTML);
}, 500);
<div class="fusion-post-content post-content">
<h2 class="blog-shortcode-post-title"></h2>
<p class="fusion-single-line-meta"></p>
<div class="fusion-post-content-container"></div>
</div>

How to add a div between two divs by Javascript

I am using wordpress and I want to add some html code on page using Javascript. I don't want to make child theme then edit php files. It is risky and I don't know about php.
I want to add a sibling div. This is an example code as default.
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
Now I want to add my custom div and its inside html between both div1 and div2.
<div class="mydiv">
<div class="mydivinside">
Text
</div>
</div>
Please let me know how is it possible using Javascript.
There are (at least) two ways, the first:
// document.querySelector() finds, and returns, the first element
// matching the supplied selector (or null, if no element is found):
var el1 = document.querySelector('.div1');
// here we create an adjacent element from the string of HTML,
// the 'afterend' argument states that this adjacent element
// follows the el1 node, rather than preceding it or appearing
// within:
el1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
var div1 = document.querySelector('.div1');
div1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
And the second where you first create that <div> to be inserted, and then use parentNode.insertBefore():
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
// here we create a <div> element:
div = document.createElement('div'),
// we retrieve the element after which the new
// element should be inserted:
div1 = document.querySelector('.div1');
// assign the supplied HTML string to the innerHTML of the
// created element:
div.innerHTML = htmlString;
// and use parentNode.insertBefore to insert the desired element
// (the first argument) before the element identified in the
// second argument, which is the nextSibling of the found
// 'div1' element:
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
div = document.createElement('div'),
div1 = document.querySelector('.div1');
div.innerHTML = htmlString;
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
References:
document.createElement().
document.querySelector().
Element.insertAdjacentHTML().
Node.firstChild.
Node.insertBefore().
Node.nextSibling.
Node.parentNode.
Use Node#insertBefore method.
// create a div element
var div = document.createElement('div');
// set class name
div.className = 'mydiv';
// set html contents
div.innerHTML = ' <div class="mydivinside"> Text </div>';
// get .div2 element
var ele = document.querySelector('.div2');
// insert before the .div2 element by getting
// its parent node
ele.parentNode.insertBefore(div, ele);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
You can just use the before method to append a div between both div1 and div2. Here is the example:
$('.div2inside').before("<div class='mydiv'><div class='mydivinside'>Text</div></div>");
You could do something like this?
var firstDiv = document.getElementById('div1');
firstDiv.parentNode.insertBefore(document.getElementById('new-div'), firstDiv.nextSibling);
This however assumes that your new-div is already in the dom.
EDIT: to create a the new-div on the fly you can use #david-thomas's solution https://stackoverflow.com/a/41425079/1768337
This link will be helpfull to get the above result.
https://plainjs.com/javascript/manipulation/insert-an-element-after-or-before-another-32/

Javascript split by spaces, but not within html-tags

My first goal is to split a string by spaces, but not the ones within html-tags.
I've tried to rewrite the following, unsuccessfully: Javascript split by spaces but not those in quotes
What would the regex look like in:
arr = fullHtmlString.split(?);
?
My main goal is to shift an IMG-tag by one space at a time.
After that I'll iterate over the array, search for the img-tag, remove it, and add it the next item, and finally join the array.
The code I use at the moment is quite comprehensive and use jQuery extensively to achive the goal.
Input:
<div>
<p><img class=something>Some text.</p>
<p>Some more text.</p>
</div>
Deisred output first time:
<div>
<p>Some<img class=something> text.</p>
<p>Some more text.</p>
</div>
...second time:
<div>
<p>Some text.<img class=something></p>
<p>Some more text.</p>
</div>
...third time:
<div>
<p>Some text.</p>
<p><img class=something>Some more text.</p>
</div>
You should not try to do this with a regular expression, why explained here.
You can use DOM properties and methods though
function run(){
var img = document.querySelector(".something"),
sibling = img,
parent = img.parentNode,
next = parent.nextElementSibling;
//Search for the next textNode
while((sibling = sibling.nextSibling) && sibling.nodeType !=3);
if(sibling) {
//split the text only once,
//so "some more text" becomes ["some","more text"]
var textParts = sibling.textContent.split(/ (.*)?/,2);
//put the first split item before the sibling
parent.insertBefore(document.createTextNode(textParts[0]+" "),sibling);
//replace the sibling with the img element
parent.replaceChild(img,sibling);
//finally if there was more text insert it after the img
textParts[1] && parent.insertBefore(document.createTextNode(textParts[1]),img.nextSibling);
} else if(!sibling && next) {
//no sibling in the current parent,
//so prepend it to the next available element in parent
next.insertBefore(img,next.firstChild);
} else {
clearInterval(timer);
}
}
var timer = setInterval(run,2000);
<div>
<p><img class="something" src="http://placehold.it/10x10">Some text.</p>
<p>Some <span>skip me</span> more text.</p>
</div>

How to wrap a group of HTML tags into a containing tag using javascript?

I've run into a problem that I don't know how to solve.
I need to wrap each grouping of <h2> and <p> tags with a containing <article> tag.
My current HTML looks something like this:
<h2 category="someCategory">
<p>text text text<p>
<h2 category="anotherCategory">
<p>text text text<p>
<p>text text text<p>
I need to use javascript to make it look like this:
<article>
<h2 category="someCategory">
<p>text text text<p>
</article>
<article>
<h2 category="anotherCategory">
<p>text text text<p>
<p>text text text<p>
</article>
Somehow the javascript needs to figure out that each new <h2> tag is the start of a new article element. And then that and the last <p> tag before the next <h2> tag will be end of the article.
(The bigger picture is that I'm parsing a markdown document and need the <article> tags as css hooks for layout.)
I have no idea how to begin solving this problem, so I would be grateful of any help!!
d13
UPDATE: Thank you!! I've tried both answers and they both work perfectly!
This will also remove the old HTML tags.
var articles = [], article, sibling, toDelete = [];
var h2s = document.getElementsByTagName("H2");
for(var i = 0, h2; h2 = h2s[i++];){
article = document.createElement("article");
sibling = h2.nextElementSibling;
article.appendChild(h2.cloneNode(true));
while(sibling && sibling.tagName !== "H2"){
if(sibling.tagName === "P"){
article.appendChild(sibling.cloneNode(true));
toDelete.push(sibling);
}
sibling = sibling.nextElementSibling;
}
articles.push(article);
}
while(toDelete.length > 0){
toDelete[toDelete.length-1].parentNode.removeChild(toDelete[toDelete.length-1]);
toDelete.pop();
}
while(h2s.length > 0){
h2s[0].parentNode.removeChild(h2s[0]);
}
for(i = 0, article; article = articles[i++];){
document.body.appendChild(article);
}

Categories

Resources