緣起:
好一段時間沒寫文章了,之前大部份的時間都在寫私人的日記,不久前寫到煩躁了,所以就先停更一段時間。工作上的話,每天做的事情其實沒差很多,copy
現有的程式碼然後做一點小改動,之後就看有什麼問題再修。說實在的,沒學到什麼比較有技術的東西,但也沒什麼興致看我們專案比較難的部份就是。
昨天,我們 PM 請我研究個東西,就是看能不能寫個 Script
來鎖定網站上的
iframe,讓右鍵點擊它們時會沒有作用,當作是一個簡單的防盜機制。
先說結論,這無法做到,PM
在請教了我們資深的工程師後,得到的回答也是做不到,所以就請我不用再研究了。但在放棄前,我有試著想了一些旁門左道的方法來達成鎖定右鍵的功能,雖然最後是以失敗告終,但在這過程中有學到不少東西,所以想寫個文章記錄下來。
關於 iframe:
有去查怎麼用 jquery 存取 iframe 裡的東西,查的過程中,有學到
X-Frame-Options
這東西,那些大網站的 http response header 都會加它,防止被 clickjack。
再來是用 jquery 存取 iframe,就我的認知,iframe 裡的內容是禁止存取的,除非那個 iframe 跟目前的 html
文件是同源。
我用簡單的程式碼 try 了一下,iframe 是複製 youtube
的內嵌分享。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iframe</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
$('iframe').each(function(index, elem){
console.info($(this).contents());
});
})
</script>
<iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</body>
</html>
確實能取得 iframe。
Top-Layer:
後來是有成功弄個 div 出來擋住 iframe
啦,但不久後又意識到有另一個問題的存在,那就是全螢幕。我發現,影片使用全螢幕後,會出現一個
#top-layer 的區塊
如果我想要讓 iframe
在變全螢幕後也不能被點選,那我就要在那個 iframe 進入 #top-layer 時,用 div
把它給包起來。後來看到,document 有個
onfullscreenchange
的事件,當有東西進入 #top-layer 時就會被觸發,我們可以在 callback function
裡用 document.fullscreenElement 來取得目前在 #top-layer 的 dom,如果沒的話,它會是
null。
我後來是沒有接著做幫進入 #top-layer 的 dom 包一個 div
的工作。
CSS 的 z-index:
我想覆蓋 iframe,但不想動到它本身跟它周圍 dom
的排列與顯示,所以在 css 上要知道怎麼用一個 div,剛好把 iframe
給蓋住。最先想到要調整的就是 div 的 z-index,把它調大一點才能,蓋過
iframe,不過,我後來看到這文章 ,它最後有提到,如果我那個當遮罩用的 div,它的父層跟 iframe
不一樣,有可能調了 zindex 後,還是不能擋住 iframe。
所以我就想到了一個架構,就是先用一個 div 把 iframe
給包住,之後再把當遮罩用的 div 給放到裡面,這樣,遮罩 div 就會跟 iframe
在同一個階層了。
jquery 的 wrap:
這邊開始實做,用 jquery 的 $('<div></div>')
可以弄出一個 div 的 jquery instance,jquery 的
wrap
可以把一個 html 元件用另一個 html 元件給包起來,before
跟
after
則可以把 html 元素加在目標物前面或後面
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iframe</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
$('iframe').each(function(index, elem){
let $wrapDiv = $('<div></div>');
let $blockDiv=$('<div></div>')
$(elem).wrap($wrapDiv);
$(elem).after($blockDiv);
});
})
</script>
<iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</body>
</html>
可以看到,iframe 有被 div 包著了,而且在它下方也多了一個 div。
CSS 的調整:
div 預設的 display 是 block,這不是我想要的,所以我就去查 display,這東西我不是很熟,也不會介紹,但經過我的嘗試,發現把 display 設成 inline-block 可以達成我的需求。設成 inline-block 後,div 的大小就會貼齊子元素。
接著是關於 position,我是看這篇文章學習的,要注意的是,最外層 div 的 postion 要設成 relative,這樣裡面的那個當遮罩用的 div,在 postion 設成 absolute 時,它在向上找定位點時才不會找到 body 去。再來把遮罩 div 的長跟寛都設成 100%,它就會貼齊最外層,最後再給它的 zindex 一個比較大的數字,就差不多完成了。
程式碼如下
<html lang="en"$gt;
<head$gt;
<meta charset="UTF-8"$gt;
<title$gt;iframe</title$gt;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"$gt;</script$gt;
</head$gt;
<body$gt;
<script$gt;
$(function () {
$('iframe').each(function (index, elem) {
let $wrapDiv = $('<div$gt;</div$gt;');
let $blockDiv = $('<div$gt;</div$gt;');
$wrapDiv.css('display', 'inline-block');
$wrapDiv.css('position', 'relative');
$blockDiv.css('height', '100%');
$blockDiv.css('width', '100%');
$blockDiv.css('position', 'absolute');
$blockDiv.css('top', '0px');
$blockDiv.css('left', '0px');
$blockDiv.css('z-index', '1000');
$(elem).wrap($wrapDiv);
$(elem).after($blockDiv);
});
})
</script$gt;
<iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen$gt;</iframe$gt;
</body$gt;
</html$gt;
可以看到,遮罩的 div 確實有擋住 iframe,不過這樣就不光是鎖右鍵了,我們根本碰不著 iframe 裡的東西 XD
就只能先這樣了,至少,我學到不少好用的東西。
沒有留言:
張貼留言