jQuery .before() doesn't insert content as I defined it - javascript

I have following HTML
Html
<aside>
<section class="links"></section>
<section class="downloads"></section>
<section class="news"></section>
<section class="contact"></section>
<aside>
I'm trying to insert </aside><aside>before section.news (effectively splitting the aside container tag in 2 aside containers with 2 sections in each)
jQuery
I use:
$("aside section.news").before("</aside><aside>");
Problem
Jquery always prints <aside></aside> instead of </aside><aside> like I want.

DOM elements are not strings, you can't add elements in that way using JavaScript, DOM elements are JavaScript objects, jQuery behind the scenes calls createElement() method of the document object which creates a DOM HTMLElement object, it doesn't add strings to the document.

Here is the "proper" way of doing it:
Create an aside element
Insert it after the existing aside element
Move desired elements inside it
var $aside1 = $("aside:first");
var $aside2 = $("<aside><\/aside>").insertAfter($aside1);
$(".news").nextAll().addBack().appendTo($aside2);
Demo here

$('</aside><aside>').insertBefore('.news');
As
<aside>
<section class="links"></section>
<section class="downloads"></section>
</aside><aside>
<section class="news"></section>
<section class="contact"></section>
<aside>
Reference about .insertBefore

$(document).ready(function(){
var one = $('aside').children().eq(0).clone().wrap('<p>').parent().html() + $('aside').children().eq(1).clone().wrap('<p>').parent().html()
var two = $('aside').children().eq(2).clone().wrap('<p>').parent().html() + $('aside').children().eq(3).clone().wrap('<p>').parent().html()
$('aside').before('<aside>'+one+'</aside');
$('aside').eq(1).html(two);
console.log(one)
console.log(two)
});

Related

How to overlay a div over 2 others div with JS/Jquery

I have a couple of <div> like this:
<div>
<div id='1'></div>
<div id='2'></div>
<div id='3'></div>
</div>
How can I create dynamically another div to cover div#1 and div#2 in JS or jQuery ?
<div id='event'>EVENT</div>
Thanks.
You can use wrapAll function provided by jQuery like
$("#1, #2").wrapAll( "<div class='new' id='event'>EVENT</div>");
.new{
color : red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div>
<div id='1'>1..</div>
<div id='2'>2..</div>
<div id='3'>3..</div>
</div>
The .wrapAll() function can take any string or object that could be passed to the $() function to specify a DOM structure. This structure may be nested several levels deep, but should contain only one inmost element. The structure will be wrapped around all of the elements in the set of matched elements, as a single group.
Here for more details
I found this on Mozilla's doc page, describing the outerHTML attribute.
https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
After you get the parts of the code you want to wrap, reassign it with a <div> on the front side of 1 and a </div> on the back side of 2.
d1 = document.getElementById('1');
d2 = document.getElementById('2');
d1.outerHTML = '<div>' + d1.outerHTML;
d2.outerHTML = d2.outerHTML + '</div>';

Adding div tag below another div tag

I have a div tag with class divstudent, lets say this is div1 tag. Now I want to create another div tag div2 dynamically below this div1 tag, not inside of the div1 tag. I want to create outside of div1 tag using javascript. How can I do that?
"div1"
<div class="divstudent"></div>
<!-- i want to be like this -->
<!-- "div1" -->
<div></div>
<!-- "div2" -->
<div></div>
<!-- "div3" -->
<div></div>
$(function() {
$("div").eq(0).after("<div>This is div 2</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
This is div 1
</div>
Try something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Divs creator</title>
<script type="text/javascript">
window.onload = function () {
var divReference = document.querySelector('.divstudent');
var divCounter = 0;
divReference.addEventListener('click', function () {
var divToCreate = document.createElement('div');
divToCreate.innerHTML = ++divCounter;
divReference.parentNode.appendChild(divToCreate);
}, false);
}
</script>
</head>
<body>
<div class="divstudent">
<input type="button" value="add div below divstudent">
</div>
</body>
</html>
Since this is tagged jquery, just use .after()
$(function() {
$("div").eq(0).after("<div>This is div 2</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
This is div 1
</div>
There are many ways to do this. One significant difference in methods is if you choose to create the elements first using Document.createElement() and then insert the elements, or create and insert the elements in one step using one of the methods that allows you to insert HTML text.
Because it is simpler, but not necessarily better, the examples below show creating and inserting the two <div> elements in a single step using methods that allow inserting HTML text into the DOM.
JavaScript:
One is to use insertAdjacentHTML() and specify that it is to be inserted afterend of the element you are using.
document.querySelector() is used to find the first <div class="divstudent">. Then insertAdjacentHTML() is used to add the additional <div> elements. Element.removeAttribute() is then used to remove the class="divstudent". Note: if we had just wanted to set teh class to something different, even '', then we could have used Element.className.
NOTE: In this answer, text identifying each <div> has been added to the <div>s so there is something visible in the examples in this answer.
//Find the first <div class="divstudent"> in the document
var studentDiv = document.querySelector('div.divstudent');
//Insert two new <div> elements.
studentDiv.insertAdjacentHTML('afterend','<div>2</div><div>3</div>');
//Remove the class="divstudent"
studentDiv.removeAttribute('class');
<div class="divstudent">1</div>
jQuery:
While your question is tagged jQuery, a comment you posted implies you are just using JavaScript. Thus, I am not sure if jQuery works for you.
If you want to use jQuery, then you can use .after() to add the <div> elements. You can then use .removeAttr() to remove the class="divstudent".
// Get the first <div class="divstudent">.
// Store it in a variable so we only walk the DOM once.
var $studentDiv = $('div.divstudent').eq(0);
//Add the two new <div> elements
$studentDiv.after('<div>2</div><div>3</div>');
//Remove the class="divstudent"
$studentDiv.removeAttr('class');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="divstudent">1</div>
You create a new div (in js), then just append your newDiv, after the target div. Something along the lines of in vanilla js:
// Create your new div
var newDiv = document.createElement("div");
newDiv.innerText = "New Div!";
// Grab the div you want to insert your new div after
var target_div = document.querySelector("div.divstudent");
// Insert newDiv after target_div (before the thing after it)
target_div.parentNode.insertBefore(newDiv, target_div.nextSibling);

.scrollIntoView any element with data- tag, or using classes to section content with data- tags

Right now, I separate my content with a class called "section", not to be confused with the html tag, e.g.:
<div class="section" data-scroll-location="top">
<nav></nav>
</div><!-- .section -->
<div class="section" data-scroll-location="content">
<p></p>
</div><!-- .section -->
<div class="section" data-scroll-location="bottom">
<footer></footer>
</div><!-- .section -->
Using the above method, I can easily grab each elementsByClassName('section'), and gather the data- value; however, I am not sure how to efficiently grab a data- tag without using a class, e.g.:
<header data-scroll-location="top"></header>
<p data-scroll-location="content"></p>
<footer data-scroll-location="bottom"></footer>
I could create a loop to grab every single element, right? But, would it not be a bad thing to do performance wise, or [insert con I am not aware of]?
What method would you use for a site with maybe 3-5 scroll destinations?
EDIT:
With the answer to my question, I was able to come up with this:
function jump(destination) {
var scrollpoint = document.querySelectorAll('[data-scroll-location=' + destination + ']');
[].forEach.call(scrollpoint, function(land) {
land.scrollIntoView();
});
}
querySelectorAll really is awesome, it will help in so many projects!
Iterating over all your elements sounds innefective, yes:)
I would use document.querySelectorAll to select your data-elements. It is supported by IE8 and up. It will give you a NodeList of the matching elements. It's not actually an Array, so forEach won't work for iterating over them, unless you use it like this:
var elems = document.querySelectorAll('[data-scroll-location]');
[].forEach.call(elems,function(elem){
//Here you can do whatever with each element
elem.innerHTML = 'I changed this';
elem.style.color = 'green';
});
jsFiddle: http://jsfiddle.net/1239m1tz/

Insert Content Before and After an Element Without Autoclosing tags

Say I have the following:
<div id="content">content</div>
And I want to insert some stuff before it ** (notice the unclosed div)**:
$("#content").before("<div>pre-pre-content</div><div>pre-content ");
And some then some more after ** (notice I am now closing the div)**:
$("#content").after(" post-content</div><div>post-post-content</div>");
My desired output is:
<div>pre-pre content</div>
<div>
pre-content <div id="content">content</div> post-content
</div>
<div>post-post content</div>
Instead, what I get is:
<div>pre-pre content</div>
<div>pre-content</div>
<div id="content">content</div>
<div>post-content</div>
<div>post-post content</div>
Because jQuery is automatically "correcting" the unclosed tags.
fiddle
Is there a way to use .wrap() to add different content before and after an element without automatically closing tags?
Note, I cannot do the following because of an unrelated restriction:
$("#content").html("<div>Content before " + $("#content).html() + " Content after</div>")
You can't insert partial or unclosed tags. Inserting elements in the DOM must insert only whole elements.
Your choices are:
Extract the element you want to be wrapped in your new element, insert the new container object and then put your original element into the container.
Manipulate the HTML of a parent directly (generally not recommended).
Use the jQuery .wrap() method which does the option in #1 for you. See here for more info on jQuery's .wrap().

Insert just opening HTML tags after an element?

I would like to insert a couple of opening DIV tags after the H1 element on a page, without inserting the corresponding closing tags (since the closing tags are contained in an included footer file which I don't have access to).
i.e.
Existing code:
<body>
<h1>Heading One</h1>
... page content...
</div>
</div>
</body>
New code:
<body>
<h1>Heading One</h1>
<div id="foo">
<div id="baa">
... page content...
</div>
</div>
</body>
DOM methods insert the div as a complete (closed) element, 'createTextNode' inserts escaped characters and 'innerHTML' needs an element to insert into. Have even tried to insert a script element with document.write without any luck.
Any ideas (jQuery would be fine)?
Update
The following worked:
document.body.innerHTML = document.body.innerHTML.replace('</h1>','</h1><div id="foo"><div id="baa">')
As pointed out by Asad the solution (which now seems obvious of course) is to use string methods on the HTML rather than DOM methods.
If you're dealing with DOM manipulation, use DOM manipulation methods. If you're dealing with HTML manipulation, use string manipulation methods.
h1.parentElement.innerHTML = h1.parentElement.innerHTML.replace("<h1>Heading One</h1>","<h1>Heading One</h1><div><div>");
i think this will answer your question, it is all about valid XML formation.
http://www.w3schools.com/xml/xml_syntax.asp
Forget DOM methods, insert it as a string using .replace().
Your approach is fundamentally wrong. The browser parses the DOM as it sees it, and automatically closes any tags that ought to be closed. It's impossible to use JavaScript to insert only the opening tag.
You say "the closing tags are contained in an included footer file which I don't have access to." Closed tags that haven't been opened are ignored, so as far as the DOM parser is concerned, those closing tags don't exist.
Your solution is either:
Put the opening tags in a header, or somewhere else on the server-side, or
Use JavaScript to grab ALL the following DOM elements, including the footer, and .wrap() them all in the desired divs.
This kind of practice seems a bit unorthodox, but perhaps something like this would help.
Existing HTML
<h1 id="testH1">Test H1</h1>
<div id="existingDiv">
<div id="existingDivContent">Existing Div Content</div>
</div>
New HTML
<h1 id="testH1">Test H1</h1>
<div id="newDiv">
<div id="existingDiv">
<div id="existingDivContent">Existing Div Content</div>
</div>
</div>
JS
The javascript is fairly rudimentary, but I think the concept can be applied to safely and properly achieve your goal.
$(document).ready(function() {
//-- parent node you wish to copy
var existingDiv = $('#existingDiv');
//-- new parent div node
var newDiv = $('<div id="newDiv">');
//-- where we want to insert the new parent node
var testH1 = $('#testH1');
//-- stuff our previous parent node into our new parent node
newDiv.html(existingDiv);
//-- insert into the DOM
testH1.after(newDiv);
});
http://jsfiddle.net/8qzvN/

Categories

Resources