'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 1:[1]

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/[email protected]/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>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1