【问题标题】:Converting <img> alt text to image caption node将 <img> 替代文本转换为图像标题节点
【发布时间】:2021-04-12 14:39:22
【问题描述】:

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."

【问题讨论】:

  • imgs[i].parentNode.insertBefore(cap, imgs[i]); 也许?
  • @AlonEitan 很好,将图像标题置于图像之上。我在下面需要它。

标签: html jscript


【解决方案1】:

我建议换行:

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

到:

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

这确保&lt;div&gt; 始终附加在&lt;img&gt; 本身之后,无论它出现在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>

【讨论】:

  • 我不知道您可以将null 作为insertBefore 的第二个参数传递:) 很高兴学习新事物
  • 这是那些罕见的功能之一,在预期无意的潜在错误时似乎经过深思熟虑:)
  • 感谢您的出色建议。我在使用 javascript 的第一周,但最多仍然感到困惑。
  • 如果你可以使用Element.append(),那么你可能也可以使用ChildNode.after()
【解决方案2】:

你需要使用图片的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)
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2010-09-24
    • 2015-05-03
    • 1970-01-01
    • 2016-06-25
    • 2018-10-25
    • 2020-12-07
    相关资源
    最近更新 更多