/*
* @title メディア再生窓生成
* @description マルチメディア要素へのリンクにhoverすると<audio>や<video>なウィンドウをポップアップしてくれるようにする
* @include http://*
* @license NYSL
*/
(function(){
var checked = []; // 同じURLに複数回リクエストを送るのを防ぐためのリストを格納
var timeout = 30 * 1000; // タイムアウトになるまでの時間(単位:ms)
if (!HTMLAnchorElement.prototype.addPopup) { // addPopupメソッドをA要素に追加
Object.defineProperty(HTMLAnchorElement.prototype, "addPopup", {
value: function(url){
var self = this;
var xhr = new XMLHttpRequest(); // HEADリクエストを送る
xhr.open("HEAD", url, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4) {
console.log(xhr.status + " : " + url);
if (xhr.status !== 200) return;
var header = xhr.getResponseHeader("Content-Type");
var type = header.split("/")[0];
var allowList = ["audio", "video"];
if (allowList.some(function(v){ return v === type })) { // いずれかにヒットすれば true
console.log(header + " - OK");
addPopupItem(self, type);
}
}
};
xhr.send(null);
window.setTimeout(function(){ // 一定時間でタイムアウト
xhr.abort();
}, timeout);
}
});
}
else {
return false;
}
// 他のスタイルから影響を受けないよう Date.now() を追加
var thisClass = "media-popup-" + Date.now();
var elems = document.getElementsByTagName("a");
elems = Array.prototype.slice.call(elems); // A要素を全て抽出
var popupItem = (function(){ // ポップアップ用の殻を作成
var div = document.createElement("div");
div.className = thisClass;
return div;
})();
var popupStyle = function(){ // スタイル定義
var style = document.createElement("style");
document.getElementsByTagName("head")[0].appendChild(style);
var s = style.sheet;
// カーソルを置いたらポップアップするように
s.insertRule("." + thisClass + "{"
+ "display: none !important;"
+ "text-indent: 0 !important;"
+ "z-index: 100 !important;"
+ "}", 0);
s.insertRule("a:hover + ." + thisClass + ", ." + thisClass + ":hover {"
+ "display: block !important;"
+ "}", s.cssRules.length);
s.insertRule("." + thisClass + "{"
+ "position: absolute !important;"
+ "}", s.cssRules.length);
};
popupStyle();
for (var i in elems) {
var url = elems[i].href;
if (url.indexOf("http") === 0) {
url = url.indexOf("#") + 1 ? url.split("#")[0] : url; // URLに # を含む場合は除去
if (checked.every(function(li){ return url !== li })) { // 全てとアンマッチなら true
checked.push(url);
elems[i].addPopup(url);
}
}
}
function addPopupItem(target, mediaType) { // ポップアップを生成
var popup = popupItem.cloneNode(), s = popup.style;
s.left = target.offsetLeft + "px";
s.top = target.offsetTop + target.offsetHeight + "px";
var element; // 殻の中身を定義
element = document.createElement(mediaType);
element.setAttribute("src", target.href);
element.setAttribute("preload", "metadata");
element.setAttribute("controls", "controls");
popup.appendChild(element);
target.parentElement.insertBefore(popup, target.nextSibling); // 目標の直後に配置
// 某ADVの公式サイトでなぜかレイアウトが崩れるので対症療法的な何か
var objRect = popup.getBoundingClientRect();
if (objRect.left === 0 && objRect.top === 0) {
s.left = s.top = "auto";
}
}
})();