Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Паттерн плагина jQuery (https://javascript.ru/forum/jquery/35576-pattern-plagina-jquery.html)

prison47 15.02.2013 03:14

Паттерн плагина jQuery
 
Здравствуйте. Разъясните пожалуйста часть конструкции для плагина.
Почти все разобрал что за что отвечает но не понятно концовка. Не могли бы вы объяснить работу строк отмеченных условными комментариями.
;(function($) {

	var defaults = {

	};

	function Nupoll(element, options) {  
		var widget = this;

		widget.config = $.extend({}, defaults, options); 
		widget.element = element;

		this.init();

	}

	Nupoll.prototype.init = function() {

	};

	$.fn.pluginNew = function(options) { 
		new Nupoll(this.first(), options); // ??????????

		return this.first();  // ??????????

	};
} (jQuery) );

danik.js 15.02.2013 03:57

new Nupoll(this.first(), options);

Создается экземпляр Nupoll (вызывается конструктор Nupoll).

this.first() - первый элемент из коллекции.

return this.first() - возвращаем первый элемент, чтобы можно было продолжить цепочку вызовов: $(el).pluginNew().continueChain()

Если плагин должен обработать каждый элемент из коллекции, то обычно делают так:

$.fn.pluginNew = function(options) {
    return this.each(function(){
        // do stuff
    });
}

prison47 15.02.2013 04:22

То есть получается если у меня плагин должен подключатся не к одному к нескольким элементам я использую такой вариант паттерна:
;(function($) {

	var defaults = {

	};

	function Nupoll(element, options) {  
		var widget = this;

		widget.config = $.extend({}, defaults, options); 
		widget.element = element;

		this.init();

	}

	Nupoll.prototype.init = function() {


// код плагина


	};

$.fn.pluginNew = function(options) {
    return this.each(function(){
        // do stuff
    });

	};
} (jQuery) );

danik.js 15.02.2013 04:32

prison47, изучите сначала основы JavaScript, потом уже учитесь делать плагины для jQuery.

<script src="//code.jquery.com/jquery-latest.min.js"></script>
<script>
    (function($) {
     
    $.fn.pluginNew = function(options) {
        return this.each(function(){
            $(this).css('color', 'red');
        });
     
    };
    
    } (jQuery) );
</script>

<div>Bla bla</div>
<div>Тест</div>
<script>
    $('div').pluginNew();
</script>

prison47 15.02.2013 04:41

Основы я как раз таки изучаю и вот такие конструкции не могу понять, в первом случае код плагина мы пишем в Nupoll.prototype.init = function() {
где уже есть доступ к дом элементу. Во втором случае приведенном вами почему-то все отсекается, тот же конструктор. Если у вас есть ссылки где можно подробнее почитать на доходчивом языке, буду признателен :)

danik.js 15.02.2013 05:10

Если вы не заметили, в моем "плагине" не используются какие-то собственные методы, опции и прочее.
this.each(fn) проходит по всем элементам коллекции и вызывает для каждого элемента функцию fn, устанавливая в качестве контекста этот элемент. Делайте с этим элементом что хотите. Я например просто изменил css свойство. Вы можете создавать какие-то объекты к примеру.

Цитата:

Сообщение от prison47
код плагина...

Это все и есть - код плагина. Разве нет?

Цитата:

Сообщение от prison47
где можно подробнее почитать

Посмотрите исходники каких-нибудь плагинов jQuery

prison47 15.02.2013 05:19

Спасибо

prison47 16.02.2013 01:14

Подскажите пожалуйста. В плагине вешаю обработчики клика через on() на ново появляющиеся элементы. Подключаю плагин к нужному элементу. Все работает. Но если нужно подключить плагин на еще один элемент например для срабатывания с другими параметрами, то обработчики клика начинают дублироваться. Если подключить на три элемента, то утраиваются. Что я неправильно делаю? Или многократное подключение плагина вообще не должно быть? Тогда как сделать срабатывание на нескольких элементах с разными параметрами?

рони 16.02.2013 01:21

prison47,
обычно метку ставят если элемент обработан плагином то второй раз его ненадо -- если нужно по новой метку убирают навешивают по новой обработчики и ставят метку

prison47 16.02.2013 01:26

А подробней если можно? Не совсем понимаю

рони 16.02.2013 01:57

prison47,
$.fn.pluginNew = function(options) {
    return this.each(function(){
    if ($(this).data('on')) return;
    $(this).data('on', true)
    // do stuff
    });
}

prison47 16.02.2013 02:15

Странно но почему то не работает. Если я правильно понял нужно так?:
$.fn.pluginNew = function(options) {
    return this.each(function(){
    if ($(this).data('on')) return;
    $(this).data('on', true)
    foo.on(....);
    });
}

danik.js 16.02.2013 10:35

Странно, тот же код, но почему то работает...

<script src="//code.jquery.com/jquery-latest.min.js"></script>
<script>
    (function($) {
      
    $.fn.pluginNew = function(options) {
        return this.each(function(){
            if ($(this).data('on')) return;
            $(this).data('on', true)
            /*foo.on(....);*/alert('Че-нибудь делаем');
        });
    }
     
    } (jQuery) );
</script>
 
<button onclick="$(this).pluginNew()">Нажми меня полностью</button>

prison47 16.02.2013 14:53

Точнее я неправильно выразился :) Работать то работает но все равно дублирует

