Отображение мультимедиа с помощью HTML и JavaScript

Oct 02 2020

У меня есть личный веб-сайт, который я использую, чтобы делиться видео и изображениями с друзьями. Ниже представлен медиа-генератор, использующий 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>&nbsp;Random
    <br/><label><input type="radio" name="modes" id="mode2"/></label>&nbsp;Old&nbsp;-&nbsp;New
    <br/><label><input type="radio" name="modes" id="mode3"/></label>&nbsp;New&nbsp;-&nbsp;Old
  </form>

  <div align="right">
    <form id="categories" align="right">
      Video<label>&nbsp;<input type="radio" name="thing" id="videoCheck"/></label><br/>
      Audio<label>&nbsp;<input type="radio" name="thing" id="audioCheck"/></label><br/>
      Photo<label>&nbsp;<input type="radio" name="thing" id="photoCheck"/></label><br/>
      Text<label>&nbsp;<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 элементов, и со временем будет добавляться больше.

Ответы

2 SᴀᴍOnᴇᴌᴀ Oct 08 2020 at 03:22

Общий отзыв

Кажется, что этот код работает приемлемо, хотя семантика «старое - новое» кажется обратной.

Первый пункт в примечаниях гласит:

  • Я упорядочиваю массивы 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по нескольким причинам:

  1. Логика может быть отделена от разметки - если над проектом работали несколько товарищей по команде, один мог работать над JavaScript, а другой мог работать над HTML независимо.
  2. Такие обработчики могут загрязнять глобальное пространство имен, что может привести к странному поведению .

Выравнивание дочерних элементов

У <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" />&nbsp;Random</label>
  <br /><label><input type="radio" name="mode" value="forward" />&nbsp;Old&nbsp;-&nbsp;New</label>
  <br /><label><input type="radio" name="mode" value="reverse" />&nbsp;New&nbsp;-&nbsp;Old</label>
  <div class="right">
    <label>Video&nbsp;<input type="radio" name="type" value="video" /></label><br />
    <label>Audio&nbsp;<input type="radio" name="type" value="audio" /></label><br />
    <label>Photo&nbsp;<input type="radio" name="type" value="photo" /></label><br />
    <label>Text&nbsp;<input type="radio" name="type" value="text" /></label>
  </div>
</form>