How can I copy a whole html element? [duplicate] - javascript

This question already has answers here:
full HTML of object returned by jQuery selector
(10 answers)
Closed 8 years ago.
Let's say I have some elements like:
<div id="some-id" class="some-class">
<h1>Something here</h1>
</div>
And I would like to copy the whole some-id element together with all it's children, send it to database and then, when reloading the page, append them to the body.
I tried:
clone() and I got: "prevObject: jQuery.fn.jQuery.init[0], context: undefined, constructor: function, init: function, selector: ""…"
cloning and JSON.stringify() and I got one warning and one error in the console:
'Attr.ownerElement' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom).
Uncaught TypeError: Converting circular structure to JSON
What can I use to end up with the html structure of my element that I can put in the database and re-use it?

If you want to persist a html structure, then you need to use its html string, you can't stringify the dom reference. The html string can be saved and can be used later to append back to the dom.
var string = $('#some-id')[0].outerHTML

Use outerHTML :
document.getElementById('some-id').outerHTML

jQuery clone should do the job. Try this:
var elem = $('#some-id');
var clone = elem.clone();
Besides, why are you saving it to the DB?

Related

textContent returns undefined

I have a table in which I want to extract the text of the active item. I do this with the following code:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active");
console.log(addedWorkout);
addedWorkout = addedWorkout.textContent;
console.log(addedWorkout);
The problem is that I keep getting undefined. I checked the console and it indeed finds the element I want without fail.
I am relatively new to Javascript, but after over an hour of Googling I could not find the issue and I don't understand why. I know that I can get the text element if I hardcore it using the following line:
document.querySelector("#selectiona1").textContent
but not with:
$("#selectiona1").textContent
What is the difference between these 2? I read that textContent is part of the DOM, to my understanding it relates to objects and according to my console i think it is an object. I made some crazy attempts like putting the object I got into the querySelector, but nothing works.
With this line:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active");
you're using jQuery to select the .dropdown-item.active inside #custDropDownMenuA, and when you select with jQuery, you get a jQuery object in response. So, addedWorkout is a jQuery object, and jQuery objects generally do not have the same properties/methods as standard HTMLElements. (querySelector is the vanilla Javascript method to retrieve an element)
Either select the [0]th item in the jQuery collection to get to the first matching element:
var addedWorkout = $("#custDropDownMenuA").find(".dropdown-item.active")[0];
Or use the jQuery method to get the text of the first matching element, which is .text():
var addedWorkoutText = addedWorkout.text();
(note the use of a new variable - you will likely find it easier to read and debug code when you create new variables rather than reassigning old ones, when possible)
Your var 'addedWorkout' is a Jquery object, not a html element.
To show the text use:
addedWorkout.text();
Alternatively, you can change the 'addedWorkout' to a html element by adding the index [0], like this:
addedWorkout[0].textContent;

How to get all possible valid attributes on a DOM element [duplicate]

This question already has answers here:
How to list all element attributes in JS?
(3 answers)
Closed 5 years ago.
Please note that .attributes only gets the current attributes, which is not what this question is about.
I want a way to get all the attributes of a DOM element. Not just the ones that are on it now, but the ones that are possible in the future too.
The specific use case is to find the potential attributes in an SVGElement that aren't in an HTMLElement - there's a list on MDN (SVG Attribute reference), but, for obvious reasons, hardcoding is not a good idea.
My initial thought was to iterate through the prototype chain of an instance of each and compare the two lists (with basic filtering for event handlers), but this doesn't actually give the potential svg attributes.
EDIT
IMPORTANT NOTE - pasting your answer code into the console on this page and using document.body as a target should show a list of over 50 attributes, including things like contentEditable, contextMenu, dir, style, etc.
This also needs to work cross-browser.
Could something like this be what you're looking for?
It looks like a DOM element object stores empty keys for all possible attributes. Could you loop over these keys and store them in an array, then from there use something similar to filter out inherited attributes?
HTML
<svg id="blah"></svg>
Javascript
const blah = document.getElementById('blah')
let possibleKeys = []
for (let key in blah) {
possibleKeys.push(key)
}
Here's a JSBin example ... it looks like it produces a list of all possible attributes but it would need some filtering.
See also this thread.
How to list all element attributes in JS?
Any one of these should work because they return a live HTMLCollection.
var svgElement = window.document.getElementsByClassName("someSvgClass")[0];
//assume someSvgClass is on svg element.
//var svgElement = window.document.getElementsByTagName("svg")[0];
//var svgElement = window.document.getElementsByName("mySvg")[0];
//assume svg has this name.
var svgAttributes = svgElement.attributes;
for(let i=0; i<svgAttributes.length; i++) {
console.log(svgAttributes[i]);
}
See the below documentation from MDN on getElementsByTagName()
The Element.getElementsByTagName() method returns a live
HTMLCollection of elements with the given tag name. The subtree
underneath the specified element is searched, excluding the element
itself. The returned list is live, meaning that it updates itself with
the DOM tree automatically. Consequently, there is no need to call
several times Element.getElementsByTagName() with the same element and
arguments.
The documentation for getElementsByName , and getElementsByClassName say the same thing; a live node list is returned. If you'd like to try it, I created a fiddle here.
You'll see that svgAttributes list is automatically updated upon clicking "Add Attribute" without re-executing any of those functions.
There is no API for that and I don't think a workaround is possible because when you change an attribute on a current DOM node, the browser is responsible for re-rendering and updating the webpage in a low-level way that is not exposed to the JavaScript context.
Also, keep in mind that any correctly formatted attribute is actually valid in the context of a DOM tree, even though it might not trigger any change at the rendering level or in the way the browser renders the page. Especially the data-* attributes.
There might be some vendor-specific API but that wouldn't be useful if you want cross-browser compatibility.
You need to hardcode it, sadly. Given that you specifically want the SVGElement attributes, maybe you can scrape the W3's SVG standard document to automatically create the list?
Edit: I made a snippet to easily scrape the values from the standard:
const uniq = arr => Array.from(new Set(arr))
const nameElements = document.querySelectorAll('table[summary="Alphabetic list of attributes"] .attr-name')
const arrNameElements = Array.prototype.slice.call(nameElements)
const svgAttributes = uniq(arrNameElements.map(el => el.innerText.replace(/\‘|\’/g, '')))
Just execute it on the svg attributes page, by opening the dev console on the page and pasting in this code :)
Edit 2: I forgot the presentation attributes. I'll let you figure that one out ;)

