【问题标题】:How to programmatically select an option in select2 from chrome extension content script?如何以编程方式从 chrome 扩展内容脚本中选择 select2 中的选项?
【发布时间】:2017-12-03 14:18:29
【问题描述】:

我已经尝试了 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>

这就是我对控制台的期望。但是,选择元素仍然保留在第一个选项“选择”中。此外,当我尝试 StackOverflow 上概述的一种方法时,其中包括调用 select2() 函数,有一个 类型错误 说未定义 select2() 函数。但是,如果 HTML 包含 select2 元素,怎么会是这样呢?

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

任何帮助将不胜感激。提前致谢。

【问题讨论】:

  • 这是错字吗? radnom_option
  • don't know if that changes anything - 使用 debugger - 在 Sources devtools 面板上选择 Content scripts。
  • edit您的问题包括您尝试对其执行更改的 HTML。
  • @will,它看起来像 typeo,但在整个代码中始终使用radnom_option。代码中不存在文字random_option
  • @Makyen,是的,我知道,这就是为什么我以问题的形式来表达它。 :D

标签: javascript jquery google-chrome-extension html-select


【解决方案1】:

我知道这已经很长时间了,但我遇到了同样的问题并设法“解决”了它,所以以防万一其他人偶然发现这个......

之所以突出显示的两行不会更改选择的值,是因为 Chrome 扩展程序内容脚本的沙盒特性。内容脚本无法访问页面范围,因此它们根本无法访问其中定义的任何对象。这是 Google 出于安全原因有意包含的行为,您可以在官方文档中阅读更多相关信息。

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

如果您绝对需要,您可以通过创建一个带有立即调用函数表达式 (IIFE) 的 &lt;script&gt; 标记来绕过这个障碍,然后将其插入 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);

如果您走这条路,请记住,在您包含在&lt;script&gt; 标记中的函数内部,您无法访问内容脚本范围内的变量,因为它将在页面范围内运行。由于这是您的用例,我可以看到两种缓解这种情况的方法,

  1. 将函数的所有代码放在一个字符串中,然后传递 字符串作为脚本的内容,类似于...
var code = `() => $('${slctr}').val(${value});.trigger('change.select2');`;
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ code +')();'));
document.body.appendChild(script);
  1. 将您需要的数据作为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);

这非常丑陋和骇人听闻,但实际上没有其他方法可以解决它。

我认为这可以理解。祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-08
    • 2023-03-21
    • 1970-01-01
    • 2016-02-24
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多