更改由AngularJs从Chrome内容脚本动态创建的包装选择的值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了更改由AngularJs从Chrome内容脚本动态创建的包装选择的值相关的知识,希望对你有一定的参考价值。

我正在开发自己使用的简单扩展。它的主要目标是基于预定义的选项动态填充表单。

当我尝试从我的内容脚本更新select元素时,它并没有真正更改所选的选项。选择框本身使用跨度集合包装在漂亮的UI中:

    <!-- Data with AngularJs bindings -->
<div class="ddOutOfVision" id="drpType_msddHolder" style="height: 0px; overflow: hidden; position: absolute;">
    <select id="drpType" name="Type" class="mobile100 ng-pristine ng-invalid ng-invalid-required" ng-model="Order.ccToAdd.Type" ng-change="change()" required="" tabindex="-1">
        <option value="" selected="">Please select  type</option>                             
        <option data-image="../icons/V.png" value="001">V</option>
        <option data-image="../icons/M.png" value="002">M</option>
        <option data-image="../icons/A.png" value="003">A</option>
        <option data-image="../icons/D.png" value="004">D</option>
    </select>
</div>

<!-- UI -->
<div class="dd ddcommon borderRadiusTp" id="drpType_msdd" tabindex="0" style="width: 100%;">
    <div class="ddTitle borderRadiusTp">
        <span class="divider"/>
        <span class="ddArrow arrowoff"/>
        <span class="ddTitleText " id="drpType_title">
            <span class="ddlabel">Please select type</span>
            <span class="description" style="display: none;"/>
        </span>
    </div>
    <input id="drpType_titleText" type="text" autocomplete="off" class="text shadow borderRadius" style="display: none;" />
    <div class="ddChild ddchild_ border shadow" id="drpType_child" style="z-index: 9999; position: absolute; visibility: visible; height: 168px; top: 33px; display: block;">
        <ul>
            <li class="enabled _msddli_ selected">
                <span class="ddlabel">Please select  type</span>
                <div class="clear"/>
            </li>
            <li class="enabled _msddli_">
                <img src="../icons/V.png" class="fnone" />
                <span class="ddlabel">V</span>
                <div class="clear"/>
            </li>
            <li class="enabled _msddli_">
                <img src="../icons/M.png" class="fnone" />
                <span class="ddlabel">M</span>
                <div class="clear"/>
            </li>
            <li class="enabled _msddli_">
                <img src="../icons/A.png" class="fnone" />
                <span class="ddlabel">A</span>
                <div class="clear"/>
            </li>
            <li class="enabled _msddli_">
                <img src="../icons/D.png" class="fnone" />
                <span class="ddlabel">D</span>
                <div class="clear"/>
            </li>
        </ul>
    </div>
</div>

我尝试了什么(它实际上并没有改变所选元素):

jQuery的

$("#drpType").val("001");
$("#drpType").val("001").change();
$("#drpType").val("001").trigger('input');
$("#drpType").val("001").trigger('input').change()

原生javascript

document.forms[0].elements[0].selectedIndex = 1;
document.forms[0].elements[0].options[2].selected = true

现代DOM选择器:

document.querySelector('#drpType [value="001"]').selected = true

甚至点击()而不是选择值...

补充说明:

  1. 在“run_at”加载的内容脚本:“document_end”
  2. 使用angularjs构建site并在文档准备好后动态创建这些元素,因此出于测试目的,我只是实现了一个等待以确保元素已经存在于DOM中。这是一个肮脏的黑客,但这不是讨论的对象。 setTimeout(function(){/ *我的代码在这里* /},8000);

更新我最终通过jQuery更改了底层数据选项和连接的UI选项的值,并且仅在Chrome开发人员模式中,通过以下代码:

$("#drpType option[value='001']").prop("selected", true).trigger('input').change()        

但这仅适用于开发人员控制台,而不适用于上下文脚本。有人知道为什么吗?

更新同时上面的改变价值的解决方案适用于Chrome控制台和Tampermonkey用户脚本,它不适用于我的扩展...

答案

最后,我设法解决了这个任务。在内容脚本中:

document.querySelector("#drpType option[value='001']").selected = true;
document.querySelector("#drpType").dispatchEvent(new Event('change', {bubbles: true}));

详细信息:由于上下文脚本在隔离环境中运行,我们需要手动触发事件,因此外部Web页面也可以触发所有订阅者。由于某种原因,jQuery更新和触发器调用不会触发全局DOM事件,对于这种情况,我必须手动创建并触发更新事件。

在这个答案中提到了更复杂的事件方法:https://stackoverflow.com/a/2856602/1187217

如果您需要它来完整地模拟真实事件,或者如果您通过html属性或addEventListener / attachEvent设置事件,则需要进行一些功能检测以正确触发事件:

if ("createEvent" in document) {
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("change", true, true);
    element.dispatchEvent(evt);
}
else
    element.fireEvent("onchange");

以上是关于更改由AngularJs从Chrome内容脚本动态创建的包装选择的值的主要内容,如果未能解决你的问题,请参考以下文章

数据表中的 Angularjs 和动态 html 内容

如何使用 Chrome DevTools 在 AngularJS 异常中暂停脚本执行?

如何更改由背景颜色确定的文本颜色?

更改由 Maven 解包的源的权限?

更改由 ng-repeat 生成的 textareas 的值

如何更改由 django 表单类创建的输入文本字段的边框半径?