Diff two containers with JS or jQuery - javascript

I want to update a container with a new version without replacing it. For example:
Container1:
<div id="container-one">
<p>
<webview src="http://i.stack.imgur.com/Ed1aw.jpg"></webview>
</p>
<p>
Text
</p>
</div>
Container2:
<div id="container-two">
<p>
Cool intro
<webview src="http://i.stack.imgur.com/Ed1aw.jpg"></webview>
</p>
<p>
Long text
</p>
<p>
New Paragraph with text in it.
</p>
</div>
Container1 updated:
<div id="container-one">
<p>
Cool intro
<webview src="http://i.stack.imgur.com/Ed1aw.jpg"></webview>
</p>
<p>
Long text
</p>
<p>
New Paragraph with text in it.
</p>
</div>
A Container1.innerHTML = Container2.innerHTMLwould be simple but I don't want to reload my webview so the code should detect new divs or updated content in existing divs and apply the modifications in Container1.
UPDATE :
Container2 is a new version of container1 edited by a user, so Container2 can have anything in it: images, links, new paragraphs.
How can I do this?

I might have not understood your question correctly, but by adding an id to the text that you want to replace, and using simple javascript, you can achieve this.
HTML
<div id="container-one">
<p>
<span id="inner-one-1"></span>
<webview src="http://i.stack.imgur.com/Ed1aw.jpg"></webview>
</p>
<p>
<span id="inner-one-2">Text</span>
</p>
</div>
<div id="container-two">
<p>
<span id="inner-two-1">Cool intro</span>
<webview src="http://i.stack.imgur.com/Ed1aw.jpg"></webview>
</p>
<p>
<span id="inner-two-2">Long text</span>
</p>
</div>
<button id="click">Click Me!</button>
JS
document.getElementById("click").onclick = function() {
document.getElementById("inner-one-2").innerHTML = document.getElementById("inner-two-2").innerHTML;
document.getElementById("inner-one-1").innerHTML = document.getElementById("inner-two-1").innerHTML;
}
DEMO HERE

please try it.
var container_one = $("#container-one").children();
var container_two = $("#container-two").children();
$.each(container_one, function(index, element){
var cont_one_html = $(this).html();
var cont_two_html = $(container_two[index]).html();
if(cont_one_html != cont_two_html){
$(this).html(cont_two_html);
}
});
please have a look on image for more understanding.

you need to get the text node and replace the content, like
$('button').on('click', function () {
// this block is for not to update the webview
// get the first text node
var txt = $('#container-one > p:first').contents().first().get(0);
if (txt.nodeType === 3) { // Node.TEXT_NODE
txt.nodeValue = $('#container-two > p:first').text();
}
// update rest of the elements
$('#container-two').children().each(function (i) {
if (i !== 0 && $('#container-one').children()[i]) {
$($('#container-one').children()[i]).html($(this).html());
}
if (!$('#container-one').children()[i]) {
$('#container-one').append($(this).clone());
}
});
});
DEMO

Have a try and see if this works for you.
var first = $('container-one p:first');
first.html($('container-two p:first').html() + first.html());
$('container-one p:last').html($('container-two p:last').html());

Use this:
function update(s){
document.getElementById("container-one").innerHTML=s.innerHTML;
}
setInterval(function(){
update(document.getElementById("container-two"));
},1000);
What this does is it updates the content once every second.
To show that it can handle dynamic content, I have made the second div editable.
Demo:http://jsfiddle.net/5RLV2/2

Related

Call previous sibling as function parameter?

