javascriptoperauserscriptsopera-mobileselectors-api

querySelectorAll() not working in Opera Mobile 11.5?


I'm trying to remove elements from webpages that aren't essential using querySelectorAll, but this doesn't seem to work on Opera Mobile 11.5. I've tried the scripts out on my PC before I've put them on my phone.

Mozilla's documents are confusing, because there are two pages about this function and one says it's compatible and the other says it isn't.

Is there a solution to fix this? Will I need to implement other libraries into these scripts I've made?

Here's how I'd like to do it:

function deleteByCSS(el) {
 elem = document.body.querySelectorAll(el);
 for (i=0; i<elem.length; i++){
  elem[i].parentNode.removeChild(elem[i]);
 }
}
deleteByCSS("here goes every CSS selector pointing to objects I want to remove");

Solution

  • Several issues:

    1. Juan Mendes' answer is right about the deletion order. If you don't delete in reverse, not only will the JS be inefficient, but there is the real chance of the script crashing due to array values that are no longer valid. If the inefficient way appears to work once or twice, that is just luck.

    2. Additionally, nested nodes need to be factored in, note the extra check in the code below.

    3. The fact that the code appears to work for you outside the Opera, User JavaScript, suggests that the nodes you are using are added by page javascript/AJAX. Compensate with a timer or similar method.

    4. If still encountering difficulties, Link to the target page and post the exact CSS selectors you are attempting.

    5. Note that querySelectorAll() is compatible with Opera Mobile 11.5, and both of those pages either say so or show a question mark -- which does not mean it is not compatible, just that Mozilla did not test it (others have). Note that there is potentially a difference between document.querySelectorAll() and {element}.querySelectorAll(), hence the two pages.

    Putting it all together, code like this should work:

    function deleteByCSS (cssSelector, delayLoopMax, delayMilliSecs) {
        //-- Use defaults, if not specified.
        var delayLoopMax    = delayLoopMax   || 0;
        var delayMilliSecs  = delayMilliSecs || 300;
        //console.log ("Args: ", cssSelector, delayLoopMax, delayMilliSecs);
    
        var doomedElements  = document.body.querySelectorAll (cssSelector);
        if (doomedElements  &&  doomedElements.length) {
            //console.log ("Found!");
            //-- Found the node(s); delete it/them.
            for (var J = doomedElements.length - 1;  J >= 0;  --J) {
                var doomedNode  = doomedElements[J];
                if (doomedNode) {
                    doomedNode.parentNode.removeChild (doomedNode);
                }
            }
        }
        else {
            //-- Nodes not found. Wait for JS to add them, if specified.
            if (delayLoopMax > 0) {
                delayLoopMax--;
                setTimeout (
                    deleteByCSS,
                    delayMilliSecs,
                    cssSelector, delayLoopMax, delayMilliSecs
                );
            }
        }
    }
    


    In this case, use it with an initial extra parameter of 20...

    deleteByCSS ("*VALID* CSS selector", 20);