рони 16.02.2013 15:08

prison47,
код дубляжа можно?

danik.js 16.02.2013 15:10

prison47, но ведь алерт вылетает только при первом нажатии. Значит все ок :)

prison47 16.02.2013 15:27

$body.on('click.noteOverlay', '#general_overlay', function(){ 
var genThis = $(this).siblings('[data-case]');
removeOverCase(genThis);
		
		});

рони 16.02.2013 15:50

prison47,
лучше небольшое демо чем часть кода

danik.js 16.02.2013 17:19

prison47, это решение всех твоих проблем. Изучи как следует:
options = options || {};
		index   = options.index || 0;

		if (!selector || options.live === false) {
			that.unbind('click.fb-start').bind('click.fb-start', run);

		} else {
			D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
		}

		this.filter('[data-fancybox-start=1]').trigger('click');

		return this;

prison47 16.02.2013 19:25

Понял, спасибо буду разбираться что к чему!

prison47 17.02.2013 00:51

Вот как-то так.
<script src="//code.jquery.com/jquery-latest.min.js"></script>
<script>

;(function($) {

    $.fn.pluginName = function( settings ) {
    	var settings = $.extend( {
    	 }, settings);
     return this.each(function() {
     	var element = $(this);
   $('.foo').click(function(){

    	     	alert($(this));
    });

}); 
};

}) (jQuery) ;
</script>
<style>
.foo{
width:100px;
height:100px;
background: #000;

}
</style>
<button onclick="$(this).pluginName()">Нажми </button>
<button onclick="$(this).pluginName()">Нажми 2</button>
<div class='foo'></div>

рони 17.02.2013 01:11

Цитата:

Сообщение от prison47
вживую клацать

http://javascript.ru/formatting

рони 17.02.2013 01:30

prison47,
<!DOCTYPE HTML>

<html>

<head>
  <title></title>
<meta charset="utf-8" />
<style type="text/css">
#general_overlay{
  background-color: #FF0099;
   width: 300px;
   height: 50px;
}
</style>
</head>

<body>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>

(function($) {

    $.fn.pluginName = function( settings ) {

    	var settings = $.extend( {

    	 }, settings);

     return this.each(function() {

     	var element = $(this);
    if($('#general_overlay').length)  {alert('No pasarán'); return} ;
	if(!$('#general_overlay').length){

		$("<div id='general_overlay'></div>").appendTo($('body'));
	};

	var genOverlay = $('#general_overlay');

    element.click( function(){

    	genOverlay.show();

    });

    $('body').on('click.overPop', '#general_overlay', function(){

    	$(this).hide();

    	       //	console.log($(this));
    });

});
};

}) (jQuery) ;
</script>

<button onclick="$(this).pluginName()">Нажми </button>

<button onclick="$(this).pluginName()">Нажми 2</button>

</body>

</html>

prison47 17.02.2013 01:40

Спасибо за оформление, вот получается если произвожу клик на диве overlay он удаляется а в консоле this проходит два раза.

А в этом коде не могу разобраться, я незнаю значение переменных , например D
options = options || {};
		index   = options.index || 0;
		if (!selector || options.live === false) {
			that.unbind('click.fb-start').bind('click.fb-start', run);
		} else {
			D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
		}
		this.filter('[data-fancybox-start=1]').trigger('click');
		return this;

