获取包含属性的开始标记 - 没有innerHTML的outerHTML

时间:2012-03-07 15:25:03

标签: javascript jquery dom innerhtml outerhtml

我想从DOM中检索某个带有其属性的标记元素。例如,来自

<a href="#" class="class">
  link text
</a>

我想得到<a href="#" class="class">,可选择关闭</a>,作为字符串或其他对象。 在我看来,这类似于在没有.outerHTML的情况下检索.innerHTML

最后,我需要通过jQuery包装其他一些元素。我试过了

var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem);

.get()返回包含其内容的DOM元素。还

var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem.tagName).parent().attr(elem.attributes);

失败,因为elem.attributes返回NamedNodeMap,这与jQuery的attr()不起作用,我无法转换它。 承认上面的例子不是很有意义,因为它们还复制了元素的不再唯一ID。但有什么简单的方法吗?非常感谢。

9 个答案:

答案 0 :(得分:15)

对于未来的Google员工,有一种方法可以在没有jQuery的情况下执行此操作:

tag = elem.outerHTML.slice(0, elem.outerHTML.indexOf(elem.innerHTML));

由于outerHTML包含开始标记,后面跟着innerHTML包含的镜像,我们可以将outerHTML从0(开头标记的开头)子串到其中innerHTML开始(开始标记的结尾),并且由于innerHTML是outerHTML的镜像,除了开始标记之外,只剩下开始标记!

此版本适用于<br>代码,<meta>代码和其他空标记:

tag = elem.innerHTML ? elem.outerHTML.slice(0,elem.outerHTML.indexOf(elem.innerHTML)) : elem.outerHTML;

由于innerHTML在自闭标记中为空,而indexOf('')始终返回0,因此上述修改首先检查是否存在innerHTML

答案 1 :(得分:4)

var wrapper = $('.class').clone().attr('id','').empty();
  • 您可能希望更改选择器以更精确地匹配您正在寻找的<a>元素。
  • clone()创建匹配元素的新副本,也可以选择复制事件处理程序。
  • 我使用attr清除元素的ID,以便我们不会重复ID。
  • empty()删除所有子节点(“innerHTML”)。

答案 2 :(得分:1)

这是我的解决方法:

opentag=elem.outerHTML.slice(0, elem.outerHTML.length-elem.innerHTML.length-elem.tagName.length-3);

我想,关闭标签的格式为:"</"+elem.tagName+">"

答案 3 :(得分:1)

这是我使用过的解决方案:

const wrap = document.createElement('div')
wrap.appendChild(target.cloneNode(true))
const openingTag = wrap.innerHTML.split('>')[0] + '>'

答案 4 :(得分:0)

不幸的是,@AaronGillion's answer并不可靠,就像我在a comment中所说的那样。感谢@sus。我建议对his/her way进行一些改动以支持<self-closing tags />

function getOpenTag(element: HTMLElement): string {
    const outerHtml = element.outerHTML;
    const len = outerHtml.length;

    const openTagLength = outerHtml[len - 2] === '/' ? // Is self-closing tag?
            len :
            len - element.innerHTML.length - (element.tagName.length + 3);
    // As @sus said, (element.tagName.length + 3) is the length of closing tag. It's always `</${tagName}>`. Correct?

    return outerHtml.slice(0, openTagLength);
}

代码在Typescript中。如果需要纯Javascript,则删除类型(HTMLElementnumber)。

答案 5 :(得分:0)

这可以在没有任何String操作的情况下完成。

相反,您可以使用元素的内部构造,并从那里自己构建字符串:

function getTagHTML(el) {
  if (!el instanceof HTMLElement) return null;
  let result = `<${el.tagName.toLowerCase()}`;
  for (const attribute in el.attributes) {
    if (el.attributes[attribute].nodeValue) 
      result += ` ${el.attributes[attribute].name}="${el.attributes[attribute].nodeValue.replace(/"/g, "&quot;")}"`
  }
  result += `></${el.tagName.toLowerCase()}>`;
  return result;
}

console.log(getTagHTML(document.getElementById('outer')));
<div id="outer" class='i-want-"this"'>
  <span>I do not want this</span>
</div>

请注意,对于<img />之类的自闭合元素,这会给您带来不必要且错误的结束标记。随意调整代码。

答案 6 :(得分:0)

如果某人没有使用jQuery。 。

elem.outerHTML
"<a href="#" class="class">
  link text
</a>"
elem.cloneNode().outerHTML
"<a href="#" class="class"></a>"

如果您想保护2014年中之前发布的Firefox等安全,请使用cloneNode(false)避免获取内部内容。

参考:https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode

答案 7 :(得分:0)

+1 为上面的 cloneNode 答案

  • 创建没有内容的 HTML
  • 循环属性
  • 可选结束标记
  • 可选的自闭合标签

function getTagHTML(el, includeClosingTag=true , selfClosing = false) {
  //return el.cloneNode(false).outerHTML;
  if (el.attributes)
    return `<${el.localName}` + 
      [...el.attributes].map(
             attr => ` ${attr.name}="${attr.nodeValue.replace(/"/g, "&quot;")}"`
      ).join`` +
      `${selfClosing ? "/" : ""}>` + 
      (!selfClosing && includeClosingTag ? `</${el.localName}>` : "");
  else 
    return null;
}

document.body.querySelectorAll("*:not(script)").forEach(el=>{
  console.log(getTagHTML(el));
  console.log(getTagHTML(el,false));
  console.log(getTagHTML(el,false,true))
});
<div id="ONE" class='CLASSNAMES' attr1='"string"'>
   INNERHTML
  </div>
  <img id="TWO" src="https://svgshare.com/i/Uhq.svg"/>

答案 8 :(得分:0)

我的解决方案使用 Reg Exp 替换元素属性中所有可能的结束标记:

const outerHTML = div.outerHTML;
const content = outerHTML.slice(0, outerHTML.length - div.innerHTML.length);
const dummy = content.replace(/'.*?'|".*?"/g, x => 'x'.repeat(x.length));
return content.slice(0, 1 + dummy.indexOf('>'));