Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Что не так с плагином (https://javascript.ru/forum/dom-window/80072-chto-ne-tak-s-plaginom.html)

Янковиц 23.04.2020 17:09

Что не так с плагином
 
Учусь писать свои плагины для Jquery. В частности слайдер. Вот что пока есть:
(function($){
		// настройки со значением по умолчанию
		var defaults = { speed: 500 };

		// наши будущие публичные методы
		var methods = {
			xDown: null,                                                        
			yDown: null,
			// инициализация плагина
			init: function(options, args ) {
				// настройки, будут индивидуальными при каждом запуске
				var options = $.extend({}, defaults, options);				
				// инициализируем лишь единожды
				if (!this.data('sSlider')) {
				
					this.data('sSlider', options);
					
					// добавим событий
					var slider = this;
					$(document)
						.on('click', '*[data-direction]', function(e){
							e.preventDefault();
							methods.move( this, $(this).data('direction'), options );
						});
				}
				return this;
			},
			// контейнер со слайдами
			move: function( slider, direction, options ) {
				var slider = $(slider),
					block  = slider.find('*[data-element="box"]'),
					items  = block.children(),
					first  = items.eq(0);
					last   = items.eq(-1);
					
				console.log( methods.init );
				
				if( first.is( ':animated' ) ) {
					return;
				}
				items.stop(true, true);
				
				if ( direction === 'prev' ) {	
					first.animate({
						marginLeft: 0 - first.outerWidth()
					}, options.speed, function() {
						first.css('margin-left', 0)
							.appendTo( first.parent() );
					});
				} else {
					last.prependTo(last.parent())
						.css('margin-left','-'+last.outerWidth()+'px')
							.animate({marginLeft:0}, options.speed);
				}
			},
		};

		$.fn.sSlider = function(method){
			// немного магии
			console.log(this);
			if ( methods[method] ) {
				// если запрашиваемый метод существует, мы его вызываем
				// все параметры, кроме имени метода прийдут в метод
				// this так же перекочует в метод
				return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
			} else if ( typeof method === 'object' || ! method ) {
				// если первым параметром идет объект, либо совсем пусто
				// выполняем метод init
				console.log( this );
				return methods.init.apply( this, arguments );
			} else {
				// если ничего не получилось
				$.error('Method "' + method + '" not found');
			}
		};
	})(jQuery);
	$('.glider').sSlider();


Застопорился в методе move. Я пытаюсь обратиться к родительскому блоку .glider, который заявлен в $('.glider').sSlider(); Но в методе move: function( slider, direction, options ), параметре slider какая-то дичь. Я не могу получить к нему доступ, чтобы обратиться к дочерним. Надеюсь на любую помощь.

рони 23.04.2020 17:49

Янковиц,
строка 23
methods.move( this slider, $(this).data('direction'), options );

Янковиц 23.04.2020 18:16

Тот же самый результат. В строках 30 и 31, результат null
(function($){
	// настройки со значением по умолчанию
	var defaults = { speed: 500 };

	// наши будущие публичные методы
	var methods = {
		xDown: null,                                                        
		yDown: null,
		// инициализация плагина
		init: function(options, args ) {
			// настройки, будут индивидуальными при каждом запуске
			var options = $.extend({}, defaults, options);				
			// инициализируем лишь единожды
			if (!this.data('sSlider')) {
			
				this.data('sSlider', options);
				
				// добавим событий
				var slider = this;
				$(document)
					.on('click', '*[data-direction]', function(e){
						e.preventDefault();
						methods.move( slider, $(this).data('direction'), options );
					});
			}
			return this;
		},
		// двигаем слайдер
		move: function( slider, direction, options ) {
			console.log( $(slider).width() );
			console.log( slider.width() );
			var block  = slider.find('*[data-element="box"]'),
				items  = block.children(),
				first  = items.eq(0);
				last   = items.eq(-1);
				
			
			if( first.is( ':animated' ) ) {
				return;
			}
			items.stop(true, true);
			
			if ( direction === 'prev' ) {	
				first.animate({
					marginLeft: 0 - first.outerWidth()
				}, options.speed, function() {
					first.css('margin-left', 0)
						.appendTo( first.parent() );
				});
			} else {
				last.prependTo(last.parent())
					.css('margin-left','-'+last.outerWidth()+'px')
						.animate({marginLeft:0}, options.speed);
			}
		},
	};

	$.fn.sSlider = function(method){
		if ( methods[method] ) {
			// если запрашиваемый метод существует, мы его вызываем
			// все параметры, кроме имени метода прийдут в метод
			// this так же перекочует в метод
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			// если первым параметром идет объект, либо совсем пусто
			// выполняем метод init
			return methods.init.apply( this, arguments );
		} else {
			// если ничего не получилось
			$.error('Method "' + method + '" not found');
		}
	};
})(jQuery);
$('.glider').sSlider();

рони 23.04.2020 18:33

Янковиц,
вы строку 19 проверьте, что там у вас

Янковиц 23.04.2020 18:36

n.fn.init [prevObject: n.fn.init(1), context: document, selector: ".glider"]
length: 0
prevObject: n.fn.init [document, context: document]
context: documentDOMStringList, origin: "file://", protocol: "file:", host: "", …}
implementation: DOMImplementation {}
compatMode: "CSS1Compat"
characterSet: "UTF-8"
charset: "UTF-8"
inputEncoding: "UTF-8"
contentType: "text/html"
doctype: html
documentElement: html
xmlEncoding: null
xmlVersion: null
xmlStandalone: false
domain: ""
referrer: ""
cookie: ""
lastModified: "04/23/2020 18:44:47"
readyState: "complete"
title: "CodePen - Just another CSS UI"
dir: ""
body: body
head: head
images: HTMLCollection(5) [img, img, img, img, img]
embeds: HTMLCollection []
plugins: HTMLCollection []
links: HTMLCollection(13) [a, a, a, a, a, a, a, a, a, a, a, a, a]
forms: HTMLCollection []
scripts: HTMLCollection(2) [script, script]
currentScript: null
defaultView: Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
designMode: "off"
onreadystatechange: null
anchors: HTMLCollection []
applets: HTMLCollection []
fgColor: ""
linkColor: ""
vlinkColor: ""
alinkColor: ""
bgColor: ""
all: HTMLAllCollection(131) [html, head, meta, title, script, link#daria-css, script, body, div.glider.container, div.glider__post.padt, div.glider__post_count, div.glider__share, div.slider__share_item.facebook, div.slider__share_item.twitter, div.slider__share_item.pinterest, div.slider__share_item.vk, img, div.glider__post_item, img, div.glider__post_data, h2, a, p, div.glider__arrow, span.glider__arrow_prev, svg, path, span.glider__arrow_next, svg, path, div.glider__box.padt, div.glider__box_item, div.block_title, h2.padr, img, span.block_title_all.padl, a, svg, path, span, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__box_item, div.block_title, h2.padr, img, span.block_title_all.padl, a, svg, path, span, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__item, div.post__data, span.post__data_item, i.date, span.post__data_item, i.views, h2, a, div.glider__box_item, div.block_title, h2.padr, …]
scrollingElement: html
onpointerlockchange: null
onpointerlockerror: null
hidden: false
visibilityState: "visible"
wasDiscarded: false
webkitVisibilityState: "visible"
webkitHidden: false
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onfreeze: null
onresume: null
onsearch: null
onsecuritypolicyviolation: null
onvisibilitychange: null
fonts: FontFaceSet {onloading: null, onloadingdone: null, onloadingerror: null, ready: Promise, status: "loaded", …}
oncopy: null
oncut: null
onpaste: null
activeElement: body
styleSheets: StyleSheetList {0: CSSStyleSheet, 1: CSSStyleSheet, length: 2}
pointerLockElement: null
fullscreenElement: null
adoptedStyleSheets: []
onabort: null
onblur: null
oncancel: null
oncanplay: null
oncanplaythrough: null
onchange: null
onclick: null
onclose: null
oncontextmenu: null
oncuechange: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
ondurationchange: null
onemptied: null
onended: null
onerror: null
onfocus: null
onformdata: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onloadeddata: null
onloadedmetadata: null
onloadstart: null
onmousedown: null
onmouseenter: null
onmouseleave: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onoperadetachedviewchange: null
onoperadetachedviewcontrol: null
onpause: null
onplay: null
onplaying: null
onprogress: null
onratechange: null
onreset: null
onresize: null
onscroll: null
onseeked: null
onseeking: null
onselect: null
onstalled: null
onsubmit: null
onsuspend: null
ontimeupdate: null
ontoggle: null
onvolumechange: null
onwaiting: null
onwheel: null
onauxclick: null
ongotpointercapture: null
onlostpointercapture: null
onpointerdown: null
onpointermove: null
onpointerup: null
onpointercancel: null
onpointerover: null
onpointerout: null
onpointerenter: null
onpointerleave: null
onselectstart: null
onselectionchange: null
onanimationend: null
onanimationiteration: null
onanimationstart: null
ontransitionend: null
children: HTMLCollection [html]
firstElementChild: html
lastElementChild: html
childElementCount: 1
fullscreenEnabled: true
fullscreen: false
onfullscreenchange: null
onfullscreenerror: null
webkitIsFullScreen: false
webkitCurrentFullScreenElement: null
webkitFullscreenEnabled: true
webkitFullscreenElement: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
rootElement: null
featurePolicy: FeaturePolicy {}
onpointerrawupdate: null
pictureInPictureElement: null
pictureInPictureEnabled: true
nodeType: 9
nodeName: "#document"
isConnected: true
ownerDocument: null
parentNode: null
parentElement: null
childNodes: NodeList(2) [html, html]
firstChild: html
lastChild: html
previousSibling: null
nextSibling: null
nodeValue: null
textContent: null

рони 23.04.2020 18:36

Янковиц,
и лучше не загадка из куска кода, а минимальный макет, пусть и не рабочий.

Янковиц 23.04.2020 18:37

То есть, как я понимаю, всё null
Это 19 строка

рони 23.04.2020 18:42

Янковиц,
попробуйте так
$(function() {
$('.glider').sSlider();

});

Янковиц 23.04.2020 18:48

Заработало!

Янковиц 23.04.2020 18:48

Интересно, в чём причина?

рони 23.04.2020 18:55

Цитата:

Сообщение от Янковиц
Интересно, в чём причина?

на момент установки плагина
на странице ещё не было элемента, jquery продолжает работать, кто - то считает что это минус jquery, и всё должно было рухнуть , кто - то что это плюс что ничего не случилось. :)

