Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting <option> of a <select> from a Chrome extension content script

I'm hopelessly trying to activate a change() event from a Chrome content script. I've gone past through of the web site and Google posts, but still nothing works.

Here's a description of what I'm trying to achieve;

Consider the following web page (reachable via http://www.gilzu.com/TFF/select.html should someone be so kind to help):

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Untitled Page</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $('#woot').die('change');
            $('#woot').live('change', function () {
                $('#description').text(jQuery('#woot').val());
                });
            console.log("window ready");       
        
            
            $("#meh").click(function() {
                $('#woot').val(15);
                $('#woot').change();
            });
            
            $('#woot').val(21);
            $('#woot').change();
        });
    </script>
</head>
<body>
    <p>
        <select id="woot">
            <option id="Option1" value="15">a</option>
            <option id="Option2" value="16">b</option>
            <option id="Option3" value="17">c</option>
            <option id="Option4" value="18">d</option>
            <option id="Option5" value="19">e</option>
            <option id="Option6" value="20">f</option>
            <option id="Option7" value="21">g</option>
        </select>
    </p>
    
    <p id="description"></p>
    <p><input type="button" id="meh" /></p>
</body>
</html>

What DO work:

  1. on startup the change() fires up and updates the selection box to 21 and shows right value on the div.
  2. pressing on the button #meh, changes the selection box to 15, triggers the change() event that shows the right value on the screen.

No surprise so far.

So I'm heading to the content script via:

$(document).ready(function () {
                $('#woot').val(17);
                $('#woot').change();
                });

so the select tag updates, but the change() event does not trigger.

I've read the forum about Chrome's extension isolated worlds and put this theory to the test:

$(document).ready( function() {
    $("#meh").click();
});

and it in fact triggers both the click event AND the change event of the select box!

Also, to contradict another post claiming that code injection of the js works:

$(document).ready( function() {
    var x = $("<script type='text/javascript' />");
    $(x).text("$('#woot').val(18); $('#woot').change();");
    $("head").append(x);        
});

Issues the same effect: select box updates but change event does not fire.

I've also tried the following:

  1. creating a button such as the example's #meh with an attached click event that triggers the select tag's change(). only the select updates, no event fires.
  2. changing the value of the select box via attr(), prop(), val() only the select updates, no event fires.
  3. firing the event via change(), trigger('change') and selectedIndex only the select updates, no event fires.
  4. delaying the command via js
  5. using focus() another control, this control or even blur() the select box as some posts suggest.

your help will be most appreciated

like image 800
gilzu Avatar asked Jul 08 '12 13:07

gilzu


2 Answers

I dont really know JQuery, but here's how to do it without JQuery and without injecting anything into the page....

var selections = document.querySelector('#woot');

selections.value = 17;

var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", true, true);
selections.dispatchEvent(evt);
like image 194
PAEz Avatar answered Nov 18 '22 19:11

PAEz


You can append a script. It'll take a lot of script appends but you can always put a custom communication event, and only inject one good script listening to that custom event and eval()ing the event data. It will work if there's no CSP.

var RunInThisContext = function(c){ try{
    var code = document.createTextNode(c);
    var script = document.createElement('script');
    script.type='text/javascript';
    script.language='javascript';
    script.appendChild(code);
    try{document.body.appendChild(script);}catch(e){document.head.appendChild(script);}

}catch(e){ console.error('ERROR: '+e); }}; 

Use like this:

RunInThisContext('('+(function(){ 
     $('select').change();
}).toString()+'()); '); 

But bear in mind you're running this directly into the page. If page doesn't have jQuery you'll have to include it first.

like image 27
Silviu-Marian Avatar answered Nov 18 '22 20:11

Silviu-Marian