Отображение мультимедиа с помощью HTML и JavaScript
У меня есть личный веб-сайт, который я использую, чтобы делиться видео и изображениями с друзьями. Ниже представлен медиа-генератор, использующий JavaScript и HTML. Его основная цель - отображать по одному изображению одним нажатием кнопки, но может отображаться любой тип мультимедиа. Моей целью было создать быстро загружающуюся страницу, на которой будут храниться все мои медиа.
//VIDEO ARRAY
var oddvideo = [
'video1',
'video2',
'video3',
'video4',
'video5',
];
//AUDIO ARRAY
var oddaudio = [
'audio1',
'audio2',
'audio3',
'audio4',
'audio5',
];
//PHOTO ARRAY
var oddphoto = [
'photo1',
'photo2',
'photo3',
'photo4',
'photo5',
];
//TEXT ARRAY
var oddtext = [
'text1',
'text2',
'text3',
'text4',
'text5',
];
//RANDOM UNUSED ARRAY ITEMS
var Uvideo = [];
var Uaudio = [];
var Uphoto = [];
var Utext = [];
//OLD-NEW VARIABLES
var videoFor = 0;
var audioFor = 0;
var photoFor = 0;
var textFor = 0;
//NEW-OLD VARIABLES
var videoRev = oddvideo.length - 1;
var audioRev = oddaudio.length - 1;
var photoRev = oddphoto.length - 1;
var textRev = oddtext.length - 1;
//GENERATOR FUNCTION
function newThing() {
//RANDOM MODE
if(mode1.checked && (videoCheck.checked || audioCheck.checked || photoCheck.checked || textCheck.checked)) {
if (videoCheck.checked) {
if (!Uvideo.length) Uvideo = [...oddvideo];
var randomY = Uvideo;
}
if (audioCheck.checked) {
if (!Uaudio.length) Uaudio = [...oddaudio];
var randomY = Uaudio;
}
if (photoCheck.checked) {
if (!Uphoto.length) Uphoto = [...oddphoto];
var randomY = Uphoto;
}
if (textCheck.checked) {
if (!Utext.length) Utext = [...oddtext];
var randomY = Utext;
}
var randomX = Math.floor(Math.random() * (randomY.length));
var y = randomY;
var x = randomX;
document.getElementById("thingDisplay").innerHTML = y[x];
// remove randomx from the unused array since it's been used now
randomY.splice(randomX, 1);
}
//OLD-NEW MODE
if(mode2.checked && (videoCheck.checked || audioCheck.checked || photoCheck.checked || textCheck.checked)) {
if(videoCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddvideo[videoFor];
videoFor++;
if (videoFor >= oddvideo.length) videoFor = 0;
}
if(audioCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddaudio[audioFor];
audioFor++;
if (audioFor >= oddaudio.length) audioFor = 0;
}
if(photoCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddphoto[photoFor];
photoFor++;
if (photoFor >= oddphoto.length) photoFor = 0;
}
if(textCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddtext[textFor];
textFor++;
if (textFor >= oddtext.length) textFor = 0;
}
}
//NEW-OLD MODE
if(mode3.checked && (videoCheck.checked || audioCheck.checked || photoCheck.checked || textCheck.checked)) {
if(videoCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddvideo[videoRev];
videoRev--;
if (videoRev < 0) videoRev = oddvideo.length - 1;
}
if(audioCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddaudio[audioRev];
audioRev--;
if (audioRev < 0) audioRev = oddaudio.length - 1;
}
if(photoCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddphoto[photoRev];
photoRev--;
if (photoRev < 0) photoRev = oddphoto.length - 1;
}
if(textCheck.checked) {
document.getElementById('thingDisplay').innerHTML = oddtext[textRev];
textRev--;
if (textRev < 0) textRev = oddtext.length - 1;
}
}
}
<body>
<div align="center" id='thingDisplay'></div>
<div align="center">
<button onclick="newThing()">New Thing</button>
</div>
<form id="mode">
<label><input type="radio" name="modes" id="mode1"/></label> Random
<br/><label><input type="radio" name="modes" id="mode2"/></label> Old - New
<br/><label><input type="radio" name="modes" id="mode3"/></label> New - Old
</form>
<div align="right">
<form id="categories" align="right">
Video<label> <input type="radio" name="thing" id="videoCheck"/></label><br/>
Audio<label> <input type="radio" name="thing" id="audioCheck"/></label><br/>
Photo<label> <input type="radio" name="thing" id="photoCheck"/></label><br/>
Text<label> <input type="radio" name="thing" id="textCheck"/></label>
</form>
</div>
</body>
Несколько замечаний ...
Я организовываю массивы JavaScript с самым молодым вверху и самым старым внизу (с датами это будет выглядеть так:
oddDate = ['Oct. 1', 'Oct. 2', 'Oct. 3', 'Oct. 4', 'Oct. 5'];Случайный режим является псевдослучайным и предназначен для отображения всех элементов массива один раз перед повторением одного.
Режимы «старый-новый» и «новый-старый» перемещаются по массивам сверху вниз и снизу вверх соответственно.
Каждый режим и категория сохраняют свое место при переходе на другой. Например, предположим, что у вас включен старый-новый режим и вы находитесь в пункте 3 текстовой категории. Вы переключаетесь в категорию фотографий, немного пробегаете по массиву, а затем возвращаетесь в категорию текста. Он отобразит следующий элемент с того места, на котором вы остановились ранее, то есть элемент 4 . То же самое можно сказать и о переключении между тремя режимами; все они независимы друг от друга. Это то, что я хотел бы сохранить.
Одна проблема заключается в том, что генератор и страница будут становиться все медленнее и медленнее, поскольку я продолжаю добавлять элементы в массивы, но я не уверен, законно ли это. В живой версии каждый массив содержит более 500 элементов, и со временем будет добавляться больше.
Ответы
Общий отзыв
Кажется, что этот код работает приемлемо, хотя семантика «старое - новое» кажется обратной.
Первый пункт в примечаниях гласит:
- Я упорядочиваю массивы JavaScript с самым младшим наверху и самым старым внизу (с датами это будет выглядеть так: oddDate = ['1 октября', '2 октября', '3 октября', 'Oct. 4 ',' 5 октября '];)
Тем не менее, третий пункт гласит:
- Режимы «старый-новый» и «новый-старый» перемещаются по массивам сверху вниз и снизу вверх соответственно.
Это кажется противоречивым, поскольку, если самый старый был внизу, тогда сортировка старого-нового должна начинаться с конца массива.
Код JavaScript кажется очень повторяющимся - особенно в функциях, newThing()но также и в именах переменных. Я бы рекомендовал некоторые изменения, описанные позже, после обзора.
Обзор
Javascript
Объявления переменных
В коде используются некоторые функции, характерные для ECMAScript-2015 (AKA ES-6), такие как синтаксис распространения . С переменными ES6 рекомендуется использовать constи letограничивать область переменных, чтобы избежать ошибок . Обратите внимание, что constэто не означает неизменность, а скорее то, что такую переменную нельзя переназначить.
Глобальные переменные
Код ссылается на элементы DOM, используя переменные, неявно созданные из атрибутов id, например
if(mode1.checked && (videoCheck.checked || audioCheck.checked || photoCheck.checked || textCheck.checked)) {
Если вы хотите провести модульное тестирование кода JavaScript, это может усложнить задачу.
Метки ввода
Похоже, что все радио-входы содержатся во <label>входах, что хорошо для доступности (например, программы чтения с экрана, возможность пользователя щелкнуть метку для фокусировки / активации входа), однако текст рядом с каждым входом не находится внутри метки. Кажется бессмысленным иметь ярлык, если в нем только ввод.
HTML
Встроенные обработчики событий
Код устанавливает обработчики событий в HTML-коде:
<button onclick="newThing()">New Thing</button>
Лучше регистрировать обработчики событий в JavaScript (например, используя newButton.addEventListenerпо нескольким причинам:
- Логика может быть отделена от разметки - если над проектом работали несколько товарищей по команде, один мог работать над JavaScript, а другой мог работать над HTML независимо.
- Такие обработчики могут загрязнять глобальное пространство имен, что может привести к странному поведению .
Выравнивание дочерних элементов
У <div>элементов есть align="center"и align="right". Это устаревший атрибут HTML 4, который больше не поддерживается в HTML 5. Его можно преобразовать в правила CSS . Обратите внимание, что это text-alignотносится к блок-контейнерам 1 . Для центральных встроенных элементов , таких как изображения, видео и т.д. должны быть установлены в и набор для .displayblockmarginauto
Несколько элементов формы
Есть два отдельных <form>элемента. Их можно объединить в единую форму, содержащую все элементы.
Упрощение кода
Следующие изменения, наряду с предложениями из вышеперечисленных пунктов обзора, могут быть использованы для значительного уменьшения длины кода:
поместить параметры в объект, который может содержать текущий индекс, и сделать объект свойством объекта, где имя свойства (т.е. ключ) является типом объекта - например,
const options = { video: { options: [ //VIDEO ARRAY 'video1', 'video2', 'video3', 'video4', 'video5', ], currentIndex: -1 }, audio: { options: [ //AUDIO ARRAY 'audio1', 'audio2', 'audio3', 'audio4', 'audio5', ], currentIndex: -1 }, photo: { options: [ //PHOTO ARRAY 'photo1', 'photo2', 'photo3', 'photo4', 'photo5', ], currentIndex: -1 }, text: { options: [ //TEXT ARRAY 'text1', 'text2', 'text3', 'text4', 'text5', ], currentIndex: -1 }, }вместо использования
idатрибутов для переключателей просто дайте имvalueатрибутыссылаться на элементы формы через
document.forms.elementsопределить, какие радиокнопки выбраны с помощью
RadioNodeList.valueиспользовать
<output>элемент для отображения вещи .использовать класс для инкапсуляции индексов вместе с методами для получения элемента в зависимости от режима
class ThingList {
constructor(items) {
this.items = items;
this.randomUnused = [...items];
this.forwardIndex = 0;
this.reverseIndex = items.length - 1;
}
forwardItem() {
return this.items[this.forwardIndex++ % (this.items.length)];
}
randomItem() {
if (!this.randomUnused.length) {
this.randomUnused.push(...this.items);
}
const index = Math.floor(Math.random() * this.randomUnused.length)
return this.randomUnused.splice(index, 1);
}
reverseItem() {
if (this.reverseIndex < 0) {
this.reverseIndex = this.items.length - 1;
}
return this.items[this.reverseIndex--];
}
}
const options = {
video: new ThingList([ //VIDEO ARRAY
'video1',
'video2',
'video3',
'video4',
'video5',
]),
audio: new ThingList([ //AUDIO ARRAY
'audio1',
'audio2',
'audio3',
'audio4',
'audio5',
]),
photo: new ThingList([ //PHOTO ARRAY
'photo1',
'photo2',
'photo3',
'photo4',
'photo5',
]),
text: new ThingList([ //TEXT ARRAY
'text1',
'text2',
'text3',
'text4',
'text5',
])
}
const output = document.getElementsByTagName('output')[0];
//GENERATOR FUNCTION
function newThing() {
if (!(document.forms.thingSelection.type.value in options)) {
return false;
}
const list = options[document.forms.thingSelection.type.value];
const method = document.forms.thingSelection.mode.value + 'Item';
const item = list[method]();
output.innerHTML = item;
}
document.getElementsByTagName('button')[0].addEventListener('click', newThing)
.center {
text-align: center;
}
.right {
text-align: right;
}
<div class="center"><output></output></div>
<div class="center">
<button>New Thing</button>
</div>
<form name="thingSelection">
<label><input type="radio" name="mode" value="random" /> Random</label>
<br /><label><input type="radio" name="mode" value="forward" /> Old - New</label>
<br /><label><input type="radio" name="mode" value="reverse" /> New - Old</label>
<div class="right">
<label>Video <input type="radio" name="type" value="video" /></label><br />
<label>Audio <input type="radio" name="type" value="audio" /></label><br />
<label>Photo <input type="radio" name="type" value="photo" /></label><br />
<label>Text <input type="radio" name="type" value="text" /></label>
</div>
</form>