From 69f19710528d363488844c79c973df2c7612648d Mon Sep 17 00:00:00 2001 From: luccioman Date: Wed, 30 Jan 2019 18:43:13 +0100 Subject: [PATCH] Added basic controls to play all audio results. Not displayed when JavaScript is disabled. --- htroot/env/base.css | 23 +++ htroot/js/yacysearch.js | 47 +----- htroot/js/yacysearchAudio.js | 294 +++++++++++++++++++++++++++++++++++ htroot/jslicense.html | 5 + htroot/yacysearch.html | 38 ++++- htroot/yacysearchitem.html | 9 +- 6 files changed, 370 insertions(+), 46 deletions(-) create mode 100644 htroot/js/yacysearchAudio.js diff --git a/htroot/env/base.css b/htroot/env/base.css index 08e0759d9..3cd0e750e 100644 --- a/htroot/env/base.css +++ b/htroot/env/base.css @@ -1089,6 +1089,29 @@ div#tagcloud { z-index: 100; } + + /******* yacysearch.html ********** + + /* Higlight overall audio controls when playing all results */ +#audioControls:not([data-current-track="-1"]) { + border-style: solid; + border-color: #1e90ff; +} + +#stopAllBtn:hover { + color: red; +} + +#playAllBtn:hover .glyphicon-play { + color: #32cd32; +} + +#playAllBtn:hover .glyphicon-pause { + color: #ff8c00; +} + +/******* yacysearch.html end ***********/ + /******* yacysearchtrailer.html ********** Styling for the resource switch button, to avoid overlapping at various screen sizes */ diff --git a/htroot/js/yacysearch.js b/htroot/js/yacysearch.js index 51eb81ea8..09305031d 100644 --- a/htroot/js/yacysearch.js +++ b/htroot/js/yacysearch.js @@ -286,52 +286,11 @@ function toggleMoreTags(button, moreTagsId) { } } -/** - * Handle embedded audio result load error. - * - * @param event - * {ErrorEvent} the error event triggered - */ -function handleAudioLoadError(event) { - if (event != null && event.target != null) { - /* Fill the title attribute to provide some feedback about the error without need for looking at the console */ - if (event.target.error != null && event.target.error.message) { - event.target.title = "Cannot play (" - + event.target.error.message + ")"; - } else { - event.target.title = "Cannot play"; - } - - /* Apply CSS class marking error for visual feedback*/ - event.target.className = "audioError"; - } -} - -/** - * Handle embedded audio result 'playing' event : pauses any other currently - * playing audio. - * - * @param event - * {Event} a 'playing' event - */ -function handleAudioPlaying(event) { - if (event != null && event.target != null) { - var audioElems = document.getElementsByTagName("audio"); - if(audioElems != null) { - for (var i = 0; i < audioElems.length; i++) { - var audioElem = audioElems[i]; - if (audioElem != event.target && audioElem.pause - && !audioElem.paused) { - audioElem.pause(); - } - } - } - } -} - /** * Handle a rendering error on a result image thumbnail. - * @param imgElem {HTMLImageElement} the html img element that could not be rendered + * + * @param imgElem + * {HTMLImageElement} the html img element that could not be rendered */ function handleResultThumbError(imgElem) { if (imgElem.parentNode != null && imgElem.parentNode.parentNode != null diff --git a/htroot/js/yacysearchAudio.js b/htroot/js/yacysearchAudio.js new file mode 100644 index 000000000..3d04cd663 --- /dev/null +++ b/htroot/js/yacysearchAudio.js @@ -0,0 +1,294 @@ +/* +* Copyright (C) 2019 by luccioman; https://github.com/luccioman +* +* This file is part of YaCy. +* +* YaCy is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 of the License, or +* (at your option) any later version. +* +* YaCy is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with YaCy. If not, see . +*/ + +/* Functions dedicated to control playing of YaCy audio search results */ + +/** + * Handle embedded audio result load error. + * + * @param event + * {ErrorEvent} the error event triggered + */ +function handleAudioLoadError(event) { + if (event != null && event.target != null) { + /* Fill the title attribute to provide some feedback about the error without need for looking at the console */ + if (event.target.error != null && event.target.error.message) { + event.target.title = "Cannot play (" + + event.target.error.message + ")"; + } else { + event.target.title = "Cannot play"; + } + + /* Apply CSS class marking error for visual feedback*/ + event.target.className = "audioError"; + + /* Start playing the next audio result when "Play all" is running */ + var playerElem = document.getElementById("audioControls"); + var currentPlayAllTrack = playerElem != null ? parseInt(playerElem + .getAttribute("data-current-track")) : -1; + if(!isNaN(currentPlayAllTrack) && currentPlayAllTrack >= 0) { + /* Currently playing all audio results */ + playAllNext(playerElem); + } + } +} + +/** + * Handle embedded audio result 'playing' event : pauses any other currently + * playing audio. + * + * @param event + * {Event} a 'playing' event + */ +function handleAudioPlaying(event) { + if (event != null && event.target != null) { + var audioElems = document.getElementsByTagName("audio"); + var playerElem = document.getElementById("audioControls"); + var currentPlayAllTrack = playerElem != null ? parseInt(playerElem + .getAttribute("data-current-track")) : -1; + if (audioElems != null) { + for (var i = 0; i < audioElems.length; i++) { + var audioElem = audioElems[i]; + + if (audioElem == event.target) { + if (!isNaN(currentPlayAllTrack) && currentPlayAllTrack >= 0) { + if(currentPlayAllTrack == i) { + /* Starting or resuming play of the currently selected "Play all" track */ + updatePlayAllButton(true); + } else { + /* Playing here a single result while "Play all" was running on a different track */ + + /* "Play all" is interrupted */ + updatePlayAllButton(false); + + /* Update the current play all track index */ + playerElem.setAttribute("data-current-track", -1); + } + } + } else if (audioElem.pause && !audioElem.paused) { + audioElem.pause(); + } + } + } + } +} + +/** + * Handle embedded audio result 'pause' event. + * + * @param event + * {Event} a 'pause' event + */ +function handleAudioPause(event) { + if(event != null && event.target != null && event.target.error == null) { + var playerElem = document.getElementById("audioControls"); + var currentPlayAllTrack = playerElem != null ? parseInt(playerElem + .getAttribute("data-current-track")) : -1; + if(!isNaN(currentPlayAllTrack) && currentPlayAllTrack >= 0) { + /* Currently playing all audio results */ + var audioElems = document.getElementsByTagName("audio"); + if(audioElems != null) { + for(var i = 0; i < audioElems.length; i++) { + if(audioElems[i] == event.target && currentPlayAllTrack == i) { + /* Update the "Play all" button icon to reflect the new status. + * Do not update when pausing another track that may be already paused. */ + updatePlayAllButton(false); + } + } + } + } + } +} + +/** + * Handle embedded audio result 'ended' event : start playing the next audio + * result when the "Play all" button is pressed. + * + * @param event + * {Event} a 'playing' event + */ +function handleAudioEnded(event) { + if (event != null && event.target != null) { + /* Start playing the next audio result when "Play all" is pressed */ + var playerElem = document.getElementById("audioControls"); + var currentPlayAllTrack = playerElem != null ? parseInt(playerElem + .getAttribute("data-current-track")) : -1; + if(!isNaN(currentPlayAllTrack) && currentPlayAllTrack >= 0) { + /* Currently playing all audio results */ + playAllNext(playerElem); + } + } +} + +/** + * Start playing the next audio result when one is available and update the + * "Play all" button. + * + * @param playerElem + * the player container element + */ +function playAllNext(playerElem) { + if (playerElem == null) { + return; + } + var audioElems = document.getElementsByTagName("audio"); + if (audioElems == null) { + /* No more audio elements ? */ + playerElem.setAttribute("data-current-track", -1); + updatePlayAllButton(false); + } else { + var currentTrack = parseInt(playerElem.getAttribute("data-current-track")); + var nextTrack; + if (isNaN(currentTrack) || currentTrack < 0 + || currentTrack >= audioElems.length) { + nextTrack = 0; + } else { + nextTrack = currentTrack + 1; + } + if (nextTrack < audioElems.length) { + while (nextTrack < audioElems.length) { + var audioElem = audioElems[nextTrack]; + if (audioElem != null && audioElem.error == null + && audioElem.play) { + if(audioElem.currentTime > 0) { + audioElem.currentTime = 0; + } + audioElem.play(); + updatePlayAllButton(true); + playerElem.setAttribute("data-current-track", nextTrack); + break; + } + /* Go to the next element when not playable */ + nextTrack++; + } + } else { + /* No other result to play */ + playerElem.setAttribute("data-current-track", -1); + updatePlayAllButton(false); + } + } +} + +/** + * Update the "Play all" button + * @param playing when true the new status becomes playing all, otherwise it becomes paused + */ +function updatePlayAllButton(playing) { + var playAllIcon = document.getElementById("playAllIcon"); + if (playAllIcon != null) { + if(playing) { + if(playAllIcon.className != "glyphicon glyphicon-pause") { + playAllIcon.className = "glyphicon glyphicon-pause"; + } + } else if(playAllIcon.className != "glyphicon glyphicon-play") { + playAllIcon.className = "glyphicon glyphicon-play"; + } + } + var playAllBtn = document.getElementById("playAllBtn"); + if(playAllBtn != null) { + if(playing) { + var pauseTitle = playAllBtn.getAttribute("data-pause-title"); + if(pauseTitle != null && playAllBtn.title != pauseTitle) { + playAllBtn.title = pauseTitle; + } + } else { + var playAllTitle = playAllBtn.getAttribute("data-playAll-title"); + if(playAllTitle != null && playAllBtn.title != playAllTitle) { + playAllBtn.title = playAllTitle; + } + } + } + +} + +/** + * Handle a click on the "Play all" button. + */ +function handlePlayAllBtnClick() { + var audioElems = document.getElementsByTagName("audio"); + var playerElem = document.getElementById("audioControls"); + var playAllIcon = document.getElementById("playAllIcon"); + if (playerElem != null && audioElems != null) { + if (playAllIcon.className == "glyphicon glyphicon-play" && audioElems.length > 0) { + var currentTrack = parseInt(playerElem + .getAttribute("data-current-track")); + if (isNaN(currentTrack) || currentTrack < 0 + || currentTrack >= audioElems.length) { + /* Start a new play of all audio results */ + currentTrack = 0; + /* Reset all times */ + for (var j = 0; j < audioElems.length; j++) { + var elem = audioElems[j]; + if (elem.paused && elem.currentTime > 0) { + elem.currentTime = 0; + } + } + } + while (currentTrack < audioElems.length) { + var currentAudioElem = audioElems[currentTrack]; + if (currentAudioElem != null && currentAudioElem.error == null + && currentAudioElem.play) { + currentAudioElem.play(); + updatePlayAllButton(true); + break; + } + /* Go to the next element when not playable */ + currentTrack++; + } + playerElem.setAttribute("data-current-track", currentTrack); + } else { + /* Pause any running track */ + for (var i = 0; i < audioElems.length; i++) { + var audioElem = audioElems[i]; + if (audioElem.pause && !audioElem.paused) { + audioElem.pause(); + } + } + } + } +} + +/** + * Handle a click on the "Stop all" button. + */ +function handleStopAllBtnClick() { + /* Stop all audio elements */ + var audioElems = document.getElementsByTagName("audio"); + if (audioElems != null) { + for (var i = 0; i < audioElems.length; i++) { + var audioElem = audioElems[i]; + if (audioElem.pause && !audioElem.paused) { + audioElem.pause(); + if(audioElem.currentTime > 0) { + audioElem.currentTime = 0; + } + } else if(audioElem.paused && audioElem.currentTime > 0) { + audioElem.currentTime = 0; + } + } + } + + updatePlayAllButton(false); + + /* Update the current track index */ + var playerElem = document.getElementById("audioControls"); + if (playerElem != null) { + playerElem.setAttribute("data-current-track", -1); + } +} \ No newline at end of file diff --git a/htroot/jslicense.html b/htroot/jslicense.html index b863e6d0e..2db9a34c3 100755 --- a/htroot/jslicense.html +++ b/htroot/jslicense.html @@ -208,6 +208,11 @@ GNU-GPL-2.0-or-later yacysearch.js + + yacysearchAudio.js + GNU-GPL-2.0-or-later + yacysearchAudio.js + yacysort.js GNU-GPL-2.0-or-later diff --git a/htroot/yacysearch.html b/htroot/yacysearch.html index abd6843fb..a31a11d11 100644 --- a/htroot/yacysearch.html +++ b/htroot/yacysearch.html @@ -9,6 +9,9 @@ + #(resultTable)#:::: + #(embed)#::#(/embed)# + #(/resultTable)# @@ -23,6 +26,18 @@ #(/jsResort)#