Аналог nextAll() на чистом javascript
Задался тут целью хоть раз написать плагин (точнее метод скорее) на нативном JS. Задача оказалась непростой, по отказу от jquery. Суть плагина: скрывать элементы под кнопку, если их больше определенного количества. Хочу использовать особо для длинных фильтров и еще где понадобится. Столкнулся со следующей проблемой не могу взять все элементы после нужного мне числа, то есть аналог nextAll().
Как это сделать? |
Цитата:
http://www.fpublisher.ru/documentati...s#hnextsibling |
ksa,
Так он возвращает только один следующий элемент, а не все. |
Цитата:
|
Цитата:
|
ksa,
вот решил с основами и познакомиться таким образом. На jquery я писал плагин, получилось вроде бы неплохо. |
Цитата:
|
ksa,
Я думаю, что вы напрасно смеетесь. Потому что многие учатся таким способом. У меня пока что вот что получается window.onload = function() { function loadElements() { //Основные параметры var element = '.filter__item', //элементы к которым будет применен метод childrenElements = '.filter__option', //дочерние элементы, больше числа которых появляется кнопка раскрытия count = 3, //число, после которого появится раскрытие speed = 250, //скорость раскрытия блока по нажатию на кнопку показа textMore = '+ Показать все', //Текст для кнопки "Показать все" textLess = '- Скрыть'; //Текст для кнопки "Cкрыть" //Переменные, используемые в плагине var elList = document.querySelectorAll(element); //находим все элементы на странице, к которым нужно применить метод Array.prototype.forEach.call(elList, function(el, i) { //Обходим в цикле все элементы var countChildren = elList[i].querySelectorAll(childrenElements); if(countChildren.length > count) { //Создаем контейнер, куда будем перемещать все элементы, которые нужно скрыть. var container = document.createElement('div'); container.className = 'loadContainer'; //Присваиваем контейнер в наш элемент elList[i].appendChild(container); //Выбираем все элементы, которые будем скрывать for(var j = 0; j < countChildren.length; j++) { if(j > count - 1) { container.appendChild(countChildren[j]); } } } }); } loadElements(); } |
Stay_Strong, это и есть плагин? :blink:
|
Нет, мне достаточно сложно сразу собирать плагин. Я реализую функционал. Потом создаю только объект default, и преобразую в плагин потом. Плагин можете посмотреть вот здесь мой (который на jquery).
А вообще принимаю любые советы по более правильной реализации структуры и оптимизации кода. |
А ты посмотри, как в JQuery это реализовано :)
|
nextAll на js
:write:
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> .test{ background-color: #008000; } .red{ background-color: #FF0000; } </style> </head> <body> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item test">test</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> <div class="item">10</div> <script> function nextAll(elem) { var next = false; return [].filter.call(elem.parentNode.children, function(child) { if (child === elem) next = true; return next && child !== elem }) }; var div = document.querySelector(".test"), next = nextAll(div); next.forEach(function(el) { el.classList.add('red'); }); </script> </body> </html> |
рони,
Спасибо, не подскажите, как мне на чистом js вот такое изобразить $.fn.mobileMenu = function (options) {}; На jquery это просто. Делаю по своему же примеру https://github.com/WebTravel/multile.../mobileMenu.js Там создаю объект default, потом расширяю еще option при помощи extand. А потом нужно бы возвращать первый элемент и делать это плагином.. А как я не в упор. Пока вот такое у меня: var defaults = { //.... } function LoadElements(element, options) { var extend = function(out) { out = out || {}; for (var i = 1; i < arguments.length; i++) { if (!arguments[i]) continue; for (var key in arguments[i]) { if (arguments[i].hasOwnProperty(key)) out[key] = arguments[i][key]; } } return out; }; this.options = extend({}, defaults, options); this.element = element; this.init(); } Дальше будет LoadElements.prototype.init = function () { // тело плагина } И дальше как раз нужно вызов осуществлять, как в $.fn Вопрос: а как? |
|
Цитата:
|
рони,
Не подскажите, почему у меня this не берется, а документ передается в функцию prototype? window.onload = function() { var defaults = { 'childrenElements' : '.filter__option',//дочерние элементы, больше числа которых появляется кнопка раскрытия 'count' : '3',//число, после которого появится раскрытие 'speed' : '250',//скорость раскрытия блока по нажатию на кнопку показа 'textMore' : '+ Показать все',//Текст для кнопки "Показать все" 'textLess' : '- Скрыть'//Текст для кнопки "Cкрыть" } function LoadElements(element, options) { var extend = function(out) { out = out || {}; for (var i = 1; i < arguments.length; i++) { if (!arguments[i]) continue; for (var key in arguments[i]) { if (arguments[i].hasOwnProperty(key)) out[key] = arguments[i][key]; } } return out; }; this.options = extend({}, defaults, options); this.element = element; this.init(); } LoadElements.prototype.init = function() { var self = this; //Переменные, используемые в плагине var elList = document.querySelectorAll(self); //находим все элементы на странице, к которым нужно применить метод Array.prototype.forEach.call(elList, function(el, i) { //Обходим в цикле все элементы var countChildren = elList[i].querySelectorAll(self.options.childrenElements); if(countChildren.length > self.options.count) { //Создаем контейнер, куда будем перемещать все элементы, которые нужно скрыть. var container = document.createElement('div'); container.className = 'loadContainer'; //Создаем кнопку для раскрытия списка var showAll = document.createElement('div'); showAll.className = 'loadMore'; showAll.innerHTML = self.options.textMore; //Присваиваем контейнер в наш элемент elList[i].appendChild(container); //Присваиваем кнопку в наш элемент elList[i].appendChild(showAll); //Выбираем все элементы, которые будем скрывать и отправлем их в контейнер for(var j = 0; j < countChildren.length; j++) { if(j > self.options.count - 1) { container.appendChild(countChildren[j]); } } //Поочередно разворачиваем и сворачиваем контейнер при нажатии showAll.onclick = function() { this.previousElementSibling.classList.toggle('active'); } } }); } (function(window) { window.loadElements = function(element, options) { this.element = element; new LoadElements(this, options); } return this; })(window); document.querySelectorAll('.filter__item').loadElements(); } <div class="filter__wrapper"> <form action="" class="filter"> <div class="filter__item"> <div class="filter__name">Производители</div> <div class="filter__option--wrapper"> <div class="filter__option"> <input id="check1" type="checkbox"/> <label for="check1">ACV</label> </div> <div class="filter__option"> <input id="check2" type="checkbox"/> <label for="check2">AE&T</label> </div> <div class="filter__option"> <input id="check3" type="checkbox"/> <label for="check3">Ariston</label> </div> <div class="filter__option"> <input id="check4" type="checkbox"/> <label for="check4">Armada</label> </div> <div class="filter__option"> <input id="check5" type="checkbox"/> <label for="check5">Baxi</label> </div> <div class="filter__option"> <input id="check6" type="checkbox"/> <label for="check6">Buderus</label> </div> <div class="filter__option"> <input id="check7" type="checkbox"/> <label for="check7">Chaffoteaux</label> </div> <div class="filter__option"> <input id="check8" type="checkbox"/> <label for="check8">Matrix</label> </div> <div class="filter__option"> <input id="check9" type="checkbox"/> <label for="check9">MATRIX</label> </div> </div> </div> </form> </div> |
Stay_Strong,
может тот кто лучше знает ООП подскажет. |
Rise,
Почему нельзя так обрабатывать extend? И как мне передать мой селектор? Как только я попадаю в функцию инициализации, вывожу console.log(this) и на выходе получаю весь документ, вместо моего селектора, к которому применяю метод. Вы понимаете в этом, могу взять урок по скайпу за плату. |
Цитата:
У тебя пока огрызки кода. Да и в них столько мешанины шо пипец! |
Скрыть элементы больше чем ...
Stay_Strong,
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> .loadContainer{ display: none; } .loadContainer.active{ display: block; } </style> <script> if (!Object.assign) { Object.defineProperty(Object, 'assign', { enumerable: false, configurable: true, writable: true, value: function(target, firstSource) { 'use strict'; if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) { continue; } var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; } }); } window.addEventListener("DOMContentLoaded", function() { function wrap(create, elms, all) { function fn(item, i) { var to = all || i == len - 1 ? create : create.cloneNode(true); item = item.parentNode.replaceChild(to, item); to.appendChild(item) } var len = elms.length; len ? [].forEach.call(elms, fn) : fn(elms) } var defaults = { "childrenElements": ".filter__option", "count": "3", "speed": "250", "textMore": "+ Показать все", "textLess": "- Скрыть" }; window.LoadElements = function LoadElements(elements, options) { if (!(this instanceof LoadElements)) return new LoadElements(elements, options); this.options = Object.assign({}, defaults, options); this.elements = typeof elements === "string" ? document.querySelectorAll(elements) : elements.length ? elements : [elements]; this.init() }; LoadElements.prototype.init = function() { var self = this; [].forEach.call(self.elements, function(el) { var countChildren = el.querySelectorAll(self.options.childrenElements); countChildren = [].slice.call(countChildren, self.options.count); if (countChildren.length) { var container = document.createElement("div"); container.className = "loadContainer"; wrap(container, countChildren, true); var showAll = document.createElement("div"); showAll.className = "loadMore"; showAll.innerHTML = self.options.textMore; showAll.addEventListener("click", function() { container.classList.toggle("active"); showAll.innerHTML = container.classList.contains("active") ? self.options.textLess : self.options.textMore }); container.parentNode.insertBefore(showAll, container.nextSibling) } }) }; LoadElements(".filter__item") }); </script> </head> <body> <div class="filter__wrapper"> <form action="" class="filter"> <div class="filter__item"> <div class="filter__name">Производители</div> <div class="filter__option--wrapper"> <div class="filter__option"> <input id="check1" type="checkbox"/> <label for="check1">ACV</label> </div> <div class="filter__option"> <input id="check2" type="checkbox"/> <label for="check2">AE&T</label> </div> <div class="filter__option"> <input id="check3" type="checkbox"/> <label for="check3">Ariston</label> </div> <div class="filter__option"> <input id="check4" type="checkbox"/> <label for="check4">Armada</label> </div> <div class="filter__option"> <input id="check5" type="checkbox"/> <label for="check5">Baxi</label> </div> <div class="filter__option"> <input id="check6" type="checkbox"/> <label for="check6">Buderus</label> </div> <div class="filter__option"> <input id="check7" type="checkbox"/> <label for="check7">Chaffoteaux</label> </div> <div class="filter__option"> <input id="check8" type="checkbox"/> <label for="check8">Matrix</label> </div> <div class="filter__option"> <input id="check9" type="checkbox"/> <label for="check9">MATRIX</label> </div> </div> </div> <div class="filter__item"> <div class="filter__name">Производители</div> <div class="filter__option--wrapper"> <div class="filter__option"> <input id="check1" type="checkbox"/> <label for="check1">ACV</label> </div> <div class="filter__option"> <input id="check2" type="checkbox"/> <label for="check2">AE&T</label> </div> <div class="filter__option"> <input id="check3" type="checkbox"/> <label for="check3">Ariston</label> </div> <div class="filter__option"> <input id="check4" type="checkbox"/> <label for="check4">Armada</label> </div> <div class="filter__option"> <input id="check5" type="checkbox"/> <label for="check5">Baxi</label> </div> <div class="filter__option"> <input id="check6" type="checkbox"/> <label for="check6">Buderus</label> </div> <div class="filter__option"> <input id="check7" type="checkbox"/> <label for="check7">Chaffoteaux</label> </div> <div class="filter__option"> <input id="check8" type="checkbox"/> <label for="check8">Matrix</label> </div> <div class="filter__option"> <input id="check9" type="checkbox"/> <label for="check9">MATRIX</label> </div> </div> </div> </form> </div> </body> </html> |
рони,
Вот вы мне тут накатали, спасибо огромное, конечно. Теперь мне тут со всем разобраться нужно, потому что это совсем стиль, не тот, в котором я писал и пишу. Вы уроки не даете по скайпу? P.S.: Здесь совсем все по-взрослому, без комментариев не разберусь. |
Stay_Strong,
попробуйте разобраться самостоятельно ... |
Часовой пояс GMT +3, время: 22:27. |