Table of contents
- HTMLElement Interface
- Hide/Show
- find / search / get by Attributes
- Attribute Value
- Node Types
- Node.ELEMENT_NODE (1)
- Node.ATTRIBUTE_NODE (2)
- Node.TEXT_NODE (3)
- Node.CDATA_SECTION_NODE(4)
- Node.PROCESSING_INSTRUCTION_NODE (7)
- Node.COMMENT_NODE (8)
- Node.DOCUMENT_NODE (9)
- Node.DOCUMENT_TYPE_NODE (10)
- Node.DOCUMENT_FRAGMENT_NODE (11)
- Check Type
- Deconstruct element to get node names and tag names / NodeName TagName
- Get Element Type
- create clone
- clone element to base64 png
- create table
- get children
- get un-rendered element dimensions
- Script Type
HTMLElement Interface
Hide/Show
CSS Style Hide
element.style.display = "block"; // Show
element.style.display = "inline"; // Show
element.style.visibility = "visible"; // Show
element.style.display = "inline-block"; // Show
element.style.display = "none"; // Hide
element.style.visibility = "hidden"; // Hide
element.style.opacity = 0; // Hide
element.setAttribute("hidden", true); //hide
element.toggle(); // hide/show
Aria Hidden
let el = document.getElementById("hidden");
console.log(el.ariaHidden); // true
el.ariaHidden = "false";
console.log(el.ariaHidden); // false
jQuery
"element".show();
//also
$("element").toggle();
find / search / get by Attributes
document.querySelector("input[name=rate]:checked").value;
wild card / search ids where id is like
document.querySelector('[id^="poll-"]').id;
check if exists
document.body.contains(document.getElementById("test"));
jQuery
$("input[type='radio'][name='scheduleType']:not(:checked)").attr("disabled", true,);
find by text jQuery
:contains(text)
Attribute Value
dataset returns DOMStringMap
Attribute must be camel cased
Element.dataset.attributeNameCamelCased
Get
- Attributes can be set and read by the
camelCase
name/key
as an object property of the dataset:element.dataset.keyname
- Attributes can also be set and read using bracket syntax:
element.dataset['keyname']
- The in operator can check if a given attribute exists: 'keyname' in
element.dataset
document
.getElementById("groupsWrapper-" + id)
.getAttribute("data-saved-assessment-count");
or
imageContainer.dataset.images;
Set
When the attribute is set, its value is always converted to a string. For example: element.dataset.example = null
is converted into data-example="null"
To remove an attribute, you can use the delete
operator: delete element.dataset.keyname
document
.getElementById("groupsWrapper-" + id)
.setAttribute("data-saved-assessment-count", "my text value");
or
// set a data attribute
el.dataset.dateOfBirth = "1960-10-03";
// Result on JS:
el.dataset.dateOfBirth === '1960-10-03'
<!--Result on HTML: -->
<div data-date-of-birth="1960-10-03" data-id="1234567890" data-user="carinaanand" id="user">Carina Anand</div>
Remove
document
.getElementById("groupsWrapper-" + id)
.removeAttribute("data-saved-assessment-count");
or
delete el.dataset.dateOfBirth;
// Result on JS:
el.dataset.dateOfBirth === undefined
<!--Result on HTML: -->
<div data-id="1234567890" data-user="carinaanand" id="user">Carina Anand</div>
null check
if (!("someDataAttr" in el.dataset)) {
el.dataset.someDataAttr = "mydata";
// Result on JS:
'someDataAttr' in el.dataset === true
}
<!--Result on HTML: -->
<div data-id="1234567890" data-some-data-attr="mydata" data-user="carinaanand" id="user">Carina Anand</div>
jQuery
$(selectElement).data("saved-assessment-count", currentTotalResultCount);
If using .data()
to modify, you need to retrieve by .data()
so new value will be reflected
Node Types
Node.ELEMENT_NODE (1)
An Element node
<p>
~~ OR ~~
<div>
Node.ATTRIBUTE_NODE (2)
- An Attribute of an Element
Node.TEXT_NODE (3)
- The actual Text inside an Element or Attr.
Node.CDATA_SECTION_NODE(4)
A CDATASection,
<!CDATA[ … ](%E2%80%A6.md#)>
Node.PROCESSING_INSTRUCTION_NODE (7)
A ProcessingInstruction of an XML document,
<?xml-stylesheet … ?>
Node.COMMENT_NODE (8)
A Comment node,
<!-- … -->
Node.DOCUMENT_NODE (9)
- A Document node
Node.DOCUMENT_TYPE_NODE (10)
A DocumentType node,
<!DOCTYPE html>
Node.DOCUMENT_FRAGMENT_NODE (11)
A DocumentFragment node
<div class="a">a</div>
Check Type
if (element.tagName === "OL") {
}
if (elementsObject && elementsObject?.body?.nodeName === "TABLE") {
}
const tagName = el.tagName || el.nodeName;
if (node?.nodeType) {
}
JavaScript check type on node element
node = e; node.nodeType === 1; node.nodeName === "DIV"; node.tagName === "DIV"; node = e.getAttributeNode("class"); node.nodeType === 2; node.nodeName === "class"; node.tagName === undefined; node = e.childNodes[0]; node.nodeType === 3; node.nodeName === "#text"; node.tagName === undefined;
nodeName breaks for nodeType === 1
only use tagName for nodeType === 1
Deconstruct element to get node names and tag names / NodeName TagName
function addBlankSelectOption(selectBox) {
const {nodeName, tagName} = selectBox;
if (nodeName === "SELECT" || tagName === "SELECT") {
const blankOption = document.createElement("option");
blankOption.setAttribute("selected", true);
blankOption.setAttribute("disabled", true);
blankOption.setAttribute("hidden", true);
selectBox.prepend(blankOption);
}
}
Get Element Type
Object.prototype.toString
.call(obj)
.replace(/^\[object (.+)\]$/, "$1")
.toLowerCase();
create clone
function createClone(element, setCSS, width, height) {
const newElement = element.cloneNode(true);
const createStyles = new Promise((resolve) => {
if (!setCSS) {
resolve(true);
}
else {
generateRulesAll(element)
.then((css) => {
newElement.setAttribute("style", css);
})
.then(resolve);
}
});
createStyles.then((css) => {
if (width) {
newElement.width = width;
newElement.style.width = `${width}`;
}
if (height) {
newElement.height = height;
newElement.style.height = `${height}`;
}
});
return newElement;
}
clone element to base64 png
using XMLSerializer
function svgToDataURL(svg) {
return Promise.resolve()
.then(() => new XMLSerializer().serializeToString(svg))
.then(encodeURIComponent)
.then((html) => `data:image/svg+xml;charset=utf-8,${html}`);
}
function nodeToDataURL(node, width, height) {
return new Promise((resolve) => {
const xmlns = "http://www.w3.org/2000/svg";
const foreignObject = document.createElementNS(xmlns, "foreignObject");
foreignObject.setAttribute("width", "100%");
foreignObject.setAttribute("height", "100%");
foreignObject.setAttribute("x", "0");
foreignObject.setAttribute("y", "0");
foreignObject.setAttribute("externalResourcesRequired", "true");
const svg = document.createElementNS(xmlns, "svg");
svg.setAttribute("width", `${width}`);
svg.setAttribute("height", `${height}`);
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
svg.appendChild(foreignObject);
foreignObject.appendChild(node);
resolve(svgToDataURL(svg));
});
}
function createImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.crossOrigin = "anonymous";
img.decoding = "sync";
img.src = url;
});
}
function buildCanvas(img) {
return new Promise((resolveCanvas) => {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const canvasHeight = img.height + 50;
const canvasWidth = img.width + 50;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.width = `${canvasWidth}`;
canvas.style.height = `${canvasHeight}`;
context.drawImage(img, 0, 0, canvas.width, canvas.height);
resolveCanvas(defaultSlideObject(canvas.toDataURL(), canvas.width, canvas.height),);
});
}
//this is similar to how html2canvas and html-to-image libraries work
// take element -> get generated css -> create ans svg(needed to paint canvas element) ->
// use svg to create xml then uri then uri data string -> use data uri to create image element by adding uri to src attribute ->
// create a canvas element inserting/drawing image in -> get dataURL to use
export function createElementToPNGBase64(arrayOfElementObjects, dimensionsObj, addIndividualElementCSS,) {
if (arrayOfElementObjects) {
return new Promise((resolve) => {
elementsToNewDocument(arrayOfElementObjects, dimensionsObj, addIndividualElementCSS,)
.then(({clonedDocument, width, height, newElementArray}) => nodeToDataURL(clonedDocument.documentElement, width, height),)
.then(createImage)
.then(buildCanvas)
.then(resolve);
});
}
}
export function cloneNodeToDocument(node, elementToAppend, idToSet, width, height, addIndividualElementCSS,) {
if (node) {
const w = width
? width
: node.scrollWidth;
const h = height
? height
: node.scrollHeight;
const newNode = createClone(node, !!addIndividualElementCSS, w, h);
newNode.id = idToSet;
elementToAppend.appendChild(newNode);
return newNode;
}
}
//array of element objects example: [{key: element}]
// dimension object key should match element if custom dimension needed
// example: {key:{height: number, width: number}}
export function elementsToNewDocument(arrayOfElementObjects, dimensionsObj, addIndividualElementCSS,) {
return new Promise((resolveNewDocument) => {
const usableArray = Array.isArray(arrayOfElementObjects)
? arrayOfElementObjects
: [arrayOfElementObjects];
const clonedDocument = document.cloneNode(true);
// documentElement.querySelectorAll("noscript").forEach(el => el.remove())
const body = clonedDocument.body;
body.innerHTML = "";
let totalWidth = 0;
let totalHeight = 0;
const clonedElementArray = usableArray.map((elementObj) => {
const key = Object.keys(elementObj)[0];
const element = elementObj[key];
const width = Object.hasOwn(dimensionsObj, key)
? dimensionsObj[key]?.width
: element.scrollWidth;
const height = Object.hasOwn(dimensionsObj, key)
? dimensionsObj[key]?.height
: element.scrollHeight;
totalWidth = totalWidth > width
? totalWidth
: width;
totalHeight += height;
cloneNodeToDocument(element, body, key, width, height, addIndividualElementCSS,);
});
resolveNewDocument({
clonedDocument: clonedDocument, width: totalWidth, height: totalHeight, newElementArray: clonedElementArray,
});
});
}
create table
export const createRow = async (row, index, newBody) => {
const newRow = newBody.insertRow(index);
newRow.innerHTML = row.innerHTML;
return newRow;
};
export const createTable = async (tableRows, rowIndex, elementsObject, divToAppend,) => {
if (elementsObject && elementsObject?.body?.nodeName === "TABLE") {
const table = elementsObject.body;
const tableId = `clone_table_${rowIndex + 1}`;
const {
nodeClone: newTable, widthToSet, heightToSet,
} = buildNewNodeClone(table, tableId, null, null, true, true);
newTable.tBodies[0].remove();
const tBody = newTable.createTBody();
const tFoot = newTable.createTFoot();
const tHead = newTable.createTHead();
tHead.innerHTML = table.tHead.innerHTML;
tFoot.innerHTML = table.tFoot.innerHTML;
const rowPromises = tableRows.map((row, index) => new Promise((resolve) => resolve(createRow(row, index, tBody))),);
await Promise.all(rowPromises).then((resolved) => {
console.log(`rows for table ${tableId} added`);
});
const tableWrapper = document.createElement("div");
tableWrapper.id = `clone_table_wrapper_${rowIndex + 1}`;
if (elementsObject?.header) {
const {
nodeClone: newHeader, widthToSet, heightToSet,
} = buildNewNodeClone(elementsObject?.header, null, null, null, true, true,);
tableWrapper.appendChild(newHeader);
}
tableWrapper.appendChild(newTable);
if (divToAppend) divToAppend.appendChild(tableWrapper);
return tableWrapper;
}
};
get children
export const getChildren = (element) => {
let childArray = [];
childArray.push(element);
const children = element?.children;
if (children) {
for (let child of children) {
childArray.push.apply(childArray, getChildren(child));
}
}
return childArray;
};
get un-rendered element dimensions
function getWidthAndHeight(node) {
const width = node.scrollWidth || node.offsetWidth || measure(node, "scrollWidth");
const height = node.scrollHeight || node.offsetHeight || measure(node, "scrollHeight");
return {width, height};
}
function measure(element, returnValue, parentNode) {
parentNode = parentNode || window.document.documentElement.lastElementChild;
const display = element.style.display;
const zIndex = element.style.zIndex;
const visibility = element.style.visibility;
element.style.display = "block";
element.style.visibility = "hidden";
element.style.zIndex = -1;
parentNode.appendChild(element);
const {
clientWidth, clientHeight, offsetWidth, offsetHeight, scrollWidth, scrollHeight,
} = element;
parentNode.removeChild(element);
element.style.display = display;
element.style.visibility = visibility;
element.style.zIndex = zIndex;
const returnObj = {
clientWidth: clientWidth,
clientHeight: clientHeight,
offsetWidth: offsetWidth,
offsetHeight: offsetHeight,
scrollWidth: scrollWidth,
scrollHeight: scrollHeight,
};
if (returnObj.hasOwnProperty(returnValue)) {
return returnObj[returnValue];
}
return {
clientWidth, clientHeight, offsetWidth, offsetHeight, scrollWidth, scrollHeight,
};
}
Script Type
Classic
<script>
s block theHTML
parser by default.
You can work around it by adding thedefer
attribute, which ensures that the script download happens in parallel withHTML
parsing.