Get the outer HTML of a detached JQuery object [duplicate]

This question already has answers here:
Get selected element's outer HTML
(30 answers)
Closed 6 years ago.
I'm creating a html node by jQuery (the sample is of tag <input> but can be of any type):
var x = $("<input>");
Then I add its attributes through a series of .prop() function:
x.prop("id", ...).prop("class", ...);
Now a certain plugin does not support JQuery object, but rather the HTML string so I invoke the plugin through this:
var n = plugin.method1(x.html())
Which I though will work but .html() returns an empty string. Although some said it will be resolved if I append it first on the DOM tree. How can I get its HTML string without appending it first in the DOM tree?
You can use .prop() to get outerHTML property.
x.prop('outerHTML');
var x = $("<input>");
x.prop('id', 'yahooooooooo');
console.log(x.prop('outerHTML'))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Bit simpler to index the HTMLElement behind it and access the outerHTML property like this:
x[0].outerHTML

single .js file to execute on multiple html pages [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 6 years ago.
I created a .js file for the directory of html of files I am working with. The purpose of the .js file is to remove element ids. So in my .js file I currently have the script
var element=document.getElementById("id1");
element.parentElement.removeChild(element);
which works perfectly fine and does what I need to do. Now If I was to include an additional script to remove the id element of a different html page
var element = document.getElementById("id1");
element.parentElement.removeChild(element);
var elem = document.getElementById("id2");
elem.parentElement.removeChild(elem);
Only the first script is executed and the second is not in addition I receive the message "Uncaught type error: cannot read 'parentElement' of null. I would think that each html page would read the .js file and match the corresponding element it is referring too and make the change.
Uncaught type error: cannot read 'parentElement' of null means that it could not find the element with the given id and therefore you can not try to find its parent element. If you wanted to make this more generic you could try abstracting it to a function
function removeElementById(elId) {
var el = document.getElementById(elId);
if (el) {
el.parentNode.removeChild(el);
}
}
Now whenever you try to remove an element it will first check that it is not "falsy" before attempting to remove the element from its parent.
It's like the error says, the parentElement of a non existing element is null, and null has no method 'removeChild' So you must check if element exists.
var element=document.getElementById("id1");
if(element) {
element.parentElement.removeChild(element);
}
The element (id2) you tried to find is probably not in DOM when the srcipt runs. You will need to check if it is null before accessing its methods.

Removing $() jQuery wrapper to just get raw JS element [duplicate]

This question already has answers here:
How to get a DOM Element from a jQuery selector?
(4 answers)
Closed 8 years ago.
Random just out of curiosity question:
Let's say for whatever reason I get an element back from a function
$(element)
But I want to remove the $( __ ) jQuery wrapper to leave the regular DOM Element:
element
Is this possible? (I'm sure it'd be smart to test $(element).length() to make sure it isn't more than 1 thing inside beforehand too...
jsFiddle
var firstElem = $(element)[0];
or
var firstElem = $(element).get(0);
Calling get() without an index gives you an array of the elements.
Reference: jQuery get()
DOM elements are stored as properties at numeric zero-based indices, so you access them just like you would for any other object.
$jqObj[0];
Or get a full Array of elements using toArray()
$jqObj.toArray();
Fiddle: http://jsfiddle.net/xHj5d/2/
removeJWrapper($('#ohHeyo'));
function removeJWrapper (el) {
console.log(el[0]);
}

Categories

Resources