Янковиц 27.04.2020 16:57

Небольшое дополнение. Добавил в плагин callback функции moveStart и moveEnd.
(function($){
	// настройки со значением по умолчанию
	var defaults = {
		speed: 500,
		moveStart: function() {},
		moveEnd: function() {},
	};

	// наши будущие публичные методы
	var methods = {
		xDown: null,                                                        
		yDown: null,
		// инициализация плагина
		init: function( options, args ) {
			// настройки, будут индивидуальными при каждом запуске
			var options = $.extend({}, defaults, options);				
			// инициализируем лишь единожды
			if (!this.data('sSlider')) {
			
				this.data('sSlider', options);
				
				// добавим событий
				var slider      = this,
					child_class = slider.find('*[data-element="box"]').children().eq(0).attr('class');
					
				$(document)
					.on('mousedown touchend', '*[data-direction]', function(e){
						methods.move( slider, $(this).data('direction'), options );
					})
			}
			return this;
		},
		// двигаем слайдер
		move: function( slider, direction, options ) {
			var block  = slider.find('*[data-element="box"]'),
				items  = block.children(),
				first  = items.eq(0),
				last   = items.eq(-1);
			
			if( first.is( ':animated' ) ) {
				return;
			}
			items.stop(true, true);
			
			options.moveStart.call( slider, direction );
			
			if ( direction === 'prev' ) {	
				first.animate({
					marginLeft: 0 - first.outerWidth()
				}, options.speed, function() {
					first.css('margin-left', 0)
						.appendTo( first.parent() );
				});
			} else {
				last.prependTo(last.parent())
					.css('margin-left','-'+last.outerWidth()+'px')
						.animate({marginLeft:0}, options.speed);
			}
			
			setTimeout(function () {
				options.moveEnd.call( slider, direction );
			}, options.speed);
		},
	};

	$.fn.sSlider = function(method){
		if ( methods[method] ) {
			// если запрашиваемый метод существует, мы его вызываем
			// все параметры, кроме имени метода прийдут в метод
			// this так же перекочует в метод
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			// если первым параметром идет объект, либо совсем пусто
			// выполняем метод init
			return methods.init.apply( this, arguments );
		} else {
			// если ничего не получилось
			$.error('Method "' + method + '" not found');
		}
	};
})(jQuery);