I'm building a wee letter-writing tool that will have a range of paragraphs the user can choose to add to a letter, but I worry that I'm doing it in a really inefficient way.
Currently, it's structured like this:
<p id="deposit-dispute" class="paragraph">This is a paragraph about deposits not being protected</p>
<button onclick="addPara(depositDispute)" class="add">Add paragraph</button>
and then in the Javascript, I create a const that pulls the inner HTML of that id:
const depositDispute = "\n" + document.getElementById("deposit-dispute").innerHTML + "\n";
which the addPara() function then adds to the textarea:
function addPara(text) {
document.getElementById("text-body").value += text;
}
But would there be a way to make the function just call whatever the previous p element had in it, rather than having to give them all unique IDs and creating a unique variable for them all?
Here it is in a codepen so you can see what I'm trying to do - the paragraphs to be added are in the accordion on the right: https://codepen.io/gordonmaloney/pen/GRWyjOP
Thanks a lot - and big apologies if this is a ridiculously amateurish question, I've spent ages trying to google a solution but can't find a thing!
G
Each box contains a paragraph and a button.
We can get all the boxes and each box paragraph and button, and finally add click event to the button to insert the paragraph html of this box to the textarea
// Get textarea and boxes
var textarea = document.getElementById('textarea');
var boxes = document.querySelectorAll('.box');
// get the button and the paragraph of each box
boxes.forEach(box => {
var btn = box.querySelector('.button');
var paragraph = box.querySelector('.paragraph');
// add the html of the selected box paragraph to the textarea
btn.addEventListener('click', () => {
textarea.value += "\n" + paragraph.innerHTML; + "\n";
});
});
<div class="wrapper">
<div class="box">
<p class="paragraph">This is paragraph 1</p>
<button class="button">Add to textarea</button>
</div>
<div class="box">
<p class="paragraph">This is paragraph 2</p>
<button class="button">Add to textarea</button>
</div>
<div class="box">
<p class="paragraph">This is paragraph 3</p>
<button class="button">Add to textarea</button>
</div>
</div>
<textarea name="" id="textarea" cols="30" rows="10"></textarea>

Swapping text of parent and child elements

