Copy and inserting HTML elements into new pop-up block - javascript

I want to completely copy all elements
<div id="articleFull"> ... </div>
(+ div inclusive) with their content in a new pop-up window
<div id="newPopUp"> ... </div>
<div id="articleFull">
<p>lorem ipsum</p>
<img src="1.png" />
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<h3>Test title</h3>
<img src="1.png" />
<p>lorem ipsum</p>
</div>
I tried to do this simple method:
http://jsfiddle.net/ApBSN/3/
articleFull = document.getElementById('articleFull');
function copyHtml(){
div = document.createElement('div')
div.id = 'newPopUp';
document.body.appendChild(div);
var t = document.getElementById('articleFull');
div.appendChild(t);
}
It works... BUT the function does not copy the code, and moves it from one place to another, effectively removing it from its original location. I just want to duplicate the block. Yes, I understand that the page can not be 2 "ID", but with this, I'll take care of myself more.
Ideas?

you can try Clone if interested in Jquery...http://api.jquery.com/clone/ this will duplicate the html rather then replacing it as in case of append
i have updated your http://jsfiddle.net/ApBSN/9/ but now you need to work on css
var t1 = document.getElementById('newPopUp');
var t = document.getElementById('articleFull');
$(t).clone().appendTo(t1);

If I understood correctly this should do it:
function copyHtml(){
div = document.createElement('div')
div.id = 'newPopUp';
document.body.appendChild(div);
var t = document.getElementById('articleFull');
t.id = "articleFull2";
div.appendChild(t);
}

Related

ES6 - Parse HTML string to Array

