From 5452195723338ebc372dc87d8a4749f903022d90 Mon Sep 17 00:00:00 2001
From: PietroBossolasco
Date: Wed, 1 Nov 2023 23:26:17 +0100
Subject: [PATCH] Release v.1.0.0
---
README.md | 81 +++++++----
source/text-selector.css | 13 +-
source/text-selector.js | 267 ++++++++++++++++++++++++-----------
styles.css | 6 -
text-selector-v0-1-1.min.css | 3 -
text-selector-v0-1-1.min.js | 3 -
text-selector-v1-0-0.min.css | 3 +
text-selector-v1-0-0.min.js | 3 +
8 files changed, 248 insertions(+), 131 deletions(-)
delete mode 100644 styles.css
delete mode 100644 text-selector-v0-1-1.min.css
delete mode 100644 text-selector-v0-1-1.min.js
create mode 100644 text-selector-v1-0-0.min.css
create mode 100644 text-selector-v1-0-0.min.js
diff --git a/README.md b/README.md
index ac4098b..d1daa6c 100644
--- a/README.md
+++ b/README.md
@@ -2,64 +2,83 @@
![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)
-The Text-Selector library is a JavaScript library that allows you to create custom select elements with a text label that, when clicked, displays a list of options. It provides an alternative and visually appealing way to present and interact with select options.
+The Text-Selector library is a JavaScript library that enables you to enhance the user experience with select elements. It allows you to replace standard select elements with custom-designed text and provides the ability to open and close the selection dynamically. This library also supports animations when jQuery is included.
## Features
-* Show a list of selectable options when the text label is clicked.
-* Easy to initialize with a simple function call.
+* Easily transform standard select elements into custom-designed text elements.
+* Customize the text with specific CSS classes and text element tags.
+* Animations for opening and closing the selector (requires jQuery).
+* Simplified initialization with a single function call.
## Installation
-To use the Text-Selector library, you can include the JavaScript file in your HTML:
+To use the Text-Selector library, follow these steps:
+
+1. Include the text-selector.min.js JavaScript file and the text-selector.min.css CSS file in your HTML.
+1. Optionally, include jQuery if you want to enable animations for opening and closing the selector. Make sure to include jQuery before the Text-Selector library.
+
```html
-
+
+
+
```
-Make sure to include the library after the document is loaded.
+
## Usage
-* Include the text-selector.js file in your HTML.
-* Create a standard select element and an associated text element. Assign id attributes to both elements.
+1. In your HTML document, insert a select element with the class text-selector. You can further customize the text by using the text-class attribute to add specific CSS classes and the text-element attribute to specify the HTML tag for the text (default is p).
```html
-
- Option 1
- Option 2
- Option 3
+
+ option 1
+ option 2
+ option 3
+ option 4
-
-Click me to select an option
```
-* Initialize the Text-Selector library by calling the textselectorinit function, passing an array of objects that define the text and select element pairs:
-```js
-textselectorinit([
- { text: 'myText', data: 'mySelect' }
-]);
+1. Initialize the Text-Selector library by calling the textSelector.init() function. This function should be called after the document has loaded.
+
+```html
+
```
-Your custom text-selector element is now ready to use. When you click on the text element, it will display the select options.
+
+1. Your custom Text-Selector elements are now ready to use. When you click on the custom text, the selector will dynamically open and display the available options.
## Example
```html
-
+
+
+
+
Text-Selector Example
+
+
+
+
-
- Option 1
- Option 2
- Option 3
+
+ option 1
+ option 2
+ option 3
+ option 4
+
+
- Click me to select an option
-
-
+
+
```
## License
diff --git a/source/text-selector.css b/source/text-selector.css
index 87434fe..0a1125d 100644
--- a/source/text-selector.css
+++ b/source/text-selector.css
@@ -1,10 +1,16 @@
-@import url(https://fonts.googleapis.com/css2&family=Roboto&display=swap);
-.text-selector {
+/* text-selector V0.1.1 - Made by Pietro Bossolasco */
+/* For docs -> https://github.com/PietroBossolasco/text-selector */
+@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100;400&display=swap');
+.text-selector{
+ display: none;
+}
+.text-selector-text {
user-select: none;
cursor: pointer;
}
.text-selector-selector {
position: absolute;
+ z-index: 1001;
display: none;
padding: 10px;
width: 200px;
@@ -47,3 +53,6 @@
.text-selector-selected {
background-color: #e2e2e2;
}
+.text-selector-text-disabled{
+ cursor: default !important;
+}
\ No newline at end of file
diff --git a/source/text-selector.js b/source/text-selector.js
index b6ade66..51245db 100644
--- a/source/text-selector.js
+++ b/source/text-selector.js
@@ -1,93 +1,188 @@
-// text-selector V0.1.1 - Made by Pietro Bossolasco
+// text-selector V1.0.0 - Made by Pietro Bossolasco
// For docs -> https://github.com/PietroBossolasco/text-selector
-function textselectorinit(e) {
- (s = document.createElement("div")).classList.add("text-selector-selector"),
- s.addEventListener("mouseleave", function () {
- (canc = !1),
- s.addEventListener("mouseover", () => {
- canc = !0;
- }),
- setTimeout(() => {
- if (!canc)
- try {
- $(".text-selector-selector").eq(0).fadeOut(100);
- } catch (e) {
- this.style.display = "none";
+const textSelector = {
+ s: null, // div with option
+ elements: [], // created
+ d: null, // select with text-selector class
+ init: function () {
+ this.d = document.getElementsByClassName("text-selector");
+ for (let key in this.d) {
+ if (this.d[key].type == "select-one") {
+ try {
+ if (!this.d[key].classList.contains("text-selector-initialized")) {
+ let ccl = this.d[key].getAttribute("text-class");
+ let ce = this.d[key].getAttribute("text-element");
+ let id = this.generateId();
+ ce = ce == null ? "p" : ce;
+ ccl = ccl === null ? "" : ccl;
+ let a = document.createElement(ce);
+ a.classList = ccl + " text-selector-text";
+ a.innerText = this.d[key].options[this.d[key].selectedIndex].text;
+ a.setAttribute("text-selector-id", id);
+ this.d[key].insertAdjacentElement("afterend", a);
+ a.addEventListener("click", this.clickHandler);
+ let c = document.createElement("div");
+ c.classList = "text-selector-selector";
+ c.setAttribute("text-selector-id", id);
+ this.d[key].addEventListener("change", function () {
+ console.log(this)
+ a.innerText = this.options[this.selectedIndex].text;
+ });
+ a.insertAdjacentElement("afterend", c);
+ this.elements.push({
+ id: id,
+ select: this.d[key],
+ text: a,
+ selector: c,
+ });
+ this.d[key].classList.add("text-selector-initialized");
+ console.log(this.d[key].disabled)
+ let ausKey = key;
+ Object.freeze(ausKey);
+ const observercallback = () => {
+ if(this.d[ausKey].disabled && !a.classList.contains("text-selector-text-disabled")){
+ a.classList.add("text-selector-text-disabled");
+ }
+ else if(!this.d[ausKey].disabled && a.classList.contains("text-selector-text-disabled")){
+ a.classList.remove("text-selector-text-disabled");
+ }
+ console.log(ausKey)
}
- canc = !1;
- }, 500);
- }),
- document.getElementsByTagName("body")[0].appendChild(s);
- for (let l = 0; l < e.length; l++) {
- let i = l;
- Object.freeze(i),
- (t = document.getElementById(e[l].text)).classList.add(
- "text-selector-text"
- ),
- -1 !== (d = document.getElementById(e[l].data)).selectedIndex &&
- (t.innerText = d.options[d.selectedIndex].text),
- (d.style.display = "none");
- try {
- t.addEventListener("click", function () {
- if (!(d = document.getElementById(e[i].data)).disabled) {
- (t = document.getElementById(e[i].text)),
- (c = d.childNodes),
- (aus = Array.from(c)),
- (s.innerHTML = "");
- var l = document.createElement("div");
- l.classList.add("text-selector-content"),
- c.forEach(function (e) {
- e.innerText &&
- ((sel = document.createElement("div")),
- e.disabled
- ? (sel.classList =
- "text-selector-selection text-selector-disabled")
- : e.selected
- ? (sel.classList =
- "text-selector-selection text-selector-selected")
- : (sel.classList =
- "text-selector-selection text-selector-normal"),
- (sel.innerText = e.innerText),
- e.disabled ||
- sel.addEventListener("click", function () {
- (ex = document.getElementsByClassName(
- "text-selector-selected"
- )),
- null != ex[0] &&
- (ex[0].classList =
- "text-selector-selection text-selector-normal"),
- (v = this.innerText),
- (this.classList =
- "text-selector-selection text-selector-selected"),
- (d.selectedIndex = aus.indexOf(e) - 1),
- (t.innerText = v);
- }),
- l.appendChild(sel));
- }),
- (s.innerHTML = ""),
- s.appendChild(l);
+ const configObserver = { attributes: true, childList: true, subtree: true };
+ const observer = new MutationObserver(observercallback);
+ observer.observe(this.d[key], configObserver);
+ }
+ } catch (ex) {
+ console.error("Error during the initialization\n", ex);
+ }
+ }
+ }
+ },
+ generateId: function () {
+ const characters =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ let result = "";
+ let ok = false;
+ let length = 10;
+ while (!ok) {
+ for (let i = 0; i < length; i++) {
+ const randomIndex = Math.floor(Math.random() * characters.length);
+ result += characters.charAt(randomIndex);
+ }
+ if (!this.isIdInArray(result)) {
+ ok = true;
+ }
+ }
+ return result;
+ },
+ isIdInArray: function (id) {
+ return this.elements.some((item) => item.id === id);
+ },
+ findElementById: function (id) {
+ return this.elements.find((item) => item.id === id);
+ },
+ removeAllContainers: function () {
+ this.elements.forEach((item) => {
+ if (item.selector.style.display != "none") {
+ try {
+ $(item.selector).fadeOut(100);
+ } catch (ex) {
+ item.selector.style.display = "none";
+ }
+ }
+ });
+ },
+ mouseLeaveHandler: function (item) {
+ let isMouseInside = false;
+
+ item.addEventListener("mouseenter", () => {
+ isMouseInside = true;
+ });
+
+ item.addEventListener("mouseleave", () => {
+ isMouseInside = false;
+ setTimeout(() => {
+ if (!isMouseInside) {
try {
- $(".text-selector-selector").eq(0).fadeIn(100);
- } catch (n) {
- s.style.display = "block";
+ $(item).fadeOut(100);
+ } catch (ex) {
+ item.style.display = "none";
}
- let o = this.offsetLeft,
- r = this.offsetTop;
- r > s.offsetHeight
- ? ((s.style.paddingBottom = this.offsetHeight + 10 + "px"),
- (s.style.top = r - s.offsetHeight + this.offsetHeight + "px"),
- (s.style.paddingTop = "10px"))
- : ((s.style.paddingBottom = "10px"),
- (s.style.top = this.offsetHeight + "px"),
- (s.style.paddingTop = this.offsetHeight + 10 + "px")),
- o > s.offsetWidth / 2 + 10
- ? (s.style.left =
- o + this.offsetWidth / 2 - s.offsetWidth / 2 + "px")
- : (s.style.left = "10px");
+ }
+ }, 500);
+ });
+ },
+ clickHandler: function (e) {
+ textSelector.removeAllContainers();
+ let data = textSelector.findElementById(
+ e.target.getAttribute("text-selector-id")
+ );
+ if (!data.select.disabled) {
+ data.selector.addEventListener(
+ "mouseleave",
+ textSelector.mouseLeaveHandler(data.selector)
+ );
+ data.selector.innerHTML = "";
+ let cn = Array.from(data.select.childNodes);
+ let content = document.createElement("div");
+ content.classList.add("text-selector-content");
+ cn.forEach((item) => {
+ if (item.innerText) {
+ let opt = document.createElement("div");
+ if (item.disabled) {
+ opt.classList = "text-selector-selection text-selector-disabled";
+ } else if (item.selected) {
+ opt.classList = "text-selector-selection text-selector-selected";
+ } else {
+ opt.classList = "text-selector-selection text-selector-normal";
+ }
+ opt.innerText = item.innerText;
+ if (!item.disabled) {
+ opt.addEventListener("click", function () {
+ ex = data.selector.getElementsByClassName(
+ "text-selector-selected"
+ );
+ if (ex[0] != null) {
+ ex[0].classList =
+ "text-selector-selection text-selector-normal";
+ }
+ v = this.innerText;
+ this.classList = "text-selector-selection text-selector-selected";
+ item.selected = true;
+ data.text.innerText = v;
+ });
+ }
+ content.appendChild(opt);
}
});
- } catch (n) {
- alert("Error in the text-selector configuration"), console.error(n);
+
+ data.selector.appendChild(content);
+ try {
+ $(data.selector).fadeIn(100);
+ } catch (ex) {
+ data.selector.style.display = "block";
+ }
+ textSelector.calculatePosition(data, this);
+ }
+ },
+ calculatePosition: function (data, element) {
+ const x = element.offsetLeft;
+ const y = element.offsetTop;
+ if (y > data.selector.offsetHeight) {
+ data.selector.style.paddingBottom = element.offsetHeight + 10 + "px";
+ data.selector.style.top =
+ y - data.selector.offsetHeight + element.offsetHeight + "px";
+ data.selector.style.paddingTop = "10px";
+ } else {
+ data.selector.style.paddingBottom = "10px";
+ data.selector.style.top = y + "px";
+ data.selector.style.paddingTop = element.offsetHeight + 10 + "px";
+ }
+ if (x > data.selector.offsetWidth / 2 + 10) {
+ data.selector.style.left =
+ x + element.offsetWidth / 2 - data.selector.offsetWidth / 2 + "px";
+ } else {
+ data.selector.style.left = x + "px";
}
- }
-}
+ },
+};
diff --git a/styles.css b/styles.css
deleted file mode 100644
index 1a16728..0000000
--- a/styles.css
+++ /dev/null
@@ -1,6 +0,0 @@
-body{
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100vh;
-}
\ No newline at end of file
diff --git a/text-selector-v0-1-1.min.css b/text-selector-v0-1-1.min.css
deleted file mode 100644
index f8dd2c1..0000000
--- a/text-selector-v0-1-1.min.css
+++ /dev/null
@@ -1,3 +0,0 @@
-/* text-selector V0.1.1 - Made by Pietro Bossolasco */
-/* For docs -> https://github.com/PietroBossolasco/text-selector */
-@import url(https://fonts.googleapis.com/css2&family=Roboto&display=swap);.text-selector-text{user-select:none;cursor:pointer}.text-selector-selector{position:absolute;display:none;padding:10px;width:200px}.text-selector-content{background-color:#fff;border-radius:5px;box-shadow:rgba(0,0,0,.05) 0 6px 24px 0,rgba(0,0,0,.08) 0 0 0 1px}.text-selector-selection{padding:5px 20px;min-height:25px;line-height:25px;user-select:none;transition-duration:.2s;font-family:Roboto,sans-serif;border-bottom:1px solid #efefef}.text-selector-selection:first-child{border-top-left-radius:5px;border-top-right-radius:5px}.text-selector-selection:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom:none}.text-selector-disabled{color:gray}.text-selector-disabled:hover{background-color:#fff!important;cursor:default!important}.text-selector-selection:hover{cursor:pointer;transition-duration:.2s;background-color:#e2e2e2}.text-selector-selected{background-color:#e2e2e2}
\ No newline at end of file
diff --git a/text-selector-v0-1-1.min.js b/text-selector-v0-1-1.min.js
deleted file mode 100644
index 1824bc2..0000000
--- a/text-selector-v0-1-1.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-// text-selector V0.1.1 - Made by Pietro Bossolasco
-// For docs -> https://github.com/PietroBossolasco/text-selector
-function textselectorinit(e){(s=document.createElement("div")).classList.add("text-selector-selector"),s.addEventListener("mouseleave",function(){canc=!1,s.addEventListener("mouseover",()=>{canc=!0}),setTimeout(()=>{if(!canc)try{$(".text-selector-selector").eq(0).fadeOut(100)}catch(e){this.style.display="none"}canc=!1},500)}),document.getElementsByTagName("body")[0].appendChild(s);for(let l=0;ls.offsetHeight?(s.style.paddingBottom=this.offsetHeight+10+"px",s.style.top=r-s.offsetHeight+this.offsetHeight+"px",s.style.paddingTop="10px"):(s.style.paddingBottom="10px",s.style.top=this.offsetHeight+"px",s.style.paddingTop=this.offsetHeight+10+"px"),o>s.offsetWidth/2+10?s.style.left=o+this.offsetWidth/2-s.offsetWidth/2+"px":s.style.left="10px"}})}catch(n){alert("Error in the text-selector configuration"),console.error(n)}}}
\ No newline at end of file
diff --git a/text-selector-v1-0-0.min.css b/text-selector-v1-0-0.min.css
new file mode 100644
index 0000000..f47ec9b
--- /dev/null
+++ b/text-selector-v1-0-0.min.css
@@ -0,0 +1,3 @@
+/* text-selector V1.0.0 - Made by Pietro Bossolasco */
+/* For docs -> https://github.com/PietroBossolasco/text-selector */
+@import url(https://fonts.googleapis.com/css2?family=Roboto:wght@100;400&display=swap);.text-selector{display:none}.text-selector-text{user-select:none;cursor:pointer}.text-selector-selector{position:absolute;z-index:1001;display:none;padding:10px;width:200px}.text-selector-content{background-color:#fff;border-radius:5px;box-shadow:rgba(0,0,0,.05) 0 6px 24px 0,rgba(0,0,0,.08) 0 0 0 1px}.text-selector-selection{padding:5px 20px;min-height:25px;line-height:25px;user-select:none;transition-duration:.2s;font-family:Roboto,sans-serif;border-bottom:1px solid #efefef}.text-selector-selection:first-child{border-top-left-radius:5px;border-top-right-radius:5px}.text-selector-selection:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-bottom:none}.text-selector-disabled{color:gray}.text-selector-disabled:hover{background-color:#fff!important;cursor:default!important}.text-selector-selection:hover{cursor:pointer;transition-duration:.2s;background-color:#e2e2e2}.text-selector-selected{background-color:#e2e2e2}.text-selector-text-disabled{cursor:default!important}
\ No newline at end of file
diff --git a/text-selector-v1-0-0.min.js b/text-selector-v1-0-0.min.js
new file mode 100644
index 0000000..88069b9
--- /dev/null
+++ b/text-selector-v1-0-0.min.js
@@ -0,0 +1,3 @@
+// text-selector V1.0.0 - Made by Pietro Bossolasco
+// For docs -> https://github.com/PietroBossolasco/text-selector
+const textSelector={s:null,elements:[],d:null,init:function(){for(let e in this.d=document.getElementsByClassName("text-selector"),this.d)if("select-one"==this.d[e].type)try{if(!this.d[e].classList.contains("text-selector-initialized")){let t=this.d[e].getAttribute("text-class"),s=this.d[e].getAttribute("text-element"),l=this.generateId();s=null==s?"p":s,t=null===t?"":t;let i=document.createElement(s);i.classList=t+" text-selector-text",i.innerText=this.d[e].options[this.d[e].selectedIndex].text,i.setAttribute("text-selector-id",l),this.d[e].insertAdjacentElement("afterend",i),i.addEventListener("click",this.clickHandler);let n=document.createElement("div");n.classList="text-selector-selector",n.setAttribute("text-selector-id",l),this.d[e].addEventListener("change",function(){console.log(this),i.innerText=this.options[this.selectedIndex].text}),i.insertAdjacentElement("afterend",n),this.elements.push({id:l,select:this.d[e],text:i,selector:n}),this.d[e].classList.add("text-selector-initialized"),console.log(this.d[e].disabled);let o=e;Object.freeze(o);let c=()=>{this.d[o].disabled&&!i.classList.contains("text-selector-text-disabled")?i.classList.add("text-selector-text-disabled"):!this.d[o].disabled&&i.classList.contains("text-selector-text-disabled")&&i.classList.remove("text-selector-text-disabled"),console.log(o)},r={attributes:!0,childList:!0,subtree:!0},d=new MutationObserver(c);d.observe(this.d[e],r)}}catch(a){console.error("Error during the initialization\n",a)}},generateId:function(){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t="",s=!1;for(;!s;){for(let l=0;l<10;l++){let i=Math.floor(Math.random()*e.length);t+=e.charAt(i)}this.isIdInArray(t)||(s=!0)}return t},isIdInArray:function(e){return this.elements.some(t=>t.id===e)},findElementById:function(e){return this.elements.find(t=>t.id===e)},removeAllContainers:function(){this.elements.forEach(e=>{if("none"!=e.selector.style.display)try{$(e.selector).fadeOut(100)}catch(t){e.selector.style.display="none"}})},mouseLeaveHandler:function(e){let t=!1;e.addEventListener("mouseenter",()=>{t=!0}),e.addEventListener("mouseleave",()=>{t=!1,setTimeout(()=>{if(!t)try{$(e).fadeOut(100)}catch(s){e.style.display="none"}},500)})},clickHandler:function(e){textSelector.removeAllContainers();let t=textSelector.findElementById(e.target.getAttribute("text-selector-id"));if(!t.select.disabled){t.selector.addEventListener("mouseleave",textSelector.mouseLeaveHandler(t.selector)),t.selector.innerHTML="";let s=Array.from(t.select.childNodes),l=document.createElement("div");l.classList.add("text-selector-content"),s.forEach(e=>{if(e.innerText){let s=document.createElement("div");e.disabled?s.classList="text-selector-selection text-selector-disabled":e.selected?s.classList="text-selector-selection text-selector-selected":s.classList="text-selector-selection text-selector-normal",s.innerText=e.innerText,e.disabled||s.addEventListener("click",function(){null!=(ex=t.selector.getElementsByClassName("text-selector-selected"))[0]&&(ex[0].classList="text-selector-selection text-selector-normal"),v=this.innerText,this.classList="text-selector-selection text-selector-selected",e.selected=!0,t.text.innerText=v}),l.appendChild(s)}}),t.selector.appendChild(l);try{$(t.selector).fadeIn(100)}catch(i){t.selector.style.display="block"}textSelector.calculatePosition(t,this)}},calculatePosition:function(e,t){let s=t.offsetLeft,l=t.offsetTop;l>e.selector.offsetHeight?(e.selector.style.paddingBottom=t.offsetHeight+10+"px",e.selector.style.top=l-e.selector.offsetHeight+t.offsetHeight+"px",e.selector.style.paddingTop="10px"):(e.selector.style.paddingBottom="10px",e.selector.style.top=l+"px",e.selector.style.paddingTop=t.offsetHeight+10+"px"),s>e.selector.offsetWidth/2+10?e.selector.style.left=s+t.offsetWidth/2-e.selector.offsetWidth/2+"px":e.selector.style.left=s+"px"}};
\ No newline at end of file