Peter
Peter

Reputation: 95

getElementsByName fails but getElementById works Chrome Extension

Using either document.getElementsByName('spanName') or jQuery('[name="spanName"]') fails (returning []) when called from within a Chrome extension (or console). However, document.getElementById('spanId') works, as does a CCS selector on a class name.

The span is already part of the DOM, prior to any intervention by the extension. However, the name attribute was added by the extension, the style attribute was modified, and a class name was added:

Original:

<div id="parentDiv">
    <span style="background-color:Yellow">Some highlighted text</span>
</div>

Updated:

<div id="parentDiv">
    <span id"spanId" name="spanName" class="highlighted" style="">Some highlighted text</span>
</div>

In addition, at one point the entire parentDiv's innerHTML is replaced and the spans are transferred

let spanNodeList = ...
let newInnerHTML = ...
let patterns = ...

for (let i = 0; i < spanNodeList.length; i++) {
    newInnerHTML.replace(patterns[i], spanNodeList[i].outerHTML)
}

document.getElementById('parentDiv').innerHTML = newInnerHTML

I am performing this transfer before adding the name attribute. Could this innerHTML replacement be the source of my woes?

By the Way...

I'm updating the spans with:

let spans = document.getElementsByTagName('span')
spans[Symbol.Iterator] = [][Symbol.Iterator]

for (let span of spans) {
   if (!/yellow/i.test(span.style.CSSText) continue;
   span.style.CSSText = ''
   span.id = <uniqueSpanId>
   span.name = 'spanName'
   span.className = "highlighted'
}

Upvotes: 1

Views: 1220

Answers (2)

Mike Gashler
Mike Gashler

Reputation: 669

My testing agrees that:

document.getElementsByName(name) does not work from chrome extensions,

but

document.getElementById(id) works, and
document.getElementsByTagName(name) works too.

If you really need to use getElementsByName, a possible solution may be to inject a script into the page, like this:

function getEls() {
    // This should work when it runs in the original page
    let results = document.getElementsByName('spanname');

    // but we have to shuttle the results back to the content script
    document.body.setAttribute('data-myresults', my_encode(results));
}

// Runs "func" in the page we are attached to
function injectScript(func) {
    const codeString = '(' + func + ')();';
    const script = document.createElement('script');
    script.textContent = codeString;
    (document.head || document.documentElement).appendChild(script);
}

injectScript(getEls);

// then, after it has had enough time to asynchronously do the job...
let results = my_decode(document.body.getAttribute('data-myresults'));

(Also, you will have to write my_encode to convert your data to a string, and my_decode to do the opposite.)

Upvotes: 0

unpollo
unpollo

Reputation: 804

Per the spec, document.getElementsByName() returns an array of elements. You will either have to loop through the result or do document.getElementsByName('spanName')[0]

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByName

Upvotes: 1

Related Questions