• Как можно управлять контекстом функции?

    BRAGA96
    @BRAGA96
    myFynction.call(context, params)
    
    myFynction.apply(context, [params])
    
    method(args, function(params) {
    // ... 
    }.bind(context))
    Ответ написан
    Комментировать
  • Как сделать api запрос один раз в день?

    BRAGA96
    @BRAGA96
    // Если в LocalStorage есть ключ request
    if (localStorage.getItem('request') !== null) {
    	// Сохраним время timestamp из storage
    	var timestamp = Number(localStorage.getItem('request'));
    	// Если текущее время больше чем timestamp + сутки, 
    	// то сделать запрос еще раз и сохранить новый timestamp
    	if (Date.now() > timestamp + 864e5) {
    		makeRequest();
    	}
    } else {
    	// Если ключа request нет в localStorage, то сделаем запрос и создадим его
    	makeRequest();
    }
    
    // Функция запроса
    function makeRequest() {
    	var url = '';
    	return $.getJSON(url, function(data) {
    		// При успешном запросе создадим/обновим запись в localStorage с текущем временем timestamp
    		localStorage.setItem('request', Date.now());
    		$('#class').html(data.vid[0].mark.desk);
    	});
    }
    Ответ написан
    Комментировать
  • Как сделать полноэкранный слайдер с кнопками навигации внутри контейнера поверх слайда?

    BRAGA96
    @BRAGA96
    Вместо абсолютно позиционированных картинок, сделайте абсолютными кнопки навигации, справа и слева, все.
    codepen
    .slider {
      padding: relative;
    }
    
    .slider img {
      display: block;
      width: 100%;
      height: 100%;
    }
    
    .slick-arrow {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      z-index: 2;
    }
    
    .slick-prev {
      left: 0;
    }
    
    .slick-next {
      right: 0;
    }
    Ответ написан
  • Popup окно с кнопкой "Напомнить позже", как сделать?

    BRAGA96
    @BRAGA96
    При нажатии на кнопку записывать в LocalStorage время нажатия timestamp. При обновлении страницы сверять если Date.now() > timestamp + 5000 (ваше время) равно true, то показывать окно.
    if (localStorage.getItem('popup') !== null) {
    	var timestamp = localStorage.getItem('popup');
    	if (Date.now() > Number(timestamp) + 5000) { // 5 секунд
    		// показываем окно
    		$('.popup').fadeIn();
    	}
    }
    
    $('button').on('click', function() {
    	localStorage.setItem('popup', Date.now());
    });
    Ответ написан
    Комментировать
  • Почему не формируется новая строка из цикла?

    BRAGA96
    @BRAGA96
    reverseString('hello, world'); //> "dlrow ,olleh"
    
    function reverseString(string) {
    	return string.split('').reverse().join('');
    }
    Ответ написан
  • Как нормально распарсить json?

    BRAGA96
    @BRAGA96
    У вас не валидный JSON, без двойных кавычек. Это даже не JSON а Javascript объект.
    JSON.parse(JSON.stringify({'id': 50, 'text': 'j', 'datetime': '2018-07-04 12:15:56.154427+00:00', 'sender': 'test', 'thread': 1}))


    Можете сразу при парсе обработать дату сделав из строки объект даты:
    var string = JSON.stringify({'id': 50, 'text': 'j', 'datetime': '2018-07-04 12:15:56.154427+00:00', 'sender': 'test', 'thread': 1});
    var object = JSON.parse(string, function(key, value) {
    	return key === 'datetime' ? new Date(value) : value;
    });
    Ответ написан
  • Как сделать реинициализацию плагина?

    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);
    Ответ написан
    5 комментариев
  • Как вытащить данные из массива отвечающий определенному критерию?

    BRAGA96
    @BRAGA96
    Как вариант
    var $item = $('a', $('.lang-item'));
    var maxWidth = Math.max.apply(null, $.makeArray($item).map(function(item) {
    	return item.offsetWidth;
    }));
    console.log(maxWidth);


    Или так:
    const $item = $('a', $('.lang-item'));
    const maxWidth = Math.max(...Array.from($item).map((item) => item.offsetWidth));
    console.log(maxWidth);
    Ответ написан
    Комментировать
  • Ввод в поле без кнопки?

    BRAGA96
    @BRAGA96
    Обернуть все это в <form></form>
    Ответ написан
    Комментировать
  • Как получить содержимое параграфа в родители с contenteditable=true?

    BRAGA96
    @BRAGA96
    Никогда не работал с contenteditable блоками, может и есть способ получше, но я предложил бы парсинг html из строки (содержимого блока)

    Тестовый html, который был в блоке:
    <p data-test="512">WDaW</p>

    jQuery
    function parseHTML(text, callback) {
    	var $html = $($.parseHTML('<div>'+ text +'</div>'));
    	if (callback) callback($html);
    	return $html.children().unwrap();
    }
    
    parseHTML($('#contenteditable').text(), function($html) {
    	var $p = $('p', $html);
    	console.log({
    		p: $p.text(),
    		data: $p.data('test'),
    		html: $html.html()
    	});
    });


    Pure JavaScript
    function parseHTML(text, callback) {
    	var html = function() {
    		var template = document.implementation.createHTMLDocument();
    		template.body.innerHTML = text;
    		return template.body.children;
    	}();
    	if (callback) callback(html[0]);
    	return html;
    }
    
    parseHTML(document.getElementById('contenteditable').innerText, function(html) {
    	console.log({
    		p: html.innerText,
    		data: html.getAttribute('data-test'),
    		html: html.outerHTML
    	});
    });
    Ответ написан
  • Сериализация и десериализация JSON документа?

    BRAGA96
    @BRAGA96
    Сериализация - JSON.stringify(object);
    Десериализация - JSON.parse(object);
    Ответ написан
  • Как правильно пройтись по списку элементов и задать каждому ширину в зависимости от содержания?

    BRAGA96
    @BRAGA96
    Функция трансформирования:
    function transform(value, in_min, in_max, out_min, out_max) {
    	return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }


    value - текущее значение
    in_min - минимально возможное значение value
    in_max - максимально возможное значение value
    out_min - минимальное значение, которое хотим получить
    out_max - максимальное значение, которое хотим получить

    Например, максимальная скорость 50 (in_max) и минимальная 0 (in_min). Мы хотим отобразить линию от 0 (out_min) до 100 (out_max), проверять будем значение 25 (value);
    При value 25 мы получим линию со значением 50.
    К этим 50 добавляем потом px или % и добавляем ширину линии.

    Пример: codepen
    var maxSpeed = 50;
    
    $('strong', $('p')).text(maxSpeed);
    
    $.each($('ul li'), function() {
    	var speed = Number($(this).text().replace(/\D/g,''));
    	$(this).append('<div style="width:'+ transform(speed, 0, maxSpeed, 0, 150) +'px"></div>');
    });
    
    function transform(value, in_min, in_max, out_min, out_max) {
      return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }
    Ответ написан
    Комментировать
  • Не могу понять как формировать url?

    BRAGA96
    @BRAGA96
    codepen
    $('form').on('submit', function(event) {
      event.preventDefault();
      console.log('https://site.com?' + $(this).serialize());
    });
    Ответ написан
  • Как убрать первый пробел в инпуте, когда условие сработало?

    BRAGA96
    @BRAGA96
    var input = document.getElementById('in');
    input.addEventListener('keydown', function(event) {
    	if (event.keyCode === 32) {
    		this.value = this.value.trim();
    	}
    }, false);
    
    if (!String.prototype.trim) String.prototype.trim = function() {
    	return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    };
    Ответ написан
    Комментировать
  • Как обработать динамические данные с помощью jquery?

    BRAGA96
    @BRAGA96
    $('.elem', $('.content')).on('click', function() {
    	// ...
    });
    Ответ написан
    Комментировать
  • Как сделать такой счётчик на js?

    BRAGA96
    @BRAGA96
    Достал из своего старого плагина функцию фейковой рандомизации с сидированием. Если интересно погуглите random seeding.
    /**
     * Рандомизация с сидированием
     * @param {number} seed - сид значение
     * @return {number/boolean} - случайное значение из переданного сид значения
    **/
    function Random(seed) {
    	this.number = function(min, max, fixed) {
    		if (!fixed) fixed = 'floor';
    		max = max || 1;
    		min = min || 0;
    		seed = (seed * 9301 + 49297) % 233280;
    		var rnd = seed / 233280;
    		switch(fixed.toLowerCase()) {
    			case 'floor': {
    				return Math.floor(min + rnd * (max - min));
    			}
    			case 'float': {
    				return min + rnd * (max - min);
    			}
    		}
    	},
    	this.boolean = function(rate) {
    		if (!rate) rate = 50;
    		seed++;
    		return Math.sin(seed) <= rate / 100;
    	}
    }


    Как использовать
    var rand = new Random(62086296325); //> seed
    rand.number(1, 5, 'floor'); //> 2 (у всех пользователей)
    Ответ написан
    2 комментария
  • Как при второй инициализации плагина передать только параметры?

    BRAGA96
    @BRAGA96
    Это называется метод. Создайте метод set передайте в него селектор и параметры. В методе сложите переданные параметры и те что были и переинциализируйте плагин, то есть запустите init с новыми параметрами.
    Вот вам шаблон-пример:
    (function($, window, undefined) {
    	'use strict';
    
    	var plugin = {
    		name: 'plugin',
    		data: {
    			setting: 'setting'
    		}
    	}, defaults = {
    		color: 'red',
    		background: 'black'
    	};
    
    	var methods = {
    		init: function($this, setting, type) {
    			var setting = function() {
    				var params = $.extend({}, defaults, setting);
    				$this.data(plugin.data.setting, params);
    				return params;
    			}();
    			/* START */
    			$this.css({
    				color: setting.color,
    				background: setting.background
    			});
    			/* END */
    		},
    		set: function(key, value) {
    			var setting = $(this).data(plugin.data.setting);
    			switch (typeof key) {
    				case 'string':
    					setting[key] = value;
    					break;
    				case 'object':
    					setting = $.extend(true, {}, setting, key);
    					break;
    			}
    			methods.init($(this), setting, 'update');
    		},
    		get: function(key) {
    			var setting = $(this).data(plugin.data.setting);
    			if (key) {
    				return Object.getOwnPropertyDescriptor(setting, key).value;
    			} else {
    				return setting;
    			}
    		},
    		destroy: function() {
    			$(this).removeData(plugin.data.setting).fadeOut(200, function() {
    				$(this).empty().show();
    			});
    		}
    	};
    
    	$.fn[plugin.name] = function(setting, key, value) {
    		if (typeof setting === 'object' || !setting) {
    			return $.each(this, function() {
    				methods.init($(this), setting, 'init');
    			});
    		} else if (typeof setting === 'string') {
    			switch(setting.toLowerCase()) {
    				case 'set':
    					return methods.set.call(this, key, value);
    				case 'get':
    					return methods.get.call(this, key);
    				case 'destroy':
    					return methods.destroy.call(this);
    			}
    		}
    	};
    
    })(jQuery, window);


    Использование:
    // Инициализация с параметрами по умолчанию
    $('.block').plugin();
    // или своими параметрами
    $('.block').plugin({
    	color: 'green',
    	background: 'white'
    });
    
    // Метод SET, изменить параметры и переинциализировать плагин
    $('.block').plugin('set', 'color', 'red');
    // или передать объект новых параметров
    $('.block').plugin('set', {
    	color: 'yellow',
    	background: 'black'
    });
    
    // Метод GET, получить параметры плагина
    $('.block').plugin('get', 'color');
    // или получить все параметры
    $('.block').plugin('get');
    
    // Метод DESTROY, отвязать плагин
    $('.block').destory();
    Ответ написан
    8 комментариев