studio-ui composer is ready to test actively

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-27 15:28:53 +02:00
parent 4cfdf1a491
commit 58ffc1ff88
12 changed files with 1198 additions and 606 deletions
@@ -3,6 +3,8 @@
var _settings = drupalSettings.edlp_studio;
var $composer;
// audio play is handled by edlp_theme
function init(){
console.log('Studio Init');
initEvents();
@@ -21,11 +23,11 @@
initAjaxCompoLinks();
initDragAndDropUI();
}
// ___ _ _ _ _ _ _ _ _ _
// / __| |_ _ _| |_(_)___ _ _ | \| |___ __| |___ | | (_)_ _ | |__ ___
// | (__| ' \ || | _| / -_) '_| | .` / _ \/ _` / -_) | |__| | ' \| / /(_-<
// \___|_||_\_,_|\__|_\___|_| |_|\_\___/\__,_\___| |____|_|_||_|_\_\/__/
function initAjaxChutierLinks(){
console.log('studio initAjaxChutierLinks');
$('.chutier-ajax-link:not(.ajax-enabled)')
@@ -119,6 +121,9 @@
$('.composition', $composer).replaceWith(data.compo);
$composer.removeClass('ajax-loading');
initDragAndDropUI();
$('body').trigger({
'type':'on-studio-compo-opened'
});
};
function onErrorOpenCompo(jqxhr, textStatus, error, $link){
$link.removeClass('ajax-loading');
@@ -172,12 +177,15 @@
};
function onCreateCompoDone(data, $link, $form){
console.log('onActionToCompoDone',data);
var $new_link = $(data.new_link);
$link
.removeClass('folded')
.parents('li')
.before($('<li>').append(data.new_link));
.before($('<li>').append($new_link));
$form.remove();
// TODO: open new composition to composer
// open new composition to composer
initAjaxCompoLinks();
openCompo($new_link);
};
function onErrorCreateCompo(jqxhr, textStatus, error, $link){
console.warn('action to compo load failed : '+error, jqxhr.responseText);
@@ -219,7 +227,6 @@
console.warn('delete compo load failed : '+error, jqxhr.responseText);
};
// ___ _ _ _ _
// / __| |_ _ _ __| (_)___ ___ _ _(_)
// \__ \ _| || / _` | / _ \___| || | |
@@ -253,7 +260,6 @@
}
// ___ __ ___ _ _ ___
// | \ _ _ __ _ __ _ / _|___ | \ _ _ ___ _ __ | | | |_ _|
// | |) | '_/ _` / _` | > _|_ _| | |) | '_/ _ \ '_ \ | |_| || |
@@ -337,9 +343,6 @@
});
};
// TODO: how to remove an item
function onOrderChanged(e, ui){
console.log('onOrderChanged : e', e);
var cid = $(e.target).parents('.composition').attr('cid');
@@ -351,7 +354,6 @@
// console.log(documents);
recordCompoList(cid, documents);
};
function recordCompoList(cid, docs){
console.log('recordCompoList '+cid, docs);
var ajax_path = _settings.save_compo_ajax_url+'/'+cid;
@@ -366,8 +368,10 @@
.fail(function(jqxhr, textStatus, error){
onErrorRecordCompo(jqxhr, textStatus, error);
});
$('body').trigger({
'type':'on-studio-compo-updated'
});
}
function onRecordCompoDone(data){
console.log('onDeleteCompoDone',data);
if(data.status == "ok"){
@@ -379,7 +383,5 @@
console.warn('record compo failed : '+error, jqxhr.responseText);
};
init();
})(jQuery, Drupal, drupalSettings);
@@ -110,7 +110,7 @@ class CompositionController extends ControllerBase {
'#options'=>array(
'attributes' => array(
'data-drupal-link-system-path' => $url->getInternalPath(),
'nid' => $this->compo->id(),
'cid' => $this->compo->id(),
'class' => ['composition-link'],
'title'=>$title,
),
@@ -173,8 +173,10 @@ class CompositionController extends ControllerBase {
$this->compo->setName($name);
}
$documents = array();
foreach ($new_documents as $nid) {
$documents[] = ['target_id'=>$nid];
if(count($new_documents)){
foreach ($new_documents as $nid) {
$documents[] = ['target_id'=>$nid];
}
}
$this->compo->set('documents', $documents);
$this->compo->save();
@@ -119,7 +119,9 @@ class StudioUIController extends ControllerBase {
'#composer_actions' => array(
'play_composition'=>array(
"#type"=>'container',
"#markup"=>t('Play my composition'),
"#attributes"=>array(
"class"=>array("compo-player-controls")
)
),// TODO: add social media links (what about composition visibility uotside studio_ui ?)
),
);
@@ -6,8 +6,9 @@
var _$corpus_canvas;
var _$row = $('main[role="main"]>.layout-content>.row');
var _$ajaxLinks;
var _audio_player;
var _audioPlayer;
var _randomPlayer;
var _compoPlayer;
// ___ _ _
// |_ _|_ _ (_) |_
@@ -20,7 +21,8 @@
_$body.on('corpus-map-ready', onCorpusMapReady);
_audio_player = new AudioPlayer();
_audioPlayer = new AudioPlayer();
_compoPlayer = new CompoPlayer();
initAjaxLinks();
@@ -42,271 +44,18 @@
// |___|\_/\___|_||_\__/__/
function initEvents(){
$('body')
.on('on-studio-chutier-updated', function(e){
.on('on-studio-chutier-updated', initAjaxLinks)
.on('on-studio-compo-updated', function(e){
initAjaxLinks();
_compoPlayer.refresh();
})
.on('search-results-loaded',function(e){
.on('on-studio-compo-opened', function(e){
initAjaxLinks();
_compoPlayer.newCompo();
})
.on('open_entree', function(e){
// e.tid available
closeAllModals();
})
.on('close_entree', function(e){
// e.tid available
backToFrontPage();
});
}
// _ _ _
// /_\ _ _ __| (_)___
// / _ \ || / _` | / _ \
// /_/ \_\_,_\__,_|_\___/
//
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/samples/gg589528%28v%3dvs.85%29
// https://www.binarytides.com/using-html5-audio-element-javascript/
function AudioPlayer(){
var that = this;
this.fid;
this.audio = new Audio();
// audio events
this.audio_events = ["loadedmetadata","canplay","playing","pause","timeupdate","ended"];
// UI dom objects
this.$container = $('<div id="audio-player">');
// btns
this.$btns = $('<div>').addClass('btns').appendTo(this.$container);
this.$previous = $('<div>').addClass('previous').appendTo(this.$btns);
this.$playpause = $('<div>').addClass('play-pause').appendTo(this.$btns);
this.$next = $('<div>').addClass('next').appendTo(this.$btns);
// timeline
this.$timelinecont= $('<div>').addClass('time-line-container').appendTo(this.$container);
this.$timeline = $('<div>').addClass('time-line').appendTo(this.$timelinecont);
this.$loader = $('<div>').addClass('loader').appendTo(this.$timeline);
this.$cursor = $('<div>').addClass('cursor').appendTo(this.$timeline);
// time
this.$time = $('<div>').addClass('time').appendTo(this.$container);
this.$currentTime = $('<div>').addClass('current-time').html('00:00').appendTo(this.$time);
this.$duration = $('<div>').addClass('duration').html('00:00').appendTo(this.$time);
// favoris
this.$fav = $('<div>').addClass('favoris').appendTo(this.$container);
// cartel
this.$cartel = $('<div>').addClass('cartel').appendTo(this.$container);
// hiding
this.hideTimer = false;
this.hideTimeMS = 10000;
// history
this.currentHistoricIndex = null;
this.historic = [];
this.shuffle_is_active = false;
// object events
this.event_handlers = {
'audio-play-next':[],
'audio-ended':[],
'stop-shuffle':[]
};
this.init();
};
AudioPlayer.prototype = {
init(){
// append ui to document
this.$container.appendTo('header[role="banner"] .region-header');
// record timeline width
this.timeline_w = parseInt(this.$timeline.width());
// init audio events
var fn = '';
for (var i = 0; i < this.audio_events.length; i++) {
fn = this.audio_events[i];
// capitalize first letter of event (only cosmetic :p )
fn = 'on'+fn.charAt(0).toUpperCase()+fn.slice(1);
this.audio.addEventListener(
this.audio_events[i],
this[fn].bind(this),
true);
}
// init btns events
this.$previous.on('click', this.playPrevious.bind(this));
this.$playpause.on('click', this.togglePlayPause.bind(this));
this.$next.on('click', this.playNext.bind(this));
// TODO: previous and next btns
},
openDocument(node){
console.log('AudioPlayer openDocument', node);
this.historic.push(node);
this.currentHistoricIndex = this.historic.length-1;
// this.shuffle_mode = shuffle_mode || false;
this.launch();
},
launch(){
this.clearTimeOutToHide();
this.setSRC(this.historic[this.currentHistoricIndex].audio_url);
this.loadNode(this.historic[this.currentHistoricIndex].nid);
// emmit new playing doc (e.g.: corpus map nowing that audio played from RandomPlayer)
try {
_$corpus_canvas.trigger({
'type':'audio-node-opened',
'nid':this.historic[this.currentHistoricIndex].nid
});
} catch (e) {
console.warn('AudioPlayer : _$corpus_canvas does not exists');
}
this.showHidePreviousBtn();
this.showHideNextBtn();
this.show();
},
// audio functions
setSRC(url){
// console.log('AudioPlayer setSRC : url', url);
this.audio.src = url;
},
onLoadedmetadata(){
var rem = parseInt(this.audio.duration, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$duration.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
this.updateLoadingBar();
},
updateLoadingBar(){
this.$loader.css({
'width':parseInt((100 * this.audio.buffered.end(0) / this.audio.duration), 10)+'%'
});
if( this.audio.buffered.end(0) < this.audio.duration ){
// loop through this function until file is fully loaded
var that = this;
window.requestAnimationFrame(that.updateLoadingBar.bind(that));
}else{
console.log('Audio fully loaded');
}
},
onCanplay(){
this.play();
},
play(){
this.audio.play();
},
playPrevious(){
if(this.currentHistoricIndex > 0){
this.currentHistoricIndex -= 1;
this.launch();
}
},
playNext(){
if(this.currentHistoricIndex < this.historic.length-1){
this.currentHistoricIndex += 1;
this.launch();
}else{
this.emmit('audio-play-next');
}
},
togglePlayPause(e){
if(this.audio.paused){
this.audio.play();
}else{
this.audio.pause();
}
},
stop(){
console.log('AudioPlayer stop()');
this.audio.pause();
this.timeOutToHide();
},
// audio events
onPlaying(){
this.$container.addClass('is-playing');
},
onPause(){
this.$container.removeClass('is-playing');
},
onTimeupdate(){
// move cursor
this.$cursor.css({
'left':(this.audio.currentTime/this.audio.duration * this.timeline_w)+"px"
});
// update time text display
var rem = parseInt(this.audio.currentTime, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$currentTime.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
},
onEnded(){
this.emmit('audio-ended');
this.stop();
},
// cartel functions
loadNode(nid){
this.$cartel.addClass('loading');
$.getJSON('/edlp/ajax/json/node/'+nid+'/player_cartel', {})
.done(this.onNodeLoaded.bind(this))
.fail(this.onNodeLoadFail.bind(this));
},
onNodeLoaded(data){
console.log('AudioPlayer node loaded');
this.$cartel.html(data.rendered).removeClass('loading');
_$body.trigger({'type':'new-audio-cartel-loaded'});
initAjaxLinks();
},
onNodeLoadFail(jqxhr, textStatus, error){
console.warn('AudioPlayer node load failed', jqxhr.responseText);
this.$cartel.removeClass('loading').html('');
},
// global
show(){
this.$container.addClass('visible');
},
showHidePreviousBtn(){
if(this.historic.length > 1 && this.currentHistoricIndex > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
},
showHideNextBtn(){
if(this.currentHistoricIndex < this.historic.length-1 || this.shuffle_is_active){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
},
timeOutToHide(){
console.log('AudioPlayer timeOutToHide()');
this.clearTimeOutToHide();
this.hideTimer = setTimeout(this.hide.bind(this), this.hideTimeMS);
},
clearTimeOutToHide(){
console.log('AudioPlayer clearTimeOutToHide()',this.hideTimer);
if(this.hideTimer){
clearTimeout(this.hideTimer);
this.hideTimer = false;
}
},
hide(){
console.log('AudioPlayer hide()');
this.$container.removeClass('visible');
// trigger highlighted node remove on corpus map
_$corpus_canvas.trigger('audio-node-closed');
},
// object events
on(event_name, handler){
if(typeof this.event_handlers[event_name] == 'undefined'){
console.warn('AudioPlayer : event '+event_name+' does not exists');
}
this.event_handlers[event_name].push(handler);
return this;
},
emmit(event_name){
var handler;
for (var i = this.event_handlers[event_name].length; i >= 0 ; i--) {
handler = this.event_handlers[event_name][i];
setTimeout(handler, 0);
}
return this;
},
.on('search-results-loaded', initAjaxLinks)
.on('open_entree', closeAllModals)
.on('close_entree', backToFrontPage);
}
// ___ _ _ ___
@@ -365,7 +114,7 @@
// Audio links
if($link.is('.audio-link')){
// TODO: stop randomplayer
_audio_player
_audioPlayer
.emmit('stop-shuffle')
.openDocument({
nid:$link.attr('nid'),
@@ -521,7 +270,7 @@
})
.on('corpus-cliked-on-node', function(e) {
console.log('theme : corpus-cliked-on-node', e);
_audio_player
_audioPlayer
.emmit('stop-shuffle')
.openDocument(e.target_node);
});
@@ -531,6 +280,284 @@
_$body.attr('corpus-map', 'ready');
}
// _ _ _
// /_\ _ _ __| (_)___
// / _ \ || / _` | / _ \
// /_/ \_\_,_\__,_|_\___/
//
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/samples/gg589528%28v%3dvs.85%29
// https://www.binarytides.com/using-html5-audio-element-javascript/
function AudioPlayer(){
var that = this;
this.fid;
this.audio = new Audio();
// audio events
this.audio_events = ["loadedmetadata","canplay","playing","pause","timeupdate","ended"];
// UI dom objects
this.$container = $('<div id="audio-player">');
// btns
this.$btns = $('<div>').addClass('btns').appendTo(this.$container);
this.$previous = $('<div>').addClass('previous').appendTo(this.$btns);
this.$playpause = $('<div>').addClass('play-pause').appendTo(this.$btns);
this.$next = $('<div>').addClass('next').appendTo(this.$btns);
// timeline
this.$timelinecont= $('<div>').addClass('time-line-container').appendTo(this.$container);
this.$timeline = $('<div>').addClass('time-line').appendTo(this.$timelinecont);
this.$loader = $('<div>').addClass('loader').appendTo(this.$timeline);
this.$cursor = $('<div>').addClass('cursor').appendTo(this.$timeline);
// time
this.$time = $('<div>').addClass('time').appendTo(this.$container);
this.$currentTime = $('<div>').addClass('current-time').html('00:00').appendTo(this.$time);
this.$duration = $('<div>').addClass('duration').html('00:00').appendTo(this.$time);
// favoris
this.$fav = $('<div>').addClass('favoris').appendTo(this.$container);
// cartel
this.$cartel = $('<div>').addClass('cartel').appendTo(this.$container);
// hiding
this.hideTimer = false;
this.hideTimeMS = 10000;
// history
this.currentHistoricIndex = null;
this.historic = [];
this.shuffle_is_active = false;
// object events
this.event_handlers = {
'audio-open-document':[],
'audio-play':[],
'audio-pause':[],
'audio-play-next':[],
'audio-ended':[],
'stop-shuffle':[]
};
this.init();
};
AudioPlayer.prototype = {
init(){
// append ui to document
this.$container.appendTo('header[role="banner"] .region-header');
// record timeline width
this.timeline_w = parseInt(this.$timeline.width());
// init audio events
var fn = '';
for (var i = 0; i < this.audio_events.length; i++) {
fn = this.audio_events[i];
// capitalize first letter of event (only cosmetic :p )
fn = 'on'+fn.charAt(0).toUpperCase()+fn.slice(1);
this.audio.addEventListener(
this.audio_events[i],
this[fn].bind(this),
true);
}
// init btns events
this.$previous.on('click', this.playPrevious.bind(this));
this.$playpause.on('click', this.togglePlayPause.bind(this));
this.$next.on('click', this.playNext.bind(this));
// TODO: previous and next btns
},
openDocument(node, caller){
// console.log('AudioPlayer openDocument', node);
if(typeof node == 'undefined'
|| typeof node.nid == 'undefined'
|| typeof node.audio_url == 'undfined'){
console.warn('AudioPlayer openDocument() node is malformed', node);
return false;
}
this.historic.push(node);
this.currentHistoricIndex = this.historic.length-1;
// this.shuffle_mode = shuffle_mode || false;
this.emmit('audio-open-document', {caller:caller});
this.launch();
},
launch(){
this.clearTimeOutToHide();
this.setSRC(this.historic[this.currentHistoricIndex].audio_url);
this.loadNode(this.historic[this.currentHistoricIndex].nid);
// emmit new playing doc (e.g.: corpus map nowing that audio played from RandomPlayer)
try {
_$corpus_canvas.trigger({
'type':'audio-node-opened',
'nid':this.historic[this.currentHistoricIndex].nid
});
} catch (e) {
console.info('AudioPlayer : _$corpus_canvas does not exists');
}
this.showHidePreviousBtn();
this.showHideNextBtn();
this.show();
},
// audio functions
setSRC(url){
// console.log('AudioPlayer setSRC : url', url);
this.audio.src = url;
},
onLoadedmetadata(){
var rem = parseInt(this.audio.duration, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$duration.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
this.updateLoadingBar();
},
updateLoadingBar(){
this.$loader.css({
'width':parseInt((100 * this.audio.buffered.end(0) / this.audio.duration), 10)+'%'
});
if( this.audio.buffered.end(0) < this.audio.duration ){
// loop through this function until file is fully loaded
var that = this;
window.requestAnimationFrame(that.updateLoadingBar.bind(that));
}else{
console.log('Audio fully loaded');
}
},
onCanplay(){
this.play();
},
play(){
this.clearTimeOutToHide();
this.audio.play();
},
playPrevious(){
if(this.currentHistoricIndex > 0){
this.currentHistoricIndex -= 1;
this.launch();
}
},
playNext(){
if(this.currentHistoricIndex < this.historic.length-1){
this.currentHistoricIndex += 1;
this.launch();
}else{
this.emmit('audio-play-next');
}
},
togglePlayPause(e){
if(this.audio.paused){
this.audio.play();
}else{
this.audio.pause();
}
},
stop(){
// console.log('AudioPlayer stop()');
this.audio.pause();
this.timeOutToHide();
},
// audio events
onPlaying(){
this.$btns.addClass('is-playing');
this.emmit('audio-play');
},
onPause(){
this.$btns.removeClass('is-playing');
this.emmit('audio-pause');
},
onTimeupdate(){
// move cursor
this.$cursor.css({
'left':(this.audio.currentTime/this.audio.duration * this.timeline_w)+"px"
});
// update time text display
var rem = parseInt(this.audio.currentTime, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$currentTime.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
},
onEnded(){
this.emmit('audio-ended');
this.stop();
},
// cartel functions
loadNode(nid){
this.$cartel.addClass('loading');
$.getJSON('/edlp/ajax/json/node/'+nid+'/player_cartel', {})
.done(this.onNodeLoaded.bind(this))
.fail(this.onNodeLoadFail.bind(this));
},
onNodeLoaded(data){
// console.log('AudioPlayer node loaded');
this.$cartel.html(data.rendered).removeClass('loading');
_$body.trigger({'type':'new-audio-cartel-loaded'});
initAjaxLinks();
},
onNodeLoadFail(jqxhr, textStatus, error){
console.warn('AudioPlayer node load failed', jqxhr.responseText);
this.$cartel.removeClass('loading').html('');
},
// global
show(){
this.$container.addClass('visible');
},
showHidePreviousBtn(){
if(this.historic.length > 1 && this.currentHistoricIndex > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
},
showHideNextBtn(){
if(this.currentHistoricIndex < this.historic.length-1 || this.shuffle_is_active){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
},
timeOutToHide(){
// console.log('AudioPlayer timeOutToHide()');
this.clearTimeOutToHide();
this.hideTimer = setTimeout(this.hide.bind(this), this.hideTimeMS);
},
clearTimeOutToHide(){
// console.log('AudioPlayer clearTimeOutToHide()',this.hideTimer);
if(this.hideTimer){
clearTimeout(this.hideTimer);
this.hideTimer = false;
}
},
hide(){
// console.log('AudioPlayer hide()');
this.$container.removeClass('visible');
// trigger highlighted node remove on corpus map
try {
_$corpus_canvas.trigger('audio-node-closed');
} catch (e) {
console.info('AudioPlayer hide() : _$corpus_canvas does not exists');
}
},
// object events
on(event_name, handler){
if(typeof this.event_handlers[event_name] == 'undefined'){
console.warn('AudioPlayer : event '+event_name+' does not exists');
}
this.event_handlers[event_name].push(handler);
return this;
},
emmit(event_name, args){
// console.log('AudioPlayer emmit() event_name', event_name);
// console.log('AudioPlayer emmit() handlers', this.event_handlers[event_name]);
var handler;
var args = args || {};
for (var i = this.event_handlers[event_name].length-1; i >= 0 ; i--) {
handler = this.event_handlers[event_name][i];
// console.log('AudioPlayer emmit() loop handler', handler);
setTimeout(function(){
// console.log('AudioPlayer emmit() timeout handler', handler);
handler(args);
}, 0);
}
return this;
},
}
// ___ _ ___ _
// | _ \__ _ _ _ __| |___ _ __ | _ \ |__ _ _ _ ___ _ _
// | / _` | ' \/ _` / _ \ ' \| _/ / _` | || / -_) '_|
@@ -540,7 +567,7 @@
this.active = false;
this.playlist = playlist;
this.$btn = $('<a>').html('Shuffle').addClass('random-player-btn');
this.init()
this.init();
};
RandomPlayer.prototype = {
init(){
@@ -554,7 +581,7 @@
this.$btn.on('click', this.toggleActive.bind(this));
// attach an event on AudioPlayer
_audio_player
_audioPlayer
.on('audio-ended', this.onAudioPlayerEnded.bind(this))
.on('audio-play-next', this.onAudioPlayNext.bind(this))
.on('stop-shuffle', this.stop.bind(this));
@@ -579,20 +606,20 @@
}
},
start(){
this.active = _audio_player.shuffle_is_active = true;
this.active = _audioPlayer.shuffle_is_active = true;
this.$btn.addClass('is-active');
this.shuffle();
this.next();
},
stop(){
this.active = _audio_player.shuffle_is_active = false;
this.active = _audioPlayer.shuffle_is_active = false;
this.$btn.removeClass('is-active');
// stop audio player
// _audio_player.stop();
// _audioPlayer.stop();
},
next(){
if(this.active && this.shuffledPlaylist.length > 0)
_audio_player.openDocument(this.shuffledPlaylist.splice(0,1)[0]);
_audioPlayer.openDocument(this.shuffledPlaylist.splice(0,1)[0]);
},
onAudioPlayNext(){
console.log('RandomPlayer : onAudioPlayNext()');
@@ -604,6 +631,215 @@
}
};
// ___ ___ _
// / __|___ _ __ _ __ ___| _ \ |__ _ _ _ ___ _ _
// | (__/ _ \ ' \| '_ \/ _ \ _/ / _` | || / -_) '_|
// \___\___/_|_|_| .__/\___/_| |_\__,_|\_, \___|_|
// |_| |__/
function CompoPlayer(){
this.playing = false;
this.paused = false;
this.playlist = [];
this.current_index = 0;
this.$compo = null;
this.init();
};
CompoPlayer.prototype = {
init(){
console.log('CompoPlayer init()');
// attach an event on AudioPlayer
_audioPlayer
.on('audio-open-document', this.onAudioOpenDocument.bind(this))
.on('audio-play', this.onAudioPlayerPlay.bind(this))
.on('audio-pause', this.onAudioPlayerPause.bind(this))
.on('audio-ended', this.onAudioPlayerEnded.bind(this));
// .on('audio-play-next', this.onAudioPlayNext.bind(this));
this.newCompo();
},
newCompo(){
console.log('CompoPlayer newCompo()');
// $('.composition_ui .composer .composition .field--name-documents')
this.$composer = $('.composition_ui .composer');
this.$compo = $('.composition_ui .composer .composition');
this.$controls = $('.composition_ui .composer .compo-player-controls');
this.$previous = $('<div>').addClass('previous')
.on('click', this.prev.bind(this))
.appendTo(this.$controls);
this.$playpause = $('<div>').addClass('play-pause')
.on('click', this.togglePlayPause.bind(this))
.appendTo(this.$controls);
this.$next = $('<div>').addClass('next')
.on('click', this.next.bind(this))
.appendTo(this.$controls);
// this.$playpause = $('.compo-player-controls', this.$composer)
// .on('click', this.togglePlayPause.bind(this));
this.refresh();
},
refresh(){
// console.log('CompoPlayer refresh(), this', this);
// this.playing = false;
// this.paused = false;
// this.resetIndex();
this.stop();
// load new playlist
this.playlist = [];
var that = this;
$('.field--name-documents .field__item',this.$compo).each(function(i,el){
var $link = $('a.audio-link',this);
that.playlist.push({
item:$(this),
audio_url:$link.attr("audio_url"),
nid:$link.attr("nid"),
});
});
this.showHideControls();
},
togglePlayPause(){
// console.log('CompoPlayer togglePlayPause');
if (this.playing && !this.paused) {
this.pause();
}else{
if(this.playing && this.paused){
this.play();
}else{
this.start();
}
}
},
start(){
console.log('start');
// console.log('CompoPlayer start()');
this.playing = true;
this.play();
},
play(){
// console.log('play');
if(this.paused){
this.paused = false;
_audioPlayer.play();
}else{
_audioPlayer.openDocument(this.playlist[this.current_index], this);
}
this.setActiveItem().showHideControls();
},
pause(){
console.log('pause');
this.paused = true;
this.showHideControls();
_audioPlayer.stop();
},
next(){
// console.log('CompoPlayer next()');
if(this.playing){
this.current_index += 1;
if(this.current_index < this.playlist.length){
this.play();
}else{
this.stop();
}
}
},
prev(){
// console.log('CompoPlayer prev()');
if(this.playing){
this.current_index -= 1;
if(this.current_index >= 0){
this.play();
}else{
this.stop();
}
}
},
stop(){
_audioPlayer.stop();
this.reset();
},
reset(){
this.playing = false;
this.paused = false;
this.resetIndex();
},
resetIndex(){
this.current_index = 0;
this.showHideControls().resetActiveItems();
},
setActiveItem(){
this.resetActiveItems();
if(this.playing && this.current_index >= 0){
this.playlist[this.current_index].item.addClass('is-active');
}
// this call shoud not be here
this.showHideControls();
return this;
},
resetActiveItems(){
for (var n = 0; n < this.playlist.length; n++) {
// console.log('node',node);
this.playlist[n].item.removeClass('is-active');
}
return this;
},
showHideControls(){
// console.log('CompoPlayer showHideNextBtn(), playing:'+this.playing+', paused:'+this.paused);
// global playing
if(this.playing && !this.paused){
this.$controls.addClass('is-playing');
}else{
this.$controls.removeClass('is-playing');
}
// playpause
if(this.playlist.length > 0){
this.$playpause.addClass('is-active');
}else{
this.$playpause.removeClass('is-active');
}
// next
if(this.playing && this.playlist.length > 1 && this.current_index < this.playlist.length -1){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
// previous
if(this.playing && this.playlist.length > 1 && this.current_index > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
return this;
},
// _audioPlayer events
onAudioOpenDocument(args){
if(args.caller !== this){
// console.log('CompoPlayer onAudioOpenDocument() called by other');
this.reset();
}
// else{
// // console.log('CompoPlayer onAudioOpenDocument() self calling');
// }
},
onAudioPlayerPlay(){
if(this.playing && this.paused){
this.paused = false;
this.showHideControls();
}
},
onAudioPlayerPause(){
if(this.playing && !this.paused){
this.paused = true;
this.showHideControls();
}
},
onAudioPlayerEnded(){
this.next();
},
// onAudioPlayNext(){
// this.next();
// }
};
// ___ _ _ _
// | _ \_ _ ___ __| |_ _ __| |_(_)___ _ _ ___
// | _/ '_/ _ \/ _` | || / _| _| / _ \ ' \(_-<
@@ -1371,6 +1371,8 @@ main[role="main"] span.close-col-btn {
background-image: url(../img/audio-player-play.svg);
padding: 0 0.3em;
cursor: pointer; }
#audio-player .btns.is-playing .play-pause {
background-image: url(../img/audio-player-pause.svg); }
#audio-player .btns .previous, #audio-player .btns .next {
opacity: 0.3;
-webkit-transition: opacity 0.3s ease-in-out;
@@ -1506,8 +1508,6 @@ main[role="main"] span.close-col-btn {
font-size: 0.75em; }
#audio-player .cartel:hover .second-cartel {
opacity: 1; }
#audio-player.is-playing .btns .play-pause {
background-image: url(../img/audio-player-pause.svg); }
.chutier-icon {
z-index: 1;
@@ -1697,6 +1697,17 @@ main[role="main"] span.close-col-btn {
display: inline-block;
vertical-align: middle;
margin-right: 5px; }
#studio-ui .composition_ui > .wrapper .compositions-list a.composition-link.ajax-loading:before {
-webkit-animation: rotation 2s infinite linear;
animation: rotation 2s infinite linear; }
@keyframes rotation {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); }
to {
-webkit-transform: rotate(359deg);
transform: rotate(359deg); } }
#studio-ui .composition_ui > .wrapper .compositions-list a.composition-link.is-active:before {
background-color: black; }
#studio-ui .composition_ui > .wrapper .compositions-list a.delete-composition-link {
@@ -1751,13 +1762,19 @@ main[role="main"] span.close-col-btn {
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding-left: 0.5em;
width: 69%; }
width: 69%;
opacity: 1;
-webkit-transition: opacity 0.3s ease-in-out;
transition: opacity 0.3s ease-in-out; }
#studio-ui .composition_ui > .wrapper .composer.ajax-loading {
opacity: 0.3; }
#studio-ui .composition_ui > .wrapper .composer > * {
-webkit-box-sizing: border-box;
box-sizing: border-box; }
#studio-ui .composition_ui > .wrapper .composer > header {
height: 25px;
padding-bottom: 5px; }
padding-bottom: 5px;
font-size: 0.756em; }
#studio-ui .composition_ui > .wrapper .composer > .composition {
position: relative;
height: calc(100% - 60px);
@@ -1785,10 +1802,10 @@ main[role="main"] span.close-col-btn {
#studio-ui .composition_ui > .wrapper .composer > .composition .field--name-documents .field__item {
display: inline-block;
position: relative;
width: 25px;
height: 100%;
white-space: nowrap;
pointer-events: none;
width: 25px;
height: 100%;
opacity: 1;
-webkit-transition: opacity 0.1s ease-in-out;
transition: opacity 0.1s ease-in-out; }
@@ -1810,6 +1827,7 @@ main[role="main"] span.close-col-btn {
margin: 0;
text-transform: none; }
#studio-ui .composition_ui > .wrapper .composer > .composition .field--name-documents .field__item article h2 a {
white-space: nowrap !important;
font-size: 0.756em; }
#studio-ui .composition_ui > .wrapper .composer > .composition .field--name-documents .field__item article h2 a:before {
content: "";
@@ -1835,6 +1853,8 @@ main[role="main"] span.close-col-btn {
transform: rotateZ(-45deg);
border: 1px solid red;
background-color: white; }
#studio-ui .composition_ui > .wrapper .composer > .composition .field--name-documents .field__item.is-active .handler {
background-color: red; }
#studio-ui .composition_ui > .wrapper .composer > .composition .remove-drop-zone {
position: absolute;
top: 0;
@@ -1845,13 +1865,38 @@ main[role="main"] span.close-col-btn {
#studio-ui .composition_ui > .wrapper .composer > .actions {
padding-top: 5px;
height: 25px; }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls > * {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 30px;
background-position: center;
background-size: contain; }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .play-pause {
background-image: url(../img/audio-player-play.svg);
padding: 0 0.3em;
cursor: pointer; }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls.is-playing .play-pause {
background-image: url(../img/audio-player-pause.svg); }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .previous, #studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .next {
opacity: 0.3;
-webkit-transition: opacity 0.3s ease-in-out;
transition: opacity 0.3s ease-in-out;
cursor: auto; }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .previous.is-active, #studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .next.is-active {
opacity: 1;
cursor: pointer; }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .previous {
background-image: url(../img/audio-player-previous.svg); }
#studio-ui .composition_ui > .wrapper .composer > .actions .compo-player-controls .next {
background-image: url(../img/audio-player-next.svg); }
#studio-ui .field__item.ui-draggable-dragging {
display: inline-block;
position: relative;
width: 25px;
height: 100%;
white-space: nowrap;
pointer-events: none;
width: 25px;
height: 100%;
opacity: 1;
-webkit-transition: opacity 0.1s ease-in-out;
transition: opacity 0.1s ease-in-out; }
@@ -1873,6 +1918,7 @@ main[role="main"] span.close-col-btn {
margin: 0;
text-transform: none; }
#studio-ui .field__item.ui-draggable-dragging article h2 a {
white-space: nowrap !important;
font-size: 0.756em; }
#studio-ui .field__item.ui-draggable-dragging article h2 a:before {
content: "";
@@ -1898,6 +1944,8 @@ main[role="main"] span.close-col-btn {
transform: rotateZ(-45deg);
border: 1px solid red;
background-color: white; }
#studio-ui .field__item.ui-draggable-dragging.is-active .handler {
background-color: red; }
.col[theme="edlp_search_search_form"], .col[theme="edlp_search_search_form"] > .wrapper {
position: relative;
@@ -6,8 +6,9 @@
var _$corpus_canvas;
var _$row = $('main[role="main"]>.layout-content>.row');
var _$ajaxLinks;
var _audio_player;
var _audioPlayer;
var _randomPlayer;
var _compoPlayer;
// ___ _ _
// |_ _|_ _ (_) |_
@@ -20,7 +21,8 @@
_$body.on('corpus-map-ready', onCorpusMapReady);
_audio_player = new AudioPlayer();
_audioPlayer = new AudioPlayer();
_compoPlayer = new CompoPlayer();
initAjaxLinks();
@@ -42,271 +44,18 @@
// |___|\_/\___|_||_\__/__/
function initEvents(){
$('body')
.on('on-studio-chutier-updated', function(e){
.on('on-studio-chutier-updated', initAjaxLinks)
.on('on-studio-compo-updated', function(e){
initAjaxLinks();
_compoPlayer.refresh();
})
.on('search-results-loaded',function(e){
.on('on-studio-compo-opened', function(e){
initAjaxLinks();
_compoPlayer.newCompo();
})
.on('open_entree', function(e){
// e.tid available
closeAllModals();
})
.on('close_entree', function(e){
// e.tid available
backToFrontPage();
});
}
// _ _ _
// /_\ _ _ __| (_)___
// / _ \ || / _` | / _ \
// /_/ \_\_,_\__,_|_\___/
//
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/samples/gg589528%28v%3dvs.85%29
// https://www.binarytides.com/using-html5-audio-element-javascript/
function AudioPlayer(){
var that = this;
this.fid;
this.audio = new Audio();
// audio events
this.audio_events = ["loadedmetadata","canplay","playing","pause","timeupdate","ended"];
// UI dom objects
this.$container = $('<div id="audio-player">');
// btns
this.$btns = $('<div>').addClass('btns').appendTo(this.$container);
this.$previous = $('<div>').addClass('previous').appendTo(this.$btns);
this.$playpause = $('<div>').addClass('play-pause').appendTo(this.$btns);
this.$next = $('<div>').addClass('next').appendTo(this.$btns);
// timeline
this.$timelinecont= $('<div>').addClass('time-line-container').appendTo(this.$container);
this.$timeline = $('<div>').addClass('time-line').appendTo(this.$timelinecont);
this.$loader = $('<div>').addClass('loader').appendTo(this.$timeline);
this.$cursor = $('<div>').addClass('cursor').appendTo(this.$timeline);
// time
this.$time = $('<div>').addClass('time').appendTo(this.$container);
this.$currentTime = $('<div>').addClass('current-time').html('00:00').appendTo(this.$time);
this.$duration = $('<div>').addClass('duration').html('00:00').appendTo(this.$time);
// favoris
this.$fav = $('<div>').addClass('favoris').appendTo(this.$container);
// cartel
this.$cartel = $('<div>').addClass('cartel').appendTo(this.$container);
// hiding
this.hideTimer = false;
this.hideTimeMS = 10000;
// history
this.currentHistoricIndex = null;
this.historic = [];
this.shuffle_is_active = false;
// object events
this.event_handlers = {
'audio-play-next':[],
'audio-ended':[],
'stop-shuffle':[]
};
this.init();
};
AudioPlayer.prototype = {
init(){
// append ui to document
this.$container.appendTo('header[role="banner"] .region-header');
// record timeline width
this.timeline_w = parseInt(this.$timeline.width());
// init audio events
var fn = '';
for (var i = 0; i < this.audio_events.length; i++) {
fn = this.audio_events[i];
// capitalize first letter of event (only cosmetic :p )
fn = 'on'+fn.charAt(0).toUpperCase()+fn.slice(1);
this.audio.addEventListener(
this.audio_events[i],
this[fn].bind(this),
true);
}
// init btns events
this.$previous.on('click', this.playPrevious.bind(this));
this.$playpause.on('click', this.togglePlayPause.bind(this));
this.$next.on('click', this.playNext.bind(this));
// TODO: previous and next btns
},
openDocument(node){
console.log('AudioPlayer openDocument', node);
this.historic.push(node);
this.currentHistoricIndex = this.historic.length-1;
// this.shuffle_mode = shuffle_mode || false;
this.launch();
},
launch(){
this.clearTimeOutToHide();
this.setSRC(this.historic[this.currentHistoricIndex].audio_url);
this.loadNode(this.historic[this.currentHistoricIndex].nid);
// emmit new playing doc (e.g.: corpus map nowing that audio played from RandomPlayer)
try {
_$corpus_canvas.trigger({
'type':'audio-node-opened',
'nid':this.historic[this.currentHistoricIndex].nid
});
} catch (e) {
console.warn('AudioPlayer : _$corpus_canvas does not exists');
}
this.showHidePreviousBtn();
this.showHideNextBtn();
this.show();
},
// audio functions
setSRC(url){
// console.log('AudioPlayer setSRC : url', url);
this.audio.src = url;
},
onLoadedmetadata(){
var rem = parseInt(this.audio.duration, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$duration.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
this.updateLoadingBar();
},
updateLoadingBar(){
this.$loader.css({
'width':parseInt((100 * this.audio.buffered.end(0) / this.audio.duration), 10)+'%'
});
if( this.audio.buffered.end(0) < this.audio.duration ){
// loop through this function until file is fully loaded
var that = this;
window.requestAnimationFrame(that.updateLoadingBar.bind(that));
}else{
console.log('Audio fully loaded');
}
},
onCanplay(){
this.play();
},
play(){
this.audio.play();
},
playPrevious(){
if(this.currentHistoricIndex > 0){
this.currentHistoricIndex -= 1;
this.launch();
}
},
playNext(){
if(this.currentHistoricIndex < this.historic.length-1){
this.currentHistoricIndex += 1;
this.launch();
}else{
this.emmit('audio-play-next');
}
},
togglePlayPause(e){
if(this.audio.paused){
this.audio.play();
}else{
this.audio.pause();
}
},
stop(){
console.log('AudioPlayer stop()');
this.audio.pause();
this.timeOutToHide();
},
// audio events
onPlaying(){
this.$container.addClass('is-playing');
},
onPause(){
this.$container.removeClass('is-playing');
},
onTimeupdate(){
// move cursor
this.$cursor.css({
'left':(this.audio.currentTime/this.audio.duration * this.timeline_w)+"px"
});
// update time text display
var rem = parseInt(this.audio.currentTime, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$currentTime.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
},
onEnded(){
this.emmit('audio-ended');
this.stop();
},
// cartel functions
loadNode(nid){
this.$cartel.addClass('loading');
$.getJSON('/edlp/ajax/json/node/'+nid+'/player_cartel', {})
.done(this.onNodeLoaded.bind(this))
.fail(this.onNodeLoadFail.bind(this));
},
onNodeLoaded(data){
console.log('AudioPlayer node loaded');
this.$cartel.html(data.rendered).removeClass('loading');
_$body.trigger({'type':'new-audio-cartel-loaded'});
initAjaxLinks();
},
onNodeLoadFail(jqxhr, textStatus, error){
console.warn('AudioPlayer node load failed', jqxhr.responseText);
this.$cartel.removeClass('loading').html('');
},
// global
show(){
this.$container.addClass('visible');
},
showHidePreviousBtn(){
if(this.historic.length > 1 && this.currentHistoricIndex > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
},
showHideNextBtn(){
if(this.currentHistoricIndex < this.historic.length-1 || this.shuffle_is_active){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
},
timeOutToHide(){
console.log('AudioPlayer timeOutToHide()');
this.clearTimeOutToHide();
this.hideTimer = setTimeout(this.hide.bind(this), this.hideTimeMS);
},
clearTimeOutToHide(){
console.log('AudioPlayer clearTimeOutToHide()',this.hideTimer);
if(this.hideTimer){
clearTimeout(this.hideTimer);
this.hideTimer = false;
}
},
hide(){
console.log('AudioPlayer hide()');
this.$container.removeClass('visible');
// trigger highlighted node remove on corpus map
_$corpus_canvas.trigger('audio-node-closed');
},
// object events
on(event_name, handler){
if(typeof this.event_handlers[event_name] == 'undefined'){
console.warn('AudioPlayer : event '+event_name+' does not exists');
}
this.event_handlers[event_name].push(handler);
return this;
},
emmit(event_name){
var handler;
for (var i = this.event_handlers[event_name].length; i >= 0 ; i--) {
handler = this.event_handlers[event_name][i];
setTimeout(handler, 0);
}
return this;
},
.on('search-results-loaded', initAjaxLinks)
.on('open_entree', closeAllModals)
.on('close_entree', backToFrontPage);
}
// ___ _ _ ___
@@ -365,7 +114,7 @@
// Audio links
if($link.is('.audio-link')){
// TODO: stop randomplayer
_audio_player
_audioPlayer
.emmit('stop-shuffle')
.openDocument({
nid:$link.attr('nid'),
@@ -521,7 +270,7 @@
})
.on('corpus-cliked-on-node', function(e) {
console.log('theme : corpus-cliked-on-node', e);
_audio_player
_audioPlayer
.emmit('stop-shuffle')
.openDocument(e.target_node);
});
@@ -531,6 +280,284 @@
_$body.attr('corpus-map', 'ready');
}
// _ _ _
// /_\ _ _ __| (_)___
// / _ \ || / _` | / _ \
// /_/ \_\_,_\__,_|_\___/
//
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
// https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/samples/gg589528%28v%3dvs.85%29
// https://www.binarytides.com/using-html5-audio-element-javascript/
function AudioPlayer(){
var that = this;
this.fid;
this.audio = new Audio();
// audio events
this.audio_events = ["loadedmetadata","canplay","playing","pause","timeupdate","ended"];
// UI dom objects
this.$container = $('<div id="audio-player">');
// btns
this.$btns = $('<div>').addClass('btns').appendTo(this.$container);
this.$previous = $('<div>').addClass('previous').appendTo(this.$btns);
this.$playpause = $('<div>').addClass('play-pause').appendTo(this.$btns);
this.$next = $('<div>').addClass('next').appendTo(this.$btns);
// timeline
this.$timelinecont= $('<div>').addClass('time-line-container').appendTo(this.$container);
this.$timeline = $('<div>').addClass('time-line').appendTo(this.$timelinecont);
this.$loader = $('<div>').addClass('loader').appendTo(this.$timeline);
this.$cursor = $('<div>').addClass('cursor').appendTo(this.$timeline);
// time
this.$time = $('<div>').addClass('time').appendTo(this.$container);
this.$currentTime = $('<div>').addClass('current-time').html('00:00').appendTo(this.$time);
this.$duration = $('<div>').addClass('duration').html('00:00').appendTo(this.$time);
// favoris
this.$fav = $('<div>').addClass('favoris').appendTo(this.$container);
// cartel
this.$cartel = $('<div>').addClass('cartel').appendTo(this.$container);
// hiding
this.hideTimer = false;
this.hideTimeMS = 10000;
// history
this.currentHistoricIndex = null;
this.historic = [];
this.shuffle_is_active = false;
// object events
this.event_handlers = {
'audio-open-document':[],
'audio-play':[],
'audio-pause':[],
'audio-play-next':[],
'audio-ended':[],
'stop-shuffle':[]
};
this.init();
};
AudioPlayer.prototype = {
init(){
// append ui to document
this.$container.appendTo('header[role="banner"] .region-header');
// record timeline width
this.timeline_w = parseInt(this.$timeline.width());
// init audio events
var fn = '';
for (var i = 0; i < this.audio_events.length; i++) {
fn = this.audio_events[i];
// capitalize first letter of event (only cosmetic :p )
fn = 'on'+fn.charAt(0).toUpperCase()+fn.slice(1);
this.audio.addEventListener(
this.audio_events[i],
this[fn].bind(this),
true);
}
// init btns events
this.$previous.on('click', this.playPrevious.bind(this));
this.$playpause.on('click', this.togglePlayPause.bind(this));
this.$next.on('click', this.playNext.bind(this));
// TODO: previous and next btns
},
openDocument(node, caller){
// console.log('AudioPlayer openDocument', node);
if(typeof node == 'undefined'
|| typeof node.nid == 'undefined'
|| typeof node.audio_url == 'undfined'){
console.warn('AudioPlayer openDocument() node is malformed', node);
return false;
}
this.historic.push(node);
this.currentHistoricIndex = this.historic.length-1;
// this.shuffle_mode = shuffle_mode || false;
this.emmit('audio-open-document', {caller:caller});
this.launch();
},
launch(){
this.clearTimeOutToHide();
this.setSRC(this.historic[this.currentHistoricIndex].audio_url);
this.loadNode(this.historic[this.currentHistoricIndex].nid);
// emmit new playing doc (e.g.: corpus map nowing that audio played from RandomPlayer)
try {
_$corpus_canvas.trigger({
'type':'audio-node-opened',
'nid':this.historic[this.currentHistoricIndex].nid
});
} catch (e) {
console.info('AudioPlayer : _$corpus_canvas does not exists');
}
this.showHidePreviousBtn();
this.showHideNextBtn();
this.show();
},
// audio functions
setSRC(url){
// console.log('AudioPlayer setSRC : url', url);
this.audio.src = url;
},
onLoadedmetadata(){
var rem = parseInt(this.audio.duration, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$duration.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
this.updateLoadingBar();
},
updateLoadingBar(){
this.$loader.css({
'width':parseInt((100 * this.audio.buffered.end(0) / this.audio.duration), 10)+'%'
});
if( this.audio.buffered.end(0) < this.audio.duration ){
// loop through this function until file is fully loaded
var that = this;
window.requestAnimationFrame(that.updateLoadingBar.bind(that));
}else{
console.log('Audio fully loaded');
}
},
onCanplay(){
this.play();
},
play(){
this.clearTimeOutToHide();
this.audio.play();
},
playPrevious(){
if(this.currentHistoricIndex > 0){
this.currentHistoricIndex -= 1;
this.launch();
}
},
playNext(){
if(this.currentHistoricIndex < this.historic.length-1){
this.currentHistoricIndex += 1;
this.launch();
}else{
this.emmit('audio-play-next');
}
},
togglePlayPause(e){
if(this.audio.paused){
this.audio.play();
}else{
this.audio.pause();
}
},
stop(){
// console.log('AudioPlayer stop()');
this.audio.pause();
this.timeOutToHide();
},
// audio events
onPlaying(){
this.$btns.addClass('is-playing');
this.emmit('audio-play');
},
onPause(){
this.$btns.removeClass('is-playing');
this.emmit('audio-pause');
},
onTimeupdate(){
// move cursor
this.$cursor.css({
'left':(this.audio.currentTime/this.audio.duration * this.timeline_w)+"px"
});
// update time text display
var rem = parseInt(this.audio.currentTime, 10),
mins = Math.floor(rem/60,10),
secs = rem - mins*60;
this.$currentTime.html('<span>'+(mins<10 ? '0':'')+mins+':'+(secs<10 ? '0':'')+secs+'</span>');
},
onEnded(){
this.emmit('audio-ended');
this.stop();
},
// cartel functions
loadNode(nid){
this.$cartel.addClass('loading');
$.getJSON('/edlp/ajax/json/node/'+nid+'/player_cartel', {})
.done(this.onNodeLoaded.bind(this))
.fail(this.onNodeLoadFail.bind(this));
},
onNodeLoaded(data){
// console.log('AudioPlayer node loaded');
this.$cartel.html(data.rendered).removeClass('loading');
_$body.trigger({'type':'new-audio-cartel-loaded'});
initAjaxLinks();
},
onNodeLoadFail(jqxhr, textStatus, error){
console.warn('AudioPlayer node load failed', jqxhr.responseText);
this.$cartel.removeClass('loading').html('');
},
// global
show(){
this.$container.addClass('visible');
},
showHidePreviousBtn(){
if(this.historic.length > 1 && this.currentHistoricIndex > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
},
showHideNextBtn(){
if(this.currentHistoricIndex < this.historic.length-1 || this.shuffle_is_active){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
},
timeOutToHide(){
// console.log('AudioPlayer timeOutToHide()');
this.clearTimeOutToHide();
this.hideTimer = setTimeout(this.hide.bind(this), this.hideTimeMS);
},
clearTimeOutToHide(){
// console.log('AudioPlayer clearTimeOutToHide()',this.hideTimer);
if(this.hideTimer){
clearTimeout(this.hideTimer);
this.hideTimer = false;
}
},
hide(){
// console.log('AudioPlayer hide()');
this.$container.removeClass('visible');
// trigger highlighted node remove on corpus map
try {
_$corpus_canvas.trigger('audio-node-closed');
} catch (e) {
console.info('AudioPlayer hide() : _$corpus_canvas does not exists');
}
},
// object events
on(event_name, handler){
if(typeof this.event_handlers[event_name] == 'undefined'){
console.warn('AudioPlayer : event '+event_name+' does not exists');
}
this.event_handlers[event_name].push(handler);
return this;
},
emmit(event_name, args){
// console.log('AudioPlayer emmit() event_name', event_name);
// console.log('AudioPlayer emmit() handlers', this.event_handlers[event_name]);
var handler;
var args = args || {};
for (var i = this.event_handlers[event_name].length-1; i >= 0 ; i--) {
handler = this.event_handlers[event_name][i];
// console.log('AudioPlayer emmit() loop handler', handler);
setTimeout(function(){
// console.log('AudioPlayer emmit() timeout handler', handler);
handler(args);
}, 0);
}
return this;
},
}
// ___ _ ___ _
// | _ \__ _ _ _ __| |___ _ __ | _ \ |__ _ _ _ ___ _ _
// | / _` | ' \/ _` / _ \ ' \| _/ / _` | || / -_) '_|
@@ -540,7 +567,7 @@
this.active = false;
this.playlist = playlist;
this.$btn = $('<a>').html('Shuffle').addClass('random-player-btn');
this.init()
this.init();
};
RandomPlayer.prototype = {
init(){
@@ -554,7 +581,7 @@
this.$btn.on('click', this.toggleActive.bind(this));
// attach an event on AudioPlayer
_audio_player
_audioPlayer
.on('audio-ended', this.onAudioPlayerEnded.bind(this))
.on('audio-play-next', this.onAudioPlayNext.bind(this))
.on('stop-shuffle', this.stop.bind(this));
@@ -579,20 +606,20 @@
}
},
start(){
this.active = _audio_player.shuffle_is_active = true;
this.active = _audioPlayer.shuffle_is_active = true;
this.$btn.addClass('is-active');
this.shuffle();
this.next();
},
stop(){
this.active = _audio_player.shuffle_is_active = false;
this.active = _audioPlayer.shuffle_is_active = false;
this.$btn.removeClass('is-active');
// stop audio player
// _audio_player.stop();
// _audioPlayer.stop();
},
next(){
if(this.active && this.shuffledPlaylist.length > 0)
_audio_player.openDocument(this.shuffledPlaylist.splice(0,1)[0]);
_audioPlayer.openDocument(this.shuffledPlaylist.splice(0,1)[0]);
},
onAudioPlayNext(){
console.log('RandomPlayer : onAudioPlayNext()');
@@ -604,6 +631,215 @@
}
};
// ___ ___ _
// / __|___ _ __ _ __ ___| _ \ |__ _ _ _ ___ _ _
// | (__/ _ \ ' \| '_ \/ _ \ _/ / _` | || / -_) '_|
// \___\___/_|_|_| .__/\___/_| |_\__,_|\_, \___|_|
// |_| |__/
function CompoPlayer(){
this.playing = false;
this.paused = false;
this.playlist = [];
this.current_index = 0;
this.$compo = null;
this.init();
};
CompoPlayer.prototype = {
init(){
console.log('CompoPlayer init()');
// attach an event on AudioPlayer
_audioPlayer
.on('audio-open-document', this.onAudioOpenDocument.bind(this))
.on('audio-play', this.onAudioPlayerPlay.bind(this))
.on('audio-pause', this.onAudioPlayerPause.bind(this))
.on('audio-ended', this.onAudioPlayerEnded.bind(this));
// .on('audio-play-next', this.onAudioPlayNext.bind(this));
this.newCompo();
},
newCompo(){
console.log('CompoPlayer newCompo()');
// $('.composition_ui .composer .composition .field--name-documents')
this.$composer = $('.composition_ui .composer');
this.$compo = $('.composition_ui .composer .composition');
this.$controls = $('.composition_ui .composer .compo-player-controls');
this.$previous = $('<div>').addClass('previous')
.on('click', this.prev.bind(this))
.appendTo(this.$controls);
this.$playpause = $('<div>').addClass('play-pause')
.on('click', this.togglePlayPause.bind(this))
.appendTo(this.$controls);
this.$next = $('<div>').addClass('next')
.on('click', this.next.bind(this))
.appendTo(this.$controls);
// this.$playpause = $('.compo-player-controls', this.$composer)
// .on('click', this.togglePlayPause.bind(this));
this.refresh();
},
refresh(){
// console.log('CompoPlayer refresh(), this', this);
// this.playing = false;
// this.paused = false;
// this.resetIndex();
this.stop();
// load new playlist
this.playlist = [];
var that = this;
$('.field--name-documents .field__item',this.$compo).each(function(i,el){
var $link = $('a.audio-link',this);
that.playlist.push({
item:$(this),
audio_url:$link.attr("audio_url"),
nid:$link.attr("nid"),
});
});
this.showHideControls();
},
togglePlayPause(){
// console.log('CompoPlayer togglePlayPause');
if (this.playing && !this.paused) {
this.pause();
}else{
if(this.playing && this.paused){
this.play();
}else{
this.start();
}
}
},
start(){
console.log('start');
// console.log('CompoPlayer start()');
this.playing = true;
this.play();
},
play(){
// console.log('play');
if(this.paused){
this.paused = false;
_audioPlayer.play();
}else{
_audioPlayer.openDocument(this.playlist[this.current_index], this);
}
this.setActiveItem().showHideControls();
},
pause(){
console.log('pause');
this.paused = true;
this.showHideControls();
_audioPlayer.stop();
},
next(){
// console.log('CompoPlayer next()');
if(this.playing){
this.current_index += 1;
if(this.current_index < this.playlist.length){
this.play();
}else{
this.stop();
}
}
},
prev(){
// console.log('CompoPlayer prev()');
if(this.playing){
this.current_index -= 1;
if(this.current_index >= 0){
this.play();
}else{
this.stop();
}
}
},
stop(){
_audioPlayer.stop();
this.reset();
},
reset(){
this.playing = false;
this.paused = false;
this.resetIndex();
},
resetIndex(){
this.current_index = 0;
this.showHideControls().resetActiveItems();
},
setActiveItem(){
this.resetActiveItems();
if(this.playing && this.current_index >= 0){
this.playlist[this.current_index].item.addClass('is-active');
}
// this call shoud not be here
this.showHideControls();
return this;
},
resetActiveItems(){
for (var n = 0; n < this.playlist.length; n++) {
// console.log('node',node);
this.playlist[n].item.removeClass('is-active');
}
return this;
},
showHideControls(){
// console.log('CompoPlayer showHideNextBtn(), playing:'+this.playing+', paused:'+this.paused);
// global playing
if(this.playing && !this.paused){
this.$controls.addClass('is-playing');
}else{
this.$controls.removeClass('is-playing');
}
// playpause
if(this.playlist.length > 0){
this.$playpause.addClass('is-active');
}else{
this.$playpause.removeClass('is-active');
}
// next
if(this.playing && this.playlist.length > 1 && this.current_index < this.playlist.length -1){
this.$next.addClass('is-active');
}else{
this.$next.removeClass('is-active');
}
// previous
if(this.playing && this.playlist.length > 1 && this.current_index > 0){
this.$previous.addClass('is-active');
}else{
this.$previous.removeClass('is-active');
}
return this;
},
// _audioPlayer events
onAudioOpenDocument(args){
if(args.caller !== this){
// console.log('CompoPlayer onAudioOpenDocument() called by other');
this.reset();
}
// else{
// // console.log('CompoPlayer onAudioOpenDocument() self calling');
// }
},
onAudioPlayerPlay(){
if(this.playing && this.paused){
this.paused = false;
this.showHideControls();
}
},
onAudioPlayerPause(){
if(this.playing && !this.paused){
this.paused = true;
this.showHideControls();
}
},
onAudioPlayerEnded(){
this.next();
},
// onAudioPlayNext(){
// this.next();
// }
};
// ___ _ _ _
// | _ \_ _ ___ __| |_ _ __| |_(_)___ _ _ ___
// | _/ '_/ _ \/ _` | || / _| _| / _ \ ' \(_-<
@@ -258,6 +258,39 @@ main[role="main"]{
// / _ \ || / _` | / _ \ _/ / _` | || / -_) '_|
// /_/ \_\_,_\__,_|_\___/_| |_\__,_|\_, \___|_|
// |__/
@mixin audio_controls {
// outline: 1px dotted orange;
&>*{
display: inline-block;
vertical-align: middle;
width:20px;height:30px;
background-position: center;
background-size: contain;
}
.play-pause{
background-image: url(../img/audio-player-play.svg);
padding:0 0.3em;
cursor: pointer;
}
&.is-playing{
.play-pause{background-image: url(../img/audio-player-pause.svg);}
}
.previous, .next{
opacity: 0.3;
transition: opacity 0.3s ease-in-out;
cursor: auto;
&.is-active{
opacity: 1;
cursor: pointer;
}
}
.previous{
background-image: url(../img/audio-player-previous.svg);
}
.next{
background-image: url(../img/audio-player-next.svg);
}
}
#audio-player{
position: absolute;
top:0; left:0;
@@ -281,34 +314,7 @@ main[role="main"]{
// outline: 1px solid green;
}
.btns{
// outline: 1px dotted orange;
&>*{
display: inline-block;
vertical-align: middle;
width:20px;height:30px;
background-position: center;
background-size: contain;
}
.play-pause{
background-image: url(../img/audio-player-play.svg);
padding:0 0.3em;
cursor: pointer;
}
.previous, .next{
opacity: 0.3;
transition: opacity 0.3s ease-in-out;
cursor: auto;
&.is-active{
opacity: 1;
cursor: pointer;
}
}
.previous{
background-image: url(../img/audio-player-previous.svg);
}
.next{
background-image: url(../img/audio-player-next.svg);
}
@include audio_controls;
}
.time-line-container{
.time-line{
@@ -413,9 +419,7 @@ main[role="main"]{
}
}
}
&.is-playing{
.btns .play-pause{background-image: url(../img/audio-player-pause.svg);}
}
}
@@ -473,18 +477,16 @@ main[role="main"]{
#studio-ui{
height:100%;
@mixin draggable_sortable_field__item {
// outline: 1px dotted green;
display: inline-block;
position: relative;
white-space: nowrap;
pointer-events: none;
// margin-right: 25px;
width:25px;
height: 100%;
&.ui-draggable-dragging{
height:100px;
// cursor: grabbing;
}
white-space: nowrap;
pointer-events: none;
opacity: 1;
transition: opacity 0.1s ease-in-out;
&.ready-to-remove{
@@ -504,6 +506,7 @@ main[role="main"]{
margin:0;
text-transform: none;
a{
white-space: nowrap!important;
&:before{
content:"";
display: inline-block;
@@ -530,6 +533,9 @@ main[role="main"]{
background-color: white;
// TODO: entries color;
}
&.is-active .handler{
background-color: red;
}
} // end mixin
.chutier_ui{
@@ -652,6 +658,9 @@ main[role="main"]{
vertical-align: middle;
margin-right: $m;
}
&.ajax-loading:before{
@include spining-loader-square;
}
&.is-active:before{
background-color: black;
}
@@ -718,12 +727,18 @@ main[role="main"]{
$header_height:25px;
$actions_height:25px;
$padding:5px;
opacity:1;
transition: opacity 0.3s ease-in-out;
&.ajax-loading{
opacity:0.3;
}
>*{
box-sizing: border-box;
}
>header{
height:$header_height;
padding-bottom:$padding;
font-size: 0.756em;
}
>.composition{
position: relative;
@@ -772,10 +787,14 @@ main[role="main"]{
padding-top:$padding;
height:$actions_height;
// outline: 1px solid blue;
.compo-player-controls{
@include audio_controls;
}
}
}
}
}
// drag and drop specifics
// created by js
.field__item.ui-draggable-dragging{
@@ -103,7 +103,6 @@ function edlptheme_preprocess_node__enregistrement__search_index(&$vars){
// dpm($vars['link_attributes']);
}
function edlptheme_preprocess_node__enregistrement__compo(&$vars){
$node = $vars['elements']['#node'];
$options = ['absolute' => TRUE];
@@ -125,6 +124,10 @@ function edlptheme_preprocess_node__enregistrement__compo(&$vars){
'nid' => $node->id(),
'class' => array('audio-link', 'ajax-link')
));
// dpm($vars);
$title = $vars['label'][0]['#context']['value'];
$vars['label'][0]['#context']['value'] = Unicode::truncate($title, 25, true, true);
// dpm($vars['link_attributes']);
}
@@ -84,8 +84,9 @@
<article{{ attributes.addClass(classes) }}>
<h2{{ title_attributes.addClass('node-title') }}>
<a href="{{ url }}" rel="bookmark" {{ link_attributes }}>
{% set text = label|render|striptags %}
{{ text|length > 25 ? text|slice(0, 25)|split(' ')|slice(0, -1)|join(' ') ~ '…' : text }}
{{ label }}
{# set text = label|render|striptags #}
{# text|length > 25 ? text|slice(0, 25)|split(' ')|slice(0, -1)|join(' ') ~ '…' : text #}
</a>
</h2>
</article>
@@ -12,13 +12,20 @@ content:
documents:
label: hidden
type: entity_reference_entity_view
weight: 0
weight: 1
region: content
settings:
view_mode: compo
link: false
third_party_settings: { }
name:
type: string
weight: 0
region: content
label: hidden
settings:
link_to_entity: false
third_party_settings: { }
hidden:
langcode: true
name: true
user_id: true
@@ -0,0 +1,26 @@
uuid: d063513e-e6a2-471a-93e0-9b02fa1117d9
langcode: fr
status: true
dependencies:
config:
- core.entity_view_mode.composition.studio_ui
module:
- edlp_studio
id: composition.composition.studio_ui
targetEntityType: composition
bundle: composition
mode: studio_ui
content:
documents:
label: hidden
type: entity_reference_entity_view
weight: 0
region: content
settings:
view_mode: compo
link: false
third_party_settings: { }
hidden:
langcode: true
name: true
user_id: true
@@ -0,0 +1,10 @@
uuid: eff6d988-0963-4718-ad52-bf10a8e1463d
langcode: fr
status: true
dependencies:
module:
- edlp_studio
id: composition.studio_ui
label: studio-ui
targetEntityType: composition
cache: true