javascript - ejemplo - Creación de un nuevo elemento DOM a partir de una cadena HTML utilizando métodos DOM o Prototype integrados
getelementsbytagname (21)
HTML5 <template> & ES6
manifestación
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @description HTML5 Template
* @augments
* @example
*
*/
/*
<template>
<h2>Flower</h2>
<img src="https://www.w3schools.com/tags/img_white_flower.jpg">
</template>
<template>
<div class="myClass">I like: </div>
</template>
*/
const showContent = () => {
// let temp = document.getElementsByTagName("template")[0],
let temp = document.querySelector(`[data-tempalte="tempalte-img"]`),
clone = temp.content.cloneNode(true);
document.body.appendChild(clone);
};
const templateGenerator = (datas = [], debug = false) => {
let result = ``;
// let temp = document.getElementsByTagName("template")[1],
let temp = document.querySelector(`[data-tempalte="tempalte-links"]`),
item = temp.content.querySelector("div");
for (let i = 0; i < datas.length; i++) {
let a = document.importNode(item, true);
a.textContent += datas[i];
document.body.appendChild(a);
}
return result;
};
const arr = ["Audi", "BMW", "Ford", "Honda", "Jaguar", "Nissan"];
if (document.createElement("template").content) {
console.log("YES! The browser supports the template element");
templateGenerator(arr);
setTimeout(() => {
showContent();
}, 0);
} else {
console.error("No! The browser does not support the template element");
}
@charset "UTf-8";
/* test.css */
:root {
--cololr: #000;
--default-cololr: #fff;
--new-cololr: #0f0;
}
[data-class="links"] {
color: white;
background-color: DodgerBlue;
padding: 20px;
text-align: center;
margin: 10px;
}
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Template Test</title>
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<section>
<h1>Template Test</h1>
</section>
<template data-tempalte="tempalte-img">
<h3>Flower Image</h3>
<img src="https://www.w3schools.com/tags/img_white_flower.jpg">
</template>
<template data-tempalte="tempalte-links">
<h3>links</h3>
<div data-class="links">I like: </div>
</template>
<!-- js -->
</body>
</html>
Tengo una cadena HTML que representa un elemento: ''<li>text</li>''
. Me gustaría agregarlo a un elemento en el DOM (una ul
en mi caso). ¿Cómo puedo hacer esto con Prototype o con métodos DOM?
(Sé que podría hacer esto fácilmente en jQuery, pero desafortunadamente no estamos usando jQuery).
Agregué un prototipo de Document
que crea un elemento a partir de una cadena:
Document.prototype.createElementFromString = function (str) {
const element = new DOMParser().parseFromString(str, ''text/html'');
const child = element.documentElement.querySelector(''body'').firstChild;
return child;
};
Aquí está el código de trabajo para mí
Quería convertir la cadena '' Texto '' a elemento HTML
var diva = UWA.createElement(''div'');
diva.innerHTML = ''<a href="http://wwww.example.com">Text</a>'';
var aelement = diva.firstChild;
Aquí está mi código, y funciona:
function parseTableHtml(s) { // s is string
var div = document.createElement(''table'');
div.innerHTML = s;
var tr = div.getElementsByTagName(''tr'');
// ...
}
Aquí hay una manera simple de hacerlo:
String.prototype.toDOM=function(){
var d=document
,i
,a=d.createElement("div")
,b=d.createDocumentFragment();
a.innerHTML=this;
while(i=a.firstChild)b.appendChild(i);
return b;
};
var foo="<img src=''//placekitten.com/100/100''>foo<i>bar</i>".toDOM();
document.body.appendChild(foo);
Con Prototype, también puedes hacer:
HTML:
<ul id="mylist"></ul>
JS:
$(''mylist'').insert(''<li>text</li>'');
Esto funcionará también:
$(''<li>'').text(''hello'').appendTo(''#mylist'');
Se siente más como una manera jquery con las llamadas de función encadenadas.
Estoy usando este método (Funciona en IE9 +), aunque no analizará <td>
o algún otro hijo directo no válido del cuerpo:
function stringToEl(string) {
var parser = new DOMParser(),
content = ''text/html'',
DOM = parser.parseFromString(string, content);
// return element
return DOM.body.childNodes[0];
}
stringToEl(''<li>text</li>''); //OUTPUT: <li>text</li>
HTML 5 introdujo el elemento <template>
que se puede usar para este propósito (como se describe ahora en la especificación WhatWG y los documentos MDN ).
Un <template>
es un elemento HTML que se permite cualquier otro tipo de elemento como hijo. La template
tiene una propiedad .content
que puede acceder con JavaScript que apunta a un DocumentFragment
con el contenido de la plantilla. Esto significa que puede convertir una cadena HTML en elementos DOM al configurar el HTML innerHTML
de un elemento <template>
, y luego .content
propiedad .content
la template
.
Ejemplos:
/**
* @param {String} HTML representing a single element
* @return {Element}
*/
function htmlToElement(html) {
var template = document.createElement(''template'');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
var td = htmlToElement(''<td>foo</td>''),
div = htmlToElement(''<div><span>nested</span> <span>stuff</span></div>'');
/**
* @param {String} HTML representing any number of sibling elements
* @return {NodeList}
*/
function htmlToElements(html) {
var template = document.createElement(''template'');
template.innerHTML = html;
return template.content.childNodes;
}
var rows = htmlToElements(''<tr><td>foo</td></tr><tr><td>bar</td></tr>'');
Tenga en cuenta que los enfoques similares que utilizan un elemento contenedor diferente, como un div
, no funcionan bien. HTML tiene restricciones sobre qué tipos de elementos pueden existir dentro de los cuales otros tipos de elementos; por ejemplo, no puedes poner un td
como hijo directo de un div
. Esto hace que estos elementos desaparezcan si intenta configurar el innerHTML
de un div
para que los contenga. Como los <template>
s no tienen tales restricciones en su contenido, este defecto no se aplica cuando se usa una plantilla.
Sin embargo, la template
no es compatible con algunos navegadores antiguos. A partir de enero de 2018, ¿Puedo usar ... las estimaciones del 90% de los usuarios a nivel mundial utilizan un navegador que admite template
? En particular, ninguna versión de Internet Explorer los admite; Microsoft no implementó el soporte de template
hasta el lanzamiento de Edge.
Si tiene la suerte de escribir un código que solo está dirigido a usuarios en navegadores modernos, continúe y utilícelos ahora mismo. De lo contrario, es posible que tenga que esperar un tiempo para que los usuarios se pongan al día.
Las nuevas implementaciones de DOM tienen range.createContextualFragment
, que hace lo que usted quiere de una manera independiente del marco.
Es ampliamente compatible. Sin embargo, para estar seguro, verifique su compatibilidad en el mismo enlace de MDN, ya que cambiará. A partir de mayo de 2017 esto es:
Feature Chrome Edge Firefox(Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) 11 15.0 9.1.2
No hay necesidad de ningún ajuste, tienes una API nativa:
const toNodes = html =>
new DOMParser().parseFromString(html, ''text/html'').body.childNodes
Para ciertos fragmentos html como <td>test</td>
, div.innerHTML, DOMParser.parseFromString y range.createContextualFragment (sin el contexto correcto) no creará el elemento <td>
.
jQuery.parseHTML () los maneja ( extraje la función parseHTML de jQuery 2 en una esencia independiente ).
Para Edge 13+, usa la etiqueta de plantilla:
function parseHTML(html) {
var t = document.createElement(''template'');
t.innerHTML = html;
return t.content.cloneNode(true);
}
var documentFragment = parseHTML(''<td>Test</td>'');
Para mejorar aún más el útil .toDOM () fragmento que podemos encontrar en diferentes lugares, ahora podemos usar de forma segura backticks ( literales de plantilla ).
Así que podemos tener comillas simples y dobles en la declaración hoo de foo .
Esto se comporta como heredocs para aquellos familiarizados con el término.
Esto puede mejorarse además con variables, para crear plantillas complejas:
Los literales de la plantilla están encerrados en el reverso (
) (acento grave) carácter en lugar de comillas dobles o simples. Los literales de plantilla pueden contener marcadores de posición. Estos están indicados por el signo de dólar y las llaves ($ {expresión}). Las expresiones en los marcadores de posición y el texto entre ellos se pasan a una función. La función predeterminada solo concatena las partes en una sola cadena. Si hay una expresión que precede a la plantilla literal (etiqueta aquí), esto se denomina "plantilla etiquetada". En ese caso, la expresión de la etiqueta (generalmente una función) se llama con el literal de la plantilla procesada, que luego puede manipular antes de emitir. Para escapar de una marca de retroceso en un literal de plantilla, coloque una barra invertida / antes de la marca de retroceso.
String.prototype.toDOM=function(){
var d=document,i
,a=d.createElement("div")
,b=d.createDocumentFragment()
a.innerHTML = this
while(i=a.firstChild)b.appendChild(i)
return b
}
// Using template litterals
var a = 10, b = 5
var foo=`
<img
onclick="alert(''The future start today!'')"
src=''//placekitten.com/100/100''>
foo${a + b}
<i>bar</i>
<hr>`.toDOM();
document.body.appendChild(foo);
img {cursor: crosshair}
Por un momento pensé que compartiría esto con un enfoque complicado pero a la vez simple que se me ocurrió ... Tal vez alguien encuentre algo útil.
/*Creates a new element - By Jamin Szczesny*/
function _new(args){
ele = document.createElement(args.node);
delete args.node;
for(x in args){
if(typeof ele[x]===''string''){
ele[x] = args[x];
}else{
ele.setAttribute(x, args[x]);
}
}
return ele;
}
/*You would ''simply'' use it like this*/
$(''body'')[0].appendChild(_new({
node:''div'',
id:''my-div'',
style:''position:absolute; left:100px; top:100px;''+
''width:100px; height:100px; border:2px solid red;''+
''cursor:pointer; background-color:HoneyDew'',
innerHTML:''My newly created div element!'',
value:''for example only'',
onclick:"alert(''yay'')"
}));
Puede crear nodos DOM válidos a partir de una cadena usando:
document.createRange().createContextualFragment()
El siguiente ejemplo agrega un elemento de botón en la página que toma el marcado de una cadena:
let html = ''<button type="button">Click Me!</button>'';
let fragmentFromString = function (strHTML) {
return document.createRange().createContextualFragment(strHTML);
}
let fragment = fragmentFromString(html);
document.body.appendChild(fragment);
Puede utilizar la siguiente función para convertir el texto "HTML" al elemento
function htmlToElement(html)
{
var element = document.createElement(''div'');
element.innerHTML = html;
return(element);
}
var html="<li>text and html</li>";
var e=htmlToElement(html);
Tarde pero solo como una nota;
Es posible agregar un elemento trivial al elemento de destino como un contenedor y eliminarlo después de usarlo.
// Probado en Chrome 23.0, Firefox 18.0, es decir, 7-8-9 y Opera 12.11.
<div id="div"></div>
<script>
window.onload = function() {
var foo, targetElement = document.getElementById(''div'')
foo = document.createElement(''foo'')
foo.innerHTML = ''<a href="#" target="_self">Text of A 1.</a> ''+
''<a href="#" onclick="return !!alert(this.innerHTML)">Text of <b>A 2</b>.</a> ''+
''<hr size="1" />''
// Append ''foo'' element to target element
targetElement.appendChild(foo)
// Add event
foo.firstChild.onclick = function() { return !!alert(this.target) }
while (foo.firstChild) {
// Also removes child nodes from ''foo''
targetElement.insertBefore(foo.firstChild, foo)
}
// Remove ''foo'' element from target element
targetElement.removeChild(foo)
}
</script>
Utilice insertAdjacentHTML() . Funciona con todos los navegadores actuales, incluso con IE11.
var mylist = document.getElementById(''mylist'');
mylist.insertAdjacentHTML(''beforeend'', ''<li>third</li>'');
<ul id="mylist">
<li>first</li>
<li>second</li>
</ul>
Nota: la mayoría de los navegadores actuales admiten elementos <template>
HTML, que proporcionan una forma más confiable de convertir elementos de creación a partir de cadenas. Vea la respuesta de Mark Amery a continuación para más detalles .
Para los navegadores más antiguos, y node / jsdom : (que aún no admite elementos <template>
en el momento de la escritura), use el siguiente método. Es lo mismo que hacen las bibliotecas para obtener elementos DOM de una cadena HTML ( con algo de trabajo adicional para que IE pueda solucionar los errores con su implementación de innerHTML
):
function createElementFromHTML(htmlString) {
var div = document.createElement(''div'');
div.innerHTML = htmlString.trim();
// Change this to div.childNodes to support multiple top-level nodes
return div.firstChild;
}
Tenga en cuenta que, a diferencia de las plantillas HTML, esto no funcionará con algunos elementos que no pueden ser legalmente hijos de <div>
, como <td>
s.
Si ya está utilizando una biblioteca, le recomendaría que siga el método aprobado por la biblioteca para crear elementos a partir de cadenas HTML:
- Prototype tiene esta característica incorporada en su método
update()
. - jQuery lo ha implementado en sus métodos
jQuery(html)
yjQuery.parseHTML
.
function domify (str) {
var el = document.createElement(''div'');
el.innerHTML = str;
var frag = document.createDocumentFragment();
return frag.appendChild(el.removeChild(el.firstChild));
}
var str = "<div class=''foo''>foo</div>";
domify(str);
var jtag = $j.li({ child:''text'' }); // Represents: <li>text</li>
var htmlContent = $(''mylist'').html();
$(''mylist'').html(htmlContent + jtag.html());
Usar jnerator