I have the following elements:
<div contenteditable="true" id="write">
<div class="tooltip">
<span>test</span> <!--text to be written in text area-->
<span class="tooltiptext"> <!--holds words to be displayed on hover-->
<span class="popUpWord">hello</span>
<br>
<span class="popUpWord">dog</span>
</span>
</div>
<div class="tooltip">
<span>test</span>
<span class="tooltiptext">
<span class="popUpWord">hello</span>
<br>
<span class="popUpWord">test</span>
</span>
</div>
</div>
These basically show a pop-up similar to the following - http://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip
On hover event of elements having the '.tooltop' class (words to be displayed inside the pop-up area), I would like to swap the word which is hovered in the pop-up area, with the word displayed in the text area after a couple of seconds.
I did the following function:
//--choosing word from pop-up list--//
$(document).on("mouseover", ".popUpWord", function(e)
{
if(!timeoutId)
{
timeoutId=window.setTimeout(function()
{
timeoutId=null;
e.currentTarget.innerHTML = e.fromElement.parentElement.parentElement.childNodes[0].childNodes[0].innerText;
/*not working*/ e.fromElement.parentElement.parentElement.childNodes[0].childNodes[0].innerHTML = e.currentTarget.innerHTML; //Although the elements I want to swap are referred to correctly,the element's text is not changing. (Tried using innerText)
},1500);
}
}).on('mouseout', '.popUpWord', function(e)
{
if(timeoutId)
{
window.clearTimeout(timeoutId);
timeoutId=null;
}
});
However, in the line marked not working - the element's text is not changing. And it is being referred to correctly.
Any help is greatly appreciated.
Thanks
Its because you are assigning the value of tooltip to the text element and re-assigning it to the tooltip.
Try this:
timeoutId=null;
var text = e.currentTarget.innerHTML;
e.currentTarget.innerHTML = e.fromElement.parentElement.parentElement.childNodes[0].childNodes[0].innerText;
e.fromElement.parentElement.parentElement.childNodes[0].childNodes[0].innerHTML = text;
You are trying to locate the source and destination elements in a way that can only lead to brittleness and errors. Give elements you know you want to work with ids and reference them that way.
Try this out. Hover over "helo".
var orig = $("orig");
var hold = $("hold");
var timeoutId = null;
$(".popUpWord").on("mouseover", function(e){
if(!timeoutId) {
timeoutId = setTimeout(function() {
e.target.innerHTML = original.textContent;
original.innerHTML = e.target.innerHTML;
},1500);
}
}).on('mouseout', function(e){
if(timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" id="write">
<div class="tooltip">
<span id="original">test</span> <!--text to be written in text area-->
<span class="tooltiptext"> <!--holds words to be displayed on hover-->
<span id="hold" class="popUpWord">hello</span>
<br>
<span class="popUpWord">dog</span>
</span>
</div>
<div class="tooltip">
<span>test</span>
<span class="tooltiptext">
<span class="popUpWord">hello</span>
<br>
<span class="popUpWord">test</span>
</span>
</div>
</div>
You will need to store the new text strings in a variable. Otherwise you are just setting it right back:
timeoutId=window.setTimeout(function()
{
var child = e.currentTarget,
parent = e.fromElement.parentElement.parentElement.childNodes[0].childNodes[0],
childtext = child.innerText,
parenttext = parent.innerText
child.innerHTML = parenttext;
parent.innerHTML = childtext;
},1500);

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);
}

Javascripts to remove text from HTML

I need a script to remove a line of text "Quantity in Stock:(Out of Stock)" from my product pages. The specific HTML code I'm trying to remove is:
<span class="PageText_L329n"><strong class="prod_qty_label">
Quantity in Stock
</strong></span>
:
<span style="color:#cc0000;"><span class="StockQuantity_OutOfStock"></span></span><br></br>
I only have limited knowledge of Javascript, and I know I need to start with something like this:
document.body.innerHTML = document.body.innerHTML.replace('', '');
But I'm struggling to make it work with having all the HTML markups in the javascript.
On my category pages (different page), I am trying to remove this text from the HTML, which may appear multiple times in the page:
<b><font color="#CC0000">
<span class="PageText_L331n">(Out of Stock)</span>
</font></b>
Any help is appreciated.
Thanks.
Like this example?
<div>
<span class="PageText_L328n"><strong class="prod_qty_label">
Quantity in Stock 1
</strong></span>
</div>
<div>
<span class="PageText_L329n"><strong class="prod_qty_label">
Quantity in Stock 2
</strong></span>
</div>
<div>
<span class="PageText_L330n"><strong class="prod_qty_label">
Quantity in Stock 3
</strong></span>
</div>
<button id="button">Remove</button>
var button = document.getElementById("button");
var PageText_L329n = document.getElementsByClassName("PageText_L329n");
function remove() {
if (PageText_L329n[0]) {
PageText_L329n[0].parentNode.removeChild(PageText_L329n[0]);
}
}
button.addEventListener("click", remove, false);
on jsfiddle
Also, maybe it is enough just to hide it rather than remove it from the DOM.
And for clearing text
<b><font color="#CC0000">
<span class="PageText_L331n">(Out of Stock)</span>
</font></b>
<button id="clear">Clear</button>
var button = document.getElementById("clear");
function clearText() {
document.getElementsByClassName("PageText_L331n")[0].textContent = "";
}
button.addEventListener("click", clearText, false);
on jsfiddle

How to show "back to top" button using jquery only if browser height is shorter than page?

How to add/show "back to top" button at bottom in a div using jquery only if height browser height is shorter than page, other wise it should be hidden?
<p>Back to top</p>
to this
<div id="mainwrapper">
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
<p>Back to top</p>
</div>
i need almost same like my this question but condition is different How to detect linked PDF on a page and show message to download Adobe reader using jquery?
I need lightweight simple solution
Something like:
var wrapper = $('#mainwrapper');
if (wrapper.outerHeight(true) > $(window).height()) {
wrapper.append('<p>Back to top</p>');
}
Do something like this:
$(document).ready(function(){
showHideControl();
$(window).resize(function(){
showHideControl();
});
});
function showHideControl() {
var h = $(window).height();
var ch = $("#content").height();
if (ch < h) {
$("#backControl").hide();
}
else {
$("#backControl").show();
}
}
The html needs to be updated a little too:
<div id="mainwrapper">
<div id="content">
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
<p> Paragraph 1 </p>
</div>
<p id="backControl">Back to top</p>
</div>

Categories

Resources