UNPKG

dropdownizer

Version:

Converts HTML <select> elements into customizable dropdowns.

2 lines 13.1 kB
/*github.com/Grafluxe/dropdownizer*/ "use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_createClass=function(){function e(e,t){for(var i=0;i<t.length;i++){var s=t[i];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}return function(t,i,s){return i&&e(t.prototype,i),s&&e(t,s),t}}();function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var Dropdownizer=function(){function e(t){_classCallCheck(this,e);var i=[];if("string"==typeof t?t=document.querySelectorAll(t):t&&t.nodeType&&(t=[t]),!t||!t.forEach||0===t.length)throw new ReferenceError("No such element exists.");t.forEach(function(e){return i.push(new Dropdownize(e))}),this._dropdowns=Object.freeze(i)}return _createClass(e,[{key:"selectItem",value:function(e){return this._dropdowns.forEach(function(t){return t.selectItem(e)}),this}},{key:"change",value:function(e){return console.warn("The Dropdownizer method 'change' has been renamed to 'onChange'. Please update your logic accordingly, as the 'change' method will be removed in a future release."),this.onChange(e)}},{key:"onChange",value:function(e){return this._dropdowns.forEach(function(t){return t.onChange(e)}),this}},{key:"onOpen",value:function(e){return this._dropdowns.forEach(function(t){return t.onOpen(e)}),this}},{key:"onClose",value:function(e){return this._dropdowns.forEach(function(t){return t.onClose(e)}),this}},{key:"removeItem",value:function(e){return this._dropdowns.forEach(function(t){return t.removeItem(e)}),this}},{key:"addItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:NaN;return this._dropdowns.forEach(function(s){return s.addItem(e,t,i)}),this}},{key:"removeListeners",value:function(){return this._dropdowns.forEach(function(e){return e.removeListeners()}),this}},{key:"enable",value:function(){return this._dropdowns.forEach(function(e){return e.enable()}),this}},{key:"disable",value:function(){return this._dropdowns.forEach(function(e){return e.disable()}),this}},{key:"destroy",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this._dropdowns.forEach(function(t){return t.destroy(e)}),this}},{key:"selectedItem",get:function(){var e=this._dropdowns.map(function(e){return e.selectedItem});return e.length>1?e:e[0]}},{key:"dropdowns",get:function(){return this._dropdowns}}],[{key:"preventNative",value:function(){Dropdownize._preventNative=!0}}]),e}(),Dropdownize=function(){function e(t){if(_classCallCheck(this,e),"string"==typeof t&&(t=document.querySelector(t)),!t||0===t.length)throw new ReferenceError("No such element exists.");if(!t.nodeType)throw new TypeError("An unexpected argument was passed in.");if(t.hasOwnProperty("dropdownized")||t.hasOwnProperty("dropdownizer"))throw new ReferenceError("Your element has already been dropdownized.");if(t.classList.contains("dropdownizer"))throw new ReferenceError("The class name 'dropdownizer' is reserved. Please choose a different class name.");this._el=t,this._createElements(),this._bindEvents(),this._convertOptionsToListItems(),this._setBtn(),this._setDropdown(),this._addListItemsListeners(),this._addToDOM()}return _createClass(e,[{key:"_createElements",value:function(){this._ui={div:document.createElement("div"),btn:document.createElement("button"),ul:document.createElement("ul")}}},{key:"_bindEvents",value:function(){this._onClickBtn=this._openList.bind(this),this._onMouseOver=this._mouseOver.bind(this),this._onMouseLeave=this._mouseLeave.bind(this),this._onChange=this._syncDropdowns.bind(this),this._onClickListItem=this._listSelect.bind(this),this._onDocClick=this._preventNativeClick.bind(this)}},{key:"_mouseLeave",value:function(){this._leaveTimer=setTimeout(this._closeList.bind(this),250),this._ui.div.addEventListener("mouseover",this._onMouseOver)}},{key:"_mouseOver",value:function(){this._ui.div.removeEventListener("mouseover",this._onMouseOver),clearTimeout(this._leaveTimer)}},{key:"_convertOptionsToListItems",value:function(){var e=this;this._listItems=[],this._lastSelectedIndex=0,this._options=Array.from(this._el.querySelectorAll("option")),this._longestLine=0,this._options.forEach(function(t,i){var s=document.createElement("li");e._setAttributes(s,t,i),s.innerHTML=t.label,t.label.length>e._longestLine&&(e._longestLine=t.label.length),e._listItems.push(s),e._ui.ul.appendChild(s)}),this._listItems[this._lastSelectedIndex].setAttribute("data-selected",!0)}},{key:"_setAttributes",value:function(e,t,i){var s=this;e.setAttribute("data-value",t.value),Array.from(t.attributes).forEach(function(t){"selected"===t.name?s._lastSelectedIndex=i:e.setAttribute("data-"+t.name,t.value||!0)})}},{key:"_setBtn",value:function(){this._touchable=window.hasOwnProperty("ontouchstart")||navigator.MaxTouchPoints>0||navigator.msMaxTouchPoints>0,this._copySelectElementAttributes(),this._bindFromOriginalElement(),this._ui.btn.addEventListener("click",this._onClickBtn),this._ui.btn.innerHTML=this._options[this._lastSelectedIndex].label}},{key:"_copySelectElementAttributes",value:function(){var e=this,t=["accesskey","class","contenteditable","contextmenu","id","dir","draggable","dropzone","hidden","id","itemid","itemprop","itemref","itemscope","itemtype","lang","slot","name","spellcheck","style","tabindex","title","translate"];Array.from(this._el.attributes).forEach(function(i){var s="";t.includes(i.name)||"data-"===i.name.slice(0,5)||(s="data-"),e._ui.div.setAttribute(s+i.name,i.value||!0)})}},{key:"_openList",value:function(t){t.preventDefault(),this._ui.div.hasAttribute("disabled")||this._el.hasAttribute("disabled")||(this._touchable&&!e._preventNative?(this._el.classList.remove("dd-x"),this._el.focus(),this._el.classList.add("dd-x")):this._ui.div.classList.contains("dd-open")?this._closeList():(this._ui.div.classList.add("dd-open"),e._preventNative?document.addEventListener("click",this._onDocClick):this._ui.div.addEventListener("mouseleave",this._onMouseLeave)),this._openCallback&&this._ui.div.classList.contains("dd-open")&&this._openCallback({target:this._ui.div,type:"open"}))}},{key:"_preventNativeClick",value:function(e){e.target.parentNode!==this._ui.div&&(document.removeEventListener("click",this._onDocClick),this._closeList())}},{key:"_closeList",value:function(){this._ui.div.classList.contains("dd-open")&&(this._ui.div.classList.remove("dd-open"),this._closeCallback&&this._closeCallback({target:this._ui.div,type:"close"}))}},{key:"_bindFromOriginalElement",value:function(){this._el.addEventListener("change",this._onChange)}},{key:"_syncDropdowns",value:function(e){var t=this._listItems[e.target.options.selectedIndex];this._changeFromOriginalElement=!0,t.click(),t.focus()}},{key:"_setDropdown",value:function(){var e=this,t=window.getComputedStyle(this._el),i=this._el.offsetWidth;this._touchable&&"0px"===t.minWidth&&(i+=9),this._ui.div.dropdownizer=this,this._ui.div.style.minWidth=i+"px",this._ui.div.classList=this._el.classList,this._ui.div.classList.add("dropdownizer"),this._ui.div.appendChild(this._ui.btn),this._ui.div.appendChild(this._ui.ul),0===this._el.offsetWidth&&setTimeout(function(){var s=window.getComputedStyle(e._ui.btn),n=parseInt(s.paddingLeft)+parseInt(s.paddingRight),o=Math.max(parseInt(t.fontSize),parseInt(s.fontSize));i=Math.ceil(o/2*e._longestLine+n),e._ui.div.style.minWidth=i+"px"},0)}},{key:"_addListItemsListeners",value:function(){var e=this;this._listItems.forEach(function(t){t.addEventListener("click",e._onClickListItem)})}},{key:"_listSelect",value:function(e){e.target.dataset.disabled||e.target===this.selectedItem.selectedTarget||(this.selectItem(this._listItems.indexOf(e.target)),this._closeList())}},{key:"_addToDOM",value:function(){this._el.parentNode.insertBefore(this._ui.div,this._el.nextSibling),this._el.id&&(this._origId=this._el.id,this._ui.div.id=this._el.id,this._el.id="__"+this._el.id),this._origClasses=this._el.classList.toString(),this._el.dropdownized=!0,this._el.classList="dd-x"}},{key:"selectItem",value:function(e){"string"==typeof e&&(e=this._convertToIndex(e)),e<0&&(e=this._listItems.length+e);var t=this._listItems[e];if(!t)throw new RangeError("Your index is out of bounds.");if(t!==this._listItems[this._lastSelectedIndex])return this._listItems[this._lastSelectedIndex].removeAttribute("data-selected"),this._lastSelectedIndex=e,this._ui.btn.innerHTML=t.innerHTML,t.setAttribute("data-selected",!0),this._el.selectedIndex=this._lastSelectedIndex,this._changeCallback&&this._changeCallback(this._callbackArgs(t,"change")),this._changeFromOriginalElement||this._el.dispatchEvent(new Event("change")),this._changeFromOriginalElement=!1,this}},{key:"_convertToIndex",value:function(e){e=e.toLowerCase();var t=this._listItems.filter(function(t){return(t.dataset.label||t.dataset.value).toLowerCase()===e});if(t.length>1)throw new Error("Your search returns multiple matches. Use an index instead.");return this._listItems.indexOf(t[0])}},{key:"_callbackArgs",value:function(e,t){var i=Object.assign({index:this._lastSelectedIndex},e.dataset),s=void 0;return delete i.selected,s={target:this._ui.div,selectedTarget:e,data:i},t&&(s.type=t),s}},{key:"onChange",value:function(e){return this._changeCallback=e,this}},{key:"onOpen",value:function(e){return this._openCallback=e,this}},{key:"onClose",value:function(e){return this._closeCallback=e,this}},{key:"removeItem",value:function(e){"string"==typeof e&&(e=this._convertToIndex(e)),e<0&&(e=this._listItems.length+e);var t=this._listItems[e];if(!t)throw new RangeError("Your index is out of bounds.");if(this._ui.ul.removeChild(t),this._listItems.splice(e,1),this._el.removeChild(this._options[e]),this._options.splice(e,1),e===this._lastSelectedIndex){var i=Math.max(e-1,0);this._lastSelectedIndex=i,this._listItems.length>0?(this._ui.btn.innerHTML=this._listItems[i].innerHTML,this._listItems[i].setAttribute("data-selected",!0)):this._ui.btn.innerHTML="&nbsp;",this._el.selectedIndex=this._lastSelectedIndex}return this}},{key:"addItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:NaN;if(i<0&&(i=this._listItems.length+i),i>this._el.childElementCount||i<0)throw new RangeError("Your index is out of bounds.");return(isNaN(i)||null===i)&&(i=this._el.childElementCount),this._addToSelect(e,t,i),this._addToList(e,t,i),this}},{key:"_addToSelect",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:NaN,s=document.createElement("option"),n=Array.from(this._el.childNodes).filter(function(e){return"OPTION"===e.nodeName});s.innerHTML=e,this._el.insertBefore(s,n[i]),this._options.splice(i,0,s),t.hasOwnProperty("label")&&s.setAttribute("label",t.label||!0),t.hasOwnProperty("disabled")&&s.setAttribute("disabled",t.disabled||!0),t.hasOwnProperty("selected")&&s.setAttribute("selected",t.selected||!0)}},{key:"_addToList",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:NaN,s=document.createElement("li");s.dataset.value=e,s.innerHTML=t.label||e,this._ui.ul.insertBefore(s,this._ui.ul.childNodes[i]),this._listItems.splice(i,0,s),s.addEventListener("click",this._onClickListItem),t.hasOwnProperty("label")&&s.setAttribute("data-label",t.label||!0),t.hasOwnProperty("disabled")&&s.setAttribute("data-disabled",t.disabled||!0),t.hasOwnProperty("selected")&&(s.setAttribute("data-selected",t.selected||!0),t.hasOwnProperty("disabled")||(0===i&&this._lastSelectedIndex++,this.selectItem(i)))}},{key:"removeListeners",value:function(){var e=this;return this._ui.btn.removeEventListener("click",this._onClickBtn),this._ui.div.removeEventListener("mouseleave",this._onMouseLeave),this._ui.div.removeEventListener("mouseover",this._onMouseOver),this._el.removeEventListener("change",this._onChange),document.removeEventListener("click",this._onDocClick),this._listItems.forEach(function(t){t.removeEventListener("click",e._onClickListItem)}),this}},{key:"enable",value:function(){return this._el.removeAttribute("disabled"),this._ui.div.removeAttribute("data-disabled"),this}},{key:"disable",value:function(){return this._el.setAttribute("disabled","true"),this._ui.div.setAttribute("data-disabled","true"),this}},{key:"destroy",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this._destroyed||(this._destroyed=!0,this.removeListeners(),this._el.parentNode.removeChild(this._ui.div),e&&(this._origId&&(this._el.id=this._origId),this._el.classList=this._origClasses)),this}},{key:"selectedItem",get:function(){return this._callbackArgs(this._listItems[this._lastSelectedIndex])}}]),e}();"object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports&&(module.exports=Dropdownizer);