I'm trying to write a Tampermonkey script to extend a commercial web application I use. In a very basic sense, some URL appears on the page and I need to extract a number from the URL and then use that number to build a new link and append it to the parent element.
So far I have this but it doesn't work when I click on the element (pagination is just UL) or when the document loads. I know the function works as if I set it to run when I click anywhere in the document it works. When JS reports that a page has loaded, it's almost like the page hasn't fully loaded yet.
(function() { 'use strict'; //get the pagination element var element = document.getElementsByClassName('pagination-sm'); element.onclick = createLinks; document.onload = createLinks; function createLinks() { var links = document.querySelectorAll ("a[href*='/Field/POPendingCreate/']"); for (var J = links.length-1; J >= 0; --J) { var thisLink = links[J]; console.log(thisLink.href); var ppon = thisLink.href.match(/\d+/)[0]; console.log(ppon); var a = document.createElement('a'); var linkText = document.createTextNode("Preview Order"); a.appendChild(linkText); a.title = "Preview Order"; a.href = "https://website.com/Field/DownloadPendingPO?POPPKeyID=" + ppon + "&co=1&po=" + ppon; a.target = "_blank"; var parentNode = thisLink.parentNode; console.log(parentNode); parentNode.appendChild(a); } } })();
The UL element looks like this:
<ul uib-pagination="" items-per-page="formData.itemPerPage" class="pagination-sm ng-pristine ng-untouched ng-valid ng-scope ng-isolate-scope pagination ng-not-empty" data-total-items="pendingList.length" data-ng-model="formData.currentPage" data-max-size="10" data-ng-if="!attachmentView && filteredDocuments.length > 0" role="menu"><!-- ngIf: ::boundaryLinks --> <!-- ngIf: ::directionLinks --><li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev ng-scope disabled"><a href="" ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle="" class="ng-binding" disabled="disabled" tabindex="-1">Previous</a></li><!-- end ngIf: ::directionLinks --> <!-- ngRepeat: page in pages track by $index --><li role="menuitem" ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page ng-scope active"><a href="" ng-click="selectPage(page.number, $event)" ng-disabled="ngDisabled&&!page.active" uib-tabindex-toggle="" class="ng-binding">1</a></li><!-- end ngRepeat: page in pages track by $index --> <!-- ngIf: ::directionLinks --><li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next ng-scope disabled"><a href="" ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle="" class="ng-binding" disabled="disabled" tabindex="-1">Next</a></li><!-- end ngIf: ::directionLinks --> <!-- ngIf: ::boundaryLinks --> </ul>
As I said above, when I set it to run when I click anywhere on the document, the function works as expected. What confuses me even more is that it doesn't work when using document.onload. It's like the page only starts loading data after I start interacting with it. The reason I'm trying to run the function when pagination is clicked is because the page seems to get all the data and store it somewhere (that I can't see) and then just flick the page when pagination is clicked. So I do need to run the function on the generated link on the new page once pagination is clicked.
It seems like I need to delay running document.onload or some other way to understand after the document data is loaded and figure out why it doesn't run when the UL pagination element is clicked?
P粉1229324662023-09-16 09:08:56
Instead of waiting for the page to render and then looping through all elements to append anchor tags. Just use a MutationObserver to handle any elements that are rendered after running your logic.
JS
(function() { 'use strict'; const createLinks = function ( nodeElement ){ const queryElem = nodeElement.parentElement || nodeElement; const links = queryElem.querySelectorAll("a[href*='/Field/POPendingCreate/']"); for ( const link of links || [] ){ // Skip link if Preview has been attached if ( link.createLinkReady ) continue; // Get numbers from link href const [ ppon ] = link.href.match(/\d+/); // Create an anchor tag const a = document.createElement('a'); a.innerHTML = 'Preview Order'; a.setAttribute( 'title', 'Preview Order' ); a.setAttribute( 'href', `https://website.com/Field/DownloadPendingPO?POPPKeyID=${ppon}&co=1&po=${ppon}` ); a.setAttribute( 'target', '_blank' ); a.setAttribute( 'rel', 'nofollow' ); // Append anchor tag to parent element link.parentElement.appendChild( a ); link.createLinkReady = true; } } // Create DOM MutationObserver const Observer = new MutationObserver( function( mutationsList ) { // Loop through mutations for ( const mutation of mutationsList || [] ) { // Loop through added nodes for ( const node of mutation.addedNodes || [] ){ // Run createLinks on node createLinks( node ); } } }); // Observe DOM for new elements starting from document.body Observer.observe( document.body, { childList:true, subtree:true } ); // Process links that have been rendered createLinks( document.body ); })();