/** * This file is part of the ForkBB . * * @copyright (c) Visman * @license The MIT License (MIT) */ if (typeof ForkBB === "undefined" || !ForkBB) { var ForkBB = {}; } ForkBB.media = (function (doc, win, nav) { 'use strict'; var id = 0, html5mime = {}, html5aRegx = getHTML5("audio", ["mp3", "m4a", "ogg", "oga", "webma", "wav", "flac"], ["mpeg", "mp4", "ogg", "ogg", "webm", "wav", "flac"]), html5vRegx = getHTML5("video", ["mp4", "m4v", "ogv", "webm", "webmv"], ["mp4", "mp4", "ogg", "webm", "webm"]), lazyFlag = false, lazyClass = "mediajslazy", lazyData = [], lazyObserver, searchClass = "formedia", addClass = "mediajslink", fb = false; function getHTML5(type, exts, mimes) { var i, r = "", a = doc.createElement(type); if (!!a.canPlayType) { for (i = 0; i"\'&]+\\.)(' + r + ')$', 'i') : false; } return false; } function getOembedSize(data) { if (data.width && data.height) { var e = 1; if (data.width < data.height) { if (data.height < 480) { e = 480 / data.height; } else if (data.height > 640) { e = 640 / data.height; } } else { if (data.width > 640) { e = 640 / data.width; } else if (data.height < 480) { e = Math.min(640 / data.width, 480 / data.height); } } return [Math.floor(data.width * e), Math.floor(data.height * e)]; } } function getOembed(url, successHandler, errorHandler) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { var data = xhr.responseText; if (typeof data === "string") { try { data = JSON.parse(data); } catch (e) { errorHandler && errorHandler(e); return; } } if ("width" in data && "height" in data && "html" in data) { successHandler && successHandler(data); } else { errorHandler && errorHandler(data); } } else { errorHandler && errorHandler(xhr); } } }; xhr.send(); } function createEl(node, type, attr, param, after) { attr = attr || {}; param = param || {}; var child, flag = type === "video" || type === "audio", obj = doc.createElement(type); for (var i in attr) { if (attr.hasOwnProperty(i)) { if (i == "style") { obj.style.cssText = attr[i]; } else { obj.setAttribute(i, attr[i]); } } } if (flag) { child = doc.createElement("source"); } for (var i in param) { if (param.hasOwnProperty(i)) { if (flag) { child.setAttribute(i, param[i]); } else { child = doc.createElement("param"); child.setAttribute("name", i); child.setAttribute("value", param[i]); obj.appendChild(child); } } } if (flag) { obj.appendChild(child); } if (!after) { return node.appendChild(obj); } return node.parentNode.insertBefore(obj, node.nextSibling); } function createMedia(node, playAttr, size, type, playParam) { var style1 = "padding-top:5px;", style2 = "overflow:hidden;position:relative;", attrDiv1 = {style: style1 + style2}, attrDiv2, tw, th; type = type || "iframe"; playParam = playParam || {}; if ("iframe" === type) { playAttr.frameborder = "0"; playAttr.scrolling = "no"; if (! playAttr.allowfullscreen) { playAttr.allowfullscreen = "allowfullscreen"; } } size = size || [640, 360]; // 0 - ошибка, 1 - размер не указывать, 2 - в пикселах, 3 - в процентах tw = typeSize(size[0]); th = typeSize(size[1]); if (!tw || !th) { return; } if (tw > 1) { attrDiv1.style = attrDiv1.style + (3 === tw ? "width:" + size[0] + ";" : "max-width:" + size[0] + "px;"); } if (3 === tw && 2 === th) { attrDiv2 = {style: style2 + "height:" + size[1] + "px;"}; playAttr.style = "width:100%;height:" + size[1] + "px;"; } else if (tw > 1 && th > 1) { attrDiv2 = {style: style2 + "height:0;padding-bottom:" + (3 === th ? size[1] : (100 * size[1] / size[0]) + "%;")}; playAttr.style = "position:absolute;left:0;top:0;width:100%;height:100%;"; } else if (tw > 1) { playAttr.style = "width:100%;"; } ++id; playAttr.id = "mediajs" + id; node.classList.replace(searchClass, addClass); var div = createEl(node, "div", attrDiv1, {}, true); if (attrDiv2) { div = createEl(div, "div", attrDiv2); } if (lazyFlag && "div" !== type) { div.classList.add(lazyClass); div.setAttribute("data-lazyid", id); lazyData[id] = { type: type, attr: playAttr, param: playParam }; if (! lazyObserver) { lazyObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { var lazyObj = entry.target, id = lazyObj.dataset.lazyid, set = lazyData[id]; createEl(lazyObj, set.type, set.attr, set.param); lazyObj.classList.remove(lazyClass); observer.unobserve(lazyObj); } }); }); } lazyObserver.observe(div); } else { createEl(div, type, playAttr, playParam); } return true; } function convertRangeToZoom(range, type) { if (type != "z") { range = Math.log(70400000 / range) / Math.log(2); } return Math.min(18, Math.max(Math.round(range), 3)); } function hmsToSec(str) { if (/^\d+$/.test(str)) { return str; } if (str = str.match(/^((\d{1,2})h)?((\b\d{1,3}|\d{1,2})m)?((\b\d{1,5}|\d{1,2})s)?$/)) { return 3600 * (str[2] || 0) + 60 * (str[4] || 0) + 1 * (str[6] || 0); } return ""; } // 0 - ошибка, 1 - размер не указывать, 2 - в пикселах, 3 - в процентах function typeSize(size) { if ("string" === typeof size && /^(?:100|[1-9]\d(?:\.\d{1,2})?)%$/.test(size)) { return 3; } else if (0 !== size % 1) { return 0; } else if (size > 15) { return 2; } else if (size < 1) { return 1; } else { return 0; } } function test(node) { var url = node.href, m = url.match(/^(.+)(?:#|%23)(\d+(?:\.\d{1,2})?)(%|%25)?(?::|%3A)(\d+(?:\.\d{1,2})?)(%|%25)?$/), arr, size; if (m) { node.herf = url = m[1]; m[2] += (m[3] ? "%" : ""); m[4] += (m[5] ? "%" : ""); if (typeSize(m[2]) > 0 && typeSize(m[4]) > 0) { size = [m[2], m[4]]; } } if (!(m = url.replace(/&/g, "&").match(/^(https?:\/\/)(www\.)?(.+)$/))) { return; } url = m[3]; if (!!html5aRegx && (arr = url.match(html5aRegx))) { createMedia(node, {controls: true, preload: "metadata", controlsList: "nodownload"}, size || ["100%", 0], "audio", {src: m[1] + (m[2] ? m[2] : "") + arr[1] + arr[2], type: html5mime[arr[2].toLowerCase()]}); } else if (!!html5vRegx && (arr = url.match(html5vRegx))) { createMedia(node, {controls: true, preload: "metadata", controlsList: "nodownload"}, size, "video", {src: m[1] + (m[2] ? m[2] : "") + arr[1] + arr[2], type: html5mime[arr[2].toLowerCase()]}); } else if (arr = url.match(/^(?:[a-z\d-]+\.)?youtu(?:be(?:-nocookie)?\.com|\.be)\/(?:playlist|(?:(?:.*?[\?&]v=)?([\w-]{11})(?:\?|&|#|$)))/)) { var b = "https://www.youtube.com/embed", param = ["wmode=transparent"], // , "controls=2" need = [], c, d, e, only; if (arr[1]) { b += "/" + arr[1]; only = ["start", "t", "end", "list", "rel", "loop"]; } else { param.push("listType=playlist"); only = ["list", "index", "loop"]; need = ["list"] } e = url.split(/[\?&#]/); while (c = e.shift()) { d = c.split("="); if (d[0] && d[1] && only.indexOf(d[0]) > -1 && /^[\w-]+$/.test(d[1])) { if (d[0] == "start" || d[0] == "t" || d[0] == "end") { param.push((d[0] == "end" ? "end" : "start") + "=" + hmsToSec(d[1])); } else { param.push(d[0] + "=" + d[1]); if (d[0] == "loop" && d[1] == "1" && arr[1]) { param.push("playlist=" + arr[1]); } } d = need.indexOf(d[0]); if (d > -1) { need.splice(d, 1); } } } if (!need.length) { createMedia(node, {src: b + "?" + param.join("&")}, size); } } else if (arr = url.match(/^(?:player\.)?vimeo\.com\/(?:[^\s\/<>'"]+\/){0,3}(?:\d+)(?=\?|#|$)/)) { getOembed("https://vimeo.com/api/oembed.json?url=https%3A//" + arr[0], function(data) { if (data.m = data.html.match(/