• Почему не формируется новая строка из цикла?

    BRAGA96
    @BRAGA96
    newStr = "", newStr[i]
    Нельзя так делать, строка не массив. Попробуйте в консоли это:
    'hello'[0] = 'R'
    Строка не изменится.
  • Как сделать реинициализацию плагина?

    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) {
    		var setting = function() {
    			var params = $.extend(true, {}, defaults, options);
    			$this.data(plugin.data.setting, params);
    			return params;
    		}();
    
    		var general = function() {
    			var params = $.extend(true, {}, {
    				time: Date.now(),
    				context: $this.get(0)
    			}, common);
    			$this.data(plugin.data.general, params);
    			return params;
    		}();
    
    		if (general.type === 'init') {
    			$this.append($('<button/>', {
    				text: 'ADD'
    			}).on('click', function() {
    				methods.addItem.call(general.context);
    			}));
    		}
    
    		methods.addItem.call(general.context);
    
    	};
    
    	methods.addItem = function() {
    		$(this).append(function() {
    			var size = $('.api-item', $(this)).length;
    			var file = '<input type="file" class="form-control app-input__file" name="images['+ size +'][image]" />';
    			var text = '<input type="text" class="form-control app-input__file" name="images['+ size +'][title]" />';
    			var preview = '<div class="api-item-preview"></div>';
    			return $('<div/>', {
    				class: 'api-item',
    			}).html(file + text + preview).on({
    				click: function() {
    					console.log('click', this);
    				}
    			});
    		}.bind(this)());
    	};
    
    	methods.getItem = function(index) {
    		return $('.api-item', $(this)).eq(index);
    	};
    
    	methods.removeItem = function(index) {
    		methods.getItem.call(this, index).remove();
    	};
    
    	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;
    	};
    
    	/**
    	 * Получить/установить значение объекта передав путь строкой ('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 'additem':
    					return methods.addItem.call(context);
    				case 'getitem':
    					return methods.getItem.apply(context, params);
    				case 'removeitem':
    					return methods.removeItem.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);
    
    
    $(function() {
    	$('.plugin').plugin();
    });


    В консоли
    $('.plugin').plugin('addItem');
    
    $('.plugin').plugin('getItem', 0);
    
    $('.plugin').plugin('removeItem', 0);
  • Как сделать реинициализацию плагина?

    BRAGA96
    @BRAGA96
    Илья, я что-то не понял Вашего вопроса. Инит нужно вызывать при инициализации и при смене параметров. В коде инита в general объекте у вас есть такие данные:
    {
    	type: 'init',
    	method: 'init'
    }
    // или
    {
    	type: 'update',
    	method: 'set'
    }


    То есть в ините вы будете знать, что за метод вызвал этот инит, чтобы не выполнять какой-то кусок кода или выполнять.
    Например, если вешать событие .on то при вызове set метода вешать еще раз обработчик не нужно, здесь и можно поставить проверку:
    if (general.type === 'init') $this.on()
  • Как нормально распарсить json?

    BRAGA96
    @BRAGA96
    Если Вы из ноды передаете этот объект, то при передаче делайте JSON.stringify(), а на клиенте уже делайте JSON.parse().
  • Как сдвинуть footer вниз при раскрытии фиксированного меню?

    BRAGA96
    @BRAGA96
    Spisoktem, сделать меню по клику или задержку наведения, чтобы после 500мс нахождения мыши на меню оно открывалось, но лучше по клику, лично меня бесят меню по наведению. Зашел в какой-то магазин случайно провел мышь и комп затормозил от супер мега меню с анимациями.
  • Как вытащить данные из массива отвечающий определенному критерию?

    BRAGA96
    @BRAGA96
    Alex Lenk, лучше item.offsetWidth чем $(item).width(). Оборачивать элемент в jQuery обертку и дергать метод дольше, чем взять ширину через нативный dom api.
  • Как вытащить данные из массива отвечающий определенному критерию?

    BRAGA96
    @BRAGA96
    Alex Lenk,
    var maxWidth = Array.prototype.reduce.call($('.lang-item a'), function(result, item) {
    	return Math.max(result, item.offsetWidth);
    }, 0);
  • Как получить свойство вложенных объектов передав строку?

    BRAGA96
    @BRAGA96 Автор вопроса
    Антон Спирин, можно пример такого решения, кроме подключения lodash?
  • Сериализация и десериализация JSON документа?

    BRAGA96
    @BRAGA96
    santimin, это на Javascript в браузере, а Вам для чего и где нужно?
  • Как создать функцию persistence()?

    BRAGA96
    @BRAGA96
    wan340, переменная persistence уже объявлена в коде. Убедитесь, что есть только одна переменная persistence в одной области видимости.
  • Что такое версия в IndexedDB?

    BRAGA96
    @BRAGA96
    Зайдите в официальную документацию и узнайте или кроме той статьи 2012 года ничего нету?
  • Не могу понять как формировать url?

    BRAGA96
    @BRAGA96
    Добавьте к input атрибут name и избавьтесь от русских символов в коде.
  • Как при второй инициализации плагина передать только параметры?

    BRAGA96
    @BRAGA96
    1) В главную IIFE функцию вы принимаете 4 аргумента: $, window, document, undefined а передаете в неё только: jQuery и window. В коде этой функции document будет undefined. Используйте такую конструкцию:
    (function($, undefined) {
    	// ...
    })(jQuery);

    Или передавайте все аргументы, которые принимаете.
    (function($, window, document, undefined) {
    	// ...
    })(jQuery, window, document);


    2) Зачем сразу после инициализации плагина вы используете set метод? Он нужен для каких-то событий, кнопок и т.д, но никак при инициализации.
    $("select").plugin({
    	startShow: function(event, parent) {
    		console.log(parent);
    	});
    });


    3) Все ваши функции это по сути callback события, их принято называть с приставкой on: onStart, onEnd.
    Так же вы можете создавать свои события:
    function eventTrigger($element, name, params) {
    	setTimeout(function() {
    		$element.trigger(name + '.' + plugin.name, params);
    	});
    }
    
    eventTrigger($('.block'), 'myEvent', [true, 'string']);
    
    $('.block').on('myEvent.pluginName', function(event, boolean, string) {
    	// ...
    });

    P.S но это тот еще костыль, прочитайте про создание своих событий в jQuery

    4) DOM. У вас очень плохая архитектура построения DOM плагина. Куча созданий элементов, куча вставок в DOM ( ~10 append, append в цикле!). Вставка в DOM должна быть только одна. Используйте меньше строк в названиях классов/свойств, запишите их все в объект. Редактировать такой код будет не удобно.

    5) Context. У Вас одинаковое DOM дерево для всех инициализаций плагина. Вы всегда оталкиваетесь от переменной container и у вас с этим проблем нет, но может вы не знали о передаче контекста и это будет вам полезно: $('.container', $('.block')) = $('.block').find('.container')

    6) DATA. Чтобы разгрузить DOM от атрибутов используйте data - $('.block').data('name', { params... }) так как сделано с setting в методе init

    7) ПЕРЕМЕННЫЕ. Чтобы Вы и другие люди, которые будут читать Ваш код понимали что делается используйте алиас $ для название переменных в которые содержится jQuery коллекция элементов. Чтобы было понятно что в этой переменной не число, не объект, а именно dom элемент, например - $container

    8) ФУНКЦИИ. У вас на ~270 строк ни одной функции, такой код будет очень сложно читать и поддерживать. Используйте функции. Можете использовать замыкания и объявлять функции в методе init. В этих функциях у вас будут доступны переменные которые объявлены в этом методе, например $this, setting и их не нужно будет передавать в каждую функцию.
    var methods = {
    	init: function($this, setting, type) {
    		// ...
    		function test() {
    			console.log($this, setting);
    		}
    	}
    };


    9) МЕТОДЫ. Не забывайте, что Ваши методы это просто свойства объекта и Вы можете их разделить для удобства и наглядности.
    var plugin = {
    	name: 'plugin',
    	data: {
    		setting: 'setting'
    	}
    }, defaults = {
    	containerClass: 'dropdown'
    }, methods = {};
    
    methods.init = function($this, setting, type) {
    	//...
    };
    
    methods.set = function(key, value) {
    	//...
    };
    
    methods.get = function(key) {
    	//...
    };


    10) СОБЫТИЯ. В коде метода init вы объявляете событие. Не забывайте что при вызове методов таких как set эти события повесятся еще раз, используйте .one или контролируйте эти моменты. Не забывайте использовать nameSpace ( 'myEvent.pluginName' ), чтобы не переопределять другие события и лучше контролировать свои, а в методе destroy и вовсе их отвязать одной строкой $('.block').off('.pluginName')

    11) СВОИ МЕТОДЫ. Не забывайте, что вы можете создавать свои методы, такие как set, get и т.д. У Вас плагин-select и я не вижу события, например select - $('select').plugin('select', 'my-value'). Метод, чтобы выбрать у нужное значение в нужного select'а, метод чтобы получить значение и т.д. Эти же методы вы можете использовать внутри init-метода для своего же удобства и универсальности.

    12) SET. Зачем Вы взяли в $.each метод set? Не нужно.