mirax-player
Advanced tools
Comparing version 6.2.0 to 6.3.0
@@ -1,408 +0,481 @@ | ||
/* # Mirax Player core license | ||
const embedTwitter = (embedDiv) => { | ||
function extractTwitterTweetId(url) { | ||
const regex = /\/status\/(\d+)/; | ||
const match = url.match(regex); | ||
if (match && match[1]) { | ||
return match[1]; | ||
} else { | ||
return null; // No match found | ||
} | ||
} | ||
Mirax Player is released under the MIT license: | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
const tweetId = extractTwitterTweetId(videoUrl); | ||
const emWidth = embedDiv.getAttribute("data-e-width"); | ||
const emHeight = embedDiv.getAttribute("data-e-height"); | ||
const inputEmbedClip = document.createElement("style"); | ||
document.head.appendChild(inputEmbedClip); | ||
const inputEmbedClipStyle = ` | ||
.mirax-embed { | ||
position: relative; | ||
width: 100%; | ||
max-width: ${emWidth}px; | ||
height: ${emHeight}px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
} | ||
.mirax-embed iframe { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
`; | ||
inputEmbedClip.appendChild(document.createTextNode(inputEmbedClipStyle)); | ||
try { | ||
// Create a div to hold the embedded tweet | ||
const tweetContainer = document.createElement("div"); | ||
embedDiv.appendChild(tweetContainer); | ||
// Set the ID for the tweet container | ||
tweetContainer.id = `tweet-${tweetId}`; | ||
// Add the Twitter widget script to the page and wait for it to load | ||
const twitterWidgetScript = document.createElement("script"); | ||
twitterWidgetScript.src = "https://platform.twitter.com/widgets.js"; | ||
twitterWidgetScript.charset = "utf-8"; | ||
twitterWidgetScript.async = true; | ||
// Attach a load event listener to the script | ||
twitterWidgetScript.addEventListener("load", () => { | ||
// The Twitter widget script has loaded, and the tweet is now embedded. | ||
// You can perform any additional actions here if needed. | ||
window.twttr.widgets.createTweet(tweetId, tweetContainer); | ||
}); | ||
document.body.appendChild(twitterWidgetScript); | ||
} catch (error) { | ||
console.error("Error embedding Twitter content:", error); | ||
} | ||
}; | ||
// Function to embed a Dailymotion video using oEmbed | ||
const embedDailymotion = (embedDiv) => { | ||
MIT License | ||
Copyright (c) [2023-present] [Demjhon Silver] | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. */ | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
const emWidth = embedDiv.getAttribute("data-e-width"); | ||
const emHeight = embedDiv.getAttribute("data-e-height"); | ||
import aziwork, { sunder } from 'aziwork'; | ||
const inputEmbedClip = document.createElement('style'); | ||
document.head.appendChild(inputEmbedClip); | ||
const inputEmbedClipStyle = ` | ||
// Function to embed a Dailymotion video using oEmbed | ||
const embedDailymotion = (video, container, videoClass) => { | ||
const videoUrl = video.videoUrl; | ||
// Define maxwidth and maxheight based on the video object's properties | ||
const maxwidth = video.width || 640; // Default width if not provided | ||
const maxheight = video.height || 360; // Default height if not provided | ||
// Check if autoplay should be enabled (true by default) | ||
const autoplayEnabled = video.autoplay !== undefined ? video.autoplay : true; | ||
// Create a script element for the JSONP request | ||
const script = document.createElement("script"); | ||
script.src = `https://www.dailymotion.com/services/oembed/?url=${encodeURIComponent( | ||
videoUrl | ||
)}&format=json&maxwidth=${maxwidth}&maxheight=${maxheight}&callback=handleDailymotionResponse`; | ||
// Define a global callback function to handle the response | ||
window.handleDailymotionResponse = (data) => { | ||
if (data.html) { | ||
// Create a div element to hold the Dailymotion video | ||
const videoContainer = document.createElement("div"); | ||
// Apply the videoClass to the videoContainer | ||
videoContainer.className = `video-${videoCount} ${videoClass} custom-dailymotion`; // Add custom-dailymotion class | ||
// Set the HTML content of the videoContainer to the oEmbed HTML | ||
videoContainer.innerHTML = data.html; | ||
// Update the video's width to be responsive | ||
const videoElement = videoContainer.querySelector('iframe'); | ||
if (videoElement) { | ||
videoElement.style.width = '100%'; // Set width to 100% for responsiveness | ||
// Conditionally add the 'autoplay' attribute | ||
if (autoplayEnabled) { | ||
videoElement.setAttribute('autoplay', 'autoplay'); | ||
} | ||
// Update the 'allow' attribute to include 'fullscreen' and 'picture-in-picture' | ||
videoElement.setAttribute('allow', 'autoplay; fullscreen; picture-in-picture; muted'); | ||
} | ||
// Append the videoContainer to the provided container | ||
container.appendChild(videoContainer); | ||
// Clean up the script element and callback function | ||
document.body.removeChild(script); | ||
delete window.handleDailymotionResponse; | ||
} | ||
}; | ||
// Append the script element to the document to trigger the JSONP request | ||
document.body.appendChild(script); | ||
.mirax-embed { | ||
position: relative; | ||
width: 100%; | ||
max-width: ${emWidth}px; | ||
height:${emHeight}px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
} | ||
.mirax-embed iframe { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
`; | ||
inputEmbedClip.appendChild(document.createTextNode(inputEmbedClipStyle)); | ||
// Create a script element for the JSONP request | ||
const script = document.createElement("script"); | ||
script.src = `https://www.dailymotion.com/services/oembed/?url=${encodeURIComponent( | ||
videoUrl | ||
)}&format=json&callback=handleDailymotionResponse`; | ||
// Define a global callback function to handle the response | ||
window.handleDailymotionResponse = (data) => { | ||
if (data.html) { | ||
embedDiv.innerHTML = data.html; | ||
} | ||
// Clean up the script element and callback function | ||
document.body.removeChild(script); | ||
delete window.handleDailymotionResponse; | ||
}; | ||
// Function to extract Vimeo video ID from a URL | ||
const extractVimeoVideoId = (url) => { | ||
const videoIdMatch = url.match(/\/(\d+)/); | ||
if (videoIdMatch && videoIdMatch[1]) { | ||
return videoIdMatch[1]; | ||
} else { | ||
console.error("Invalid Vimeo video URL"); | ||
return ""; | ||
// Append the script element to the document to trigger the JSONP request | ||
document.body.appendChild(script); | ||
}; | ||
const embedTiktok = async (embedDiv) => { | ||
try { | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
// Fetch oEmbed data from TikTok's API | ||
const response = await fetch(`https://www.tiktok.com/oembed?url=${encodeURIComponent(videoUrl)}`); | ||
if (!response.ok) { | ||
throw new Error(`Failed to fetch TikTok oEmbed data: ${response.statusText}`); | ||
} | ||
}; | ||
const data = await response.json(); | ||
if (data.html) { | ||
data.html = data.html.replace(/<script[^>]*>.*<\/script>/gi, ""); | ||
} | ||
embedDiv.innerHTML = data.html; | ||
const miraxBinderTikTok = document.createElement("script"); | ||
miraxBinderTikTok.src = "https://www.tiktok.com/embed.js"; | ||
document.body.appendChild(miraxBinderTikTok); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
// Function to extract YouTube video ID from a URL | ||
const extractYouTubeVideoId = (url) => { | ||
// Check if it's a YouTube Shorts URL | ||
const shortsMatch = url.match(/(?:shorts\/|v=)([a-zA-Z0-9_-]{11})/); | ||
if (shortsMatch && shortsMatch[1]) { | ||
return shortsMatch[1]; | ||
} | ||
// Check if it's a regular YouTube video URL | ||
const videoIdMatch = url.match(/(\?v=|\/embed\/|\/watch\?v=|\/v\/|\/e\/|youtu.be\/)([^#&?]*).*/); | ||
if (videoIdMatch && videoIdMatch[2].length === 11) { | ||
return videoIdMatch[2]; | ||
} | ||
throw new Error("Invalid YouTube video URL"); | ||
}; | ||
// Function to embed a YouTube video | ||
const embedYouTube = (embedDiv) => { | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
const emWidth = embedDiv.getAttribute("data-e-width"); | ||
const emHeight = embedDiv.getAttribute("data-e-height"); | ||
const inputEmbedClip = document.createElement('style'); | ||
document.head.appendChild(inputEmbedClip); | ||
const inputEmbedClipStyle = ` | ||
.mirax-embed { | ||
display: flex; | ||
justify-content: center; /* Center horizontally */ | ||
align-items: center; /* Center vertically */ | ||
position: relative; | ||
width: 100%; | ||
max-width: ${emWidth}px; | ||
height: ${emHeight}px; | ||
overflow: hidden; | ||
text-align: center; | ||
} | ||
.mirax-embed iframe { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
`; | ||
inputEmbedClip.appendChild(document.createTextNode(inputEmbedClipStyle)); | ||
const embedVimeo = (video, container, videoClass) => { | ||
const emWidth = video.width || 640; | ||
const emHeight = video.height || 360; | ||
const controlsValue = video.controls; | ||
const AutoplayValue = video.autoplay; | ||
const LoopValue = video.loop; | ||
const videoId = extractVimeoVideoId(video.videoUrl); | ||
const playerDiv = document.createElement("div"); | ||
playerDiv.className = `video-${videoCount} ${videoClass}`; | ||
playerDiv.dataset.eWidth = emWidth; | ||
playerDiv.dataset.eHeight = emHeight; | ||
playerDiv.dataset.efullscreen = video.fullscreen; | ||
playerDiv.dataset.eVideoId = videoId; | ||
container.appendChild(playerDiv); | ||
const videoId = extractYouTubeVideoId(videoUrl); | ||
// Check if the YouTube iframe API is already available | ||
if (window.YT && window.YT.Player) { | ||
initializeYouTubeAPI(embedDiv, videoId, { | ||
width: emWidth, // Use the e-width attribute | ||
height: emHeight, // Use the e-height attribute | ||
}); | ||
} else { | ||
// Define the callback function when the YouTube iframe API is ready | ||
window.onYouTubeIframeAPIReady = () => { | ||
initializeYouTubeAPI(embedDiv, videoId); | ||
}; | ||
// Load the YouTube iframe API script | ||
const script = document.createElement("script"); | ||
script.src = "https://player.vimeo.com/api/player.js"; | ||
script.src = "https://www.youtube.com/iframe_api"; | ||
script.async = true; | ||
script.onload = () => { | ||
const vimeoPlayer = new window.Vimeo.Player(playerDiv, { | ||
id: videoId, | ||
width: emWidth, | ||
height: emHeight, | ||
controls: controlsValue, | ||
autoplay: AutoplayValue, | ||
muted: true, // Set muted to true for autoplay | ||
loop: LoopValue, | ||
}); | ||
vimeoPlayer.ready().then(() => { | ||
// You can use player methods here as needed | ||
}); | ||
}; | ||
document.body.appendChild(script); | ||
return () => { | ||
if (playerDiv) { | ||
playerDiv.innerHTML = ""; | ||
} | ||
document.body.removeChild(script); | ||
}; | ||
}; | ||
const embedTwitter = (video, container, videoClass) => { | ||
const extractTwitterTweetId = (url) => { | ||
const regex = /\/status\/(\d+)/; | ||
const match = url.match(regex); | ||
if (match && match[1]) { | ||
return match[1]; | ||
} else { | ||
return null; // No match found | ||
} | ||
}; | ||
try { | ||
const videoUrl = video.videoUrl; | ||
const tweetId = extractTwitterTweetId(videoUrl); | ||
// Create a div to hold the embedded tweet | ||
const tweetContainer = document.createElement("div"); | ||
// Apply the videoClass to the tweetContainer | ||
tweetContainer.className = `video-${videoCount} ${videoClass}`; | ||
// Set the ID for the tweet container | ||
tweetContainer.id = `tweet-${tweetId}`; | ||
// Add the Twitter widget script to the page and wait for it to load | ||
const twitterWidgetScript = document.createElement("script"); | ||
twitterWidgetScript.src = "https://platform.twitter.com/widgets.js"; | ||
twitterWidgetScript.charset = "utf-8"; | ||
twitterWidgetScript.async = true; | ||
// Attach a load event listener to the script | ||
twitterWidgetScript.addEventListener("load", () => { | ||
// The Twitter widget script has loaded, and the tweet is now embedded. | ||
// You can perform any additional actions here if needed. | ||
window.twttr.widgets.createTweet(tweetId, tweetContainer); | ||
}); | ||
// Append the tweet container to the provided container | ||
container.appendChild(tweetContainer); | ||
container.appendChild(twitterWidgetScript); | ||
} catch (error) { | ||
console.error("Error embedding Twitter content:", error); | ||
} | ||
// Function to clean up the player | ||
return () => { | ||
if (embedDiv) { | ||
embedDiv.innerHTML = ""; // Remove the YouTube player iframe | ||
} | ||
}; | ||
// Map to track embedded TikTok videos | ||
const embeddedTikTokVideos = new Map(); | ||
const embedTiktok = (video, container, videoClass) => { | ||
const videoUrl = video.videoUrl; | ||
// Check if the TikTok video URL has already been embedded | ||
if (embeddedTikTokVideos.has(videoUrl)) { | ||
// Video has already been embedded, no need to embed it again | ||
return; | ||
}; | ||
// Function to initialize the YouTube API | ||
const initializeYouTubeAPI = (embedDiv, videoId) => { | ||
const emWidth = embedDiv.getAttribute("data-e-width"); | ||
const emHeight = embedDiv.getAttribute("data-e-height"); | ||
const emFS = embedDiv.getAttribute("data-e-fullscreen"); | ||
const emControls = embedDiv.getAttribute("data-e-controls"); | ||
const emAutoplay = embedDiv.getAttribute("data-e-autoplay"); | ||
const emLoop = embedDiv.getAttribute("data-e-loop"); | ||
const fullscreenValue = emFS === "false" ? 0 : 1; | ||
const controlsValue = emControls === "false" ? 0 : 1; | ||
const AutoplayValue = emAutoplay === "false" ? 0 : 1; | ||
const AutomutedValue = emAutoplay === "false" ? 0 : 1; | ||
const LoopValue = emLoop === "false" ? 0 : 1; | ||
const inputEmbedClip = document.createElement('style'); | ||
document.head.appendChild(inputEmbedClip); | ||
const inputEmbedClipStyle = ` | ||
.mirax-embed { | ||
position: relative; | ||
width: 100%; | ||
max-width: ${emWidth}px; | ||
height:${emHeight}px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
} | ||
// Mark the TikTok video URL as embedded | ||
embeddedTikTokVideos.set(videoUrl, true); | ||
const width = video.width || '100%'; // Default width if not provided | ||
const height = video.height || '100%'; // Default height if not provided | ||
aziwork.get(`https://www.tiktok.com/oembed?url=${encodeURIComponent(videoUrl)}`) | ||
.then((response) => { | ||
const data = sunder(response); // Parse JSON data using sunder | ||
if (data.html) { | ||
data.html = data.html.replace(/<script[^>]*>.*<\/script>/gi, ''); | ||
} | ||
const videoContainer = document.createElement('div'); | ||
const videoCount = Date.now(); | ||
// Apply the videoClass to the videoContainer | ||
videoContainer.className = `video-${videoCount} ${videoClass}`; | ||
// Set the width and height of the videoContainer | ||
videoContainer.style.width = width; | ||
videoContainer.style.height = height; | ||
videoContainer.innerHTML = data.html; | ||
// Check if the TikTok embed script is already loaded | ||
if (!document.querySelector('script[src="https://www.tiktok.com/embed.js"]')) { | ||
// Dynamically load the TikTok embed script | ||
const miraxBinderTikTok = document.createElement('script'); | ||
miraxBinderTikTok.src = 'https://www.tiktok.com/embed.js'; | ||
document.body.appendChild(miraxBinderTikTok); | ||
} | ||
if (container) { | ||
// Append the videoContainer to the specified container (if provided) | ||
container.appendChild(videoContainer); | ||
} else if (document.body) { | ||
// Append the videoContainer to the body if no container is specified | ||
document.body.appendChild(videoContainer); | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error('An error occurred while embedding TikTok video:', error); | ||
}); | ||
}; | ||
let videoCount = 1; // Initialize videoCount | ||
const embedFacebook = (video, container, videoClass) => { | ||
const videoUrl = video.videoUrl; | ||
const autoplay = video.autoplay ? 'autoplay=true' : 'autoplay=false'; | ||
const muted = autoplay ? 'muted=true' : 'muted=false'; | ||
const emWidth = video.width || 640; | ||
const emHeight = video.height || 360; | ||
// Create an iframe element for the Facebook video | ||
const iframe = document.createElement('iframe'); | ||
iframe.setAttribute('src', `https://www.facebook.com/plugins/video.php?href=${encodeURIComponent(videoUrl)}&width=${emWidth}&height=${emHeight}&show_text=false&${autoplay}&${muted}`); | ||
iframe.setAttribute('width', emWidth); | ||
iframe.setAttribute('height', emHeight); | ||
iframe.setAttribute('frameborder', '0'); | ||
if (video.fullscreen) { | ||
iframe.setAttribute('allowfullscreen', 'true'); | ||
.mirax-embed iframe { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
iframe.className = `video-${videoCount} ${videoClass} custom-facebook`; | ||
videoCount++; | ||
container.appendChild(iframe); | ||
}; | ||
// Function to extract YouTube video ID from a URL | ||
const extractYouTubeVideoId = (url) => { | ||
// Check if it's a YouTube Shorts URL | ||
const shortsMatch = url.match(/(?:shorts\/|v=)([a-zA-Z0-9_-]{11})/); | ||
if (shortsMatch && shortsMatch[1]) { | ||
return shortsMatch[1]; | ||
`; | ||
inputEmbedClip.appendChild(document.createTextNode(inputEmbedClipStyle)); | ||
if (embedDiv) { | ||
new window.YT.Player(embedDiv, { | ||
videoId: videoId, | ||
width: emWidth, // Use the e-width attribute | ||
height: emHeight, // Use the e-height attribute | ||
playerVars: { | ||
fs: fullscreenValue, | ||
controls: controlsValue, // 0 or 1 | ||
cc_load_policy: 1, | ||
autoplay: AutoplayValue, | ||
mute: AutomutedValue, | ||
loop: LoopValue | ||
} | ||
}); | ||
} | ||
}; | ||
// Function to extract Vimeo video ID from a URL | ||
const extractVimeoVideoId = (url) => { | ||
const videoIdMatch = url.match(/\/(\d+)/); | ||
if (videoIdMatch && videoIdMatch[1]) { | ||
return videoIdMatch[1]; | ||
} else { | ||
console.error("Invalid Vimeo video URL"); | ||
return ""; | ||
} | ||
}; | ||
// Function to embed a Vimeo video | ||
const embedVimeo = (embedDiv) => { | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
const emWidth = embedDiv.getAttribute("data-e-width"); | ||
const emHeight = embedDiv.getAttribute("data-e-height"); | ||
const emControls = embedDiv.getAttribute("data-e-controls"); | ||
const emAutoplay = embedDiv.getAttribute("data-e-autoplay"); | ||
const emLoop = embedDiv.getAttribute("data-e-loop"); | ||
const controlsValue = emControls === "false" ? 0 : 1; | ||
const AutoplayValue = emAutoplay === "false" ? false : true; | ||
const LoopValue = emLoop === "false" ? false : true; | ||
const inputEmbedClip = document.createElement('style'); | ||
document.head.appendChild(inputEmbedClip); | ||
const inputEmbedClipStyle = ` | ||
.mirax-embed { | ||
position: relative; | ||
width: 100%; | ||
max-width: ${emWidth}px; | ||
height:${emHeight}px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
} | ||
// Check if it's a regular YouTube video URL | ||
const videoIdMatch = url.match(/(\?v=|\/embed\/|\/watch\?v=|\/v\/|\/e\/|youtu.be\/)([^#&?]*).*/); | ||
if (videoIdMatch && videoIdMatch[2].length === 11) { | ||
return videoIdMatch[2]; | ||
.mirax-embed iframe { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
throw new Error("Invalid YouTube video URL"); | ||
`; | ||
inputEmbedClip.appendChild(document.createTextNode(inputEmbedClipStyle)); | ||
const videoId = extractVimeoVideoId(videoUrl); | ||
// Create a script element to load the Vimeo Player API | ||
const script = document.createElement("script"); | ||
script.src = "https://player.vimeo.com/api/player.js"; | ||
script.async = true; | ||
// Callback when the Vimeo Player API script is loaded | ||
script.onload = () => { | ||
const vimeoPlayer = new window.Vimeo.Player(embedDiv, { | ||
id: videoId, | ||
width: emWidth, // Use the e-width attribute | ||
height: emHeight, // Use the e-height attribute | ||
controls: controlsValue, | ||
autolay: AutoplayValue, | ||
muted: false, | ||
loop: LoopValue, | ||
responsive: true | ||
}); | ||
vimeoPlayer.ready().then(() => { | ||
// You can use player methods here as needed | ||
}); | ||
}; | ||
const embedYouTube = (video, container, videoClass) => { | ||
if (!container) { | ||
console.error("Container element not found."); | ||
return; | ||
document.body.appendChild(script); | ||
// Function to clean up the player | ||
return () => { | ||
if (embedDiv) { | ||
embedDiv.innerHTML = ""; // Remove the Vimeo player iframe | ||
} | ||
const autoplayValue = video.autoplay ? 1 : 0; | ||
const muteValue = video.autoplay ? 1 : video.muted ? 1 : 0; | ||
const loopValue = video.autoplay ? 1 : video.loop ? 1 : 0; | ||
const videoId = extractYouTubeVideoId(video.videoUrl); | ||
// Create an iframe element for the YouTube player | ||
const iframe = document.createElement("iframe"); | ||
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=${autoplayValue}&mute=${muteValue}&loop=${loopValue ? 1 : 0}&controls=${video.controls ? 1 : 0}`; | ||
iframe.width = video.width || 640; | ||
iframe.height = video.height || 360; | ||
iframe.frameborder = "0"; | ||
if (video.fullscreen) { | ||
iframe.setAttribute("allow", "fullscreen"); | ||
} | ||
// Apply the videoClass to the iframe element | ||
iframe.className = videoClass; | ||
// Append the iframe to the provided container | ||
container.appendChild(iframe); | ||
document.body.removeChild(script); | ||
}; | ||
const embed = (videos) => { | ||
videos.map((video) => { | ||
const videoClass = video.videoClass || ""; | ||
const container = document.querySelector(`.${videoClass}`); | ||
// Clear the container before embedding a new video | ||
while (container.firstChild) { | ||
container.removeChild(container.firstChild); | ||
} | ||
if (video.videoUrl.includes("youtube.com") || video.videoUrl.includes("youtu.be")) { | ||
embedYouTube(video, container, videoClass); | ||
} | ||
else if (video.videoUrl.includes("facebook.com") || video.videoUrl.includes("fb.com")) { | ||
embedFacebook(video, container, videoClass); | ||
} | ||
else if (video.videoUrl.includes("tiktok.com") || video.videoUrl.includes("tiktok")) { | ||
embedTiktok(video, container, videoClass); | ||
} | ||
else if (video.videoUrl.includes("twitter.com")) { | ||
embedTwitter(video, container, videoClass); | ||
} | ||
else if (video.videoUrl.includes("vimeo.com")) { | ||
embedVimeo(video, container, videoClass); | ||
} | ||
else if (video.videoUrl.includes("dailymotion.com") || video.videoUrl.includes("dailymotion")) { | ||
embedDailymotion(video, container, videoClass); | ||
} | ||
else { | ||
throw new Error("Invalid video URL"); | ||
} | ||
}); | ||
}; | ||
}; | ||
const embed = (selector) => { | ||
const embedDiv = document.querySelector('.' + selector); // Prepend a dot symbol | ||
const videoUrl = embedDiv.getAttribute("data-e-url"); | ||
if (videoUrl.includes("vimeo.com")) { | ||
embedVimeo(embedDiv); | ||
} else if (videoUrl.includes("youtube.com") || videoUrl.includes("youtu.be")) { | ||
embedYouTube(embedDiv); | ||
} else if (videoUrl.includes("tiktok.com") || videoUrl.includes("tiktok")) { | ||
embedTiktok(embedDiv); | ||
} else if (videoUrl.includes("dailymotion.com") || videoUrl.includes("dailymotion")) { | ||
embedDailymotion(embedDiv); | ||
} else if (videoUrl.includes("twitter.com")) { | ||
embedTwitter(embedDiv); | ||
} else { | ||
throw new Error("Invalid video URL"); | ||
} | ||
}; | ||
export default embed; | ||
@@ -409,0 +482,0 @@ |
import './miraxplayerUI.js'; | ||
export function miraxPlayer(videoClip) { | ||
function miraxPlayer(playerDiv) { | ||
// Check if the control elements have already been created | ||
const existingControls = videoClip.parentNode.querySelector('.mirax-theme'); | ||
const existingControls = playerDiv.parentNode.querySelector('.mirax-theme'); | ||
if (existingControls) { | ||
return; | ||
} | ||
// Create control elements | ||
const controlDiv = document.createElement("div"); | ||
// Append the control div to the videoClip element's parent node | ||
videoClip.parentNode.appendChild(controlDiv); | ||
// Append the control div to the playerDiv element's parent node | ||
playerDiv.parentNode.appendChild(controlDiv); | ||
// Error Handler if video file not exist or not found | ||
videoClip.addEventListener("error", function () { | ||
playerDiv.addEventListener("error", function () { | ||
// Check the networkState | ||
if (this.networkState > 2) { | ||
// Create a text element | ||
const videoText = document.createElement("p"); | ||
// Set the text content | ||
videoText.textContent = "Video not found"; | ||
// Set the class name | ||
videoText.className = "video-text"; | ||
// Append the text element to the video element's parent node | ||
this.parentNode.appendChild(videoText); | ||
} | ||
}); | ||
@@ -86,50 +54,15 @@ | ||
//**********************************************// | ||
// | ||
// Player THEME | ||
// | ||
//*********************************************// | ||
const playerTheme = videoClip.getAttribute("data-player-theme"); | ||
const playerTheme = playerDiv.getAttribute("data-player-theme"); | ||
controlDiv.className = "mirax-theme"; | ||
controlDiv.style.backgroundColor = playerTheme; | ||
@@ -141,220 +74,108 @@ | ||
//**********************************************// | ||
// | ||
// PIP ( Picture in Picture ) | ||
// | ||
//*********************************************// | ||
const pipButton = document.createElement('mirax'); | ||
pipButton.className = 'pip-button'; | ||
controlDiv.appendChild(pipButton); | ||
pipButton.addEventListener('click', () => { | ||
if (document.pictureInPictureElement) { | ||
// Exit PiP | ||
document.exitPictureInPicture(); | ||
} else if (videoClip !== document.pictureInPictureElement) { | ||
} else if (playerDiv !== document.pictureInPictureElement) { | ||
// Request PiP | ||
videoClip.requestPictureInPicture(); | ||
playerDiv.requestPictureInPicture(); | ||
} | ||
}); | ||
videoClip.addEventListener('enterpictureinpicture', handleEnterPiP); | ||
videoClip.addEventListener('leavepictureinpicture', handleLeavePiP); | ||
playerDiv.addEventListener('enterpictureinpicture', handleEnterPiP); | ||
playerDiv.addEventListener('leavepictureinpicture', handleLeavePiP); | ||
function handleEnterPiP() { | ||
// Update UI or perform actions when entering PiP | ||
console.log('Enter PiP mode'); | ||
} | ||
function handleLeavePiP() { | ||
// Update UI or perform actions when leaving PiP | ||
console.log('Exited PiP mode'); | ||
} | ||
document.addEventListener('keydown', (event) => { | ||
// Check if Alt+P is pressed | ||
if (event.altKey && event.code === 'KeyP') { | ||
// Toggle PiP mode | ||
if (document.pictureInPictureElement) { | ||
document.exitPictureInPicture(); | ||
} else { | ||
videoClip.requestPictureInPicture(); | ||
playerDiv.requestPictureInPicture(); | ||
} | ||
} | ||
}); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Play Button | ||
// | ||
//*********************************************// | ||
// Define event listener and function for the play button | ||
const playButton = document.createElement('mirax'); | ||
playButton.className = 'play-button'; | ||
playButton.addEventListener('click', playerButton); | ||
controlDiv.appendChild(playButton); | ||
function playerButton() { | ||
if (videoClip.paused) { | ||
videoClip.play(); | ||
if (playerDiv.paused) { | ||
playerDiv.play(); | ||
playButton.classList.add("pause"); // Add the pause class name | ||
} else { | ||
videoClip.pause(); | ||
playerDiv.pause(); | ||
playButton.classList.remove("pause"); // Remove the pause class name | ||
} | ||
} | ||
// Add event listener to the video element itself to toggle play state | ||
videoClip.addEventListener('click', () => { | ||
if (videoClip.paused) { | ||
videoClip.play(); | ||
playerDiv.addEventListener('click', () => { | ||
if (playerDiv.paused) { | ||
playerDiv.play(); | ||
playButton.classList.add("pause"); | ||
} else { | ||
videoClip.pause(); | ||
playerDiv.pause(); | ||
playButton.classList.remove("pause"); | ||
} | ||
}); | ||
// Update the styles or UI of the play button based on video state | ||
function updatePlayButton() { | ||
if (videoClip.paused) { | ||
if (playerDiv.paused) { | ||
playButton.classList.remove("pause"); | ||
} else { | ||
playButton.classList.add("pause"); | ||
} | ||
} | ||
// Listen to video play and pause events | ||
videoClip.addEventListener('play', updatePlayButton); | ||
videoClip.addEventListener('pause', updatePlayButton); | ||
playerDiv.addEventListener('play', updatePlayButton); | ||
playerDiv.addEventListener('pause', updatePlayButton); | ||
@@ -364,42 +185,20 @@ | ||
//**********************************************// | ||
// | ||
// Backward Button >> | ||
// | ||
//*********************************************// | ||
const backwardButton = document.createElement('mirax'); | ||
backwardButton.className = 'backward-button'; | ||
backwardButton.addEventListener('click', backwarderButton); | ||
controlDiv.appendChild(backwardButton); | ||
function backwarderButton() { | ||
// Backward the video by 10 seconds | ||
videoClip.currentTime = Math.max(videoClip.currentTime - 10, 0); | ||
playerDiv.currentTime = Math.max(playerDiv.currentTime - 10, 0); | ||
} | ||
@@ -413,52 +212,23 @@ | ||
//**********************************************// | ||
// | ||
// Forward Button >> | ||
// | ||
//*********************************************// | ||
const forwardButton = document.createElement('mirax'); | ||
forwardButton.className = 'forward-button'; | ||
forwardButton.addEventListener('click', forwarderButton); | ||
controlDiv.appendChild(forwardButton); | ||
function forwarderButton() { | ||
// Forward the video by 10 seconds | ||
videoClip.currentTime = Math.min(videoClip.currentTime + 10, videoClip.duration); | ||
playerDiv.currentTime = Math.min(playerDiv.currentTime + 10, playerDiv.duration); | ||
} | ||
@@ -468,132 +238,70 @@ | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Play video - press space bar | ||
// | ||
//*********************************************// | ||
// Add keydown event listener to the document | ||
document.addEventListener('keydown', function(event) { | ||
// Check if the pressed key is the space bar | ||
// Check if the pressed key ctrl and space bar | ||
if (event.code === 'Space') { | ||
// Prevent the default action of scrolling | ||
event.preventDefault(); | ||
// Call the same function that you use for the play button | ||
playerButton(); | ||
if (event.ctrlKey) { // CTRL + SPACEBAR | ||
// Call the same function that you use for the play button | ||
playerButton(); | ||
} | ||
} | ||
}); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Volume slider | ||
// | ||
//*********************************************// | ||
let prevVolume = 1; | ||
// Create the volume input element | ||
const volumeInput = document.createElement('input'); | ||
volumeInput.type = 'range'; | ||
volumeInput.className = 'volume-slider'; | ||
volumeInput.min = '0'; | ||
volumeInput.max = '1'; | ||
volumeInput.step = '0.01'; | ||
volumeInput.defaultValue = '1'; | ||
// Add event listener to update volume | ||
volumeInput.addEventListener('input', function() { | ||
videoClip.volume = parseFloat(this.value); | ||
playerDiv.volume = parseFloat(this.value); | ||
}); | ||
controlDiv.appendChild(volumeInput); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Speed Options | ||
// | ||
//*********************************************// | ||
@@ -603,275 +311,137 @@ | ||
//**********************************************// | ||
// | ||
// Speed Options | ||
// | ||
//*********************************************// | ||
// Create a div element for the gear icon container | ||
const gearIconContainer = document.createElement('div'); | ||
gearIconContainer.className = 'gear-icon'; | ||
gearIconContainer.style.width = '12px'; | ||
gearIconContainer.style.height = '12px'; | ||
gearIconContainer.style.position = 'absolute'; | ||
gearIconContainer.style.right = '29px'; | ||
gearIconContainer.style.right = '39px'; | ||
gearIconContainer.style.top = '9px'; | ||
gearIconContainer.style.cursor = 'pointer'; | ||
// Create a div element for the gear outer circle | ||
const outerCircle = document.createElement('div'); | ||
outerCircle.className = 'outer-circle'; | ||
outerCircle.style.width = '12px'; | ||
outerCircle.style.height = '12px'; | ||
outerCircle.style.border = '1px solid white'; // Adjust border properties as needed | ||
outerCircle.style.borderRadius = '50%'; | ||
outerCircle.style.position = 'absolute'; | ||
outerCircle.style.boxSizing = 'border-box'; | ||
const horizontalLine = document.createElement('div'); | ||
horizontalLine.className = 'horizontal-line'; | ||
horizontalLine.style.width = '6px'; // Adjust the width as needed | ||
horizontalLine.style.height = '2px'; | ||
horizontalLine.style.backgroundColor = 'white'; // Change color as needed | ||
horizontalLine.style.position = 'absolute'; | ||
horizontalLine.style.top = '55%'; | ||
horizontalLine.style.left = '35%'; | ||
horizontalLine.style.transform = 'translate(-50%, -50%)'; | ||
// Create a div element for the vertical line of the "L" flip shape | ||
const verticalLine = document.createElement('div'); | ||
verticalLine.className = 'vertical-line'; | ||
verticalLine.style.width = '2px'; | ||
verticalLine.style.height = '6px'; // Adjust the height as needed | ||
verticalLine.style.backgroundColor = 'white'; // Change color as needed | ||
verticalLine.style.position = 'absolute'; | ||
verticalLine.style.top = '30%'; | ||
verticalLine.style.left = '50%'; | ||
verticalLine.style.transform = 'translate(-50%, -50%)'; | ||
// Append the horizontal and vertical lines to the gear icon container | ||
gearIconContainer.appendChild(horizontalLine); | ||
gearIconContainer.appendChild(verticalLine); | ||
// Append the outer circle to the gear icon container | ||
gearIconContainer.appendChild(outerCircle); | ||
// Add the gear icon container to your player's UI | ||
controlDiv.appendChild(gearIconContainer); | ||
// Create a div element for the tooltip | ||
const tooltip = document.createElement('div'); | ||
tooltip.className = 'tooltip'; | ||
tooltip.style.width = '80px'; | ||
tooltip.style.height = '150px'; | ||
tooltip.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; | ||
tooltip.style.color = 'white'; | ||
tooltip.style.position = 'absolute'; | ||
tooltip.style.display = 'none'; | ||
tooltip.style.zIndex = '100'; | ||
tooltip.style.fontFamily = 'Arial, Corbel'; | ||
tooltip.style.fontWeight = 'normal'; | ||
tooltip.style.fontSize = '11px'; | ||
tooltip.style.lineHeight = '19px'; | ||
// Adjust the top property to make the tooltip appear above the gear icon | ||
tooltip.style.right = '40px'; | ||
tooltip.style.bottom = '30px'; // Change this value to position the tooltip above the gear icon | ||
tooltip.style.padding = '5px'; | ||
// Create a div element for the tooltipzz | ||
// Add speed options to the tooltip | ||
const tooltipzz = document.createElement('div'); | ||
tooltipzz.className = 'tooltipzz'; | ||
tooltipzz.style.width = '80px'; | ||
tooltipzz.style.height = '160px'; | ||
tooltipzz.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; | ||
tooltipzz.style.color = 'white'; | ||
tooltipzz.style.position = 'absolute'; | ||
tooltipzz.style.display = 'none'; | ||
tooltipzz.style.zIndex = '100'; | ||
tooltipzz.style.fontFamily = 'Arial, Corbel'; | ||
tooltipzz.style.fontWeight = 'normal'; | ||
tooltipzz.style.fontSize = '11px'; | ||
tooltipzz.style.lineHeight = '19px'; | ||
// Adjust the top property to make the tooltipzz appear above the gear icon | ||
tooltipzz.style.right = '40px'; | ||
tooltipzz.style.bottom = '-5px'; // Change this value to position the tooltipzz above the gear icon | ||
tooltipzz.style.padding = '5px'; | ||
// Add speed options to the tooltipzz | ||
// Add speed options to the tooltip | ||
const speedOptions = [ | ||
{ value: 0.25, label: '0.25x' }, | ||
{ value: 0.5, label: '0.5x' }, | ||
{ value: 0.75, label: '0.75x' }, | ||
{ value: 1, label: 'Normal' }, | ||
{ value: 1.25, label: '1.25x' }, | ||
{ value: 1.5, label: '1.5x' }, | ||
{ value: 1.75, label: '1.75x' }, | ||
{ value: 2, label: '2x' } | ||
]; | ||
let selectedOption = null; // Track the selected option | ||
speedOptions.forEach((option) => { | ||
const optionElement = document.createElement('div'); | ||
optionElement.className = 'speed-option'; // Add this class for event handling | ||
optionElement.textContent = option.label; | ||
optionElement.style.cursor = 'pointer'; | ||
tooltip.appendChild(optionElement); | ||
tooltipzz.appendChild(optionElement); | ||
optionElement.addEventListener('click', () => { | ||
// Extract the numeric value from the label | ||
const speedValue = parseFloat(option.value); | ||
changePlaybackSpeed(speedValue); | ||
// Update the selected option and indicator | ||
selectedOption = optionElement; | ||
updateSelectedIndicator(); | ||
}); | ||
// Add mouseover and mouseout event listeners to change background color | ||
optionElement.addEventListener('mouseover', () => { | ||
optionElement.style.backgroundColor = 'rgba(45, 85, 255, 0.8)'; // Blue background on hover | ||
}); | ||
optionElement.addEventListener('mouseout', () => { | ||
// Remove background color on mouseout, but skip the selected option | ||
if (optionElement !== selectedOption) { | ||
optionElement.style.backgroundColor = ''; | ||
} | ||
}); | ||
}); | ||
// Function to update the visual indicator for the selected option | ||
function updateSelectedIndicator() { | ||
speedOptionElements.forEach((optionElement) => { | ||
if (optionElement === selectedOption) { | ||
optionElement.style.backgroundColor = 'rgba(45, 85, 255, 1)'; // Set the selected option's background color | ||
optionElement.style.color = 'white'; // Set text color for better visibility | ||
optionElement.style.borderRadius = '2px'; | ||
} else { | ||
optionElement.style.backgroundColor = ''; // Remove background color from other options | ||
optionElement.style.color = ''; // Remove text color from other options | ||
} | ||
}); | ||
} | ||
@@ -884,77 +454,36 @@ | ||
// Add the tooltip to the player's UI | ||
controlDiv.appendChild(tooltip); | ||
// Remove the initial 'display: none' style from the tooltip | ||
tooltip.style.display = 'none'; | ||
// Add the tooltipzz to the player's UI | ||
controlDiv.appendChild(tooltipzz); | ||
// Remove the initial 'display: none' style from the tooltipzz | ||
tooltipzz.style.display = 'none'; | ||
// Add event listeners for mouseover and mouseout to show/hide the tooltipzz | ||
// Add event listeners for mouseover and mouseout to show/hide the tooltip | ||
gearIconContainer.addEventListener('mouseover', () => showTooltip()); | ||
tooltip.addEventListener('mouseover', () => showTooltip()); | ||
tooltip.addEventListener('mouseout', () => hideTooltip()); | ||
tooltipzz.addEventListener('mouseover', () => showTooltip()); | ||
tooltipzz.addEventListener('mouseout', () => hideTooltip()); | ||
// Function to show the tooltipzz | ||
// Function to show the tooltip | ||
function showTooltip() { | ||
tooltipzz.style.display = 'block'; | ||
tooltip.style.display = 'block'; | ||
} | ||
// Function to hide the tooltipzz | ||
// Function to hide the tooltip | ||
function hideTooltip() { | ||
tooltipzz.style.display = 'none'; | ||
tooltip.style.display = 'none'; | ||
} | ||
// Add event listeners to the speed options in the tooltipzz | ||
const speedOptionElements = tooltipzz.querySelectorAll('.speed-option'); | ||
// Add event listeners to the speed options in the tooltip | ||
const speedOptionElements = tooltip.querySelectorAll('.speed-option'); | ||
speedOptionElements.forEach((optionElement) => { | ||
optionElement.addEventListener('click', () => { | ||
const speedValue = parseFloat(optionElement.textContent); | ||
changePlaybackSpeed(speedValue); | ||
}); | ||
}); | ||
// Function to change the playback speed of the video | ||
function changePlaybackSpeed(speed) { | ||
videoClip.playbackRate = speed; | ||
playerDiv.playbackRate = speed; | ||
hideTooltip(); | ||
} | ||
@@ -970,68 +499,30 @@ | ||
//**********************************************// | ||
// | ||
// Speaker UI icon | ||
// | ||
//*********************************************// | ||
let xSymbolInterval; | ||
// Function to toggle the visibility of the xSymbol | ||
function toggleXSymbol() { | ||
xSymbol.style.visibility = xSymbol.style.visibility === 'visible' ? 'hidden' : 'visible'; | ||
} | ||
// Add event listener to update xSymbol visibility when video play/pause | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1042,47 +533,22 @@ | ||
// Create a div element for the speaker icon container | ||
const speakerIconContainer = document.createElement('div'); | ||
speakerIconContainer.className = 'speaker-icon'; | ||
speakerIconContainer.style.width = '20px'; | ||
speakerIconContainer.style.height = '50px'; | ||
speakerIconContainer.style.position = 'absolute'; | ||
speakerIconContainer.style.marginRight = '87px'; | ||
speakerIconContainer.style.right = '0'; // Set the right property to auto | ||
speakerIconContainer.style.cursor = 'pointer'; | ||
// Get the volume slider element | ||
const volumeSlider = document.querySelector('.volume-slider'); | ||
volumeSlider.style.opacity = '0'; // Initially hide the volume slider | ||
// Add a mouseenter event listener to show the volume slider when hovering over the speaker icon | ||
speakerIconContainer.addEventListener('mouseenter', () => { | ||
volumeSlider.style.opacity = '1'; | ||
}); | ||
// Gear Icon pure javascript: | ||
@@ -1096,86 +562,40 @@ | ||
// Add a wheel event listener to the volume slider | ||
volumeSlider.addEventListener('wheel', function (event) { | ||
// Prevent the default scrolling behavior | ||
event.preventDefault(); | ||
// Calculate the new volume value based on the mouse wheel delta | ||
const delta = event.deltaY > 0 ? -0.1 : 0.1; // Adjust the step as needed | ||
let newVolume = parseFloat(this.value) + delta; | ||
// Ensure the volume stays within the range [0, 1] | ||
newVolume = Math.max(0, Math.min(1, newVolume)); | ||
// Update the volume slider value and video volume | ||
this.value = newVolume; | ||
playerDiv.volume = newVolume; | ||
videoClip.volume = newVolume; | ||
// Update the x symbol based on the volume value | ||
if (newVolume === 0) { | ||
xSymbol.textContent = 'x'; | ||
volumeInput.style.backgroundColor = '#FF004F'; | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
speakerBox.style.backgroundColor = '#FF004F'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1186,55 +606,26 @@ | ||
} | ||
else if (newVolume <= 0.5 ) { | ||
xSymbol.textContent = '|'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
volumeInput.style.backgroundColor = 'orange'; | ||
xSymbol.style.color = 'orange'; | ||
speakerBox.style.backgroundColor = 'orange'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
@@ -1248,64 +639,29 @@ | ||
} | ||
else { | ||
xSymbol.textContent = ')'; | ||
volumeInput.style.backgroundColor = 'white'; | ||
speakerBox.style.backgroundColor = 'white'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
} | ||
}); | ||
@@ -1323,20 +679,5 @@ | ||
// Add a mouseleave event listener to hide the volume slider when not hovering over the speaker icon | ||
speakerIconContainer.addEventListener('mouseleave', () => { | ||
volumeSlider.style.opacity = '0'; | ||
}); | ||
@@ -1347,81 +688,39 @@ | ||
// Add a wheel event listener to the speaker icon container | ||
speakerIconContainer.addEventListener('wheel', function (event) { | ||
// Prevent the default scrolling behavior | ||
event.preventDefault(); | ||
// Calculate the new volume value based on the mouse wheel delta | ||
const delta = event.deltaY > 0 ? -0.1 : 0.1; // Adjust the step as needed | ||
let newVolume = parseFloat(volumeSlider.value) + delta; | ||
// Ensure the volume stays within the range [0, 1] | ||
newVolume = Math.max(0, Math.min(1, newVolume)); | ||
// Update the volume slider value and video volume | ||
volumeSlider.value = newVolume; | ||
playerDiv.volume = newVolume; | ||
videoClip.volume = newVolume; | ||
// Update the x symbol based on the volume value | ||
if (newVolume === 0) { | ||
volumeInput.style.backgroundColor = '#FF004F'; | ||
xSymbol.textContent = 'x'; | ||
xSymbol.style.fontSize= '11px'; | ||
xSymbol.style.top = '16px'; | ||
xSymbol.style.top = '18px'; | ||
xSymbol.style.color = 'white'; | ||
speakerBox.style.backgroundColor = '#FF004F'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1431,50 +730,24 @@ | ||
} | ||
else if (newVolume <= 0.5 ) { | ||
xSymbol.textContent = '|'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
volumeInput.style.backgroundColor = 'orange'; | ||
speakerBox.style.backgroundColor = 'orange'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
@@ -1484,62 +757,30 @@ | ||
} | ||
else { | ||
xSymbol.textContent = ')'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
volumeInput.style.backgroundColor = 'white'; | ||
speakerBox.style.backgroundColor = 'white'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
} | ||
}); | ||
@@ -1550,25 +791,11 @@ | ||
// Add a mouseenter event listener to show the volume slider when hovering over the volume slider | ||
volumeSlider.addEventListener('mouseenter', () => { | ||
volumeSlider.style.opacity = '1'; | ||
}); | ||
// Add a mouseleave event listener to hide the volume slider when not hovering over the volume slider | ||
volumeSlider.addEventListener('mouseleave', () => { | ||
volumeSlider.style.opacity = '0'; | ||
}); | ||
@@ -1579,43 +806,36 @@ | ||
// Create a div element for the speaker box | ||
const speakerBox = document.createElement('div'); | ||
speakerBox.className = 'box'; | ||
speakerBox.style.width = '6px'; | ||
speakerBox.style.height = '6px'; | ||
speakerBox.style.backgroundColor = 'white'; | ||
speakerBox.style.position = 'absolute'; | ||
speakerBox.style.left = '3px'; | ||
speakerBox.style.top = '22px'; | ||
const speakerTrapezoid = document.createElement('div'); | ||
speakerTrapezoid.className = 'speakerTrapezoid'; | ||
speakerTrapezoid.style.borderBottom = '6px solid white'; | ||
speakerTrapezoid.style.borderLeft = '3px solid transparent'; | ||
speakerTrapezoid.style.borderRight = '3px solid transparent'; | ||
speakerTrapezoid.style.height = '10'; | ||
speakerTrapezoid.style.width = '6px'; | ||
speakerTrapezoid.style.transform = 'rotate(-90deg)'; | ||
speakerTrapezoid.style.marginLeft ='2px'; | ||
speakerTrapezoid.style.marginTop ='22px'; | ||
document.body.appendChild(speakerTrapezoid); | ||
// Append the speaker box and cone to the speaker icon container | ||
speakerIconContainer.appendChild(speakerBox); | ||
speakerIconContainer.appendChild(speakerTrapezoid); | ||
// Append the speaker icon container to the controlDiv | ||
controlDiv.appendChild(speakerIconContainer); | ||
@@ -1625,92 +845,45 @@ | ||
//______________________________________________________________________ | ||
// Create a span element for the ")" symbol | ||
const xSymbol = document.createElement('span'); | ||
xSymbol.className = 'x-symbol'; | ||
xSymbol.textContent = ')'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.color = 'white'; // Set the color to white once | ||
xSymbol.style.position = 'absolute'; | ||
xSymbol.style.left = '15px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
xSymbol.style.fontFamily = 'Arial, Corbel'; | ||
// Append the ")" symbol to the speaker icon container | ||
speakerIconContainer.appendChild(xSymbol); | ||
// Add event listener to update volume and x symbol | ||
volumeInput.addEventListener('input', function () { | ||
// Use the video element directly | ||
playerDiv.volume = parseFloat(this.value); | ||
videoClip.volume = parseFloat(this.value); | ||
// Update the x symbol based on the volume value | ||
if (videoClip.volume === 0) { | ||
if (playerDiv.volume === 0) { | ||
xSymbol.textContent = 'x'; | ||
xSymbol.style.fontSize = '11px'; | ||
xSymbol.style.top = '16px'; | ||
xSymbol.style.top = '18px'; | ||
// Change the background color of the volume slider to #FF004F | ||
volumeInput.style.backgroundColor = '#FF004F'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1721,53 +894,25 @@ | ||
} | ||
else if (videoClip.volume <= 0.5 ) { | ||
else if (playerDiv.volume <= 0.5 ) { | ||
xSymbol.textContent = '|'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
volumeInput.style.backgroundColor = 'orange'; | ||
speakerBox.style.backgroundColor = 'orange'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'orange'; | ||
}); | ||
@@ -1779,54 +924,25 @@ | ||
} | ||
else { | ||
xSymbol.textContent = ')'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
volumeInput.style.backgroundColor = 'white'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1836,8 +952,3 @@ | ||
} | ||
}); | ||
@@ -1849,78 +960,37 @@ | ||
// Add event listener to the speaker icon container | ||
speakerIconContainer.addEventListener("click", function() { | ||
// Toggle the mute state of the video element | ||
videoClip.muted = !videoClip.muted; | ||
playerDiv.muted = !playerDiv.muted; | ||
// Change the color of the speaker icon based on the mute state | ||
if (videoClip.muted) { | ||
if (playerDiv.muted) { | ||
// Set the color to gray | ||
speakerBox.style.backgroundColor = "#FF004F"; | ||
// Change the background color of the volume slider to #FF004F | ||
xSymbol.textContent = 'x'; | ||
xSymbol.style.fontSize = '11px'; | ||
xSymbol.style.top = '16px'; | ||
xSymbol.style.top = '18px'; | ||
volumeInput.style.backgroundColor = '#FF004F'; | ||
prevVolume = volumeInput.value; | ||
volumeInput.value = '0'; | ||
videoClip.volume = 0; | ||
playerDiv.volume = 0; | ||
speakerBox.style.backgroundColor = '#FF004F'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
@@ -1930,92 +1000,45 @@ | ||
} else { | ||
// Set the color to white | ||
speakerBox.style.backgroundColor = "white"; | ||
volumeInput.style.backgroundColor = 'white'; | ||
xSymbol.textContent = ')'; | ||
xSymbol.style.fontSize = '8px'; | ||
xSymbol.style.top = '19px'; | ||
xSymbol.style.top = '20px'; | ||
// Restore the previous volume value after unmuting | ||
volumeInput.value = prevVolume; | ||
videoClip.volume = parseFloat(prevVolume); | ||
playerDiv.volume = parseFloat(prevVolume); | ||
speakerBox.style.backgroundColor = 'white'; | ||
videoClip.addEventListener('play', () => { | ||
playerDiv.addEventListener('play', () => { | ||
// Start toggling the symbol every 500 milliseconds (adjust timing as needed) | ||
xSymbolInterval = setInterval(toggleXSymbol, 700); | ||
xSymbol.style.color = 'white'; | ||
}); | ||
videoClip.addEventListener('pause', () => { | ||
playerDiv.addEventListener('pause', () => { | ||
// Stop toggling and make the symbol visible | ||
clearInterval(xSymbolInterval); | ||
xSymbol.style.visibility = 'visible'; | ||
xSymbol.style.color = 'white'; | ||
}); | ||
} | ||
}); | ||
//**********************************************// | ||
// | ||
// Progress bar slider with scroll bar, mouse wheel, and keyboard shortcuts | ||
// | ||
//*********************************************// | ||
const progressBar = document.createElement('progress'); | ||
progressBar.className = 'progress-bar'; | ||
progressBar.min = '0'; | ||
progressBar.max = '100'; | ||
progressBar.value = '0'; | ||
controlDiv.appendChild(progressBar); | ||
@@ -2025,124 +1048,61 @@ | ||
videoClip.addEventListener('timeupdate', function() { | ||
const percentPlayed = (videoClip.currentTime / videoClip.duration) * 100; | ||
playerDiv.addEventListener('timeupdate', function() { | ||
const percentPlayed = (playerDiv.currentTime / playerDiv.duration) * 100; | ||
progressBar.value = percentPlayed; | ||
}); | ||
progressBar.addEventListener('mousedown', function(e) { | ||
handleProgressBarClick(e); | ||
}); | ||
// Function to handle mouse wheel events | ||
progressBar.addEventListener('wheel', function(e) { | ||
e.preventDefault(); // Prevent the default scroll behavior | ||
const delta = e.deltaY; // Get the scrolling direction (positive or negative) | ||
// Adjust the video's current time based on the scrolling direction | ||
const step = 1; // You can adjust the step size as needed | ||
const currentTime = playerDiv.currentTime + (delta > 0 ? step : -step); | ||
const currentTime = videoClip.currentTime + (delta > 0 ? step : -step); | ||
// Ensure the currentTime stays within the video's duration limits | ||
playerDiv.currentTime = Math.min(Math.max(currentTime, 0), playerDiv.duration); | ||
videoClip.currentTime = Math.min(Math.max(currentTime, 0), videoClip.duration); | ||
// Update the progress bar value | ||
progressBar.value = (videoClip.currentTime / videoClip.duration) * 100; | ||
progressBar.value = (playerDiv.currentTime / playerDiv.duration) * 100; | ||
}); | ||
function handleProgressBarClick(e) { | ||
const rect = progressBar.getBoundingClientRect(); | ||
const offsetX = e.clientX - rect.left; | ||
const newProgress = (offsetX / rect.width) * 100; | ||
playerDiv.currentTime = (newProgress / 100) * playerDiv.duration; | ||
videoClip.currentTime = (newProgress / 100) * videoClip.duration; | ||
const onMouseMove = function(e) { | ||
const offsetX = e.clientX - rect.left; | ||
const newProgress = (offsetX / rect.width) * 100; | ||
videoClip.currentTime = (newProgress / 100) * videoClip.duration; | ||
playerDiv.currentTime = (newProgress / 100) * playerDiv.duration; | ||
}; | ||
const onMouseUp = function() { | ||
document.removeEventListener('mousemove', onMouseMove); | ||
document.removeEventListener('mouseup', onMouseUp); | ||
}; | ||
document.addEventListener('mousemove', onMouseMove); | ||
document.addEventListener('mouseup', onMouseUp); | ||
} | ||
// Function to handle keyboard shortcuts | ||
document.addEventListener('keydown', function(e) { | ||
if (e.key === 'ArrowLeft') { | ||
// Rewind the video by 10 seconds | ||
videoClip.currentTime = Math.max(videoClip.currentTime - 10, 0); | ||
playerDiv.currentTime = Math.max(playerDiv.currentTime - 10, 0); | ||
e.preventDefault(); // Prevent the default behavior of scrolling the page | ||
} else if (e.key === 'ArrowRight') { | ||
// Forward the video by 10 seconds | ||
videoClip.currentTime = Math.min(videoClip.currentTime + 10, videoClip.duration); | ||
playerDiv.currentTime = Math.min(playerDiv.currentTime + 10, playerDiv.duration); | ||
e.preventDefault(); // Prevent the default behavior of scrolling the page | ||
} | ||
}); | ||
@@ -2153,15 +1113,6 @@ | ||
//**********************************************// | ||
// | ||
// Dynamic Player Width | ||
// | ||
//*********************************************// | ||
@@ -2174,2 +1125,4 @@ | ||
const dynamicWidth = playerDiv.getAttribute("data-player-width"); | ||
const dynamicFloat = playerDiv.getAttribute("data-player-float"); | ||
@@ -2182,56 +1135,20 @@ | ||
const dynamicWidth = videoClip.getAttribute("data-player-width"); | ||
const dynamicFloat = videoClip.getAttribute("data-player-float"); | ||
const inputPlayerClip = document.createElement('style'); | ||
document.head.appendChild(inputPlayerClip); | ||
const inputPlayerClipStyle = ` | ||
.mirax-player { | ||
min-width:300px; | ||
min-width:350px; | ||
max-width: ${dynamicWidth + 400}px; | ||
width: 100%; /* This ensures the video fills its container while respecting max-width */ | ||
height: auto; /* This maintains the video's aspect ratio */ | ||
min-height:100px; | ||
max-height:450px; | ||
background-color: #000000; | ||
margin: 0 auto; | ||
} | ||
:root { | ||
--progress-width: 100%; | ||
} | ||
@@ -2241,58 +1158,45 @@ | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
display: none; | ||
transition: transform 0.3s; | ||
} | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
display: block; | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
height: 20px; | ||
min-width:350px; | ||
max-width: 95%; | ||
min-width: 300px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
margin-top:-44px; | ||
bottom: 0; | ||
left: 10; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
padding-top:5px; | ||
padding-bottom:5px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
} | ||
.progress-bar { | ||
display: block; | ||
margin: 0 auto; | ||
position: relative; | ||
margin-top:-49px; | ||
margin-top:-36px; | ||
width: 100%; | ||
width: var(--progress-width); | ||
max-width: var(--progress-max-width); | ||
height: 14px; | ||
background-color: rgba(0, 0, 0, 0.1); | ||
height: 6px; | ||
background-color: rgba(255, 255, 255, 0.1); | ||
border-style: none; | ||
} | ||
@@ -2302,21 +1206,11 @@ | ||
.player-selector { | ||
margin: 0 auto; | ||
width: 100%; | ||
max-width: ${dynamicWidth}px; | ||
position: relative; | ||
float: ${dynamicFloat}; | ||
text-align: center; | ||
} | ||
`; | ||
inputPlayerClip.appendChild(document.createTextNode(inputPlayerClipStyle)); | ||
@@ -2333,129 +1227,60 @@ | ||
//**********************************************// | ||
// | ||
// Timestamp Math System | ||
// | ||
//*********************************************// | ||
// After creating the currentTimeDiv | ||
const currentTimeDiv = document.createElement('div'); | ||
currentTimeDiv.className = 'current-time'; | ||
controlDiv.appendChild(currentTimeDiv); | ||
// After creating the timeDurationDiv | ||
const timeDurationDiv = document.createElement('div'); | ||
timeDurationDiv.className = 'time-duration'; | ||
controlDiv.appendChild(timeDurationDiv); | ||
// Set the initial margin-left to 40px for timeDurationDiv | ||
timeDurationDiv.style.marginLeft = '40px'; | ||
currentTimeDiv.style.marginLeft = '10px'; | ||
currentTimeDiv.style.textAlign = 'right'; | ||
// Listen to the timeupdate event to update the current time and adjust margin | ||
playerDiv.addEventListener('timeupdate', updateCurrentTime); | ||
videoClip.addEventListener('timeupdate', updateCurrentTime); | ||
// Function to update the current time in the currentTimeDiv | ||
function updateCurrentTime() { | ||
const currentTime = videoClip.currentTime; | ||
const currentTime = playerDiv.currentTime; | ||
const formattedTime = formatTime(currentTime); | ||
currentTimeDiv.textContent = formattedTime; | ||
timeDurationDiv.style.opacity = '1'; | ||
// Check if the current time is greater than or equal to 1 minute (01:00) | ||
if (currentTime >= 60) { | ||
// #FF004Fuce marginLeft by 40px | ||
timeDurationDiv.style.marginLeft = '40px'; | ||
} | ||
// Check if the current time is greater than or equal to 10 minutes (10:00) | ||
if (currentTime >= 600) { | ||
// #FF004Fuce marginLeft by 45px | ||
timeDurationDiv.style.marginLeft = '45px'; | ||
} | ||
// Check if the current time is greater than or equal to 1 hour (01:00:00) | ||
if (currentTime >= 3600) { | ||
// #FF004Fuce marginLeft by 63px | ||
timeDurationDiv.style.marginLeft = '63px'; | ||
} | ||
// Check if the current time is greater than or equal to 10 hour (10:00:00) | ||
if (currentTime >= 36000) { | ||
// #FF004Fuce marginLeft by 69px | ||
timeDurationDiv.style.marginLeft = '69px'; | ||
} | ||
} | ||
@@ -2465,132 +1290,70 @@ | ||
// Function to update time duration | ||
function updateDuration(videoClip, timeDurationDiv) { | ||
if (!isNaN(videoClip.duration)) { | ||
const formattedDuration = formatTime(videoClip.duration); | ||
function updateDuration(playerDiv, timeDurationDiv) { | ||
if (!isNaN(playerDiv.duration)) { | ||
const formattedDuration = formatTime(playerDiv.duration); | ||
timeDurationDiv.textContent = formattedDuration; | ||
} | ||
} | ||
// Function to format time in HH:MM:SS with conditional zero-padding | ||
function formatTime(seconds) { | ||
const hours = Math.floor(seconds / 3600); | ||
const minutes = Math.floor((seconds % 3600) / 60); | ||
const secs = Math.floor(seconds % 60); | ||
let formattedTime = ''; | ||
if (hours >= 1) { | ||
formattedTime += `${hours.toString()}:`; | ||
} | ||
formattedTime += `${minutes.toString().padStart(1, '0')}:${secs.toString().padStart(2, '0')}`; | ||
return formattedTime; | ||
} | ||
// Set initial content of currentTimeDiv | ||
currentTimeDiv.textContent = formatTime(0); | ||
// Listen to the timeupdate event to update the current time and adjust margin | ||
playerDiv.addEventListener('timeupdate', updateCurrentTime); | ||
videoClip.addEventListener('timeupdate', updateCurrentTime); | ||
// Listen to the loadedmetadata event to update time duration and adjust margin | ||
playerDiv.addEventListener('loadedmetadata', () => updateDuration(playerDiv, timeDurationDiv)); | ||
videoClip.addEventListener('loadedmetadata', () => updateDuration(videoClip, timeDurationDiv)); | ||
//**********************************************// | ||
// | ||
// Progress bar value color | ||
// | ||
//*********************************************// | ||
const playerBar = videoClip.getAttribute("data-player-bar"); | ||
const playerBar = playerDiv.getAttribute("data-player-bar"); | ||
var color_progress_bar = playerBar; | ||
const inputProgressBar = document.createElement('style'); | ||
document.head.appendChild(inputProgressBar); | ||
const inputProgressBarStyle = ` | ||
progress::-webkit-progress-bar { | ||
background-color: rgba(255, 255, 255, 0.1); | ||
position:relative; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: ${color_progress_bar}; | ||
position:relative; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: ${color_progress_bar}; | ||
position:relative; | ||
} | ||
progress::-ms-fill { | ||
background-color: ${color_progress_bar}; | ||
position:relative; | ||
@@ -2600,13 +1363,71 @@ | ||
} | ||
progress::-ms-fill { | ||
progress::-webkit-slider-thumb { | ||
width: 11px; | ||
height: 11px; | ||
margin-top:-1px; | ||
border-radius: 100%; | ||
background-color: red; | ||
border-style: none; | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
progress::-moz-range-thumb { | ||
width: 11px; | ||
height: 11px; | ||
margin-top:-1px; | ||
border-radius: 100%; | ||
background-color: red; | ||
border-style: none; | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
background-color: ${color_progress_bar}; | ||
position:relative; | ||
} | ||
`; | ||
inputProgressBar.appendChild(document.createTextNode(inputProgressBarStyle)); | ||
//**********************************************// | ||
// | ||
// Double Click Fullscreen | ||
// | ||
//*********************************************// | ||
playerDiv.addEventListener('dblclick', toggleFullscreen); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Fullscreen Button | ||
// | ||
//*********************************************// | ||
// Existing code for the fullscreen button | ||
const fullscreenButton = document.createElement('mirax'); | ||
fullscreenButton.className = 'fullscreen'; | ||
controlDiv.appendChild(fullscreenButton); | ||
fullscreenButton.addEventListener('click', toggleFullscreen); | ||
@@ -2617,57 +1438,113 @@ | ||
progress::-webkit-slider-thumb { | ||
function toggleFullscreen() { | ||
const video = document.querySelector('.mirax-player'); | ||
if (document.documentElement.requestFullscreen) { | ||
if (!document.fullscreenElement) { | ||
// Store the original video dimensions | ||
video.dataset.originalWidth = video.style.width; | ||
video.dataset.originalHeight = video.style.height; | ||
width: 11px; | ||
// Calculate video's aspect ratio | ||
const videoAspectRatio = video.videoWidth / video.videoHeight; | ||
height: 11px; | ||
if (videoAspectRatio > 1) { | ||
// Video is landscape (16:9 or wider) | ||
video.style.width = '100%'; | ||
video.style.height = '100%'; | ||
} else { | ||
// Video is portrait (9:16 or taller) | ||
// Calculate the height to maintain 9:16 aspect ratio with increased height | ||
const screenHeight = window.innerHeight; | ||
const targetHeight = screenHeight + 127; // Increase the height by 127 pixels (adjust as needed) | ||
margin-top:-1px; | ||
video.style.width = 'auto'; | ||
video.style.height = `${targetHeight}px`; | ||
} | ||
border-radius: 100%; | ||
document.documentElement.requestFullscreen(); | ||
} else { | ||
// Restore the original video dimensions | ||
video.style.width = video.dataset.originalWidth; | ||
video.style.height = video.dataset.originalHeight; | ||
background-color: red; | ||
document.exitFullscreen(); | ||
} | ||
} | ||
} | ||
border-style: none; | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
// Function to hide the control div with a fade-out effect | ||
function showControlDiv(miraxTheme) { | ||
miraxTheme.style.opacity = 1; | ||
miraxTheme.style.transition = 'opacity 0.3s'; | ||
} | ||
} | ||
// Function to check for inactivity and hide the control div | ||
function checkForInactivity(miraxPlayer, miraxTheme) { | ||
let hideTimer; | ||
function onMouseMove() { | ||
// Mouse is moving, show the control div with a fade-in effect | ||
miraxTheme.style.opacity = 0; | ||
miraxTheme.style.transition = 'opacity 0.3s'; | ||
progress::-moz-range-thumb { | ||
// Reset the hide timer | ||
clearTimeout(hideTimer); | ||
width: 11px; | ||
// Set a new timer to hide the control div after 7 seconds of inactivity | ||
hideTimer = setTimeout(() => { | ||
showControlDiv(miraxTheme); | ||
}, 7000); // 7000 milliseconds (7 seconds) | ||
} | ||
height: 11px; | ||
function onMouseOver(event) { | ||
// Mouse is over the player, check for inactivity | ||
clearTimeout(hideTimer); | ||
margin-top:-1px; | ||
// Get the height of the viewport | ||
const viewportHeight = window.innerHeight; | ||
border-radius: 100%; | ||
// Define the new threshold (e.g., 200 pixels) from the bottom to trigger the control div | ||
const threshold = 200; | ||
background-color: red; | ||
// Calculate the distance from the mouse pointer to the bottom of the viewport | ||
const distanceToBottom = viewportHeight - event.clientY; | ||
const distanceToTop = viewportHeight - event.clientX; | ||
border-style: none; | ||
cursor: pointer; | ||
// Check if the mouse pointer is within the threshold from the bottom | ||
if (distanceToBottom <= threshold) { | ||
// Mouse is near the wide bottom part, keep showing the control div | ||
miraxTheme.style.opacity = 0; | ||
miraxTheme.style.transition = 'opacity 0.3s'; | ||
} | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
if (distanceToTop <= threshold) { | ||
// Mouse is near the wide bottom part, keep showing the control div | ||
miraxTheme.style.opacity = 0; | ||
miraxTheme.style.transition = 'opacity 0.3s'; | ||
} | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
} | ||
function onMouseOut() { | ||
// Mouse is out of the player, check for inactivity and hide the control div | ||
showControlDiv(miraxTheme); | ||
} | ||
miraxPlayer.addEventListener('mousemove', onMouseMove); | ||
miraxPlayer.addEventListener('mouseover', onMouseOver); | ||
miraxPlayer.addEventListener('mouseout', onMouseOut); | ||
// Initially hide the control div | ||
miraxTheme.style.opacity = 0; | ||
miraxTheme.style.transition = 'opacity 0.3s'; | ||
} | ||
@@ -2679,151 +1556,239 @@ | ||
// Add an event listener to handle fullscreen change events | ||
document.addEventListener('fullscreenchange', () => { | ||
if (document.fullscreenElement === document.documentElement) { | ||
// Mirax player container is in fullscreen mode, update your UI here | ||
// You can modify the player's CSS or perform other actions | ||
} | ||
document.body.style.overflow = 'hidden'; // Prevent scrolling | ||
document.documentElement.style.backgroundColor = '#000'; // Set background color | ||
document.body.style.margin = '0'; // Remove body margin | ||
document.body.style.padding = '0'; // Remove body padding | ||
document.documentElement.style.margin = '0'; // Remove html margin | ||
document.documentElement.style.padding = '0'; // Remove html padding | ||
`; | ||
inputProgressBar.appendChild(document.createTextNode(inputProgressBarStyle)); | ||
const miraxPlayer = document.querySelector('.mirax-player'); | ||
const miraxTheme = document.querySelector('.mirax-theme'); | ||
// Call the function to set up event listeners for inactivity handling | ||
checkForInactivity(miraxPlayer, miraxTheme); | ||
const inputPlayerClip = document.createElement('style'); | ||
document.head.appendChild(inputPlayerClip); | ||
const inputPlayerClipStyle = ` | ||
.mirax-player { | ||
min-width: 350px; | ||
max-width: 100%; | ||
width: 100%; | ||
height: auto; | ||
min-height: 100px; | ||
max-height: 100%; | ||
background-color: #000000; | ||
margin: 0 auto; | ||
} | ||
/* Initially hide the control div */ | ||
.mirax-theme { | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
height: 20px; | ||
min-width: 350px; | ||
max-width: 95%; | ||
margin-top: -44px; | ||
bottom: 0; | ||
left: 10; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
padding-top: 5px; | ||
padding-bottom: 5px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
transition: opacity 10s; | ||
} | ||
.player-selector { | ||
margin: 0 auto; | ||
width: 100%; | ||
max-width: 100%; | ||
position: relative; | ||
text-align: center; | ||
} | ||
`; | ||
inputPlayerClip.appendChild(document.createTextNode(inputPlayerClipStyle)); | ||
//**********************************************// | ||
// | ||
playerDiv.classList.add('fullscreen-mode'); | ||
} else { | ||
// Mirax player container exited fullscreen mode, update your UI here | ||
// Restore the player's original UI | ||
// Double Click Fullscreen | ||
// | ||
playerDiv.classList.remove('fullscreen-mode'); | ||
//*********************************************// | ||
const inputPlayerClip = document.createElement('style'); | ||
document.head.appendChild(inputPlayerClip); | ||
const inputPlayerClipStyle = ` | ||
.mirax-player { | ||
min-width:350px; | ||
max-width: ${dynamicWidth + 400}px; | ||
width: 100%; /* This ensures the video fills its container while respecting max-width */ | ||
height: auto; /* This maintains the video's aspect ratio */ | ||
min-height:100px; | ||
max-height:450px; | ||
background-color: #000000; | ||
margin: 0 auto; | ||
} | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
diplay: block; | ||
opacity: 1; | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
display: block; | ||
margin: 0 auto; | ||
position: relative; | ||
width: 95%; | ||
height: 20px; | ||
min-width:350px; | ||
max-width: 95%; | ||
margin-top:-44px; | ||
bottom: 0; | ||
left: 10; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
padding-top:5px; | ||
padding-bottom:5px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
.player-selector { | ||
margin: 0 auto; | ||
width: 100%; | ||
max-width: ${dynamicWidth}px; | ||
position: relative; | ||
float: ${dynamicFloat}; | ||
text-align: center; | ||
} | ||
`; | ||
inputPlayerClip.appendChild(document.createTextNode(inputPlayerClipStyle)); | ||
videoClip.addEventListener('dblclick', toggleFullscreen); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Fullscreen Button | ||
document.body.style.overflow = ''; // Restore scrolling | ||
document.documentElement.style.backgroundColor = ''; // Restore background color | ||
document.body.style.margin = ''; // Restore body margin | ||
document.body.style.padding = ''; // Restore body padding | ||
document.documentElement.style.margin = ''; // Restore html margin | ||
document.documentElement.style.padding = ''; // Restore html padding | ||
// | ||
//*********************************************// | ||
} | ||
}); | ||
const fullscreenButton = document.createElement('mirax'); | ||
fullscreenButton.className = 'fullscreen'; | ||
controlDiv.appendChild(fullscreenButton); | ||
fullscreenButton.addEventListener('click', toggleFullscreen); | ||
function toggleFullscreen() { | ||
if (videoClip.requestFullscreen) { | ||
if (document.fullscreenElement) { | ||
document.exitFullscreen(); | ||
} else { | ||
videoClip.requestFullscreen(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
/* # Mirax Player core license | ||
Mirax Player is released under the MIT license: | ||
MIT License | ||
Copyright (c) [2023-present] [Demjhon Silver] | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. */ | ||
export default miraxPlayer; |
@@ -7,6 +7,9 @@ | ||
// Define the content string | ||
const content_backward = "\\0279C"; | ||
const content_play = "\\27A4"; | ||
const content_forward = "\\0279C"; | ||
const content_pip = "\\021F1"; | ||
const content_fullscreen = "\\02752"; | ||
const content_backward = "\\27A4"; | ||
const content_play = "\\25B6"; | ||
const content_forward = "\\27A4"; | ||
const content_pause = "|" + " " + "|"; | ||
const content_speaker = "\\1F508"; | ||
const content_pip = "\\0393"; | ||
@@ -18,23 +21,5 @@ | ||
.speakerTrapezoid { | ||
position: absolute; | ||
right:-25px; | ||
background: none; | ||
margin-top:13px; | ||
} | ||
.speakerTrapezoid::before { | ||
content: ""; | ||
width: 50px; /* Adjust the width and height as needed */ | ||
height: 50px; | ||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='50' height='50'%3E%3Crect x='5' y='16' width='5' height='16' fill='%23FFFFFF' /%3E%3Cpolygon points='10,19 30,9 30,39 10,29' fill='%23FFFFFF' /%3E%3C/svg%3E"); | ||
font-size: 15px; | ||
appearance: none; | ||
display: inline-block; /* Make sure it's an inline-block or block element */ | ||
} | ||
.play-button { | ||
@@ -62,9 +47,6 @@ position: absolute; | ||
.play-button.pause::before { | ||
content: ""; | ||
width: 30px; /* Adjust the width as needed */ | ||
height: 30px; /* Adjust the height as needed */ | ||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='30' height='30'%3E%3Crect x='0' y='40' width='10' height='35' fill='%23FFFFFF' /%3E%3Crect x='23' y='40' width='10' height='35' fill='%23FFFFFF' /%3E%3C/svg%3E"); | ||
font-size: 12px; | ||
content: "${content_pause}"; | ||
color:white; | ||
font-size:12px; | ||
appearance: none; | ||
display: inline-block; /* Make sure it's an inline-block or block element */ | ||
} | ||
@@ -77,4 +59,2 @@ | ||
@@ -136,5 +116,5 @@ .play-button:hover { | ||
right: 0; | ||
margin-right:75px; | ||
margin-right:73px; | ||
top:0; | ||
margin-top:-45px; | ||
margin-top:-34px; | ||
width:50px; | ||
@@ -241,4 +221,20 @@ height: 3px; | ||
/* .speaker-icon { | ||
position: absolute; | ||
float: right; | ||
margin-top:-25px; | ||
margin-left:32px; | ||
} | ||
.speaker-icon::before { | ||
position: absolute; | ||
content: "${content_speaker}"; | ||
font-size: 17px; | ||
} */ | ||
.current-time { | ||
@@ -269,7 +265,7 @@ position: absolute; | ||
progress::-webkit-progress-value { | ||
background-color: rgba(255, 255, 255, 0.8); | ||
background-color: rgba(45, 85, 255, 0.9); | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgba(255, 255, 255, 0.8); | ||
background-color: rgba(45, 85, 255, 0.9); | ||
@@ -289,7 +285,17 @@ } | ||
.pip-button { | ||
min-width:20px; | ||
width: 100%; | ||
max-width: 30px; | ||
position: absolute; | ||
right:54px; | ||
background: none; | ||
font-size:15px; | ||
right:0; | ||
margin-top: 4px; | ||
margin-right:54px; | ||
height: 20px; | ||
background: none; | ||
color: #fff; | ||
border-style: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
transition: color 0.3s ease; | ||
font-size:15px; | ||
} | ||
@@ -300,3 +306,3 @@ | ||
content: "${content_pip}"; | ||
font-size:15px; | ||
} | ||
@@ -309,8 +315,17 @@ | ||
.fullscreen { | ||
min-width:20px; | ||
width: 100%; | ||
max-width: 30px; | ||
position: absolute; | ||
right:5px; | ||
background: none; | ||
font-size:15px; | ||
margin-right:5px; | ||
right:0; | ||
height: 20px; | ||
background: none; | ||
color: #fff; | ||
border-style: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
transition: color 0.3s ease; | ||
font-size:15px; | ||
} | ||
@@ -322,17 +337,17 @@ | ||
.fullscreen::before { | ||
content: "${content_fullscreen}"; | ||
.fullscreen::before { | ||
color: #ffffff; | ||
cursor: pointer; | ||
content: ""; | ||
width: 12px; /* Adjust the width as needed */ | ||
height: 12px; /* Adjust the height as needed */ | ||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='12' height='12'%3E%3Crect x='0' y='0' width='100' height='100' fill='%23FFFFFF' /%3E%3Crect x='12' y='12' width='70' height='70' fill='%23818589' /%3E%3C/svg%3E"); | ||
font-size: 12px; | ||
appearance: none; | ||
display: inline-block; /* Make sure it's an inline-block or block element */ | ||
} | ||
/* Style the text elements */ | ||
@@ -380,22 +395,8 @@ .video-text, .input-text { | ||
const mediaQuery = ` | ||
@media (max-width: 840px) { | ||
@media (max-width: 740px) { | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
width: 100%; | ||
max-width: 95%; | ||
min-width: 300px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
display: none; | ||
} | ||
@@ -406,22 +407,19 @@ | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
display: block; | ||
margin: 0 auto; | ||
position: relative; | ||
width: 95%; | ||
height: 20px; | ||
max-width:96%; | ||
margin-top:-44px; | ||
bottom: 0; | ||
left: 10; | ||
color: #fff; | ||
padding-top:5px; | ||
padding-bottom:5px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
.player-selector { | ||
margin: auto 0 !important; | ||
margin-top:20px !important; | ||
width:auto; | ||
max-width: 95.90% !important; | ||
margin-left:10px !important; | ||
} | ||
.mirax-player { | ||
margin-right:-10px !important; | ||
} | ||
} | ||
@@ -439,3 +437,3 @@ `; | ||
const mediaQuery2 = ` | ||
@media (max-width: 690px) { | ||
@media (max-width: 540px) { | ||
@@ -452,60 +450,5 @@ | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
width: 100%; | ||
max-width: 95%; | ||
min-width: 300px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
} | ||
.player-selector { | ||
margin: auto 0 !important; | ||
margin-top:15px !important; | ||
width:auto; | ||
max-width: 94.90% !important; | ||
margin-left:10px !important; | ||
} | ||
.mirax-player { | ||
margin-right:-10px !important; | ||
} | ||
.play-button { | ||
margin-left:0px; | ||
} | ||
.backward-button { | ||
left:40%; | ||
} | ||
.forward-button { | ||
left: 59%; | ||
} | ||
} | ||
@@ -515,208 +458,1 @@ `; | ||
miraxStyleMediaQuery2.appendChild(document.createTextNode(mediaQuery2)); | ||
const miraxStyleMediaQuery3 = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery3); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery3 = ` | ||
@media (max-width: 500px) { | ||
.video-text, .input-text { | ||
background-size: 50px 50px; | ||
width:100%; | ||
max-width:240px; | ||
min-height:110px; | ||
height: auto; | ||
max-height:100px; | ||
} | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
width: 90%; | ||
max-width: 90%; | ||
min-width: 250px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
} | ||
.player-selector { | ||
margin: auto 0 !important; | ||
margin-top:10px !important; | ||
width:auto; | ||
max-width: 94.90% !important; | ||
margin-left:10px !important; | ||
} | ||
.mirax-player { | ||
margin-right: 5px !important; | ||
} | ||
.play-button { | ||
margin-left:0px; | ||
} | ||
.backward-button { | ||
left:40%; | ||
} | ||
.forward-button { | ||
left: 59%; | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery3.appendChild(document.createTextNode(mediaQuery3)); | ||
const miraxStyleMediaQuery4 = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery4); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery4 = ` | ||
@media (max-width: 360px) { | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
width: 60%; | ||
max-width: 70%!important; | ||
min-width: 250px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
} | ||
.backward-button { | ||
left:42%; | ||
} | ||
.forward-button { | ||
left: 56%; | ||
} | ||
.mirax-player { | ||
min-width:200px; | ||
max-width: 300px !important; | ||
width: 100%; | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery4.appendChild(document.createTextNode(mediaQuery4)); | ||
const miraxStyleMediaQuery5 = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery5); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery5 = ` | ||
@media (max-width: 350px) { | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
opacity: 0; /* Start with 0 opacity */ | ||
transition: opacity 0.3s; /* Use opacity for a smooth transition */ | ||
position: absolute; | ||
bottom: 20px; | ||
width: 100%; | ||
max-width: 100%; | ||
min-width: 230px; | ||
height: 30px; | ||
background-color: rgba(0, 0, 0, 0.7); | ||
color: #fff; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
left: 50%; /* Center horizontally */ | ||
transform: translateX(-50%); /* Adjust to perfectly center */ | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
opacity: 1; /* Change opacity to 1 on hover to make it visible */ | ||
} | ||
.backward-button { | ||
left:42%; | ||
} | ||
.forward-button { | ||
left: 58%; | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery5.appendChild(document.createTextNode(mediaQuery5)); |
@@ -1,5 +0,5 @@ | ||
//index.js - This is package's entry point | ||
//index.js - This is your package's entry point | ||
export { default as embed } from './dist/miraxEmbedder'; | ||
export { default as miraxPlayer } from './dist/MiraxPlayer'; | ||
export { default as miraxEmbed } from './dist/miraxEmbedder'; | ||
@@ -6,0 +6,0 @@ |
@@ -6,31 +6,15 @@ // mirax-player.d.ts | ||
// Type for the VideoEmbed function | ||
type VideoEmbed = ( | ||
selector: HTMLDivElement | null | ||
) => void; | ||
// Type for the Video object built-in typescript | ||
type Video = { | ||
width?: number; | ||
height?: number; | ||
autoplay?: boolean; | ||
fullscreen?: boolean; | ||
controls?: boolean; | ||
loop?: boolean; | ||
videoUrl: string; | ||
videoClass: string; | ||
}; | ||
// Type for the VideoPlayer function | ||
type VideoPlayer = ( | ||
videoClip: HTMLVideoElement | ||
) => void; | ||
// Type for the VideoEmbed function | ||
type VideoEmbed = ( | ||
video: any, container?: HTMLElement | ||
) => void; | ||
// Type for the VideoPlayer function | ||
type VideoPlayer = ( | ||
videoClip: HTMLVideoElement | ||
) => void; | ||
// Export the VideoEmbed & VideoPlayer type | ||
// Export the VideoEmbed and VideoPlayer types | ||
export const embed: VideoEmbed; | ||
export const miraxPlayer: VideoPlayer; | ||
} |
{ | ||
"name": "mirax-player", | ||
"version": "6.2.0", | ||
"description": "Mirax Player is a free video player for React, Vue, Angular, and Svelte that can embed videos from platforms like Facebook, TikTok, YouTube/Shorts, Twitter, Vimeo and Dailymotion.", | ||
"version": "6.3.0", | ||
"description": "Mirax Player is a free video player for React, Vue, Angular, and Svelte that can embed videos from platforms like TikTok, YouTube/Shorts, Twitter, Vimeo and Dailymotion.", | ||
"main": "index.js", | ||
"types": "mirax-player.d.ts", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
@@ -17,3 +20,2 @@ "type": "git", | ||
"embed video", | ||
"facebook", | ||
"youtube", | ||
@@ -24,3 +26,2 @@ "vimeo", | ||
"twitter", | ||
"shorts", | ||
"javascript", | ||
@@ -33,5 +34,2 @@ "typescript", | ||
], | ||
"dependencies": { | ||
"aziwork": "^1.0.0" | ||
}, | ||
"author": "Demjhon Silver", | ||
@@ -38,0 +36,0 @@ "license": "MIT", |
351
README.md
@@ -9,11 +9,16 @@ <p align="center"> | ||
[![npm version](https://img.shields.io/npm/v/mirax-player.svg?logo=npm&style=flat-square&label=Latest&color=blue)](https://www.npmjs.com/package/mirax-player) | ||
![Build Status](https://img.shields.io/badge/Build-Passing-brightgreen?style=flat-square) | ||
![Written](https://img.shields.io/badge/JavaScript-blue?logo=javascript&label=Written&style=flat-square&color=FDDA0D) | ||
![Downloads](https://img.shields.io/npm/dt/mirax-player.svg?&style=flat-square&label=Downloads&color=orange) | ||
[![License](https://img.shields.io/npm/l/mirax-player.svg?style=flat-square&label=License&color=green)](https://github.com/demjhonsilver/mirax-player/blob/main/LICENSE.md) | ||
![Written](https://img.shields.io/badge/JavaScript-blue?logo=javascript&label=Supports&style=flat-square&color=FDDA0D) | ||
![Written](https://img.shields.io/badge/TypeScript-blue?logo=typescript&label=Supports&style=flat-square&color=blue) | ||
![Downloads](https://img.shields.io/npm/dt/mirax-player.svg?style=flat-square&label=DOWNLOADS&color=brightgreen) | ||
[![License](https://img.shields.io/npm/l/mirax-player.svg?style=flat-square&label=LICENSE&color=green)](https://github.com/demjhonsilver/mirax-player/blob/main/LICENSE.md) | ||
</div> | ||
</div> | ||
<p align="center"> | ||
@@ -23,4 +28,2 @@ <img src="https://raw.githubusercontent.com/demjhonsilver/mirax-player/main/img/theme1.png"/> | ||
--------------------- | ||
@@ -36,8 +39,2 @@ | ||
- [Embed Video](#embed-video) | ||
- [TypeScript](#typescript) | ||
- [Embed Css](#embed-css) | ||
- [React](#react) | ||
- [Vue](#vue) | ||
- [Angular](#angular) | ||
- [Svelte](#svelte) | ||
- [Video Player](#video-player) | ||
@@ -51,6 +48,6 @@ - [CSS Player](#css-player) | ||
Mirax Player is a free video player for React, Vue, Angular, and Svelte that can embed videos from platforms like Facebook, TikTok, YouTube/Shorts, Twitter, Vimeo and Dailymotion. This library package enables you to dynamically embed videos from any video site, using any URL you like, and as many videos as you need. | ||
Mirax Player is a free video player for React, Vue, Angular, and Svelte that can embed videos from platforms like TikTok, YouTube/Shorts, Twitter, Vimeo and Dailymotion. This library package enables you to set any URL once within a single embed code tag and dynamically embed videos from any video sites. | ||
Frameworks / Libraries | Tested versions | ||
Frameworks / Library | Tested versions | ||
------ | -------- | | ||
@@ -65,39 +62,37 @@ ![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) | 18 & above | ||
## Release-notes | ||
Version 6.2.0 | ||
Major Changes: | ||
Version 6 | ||
- The Mirax video player has been revised. | ||
- The Mirax embed feature is now easier to use. | ||
- The Mirax player can embed multiple videos. | ||
- The embed TypeScript versions are available. [See TypeScript](#typescript) | ||
Major changes: | ||
Minor Changes: | ||
- Mirax tags become Mirax props." | ||
- useRef, ref, and element are based on HTMLDivElement, which has been removed." | ||
- The class names for the player and embed are more aligned with naming conventions." | ||
- The destructuring syntax becomes straightforward for named exports like { embed } and { player }. | ||
v6.2.0 | ||
- The progress bar for video player is wider and the default color is white. | ||
- The speed option panel is getting lower. | ||
Minor changes: | ||
v6.1.0 | ||
- Examples for React embedding are based on named exports. | ||
- Adding a dependency from Aziwork. | ||
6.3.0 | ||
- The shortcut key for playing videos will be Ctrl + Space for video player | ||
6.2.0 | ||
- Revised data-mirax-embed to data-e-." | ||
Patch Changes: | ||
v6.1.2 | ||
Patch changes: | ||
- Margin added to the Mirax video player for responsive dimensions. | ||
- Progress bar move to the top | ||
v6.1.1 | ||
------- | ||
## Features | ||
- The Aziwork package has been updated to version 1.0.0. | ||
## Features | ||
- This video player supports both TypeScript and JavaScript, making it developer-friendly. | ||
- Easy to use and responsive. | ||
- Capable of embedding one or many videos from platforms like Facebook, TikTok, YouTube, YouTube Shorts, Twitter, Dailymotion and Vimeo. | ||
- Supports playing videos in both portrait and landscape orientations. | ||
- Set up once, everything is flexible. | ||
- Can embed videos like TikTok, YouTube, YouTube Shorts, Twitter, Vimeo and Dailymotion. | ||
- Capable of playing videos (Portrait or Landscape). | ||
- Customizable color themes. | ||
- Supports PIP (Picture-in-Picture). | ||
------------- | ||
@@ -114,8 +109,9 @@ ## Installation | ||
![Facebook](https://img.shields.io/badge/Facebook-%231877F2.svg?style=for-the-badge&logo=Facebook&logoColor=white) | ||
![Twitter](https://img.shields.io/badge/Twitter-%231DA1F2.svg?style=for-the-badge&logo=Twitter&logoColor=white) | ||
![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white) | ||
![TikTok](https://img.shields.io/badge/TikTok-%23000000.svg?style=for-the-badge&logo=TikTok&logoColor=white) | ||
![Vimeo](https://camo.githubusercontent.com/2026999d43e099c9c835757e3d2f5f8c574efad153f4e3d5143914223e9cbc24/68747470733a2f2f613131796261646765732e636f6d2f62616467653f6c6f676f3d76696d656f) | ||
![Dailymotion](https://a11ybadges.com/badge?logo=dailymotion) | ||
Logo | Sites | Source type | Docs. | ||
------ | -------- | --------- | ---------- | | ||
![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white) | YouTube / Shorts | Iframe Api | https://developers.google.com/youtube/iframe_api_reference | ||
![Vimeo](https://camo.githubusercontent.com/2026999d43e099c9c835757e3d2f5f8c574efad153f4e3d5143914223e9cbc24/68747470733a2f2f613131796261646765732e636f6d2f62616467653f6c6f676f3d76696d656f) | Vimeo | Player SDK | https://developer.vimeo.com/player/sdk | ||
![TikTok](https://img.shields.io/badge/TikTok-%23000000.svg?style=for-the-badge&logo=TikTok&logoColor=white) | TikTok | oEmbed API | https://developers.tiktok.com/doc/embed-videos/ | ||
![Dailymotion](https://a11ybadges.com/badge?logo=dailymotion) | Dailymotion | oEmbed API | https://developers.dailymotion.com/player/#player-oembed | ||
![Twitter](https://img.shields.io/badge/Twitter-%231DA1F2.svg?style=for-the-badge&logo=Twitter&logoColor=white) | Twitter / X | JavaScript API | https://developer.twitter.com/en/docs/twitter-for-websites/javascript-api/guides/set-up-twitter-for-websites | ||
-------- | ||
@@ -125,117 +121,51 @@ | ||
Attributes | Functionality | Type | Required | | ||
Mirax embed props | Functionality | Type | Required | | ||
------ | -------- | -------- | ---------- | ||
`width` | dynamic width | number | optional | ||
`height` | dynamic height | number |optional | ||
`fullscreen` | enable fullscreen | boolean | optional | ||
`controls` | enable controllers | boolean | optional | ||
`autoplay` | enable autoplay | boolean | optional | ||
`loop` | enable loop | boolean | optional | ||
`videoClass` | set any classname | string | yes | ||
`videoUrl` | video address, url/links | string | yes | ||
`mirax-embed` | responsiveness | any | yes | ||
`data-e-width` | dynamic width | integer | yes | ||
`data-e-height` | dynamic height | integer | yes | ||
`data-e-fullscreen` | enable fullscreen | boolean | optional (true false) | ||
`data-e-controls` | enable controllers | boolean | optional (true false ) | ||
`data-e-autoplay` | enable autoplay | boolean | optional (true false) | ||
`data-e-loop` | enable loop | boolean | optional (true false) | ||
`data-e-url` | video address, url/links | any | yes | ||
--------- | ||
## TypeScript | ||
![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) | ||
- located at repository files | ||
```html | ||
mirax-player/ | ||
|-- src/ | ||
| |-- angular/ | ||
| |-- react/TypeScriptEmbed.md | ||
| |-- svelte/TypeScriptEmbed.md | ||
| |-- vue/TypeScriptEmbed.md | ||
src/react/TypeScriptPlayer.md | ||
src/react/TypeScriptEmbed.md | ||
src/vue/TypeScriptPlayer.md | ||
src/vue/TypeScriptEmbed.md | ||
src/svelte/TypeScriptPlayer.md | ||
src/svelte/TypeScriptEmbed.md | ||
``` | ||
## Embed-css | ||
You can add your own css set-up: <!-- You can rename, change color, resize, positioning etc. --> | ||
You may apply to app.css or index.css or any css file. | ||
This is sample only, you can rename, recreate, and do something: | ||
```css | ||
.embed-youtube-one-clip { | ||
display: flex; | ||
justify-content: center; /* Center horizontally */ | ||
align-items: center; /* Center vertically */ | ||
border: 2px solid orange; | ||
width: 100%; | ||
max-width: 640px; | ||
margin: auto; /* Center the entire container horizontally */ | ||
} | ||
``` | ||
For more css embed video styles: | ||
- located at css.md | ||
```html | ||
mirax-player/ | ||
|-- src/css-embed/css.md (including Angular css) | ||
``` | ||
----------- | ||
If you want sample code for embed multiple videos? | ||
----- | ||
Located at repository files ( EMBED MANY VIDEOS HERE) | ||
``` | ||
mirax-player/ | ||
|-- src/ | ||
| |-- angular/TypeScriptEmbed.md | ||
| |-- react/JavaScriptEmbed.md | ||
| |-- svelte/JavaScriptEmbed.md | ||
| |-- vue/JavaScriptEmbed.md | ||
``` | ||
------ | ||
Use Google chrome as much as possible to load more videos properly. | ||
------------ | ||
Recommended web browser for local test: | ||
----- | ||
![Google Chrome](https://img.shields.io/badge/Google%20Chrome-4285F4?style=for-the-badge&logo=GoogleChrome&logoColor=white) | ||
-------- | ||
Reminder: | ||
- Don't forget to restart your server. | ||
------------ | ||
## React | ||
```jsx | ||
import { useEffect } from 'react'; | ||
# React embed | ||
```js | ||
import React, { useEffect } from "react"; | ||
import { embed } from 'mirax-player'; | ||
export const ExampleComponent = () => { | ||
const ExampleComponent = () => { | ||
useEffect(() => { | ||
embed([ | ||
{ | ||
width: 640, | ||
height: 360, | ||
autoplay: true, | ||
fullscreen: false, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=oEXFMGK7IC0', | ||
videoClass: 'embed-youtube-one-clip' | ||
} | ||
]) | ||
}); | ||
embed("mirax-embed"); | ||
}, []); | ||
return ( | ||
<> | ||
<div className="embed-youtube-one-clip"></div> | ||
</> | ||
<div className="mirax-embed" | ||
data-e-width="640" // 800 x 450 or 1000 x 562.5 | ||
data-e-height="360" | ||
data-e-autoplay="false" // for autoplay set true or remove this props | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` | ||
## Vue | ||
```js | ||
# Vue embed | ||
```js | ||
<template> | ||
<div> | ||
<div class="embed-youtube-one-clip"></div> | ||
<div class="mirax-embed" | ||
data-e-width="640" // 800 x 450 or 1000 x 562.5 | ||
data-e-height="360" | ||
data-e-autoplay="false" // for autoplay set true or remove this props | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
@@ -245,31 +175,18 @@ </template> | ||
<script> | ||
import { onMounted } from 'vue'; | ||
import { onMounted } from "vue"; | ||
import { embed } from 'mirax-player'; | ||
export default { | ||
name: 'ExampleComponent', | ||
setup() { | ||
onMounted(() => { | ||
embed([ | ||
{ | ||
width: 640, | ||
height: 360, | ||
autoplay: true, | ||
fullscreen: false, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=oEXFMGK7IC0', | ||
videoClass: 'embed-youtube-one-clip' | ||
} | ||
]) | ||
embed('mirax-embed'); | ||
}); | ||
return {}; | ||
}, | ||
} | ||
}; | ||
</script> | ||
``` | ||
## Angular | ||
# Angular embed | ||
```ts | ||
import { Component, AfterViewInit } from '@angular/core'; | ||
import { Component, OnInit } from '@angular/core'; | ||
import { embed } from 'mirax-player'; | ||
@@ -279,45 +196,26 @@ | ||
selector: 'app-example', | ||
template: ` | ||
<div class="embed-youtube-one-clip"></div> | ||
`, | ||
styleUrls: ['./example.component.css'], | ||
templateUrl: './example.component.html', | ||
styleUrls: ['./example.component.css'] | ||
}) | ||
export class ExampleComponent implements AfterViewInit { | ||
ngAfterViewInit() { | ||
embed([ | ||
{ | ||
width: 640, | ||
height: 360, | ||
autoplay: true, | ||
fullscreen: false, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=oEXFMGK7IC0', | ||
videoClass: 'embed-youtube-one-clip' | ||
} | ||
]); | ||
export class ExampleComponent implements OnInit { | ||
constructor() { } | ||
ngOnInit(): void { | ||
embed('mirax-embed'); | ||
} | ||
} | ||
} | ||
``` | ||
For Angular css: | ||
--- | ||
example.component.html | ||
[Angular embed Css](#embed-css) | ||
```css | ||
::ng-deep .embed-youtube-one-clip { | ||
display: flex; | ||
justify-content: center; /* Center horizontally */ | ||
align-items: center; /* Center vertically */ | ||
border: 2px solid orange; | ||
width: 100%; | ||
max-width: 640px; | ||
margin: auto; /* Center the entire container horizontally */ | ||
} | ||
------------- | ||
```html | ||
<div class="mirax-embed" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
``` | ||
## Svelte | ||
```js | ||
# Svelte embed | ||
```js | ||
<script> | ||
@@ -328,26 +226,21 @@ import { onMount } from 'svelte'; | ||
onMount(() => { | ||
embed([ | ||
{ | ||
width: 640, | ||
height: 360, | ||
autoplay: true, | ||
fullscreen: false, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=oEXFMGK7IC0', | ||
videoClass: 'embed-youtube-one-clip' | ||
} | ||
]); | ||
embed('mirax-embed'); | ||
}); | ||
</script> | ||
<div> | ||
<div class="embed-youtube-one-clip"></div> | ||
<div class="mirax-embed" | ||
data-e-width="640" // 800 x 450 or 1000 x 562.5 | ||
data-e-height="360" | ||
data-e-autoplay="false" // for autoplay set true or remove this props | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
``` | ||
----------------- | ||
## Video-player | ||
Player Attributes | Functionality |Type | Required | | ||
Mirax player props | Functionality |Type | Required | | ||
------ | -------- | ----------- | ---------- | ||
`player-selector` | responsiveness | any| yes | ||
`data-player-width` | dynamic width | number | yes | ||
`data-player-width` | dynamic width | integer | yes | ||
`data-player-float` | dynamic alignment | string |optional | ||
@@ -379,10 +272,10 @@ `data-player-theme` | player color | any | optional | ||
```js | ||
import { useEffect, useRef } from "react"; | ||
import React, { useEffect, useRef } from "react"; | ||
import { miraxPlayer } from 'mirax-player'; | ||
export const ExampleComponent = () => { | ||
const ExampleComponent = () => { | ||
const playerDiv = useRef(null); | ||
useEffect(() => { | ||
miraxPlayer(playerDiv.current); | ||
}); | ||
},[]); | ||
return ( | ||
@@ -397,2 +290,3 @@ <div className="player-selector"> | ||
}; | ||
export default ExampleComponent; | ||
``` | ||
@@ -403,3 +297,3 @@ # Vue video player | ||
<div class="player-selector"> | ||
<video ref="playerDiv" | ||
<video ref="videoPlayer" | ||
class="mirax-player" | ||
@@ -418,8 +312,8 @@ data-player-width="800" | ||
setup() { | ||
const playerDiv = ref(null); | ||
const videoPlayer = ref(null); | ||
onMounted(() => { | ||
miraxPlayer(playerDiv.value); | ||
miraxPlayer(videoPlayer.value); | ||
}); | ||
return { | ||
playerDiv | ||
videoPlayer | ||
}; | ||
@@ -444,3 +338,3 @@ } | ||
export class ExampleComponent implements AfterViewInit { | ||
@ViewChild('playerDiv', { static: true }) playerDiv!: ElementRef<HTMLVideoElement>; | ||
@ViewChild('videoPlayer', { static: true }) videoPlayer!: ElementRef<HTMLVideoElement>; | ||
ngAfterViewInit(): void { | ||
@@ -450,3 +344,3 @@ this.initializemiraxPlayer(); | ||
initializemiraxPlayer() { | ||
miraxPlayer(this.playerDiv.nativeElement); | ||
miraxPlayer(this.videoPlayer.nativeElement); | ||
} | ||
@@ -461,3 +355,3 @@ } | ||
<div class="player-selector"> | ||
<video #playerDiv | ||
<video #videoPlayer | ||
class="mirax-player" | ||
@@ -475,5 +369,5 @@ data-player-width="800" | ||
let playerDiv; | ||
let videoPlayer; | ||
onMount(() => { | ||
miraxPlayer(playerDiv); | ||
miraxPlayer(videoPlayer); | ||
}); | ||
@@ -483,3 +377,3 @@ </script> | ||
<div class="player-selector"> | ||
<video bind:this={playerDiv} class="mirax-player" | ||
<video bind:this={videoPlayer} class="mirax-player" | ||
data-player-width="800" | ||
@@ -543,3 +437,2 @@ src="clip.mp4"> | ||
## License | ||
@@ -546,0 +439,0 @@ |
@@ -1,74 +0,15 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md (including Angular css) | ||
Use Google chrome as much as possible to load more videos properly. | ||
```ts | ||
import { Component, AfterViewInit } from '@angular/core'; | ||
import { Component, OnInit } from '@angular/core'; | ||
import { embed } from 'mirax-player'; | ||
interface VideoConfig { | ||
width?: number; | ||
height?: number; | ||
autoplay?: boolean; | ||
fullscreen?: boolean; | ||
controls?: boolean; | ||
videoUrl: string; | ||
videoClass: string; | ||
} | ||
@Component({ | ||
selector: 'app-example', | ||
template: ` | ||
<div class="embed-tiktok"></div> | ||
<div class="embed-twitter"></div> | ||
<div class="embed-youtube"></div> | ||
<div class="embed-facebook"></div> | ||
<div class="embed-facebook2"></div> | ||
`, | ||
styleUrls: ['./example.component.css'], | ||
templateUrl: './example.component.html', | ||
styleUrls: ['./example.component.css'] | ||
}) | ||
export class ExampleComponent implements AfterViewInit { | ||
videos: VideoConfig[] = [ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]; | ||
ngAfterViewInit(): void { | ||
embed(this.videos); | ||
export class ExampleComponent implements OnInit { | ||
constructor() { } | ||
ngOnInit(): void { | ||
embed('mirax-embed'); | ||
} | ||
} | ||
``` |
@@ -1,63 +0,19 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```jsx | ||
import { useEffect } from 'react'; | ||
```js | ||
import React, { useEffect } from "react"; | ||
import { embed } from 'mirax-player'; | ||
export const ExampleComponent = () => { | ||
const videos = [ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]; | ||
const ExampleComponent = () => { | ||
useEffect(() => { | ||
embed(videos); | ||
}); | ||
embed("mirax-embed"); | ||
}, []); | ||
return ( | ||
<> | ||
<div className="embed-tiktok"></div> | ||
<div className="embed-twitter"></div> | ||
<div className="embed-youtube"></div> | ||
<div className="embed-facebook"></div> | ||
<div className="embed-facebook2"></div> | ||
</> | ||
<div className="mirax-embed" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" // for autoplay set true or remove this props (data-e-autoplay="false") | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` |
@@ -1,73 +0,20 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```ts | ||
import { useEffect } from 'react'; | ||
import React, { useEffect } from "react"; | ||
import { embed } from 'mirax-player'; | ||
interface VideoConfig { | ||
width?: number; | ||
height?: number; | ||
autoplay?: boolean; | ||
fullscreen?: boolean; | ||
controls?: boolean; | ||
videoUrl: string; | ||
videoClass: string; | ||
} | ||
export const ExampleComponent: React.FC = () => { | ||
const videos: VideoConfig[] = [ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok', | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter', | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube', | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook', | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2', | ||
}, | ||
]; | ||
const ExampleComponent: React.FC = () => { | ||
useEffect(() => { | ||
embed(videos); | ||
}); | ||
embed("mirax-embed"); | ||
}, []); | ||
return ( | ||
<> | ||
<div className="embed-tiktok"></div> | ||
<div className="embed-twitter"></div> | ||
<div className="embed-youtube"></div> | ||
<div className="embed-facebook"></div> | ||
<div className="embed-facebook2"></div> | ||
</> | ||
<div className="mirax-embed" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" // for autoplay set true or remove this props (data-e-autoplay="false") | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` |
```ts | ||
import { useEffect, useRef } from "react"; | ||
import React, { useEffect, useRef } from "react"; | ||
import { miraxPlayer } from 'mirax-player'; | ||
interface ExampleComponentProps { | ||
dataPlayerWidth?: number; | ||
} | ||
export const ExampleComponent: React.FC<ExampleComponentProps> = ({ dataPlayerWidth }) => { | ||
const ExampleComponent: React.FC = () => { | ||
const playerDiv = useRef<HTMLVideoElement | null>(null); | ||
useEffect(() => { | ||
if (playerDiv.current) { | ||
miraxPlayer(playerDiv.current); | ||
} | ||
}, [dataPlayerWidth]); | ||
},[]); | ||
return ( | ||
<div className="player-selector"> | ||
<video | ||
className="mirax-player" | ||
ref={playerDiv} | ||
data-player-width={dataPlayerWidth || 800} | ||
src="clip.mp4" | ||
></video> | ||
<video className="mirax-player" ref={playerDiv} | ||
data-player-width="800" | ||
src="clip.mp4"> | ||
</video> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` |
@@ -1,9 +0,1 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```js | ||
@@ -14,49 +6,13 @@ <script> | ||
const videos = [ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]; | ||
onMount(() => { | ||
embed(videos); | ||
embed('mirax-embed'); | ||
}); | ||
</script> | ||
<div> | ||
<div class="embed-tiktok"></div> | ||
<div class="embed-twitter"></div> | ||
<div class="embed-youtube"></div> | ||
<div class="embed-facebook"></div> | ||
<div class="embed-facebook2"></div> | ||
<div class="mirax-embed" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
``` |
@@ -1,9 +0,1 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```ts | ||
@@ -13,60 +5,14 @@ <script lang="ts"> | ||
import { embed } from 'mirax-player'; | ||
interface VideoConfig { | ||
width?: number; | ||
height?: number; | ||
autoplay?: boolean; | ||
fullscreen?: boolean; | ||
controls?: boolean; | ||
videoUrl: string; | ||
videoClass: string; | ||
} | ||
const videos: VideoConfig[] = [ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]; | ||
onMount(() => { | ||
embed(videos); | ||
embed(embedDiv); | ||
}); | ||
</script> | ||
<div> | ||
<div class="embed-tiktok"></div> | ||
<div class="embed-twitter"></div> | ||
<div class="embed-youtube"></div> | ||
<div class="embed-facebook"></div> | ||
<div class="embed-facebook2"></div> | ||
<div class="mirax-player" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
``` | ||
``` |
```ts | ||
<!-- YourComponent.svelte --> | ||
<script lang="ts"> | ||
@@ -7,10 +6,6 @@ import { onMount } from 'svelte'; | ||
export let dataPlayerWidth: number | undefined; | ||
let playerDiv: HTMLVideoElement | undefined; | ||
let playerDiv: HTMLVideoElement | null; | ||
onMount(() => { | ||
if (playerDiv) { | ||
miraxPlayer(playerDiv); | ||
} | ||
}); | ||
@@ -20,11 +15,8 @@ </script> | ||
<div class="player-selector"> | ||
<video | ||
class="mirax-player" | ||
bind:this={playerDiv} | ||
data-player-width={dataPlayerWidth || 800} | ||
src="clip.mp4"> | ||
<video class="mirax-player" bind:this={playerDiv} | ||
data-player-width="800" | ||
src="clip.mp4"> | ||
<track kind="captions" src="" label="English" default> | ||
</video> | ||
</div> | ||
``` |
@@ -1,17 +0,8 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```js | ||
<template> | ||
<div> | ||
<div class="embed-tiktok"></div> | ||
<div class="embed-twitter"></div> | ||
<div class="embed-youtube"></div> | ||
<div class="embed-facebook"></div> | ||
<div class="embed-facebook2"></div> | ||
<div class="mirax-embed" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
@@ -21,53 +12,14 @@ </template> | ||
<script> | ||
import { onMounted } from 'vue'; | ||
import { onMounted } from "vue"; | ||
import { embed } from 'mirax-player'; | ||
export default { | ||
name: 'ExampleComponent', | ||
setup() { | ||
const videos = ([ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]); | ||
onMounted(() => { | ||
embed(videos); | ||
embed('mirax-embed'); | ||
}); | ||
return { | ||
videos, | ||
}; | ||
}, | ||
return {}; | ||
} | ||
}; | ||
</script> | ||
``` |
@@ -1,17 +0,8 @@ | ||
You can find the css styles for these embed videos | ||
mirax-player/ | ||
|-- src/css-embed/css.md | ||
Use Google chrome as much as possible to load more videos properly. | ||
```ts | ||
<template> | ||
<div> | ||
<div class="embed-tiktok"></div> | ||
<div class="embed-twitter"></div> | ||
<div class="embed-youtube"></div> | ||
<div class="embed-facebook"></div> | ||
<div class="embed-facebook2"></div> | ||
<div class="mirax-embed" ref="embedDiv" | ||
data-e-width="640" | ||
data-e-height="360" | ||
data-e-autoplay="false" | ||
data-e-url="https://vimeo.com/217499569"> | ||
</div> | ||
@@ -21,55 +12,9 @@ </template> | ||
<script setup lang="ts"> | ||
import { onMounted } from 'vue'; | ||
import { onMounted } from "vue"; | ||
import { embed } from 'mirax-player'; | ||
const videos = <VideoConfig[]>([ | ||
{ | ||
videoUrl: 'https://www.tiktok.com/@scout2015/video/6718335390845095173', | ||
videoClass: 'embed-tiktok' | ||
}, | ||
{ | ||
width: 300, | ||
height: 600, | ||
videoUrl: 'https://twitter.com/cheerfulclips/status/1677022600655175680', | ||
videoClass: 'embed-twitter' | ||
}, | ||
{ | ||
width: 640, | ||
height: 360, | ||
fullscreen: true, | ||
controls: true, | ||
videoUrl: 'https://www.youtube.com/watch?v=vBGiFtb8Rpw', | ||
videoClass: 'embed-youtube' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook' | ||
}, | ||
{ | ||
width: 318, | ||
height: 180, | ||
autoplay: false, | ||
videoUrl: 'https://www.facebook.com/facebook/videos/10153231379946729/', | ||
videoClass: 'embed-facebook2' | ||
}, | ||
]); | ||
onMounted(() => { | ||
embed(videos); | ||
embed('mirax-embed'); | ||
}); | ||
interface VideoConfig { | ||
width?: number; | ||
height?: number; | ||
autoplay?: boolean; | ||
fullscreen?: boolean; | ||
controls?: boolean; | ||
videoUrl: string; | ||
videoClass: string; | ||
} | ||
</script> | ||
``` |
```ts | ||
<template> | ||
<div class="player-selector"> | ||
<video | ||
class="mirax-player" | ||
ref="playerDiv" | ||
:data-player-width="dataPlayerWidth || 800" | ||
src="clip.mp4" | ||
> | ||
<track kind="captions" src="" label="English" default /> | ||
<video class="mirax-player" ref="playerDiv" | ||
data-player-width="800" | ||
src="clip.mp4"> | ||
</video> | ||
@@ -15,27 +11,12 @@ </div> | ||
<script lang="ts"> | ||
import { ref, onMounted, defineProps } from 'vue'; | ||
<script setup lang="ts"> | ||
import { ref, onMounted } from "vue"; | ||
import { miraxPlayer } from 'mirax-player'; | ||
export default { | ||
props: { | ||
dataPlayerWidth: Number, | ||
}, | ||
setup() { | ||
const playerDiv = ref<HTMLVideoElement | null>(null); | ||
const props = defineProps(['dataPlayerWidth']); | ||
const playerDiv = ref<HTMLVideoElement | null>(null); | ||
onMounted(() => { | ||
if (playerDiv.value) { | ||
miraxPlayer(playerDiv.value); | ||
} | ||
}); | ||
return { | ||
playerDiv, | ||
props, | ||
}; | ||
}, | ||
}; | ||
onMounted(() => { | ||
miraxPlayer(playerDiv.value); | ||
}); | ||
</script> | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
0
27
1839
101266
1
429
1
- Removedaziwork@^1.0.0