• Как выбрать селектор с помощью CSS?

    @Dubrovin Автор вопроса
    Сергей, интересное замечание, но на практике такого быть не может, поскольку темплейт кнопки общий, или везде div или везде span.
  • Как убрать ошибку Failed to execute dispatchEvent?

    @Dubrovin Автор вопроса
    Решил проблему в лоб добавлением нового параметра в setValue:
    setValue( value, trigger = true ) {
    		if ( trigger ) {
    			k.trigger( this.el, this.change );
    		}
    	}
  • Почему в этой операции javascript выводится 16?

    @Dubrovin
    var x = 2, y = 3;

    //это просто объявление функции, ничего не делает пока её не вызовут
    function plus1(x) {
    return x+1;
    }

    //здесь y равен 3, поэтому вернётся 4
    //обратите внимание, здесь результат никуда не передаётся, при следующем вызове этой функции с y=3 всё равно вернётся 4.
    plus1(y)

    //в переменную square положили объявление (дескриптор) функции, код ничего не делает пока не вызовут эту функцию
    var square = function(x) {
    return x*x;
    };

    // сначала сработает функция plus1(y), которая точно также вернёт 4, потому как y здесь тоже равен 3
    // совсем не важно что эта функция вызывалась чуть ранее
    // потом сработает square( 4 ), которая вернёт 16
    square( plus1(y) )
  • Как убрать ошибку Failed to execute dispatchEvent?

    @Dubrovin Автор вопроса
    По идее первое что приходит на ум, в месте вызова dispatchEvent перед самим вызовом проверять, не было ли это событие вызвано, и если было, то не вызывать его снова. Только не знаю, как это реализовать.
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Minifets, дак вот и не понятно, как сделать этот рабочий код... в jQuery слишком много кода, чтобы понять какой именно отвечает за нужный функционал.
    Нужен хотя бы рабочий пример для двух методов find и on. Чтобы функция могла принимать как элемент (document, Node, window, HTMLElement), так и строковый селектор.
    Можете помочь запрограммировать? Я готов заплатить за вашу консультацию, если напишите контакты как с вами связаться.
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Ещё кстати вопрос на счёт производительности, это получается, что каждый экземпляр обёртки будет содержать в себе декларации всех кастомных методов? Я так понимаю, что это не очень хорошая практика.
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Minifets, я не много не так выразился, я хочу добавить свои функции, аналогичные стандартным. Т.е. вместо document.querySelector( 'input' ) писать K('input'), вместо input.addEventListener( 'click', function(){ }) писать K('input').on('click', function() { }). Если например, внутрь K передать не селектор, а ноду или window, то должен возвращаться объект со свойство elem = window (в вашем приведённом коде это вызовет ошибку).
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Minifets,
    jQuery не используем. Как это должно работать я понимаю, я не понимаю, как это запрограммировать.
    Вот на счёт добавления своих методов в Object: prntscr.com/iarrx7
    На словах всё просто, на деле - нет. Не понятно, почему нет готовых паттернов под свои хелперы.
    Не понятно даже, как например, перезаписать стандартные API-функции своими, например, вместо querySelector - find, вместо addEventListener - on (как это сделано в jQuery).
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Не работает, так как вы пишите, плюс начинают вываливаться ошибки если на странице подключен jQuery.
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    Minifets, дак а что это единственный подход? как обычно добавляют helper функции?
  • Как сделать цепную функцию самостоятельно на JS?

    @Dubrovin Автор вопроса
    Roman Domoratskii, гуглил, не помогает.

    Упёрся в то, что у возвращаемого объекта цепочки отсутствуют необходимые свойства и методы, т.е. если мне нужно, например, у input получить value, то я не могу сказать life( input ).value вместо этого нужно писать life( input ).el.value что не очень удобно, так как на этом цепочка обрывается. Выходит что нужно руками перегружать все необходимые методы.

    Сейчас получился вот такой код:
    function k( selector ) {
    	class K {
    		constructor( selector ) {
    			if ( ( selector === window ) || ( selector instanceof Node ) || ( selector instanceof HTMLElement ) ) {
    				this.el = selector;
    			} else {
    				this.el = document;
    				this.find( selector );
    			}
    		}
    
    		find( selector ) {
    			console.log( selector );
    			this.el = this.el.querySelector( selector );
    			return this;
    		}
    
    		on( event, handler ) {
    			this.el.addEventListener( event, handler );
    		}
    
    		off( event, handler ) {
    			this.el.removeEventListener( event, handler );
    		}
    
    	}
    
    	return new K( selector );
    }
    
    export default k;
  • Как сделать цепную функцию самостоятельно на JS?

    @Dubrovin Автор вопроса
    Смотрите, допустим, у меня есть метод find, который просто является обёркой над querySelector и я хочу использовать вот такой синтаксис: life( selector ).doSomething().doSomethingElse().
    При каждом новом вызове life внутри возвращаемого объекта селектор должен устанавливаться из параметра selector. При такой реализации как у вас так не получается.
  • Как правильно оформить helper функции?

    @Dubrovin Автор вопроса
    То есть я могу написать, например, вот так:
    Object.prototype.find = function( selector ) {
        return this.querySelector( selector ); 
    }

    и использовать потом в коде следующим образом: el.find( '.myclass') ?
    Насколько это хорошая практика, ведь могут быть конфликты с другими js файлами, если кто-нибудь из разработчиков использует те же самые подходы.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Спасибо за пример! Вот только не понятно, какие общие свойства и методы кроме init и el уносить в класс компонент.

    На счёт ES6 причина в том, чтобы сделать код как раз таки не поддерживаемым старыми браузерами. В CSS, например, мы используем CSS Grid, который также поддерживается не всеми браузерами. ES6 код в отличие от трансформированного бабелем будет весить на несколько Кб меньше.

    По поводу БЭМ вы заблужаетесь, БЭМ это не про CSS, а про компонентный (блочный) подход к разработке приложения, про компонентное построение архитектуры приложения, включая PHP, JS, CSS и вообще любой другой язык, не важно как вы реализуете эту методологию. React в каком то смысле является реализацией БЭМ методологии (компонент = блок).

    let = _this используем для того, чтобы не использовать .bind( this ).

    Поразмышлял над вашим предложением использовать синтаксис import / export ES6, нашёл rollupjs как альтернативу webpack / browserify. Rollup умеет клеить файлы без лишнего кода и с учётом всех зависимостей.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Антон Спирин,
    насколько мне известно, babel полностью убирает ES6 синтаксис из кода, нам это не нужно. let должны остаться let, а не var, class должны остаться class, а не function с прототипами.
    Js пробовали собирать webpack и browserify, но эти инструменты добавляют "лишние" обёртки над нашим кодом, не совсем понятен профит от этого, если можно просто склеить файлы с помощью gulp и получить конкретно то, что пишешь и ничего более. Тем более, есть gulp-file-import с помощью которого можно в любом месте заинклудить любой кусок кода из другого файла.

    На счёт именования классов - не совсем понятно, как именно заменить БЭМ тем, что вы приводите как пример.
    .select__item__icon - вот такого селектора вообще не может быть по БЭМ, у блока может быть только один элемент, или .select__item или .select__icon. Мы используем уровни переопределения по БЭМ (слои), с помощью которых дизайн (scss) полностью независим от компонентов (php+js). Мы знаем про SMACSS и OOCSS, но это не работает для методологии БЭМ. По БЭМу классы как раз таки короче, чем по SMACSS и OOCSS, например, если у меня есть модификатор цвета кнопки --primary, то я могу в CSS просто написать --primary {}, а не button-primary как это делают, например, в bootstrap.

    Шаблонизаторы мы не используем, сам php это шаблонизатор. У нас есть один класс Component, который умеет делать рендер темплейта и использовать для рендера другие компоненты (блоки БЭМ).
    Т.е. если нам нужно нарисовать, например, форму поиска с кнопкой, то класс Component создаст 3 дочерних компонента (инпут, кнопка, иконка) и сделает рендер формы из этих компонентов. Вся эта магия происходит в PHP. JavaScript должен только обеспечить взаимодействие между компонентами, когда они отрендерились на странице.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Антон Спирин, ещё проблема в том, что вы предлагаете рендерить HTML с помощью JS и это не подходит нам, потому как у нас за рендер отвечает PHP и в нем уже реализован рендер всех компонентов. У нас не one-page приложение.
    Поэтому решения вроде React, Vue, Angular принципиально не подходят.

    Нам нужен рендер в PHP, поведение в JS. И вопрос по большей части как правильно организовать архитектуру своего фреймворка, в частности компонентов, в частности в JS, чтобы не копипастить код.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Антон Спирин, Спасибо за ссылку на Preact, 4кб это действительно мало, но я всё равно не понимаю, как можно избежать дублирования кода при создании компонентов и как именно фреймворк в этом поможет.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Антон Спирин, спасибо за ответ. Но я не совсем понимаю, как именно, например, React решит проблему которую я описываю. Все компоненты в любом случае нужно будет создавать самостоятельно с их поведением, не важно на нативном JS или на React. Точно также можно дублировать код и с использованием React. То есть в результате получится 50кб нашего кода + вес фреймворка.
    На счёт модулей - насколько мне известно, это не поддерживается браузерами, и если даже будет поддерживаться, то на HTTP 1.1 всё равно будет рукопожатие для получения каждого отдельного файла, а мы клеим абсолютно все модули в один файл, т.е. всего один файл JS для всего сайта. Ну и даже на HTTP 2.0 любой Google Pagespeed, GTmetrix будет ругаться на несколько JS файлов.
    Декларацию классов добавляем в глобальную переменную, чтобы потом их инициализировать вот таким кодом:
    document.addEventListener( 'DOMContentLoaded', function() {
    	ksf.declaration.forEach( function( component ) {
    		let elList = document.querySelectorAll( component.elSelector );
    		elList.forEach( function( el ) {
    			ksf.components[ el.dataset.id ] = new component.classDecl( el );
    		} );
    	} );
    } );


    На счёт CSS Modules ничего не слышал, наткнулся на статью на хабре: https://habrahabr.ru/post/335244/
    Но в ней человек вообще не разобрался с БЭМ, если пишет имена классов как block__element1__element2___element3, вот пример SCSS кода для компонента Checkbox:
    .checkbox {
    
    		min-width: $fr-1;
    		padding: $gap-sm / 2;
    
    		&:focus {
    			.checkbox__control {
    				box-shadow: 0 0 0 3px rgba($primary, 0.35);
    			}
    		}
    
    		&__label {
    			display: flex;
    			align-items: center;
    			color: $dark;
    		}
    
    		&__input {
    			display: none;
    
    			&:hover {
    				+ .checkbox__label {
    					.checkbox__control {
    						background-color: $light2;
    					}
    				}
    			}
    
    			&:checked {
    				+ .checkbox__label {
    					.checkbox__control {
    						background-color: $primary;
    
    						&::after {
    							opacity: 1;
    						}
    					}
    				}
    			}
    		}
    
    		&__control {
    			position: relative;
    			display: inline-block;
    			width: 24px;
    			height: 24px;
    			margin-right: $gap-xs;
    			border: 0;
    			border-radius: 5px;
    			background-color: $light;
    			transition: 0.2s;
    
    			&::after {
    				@include fa-icon(f00c, 16px);
    				position: absolute;
    				top: 50%;
    				left: 50%;
    				color: $color-white;
    				opacity: 0;
    				transform: translate(-50%, -50%);
    			}
    		}
    	}
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Мы реализуем методологию БЭМ в своём собственном фреймворке, уже написано более 30 компонентов и весь JS-код занимает в несжатом виде 50кб. В качестве бекэнда у нас не Node.JS, а PHP. Создавать темплейты из JSON у нас нет необходимости, это задача PHP, а не JS. JS реализует только поведение элементов.
    Вы предлагаете подключить Vue.js который весит 80кб или React который весит почти 100кб. А мой вопрос был в том, как превратить наши 50кб, например, в 30кб, а не запихивать в JS-приложение лишний код, которым никто не будет пользоваться.
  • Как правильно унаследовать компоненты чтобы не дублировать код?

    @Dubrovin Автор вопроса
    Антон Спирин, на счёт передачи параметров - это сработает в данном конкретном случае, но другие компоненты могут сильно отличаться. Какой толк использовать фреймворк если не понимаешь как он работает? Более того, фреймворки, как правило, все тяжёлые.
    Вы вот привели в пример backbone, какие проблемы решает в данном случае использование этого фреймворка? Там есть логика работы для чекбоксов, свитчеров, рейндж-слайдеров, колор-пикеров и других UI компонентов? Конечно же нет, это всё нужно реализовывать самому. И уж поверьте, мы это сделаем лучше, чем большинство говнокодеров сделает тоже самое на jQuery.
    Все с чего-то начинают. Если для вас ответ на вопрос очевидный, почему бы не поделиться опытом и не рассказать как вы видите решение проблемы? а не отвечать шаблонно вроде "идите юзайте React, Angular, Vue и не изобретайте велосипед"