How can I dynamically wrap elements in a div within another div? - javascript

I have the following output of WordPress content:
link1
text1
<br>
<br>
link2
text2
<br>
<br>
link3
text
<br>
<br>
link4
text4
<br>
<br>
I DO NOT have access to edit the content so I'm looking to edit this via jQuery. I need to wrap each link with the text and br before next link in a div and then split it in two columns. So the final result would be something like this:
<div class="col-left">
<div class="item">
link1
text1
<br>
<br>
</div>
<div class="item">
link2
text2
<br>
<br>
</div>
</div>
<div class="col-right">
<div class="item">
link3
text3
<br>
<br>
</div>
<div class="item">
link4
text4
<br>
<br>
</div>
</div>
Any idea how can I achieve this using jQuery?
I have tried using .wrap() like this:
$('a').wrap( "<div class='item'></div>" );

That's a pretty fun challenge.
A quick explanation...
jQuery appears to struggle when getting text elements which aren't wrapped in any tag, so we must fist wrap them. I've used a <span>. I've used the code from this post to do that.
Now that they're all wrapped up nicely, we can select the elements we're interested in, and find the halfway point. If we have an odd number, let's call Math.ceil, so that the extra one ends up in the Left column.
var a = $('a');
var i = Math.ceil(a.length/2);
Now let's just get the first column and second column elements by calling $.slice.
var firstColEls = a.slice(0,i);
var secondColEls = a.slice(i);
We can now loop through the elements and add the <div> with the item class. I'm using itemC1 and itemC2 so we can quickly select all the grouped elements later on. The class can have the same styling.
$.each(firstColEls, function(idx,el){
$(el).nextUntil('a').addBack().wrapAll('<div class="itemC1"></div>');
});
$.each(secondColEls, function(idx,el){
$(el).nextUntil('a').addBack().wrapAll('<div class="itemC2"></div>');
});
Now let's select the items, and wrap all of them (together) in the left/right column divs!
$('.itemC1').wrapAll('<div class="l"></div>');
$('.itemC2').wrapAll('<div class="r"></div>';
Wasn't that fun? :). Working Fiddle.

Have you tried setting a variable like so:
if (check how many links) {
var wrapLinkLeft = $('<div class="col-left"><div class="item">link1<br><br></div></div>');
var wrapLinkRight = $('<div class="col-right"><div class="item">link2<br><br></div></div>');
$(wrapLinkLeft).appendTo('body'); //for example append it to the body
}
to make the link dynamic leave it empty and just append it to the href, which means you will probably need to set a class or ID for this href or build a counter to keep track of where the scripts at.

This is the closest I could get. It gives the desired outcome, but I'm not sure that it's terribly flexible.
var textNodes = $('a').first().parent().contents().filter(function() {
return this.nodeType === 3 && $(this).text() !== "\n";
});
$(textNodes).each(function() {
$(this).wrap('<span></span>');
});
var groups = $('a');
$(groups).each(function(index, item) {
$(item).before('<div class="item"></div>');
var theDiv = $(item).prev();
var theItem = $(item).detach();
var theRest = theDiv.nextUntil('a').detach();
theDiv.append(theItem);
theDiv.append(theRest);
theDiv.find('span').contents().unwrap();
});
var theDivs = $('.item');
var half = theDivs.length / 2;
$(theDivs).first().before('<div class="col-left"></div><div class="col-right"></div>');
var i;
for (i = 0; i < half; i++)
{
var nextDiv = $(theDivs[i]).detach();
$('.col-left').append(nextDiv);
}
for (; i < theDivs.length; i++)
{
var nextDiv = $(theDivs[i]).detach();
$('.col-right').append(nextDiv);
}
And here's the JSFiddle. Cheers.

Related

How to edit html element with Javascript dom?

i try to edit the span element inside with javascript dom:
<div class="data">
<span>Jan. 16, 2019</span>
</div>
So that only last 4 characters are shown,
var list = document.getElementById("data");
list.removeChild(list.childNodes[3]);
But it doesnot work
One error: you're searching with getElementById for an element with id data but data is the class.
<div id="data"> should make the list assignment work. Or use document.querySelector('.data')
The next line with removeChild makes no sense to me, at least with given HTML.
In order to only keep the last four characters in the span:
var list = document.getElementsByClassName("data")[0];
let str = list.childNodes[1].textContent;
list.childNodes[1].textContent = str.substring(str.length-4, str.length);
<div class="data">
<span>Jan. 16, 2019</span>
</div>
Two things are going wrong. You are looking for an ID, but the HTML does not have an ID. Also showing the last 4 characters is not going alright.
I would propose to add an id to the span:
<div class="data">
<span id="date">Jan. 16, 2019</span>
</div>
var span = document.getElementById("date");
var date = span.textContent;
span.textContent = date.substr(date.length - 4);

how to remove the lastchild element of dynamically generated DIV and return the html as string

How to remove the lastchild of the dynamically generated div and regenerate the html as string.
Sample HTML DIV
strHtmlString = "<div contenteditable='true' id='undefined'>Test1</div>
<div contenteditable='true' id='sentenceFreeTextField67' type='sentenceFreeTextField'>One</div>
<div id='multiselectAnchors' type='multi'>
<div id='options32' >Two</div>
<div contenteditable='true' id='sentenceFreeTextField68' type='sentenceFreeTextField'>One</div>
</div>
<div id='blank4' contenteditable='true' type='blankField'> </div>
<div id='Div1' type='multi'>
<div id='options33' >Three</div>
<div contenteditable='true' id='sentenceFreeTextField69' type='sentenceFreeTextField'>One</div>
</div>"
here is the code sample
if (($('<DIV/>').html(strSentence)[0].lastChild.lastChild.type === 'sentenceFreeTextField') && (!$.trim($('<DIV/>').html(strSentence)[0].lastChild.lastChild.innerText))) {
strHtmlString = $('<DIV/>').html(strSentence)[0].lastChild.lastChild.remove().html; (this remove().html doesn't work)
}
the need is to delete the lastchild of the div at runtime and convert back to string as it was earlier. I can do string manipulation however, might not the be the right way, please suggest
var el = $(strHtmlString);
// dont know what you meant by last child, so taking the id
el.children().find("#sentenceFreeTextField69").remove();
var str = el.wrap("<div/>").parent().html()
Generate a DIV dynamically:
$('body').append('<div>');
Access the DIV immediately after generation:
var $divElement = $('body').append('<div>').find('div');
Get the last child:
var $lastChildElement = $divElement.last();
Get the HTML of the last child (more specifically, the innerHTML):
var $lastChildHTML = $lastChildElement.html();
Do it all together then you turn around:
var $lastChildHTML = $('body').append('<div>').find('div').last().html();
That's what it's all about.
var last = $(element).children(':last-child');
var html = $(last).html();
$(last).remove();
var newHtml = $(element).html();
//incase you want the html with it's parent as well do this
var newHtml = $(element).parent().html();

Remove span - tags and keep the content in an <td> parent tag

i have for example this:
<td "class=name">
<span class="removed">one</span>
<span class="added">two</span>
</td>
or this:
<td class=name> one
<span class="removed">two</span>
<span class="added">three</span>
</td>
or this:
<div>
one
<span class="added">two</span>
three four
<span class="removed">five</span>
six
</div>
and want to change it with JavaScript (without JQuery) to this:
<td "class=name">
two
</td>
or this:
<td class=name>
one
three
</td>
or this:
<div>
one
two
three
four
six
</div>
can't figure it out. and only found a lot of jquery stuff like replaceWith and so on, but need pure javascript for it
Here is the best and easiest method that only requires one line of code and uses jQuery:
$('.added').contents().unwrap();
Breakdown:
$('.added') = Selects the element with the added class.
.contents() = Grabs the text inside the selected element.
.unwrap() = Unwraps the text removing the <span> and </span> tags while keeping the content in the exact same location.
If all the span tags you have that you want removing have a class of removed or added and testing them using the class doesn't affect any of your other html you could try this.
var spans = document.getElementsByTagName("span");
for(var i=0; i<spans.length;i++)
{
if(spans[i].className == "added")
{
var container = spans[i].parentNode;
var text = spans[i].innerHTML;
container.innerHTML += text;
container.removeChild(spans[i]);
}
else if(spans[i].className == "removed")
{
var container = spans[i].parentNode;
container.removeChild(spans[i]);
}
}
Otherwise you need to find a way by ID or class name perhaps to grab the container of the span tags and do something similar. For instance like this
var myDiv = document.getElementById("myDiv");
var spans = myDiv.getElementsByTagName("span");
for(var i=0; i<spans.length;i++)
{
if(spans[i].className == "added")
{
var text = spans[i].innerHTML;
}
myDiv.innerHTML += text;
myDiv.removeChild(spans[i]);
}
Hope this helps
EDIT
Try here for an idea of how to implement this code using a getElementsByClassName() function which might simplify this. It returns an array like getElementsByTagName() does which you can iterate over.
You can remove any html class with the following code:
<div id="target_div">one<span class="added">two</span>three four<span class="removed">five</span>six</div>
<script type="text/javascript">
function remove_html_tag(tag,target_div){
var content=document.getElementById(target_div).innerHTML;
var foundat=content.indexOf("<"+tag,foundat);
while (foundat>-1){
f2=content.indexOf(">",foundat);
if (f2>-1) {content=content.substr(0,foundat)+content.substr(f2+1,content.length);}
f2=content.indexOf("</"+tag+">",foundat);
if (f2>-1){content=content.substr(0,f2)+content.substr(f2+3+tag.length,content.length);}
foundat=content.indexOf("<"+tag,foundat);
}document.getElementById(target_div).innerHTML=content;}
</script>
Remove span tag

jQuery find and replace string

I have somewhere on website a specific text, let's say "lollypops", and I want to replace all the occurrences of this string with "marshmellows". The problem is that I don't know where exactly the text is. I know I could do something like:
$(body).html($(body).html().replace('lollypops', 'marshmellows'));
This would probably work, but I need to rewrite as little HTML as I can, so I'm thinking something like:
search for the string
find the closest parent element
rewrite only the closest parent element
replace this even in attributes, but not all, for example replace it in class, but not in src
In example, I would have structure like this
<body>
<div>
<div>
<p>
<h1>
<a>lollypops</a>
</h1>
</p>
<span>lollypops</span>
</div>
</div>
<p>
<span class="lollypops">Hello, World!</span>
<img src="/lollypops.jpg" alt="Cool image" />
</p>
<body>
In this example, every occurrence of "lollypops" would be replaced, only <img src="... would remain the same and the only elements that would actually be manipulated would be <a> and both <span>s.
Does anybody know how to do this?
You could do something like this:
$("span, p").each(function() {
var text = $(this).text();
text = text.replace("lollypops", "marshmellows");
$(this).text(text);
});
It will be better to mark all tags with text that needs to be examined with a suitable class name.
Also, this may have performance issues. jQuery or javascript in general aren't really suitable for this kind of operations. You are better off doing it server side.
You could do something this way:
$(document.body).find('*').each(function() {
if($(this).hasClass('lollypops')){ //class replacing..many ways to do this :)
$(this).removeClass('lollypops');
$(this).addClass('marshmellows');
}
var tmp = $(this).children().remove(); //removing and saving children to a tmp obj
var text = $(this).text(); //getting just current node text
text = text.replace(/lollypops/g, "marshmellows"); //replacing every lollypops occurence with marshmellows
$(this).text(text); //setting text
$(this).append(tmp); //re-append 'foundlings'
});
example: http://jsfiddle.net/steweb/MhQZD/
You could do something like this:
HTML
<div class="element">
<span>Hi, I am Murtaza</span>
</div>
jQuery
$(".element span").text(function(index, text) {
return text.replace('am', 'am not');
});
Below is the code I used to replace some text, with colored text. It's simple, took the text and replace it within an HTML tag. It works for each words in that class tags.
$('.hightlight').each(function(){
//highlight_words('going', this);
var high = 'going';
high = high.replace(/\W/g, '');
var str = high.split(" ");
var text = $(this).text();
text = text.replace(str, "<span style='color: blue'>"+str+"</span>");
$(this).html(text);
});
var string ='my string'
var new_string = string.replace('string','new string');
alert(string);
alert(new_string);
Why you just don't add a class to the string container and then replace the inner text ? Just like in this example.
HTML:
<div>
<div>
<p>
<h1>
<a class="swapText">lollipops</a>
</h1>
</p>
<span class="swapText">lollipops</span>
</div>
</div>
<p>
<span class="lollipops">Hello, World!</span>
<img src="/lollipops.jpg" alt="Cool image" />
</p>
jQuery:
$(document).ready(function() {
$('.swapText').text("marshmallows");
});

Replace node with innerhtml

With JavaScript I want to remove a specific DOM node and replace it with the innerHTML. For example I want to change
<div>
...
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
...
</div>
To
<div>
...
this is <b> the text </b> I want to remain.
...
</div>
Try this:
var oldElem = document.getElementById('t1');
oldElem.innerHTML = 'this is <b> the text </b> I want to remain.';
var parentElem = oldElem.parentNode;
var innerElem;
while (innerElem = oldElem.firstChild)
{
// insert all our children before ourselves.
parentElem.insertBefore(innerElem, oldElem);
}
parentElem.removeChild(oldElem);
There is a demo here.
This is effectively the same thing as .replaceWith() from jQuery:
$("#t1").replaceWith('this is <b> the text </b> I want to remain.');
var t1 = document.getElementById("t1");
t1.outerHTML = "this is <b> the text </b> I want to remain.";
http://youmightnotneedjquery.com/#replace_from_html
If you are using jQuery, you can try
var inner = j$("#t1").html()
$('#t1').replaceWith(inner);
This works:
var t1 = document.getElementById("t1");
t1.parentNode.innerHTML = t1.innerHTML;
Edit:
Please note that if the parent of t1 has any other children, the above will remove all those children too. The following fixes this problem:
var t1 = document.getElementById("t1");
var children = t1.childNodes;
for (var i = 0; i < children.length; i++) {
t1.parentNode.insertBefore(children[i].cloneNode(true), t1);
}
t1.parentNode.removeChild(t1);
It's very easy actually:
let span = document.getElementById('id');
span.outerHTML = span.innerHTML;
I just modified the HTML Like this.
<div>
<div id="t0">
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
</div>
</div>
And you do something like
document.getElementById("t0").innerHTML = "this is <b> the text </b> I want to remain.";
Hope it works
you might want to consider using jquery if that's possible.
it would make your life way way wayyyyyyyy easier.
once you have jquery, you can easily do this via
$("#t1").html("this is <b> the text </b> I want to remain.");
and if you find it a hassle to learn, you can always start by learning the jquery selectors.
you wouldn't know why you haven't been using it all this while :)
sorry if this is not what you want exactly..
~jquery addict
Updated:
To show what html text to put inside.
This is similar to the other answers but more functional.
go.onclick = () => {
[...t1.childNodes].forEach(e => {
t1.parentElement.insertBefore(e, t1);
});
t1.remove();
go.disabled = true;
}
#t1 {
color: red;
}
<div>
<div>BEFORE</div>
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
<div>AFTER</div>
<button id="go">GO</button>
</div>

Categories

Resources