How does this jquery code work? - javascript

(Sorry for the bad title, I can't think of a better one)
I recently learned that you can do something like this in jquery:
$("<div><span>content</span></div>").css("color", "red").appendTo("body");
My question is about the following:
$("<div><span>content</span></div>")
How does jquery turn this from a string into dom elements, and how could you do the same thing in vanilla js (no jquery)?
I have attempted to look through the jquery source code, but I don't really understand it.
Any explanation is greatly appreciated!

the equivalent in pure javascript would be
var newDiv = document.createElement("DIV");
newDiv.style.color = "red";
var newSpan = document.createElement("SPAN");
newSpan.innerHTML = "content";
newDiv.appendChild(newSpan);
document.body.appendChild(newDiv);
jquery shortcuts this by defining functions that are chainable meaning the next function uses the previous functions return value as its input so in your example it is adding the css to your html code and then adding all of that code to the body

jQuery is creating a new instance of a jQuery object that contains a reference to the DOM elements created by parsing <div><span>content</span></div>.
One really useful thing jQuery does is that every invocation of jQuery or any of its API methods returns either the newly created jQuery instance or the current jQuery instance. The benefit of this is that you can chain your calls to transform a set of DOM elements.
In this case, $(...) returns a jQuery instance containing the DOM elements you want to operate on. Next, you chained css() which adds style properties to that element. Finally, you chain appendTo() which adds that to a target DOM element. In this case, that target is the <body> element.
Here's how this process would look (roughly) in JavaScript:
First, we need to create the DOM elements we wish to insert.
var node = document.createElement("div");
node.innerHTML = "<div><span>content</span></div>";
var myElement = node.children[0];
Then we'll set the style properties.
myElement.style.color = "red";
Finally, lets append it to an existing element.
document.body.appendChild(myElement);
The creation of the DOM elements from a string happens through the magic of the innerHTML property. When the JavaScript parser encounters a string being set to an elements innerHTML, it will parse that string into DOM elements and insert those elements as children.
Therefore, what jQuery is doing under the hood is creating a dummy element, setting the string you provided as a value on the dummy elements innerHTML property. This causes the DOM elements to be created and inserted as the dummy elements children. Lastly, it retrieves the reference to the children element (the elements you want).

This line creates an jQuery wrapped object from an html string, essentially creating a div with a span inside it whose text is the word content:
$("<div><span>content</span></div>")
This applies a CSS property to the created element telling it to display the text in red:
.css("color", "red")
This adds the created and styled element to the DOM at the end of the body tag:
.appendTo("body");

Related

Vanilla JavaScript replace element

I've looked around and can't seem to find a solution to directly replacing an element with a HTML string using vanilla JavaScript (not jQuery).
I'm storing a bunch of svg's in a directory that's publicly accessible, and I want to be able to include them in my files via the image tag <img src="path/to/svgs/example.svg">. However, this comes with its drawbacks as they can't be coloured/styled when they're pulled in as an image (to my knowledgE).
I discovered this example jQuery Image to SVG but obviously this uses jQuery's replaceWith function. I'm trying to replicate the functionality but struggling with the aforementioned function. All examples I've found end up creating a parent div element, and appending the new HTML to that newly created element.
TL;DR: Can I directly replace an element (IMG to SVG) using vanilla JavaScript without creating parent nodes?
jQuery is also using JavaScript behind replaceWith method, so if you want to replace one element with another you need to do next steps:
Create new element
Add it after/before an element that needs to be replaced
Then remove original element
e.g
If we have HTML list
<ul>
<li>before</li>
<li id="my-element">My element</li>
<li>after</li>
</ul>
and we want to replace list item, with id "my-element", with the new element then we need to do next:
//get reference to element that we want to replace
var elementToReplace = document.getElementById('my-element');
//create new element which will replace existing element
var newLi = document.createElement('li');
//just setting html in it
newLi.innerHTML = 'Just added';
//getting parent element reference and executing method "insertBefore" passing our new element and reference of element that we want to replace
elementToReplace.parentNode.insertBefore(newLi, elementToReplace.nextSibling);
//then we remove original element
elementToReplace.parentNode.removeChild(elementToReplace);
I hope this helps.
Assuming you have already loaded the SVG into a string (via XmlHttpRequest, fetch etc). Then you can parse it using the DOMParser.
var parser = new DOMParser();
var doc = parser.parseFromString(stringContainingSVGSource, "image/svg+xml");
See: Parse SVG and add it to a svg element
Then you can replace the original <img> using something like the insertBefore/removeChild method that Senad suggests.

How to detect an jquery element is in DOM?

I have a jquery element. and I remove it from DOM by using remove(), but jQuery still keep a reference of it.
and later I still can use it and insert it into DOM.
How to detect that this "var p" is in DOM or off DOM ?
var p=$('p');
p.remove();
console.log(p);
p.insertAfter($('body'));
I think p.parent() is more easy way to go. if it in DOM it will get another DOM node
use javascript length to check if dom element exists or not
if($("p").length>0)
{
// p exists
}
var p=$('p');
p.remove();
So when you did p.remove(), it is removed from the dom but it still exists in memory as a stand alone dom node object with all its contents intact.
You can perform any operation as in normal dom element like append anywhere, change contents or change attributes.
The only difference is that it is not part of the document unless you append it in the html.
jQuery has contains method to check if the element is part of the document
jQuery.contains(document, $foo[0]));
p.parent() in case of removed p will return a 0 length jquery object because p is independent node and has no parent.