I have an HTML formatted string:
let dataString = '<p>Lorem ipsum</p> <figure><img src="" alt=""></figure> <p>Lorem ipsum 2</p> <figure><img src="" alt=""></figure>';
How can I parse this string to get an array of tags as below?
let dataArray = [
'<p>Lorem ipsum</p>',
'<figure><img src="" alt=""></figure>',
'<p>Lorem ipsum 2</p>',
'<figure><img src="" alt=""></figure>',
];
Turn it into a document with DOMParser, then take the children of the body and .map their .outerHTML:
const str = '<p>Lorem ipsum</p> <figure><img src="" alt=""></figure> <p>Lorem ipsum 2</p> <figure><img src="" alt=""></figure>';
const doc = new DOMParser().parseFromString(str, 'text/html');
const arr = [...doc.body.children].map(child => child.outerHTML);
console.log(arr);
(you can also achieve this by creating an element and setting the innerHTML of the element to the string, and then iterating over its children, but that could allow for arbitrary code execution, if the input string isn't trustworthy)
Dom parsing is recommended.
Here using vanilla JS without the DOMParser used in the other answer
let dataString = `<p>Lorem ipsum</p> <figure><img src="" alt=""></figure> <p>Lorem ipsum 2</p> <figure><img src="" alt=""></figure>`;
let domFragment = document.createElement("div");
domFragment.innerHTML = dataString;
const arr = [...domFragment.querySelectorAll("div>p,div>figure")].map(el => el.outerHTML)
console.log(arr)
If you cannot use that, then your SPECIFIC string can be split like this after fixing your nested quotes.
Note any change for example adding a space after the <img..> will break such a script
let dataString = `<p>Lorem ipsum</p> <figure><img src="" alt=""></figure> <p>Lorem ipsum 2</p> <figure><img src="" alt=""></figure>`;
dataString = dataString.replace(/> /g,">|").split("|")
console.log(dataString)
I am not clear with your question. Is that a random string or a html string? The split rule is slice the origin string into html element parts?
If true, I think we can handle it with a dummy element.
For convenient, I use jQuery selector:
let stringToSplit = `<p>Lorem ipsum</p> <figure><img src="" alt=""></figure> <p>Lorem ipsum 2</p> <figure><img src="" alt=""></figure>`
$dummy = $("<div/>"); // create a dummy
$dummy.html(stringToSplit);
var dataArray = [];
var dummyChildren = $dummy.children();
for (var i = 0; i < dummyChildren.length; i++) {
dataArray[i] = dummyChildren[i].outerHTML
}
$dummy = null; // remove from memory
console.log(dataArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

CKEditor get range to insert HTML at custom location

I am working on a module CKEditor Responsive Plugin for Drupal 7. I would need to insert a piece of HTML at a custom location above the cursor position. Below is the image which shows current cursor position:
The HTML of above part of the code looks like this:
<div class="ckeditor-col-container">
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
</div>
<p><br />
Sri Ramakrishna Vidya Kendra
</p>
<p></p>
The three div's which you see is the location which I now want to insert - that means I need to append my new set of div's below the last child div of the div with class ckeditor-col-container
I have gone through this SO link which talks about inserting HTML in given range: Insert HTML before an element in CKEditor
However, following are the challenges which I was not able to solve:
Traverse through the DOM above current cursor location to prepare the range with respect to the nearest div with class ckeditor-col-container
Get to the end of this (ckeditor-col-container) DOM and prepare range so that the new HTML elements would be inserted inside the scope of ckeditor-col-container
The DOM structure above cursor can be nested, but I am interested to find the nearest div with class ckeditor-col-container irrespective of the complicated nested DOM structures.
This is relatively easy to achive using jQuery object and traversing through DOM but CKEditor is cryptic with comparatively very less literature. Also point 3 in the above is tricky as a hierarchical datastructure has to be read in a flat fashion.
Any help would be appreciated.
Edit:
The example HTML piece of code which I want to insert is the same div's which you can find above:
lorem ipsum
And the final HTML will be like this:
<div class="ckeditor-col-container">
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
.
.
.
<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">
<div class="grid-12 twelvecol">
<p>lorem ipsum</p>
</div>
</div>
.
.
.
</div>
<p><br />
Sri Ramakrishna Vidya Kendra
</p>
<p></p>
The new 'inserted' div is the one which is displayed between the dots. I did not find a way to highlight the code when it is code-formatted.
The code doesn't do a complete traversing, but I think it can give you a pretty good place to start with.
The general idea is to take the current position of the cursor and start to check if any of the siblings (up and down the DOM tree) is the element we are looking for.
CKEDITOR.plugins.add( 'samplePlugin', {
icons: 'samplePluginIcon',
init: function( editor ) {
editor.addCommand( 'samplePlugin', {
exec: function( editor ) {
// First we need to find where our cursor is
var selection = editor.getSelection();
var range = selection.getRanges()[0];
// We go up and down the DOM tree, so we need the prev and next elements
var prevNode = range.getPreviousNode();
var nextNode = range.getNextNode();
// Save the container we are looking for
var container = null;
while (prevNode || nextNode) {
while (prevNode && prevNode.type == CKEDITOR.NODE_TEXT) {
prevNode = prevNode.getPreviousSourceNode();
}
if (prevNode && prevNode.hasClass('ckeditor-col-container')) {
container = prevNode;
break;
} else if (prevNode) {
prevNode = prevNode.getPreviousSourceNode();
}
while (nextNode && nextNode.type == CKEDITOR.NODE_TEXT) {
nextNode = nextNode.getNextSourceNode();
}
if (nextNode && nextNode.hasClass('ckeditor-col-container')) {
container = nextNode;
break;
} else if (nextNode) {
nextNode = nextNode.getNextSourceNode();
}
}
// In case we found the container we are looking for - just append some HTML to it.
if (container) {
container.appendHtml('<div class="hundred-hundred-fifty-fifty-thirtythree-thirtythree">'+
'<div class="grid-12 twelvecol">'+
'<p>lorem ipsum</p>'+
'</div>'+
'</div>')
}
}
});
editor.ui.addButton( 'samplePlugin', {
label: 'samplePlugin',
command: 'samplePlugin',
toolbar: 'insert'
});
}
});

How can I Target parent and child class I javascript

<div id="inst4" class="block_navigation block">
<div class="content">
<div> Content Start here !!!</div>
</div>
</div>
<script>
var blockNav = document.getElementsByClassName("block_navigation")[0].getElementsByClassName("content");
blockNavIcon = document.createElement("img");
blockNavIcon.setAttribute("src", blockIcon);
blockNav.appendChild(blockNavIcon);
}
</script>
Here I am targeting content class, but it is not working, How can i do this any solution.
There are few problems in your script, you are using the class block_navigation twice, also blockNav is a NodeList
You can easily use .querySelector()
var blockNav = document.querySelector(".block_navigation .content");
blockNavIcon = document.createElement("img");
blockNavIcon.setAttribute("src", '//placehold.it/64');
blockNav.appendChild(blockNavIcon);
<div id="inst4" class="block_navigation block">
<div class="content">
<div>Content Start here !!!</div>
</div>
</div>
You can use use .getElementsByClassName("content")[0]
Hope this wil be helpful
var blockIcon = "http://weknowyourdreams.com/images/forest/forest-04.jpg";
var blockNav = document.getElementsByClassName("block_navigation")[0]
.getElementsByClassName("content")[0]; // Will select the child element
blockNavIcon = document.createElement("img");
blockNavIcon.setAttribute("src", blockIcon);
blockNav.appendChild(blockNavIcon)
JSFIDDLE

How to get all elements but div (for example), including nested ones?

This is probably a long shot but is there a way to get a collection of elements in JQuery or not without a specific tag/class/id, even the nested ones?
Let's say I have this piece of code:
<div class="container1">
Lorem ipsum dolor sit amet
<br><br>
</div>
<p>This is p 1
<div class="footer">
tessssst
<p>
p test
</p>
</div>
</p>
<div class="container">
tessst
</div>
<p>This is p 2
<div id="someID" class="container">
tessssst 2
</div>
</p>
Now, I'm using JQuery like this, in order to find all but div tags, including descendants:
$('body').find(':not(div, div *)')
In the result collection, I still get the div inside the p elements and I don't want that.
Is there any way to achieve that? I know that this div is part of h1 and since I just want to select elements and not removing or doing DOM manipulations it could be a weird thing to wish for but this is what I need.
The bigger problem - I need to retrieve all text nodes but to exclude some tags/classes/IDs. I'm doing so as suggested here but it's not good enough.
Thanks.
The code you provided seems to work, but maybe you could try this?
$('body').find("*").filter(":not(div)");
There is a jQuery function not(), which removes matching elements from the current set.
So all you need to do is
var nonDivs = $('body').find('*').not('div');
You can do that by first selecting all elements, then selecting <div>s and their descendants, and filtering the "all" results with the "divs" result using .not() (the red style is used to mark the matched set):
var all = $('body').find('*');
var divAll = $('body').find('div, div *');
var nonDiv = all.not(divAll);
nonDiv.css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container1">
Lorem ipsum dolor sit amet
<br><br>
</div>
<p>This is p 1
<div class="footer">
tessssst
<p>
p test
</p>
</div>
</p>
<div class="container">
tessst
</div>
<p>This is p 2
<div id="someID" class="container">
tessssst 2
</div>
</p>
In the filter function check if it's a text node and also check all of its parents for class, id, tag name - whatever selectors you would like to filter by.
var textnodes = $('body').find("*").contents()
.filter(function () {
return (this.nodeType === 3 && $(this).parents("div").length <= 0);
})
.each(function () {
console.log($(this).text());
});
Here's a working example: https://jsfiddle.net/hracw15o/3/

Wrap every immediate group of objects, including text, except divs inside a new div

I'm trying to wrap every immediate group of objects that is not a div inside a wrap class. Is there any way
Input:
var $code =
'Lorem Ipsum
<p>Foo Bar</p>
<div class="myclass"></div>
<p>Foo Bar</p>
<div class="myclass"></div>'
var $object = $('<div/>').html($code);
Wanted output:
<div class="wrap">
Lorem Ipsum
<p>Foo Bar</p>
</div>
<div class="myclass"></div>
<div class="wrap">
<p>Foo Bar</p>
</div>
<div class="myclass"></div>
What I've tried:
$object.contents().not('> .myclass').wrap('<div class="wrap"></div>');
Can someone help me please? I'm stuck here.
Thank you very much!
Haven't checked whether there is a more optimal way to do it, but there you go
var code =
'Lorem Ipsum<p>Foo Bar</p><div class="myclass"></div><p>Foo Bar</p><div class="myclass"></div>'
var $object = $('<div/>').html(code);
var $obj = $();
$object.contents().each(function () {
if ($(this).hasClass('myclass')) {
$obj.wrapAll('<div class="wrap"/>');
$obj = $();
} else {
$obj = $obj.add(this)
}
})
$obj.wrapAll('<div class="wrap"/>');
Demo: Fiddle

Categories

Resources