Я много работаю в Salesforce, и у меня есть несколько страниц, с которыми я работаю регулярно, с очень длинными выпадающими списками (например, до 1000 вариантов), и я хотел создать решение для быстрой фильтрации, которое находит SELECT настраница, и добавляет к нему поле фильтра.(Подробнее об этом ниже)
SF использует IFRAME на большинстве всех внутренних страниц, и этот код НЕ будет выбирать объекты IFRAME со страницы.
document.getElementsByTagName('IFRAME')
возвращает 0 объектов, несмотря на то, что я могу посмотреть на исходный код страницы и увидеть IFRAME.Похоже, это не связано с какой-либо межсайтовой безопасностью, так как в моем тестировании вызов getElementsByTagName('IFRAME')
привел бы объект iframe в «плохую» исходную ситуацию, но попытка получить доступ к чему-либо внутри IFRAME не удалась.В этом случае он даже не получает IFRAME.
Путь к одному из SELECT, на который я хочу попасть, выглядит следующим образом:
html> body> div> div> section> div> force-aloha-page> div> iframe> html> body> div> p> select
Я думаю, что проблема связана с этим пользовательским тегом force-aloha-page
.Я пытался получить другие элементы внутри этого узла, но безуспешно.В одной из строк ниже он выводит HTML DOM пользовательского тега, который показывает IFRAME.
Это ошибка?Или ожидаемое поведение, при котором вы не можете обойти DOM внутри пользовательских тегов?
Я пробовал некоторые сценарии в консоли Chrome, но это не давало бы мне видимость этого тега.
- document.getElementsByClassName ("oneAlohaPage") [0] .childNodes.length
1
- document.getElementsByClassName ("oneAlohaPage") [0] .childNodes [0] .tagName
"FORCE-ALOHA-PAGE"
- document.getElementsByTagName ("FORCE-ALOHA-PAGE"). Длина
1
- document.getElementsByTagName("FORCE-ALOHA-PAGE") [0] .childNodes.length
0
- document.getElementsByTagName ("FORCE-ALOHA-PAGE") [0] .innerHTML
""
- typeof document.getElementsByTagName ("FORCE-ALOHA-PAGE") [0]
"object"
- document.getElementsByTagName ("FORCE-ALOHA-PAGE") [0]
<force-aloha-page data-data-rendering-service-uid="203" data-aura-rendered-by="505:0" force-alohapage_alohapage-host><div force-alohapage_alohapage class="iframe-parent slds-template_iframe slds-card"><iframe force-alohapage_alohapage height="100%" width="100%" scrolling="yes" allowtransparency="true" name="vfFrameId_1569557364522" title="Page Configuration" allowfullscreen="true" lang="en-US" allow="geolocation *; microphone *; camera *">…</iframe></div></force-aloha-page>
- document.getElementsByTagName ("FORCE-ALOHA-PAGE") [0] .parentNode
<div class="oneAlohaPage" data-aura-rendered-by="502:0" data-aura-class="oneAlohaPage">…</div>
- document.getElementsByTagName ("FORCE-ALOHA-PAGE") [0] .firstChild
null
- document.getElementsByTagName ("FORCE-ALOHA-PAGE")[0] .parentNode.firstChild
<force-aloha-page data-data-rendering-service-uid="203" data-aura-rendered-by="505:0" force-alohapage_alohapage-host>…</force-aloha-page>
Я попытался создать рекурсивный скрипт, который пытается получить все элементы путем обхода всех узлов и дочерних узлов, но по-прежнему не может попасть внутрьэтот пользовательский тег.
var allNodes = function(el) {
var a = [];
for(var i=0;i<el.childNodes.length;i++) {
a.push(el.childNodes[i]);
a = a.concat(allNodes(el.childNodes[i]));
}
return a;
};
var all = allNodes(document.body);
//The array will contain the 'force-aloha-page' element, but nothing inside it.
Есть ли какой-нибудь способ получить доступ к DOM внутри этих пользовательских тегов?
Текущее решение
Я создалЗакладка на основе JS в Chrome, чтобы добавить фильтр INPUT к любому SELECT на веб-странице, когда я нажимаю на закладку.Я проверил это на страницах с IFRAME, и, пока браузер доволен политикой происхождения, он работает.Это тестовая страница, которую я использовал, когда писал код закладки.
testpage1.html
<html>
<body>
<select>
<option value="1">1</option>
<option value="10">10</option>
<option value="2">2</option>
<option value="20">20</option>
</select>
<br /><br />
<select>
<option value="Apples">Apples</option>
<option value="Berries">Berries</option>
<option value="Candies">Candies</option>
<option value="Danishes">Danishes</option>
</select>
<br /><br />
<iframe src="testpage2.html"></iframe>
</body>
</html>
testpage2.html
<html>
<body>
<select>
<option value="3">3</option>
<option value="30">30</option>
<option value="4">4</option>
<option value="40">40</option>
</select>
<br /><br />
<select onchange="selectChange(this)">
<option value="Eclaires">Eclaires</option>
<option value="Frozen Custard">Frozen Custard</option>
<option value="Grapes">Grapes</option>
<option value="Heath Bar">Heath Bar</option>
</select>
<script type="text/javascript">
function selectChange(el) {
console.log("Select value: " + el.value);
}
</script>
</body>
</html>
Код закладки (минимизирован):
При использовании Chrome щелкните правой кнопкой мыши на панели закладок, Добавить страницу, задайте имя страницы, например «Выбор фильтров», затем очистите URL-адрес и введите его.
javascript:(function(){var selects=function(d){var a=[],s=d.getElementsByTagName('SELECT'),b=d.getElementsByTagName('IFRAME');for(var i=0;i<s.length;i++)a.push(s[i]);for(var i=0;i<b.length;i++){try{a=a.concat(selects(b[i].contentWindow.document));}catch(e){console.log(e);}}return a;},blink=function(els,i){if(i>=els.length)return;var el=els[i],s=el.style,t=200,nb='3px solid blue',eb=s.border+'';el.scrollIntoView();s.border=nb;setTimeout(function(){s.border=eb;},t);setTimeout(function(){s.border=nb;},t*2);setTimeout(function(){s.border=eb;if(confirm("This one?")){filter(el);}else{blink(els,i+1);}},t*3);},opt=function(v,t,p){var y=document.createElement('OPTION');y.value=v;y.text=t;p.appendChild(y);},filter=function(el){console.log('Filtering...');var d=document,c=d.createElement('INPUT'),o=[];c.type='text';c.placeholder='Filter list';c.style.width=el.style.width;c.style.display='block';el.parentNode.insertBefore(c,el);c.onkeyup=function(ev){var j=c.value+'',h=el.options,x=0;if(o.length==0){for(var e=0;e<h.length; e++){with(h[e]){o.push({'v':value,'t':text});}}}for(var g=h.length-1;g>=0;g--)el.remove(g);for(var i=0;i<o.length; i++){if(j.length==0){opt(o[i].v,o[i].t,el);}else{if(match(o[i].t,j)){if(x==0) opt('','',el);opt(o[i].v,o[i].t,el);x++;}}}if(x>0) el.options[0].text='<'+x+' Match(es) Found>';};},match=function(a,b){a=(a+'').toLowerCase();b=(b+'').toLowerCase();if(b.indexOf('*')<0){return a.indexOf(b)>=0;}else{var r='.*',c=b.split('*');for(var i=0;i<c.length;i++){r+='.*'+(c[i].length>0?'('+c[i]+')':'');}r+='.*';return (new RegExp(r)).test(a);}},d=document,s=selects(d),v=[];for(var i=0;i<s.length;i++){if (window.getComputedStyle(s[i]).display !== 'none') v.push(s[i]);}console.log('SELECTs: '+s.length);console.log('Visible SELECTs: '+v.length);blink(v,0);})();
Код закладки (меньше минус):
javascript:(function(){
//return an array of all selects in the main page or in iframes
var selects=function(d){
var a=[],
s=d.getElementsByTagName('SELECT'),
b=d.getElementsByTagName('IFRAME');
for(var i=0;i<s.length;i++)
a.push(s[i]);
for(var i=0;i<b.length;i++){
try{
a=a.concat(selects(b[i].contentWindow.document));
}catch(e){
console.log(e);
}
}
return a;
},
//makes the SELECT border blink and scrolls it into view
blink=function(els,i){
if(i>=els.length)return;
var el=els[i],s=el.style,t=200,
nb='3px solid blue',eb=s.border+'';
el.scrollIntoView();
s.border=nb;
setTimeout(function(){s.border=eb;},t);
setTimeout(function(){s.border=nb;},t*2);
setTimeout(function(){
s.border=eb;
if(confirm("This one?")){
filter(el);
}else{
blink(els,i+1);
}
},t*3);
},
//helper for creating options on a select
opt=function(v,t,p){
var y=document.createElement('OPTION');
y.value=v;
y.text=t;
p.appendChild(y);
},
//creates the new filter input and adds it to the page
filter=function(el){
console.log('Filtering...');
var d=document,c=d.createElement('INPUT'),o=[];
c.type='text';
c.placeholder='Filter list';
c.style.width=el.style.width;
c.style.display='block';
el.parentNode.insertBefore(c,el);
//filters the option list when something is typed
c.onkeyup=function(ev){
var j=c.value+'',h=el.options,x=0;
if(o.length==0){
for(var e=0;e<h.length; e++){
with(h[e]){
o.push({'v':value,'t':text});
}
}
}
for(var g=h.length-1;g>=0;g--)el.remove(g);
for(var i=0;i<o.length; i++){
if(j.length==0){
opt(o[i].v,o[i].t,el);
}else{
if(match(o[i].t,j)){
if(x==0) opt('','',el);
opt(o[i].v,o[i].t,el);
x++;
}
}
}
if(x>0) el.options[0].text='<'+x+' Match(es) Found>';
};
},
//determines if the option text matches the filter criteria, with wildcard support
match=function(a,b){
a=(a+'').toLowerCase();
b=(b+'').toLowerCase();
if(b.indexOf('*')<0){
return a.indexOf(b)>=0;
}else{
var r='.*',c=b.split('*');
for(var i=0;i<c.length;i++){
r+='.*'+(c[i].length>0?'('+c[i]+')':'');
}
r+='.*';
return (new RegExp(r)).test(a);
}
},
d=document,s=selects(d),v=[];
//gets only SELECTs that are visible on the page
for(var i=0;i<s.length;i++){
if (window.getComputedStyle(s[i]).display !== 'none')
v.push(s[i]);
}
console.log('SELECTs: '+s.length);
console.log('Visible SELECTs: '+v.length);
//Begin.
blink(v,0);
})();