onclick or inline script isn't working in extension

前端 未结 5 1112
渐次进展
渐次进展 2020-11-21 04:57

This seems to be the easiest thing to do, but it\'s just not working. In a normal browser the .html and .js files works perfectly, but in the Chrome/Firefox extension the

相关标签:
5条回答
  • 2020-11-21 05:20

    I decide to publish my example that I used in my case. I tried to replace content in div using a script. My problem was that Chrome did not recognized / did not run that script.

    In more detail What I wanted to do: To click on a link, and that link to "read" an external html file, that it will be loaded in a div section.

    • I found out that by placing the script before the DIV with ID that was called, the script did not work.
    • If the script was in another DIV, also it does not work
    • The script must be coded using document.addEventListener('DOMContentLoaded', function() as it was told

          <body>
          <a id=id_page href ="#loving"   onclick="load_services()"> loving   </a>
      
              <script>
                      // This script MUST BE under the "ID" that is calling
                      // Do not transfer it to a differ DIV than the caller "ID"
                      document.getElementById("id_page").addEventListener("click", function(){
                      document.getElementById("mainbody").innerHTML = '<object data="Services.html" class="loving_css_edit"; ></object>'; });
                  </script>
          </body>
      
        <div id="mainbody" class="main_body">
              "here is loaded the external html file when the loving link will 
               be  clicked. "
        </div>
      
    0 讨论(0)
  • 2020-11-21 05:26

    As already mentioned, Chrome Extensions don't allow to have inline JavaScript due to security reasons so you can try this workaround as well.

    HTML file

    <!doctype html>
        <html>
            <head>
                <title>
                    Getting Started Extension's Popup
                </title>
                <script src="popup.js"></script>
            </head>
            <body>
                <div id="text-holder">ha</div><br />
                <a class="clickableBtn">
                      hyhy
                </a>
            </body>
        </html>
    <!doctype html>
    

    popup.js

    window.onclick = function(event) {
        var target = event.target ;
        if(target.matches('.clickableBtn')) {
            var clickedEle = document.activeElement.id ;
            var ele = document.getElementById(clickedEle);
            alert(ele.text);
        }
    }
    

    Or if you are having a Jquery file included then

    window.onclick = function(event) {
        var target = event.target ;
        if(target.matches('.clickableBtn')) {
            alert($(target).text());
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:35

    Chrome Extensions don't allow you to have inline JavaScript (documentation).
    The same goes for Firefox WebExtensions (documentation).

    You are going to have to do something similar to this:

    Assign an ID to the link (<a onClick=hellYeah("xxx")> becomes <a id="link">), and use addEventListener to bind the event. Put the following in your popup.js file:

    document.addEventListener('DOMContentLoaded', function() {
        var link = document.getElementById('link');
        // onClick's logic below:
        link.addEventListener('click', function() {
            hellYeah('xxx');
        });
    });
    

    popup.js should be loaded as a separate script file:

    <script src="popup.js"></script>
    
    0 讨论(0)
  • 2020-11-21 05:37

    I had the same problem, and didn´t want to rewrite the code, so I wrote a function to modify the code and create the inline declarated events:

    function compile(qSel){
        var matches = [];
        var match = null;
        var c = 0;
    
        var html = $(qSel).html();
        var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;
    
        while (match = pattern.exec(html)) {
            var arr = [];
            for (i in match) {
                if (!isNaN(i)) {
                    arr.push(match[i]);
                }
            }
            matches.push(arr);
        }
        var items_with_events = [];
        var compiledHtml = html;
    
        for ( var i in matches ){
            var item_with_event = {
                custom_id : "my_app_identifier_"+i,
                code : matches[i][5],
                on : matches[i][3],
            };
            items_with_events.push(item_with_event);
            compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
        }
    
        $(qSel).html(compiledHtml);
    
        for ( var i in items_with_events ){
            $("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
                eval(items_with_events[i].code);
            });
        }
    }
    
    $(document).ready(function(){
        compile('#content');
    })
    

    This should remove all inline events from the selected node, and recreate them with jquery instead.

    0 讨论(0)
  • 2020-11-21 05:43

    Reason

    This does not work, because Chrome forbids any kind of inline code in extensions via Content Security Policy.

    Inline JavaScript will not be executed. This restriction bans both inline <script> blocks and inline event handlers (e.g. <button onclick="...">).

    How to detect

    If this is indeed the problem, Chrome would produce the following error in the console:

    Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

    To access a popup's JavaScript console (which is useful for debug in general), right-click your extension's button and select "Inspect popup" from the context menu.

    More information on debugging a popup is available here.

    How to fix

    One needs to remove all inline JavaScript. There is a guide in Chrome documentation.

    Suppose the original looks like:

    <a onclick="handler()">Click this</a> <!-- Bad -->
    

    One needs to remove the onclick attribute and give the element a unique id:

    <a id="click-this">Click this</a> <!-- Fixed -->
    

    And then attach the listener from a script (which must be in a .js file, suppose popup.js):

    // Pure JS:
    document.addEventListener('DOMContentLoaded', function() {
      document.getElementById("click-this").addEventListener("click", handler);
    });
    
    // The handler also must go in a .js file
    function handler() {
      /* ... */
    }
    

    Note the wrapping in a DOMContentLoaded event. This ensures that the element exists at the time of execution. Now add the script tag, for instance in the <head> of the document:

    <script src="popup.js"></script>
    

    Alternative if you're using jQuery:

    // jQuery
    $(document).ready(function() {
      $("#click-this").click(handler);
    });
    

    Relaxing the policy

    Q: The error mentions ways to allow inline code. I don't want to / can't change my code, how do I enable inline scripts?

    A: Despite what the error says, you cannot enable inline script:

    There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes 'unsafe-inline' will have no effect.

    Update: Since Chrome 46, it's possible to whitelist specific inline code blocks:

    As of Chrome 46, inline scripts can be whitelisted by specifying the base64-encoded hash of the source code in the policy. This hash must be prefixed by the used hash algorithm (sha256, sha384 or sha512). See Hash usage for <script> elements for an example.

    However, I do not readily see a reason to use this, and it will not enable inline attributes like onclick="code".

    0 讨论(0)
提交回复
热议问题