您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
解除超星自动暂停播放的限制并添加自动播放下一集的功能
- // ==UserScript==
- // @name Fuck Chaoxing
- // @namespace xuyiming.open@outlook.com
- // @description 解除超星自动暂停播放的限制并添加自动播放下一集的功能
- // @author 依然独特
- // @version 1.2.4
- // @grant none
- // @run-at document-start
- // @require https://gf.qytechs.cn/scripts/18715-hooks/code/Hooks.js?version=661566
- // @require https://gf.qytechs.cn/scripts/29782-docsready/code/docsReady.js?version=603417
- // @include *://*.chaoxing.com/mycourse/studentstudy*
- // @include *://*.chaoxing.com/ananas/modules/video/index.html*
- // @match *://*.chaoxing.com/mycourse/studentstudy*
- // @match *://*.chaoxing.com/ananas/modules/video/index.html*
- // @include *://*.chaoxing.com/ananas/modules/work/index.html
- // @include *://*.chaoxing.com/ananas/modules/work/index.html*
- // @match *://*.chaoxing.com/ananas/modules/work/index.html
- // @match *://*.chaoxing.com/ananas/modules/work/index.html*
- // @license BSD 2-Clause
- // @homepageURL https://gist.github.com/xymopen/eb65046644ff5cb7c0668e5d4f9607d1
- // ==/UserScript==
- // TODO: CX update with an HTML5 Player. Need some time digging with it
- // NOTE: I no longer have any lesson on CX. development may delayed.
- ( function () {
- "use strict";
- // So, let's first clarify the structure of Chaoxing Student Study Page
- // A course is made up of mulitple chapters
- // A chapter is made up of mulitple cards, saying a multi-media card and a unit test card
- // A card is made up of multiple jobs, saying two video jobs and a ppt job
- // When a video job is finished, finishJob() would be called on MoocPlayer,
- // which calls proxy_completed(),
- // whick calls ed_complete(),
- // which calls JC.completed on card iframe,
- // which emits an completed event,
- // which trigger unlock(),
- // which calls onReadComplete() on the top window
- // When a ppt job is loaded, uParse() would be called
- // which calls unlock()
- // onReadComplete() then calls onReadComplete1() to pull updated chapter list from the server
- // and calls jobflag() to figure out how many jobs remaining to finish
- // jobflag() looks in card iframe for .ans-job-icon as total jobs and .ans-job-finished as unfinished ones.
- // ppt jobs doesn't count for they don't have .ans-job-icon or .ans-job-finished
- // Generally speaking we only need to handle video jobs
- // However Chrome blocks Flash. :facepalm:
- /**
- * @param {(config: any, createCXPlayer: Function) => any} onPlayerInit
- * @param {Window} [contextWindow]
- */
- function hookCXPlayer ( onPlayerInit, contextWindow ) {
- if ( undefined === contextWindow ) {
- contextWindow = window;
- }
- // CXPlayer and pauseMovie() loaded as jQuery plug-ins
- // so hook jQuery to access it.
- Hooks.set( contextWindow, "jQuery", function ( target, propertyName, ignored, jQuery ) {
- Hooks.method( jQuery.fn, "cxplayer", function ( target, methodName, method, thisArg, args ) {
- var replyArgs = arguments, $globalPlayer, $player,
- globalConfig = args[ 0 ];
- function createCXPlayer ( config ) {
- if ( undefined !== config ) {
- globalConfig = config;
- args[ 0 ] = config;
- }
- $globalPlayer = Hooks.Reply.method( replyArgs );
- return $globalPlayer;
- }
- $player = onPlayerInit( globalConfig, createCXPlayer );
- if ( undefined !== $player ) {
- $globalPlayer = $player;
- }
- return $globalPlayer;
- } );
- return Hooks.Reply.set( arguments );
- } );
- };
- var globalVideoJs;
- /**
- * @param {Window} [contextWindow]
- * @see {@link [videojs-ext.min.js](https://mooc1-2.chaoxing.com/ananas/videojs-ext/videojs-ext.min.js)}
- */
- function videoJsStudyUncontrolAndTimelineNull ( contextWindow ) {
- if ( undefined === contextWindow ) {
- contextWindow = window;
- }
- Hooks.set( contextWindow, "videojs", function ( target, propertyName, ignored, videojs ) {
- globalVideoJs = videojs;
- Hooks.method( videojs, "registerPlugin", function ( target, methodName, method, thisArg, args ) {
- if ( "studyControl" === args[ 0 ] ) {
- method.call( thisArg, "studyControl", function () { } );
- return args[ 1 ]
- } else if ( "timelineObjects" === args[ 0 ] ) {
- method.call( thisArg, "timelineObjects", function () { } );
- return args[ 1 ]
- } else {
- return Hooks.Reply.method( arguments );
- }
- } );
- return Hooks.Reply.set( arguments );
- } );
- }
- /**
- * @param {(config: any, createPlayer: Function) => any} onPlayerInit
- * @param {Window} [contextWindow]
- */
- function hookVideojs ( onPlayerInit, contextWindow ) {
- if ( undefined === contextWindow ) {
- contextWindow = window;
- }
- Hooks.set( contextWindow, "ans", function ( target, propertyName, ignored, ans ) {
- Hooks.method( ans, "VideoJs", function ( target, methodName, method, thisArg, args ) {
- var replyArgs = arguments, $globalPlayer, $player,
- globalConfig = args[ 0 ].params;
- function createPlayer ( config ) {
- var player;
- if ( undefined !== config ) {
- globalConfig = config;
- args[ 0 ].params = config;
- }
- // CX didn't return player instance to us
- // nail it
- Hooks.Reply.method( replyArgs );
- return globalVideoJs( args[ 0 ].videojs );
- }
- $player = onPlayerInit( globalConfig, createPlayer );
- if ( undefined !== $player ) {
- $globalPlayer = $player;
- }
- return $globalPlayer;
- } );
- return Hooks.Reply.set( arguments );
- } );
- };
- /**
- * @param {NodeList} list
- * @returns {number}
- */
- function findCurIdx ( list ) {
- return Array.prototype.findIndex.call( list, function ( chapter ) {
- return chapter.classList.contains( "currents" );
- } );
- };
- function canNextCard () {
- var contextDocument = window.top.document.querySelector( "iframe" ).contentDocument;
- return Array.prototype.filter.call( contextDocument.querySelectorAll( ".ans-job-icon" ), function ( jobContainer ) {
- return !jobContainer.parentNode.classList.contains( "ans-job-finished" );
- } ).length === 0;
- }
- function nextCard () {
- var cards, nextSectionIndex;
- cards = document.querySelectorAll( "#mainid .tabtags span" );
- nextSectionIndex = findCurIdx( cards ) + 1;
- if ( nextSectionIndex < cards.length ) {
- cards[ nextSectionIndex ].click();
- return true;
- } else {
- return false;
- }
- }
- function nextChapter () {
- var document = window.top.document,
- chapters = document.querySelectorAll(
- "#coursetree .ncells h1," +
- "#coursetree .ncells h2," +
- "#coursetree .ncells h3," +
- "#coursetree .ncells h4," +
- "#coursetree .ncells h5," +
- "#coursetree .ncells h6"
- ),
- curChapterIdx = findCurIdx( chapters ),
- nextChapter = Array.prototype.slice.call( chapters, curChapterIdx + 1 ).find( function ( chapter ) {
- // finished chapters are classified as blue
- // and locked chapters are classified as lock
- return !chapter.querySelector( ".blue" ) && !chapter.querySelector( ".lock" );
- } );
- // Go to the first unfinished and unlocked chapter
- if ( nextChapter ) {
- nextChapter.click();
- return true;
- } else {
- // or wait for next call when one locked chapter may be unlocked
- return false;
- }
- }
- if ( "/ananas/modules/video/index.html" === window.location.pathname ) {
- // Video Job iframe
- hookCXPlayer( function ( config, createCXPlayer ) {
- var $player;
- // https://mooc1-1.chaoxing.com/ananas/modules/video/cxplayer/moocplayer_4.0.11.js
- config.datas.enableFastForward = true;
- config.datas.enableSwitchWindow = 1;
- config.datas.errorBackTime = false;
- config.datas.isAutoPlayNext = true;
- config.datas.isDefaultPlay = true;
- config.datas.pauseAdvertList = [];
- config.datas.preAdvertList = [];
- // if ( config.events &&
- // config.events.onAnswerRight &&
- // !config.events.onAnswerRight.toString()
- // .replace( /(function .*?\(.*?\))/g, "" ).trim() // remove function signifigure
- // .replace( /^\{|\}$/g, "" )
- // .replace( /\/\/.*(\r|\n|(\r\n))/g, "" ) // remove single line comment
- // .replace( /\/\*.*\*\//mg, "" ) // remove multiple line comment
- // .match( /^\s*$/ )
- // ) {
- // window.alert( "onAnswerRight() is not empty. It's unsafe to block the resource URL." );
- // }
- $player = createCXPlayer();
- // Remove native `onPause` listener
- // prevent pause the movie from JS side
- $player.unbind( "onPause" );
- // Unpausable playback
- // TODO: find better way handling multiple players playing at the same time
- $player.pauseMovie = function () { };
- $player.bind( "onPause", function () {
- $player.playMovie();
- } );
- $player.bind( "onError", function () {
- if ( 4 === $player.getPlayState() ) {
- window.location.reload();
- }
- } );
- window.MoocPlayer.prototype.switchWindow = function () { return this; };
- window.jQuery.fn.pauseMovie = function () { };
- // Object.keys( config.events ).forEach( e => $player.bind( e, () => {
- // const id = $player.find( 'object[type="application/x-shockwave-flash"]' ).attr( 'id' );
- // const state = [ "error", "playing", "paused", "hanging", "stop" ][ $player.getPlayState() ];
- // console.log( `[Fuck Chaoxing]${ e } is triggered. Player#${ id } is ${ state }.` );
- // } ) );
- } );
- videoJsStudyUncontrolAndTimelineNull();
- hookVideojs( function ( config, createPlayer ) {
- var $player;
- config.enableFastForward = 1;
- config.enableSwitchWindow = 1;
- $player = createPlayer();
- $player.on( "ready", function () {
- // immediate play video may cause DOMException
- setTimeout( function () {
- $player.play();
- }, 5000 );
- } );
- } );
- } else if ( "/mycourse/studentstudy" === window.location.pathname ) {
- // Card iframe
- domReady().then( function () {
- var hasNextCard = true,
- jobflagApplied = false,
- ajaxesPending = 0;
- function onReadComplete () {
- if ( jobflagApplied && ajaxesPending && !hasNextCard ) {
- nextChapter();
- jobflagApplied = false;
- }
- };
- window.jQuery( document ).ajaxComplete( function () {
- ajaxesPending -= 1;
- if ( ajaxesPending === 0 ) {
- onReadComplete();
- }
- } );
- Hooks.method( window.jQuery, "ajax", function ( target, methodName, method, thisArg, args ) {
- ajaxesPending += 1;
- return Hooks.Reply.method( arguments );
- } );
- Hooks.method( window, "onReadComplete1", function ( target, methodName, method, thisArg, args ) {
- var returns = Hooks.Reply.method( arguments );
- onReadComplete();
- return returns;
- } );
- Hooks.method( window, "jobflag", function ( target, methodName, method, thisArg, args ) {
- if ( canNextCard() ) {
- hasNextCard = nextCard();
- }
- jobflagApplied = true;
- onReadComplete();
- return Hooks.Reply.method( arguments );
- } );
- } );
- }
- } )();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址