如何以编程方式选择一个选项从chrome扩展内容脚本的select2

How to programmatically select an option in select2 from chrome extension content script?

本文关键字:扩展 chrome 选项 select2 脚本 一个 编程 方式 选择      更新时间:2023-09-26

我在StackOverflow上尝试了所有的答案。但是,我似乎无法通过编程方式根据选项的值选择选项。

我这样做从一个内容脚本在Chrome扩展->不知道如果这改变了什么。

我的代码如下:

chrome.runtime.onMessage.addListener(
  function(response, sender, sendResponse){
    if (typeof response === 'string' || response instanceof String){
        var dropdown = false;
        if ((document.getElementById(response)).nodeName == 'SELECT'){
            //console.log('im here');
            dropdown = true;
            var options = $('#' + response).find('option');
            var random_num = ~~((Math.random() * (options.length - 1)) + 1 );
            var radnom_option = options[random_num];
            var value = radnom_option.value;
            var slctr = ('#' + response);
            /*
              I thought that the next two lines would change the selected option.
            */
            $(slctr).val(value); 
            $(slctr).trigger('change.select2');
            console.log($(slctr));
            console.log(options);
            console.log(random_num);
            console.log(radnom_option);
            console.log(value);
            console.log(slctr);
        }
        dropdown = true;
        sendResponse(dropdown);
    }
});

当它运行时,控制台显示:

[select#entity_email_1_createPersonEmailType.form-control.entity_email.select2.required, context: document, selector: "#entity_email_1_createPersonEmailType"]
[option, option#option_business, option#option_other, option#option_personal, option#option_school, prevObject: init[1], context: document, selector: "#entity_email_1_createPersonEmailType option"]
2
<option id="option_other" data-option-id="option_other" value="916">Other</option>
916
#entity_email_1_createPersonEmailType

我想修改的那部分HTMl是:

<div
                                        class="col-md-12"
                                                    >
                        <div class="form-group formGroup">
                                        <label
                            class="control-label"
                                                            for="entity_email[1][quickAddPersonEmailType]"
                                                            >Email Type* </label>
                                    <select
                        placeholder=""
                        class="form-control  entity_email select2  required "
                                                    name="entity_email[1][email_type]"
                                                    id="entity_email_1_quickAddPersonEmailType"
                        title="Email Type"
                                                    data-field-suffix=""
                        data-field-name="email_type"
                        data-init-callback=""
                        data-field-alias="Email Type"
                        tabindex=""
                                                                                 data-field-required="entity_email"                                                                                                         >
                                                                                                                                                            <option data-option-id="option_empty" value="">Select</option>
    <option
    id="option_business"
    data-option-id="option_business"
    value="915"
    >Business</option>
        <option
    id="option_other"
    data-option-id="option_other"
    value="916"
    >Other</option>
        <option
    id="option_personal"
    data-option-id="option_personal"
    value="913"
    >Personal</option>
        <option
    id="option_school"
    data-option-id="option_school"
    value="914"
    >School</option>

这就是我对控制台的期望。但是,select元素仍然保留在第一个选项"select"。此外,当我尝试在StackOverflow上概述的方法,其中包括调用select2()函数时,有一个TypeError说明select2()函数没有定义。但是,如果HTML包含select2元素,怎么会出现这种情况呢?

我在这里做错了什么?是否存在其他方法能够实现能够选择特定选项的最终目标?例如,我是否可以删除所有选项,然后在更改默认值的同时再次添加它们?

任何帮助都将非常感激。提前感谢。

我知道这已经很长时间了,但我有同样的问题,并设法"解决"它,所以万一有人偶然发现这个…

为什么你突出显示的两行不改变选择值的原因,是因为Chrome扩展的内容脚本的沙箱性质。内容脚本不能访问页面作用域,因此它们根本不能访问其中定义的任何对象。这是谷歌出于安全考虑故意设计的行为,您可以在官方文档中阅读更多关于它的信息。

当您运行所包含的代码时,所触发的事件不会到达页面中声明的任何事件侦听器,因为jQuery和select2实例不一样,所以什么也没有发生,正如您注意到的那样。

如果您绝对需要,您可以通过创建一个<script>标记来绕过这个障碍,该标记带有一个立即调用的函数表达式(IIFE),用于触发,并将其插入DOM中。

使用JSX

const code = () => $('selector').val('some value').trigger('change.select2');
const script = <script>({code})();</script>;
document.body.appendChild(script);

如果您没有可用的JSX,您总是可以使用旧的方式:

var code = () => $('selector').val('some value').trigger('change.select2');
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ code +')();'));
document.body.appendChild(script);

如果您走这条路,请记住,在您包含在<script>标记中的函数内部,您不能访问来自内容脚本范围的变量,因为它将在页面范围内运行。由于这是您的用例,我可以看到两种方法来减轻这种情况,

  1. 将函数的所有代码放入字符串中,并传递该字符串字符串作为脚本的内容,如…
var code = `() => $('${slctr}').val(${value});.trigger('change.select2');`;
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ code +')();'));
document.body.appendChild(script);
  • 包括你需要的数据作为data-属性在脚本中,然后在函数中使用类似的东西拉数据例如script.getAttribute('data-selector'),其中script将插入HTMLScriptElement(您将需要一种方法来访问该节点)。
  • var code = () => {
        var script = document.getElementById('my-script-id');
        var selector = script.getAttribute('data-selector');
        var value = script.getAttribute('data-value');
        $(selector).val(value).trigger('change.select2');
    };
    var script = document.createElement('script');
    script.id = 'my-script-id';
    script.setAttribute('data-selector', selector);
    script.setAttribute('data-value', value);
    script.appendChild(document.createTextNode('('+ code +')();'));
    document.body.appendChild(script);
    

    这是非常丑陋和黑客,但真的没有其他办法。

    我想这已经表达了我的意思。好运。