diff --git a/dist/Dropdownizer.js b/dist/Dropdownizer.js index 21299cf..bcaf355 100644 --- a/dist/Dropdownizer.js +++ b/dist/Dropdownizer.js @@ -72,10 +72,54 @@ var Dropdownizer = function () { * Listens for change events. * @param {Function} callback The callback function to execute when a list item changes. * @returns {Dropdownizer} The Dropdownizer instance. + * @deprecated This method has been renamed to 'onChange'. */ value: function change(callback) { + 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."); + return this.onChange(callback); + } + + /** + * Listens for change events. + * @param {Function} callback The callback function to execute when a list item changes. + * @returns {Dropdownizer} The Dropdownizer instance. + */ + + }, { + key: "onChange", + value: function onChange(callback) { + this._dropdowns.forEach(function (dropdown) { + return dropdown.onChange(callback); + }); + return this; + } + + /** + * Listens for open events. + * @param {Function} callback The callback function to execute when a dropdown is opened. + * @returns {Dropdownizer} The Dropdownizer instance. + */ + + }, { + key: "onOpen", + value: function onOpen(callback) { this._dropdowns.forEach(function (dropdown) { - return dropdown.change(callback); + return dropdown.onOpen(callback); + }); + return this; + } + + /** + * Listens for close events. + * @param {Function} callback The callback function to execute when a dropdown is closed. + * @returns {Dropdownizer} The Dropdownizer instance. + */ + + }, { + key: "onClose", + value: function onClose(callback) { + this._dropdowns.forEach(function (dropdown) { + return dropdown.onClose(callback); }); return this; } @@ -345,6 +389,13 @@ var Dropdownize = function () { } } } + + if (this._openCallback && this._ui.div.classList.contains("dd-open")) { + this._openCallback({ + target: this._ui.div, + type: "open" + }); + } } }, { key: "_preventNativeClick", @@ -357,7 +408,16 @@ var Dropdownize = function () { }, { key: "_closeList", value: function _closeList() { - this._ui.div.classList.remove("dd-open"); + if (this._ui.div.classList.contains("dd-open")) { + this._ui.div.classList.remove("dd-open"); + + if (this._closeCallback) { + this._closeCallback({ + target: this._ui.div, + type: "close" + }); + } + } } }, { key: "_bindFromOriginalElement", @@ -532,7 +592,7 @@ var Dropdownize = function () { */ }, { - key: "change", + key: "onChange", /** @@ -540,11 +600,37 @@ var Dropdownize = function () { * @param {Function} callback The callback function to execute when a list item changes. * @returns {Dropdownize} The Dropdownize instance. */ - value: function change(callback) { + value: function onChange(callback) { this._changeCallback = callback; return this; } + /** + * Listens for an open event. + * @param {Function} callback The callback function to execute when a dropdown is opened. + * @returns {Dropdownize} The Dropdownize instance. + */ + + }, { + key: "onOpen", + value: function onOpen(callback) { + this._openCallback = callback; + return this; + } + + /** + * Listens for a close event. + * @param {Function} callback The callback function to execute when a dropdown is closed. + * @returns {Dropdownize} The Dropdownize instance. + */ + + }, { + key: "onClose", + value: function onClose(callback) { + this._closeCallback = callback; + return this; + } + /** * Removes all listeners. * @returns {Dropdownize} The Dropdownize instance. diff --git a/dist/Dropdownizer.min.js b/dist/Dropdownizer.min.js index d3840e1..5e9893e 100644 --- a/dist/Dropdownizer.min.js +++ b/dist/Dropdownizer.min.js @@ -1,2 +1,2 @@ /*github.com/Grafluxe/dropdownizer*/ -"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}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;i0&&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=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)))}},{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.remove("dd-open")}},{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||(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));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:"change",value:function(e){return this._changeCallback=e,this}},{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); \ No newline at end of file +"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}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;i0&&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=this._el.querySelectorAll("option"),this._longestLine=0,this._options.forEach(function(t,i){var n=document.createElement("li");e._setAttributes(n,t,i),n.innerHTML=t.label,t.label.length>e._longestLine&&(e._longestLine=t.label.length),e._listItems.push(n),e._ui.ul.appendChild(n)}),this._listItems[this._lastSelectedIndex].setAttribute("data-selected",!0)}},{key:"_setAttributes",value:function(e,t,i){var n=this;e.setAttribute("data-value",t.value),Array.from(t.attributes).forEach(function(t){"selected"===t.name?n._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 n="";t.includes(i.name)||"data-"===i.name.slice(0,5)||(n="data-"),e._ui.div.setAttribute(n+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 n=window.getComputedStyle(e._ui.btn),s=parseInt(n.paddingLeft)+parseInt(n.paddingRight),o=Math.max(parseInt(t.fontSize),parseInt(n.fontSize));i=Math.ceil(o/2*e._longestLine+s),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||(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));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),n=void 0;return delete i.selected,n={target:this._ui.div,selectedTarget:e,data:i},t&&(n.type=t),n}},{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:"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); \ No newline at end of file diff --git a/package.json b/package.json index 0a7caae..f36b0e5 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "author": "Leandro Silva (http://grafluxe.com)", "homepage": "https://github.com/Grafluxe/dropdownizer", - "version": "1.3.2", + "version": "1.4.0", "license": "MIT", "repository": "Grafluxe/dropdownizer.git", "keywords": [