您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
To learn more faster and efficiently
// ==UserScript== // @name Focus always and replay if video is paused // @name:zh-TW 始終保持焦點並在視頻暫停時自動播放 // @namespace http://tampermonkey.net/ // @version 0.4.5 // @description To learn more faster and efficiently // @description:zh-tw 此腳本旨在提高在線學習效率,透過自動保持視頻播放視窗的焦點並在視頻暫停時自動重播。適用於 `https://iedu.foxconn.com/*` 網站,能夠確保學習過程中視頻連續播放,無需手動干預,特別適合忙碌且希望提高學習效率的用戶。 // @author pjiaquan // @match https://iedu.foxconn.com/public/user/* // @match https://iedu.foxconn.com/public/play/* // @run-at document-start // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant GM.xmlHttpRequest // @connect us-central1-exam-fc1f9.cloudfunctions.net // @connect 127.0.0.1 // @license MIT // ==/UserScript== (function() { 'use strict'; window.onblur = null; window.blurred = false; let projectName = ""; let playingVideoTitle = ""; let isClicked = false; document.hasFocus = () => true; window.onFocus = () => true; [ "hidden", "mozHidden", "msHidden", "webkitHidden" ].forEach(prop_name => { Object.defineProperty(document, prop_name, {value: false}); }); Object.defineProperty(document, "visibilityState", {get: () => "visible"}); Object.defineProperty(document, "webkitVisibilityState", {get: () => "visible"}); document.onvisibilitychange = undefined; var event_handler = (event) => { if (["blur", "mouseleave", "mouseout"].includes(event.type) && (event.target instanceof HTMLInputElement || event.target instanceof HTMLAnchorElement || event.target instanceof HTMLSpanElement)) { return; // exclude input, anchor, and span elements } event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); }; [ "visibilitychange", "webkitvisibilitychange", "blur", "hasFocus", "mouseleave", "mouseout", "mozvisibilitychange", "msvisibilitychange" ].forEach(event_name => { window.addEventListener(event_name, event_handler, true); document.addEventListener(event_name, event_handler, true); }); let videoData = { filename: null, waresMap: new Map() }; // script1 functionality function updateVideoProgress() { // if(sn) { // console.log(sn); // } if (!isVideoPlaying()) { console.log('Video is not playing!'); startPlayingVideo(); } else { // console.log(wares); var videoElement = document.getElementById('realvideo_html5_api'); if (videoElement && videoElement.tagName === 'VIDEO') { const activeElement = document.querySelector('dl .active'); // Check if the active element exists and log its title attribute or inner text if (activeElement) { // console.log('Active element found:', activeElement); // console.log('Title:', activeElement.getAttribute('title')); playingVideoTitle = activeElement.getAttribute('title'); // console.log('Content:', activeElement.innerText); //console.log('title: ', playingVideoTitle); } else { console.log('No active element found'); } // videoElement.muted(); // console.log('#301: video is playing', videoElement); if(videoElement.src.indexOf("hdvideo") >= 0){ //console.log("您正在播放的是高清版本的"); var currentSrc = videoElement.src; if(currentSrc.indexOf() >= 0) { console.log('you are hd mode'); var newSrc = currentSrc.replace('hdvideo', 'sdvideo'); videoElement.src = newSrc; videoElement.muted = true; // Load the new video source and mute it videoElement.load(); } } if (wares && wares.length > 0) { //console.log(window.wares); var i = 0; for(i = 0; i < wares.length; i++) { if(wares[i].isComplete === "N") { let v = wares[i]; let duration = v.duration; let playtime = v.playtime; let percentage = (playtime / duration) * 100; console.log(`${wares[i].name} 沒完成, 剩下: ${percentage.toFixed(2)}% ${new Date().toLocaleString()} #1`); // Usage example const progress_data = { userId: userId, userName: userName, // examName: window.wares[i].name, progress: percentage.toFixed(2), examName: projectName + ': ' + playingVideoTitle || 'Sample Exam Title' // Replace with actual data }; sendDataToServer(progress_data); // Find the element by its title attribute // var myElement = document.querySelector('dd[title="六西格玛项目定义"]'); var myElement = document.querySelector(`dd[title="${wares[i].name}"]`); if (myElement) { console.log('found element 1'); if(playingVideoTitle !== wares[i].name) { console.log('found element 1 cliked'); //myElement.click(); } break; // Exit the loop after the first click } else { console.log('Element not found'); } } else if(wares[i].isComplete === undefined) { let v = wares[i]; let duration = v.duration; let playtime = v.playtime; let percentage = (playtime / duration) * 100; console.log(`${wares[i].name} 沒完成, 剩下: ${percentage.toFixed(2)}% ${new Date().toLocaleString()} #2`); // Usage example const progress_data2 = { userId: userId, userName: userName, // examName: window.wares[i].name, progress: percentage.toFixed(2), examName: projectName + ': ' + playingVideoTitle || 'Sample Exam Title' // Replace with actual data }; sendDataToServer(progress_data2); var myElement2 = document.querySelector(`dd[title="${wares[i].name}"]`); if (myElement2) { // Trigger the click event on the element console.log('found element 2'); if(playingVideoTitle !== wares[i].name) { console.log('found element 2 cliked'); //myElement2.click(); } break; // Exit the loop after the first click } else { console.log('Element not found'); } // if (videoElement.readyState >= 1) { // Check if metadata is loaded // var duration = videoElement.duration; // var targetTime = duration * 0.95; // Calculate 95% of the total duration // console.log('Setting currentTime to: ', targetTime); // videoElement.currentTime = targetTime; // Set the video progress to 95% // videoElement.play() // .then(() => console.log("Video playback started at 95%")) // .catch((error) => console.error("Error attempting to play video:", error)); // } else { // // Wait for metadata to be loaded before setting currentTime // videoElement.addEventListener('loadedmetadata', function() { // var duration = videoElement.duration; // var targetTime = duration * 0.95; // Calculate 95% of the total duration // console.log('Setting currentTime to: ', targetTime); // videoElement.currentTime = targetTime; // Set the video progress to 95% // videoElement.play() // .then(() => console.log("Video playback started at 95%")) // .catch((error) => console.error("Error attempting to play video:", error)); // }); // } } else { // try { // let v = window.wares[i]; // let duration = v.duration; // let playtime = v.playtime; // let percentage = (playtime / duration) * 100; // console.log(`${window.wares[i].name} 已經完成, 剩下: ${percentage.toFixed(2)}%`); // // URL of the Cloud Function endpoint // const url = 'https://us-central1-exam-fc1f9.cloudfunctions.net/saveProgress'; // // Data to be sent // const data = { // // userId: userId, // examName: window.wares[i].name, // progress: percentage.toFixed(2), // drink: 'mojito' // }; // // Using GM.xmlHttpRequest to send a POST request with the data // GM.xmlHttpRequest({ // method: 'POST', // url: url, // headers: { // 'Content-Type': 'application/json' // }, // data: JSON.stringify(data), // onload: function(response) { // // Parse the JSON response // const result = JSON.parse(response.responseText); // console.log('Success:', result); // }, // onerror: function(error) { // console.error('Error:', error); // } // }); // }catch (error) { // console.log(error); // } } } } } } } function setupVideoCheck() { const activeElement = document.querySelector('.breadcrumb .active'); projectName = activeElement.textContent; //console.log('Page loaded, running script'); setInterval(updateVideoProgress, 5000); // Function to observe DOM changes and click the "确定" button function observeDOMChanges() { const targetNode = document.body; const config = { childList: true, subtree: true }; const callback = function(mutationsList, observer) { for (let mutation of mutationsList) { if (mutation.type === 'childList') { const confirmButton = document.querySelector('.layui-layer-btn0'); if (confirmButton) { confirmButton.click(); console.log('Clicked "确定" button'); observer.disconnect(); // Stop observing after the button is clicked break; } } } }; const observer = new MutationObserver(callback); observer.observe(targetNode, config); } // Start observing for DOM changes observeDOMChanges(); } function isVideoPlaying() { var videoElement = document.getElementById('realvideo_html5_api'); if (videoElement && videoElement.tagName === 'VIDEO') { // console.log(videoElement); if(videoElement.src.indexOf("hdvideo") >= 0){ //console.log("您正在播放的是高清版本的"); var currentSrc = videoElement.src; var newSrc = currentSrc.replace('hdvideo', 'sdvideo'); videoElement.muted = true; videoElement.src = newSrc; // Load the new video source and mute it //videoElement.load(); } // Extract the src attribute var videoSrc = videoElement.getAttribute("src"); // Extract the filename from the src URL var videoFilename = videoSrc.split('/').pop().split('.')[0]; // Save the filename to the videoData object videoData.filename = videoFilename; // Map the videoFilename with wares if needed if (wares && wares.length > 0) { wares.forEach((ware, index) => { videoData.waresMap.set(videoFilename, ware); // Example mapping }); } // Output the filename or save it as needed if (videoData && videoData.waresMap) { const firstEntry = videoData.waresMap.entries().next().value; if (firstEntry) { const [firstKey, firstValue] = firstEntry; if(firstValue.isComplete === "Y") { return true; } } else { console.log('Map is empty'); } } return !videoElement.paused; } else { console.log('Video element not found or is not a video tag'); return null; } } function startPlayingVideo() { var videoElement = document.getElementById('realvideo_html5_api'); if (videoElement && videoElement.tagName === 'VIDEO') { videoElement.muted = true; videoElement.play() .then(() => console.log("Video playback started")) .catch((error) => console.error("Error attempting to play video:", error)); } else { console.log('Video element not found or is not a video tag'); } } // Define the function to send data using GM.xmlHttpRequest function sendDataToServer(data) { const url = 'https://us-central1-exam-fc1f9.cloudfunctions.net/saveProgress'; const testUrl = 'http://127.0.0.1:5001/exam-fc1f9/us-central1/saveProgress'; GM.xmlHttpRequest({ method: 'POST', url: url, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify(data), // JSON stringify the payload onload: function(response) { try { // Parse the JSON response const result = JSON.parse(response.responseText); //console.log('Success:', result); } catch (e) { console.error('Error parsing response:', e); } }, onerror: function(error) { console.error('Request failed:', error); }, ontimeout: function() { console.error('Request timed out'); } }); // GM.xmlHttpRequest({ // method: 'POST', // url: testUrl, // headers: { // 'Content-Type': 'application/json' // }, // data: JSON.stringify(data), // JSON stringify the payload // onload: function(response) { // try { // // Parse the JSON response // const result = JSON.parse(response.responseText); // //console.log('Success:', result); // } catch (e) { // console.error('Error parsing response:', e); // } // }, // onerror: function(error) { // console.error('Request failed:', error); // }, // ontimeout: function() { // console.error('Request timed out'); // } // }); } window.addEventListener('load', setupVideoCheck); })();