将 <img> 替代文本转换为图像标题节点

Converting <img> alt text to image caption node

function altTextToImageCaption() {
  let imgs = document.getElementsByTagName('img');
  for (var i = 0; i < imgs.length; i++) {
    var att = imgs[i].attributes.getNamedItem('alt');
    if (!att) continue;
    var alt = att.value;
    if (!alt) continue;
    if (!alt.startsWith('Fig ')) continue;
    var cap = document.createElement('div');
    cap.setAttribute('class', 'imageCaption');
    cap.appendChild(document.createTextNode(alt));
    document.body.insertBefore(cap, imgs[i].nextSibling);
  }
}
<body onload="altTextToImageCaption()">
  <h1>Image Caption No Workie</h1>
  <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 1. First caption.">

  <div>
  <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 2. Second caption.">
  </div>
</body>

我试图想出一个 jscript 函数,该函数在 html 文档中的所有图像下方插入一个标题文本,该文档包含一个以“Fig”开头的 alt 属性。似乎工作正常,除非 img 节点位于 divspan 内。在那种情况下有一个例外:

Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."

我建议更改线路:

document.body.insertBefore(cap, imgs[i].nextSibling);

至:

imgs[i].parentNode.insertBefore(cap, imgs[i].nextSibling);

这确保 <div> 始终附加在 <img> 本身之后,无论它出现在 DOM 中的什么位置:

function altTextToImageCaption() {
  let imgs = document.getElementsByTagName('img');
  for (var i = 0; i < imgs.length; i++) {
    var att = imgs[i].attributes.getNamedItem('alt');
    if (!att) continue;
    var alt = att.value;
    if (!alt) continue;
    if (!alt.startsWith('Fig ')) continue;
    var cap = document.createElement('div');
    cap.setAttribute('class', 'imageCaption');
    cap.appendChild(document.createTextNode(alt));
    imgs[i].parentNode.insertBefore(cap, imgs[i].nextSibling);
  }
}
<body onload="altTextToImageCaption()">
  <h1>Image Caption No Workie</h1>
  <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 1. First caption.">

  <div>
    <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 2. Second caption.">
  </div>
</body>

然而,虽然这解决了问题,但我还将您的函数完全重写为以下内容 - 并且还使用不显眼的 JavaScript - 如下:

// using an Arrow function to create the function as a const:
const altTextToImageCaption = () => {
  // using document.querySelectorAll() to retrieve only
  // <img> elements that have an 'alt' attribute that starts
 // with the string "Fig "
  let images = document.querySelectorAll('img[alt^="Fig "]');

  // using NodeList.prototype.forEach() to iterate over the
  // NodeList of <img> element-nodes:
  images.forEach(
    // using an anonymous Arrow function:
    (img) => {
      // retrieving the attribute-value of the 'alt'
      // attribute, and removing leading/trailing
      // white-space:
      let alt = img.alt.trim(),
        // creating a <div> element:
        div = document.createElement('div');

      // using the Element.classList API to add the
      // 'imageCaption' class-name:
      div.classList.add('imageCaption');
      // using ParentNode.append() to append
      // the string:
      div.append(alt);

      // navigating to the <img> element's parent,
      // and using ParentNode.insertBefore() to
      // insert the new ('div') content before the
      // next-sibling of the <img> element:
      img.parentNode.insertBefore(div, img.nextSibling);
    });
}

// binding the event-handling in JavaScript rather than inline
// event-binding; here we bind the altTextToImageCaption() function
// as the event-handler for the 'DOMContentLoaded' event:
window.addEventListener('DOMContentLoaded', altTextToImageCaption);
<body>
  <h1>Image Caption No Workie</h1>
  <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 1. First caption.">

  <div>
    <img src="https://www.easyrgb.com/look/home_logo.png" alt="Fig 2. Second caption.">
  </div>
</body>

您需要使用图片的parentNode调用insertBefore

作为额外的清理,您可以使用 for..of 稍微清理一下代码。

我提议:

function altTextToImageCaption() {
  let imgs = document.getElementsByTagName('img')
  for(let img of imgs) {
    var att = img.attributes.getNamedItem('alt')
    if (!att) continue
    let alt = att.value
    if (!alt) continue
    if (!alt.startsWith('Fig ')) continue
    let cap = document.createElement('div')
    cap.setAttribute('class', 'imageCaption')
    cap.appendChild(document.createTextNode(alt))
    img.parentNode.insertBefore(cap, img.nextSibling)
  }
}