Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Объект для видео (https://javascript.ru/forum/misc/53831-obekt-dlya-video.html)

arcmag 20.02.2015 12:36

Объект для видео
 
Всем привет. Сейчас изучаю объекты и вот решил сделать небольшой простенький видео плеер при помощи конструктора объектов.
Вот код
var all_video = [];
function video_designer(){
    this.videoBlock; 
    this.video;
    this.PlayPause;
    this.StopV;
    this.fPlay = function(){this.video.play();}
}
window.onload = function(){
    mas_video = document.getElementsByClassName("videoBlock");
    for(var i=0; i<mas_video.length; i++){
        var newObj = new video_designer;
        newObj.videoBlock = mas_video[i]; // получаем блок обертку в которой находится видео
        newObj.video = mas_video[i].childNodes[3]; // получаем видео
        newObj.PlayPause = mas_video[i].childNodes[5].childNodes[1]; // получаем кнопку при нажатии которой запускается видео
        newObj.StopV = mas_video[i].childNodes[5].childNodes[3]; // получаем кнопку при нажатии которой выключается видео 
        newObj.PlayPause.addEventListener("click",newObj.fPlay); // добавляем событие к кнопке что бы при нажатии видео начинало проигрываться
        all_video.push(newObj); // записываем текущий объект видео в массив и создаем новый объект видео если они еще имеются на странице
    }
}

Проблема возникает при вызове метода fPlay, не могу понять в чем дело все вроде бы правильно написано, объекты для меня тема новая, поэтому много чего пока что не знаю и не понимаю.
Пожалуйста подскажите как решить проблему?
Желательно дайте понятный пример решения, мне на примерах как то понятнее понимается :)

tsigel 20.02.2015 14:07

arcmag,
Во первых имена констркторов объектов принято писать с большой буквы.
Во вторых у вас в обработчике клика не верный контекст.
В третьих не надо объявлять методы объекта в конструкторе, это приводит к перерасходу памяти. Методы надо объявлять в прототипе.
/**
 * @class VideoManager
 * @param {HTMLVideoElement} video
 * @param {HTMLElement} playPause
 * @constructor
 */
function VideoManager(video, playPause){
    /**
     * Видео элемент
     * @type {HTMLVideoElement}
     */
    this.video = video;
    
    this._setHandlers(playPause);
}

/**
 * Назначаем обработчик
 * @param {HTMLElement} playPause
 * @private
 */
VideoManager.prototype._setHandlers = function (playPause) {
    playPause.addEventListener("click", this.play.bind(this), false);
};

VideoManager.prototype.play = function(){
    this.video.play();
};

arcmag 20.02.2015 14:35

То есть надо написать как то так?

var all_video = [];
function Video_designer(){
    this.videoBlock; 
    this.video;
    this.PlayPause;
    this.StopV;
}
Video_designer.prototype.fPlay = function(){
	this.video.play();
};
Video_designer.prototype.fStop = function(){
	this.video.stop();
};
window.onload = function(){
    mas_video = document.getElementsByClassName("videoBlock");
    for(var i=0; i<mas_video.length; i++){
        var newObj = new Video_designer;
        newObj.videoBlock = mas_video[i]; // получаем блок обертку в которой находится видео
        newObj.video = mas_video[i].childNodes[3]; // получаем видео
        newObj.PlayPause = mas_video[i].childNodes[5].childNodes[1]; // получаем кнопку при нажатии которой запускается видео
        newObj.StopV = mas_video[i].childNodes[5].childNodes[3]; // получаем кнопку при нажатии которой выключается видео 
        newObj.PlayPause.addEventListener("click",newObj.fPlay); // добавляем событие к кнопке что бы при нажатии видео начинало проигрываться
        all_video.push(newObj); // записываем текущий объект видео в массив и создаем новый объект видео если они еще имеются на странице
    }
}


Все равно не работает, в консоли появляется такая ошибка
Uncaught TypeError: Cannot read property 'play' of undefined
То есть как мне кажется проблема в том что метод почему то не видит this.video объекта для которого я вызываю play().
Хотя может я и ошибаюсь, но почему так не могу понять.

danik.js 20.02.2015 14:39

Цитата:

Сообщение от arcmag
childNodes[3]

Че за магические числа?
Цитата:

Сообщение от arcmag
не видит this.video

Может потому что он равен undefined?, так как childNodes[3] нету?

arcmag 20.02.2015 14:46

Нет это у меня в коде есть разметка

