Nested Javascript Templates ... is this possible / valid?

Viewed 12994

Is it possible to have nested JavaScript template tags e.g.

<script id="Product" type="text/html">
    <div class="product">
        ....
        <div class="features">
            <script id="Features" type="text/html">
                <div class="feature">
                    ...
                </div>
            </script>
        </div>
        ...
    </div>
</script>

When the template "Product" is evaluated the feature template is now available as a template that I can call when I'm ready.

When I try this method in my browser, I notice some elements appear in the wrong order as if I forgot an end tag somewhere.

However when I remove the nested template (Feature) it is all good ...

Wondering if there was proper way of achieving this.

7 Answers

You can use <style type="text/html"></style> or <noscript></noscript> to wrap your <script></script> tag.

I think <noscript> is better than <style>

example:

<noscript id="s">
  <div class="r">
    <p>{%= o.rand %}</p>
    <script>
      console.log('sdf');
    </script>
  </div>
</noscript>

<style id="s" type="text/html">
  <div class="r">
    <p>{%= o.rand %}</p>
    <script>
      console.log('sdf');
    </script>
  </div>
</style>

Yes, it is possible to have nested <script> tags (with XHTML application/xhtml+xml):

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>XHTML nested &lt;script&gt;</title>
</head>
<body>
  <script id="Product" type="text/html">
    <div class="product">
      ....
      <div class="features">
        <script id="Features" type="text/html">nested
          <div class="feature">
            ...
          </div>
        </script>
      </div>
      ...
    </div>
  </script>
</body>
</html>

Code snippet does not support XHTML, I have to use iframe with data URL:

<iframe src="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20contenteditable%3D%22true%22%3E%3Chead%3E%3Ctitle%3EXHTML%20nested%20%26lt%3Bscript%26gt%3B%3C%2Ftitle%3E%3C%2Fhead%3E%3Cbody%3E%3Cstyle%3Estyle%2C%20script%20%7B%20display%3A%20block%3B%20font-family%3A%20monospace%3B%20white-space%3A%20pre%3B%20padding-left%3A%2010px%20%7D%0Astyle%20%7B%20border-left%3A%2010px%20solid%20%2398A6C0%20%7D%0Ascript%20%7B%20border-left%3A%2010px%20solid%20%23D6F034%20%7D%3C%2Fstyle%3E%3Cscript%20id%3D%22Product%22%20type%3D%22text%2Fhtml%22%3Eouter%0A%20%20%20%20%3Cdiv%20class%3D%22product%22%3E%0A%20%20%20%20%20%20%20%20....%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22features%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%20id%3D%22Features%22%20type%3D%22text%2Fhtml%22%3Einner%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22feature%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fscript%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%3C%2Fdiv%3E%0A%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E" width="100%"></iframe>

Yes, it is possible to have nested <script> tags in HTML DOM:

productScript = document.createElement('script')
productScript.setAttribute('id', 'Product')
productScript.setAttribute('type', 'text/html')
productScript.appendChild(document.createTextNode('outer'))

product = document.createElement('div')
product.setAttribute('class', 'product')
product.appendChild(document.createTextNode(`
        ....
        `))

features = document.createElement('div')
features.setAttribute('class', 'features')

featuresScript = document.createElement('script')
featuresScript.setAttribute('id', 'Features')
featuresScript.setAttribute('type', 'text/html')
featuresScript.appendChild(document.createTextNode('inner'))

feature = document.createElement('div')
feature.setAttribute('class', 'feature')
feature.appendChild(document.createTextNode(`
        ...
    `))

featuresScript.appendChild(feature)
features.appendChild(featuresScript)
product.appendChild(document.createTextNode(`
        ...
    `))
product.appendChild(features)
productScript.appendChild(product)
document.body.appendChild(productScript)
script[type="text/html"] {
  display: block;
  font-family: monospace;
  white-space: pre;
  padding-left: 10px;
  border-left: 10px solid #D6F034
}

No, it is not possible to have nested <script> tags in HTML serialization. Its content is not parsed:

let product = document.getElementById('Product')
console.log(product.textContent)
<script id="Product" type="text/html">
    <div class="product">
        ....
        <div class="features">
            <script id="Features" type="text/html">nested
                <div class="feature">
                    ...
                </div>
            </script>
        </div>
        ...
    </div>
</script>

No, you can't really use the nested script tag inside . When it finds a similar tag inside, the browser will always stop building up the code execution. It does not matter if the nested script has an opening tag. It is because Browser doesn't parse the code as explained by TJ Crowder

Related