@flammerman
Web Developer / И фронт и сервер

Как сделать реинициализацию плагина?

(function($){
	$.fn.appProductImages = function(options) {
	  	
		var settings = $.extend({

	    }, options);
		
		var container = this;
		var button = $('<button/>', {class: 'btn btn-default api-button-add', type: 'button'});
		container.append(button);
		
		var init = function() {
			container.find('.api-item').each(function(){
				var preview = $(this).find('.api-item-preview');
				$(this).find('input[type="file"]').appInputImage({
					container : preview	
				});
			})	
		}

		// Function add new item
		var item = function(){
			var itemsLength = container.find('.api-item').length;
			var item = $('<div/>', {class: 'api-item'});
			var inputFile = $('<input/>', {class: 'form-control app-input__file', type: 'file', name: 'images['+itemsLength+'][image]'});
			var inputText = $('<input/>', {class: 'form-control app-input__text', type: 'text', name: 'images['+itemsLength+'][title]'});
			var preview = $('<div/>', {class: 'api-item-preview'});
			item.append(inputFile).append(inputText).append(preview); 
			return item;
		}	

		item();
		init();

	};

})(jQuery);


$(function(){
	        $('#product-images').appProductImages();
	})


Плагин цепляется к контейнеру с данным ИД. Наворачивает нужный функционал. И в общем то все работает пока плагин не создаст дополнительный элемент внутри контейнера. В такой ситуации хотелось бы как-то его перепривзять еще раз. Чтобы видел контейнер уже с дополнительными элементами или при удалении элементов, также реинициализировался. По сути он добавляет в контейнер пару инпут полей, кнопку "добавить еще пару" + появится доп. функционал, например удалить пару полей. И на каждое поле привязывает еще доп. плагин, который по "onchange" добавляет превью картинки

(function($){
	
	var methods = {
		init: function(options){ 
		    
		    var obj = this;
			obj.addItem()
			return this;

		},
		addItem: function(){ 
			var itemsLength = this.find('.api-item').length;
			var item = $('<div/>', {class: 'api-item'});
			var inputFile = $('<input/>', {class: 'form-control app-input__file', type: 'file', name: 'images['+itemsLength+'][image]'});
			var inputText = $('<input/>', {class: 'form-control app-input__text', type: 'text', name: 'images['+itemsLength+'][title]'});
			var preview = $('<div/>', {class: 'api-item-preview'});
			item.append(inputFile).append(inputText).append(preview);
			this.append(item);
			alert('add');
		},
		getItem: function(num){ 
			obj.find('.api-item').eq(num);
		},
		deleteItem: function(num){ 
			//obj.appInputImage().getItem(num).remove();
		},
	};

	$.fn.appProductImages = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Метод ' +  method + ' в jQuery.appProductImages не существует');
		}   
	};

})(jQuery);


Пробую еще как-то так, работать с методами. Но утт вообще не понятно какой в них смысл., методы Add не доступны внутри init. То есть где писать рабочий код плагина не понятно. и как эти методы использовать при инициализации
  • Вопрос задан
  • 92 просмотра
