1

I'm trying to access the appsTableData variable of the following page:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <!-- some css and metadata -->
    <script type="text/javascript" src="/static/jquery/jquery-1.8.2.min.js">
    </script>
    <script type="text/javascript" src="/static/jquery/jquery-ui-1.9.1.custom.min.js">
    </script>
    <script type="text/javascript" src="/static/dt-1.9.4/js/jquery.dataTables.min.js">
    </script>
    <script type="text/javascript" src="/static/yarn.dt.plugins.js">
    </script>
    <script type="text/javascript">
        $( function () {
            $( '#nav' ).accordion( {autoHeight: false, active: 0} );
            appsDataTable = $( '#apps' ).dataTable( {
                bStateSave: true, "fnStateSave": function ( oSettings, oData ) {
                    data = oData.aoSearchCols;
                    for( i = 0; i < data.length; i++ ) {
                        data[i].sSearch = ""
                    }
                    sessionStorage.setItem( oSettings.sTableId, JSON.stringify( oData ) );
                }, "fnStateLoad": function ( oSettings ) {
                    return JSON.parse( sessionStorage.getItem( oSettings.sTableId ) );
                }, bJQueryUI: true, sPaginationType: 'full_numbers', iDisplayLength: 20, aLengthMenu: [20, 40, 60, 80, 100], 'aaData': appsTableData, bDeferRender: true, bProcessing: true
                , aoColumnDefs: [
                    {'sType': 'string', 'aTargets': [0], 'mRender': parseHadoopID}
                    , {'sType': 'numeric', 'aTargets': [5, 6], 'mRender': renderHadoopDate}
                    , {'sType': 'numeric', bSearchable: false, 'aTargets': [9], 'mRender': parseHadoopProgress}], aaSorting: [[0, 'desc']]
            } ).fnSetFilteringDelay( 188 );
        } );
    </script>
    <div id="jsnotice" class="ui-state-error">
        This page will not function without javascript enabled. Please enable javascript on your browser.
    </div>
    <script type="text/javascript">
        $( '#jsnotice' ).hide();
    </script>
    </div>
    <table id="apps">
        <thead>
            <tr>
                <th class="id">
                    ID
                </th>
                <!-- etc -->
            </tr>
        </thead>
        <script type="text/javascript">
            var appsTableData = [ /*some array*/ ];
        </script>
        <tbody>
        </tbody>
    </table>
    </td>
    </tr>
    </tbody>
    </table>
</html>

However, I cannot get to catch its value with the following GM code:

// ==UserScript==
// @name        ...
// @namespace   ...
// @description ...
// @include     ...
// @updateURL   ...
// @downloadURL ...
// @version     2
// @grant       GM_getValue
// ==/UserScript==

document.body.onload = function() {
    console.log(GM_getValue("appsTableData", []));
}

My real code uses document.body.onload but not the timeout. The reason for using this callback is that the table gets constructed by jquery.dataTables.min.js from appsTableData when loading the page, so I need to execute my code after this. I have a working code that modifies some stuff in the table, so it does mean the jQuery has run when my script gets executed. However, GM_getValue("appsTableData", []) still yields undefined.

I'm guessing it's a scoping issue, but I still find this odd since this is the purpose of GM_getValue. Any idea to fix this ?

Dici
  • 25,226
  • 7
  • 41
  • 82
  • use your user script to inject a plain external script you can easily debug and edit. once it's working, only then, should you move the code into the actual user script. – dandavis Jul 06 '16 at 18:57
  • Well, the following, very straightforward script works as an external script added at the very end of the file: `console.log(appsTableData")`, so I would expect my GM script to also be able to access it – Dici Jul 06 '16 at 19:01
  • it depends on the timing. GM can run early to alter things that happen while the page is loaded. – dandavis Jul 06 '16 at 19:03
  • Note sure it's a duplicate since it does not explain why `GM_value` did not work. Voting to reopen to see if someone can answer to that bit since I already found a workaround but not a root cause to the problem – Dici Jul 06 '16 at 20:26
  • If that's your answer, below, it is a duplicate. Although it's a bit of a non sequitur from the question. ... Otherwise, you need to provide enough info to replicate the problem. Provide everything listed in step 6 of [this answer](http://stackoverflow.com/a/31086018/). ... In current Firefox and current GM, your original code returns an empty array (`[]`), as expected. HOWEVER, arrays are not a valid type for `GM_getValue` and `GM_setValue`. They must be JSON encoded. ... You might have inadvertently stored the *string* `"undefined"`? – Brock Adams Jul 06 '16 at 21:09
  • I'm not in control of the HTML page I apply my GM script, otherwise I would not write a GM script to begin with. You're right about `GM_setValue`, I just found out that this does not support arrays. Fair enough, I did not see this in the doc at first. Cheers :p – Dici Jul 06 '16 at 22:24

1 Answers1

0

Found a solution, leaving an answer for posterity. I found that you can access the window object of the page by using unsafeWindow. You also have to @grant it to your script:

// ==UserScript==
// @name        ...
// @namespace   ...
// @description ...
// @include     ...
// @updateURL   ...
// @downloadURL ...
// @version     2
// @grant       unsafeWindow
// ==/UserScript==

document.body.onload = function() {
    console.log(unsafeWindow.appsTableData);
}
Dici
  • 25,226
  • 7
  • 41
  • 82