<div class="videoBlock">
<div class="titleVideo">Заголовок видео</div>
<video id="video001">
<source src="video/drawing.mp4" type="video/mp4" />
<source src="video/drawing.ogv" type="video/ogg" />
<source src="video/drawing.webm" type="video/webm" />
</video>
<div class="toolsControll">
<div class="button cont1"></div>
<div class="button cont3"></div>
<div class="wrapperProgress">
<div class="wrapperLoading"></div>
<div class="wrapperPosition"></div>
</div>
<div class="infoTime">00:00/00:00</div>
<div class="volume"></div>
<div class="resize"></div>
<div class="actionInfo"></div>
</div>

в ней находятся нужные элементы, тут все правильно я все проверял

tsigel 20.02.2015 14:53

arcmag,

newObj.PlayPause.addEventListener("click",newObj.f Play.bind(newObj), false)


Говорю же, контекст не тот.

tsigel 20.02.2015 14:56

arcmag,
Вообще тот код что в цикле - просто ужас. По хорошему надо давать в конструктор объекта те данные с которыми он будет работать и не надо напрямую обращаться к ключам объекта. Если уж следовать вашей логике, то надо в конструктор класть видео блок, в видео менеджере сделать метод инициализации, чтобы он сам искал нужные элементы, видео и вешал обработчики, как в примере который я вам писал.

danik.js 20.02.2015 15:42

Цитата:

Сообщение от tsigel
вешал обработчики, как в примере который я вам писал

Вот именно. Я вообще не заметил навешивание обработчиков в цикле, так как там его не должно быть вообще. Думал fPlay вызываешь напрямую.

arcmag 20.02.2015 16:14

Окончательно запутавшись решил получше изучить ваш пример и как то переделать его под себя.
Пришлось покопаться в сети и почитать о bind() после чего поматерившись методом тыка удалось таки запустить свое чудовище.

var all_video = [];
function Video_designer(myVideoBlock){
	this.videoBlock = myVideoBlock; 
	this.video = this.videoBlock.childNodes[3];
	this.PlayPause = this.videoBlock.childNodes[5].childNodes[1];
	this.StopV = this.videoBlock.childNodes[5].childNodes[3];
	
	this.fPlay = function(){this.video.play();}
	this.fStop = function(){this.video.pause();}
}


window.onload = function(){
	mas_video = document.getElementsByClassName("videoBlock");
	for(var i=0; i<mas_video.length; i++){
		var newObj = new Video_designer(mas_video[i]);
		console.log(newObj.videoBlock+" 1");
newObj.PlayPause.addEventListener("click",newObj.fPlay.bind(newObj));
newObj.StopV.addEventListener("click",newObj.fStop.bind(newObj));
		all_video.push(newObj);
	}
}


Вроде бы работает :) я аж почувствовал как захрустел мой мозг от напряжения когда я это переваривал.

Товарищу tsigel большое спасибо, без вас бы я не справился.

tsigel 20.02.2015 16:22

arcmag,
В js принято называть переменные в camel case, не надо подчеркиваний.

var allVideo = [];

var VideoDesigner = function VideoDesigner(myVideoBlock){
	this.video = myVideoBlock.querySelector("video");
	this.playPause = myVideoBlock.childNodes[5].childNodes[1];
	this.stopV = myVideoBlock.childNodes[5].childNodes[3];
    this._setHandlers();
};

VideoDesigner.prototype._setHandlers = function () {
    this.playPause.addEventListener("click", this.fPlay.bind(this), false);
    this.stopV.addEventListener("click", this.fStop.bind(this), false);
};

VideoDesigner.prototype.fPlay = function(){
    this.video.play();
};

VideoDesigner.prototype.fStop = function(){
    this.video.pause();
};

window.onload = function(){
   Array.prototype.forEach.call(document.getElementsByClassName("videoBlock"), function (myVideoBlock) {
       allVideo.push(new VideoDesigner(myVideoBlock));
   });
};


Постарайтесь убрать из кода цифры, понимание которых затрудняет код. Дайте кнопке плейПауза особый класс и тогда "myVideoBlock.childNodes[5].childNodes[1]" превратится в "myVideoBlock.querySelector(".особый класс")". Ото сильно упростит понимание вашего кода и убережот от ошибок по невнимательности.

Подчеркивание перед методом означает что это приватный метод, и пользоваться им может только его владелец (но это условности)

Примерно так это должно выглядеть. Симпотичнее, верно? ;)


Часовой пояс GMT +3, время: 12:14.