我正在开发自己使用的简单扩展。它的主要目标是基于预定义的选项动态填充表单。
当我尝试从内容脚本更新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
甚至点击()而不是选择\值...
附加说明:
使用angularjs构建网站,并在文档准备好后动态创建这些元素,因此出于测试目的,我已经 只是实现了等待,以确保元素已经存在 在DOM中。这是一个肮脏的黑客,但这不是一个对象 讨论
setTimeout(function(){/ *我的代码在这里* /},8000);
更新 我最终通过jQuery更改了底层数据选项和连接的UI选项的值,并且仅在Chrome开发人员模式中,通过以下代码:
$("#drpType option[value='001']").prop("selected", true).trigger('input').change()
但仅适用于开发者控制台,而不适用于上下文脚本。有人知道为什么吗?
更新 同时上面的改变价值的解决方案适用于Chrome控制台和Tampermonkey用户脚本,它不适用于我的扩展...
答案 0 :(得分:2)
最后,我设法解决了这个问题。在内容脚本中:
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");