Пригласить эксперта
Ответы на вопрос 1
BRAGA96
@BRAGA96
Здесь я постарался описать основные моменты, если что-то забыл, то спрашивайте.
Сам код плагина:
(function($, window, undefined) {
	'use strict';

	/* Общие настройки плагина */
	var plugin = {
		name: 'plugin',
		version: '1.0.0',
		data: {
			setting: 'setting',
			general: 'general'
		}
	};

	/* Настройки инициализации по умолчанию */
	var defaults = {
		color: 'red',
		background: 'black',
		padding: '10px'
	};

	var methods = {};

	methods.init = function($this, options, common) {
		/**
		 * Записываем настройки плагина в $.data элемента,
		 * чтобы потом в любой момент достать настройки 
		**/
		var setting = function() {
			var params = $.extend(true, {}, defaults, options);
			$this.data(plugin.data.setting, params);
			return params;
		}();

		/**
		 * Создаем общий объект свойств, которыми будем пользоватся
		 * в методе init. Общий объект заменяет глобальные переменные в методе init,
		 * так удобней и чище, все в одном месте. Не нужно на этом уровне создавать
		 * var flag = true; и использовать его по всему коду init и в функциях замыкания,
		 * лучше объект
		**/
		var general = function() {
			var params = $.extend(true, {}, {
				time: Date.now(),
				context: $this.get(0)
			}, common);
			$this.data(plugin.data.general, params);
			return params;
		}();

		/* Начало инициализации плагина */
		$this.css({
			color: setting.color,
			background: setting.background
		});

		setPadding();
		/* Конец инициализации плагина */

		/* Функции в замыкании для видимости: $this, setting, general */
		function setPadding() {
			general.context.style.padding = setting.padding;
		}
	};

	/**
	 * Метод SET. Логика его в том, чтобы взять текущие настройки
	 * плагина из $.data элемента, присоеденить свои
	 * и переинициализировать плагин уже с новыми настройками
	**/
	methods.set = function(key, value) {
		var setting = $(this).data(plugin.data.setting);
		switch (typeof key) {
			case 'string':
				if (key.includes('.')) {
					nestedObjectPath(setting, key, value);
				} else {
					setting[key] = value;
				}
				break;
			case 'object':
				setting = $.extend(true, {}, setting, key);
				break;
		}
		return methods.init($(this), setting, {
			type: 'update',
			method: 'set'
		});
	};

	methods.get = function(category, key) {
		var section = $(this).data(category);
		if (key) {
			if (key.includes('.')) {
				return nestedObjectPath(section, key);
			} else {
				return Object.getOwnPropertyDescriptor(section, key).value;
			}
		}
		return section;
	};

	methods.destroy = function() {
		$(this).removeData(plugin.data.setting).fadeOut(200, function() {
			$(this).empty().show();
		});
	};

	methods.version = function() {
		return plugin.version;
	};

	/* Все остальные общие функции, которым не нужна область видимости init метода */
	/**
	 * Получить/установить значение объекта передав путь строкой ('price.current.USD')
	 * @param {object} object - объект
	 * @param {string} key - путь к свойству
	 * @param {any} value - значение
	 * @returns {any} - значение свойства объекта
	**/
	function nestedObjectPath(object, key, value) {
		var path = key.split('.');
		var get = function(path, object) {
			return path.reduce(function(previous, current) {
				return previous[current];
			}, object);
		};
		if (value) {
			var way = path.pop();
			get(path, object)[way] = value;
			return object;
		} else {
			return get(path, object);
		}
	}
	/* Конец объявления общих функций */

	/* Инициализации плагина и запуск методов */
	$.fn[plugin.name] = function(setting) {
		if (typeof setting === 'object' || !setting) {
			return $.each(this, function() {
				methods.init($(this), setting, {
					type: 'init',
					method: 'init'
				});
			});
		} else if (typeof setting === 'string') {
			var params = Array.prototype.slice.call(arguments, 1);
			var context = this.get(0);
			switch(setting.toLowerCase()) {
				case 'set':
					return methods.set.apply(context, params);
				case 'get':
					return methods.get.apply(context, params);
				case 'destroy':
					return methods.destroy.call(context);
				case 'version':
					return methods.version();
			}
		}
	};

})(jQuery, window);


Использование плагина, методы:
/* Инициализация плагина с параметрами по умолчанию */
$('div').plugin();

/* Инициализация плагина с параметрами */
$('div').plugin({
	color: 'green',
	background: 'white'
});

/* Изменим параметры плагина, например по клику кнопке */
$('button').on('click', function() {
	$('div').plugin('set', 'color', 'yellow');
});

/* Или передадим больше параметров для изменения */
$('button').on('click', function() {
	$('div').plugin('set', {
		color: 'black',
		background: 'white'
	});
});

/**
 * Если у нас в настройках вложенные объекты
 * то для этого мы объявили функцию nestedObjectPath
 * и описали логику в методах set и get
 * У нас появилась возможность одной строкой 
 * имзенить/получить свойства вложеных объектов
**/
$('div').plugin('set', 'color.theme.light', 'white');

/* Или передадим объектом */
$('div').plugin('set', {
	color: {
		theme: {
			light: 'white'
		}
	}
});

/* Получить настройки/параметры плагина */
var color = $('div').plugin('get', 'setting', 'color');

/* Или получим general объект */
var time = $('div').plugin('get', 'general', 'time');

/**
 * Отвяжем/разрушим плагин.
 * Этот метод индивидуальный для каждого плагина
 * и данный пример не является универсальным для всех плагинов
**/
$('div').pluign('destroy');

/* Получить текущюю версию плагина */
$().plugin('version');


Поповоду ошибок в вашем плагине:
Никогда так не делайте, вставка в DOM должна быть только одна:
item.append(inputFile).append(inputText).append(preview);
this.append(item);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы