¿Es posible acceder a los elementos de Shadow DOM a través del documento padre?


Esta pregunta está más dirigida a los elementos shadow DOM creados por el usuario, pero para la accesibilidad usaré el tipo de entrada date para esta pregunta:

Digamos por ejemplo que tengo una entrada date en mi página. Con un par de bits editados, el marcado shadow DOM para esto (usando Chrome) se ve algo como:

<input type="date">
    #document-fragment
        <div pseudo="-webkit-datetime-edit">
            <div pseudo="-webkit-datetime-edit-fields-wrapper">
                <span role="spinbutton">dd</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">mm</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">yyyy</span>
            </div>
        </div>
        <div></div>
        <div pseudo="-webkit-calendar-picker-indicator"></div>

Los métodos y propiedades asociados con la entrada date no parecen hacer referencia al DOM de sombra en absoluto ( JSFiddle ), así que me preguntaba cómo (si es que lo hace) puede ¿se puede acceder a estos elementos de Shadow DOM?

Author: Supersharp, 2013-05-19

3 answers

int32_t está justo en esa sombra DOM, por definición, es una forma de llenar un nodo con DOM que desea ocultar de fuentes externas (Encapsulación). El punto es que usted, como autor del componente, puede elegir exactamente qué partes se expondrán a CSS o JavaScript externos y cuáles no.

Desafortunadamente, no puede crear una interfaz JavaScript pública para su Shadow DOM sin usar otra especificación de vanguardia llamada Elementos personalizados. Si eliges hacer eso, es tan simple como agregar métodos públicos personalizados al prototipo de tu elemento. Desde estos puedes acceder a las funciones internas de tu Shadow DOM (ver el tercer ejemplo aquí).

Sin embargo, puede exponer hooks para CSS para acceder a las funciones internas de su Shadow DOM sin usar Elementos personalizados. Hay dos maneras de hacerlo:

  1. Pseudo-elementos
  2. Variables CSS

Pseudo-elementos

Chrome y Firefox exponen ciertas partes de su Shadow DOM a CSS a través de pseudo-elementos especiales. Aquí está su ejemplo de la entrada date con la adición de una regla CSS que solo se aplica a la parte numérica del campo de fecha mediante el uso del pseudo-elemento -webkit-datetime-edit proporcionado por Chrome.

Aquí está una lista parcial de los pseudo-elementos de WebKit disponibles. También puede activar la opción Show Shadow DOM en DevTools y buscar atributos llamados pseudo.

Los autores de componentes también pueden crear sus propios pseudo-elementos para exponer partes de su DOM Sombra (ver el 2do ejemplo aquí).

Variables CSS

Una manera aún mejor es usar variables CSS, que puede habilitar con Enable experimental WebKit features en about:flags en Chrome. Luego echa un vistazo a este violín que utiliza variables CSS para comunicar al DOM de Sombras qué color debe usar para su tema"."

 18
Author: CletusW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-20 18:47:35

Ahora (2016) puede acceder a los elementos open shadow DOM creados por el usuario (¡pero no shadow DOM creado por el agente de usuario!) usando el método querySelector en la raíz Shadow DOM:

<body>
    <div id="container"></div>
    <script>
        //Shadow Root
        var root = container.createShadowRoot()
        //new syntax:
        var root = container.attachShadow( { mode: "open" } )

        //Inside element
        var span = document.createElement( "span" )
        span.textContent = "i'm inside the Shadow DOM"
        span.id = "inside"
        root.appendChild( span )

        //Access inside element
        console.log( container.shadowRoot.querySelector( "#inside" ) )
    </script>
</body>

//Shadow Root
var root = container.createShadowRoot()

//Inside element
var span = document.createElement( "span" )
span.textContent = "i'm inside the Shadow DOM"
span.id = "inside"
root.appendChild( span )

//Access inside element
function get() 
{
  alert( container.shadowRoot.querySelector( "#inside" ).id )
}
<!DOCTYPE html>
<html>
<head>
    <title></title>
	<meta charset="utf-8" />
</head>
<body>
	<div id="container"></div>
    <button onclick="get()">Get</button>
	<script>
	</script>
</body>
</html>
 14
Author: Supersharp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-07 15:17:59

No se puede acceder al contenido del Shadow DOM desde scripts fuera del Shadow DOM. La encapsulación es el propósito de Shadow DOM.

 4
Author: int32_t,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-20 00:15:10