更改由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
甚至点击()而不是选择值...
补充说明:
- 在“run_at”加载的内容脚本:“document_end”
- 使用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内容脚本动态创建的包装选择的值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Chrome DevTools 在 AngularJS 异常中暂停脚本执行?