I have a userscript (Tampermonkey in Chrome) which runs either when the page is opened by the user, or which may open the page in a separate window (where the concerned script then runs). When the page is opened by the user, everything works as expected.
However, when the page is opened in another window, this function sometimes does not process the text as expected.
Code:
function processTableRows() {
var regex = new RegExp(/(.*?)(\d{7})/);
var texts = document.querySelectorAll(".table__row");
var out = [];
texts.forEach(text=> {
var fixMonth = text.innerText.replace(/(\d*)月/, function(p1) {
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
return monthNames[(parseInt(p1) - 1)];
}).replace(regex,
"example.com/page.html?id=$2\n$1");
out.push(fixMonth);
});
return out;
}
Example page text (before script):
05 6月 2019 8989898
Some text
Some more text
When the user opens the page, both the userscript and the code in the console give the expected output:
example.com/page.html?id=8989898
05 Jun 2019
Some text
Some more text
However, when it is launched in a separate Window, it returns (Both TM script and console run):
05 Jun 2019
example.com/page.html?id=8989898
Some text
Some more text
I can't imagine for the life of me why the second replace()
seems to be functioning differently in a separate window. I thought it may be related to some of JavaScript's regex funkiness, e.g. moving an index, affecting the chained call, but MDN indicates it only returns a string.
EDIT: Further information obtained after the comments that were below:
When the page is launched in a new (popup) window, it is small and the original text renders like:
05 6月 2019
8989898
Some text
Some more text
However, when the window is larger (as when the user visits it), it looks like:
05 6月 2019 8989898
Some text
Some more text
In general, if the same userscript gives different results -- on the same page -- depending on how that page is opened, the causes can be:
Timing. The page loads slower or faster depending on various factors, frequently caching. So the script may fire before the content it seeks is present/finished.
Use waitForKeyElements
or MutationObserver
to compensate. Search around for previous questions where this has been covered.
AJAX. The page is not actually doing a normal HTML load, but is using javascript to (re)write a "new" page.
Again, waitForKeyElements
or MutationObserver
are helpful against such pages. And, again, covered in previous questions.
"Responsive" layout/behaviors. The same page may display different content, and/or in a different ways depending on window size (typically) or some state tracking or some passed-in parameters.
In such a case, your script may need logic code to adapt to different variants of the page.
Code that is sensitive to rendering. If your script relies on positioning, CSS style, element sizes, etc.; it may break merely when the window is a different size, or when the page takes different times to render.
In this case, the question code appears to have a variant of reason 4. It uses innerText
and innerText varies its results depending on whitespace and visibility. (innerText is also slower than textContent
.)
The solution is to use textContent
instead of innerText
.
Here's a demo showing how the two properties can differ:
srcNode = $(".variableDiv")[0];
$("#TC").text (srcNode.textContent);
$("#IT").text (srcNode.innerText);
.variableDiv {border: 1px solid gray; margin-bottom: 1em;}
td, th {border: 1px solid gray; padding: 0.2ex 1ex;}
table {border-collapse: collapse;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Source Div:
<div class="variableDiv">
Chuck Norris has two speeds: <br> Walk, and Kill.<br>
<span style="display:none">Hidden Text</span>
</div>
<table>
<tr> <th>textContent</th> </tr>
<tr> <td><pre id="TC"> </pre></td> </tr>
<tr> <th>innerText</th> </tr>
<tr> <td><pre id="IT"> </pre></td> </tr>
</table>
IIRC, different browsers might also vary innerText's results on hidden overflow and/or occluding elements, but I haven't verified that.