User:Valerio Bozzolan/PlayerGoodies.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:Valerio Bozzolan/PlayerGoodies. |
/**
* This is a MediaWiki gadget to extend the functionalities of
* the default player.
*
* Some features:
* - allow to alert when closing a page while a file is playing
* - allow to check a file as already listened/seen
* - allow to restart from the previous point
*
*/
/**
* Eventually initialize the plugin
*
* This allows to inherit users' configuration
*/
window.PlayerGoodies = window.PlayerGoodies || {};
/**
* Wrapper for the gadget
*/
( function( mw, $, PlayerGoodies ) {
/**
* Default configuration for the PlayerGoodies plugin
*/
var DEFAULT_CONFIG = {
};
// try to inherit user's configuration or just initialize an empty one
PlayerGoodies.config = PlayerGoodies.config || {};
// merge the user configuration with the default configuration
$.extend( PlayerGoodies.config, DEFAULT_CONFIG );
/*
* UTILITIES
*/
/**
* Event fired when the player is ended
*/
function onPlayerEnded() {
alert("ended");
}
/**
* Event fired when the player is paused
*/
function onPlayerPaused() {
alert("ended" );
}
/**
* Event fired when the player is played
*/
function onPlayerPlay() {
alert("play");
}
/*
* CLASSES
*/
/**
* Constructor for a PlayerGoodieFile
*
* Remember to call .init()
*/
var PlayerGoodieFile = function() {
// this.$playBtn
// this.$container
// this.$audio
};
/**
* Initialize an audio element
*/
PlayerGoodieFile.init = function() {
// eventually find the container
if( !this.$container ) {
// no play button no party
if( !this.$playBtn || !this.$playBtn.length ) {
throw 'missing this.$playBtn - oh nose!';
}
this.$container = this.$playBtn.closest( '.mediaContainer' );
}
// eventually find the audio file
if( !this.$audio ) {
this.$audio = this.$container.find( 'audio' );
}
// no audio no party
var $audio = this.$audio;
if( !$audio || !$audio.length ) {
throw 'missing this.$audio - oh-nose!';
}
// register some events on the <audio> element
$audio.on( 'play', PlayerGoodie.onPlay );
$audio.on( 'ended', PlayerGoodie.onEnded );
$audio.on( 'paused', PlayerGoodie.onPaused );
};
/**
* Trigger the internal play callback
*/
PlayerGoodieFile.prototype.triggerInternalPlay = function() {
onPlayerPlay.bind( this.$audio )();
};
/*
* CORE
*/
/**
* Check if the page has an audio file
*
* @return {boolean}
*/
PlayerGoodies.hasAudioFile = function() {
return $( 'audio' ).length > 0;
};
/**
* Check if the page has a video file
*
* @return {boolean}
*/
PlayerGoodies.hasVideoFile = function() {
return $( 'video' ).length > 0;
};
/**
* Check if the page has a multimedia file
*
* @return {boolean}
*/
PlayerGoodies.hasMultimediaFile = function() {
return PlayerGoodies.hasVideoFile() || PlayerGoodies.hasAudioFile();
};
/**
* Initialize and run the plugin
*/
PlayerGoodies.init = function() {
// check if it has sense to start
if( !PlayerGoodies.hasMultimediaFile() ) {
return;
}
// do not proceed with weird pages
if( mw.config.get( 'wgArticleId' ) < 0 ) {
return;
}
// require missing modules
mw.loader.using( 'mediawiki.api', function () {
// now we can start the party
PlayerGoodies.run();
} );
};
/**
* Start the party
*
* Workflow:
* 1. find all the audio players in the page
* 2. eventually obtain page IDs from page titles
*
* This method assumes that all the needed dependencies are present.
*/
PlayerGoodies.run = function() {
// array of players in the page
// fileTitle => PlayerGoodie
var playerGoodiesByTitle = {};
/**
* Find all the "Play" buttons
*
* Note that, only after clicking this button the first time,
* MediaWiki will spawn the <audio> tag.
*/
$( '.mediaContainer .play-btn' ).click( function() {
// the play button
var $playBtn = $(this);
// do not initialize twice
if( !$playBtn.data( 'PlayerGoodiesInitializedFromPlayBtn' ) ) {
$playBtn.data( 'PlayerGoodiesInitializedFromPlayBtn', true );
/**
* Note that, before clicking the play button,
* there was not any <audio> tag.
*
* MediaWiki will spawn that damn <audio> tag
* just after clicking that fake play button.
*
* So, just wait.
*
* This is a very stupid hack. Please fix this
* if you have the time to investigate how that
* MediaWiki component works. I really don't know.
*/
setTimeout( function() {
/**
* Note that few clock cycles before, the user clicked
* on the "Play" icon. Anyway, we were not able to fire
* our damn 'play' callback because the <audio>
* element, even if now is playing, was created just now
* without any callback.
*
* Let's init the element, attach the callbacks, and
* trigger our 'play' callback manually.
*/
var p = new PlayerGoodieFile();
p.$playBtn = $playBtn;
p.init();
// as said, trigger our play event manually
p.triggerInternalPlay();
}, 1 );
}
} );
// preoad all the page ids
PlayerGoodies.preloadPageIDs();
};
/**
* Preload all the page IDs from the known page titles
*
* This method should be called after the 'run()' method.
*/
PlayerGoodies.preloadPageIDs = function() {
// array of titles we d
var titlesWithoutId = [];
var missingTitle = [];
// loop all the players in the page
var playerGoodies = PlayerGoodies.playerGoodies;
var playerGoodie;
for( var i in playerGoodies ) {
playerGoodie = playerGoodies[ i ];
if( playerGoodie.id === undefined ) {
// add this title in the list
titlesWithoutId.push( playerGoodie.title );
missingTitle.push( playerGoodie );
}
}
if( playerGoodies.length ) {
// ..todo
}
};
/**
* Set some data about a page
*
* It returns a Premise object
*
* @param {int} pageId
* @param {object} data
*/
PlayerGoodies.savePageData = function( pageId, data ) {
// TODO: create savePageDataInUserSubpage( pageId, data );
return this.savePageDataInLocalStorage( pageId, data );
};
/**
* Save some data about a page in the browser's local storage
*
* @param {int} pageId
* @param {object} dataPage
* @return {Promise}
*/
PlayerGoodies.savePageDataInLocalStorage = function ( pageId, dataPage ) {
// everything OK
var ok = true;
// local storage option name
var optionName = 'mwPlayerGoodiesGadgetData';
// check existing data (it's a JSON string)
var dataJSON = mw.storage.get( optionName ) || '{}';
// parse existing data
var data = JSON.parse( dataJSON ) || {};
// check existing data about pages
var dataPages = data.dataPages || {};
// check existing page data
var dataPageOld = [ pageId ] || {};
// extends the existing data with the new data
dataPages[ pageId ] = $.extends( {}, dataPageOld, dataPage );
// encapsulate again the data as JSON
var newDataJSON = JSON.stringify( data );
// save
mw.storage.set( optionName, newDataJSON );
/**
* Return a dummy promise with the fresh data
*
* The Promise is not very useful here, but
* see also savePageDataInUserSubpage().
*/
return new Promise( function (resolve, reject ) {
resolve( data );
} );
};
/**
* Prepare the page
*/
PlayerGoodies.init();
} )( mw, jQuery, window.PlayerGoodies );