What is the difference between appendChild, insertAdjacentHTML, and innerHTML

I want to know what the difference is between appendChild, insertAdjacentHTML, and innerHTML.
I think their functionality are similar but I want to understand clearly in term of usage and not the execution speed.
For example, I can use innerHTML to insert a new tag or text into another tag in HTML but it replaces the current content in that tag instead of appends.
If I would like to do it that way (not replace) I need to use insertAdjacentHTML and I can manage where I want to insert a new element (beforebegin, afterbegin, beforeend, afterend)
And the last if I want to create (not insertion in current tag) a new tag and insert it into HTML I need to use appendChild.
Am I understanding it correctly? Or are there any difference between those three?
element.innerHTML
From MDN:
innerHTML sets or gets the HTML syntax describing the element's descendants.
when writing to innerHTML, it will overwrite the content of the source element. That means the HTML has to be loaded and re-parsed. This is not very efficient especially when using inside loops.
node.appendChild
From MDN:
Adds a node to the end of the list of children of a specified parent node. If the node already exists it is removed from current parent node, then added to new parent node.
This method is supported by all browsers and is a much cleaner way of inserting nodes, text, data, etc. into the DOM.
element.insertAdjacentHTML
From MDN:
parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position. [ ... ]
This method is also supported by all browsers.
....
The appendChild methods adds an element to the DOM.
The innerHTML property and insertAdjacentHTML method takes a string instead of an element, so they have to parse the string and create elements from it, before they can be put into the DOM.
The innerHTML property can be used both for getting and setting the HTML code for the content of an element.
#Guffa did explain the main difference ie innerHTML and insertAdjacentHTML need to parse the string before adding to DOM.
In addition see this jsPerf that will tell you that generally appendChild is faster for the job it provides.
One that I know innerHTML can grab 'inner html', appendChild and insertAdjacentHTML can't;
example:
<div id="example"><p>this is paragraph</p><div>
js:
var foo = document.getElementById('example').innerHTML;
end then now
foo = '<p>this is paragraph</p>';
DOCS:
appendChild
insertAdjacentHTML
innerHtml
innerHTML vs appendChild() performance
insertAdjacentHTML vs innerHTML vs appendChild performance
the main difference is location (positioning) :
(elVar mean element saved to variable)
** elVar.innerHTML: used to sets/get text and tags (like ) inside an element (if u use "=" it replace the content and "+=" will add to the end.
** divElvar.appendChild(imgElVar): to add pure element to the end of another element (or start with prepend) .
** insertedElVar.insertAdjacentElement(beforebegin,targetElvar): it insert element into spicific location before elVar (after it with "afterend").
-innerText: can replace/get/insertOnEnd text.but can read tags and text inside element with display:hidden , cant insert on start .
-innercontent : show all text inc hidden , cant read html tags and it put empty spaces instead of them , cant insert on start
-innerHTML: read all set all , cant insert on start
-prepend : insert text at start of elvar (but cant use to get/replace text or html)
prepend was needed for start, after it made its easy to make append , not for a need , its just bcz lol

How to insert a HTML fragment and hold a reference to the outer element?

I've always wondered how this jQuery feature works: $('<span>Hello world</span>')[0]
That is supposed to return a reference to the newly created span element. How can I achieve the same result using the native DOM methods? insertAdjacentHTML? innerHTML? documentFragment?
I need to insert a HTML fragment and hold a reference to the outer element without the need of using createElement/appendChild.
Thanks.
It's possible to create an element, set its innerHTML, and return the first child. The container element is never added to the DOM:
var el = document.createElement('div');
el.innerHTML = '<span>Hello world</span>';
console.log(el.firstChild);
If that's wrapped in a function, I believe the original container will be eligible for garbage collection as soon as the child is appended somewhere else.
jQuery seems to be doing something more sophisticated, checking if the string contains a single tag or not, and creating a fragment for more complicated strings. See the parseHTML method on jQuery's source code.

Detect dynamic div elements with getElementById()

So when the code ...
document.getElementById('classhere').childNodes
... runs, I manage to get all elements with that ID EXCEPT for elements that have been dynamically created by a 'createDiv()' function:
function createDiv()
{
var divTag = document.createElement("div");
divTag.id = "classhere" + num;
...
I would like to get all div elements with that Id, even dynamically created div elements. Does anyone have a solution? Thanks!
Try out jQuery
jQuery Wildcard Selector
http://www.emadibrahim.com/2009/07/25/jquery-wildcard-selector/
So when the code ...
document.getElementById('classhere').childNodes
... runs, I manage to get all elements with that ID
getElementById looks up a single element by ID, not by class. That line as quoted will look up an element with the id value "classhere" and return a NodeList of its immediate child nodes (elements, text nodes, etc.). If you create further elements and either don't add them to the DOM, or add them elsewhere (not as immediate children of the "classhere" element), they won't be on the NodeList. It has nothing to do with whether they were created during the main HTML parsing or after-the-fact with JavaScript.
I would like to get all div elements with that Id...
There can be only one element with a given ID.
If you're trying to find all elements whose id starts with "classname", you can use an "attribute starts with selector":
var divs = $("div[id^='classname']");
...gives you a jQuery object containing all of the matching divs as of the time you executed the statement (unlike a NodeList, it's not live; if you change things you'll have to run the selector again).

Categories