рони 17.02.2013 01:54

Цитата:

Сообщение от prison47
this проходит два раза.

сейчас пост 23 это не так

рони 17.02.2013 01:58

prison47,
лучше скажите как вы хотите чтоб это работало

prison47 17.02.2013 02:06

Понимаете у меня "плагин" он вешается например на кнопку. При клике на кнопку в конец бади добавляется див оверлей с display:none. Потом добавляется еще один див с определенной информацией он позиционирован в угол браузера. Кликаем на этот див с информацией он позиционируется в центр экрана а див оверелей появляется dispaly:block и затемняет экран. По принципе как в лайт боксах. Потом кликаем один раз на див оверлей он скрывается а второй див удаляется. Так вот клик на скрытие оверлея я вешаю через on(). Если вешать плагин на один элемент на странице (кнопку) то все ок, если на два то обработчик on() срабатывает 2 раза!

Точнее в конец бади оверлей добавляется сразу. А див с информацией при нажатии

рони 17.02.2013 02:15

prison47, извините но пока из ваших попыток в который раз обьяснить что вы хотите , я в который раз ничего непонял, может вам не плагин нужен?

рони 17.02.2013 02:24

Цитата:

Сообщение от prison47
Потом добавляется еще один див

Цитата:

Сообщение от prison47
А див с информацией при нажатии

откуда берётся ваш таинственный див и куда исчезает ? и ненадо уточнять где что позиционировано , пока это только отвлекает, алгоритма невидно , что зачем и откуда должно происходить а что нет.

рони 17.02.2013 02:29

prison47,
или сделали так
if(!$('#general_overlay').length){

		$("<div id='general_overlay'></div>").appendTo($('body'));

      $('body').on('click.overPop', '#general_overlay', function(){

    	$(this).hide();

    	       console.log($(this));
    });



    };

prison47 17.02.2013 02:45

Вот отбросил все что отвлекает.
;(function($) {

    $.fn.homerTwice = function( settings ) {

    	var settings = $.extend( {

    	 }, settings);

     return this.each(function() {

     	var element = $(this);

		if(!$('#general_overlay').length){ // проверяем если данного дива нет на странице то добавляем его, в стилях дисплей none

			$("<div id='general_overlay'></div>").appendTo($('body'));
		};
		
		var genOverlay = $('#general_overlay');

    element.click( function(){

    	genOverlay.show(); //  кликаем по кнопке, наш див #general_overlay появляется

    });


    $('body').on('click.overPop', '#general_overlay', function(){ // кликаем на диве #general_overlay он исчезает
    	$(this).hide(); 

    	     	console.log($(this)); // если плагин вешается например на две кнопки ( $('#btn_1').homerTwice(); $('#btn_2').homerTwice(); ), то происходит двойное срабатывание нажатия
    });

     }); // this each close

	};

}) (jQuery) ;

рони 17.02.2013 02:49

prison47,
$('body').on тогда надо ставить в конец 15 строки

prison47 17.02.2013 03:05

Да действительность оказалось настолько очевидным :-?
СПАСИБО ПРЕОГРОМНОЕ!!!

prison47 17.02.2013 05:58

А как быть если мы вешаем обработчик на изменения окна браузера?
$(window).off('resize.noteResize').on('resize.noteResize', function(){ 
       console.log($(this));
});

В консоль this записывается два раза (при условие что плагин подключен дважды). Если использовать без .off('resize.noteResize') тогда this записывается 4 раза. Пробовал через .data() решить проблему. Тоесть повесить проверку если .data() у windows не существует то повесить обработчик и записать для windows .data(). Но все равно дублирует. В чем я сделал ошибку?
if(! $.hasData(window) ){
$(window).data('foo');
$(window).on('resize.noteResize', function(){ 

console.log($(this));
});
};


А вот если подключить плагин 3 раза или 1 раз, this записывается все равно 2 раза. Я так понял это все таки не двойное навешивание обработчика.

рони 17.02.2013 09:50

Цитата:

Сообщение от prison47
вешаем обработчик на изменения окна браузера

надо ставить таймер на 100-500ms;
resize =>
1.обнулили таймер
2. поставили таймер
3. таймер сработал сделал всё что нужно.
resize это серия event -- надо/желательно дождаться последнего.


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