Search code examples
javascripthtmles6-modules

Access html5 data-* attributes defined in a module script


When loading scripts without using modules, I could use the document.currentscript to access custom attributes.

E.g.

<script src="js/myscript.js" data-custom-attribute="my-value"></script>

Within myscript.js I can then do the following

// will contain "my-value"
const myAttribute = document.currentScript.getAttribute('data-custom-attribute'); 

If I load the javascript using module syntax however, the currentScript is set to null and this doesn't work.

<script src="js/myscript.js" data-custom-attribute="my-value" type="module"></script>

Is there a way to still access such attributes within the javascript file?


Solution

  • From MDN

    The Document.currentScript property returns the element whose script is currently being processed and isn't a JavaScript module. (For modules use import.meta instead.)

    import.meta does not provide the data-attribute. Here are a few alternatives:

    [edit may 2022] The import from the original snippet does not exist anymore. Though it's still loaded from cdn.jsdelivr.net, this may in the future not be the case. So, added a new snippet using a more persistent library.

    <script data-custom-attribute="my-value" type="module">
      import {Logger} from 
        "https://cdn.jsdelivr.net/gh/KooiInc/DOM-Utilities@v1.1.2/SmallHelpers.js";
      const log = Logger();
      log(`document.currentScript is ${document.currentScript}`);
      log(`But with querySelector ... data-custom-attribute from module script: ${
        document.querySelector("script[type=module]").dataset.customAttribute}`);
      log(`Or more precize: document.querySelector("script[data-custom-attribute]"): ${
        document.querySelector("script[data-custom-attribute]")
          .dataset.customAttribute}`);
      log(`Or retrieve and filter document.scripts: ${[...document.scripts]
          .find(scrpt => scrpt.dataset.customAttribute).dataset.customAttribute}`);
    </script>

    <script type="module" data-custom-attribute="my-value">
      import $ from "https://kooiinc.github.io/JQL/lib/JQLBundle.js";
      $.setStyle(`#result`, {whiteSpace: `nowrap`});
      $.setStyle(`#result div`, {marginTop: `0.3rem`});
      $.setStyle(`code`, {color: `green`});
      const log = (...lines) => 
        lines.forEach( line => $(`#result`).html(`<div>${line}</div>`, true));
      const indent = `<br>&nbsp;&nbsp;`;
      
      // --------------------------------------------------------------------------
      log(`<code>document.currentScript</code> = ${document.currentScript}`); 
      log(`But<br>
        <code>document.querySelector("script[type=module]")
        .dataset.customAttribute</code> = "${ 
         document.querySelector("script[type=module]").dataset.customAttribute}"`);
      log(`Or targeted exactly<br> 
        <code>document.querySelector("script[data-custom-attribute]")
        ${indent}.dataset.customAttribute</code> = "${ 
        document.querySelector("script[data-custom-attribute]")
          .dataset.customAttribute}"`); 
      log(`Or retrieve from <code>document.scripts</code><br>
        <code>[...document.scripts].find(scrpt =>
           ${indent}scrpt.dataset.customAttribute).dataset.customAttribute</code> = "${
            [...document.scripts].find(scrpt => scrpt.dataset.customAttribute)
              .dataset.customAttribute}"`);
    </script>
    
    <div id="result"></result>