无法通过JavaScript通过DOM访问自定义标记内的IFRAME

问题描述 投票:0回答:1

我正在Chrome中创建一个基于JS的书签,以在我单击书签时将过滤器INPUT添加到网页上的任何SELECT。我对具有IFRAME的页面进行了测试,只要浏览器对源策略感到满意,它就可以工作。请参阅下面的最低可行解决方案。

我在Salesforce中工作很多,并且经常使用多个页面,这些页面的下拉列表非常长(例如多达1000个选项),我想使用这种“快速”过滤解决方案。

问题是,SF在大多数后端页面上都使用了iframe,并且此代码不会从页面中选择IFRAME对象。

document.getElementsByTagName('IFRAME')返回0个对象,即使我可以查看页面源并看到IFRAME。在我的测试中,“起源”情况下的“ get IFRAMEs”调用可以正常工作,它试图访问IFRAME中可能失败的内容。

我要获取的SELECT之一的路径如下:

html>正文> div> div>部分> div> force-aloha-page> div>iframe> html>正文> div> p>选择

我认为问题与该自定义标签force-aloha-page有关。我尝试将其他元素放入该节点内,但没有成功。

这是一个错误吗?还是您无法遍历自定义标签内的DOM的预期行为?

我尝试创建一个递归脚本,该脚本试图通过遍历所有节点和子节点来获取所有元素,但是仍然无法在该自定义标记内获取。

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?

当前解决方案测试用例

这是我编写书签代码时使用的测试页。

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);
})();
javascript html dom iframe
1个回答
0
投票

下面的代码段应该起作用。

// Query all iframes in the DOM
var iframesNodes = document.querySelectorAll("iframe");

// Transfrom nodeList into an array
var iframes = Array.prototype.slice.call(iframesNodes);
console.log(iframes);

// Loop through all iframes
iframes.map(function(iframe){
  // Get the document of the current iframe
  var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
  
  /* ... Then do what ever you want with the iframe document ... */
  innerDoc.body.style.backgroundColor = "#ff0000"
});
<exampletag>
    <iframe src="/" />
</exampletag>
 
<iframe src="/" />

如果要使用自定义标签,则应阅读:https://www.smashingmagazine.com/2014/03/introduction-to-custom-elements/

© www.soinside.com 2019 - 2024. All rights reserved.