Затем вызываю слайдер:

$(function() {
		$('.glider').sSlider({
			moveStart: function( slider, direction ) {
				console.log( slider );
				console.log( direction );
			},
		});
	});


При этом console.log из строки 04 показывает "prev" или "next", а в строке 05 "undefined". Хотя сначала я ожидал увидеть DOM элемент $('.glider'), а затем направление direction. Что я делаю не так?

рони 27.04.2020 17:22

Янковиц,
$(function() {
		$('.glider').sSlider({
			moveStart: function(direction ) {
				console.log( this );
				console.log( direction );
			},
		});
	});

рони 27.04.2020 17:25

Янковиц,
или так
options.moveStart.call( null  , slider, direction );

или так
options.moveStart.call( slider , slider, direction );

для moveStart: function( slider, direction )

рони 27.04.2020 17:29

Янковиц,
Метод call
func.call(context, arg1, arg2, ...) сначала идёт контекст (this), а потом уже аргументы.

Янковиц 27.04.2020 17:48

Спасибо большое

Янковиц 28.04.2020 17:27

Стало необходимо запускать процессы более 1 раза на странице. Я понимаю, что нужно использовать что-то вроде этого:
return this.each(function() {
                var $this = $(this);
            });

Но совершенно не знаю, в какой момент

рони 28.04.2020 17:32

Янковиц,
вместо строк 18 - 31

Янковиц 28.04.2020 17:37

На строку 20 ругается: index.html:20 Uncaught TypeError: this.data is not a function

рони 28.04.2020 17:43

Цитата:

Сообщение от Янковиц
this.data is not a function

Цитата:

Сообщение от Янковиц
var $this = $(this);

:-?

рони 28.04.2020 18:09

Янковиц,
убрал лишнее ...
// инициализация плагина
init: function f(options, args) {
    var options = $.extend({}, defaults, options);
    return this.each(function() {
        var $this = $(this);
        if (!$this.data("sSlider")) {
            $this.data("sSlider", options);
            $("[data-direction]", $this).on("mousedown touchend", function(e) {
                methods.move($this, $(this).data("direction"), options);
            });
        }
    });
},

Янковиц 28.04.2020 18:29

Подскажите, как можно получить селектор .glider объявленный в
$('.glider').sSlider();

?

рони 28.04.2020 18:48

Янковиц,
сейчас только указав в options.

рони 28.04.2020 18:52

Янковиц,
может сделать без jquery?


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