2017年2月27日月曜日

iframeからlocationをgetしたい場合はidが必須でframesから辿る

タイトルの内容を覚えられればそれでOKなのですが、私はどうやら覚えられないらしく、必要になるたびに過去のサンプルを確認しているアリサマなのでiframeをコントロールする時に使うメソッドもまとめておくことにしました。




以下ソース
<html>
<title>iframe</title>
<body style="text-align:center;">
<iframe id=ifr style="border:solid 1px #000;width:100%;"></iframe>
<button id=btn0>初期化</button>
<button id=btn1>byFrames</button>
<button id=btn2>getDoc</button>
<table id=tbl border=1>
<tr>
<td></td>
<td><select></select></td>
</tr>
</table>
</body>
<script>
resizeTo(500,400)
newTR=function(){
var FI='firstChild'
var tbo=tbl[FI], tr=tbo[FI].removeNode(true), newTR
return function(str){
tbo.insertBefore(newTR=tr.cloneNode(true))
newTR[FI].innerText = str
return newTR
}
}()
iniSel=function(tr, arr, elemIFR){
var sel=tr.getElementsByTagName('select')[0], ops=sel.options
for(var i=0,L=arr.length;i<L;i++){ ops[i] = new Option(arr[i]) }
sel.onchange = function(){ var op=this.options[this.selectedIndex]; confirm(elemIFR[op.text]) }
return sel
}
getNames=function(obj){
var arr=[], name
for(name in obj){arr.push(name)}
return arr
}
onload=function(){
var elemIFR
iniSel(
newTR('document.getElementsByTagName'),
getNames(elemIFR=document.getElementsByTagName('iframe')[0]).sort(),
elemIFR
)
iniSel(
newTR('document.body.firstChild'),
getNames(elemIFR=document.body.firstChild).sort(),
elemIFR
)
iniSel(
newTR('frames[frames.length-1]'),
getNames(elemIFR=frames[frames.length-1]).sort(),
elemIFR
)
iniSel(
newTR('ifr'),
getNames(elemIFR=ifr).sort(),
elemIFR
)
var arr0=getNames(ifr), elem=document.body.firstChild, arr1=getNames(elem), obj={}, arr2=[], name, arr3=[]
for(var i=0,L=arr0.length;i<L;i++){ obj[arr0[i]] = {v:ifr[arr0[i]]} }
for(i=0,L=arr1.length;i<L;i++){
name = arr1[i]
if(!obj[name]){continue}
arr2.push({win:obj[name].v, dom:elem[name]})
arr3.push(name)
}
iniSel(newTR('共通'), arr3).onchange = function(){ var str=this.options[this.selectedIndex].text; confirm(str+'\nwin:['+ifr[str]+']\ndom:['+document.body.firstChild[str]+']') }
var sw
btn0.onclick = function(){ objIframe.setLocation('ifr', document.title=sw='about:blank') }
objIframe.setRSC('ifr', function(){
if(this.readyState!='complete'){return}
if(sw){return sw=false}
document.title = objIframe.decodeURI(objIframe.getLocation('ifr'))
}, '')
btn1.onclick=function(){ getByFrame(document.body.firstChild) }
btn2.onclick=function(){
var doc=objIframe.getDoc('ifr'), div=document.createElement('div')
doc.write('<font size=30>123</font>')
doc.body.insertBefore( div )
div.innerText = 'aiueo'
}
}
objIframe=function(){
var getById=function(id){return document.getElementById(id)}
return {
setRSC:function(id, fun, src){
elem=getById(id)
elem.onreadystatechange = fun
elem.src = src
},
getLocation:function(id){ return frames[id].location },
setLocation:function(id, url){ frames[id].location = url },
decodeURI:function(str){return decodeURI(str).replace(/^file:/,'').replace(/^\/+(\w:)/,'$1')},
getDoc:function(id){return getById(id).contentWindow.document}
}
}()
getByFrame=function(elem){
var fun特定用=function(){}, str1=12345678, prop='onfocus', sw=elem[prop]
fun特定用.str0 = (new Date()).toLocaleString()
if(sw){
while(elem[prop][sw=(new Date()).toLocaleString()]){}
elem[prop][sw] = fun特定用
}else{
elem[prop] = fun特定用
}
// confirm('elem.oH:['+elem.outerHTML+']\nsw['+sw+']\npropName:['+prop+']\nprop:['+elem[prop]+']')
for(var i=0,L=frames.length, elem_;i<L;i++){
elem_ = frames[i]
// confirm('i['+i+']\nL['+L+']\n['+elem_[prop]+']')
if(!elem_[prop]){continue}
// confirm('継続')
if(sw && elem_[prop][sw] && elem_[prop][sw].str0==fun特定用.str0){
fun特定用.str0 = str1
if(elem_[prop][sw].str0==fun特定用.str0){
delete elem_[prop][sw]
return elem_
}
}else{
if(elem_[prop].str0==fun特定用.str0){
fun特定用.str0 = str1
if(elem_[prop].str0==fun特定用.str0){
elem_[prop] = null
return elem_
}
}
}
}
// frames.length==1なら特定できる…けど、1個ではない場合は無理なのでそういう方法は使わない。
confirm('特定できませんでした。。')
}
</script>
</html>
view raw objIframe.hta hosted with ❤ by GitHub


動作画面



できればid属性は使わない方法が良かったのですが、DOMツリー側から参照した場合に利用できるsrc属性はinputができてもoutputは常にカラなのでlocationをgetするためにはframesから辿る他なく、iframeがページ内に1つとは限らないのでframes以下で任意のiframeを特定するためにどうしてもidが必要でした。

framesから参照した場合とDOMツリーから参照した場合とで共通する項目があるので、それを使って特定できないか試みましたが「byFrames」ボタンを押すと以下のメッセージが表示されました。


「byFrames」実行後に「共通」で「onfocus」を選択すると以下のように表示されるので、名前は同じでも実体は異なるようです。


0 件のコメント:

コメントを投稿