i got this error on input.value and input.length:
scripts.js:151 Uncaught TypeError: Cannot read property 'length' of
undefined
I'm trying to apply a currency mask to an input, but I'm getting errors
function formatNumber(n) {
// format number 1000000 to 1,234,567
return n.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
function formatCurrency(input, blur) {
// appends $ to value, validates decimal side
// and puts cursor back in right position.
// get input value
var input_val = input.value;
console.log(input)
// don't validate empty input
if (input_val === "") { return; }
// original length
var original_len = input_val.length;
// initial caret position
var caret_pos = input.getAttribute("selectionStart");
// check for decimal
if (input_val.indexOf(".") >= 0) {
// get position of first decimal
// this prevents multiple decimals from
// being entered
var decimal_pos = input_val.indexOf(".");
// split number by decimal point
var left_side = input_val.substring(0, decimal_pos);
var right_side = input_val.substring(decimal_pos);
// add commas to left side of number
left_side = formatNumber(left_side);
// validate right side
right_side = formatNumber(right_side);
// On blur make sure 2 numbers after decimal
if (blur === "blur") {
right_side += "00";
}
// Limit decimal to only 2 digits
right_side = right_side.substring(0, 2);
// join number by .
input_val = "$" + left_side + "." + right_side;
} else {
// no decimal entered
// add commas to number
// remove all non-digits
input_val = formatNumber(input_val);
input_val = "$" + input_val;
// final formatting
if (blur === "blur") {
input_val += ".00";
}
}
// send updated string to input
input.value(input_val);
// put caret back in the right position
var updated_len = input_val.length;
caret_pos = updated_len - original_len + caret_pos;
input[0].setSelectionRange(caret_pos, caret_pos);
}
(function initalize() {
// IIFE method
let input = document.querySelector("input[data-type='currency']")
input.addEventListener("keyup", () => {
formatCurrency(this);
})
input.addEventListener("keyup", () => {
formatCurrency(this, "blur");
})
})();
.textfield_label {
font-family: "Poppins";
color: #a3a3a3;
margin-bottom: 10px;
text-transform: uppercase;
letter-spacing: 1.5px;
}
.material-textfield {
font-family: "Poppins";
position: relative;
margin-bottom: 30px;
color: #a3a3a3;
}
.material-textfield label {
font-family: "Poppins";
position: absolute;
font-size: 1.2rem;
left: 0;
top: 50%;
transform: translateY(-50%);
background: #fff;
border-radius: 5px;
color: gray;
padding: 0 0.3rem;
margin: 0 0.5rem;
transition: 0.1s ease-out;
transform-origin: left top;
pointer-events: none;
}
.material-textfield input {
font-family: "Poppins";
width: 100%;
font-size: 1rem;
outline: none;
border: 1px solid #ffb24f;
border-radius: 5px;
background: #00416a;
padding: 1rem 0.7rem;
color: #ffb24f;
transition: 0.1s ease-out;
}
.material-textfield::before {
background: none;
border: 1px solid #ffb24f;
content: "";
display: block;
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
pointer-events: none;
}
.material-textfield input:focus {
border-color: #ebb76e;
}
.material-textfield input:focus + label {
color: #ebb76e;
top: 0;
transform: translateY(-50%) scale(0.9);
background: linear-gradient(
180deg,
rgba(235, 235, 235, 1) 0%,
rgba(235, 235, 235, 1) 50%,
rgba(255, 255, 255, 1) 50%,
rgba(255, 255, 255, 1) 100%
);
}
.material-textfield input::placeholder{
color:#ebb76e;
}
<div class="input_renda">
<h3 class="textfield_label">
value
</h3>
<div class="material-textfield">
<input type="text" name="currency-field" id="currency-field" pattern="^\$\d{1,3}(,\d{3})*(\.\d+)?$"
value="" data-type="currency" placeholder=" $1,000,000.00" />
</div>
</div>
but I don't know why the input. value is not working,
why do I get the element with the query selector
If anyone can help me with this I'm happy
You can use the following function to mask currencies numbers:
export const moneyMask = (value: string) => {
value = value.replace('.', '').replace(',', '').replace(/\D/g, '')
const options = { minimumFractionDigits: 2 }
const result = new Intl.NumberFormat('pt-BR', options).format(
parseFloat(value) / 100
)
console.log(result)
return 'R$ ' + result
}
This bug is caused by the improper use of the this keyword inside:
let input = document.querySelector("input[data-type='currency']")
input.addEventListener("keyup", () => {
formatCurrency(this);
})
Here you're trying to pass the input object as a parameter to the formatCurrency function but this doesn't refer to it. To get a reference you need to use the special e parameter for the callback function and access it using e.target which holds a reference to the object that caused the event.
e.g.
let input = document.querySelector("input[data-type='currency']")
input.addEventListener("keyup", (e) => {
formatCurrency(e.target);
})
Furthermore, later on in your script you're trying to assign a value back to the input object by:
input.value(input_val);
With the above you're actually trying to call a function named value() - to change the .value property of your object you need to do it like this:
input.value=input_val;
Simple demo of usage of the built-in currency mode of .toLocaleString().
currencyfield.addEventListener("input", format, false)
function format (){
let val = +currencyfield.value;
document.querySelector(".textfield_label").textContent = val.toLocaleString('fullwide', {maximumFractionDigits:2, style:'currency', currency:'USD', useGrouping:true})
}
<div class="input_renda">
<h3 class="textfield_label">$0.00</h3>
<div class="material-textfield">
<input type="text" name="currency-field" id="currencyfield" value="" data-type="currency" placeholder=" $1,000,000.00" />
</div>
</div>
let input = document.getElementsByClassName("productPrice");
console.log(input.length);
for (var i = 0; i < input.length; i++) {
input[i].addEventListener("keyup", (e) => { formatCurrency(e.target); });
input[i].addEventListener("keypress", (e) => { formatCurrency(e.target); });
}
function formatNumber(n) {
// format number 1234567,89 to 1 234 567,89
return n.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, " ")
}
function formatCurrency(input) {
var input_val = input.value;
if (input_val === "") { return; }
var original_len = input_val.length;
var caret_pos = input.selectionStart;
if (input_val.indexOf(",") >= 0) {
var decimal_pos = input_val.indexOf(",");
var left_side = input_val.substring(0, decimal_pos);
var right_side = input_val.substring(decimal_pos);
left_side = formatNumber(left_side);
right_side = formatNumber(right_side);
right_side = right_side.substring(0, 2);
input_val = left_side + "," + right_side;
} else {
input_val = formatNumber(input_val);
}
input.value = input_val;
var updated_len = input_val.length;
caret_pos = updated_len - original_len + caret_pos;
input.setSelectionRange(caret_pos, caret_pos);
}
<input type="text" class="productPrice">
<br>
<br><input type="text" class="productPrice">
<br>
<br><input type="text" class="productPrice">
<br>
<br><input type="text" class="productPrice">
<br>
<br>
Related
I have a string of email addresses separated by a delimiter ';' and want to show all text as it is. Also want to clip any overflow text over one line and then show +count of emails ids remaining that user did not get to see(driven by some # and ; character logic). Is there any way to know how many characters are retained/ or even removed from the HTML text after the it is clipped ?
I don't know what is your criteria exactly, but here is an example of how it can be calculated:
var span = document.getElementById("text");
var countSpan = document.getElementById("count");
var orig = span.innerText;
var vis = orig;
while(vis.length && span.scrollWidth > parseFloat(window.getComputedStyle(span).width))
{
vis = vis.slice(0,-1);
span.innerText = vis + "....";
}
span.innerText = orig;
var visibleText = vis;
var truncatedText = orig.replace(new RegExp("^" + vis.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), "");
var visibleCleanLessText;
var visibleCleanMoreText;
var truncatedCleanLessText;
var truncatedCleanMoreText;
if (truncatedText === "" || truncatedText.substr(0, 1) == ";")
{
visibleCleanLessText = vis;
visibleCleanMoreText = vis;
truncatedCleanLessText = truncatedText.substr(1);
truncatedCleanMoreText = truncatedCleanLessText;
}
else
{
var m = vis.match(/;([^;]*)$/);
visibleCleanLessText = m ? vis.replace(/;[^;]*$/, "") : "";
visibleCleanMoreText = vis + (truncatedText.match(/^([^;]*);/) || ["",""])[1];
truncatedCleanMoreText = (m ? m[1] : vis) + truncatedText;
truncatedCleanLessText = truncatedText.replace(/^[^;]*;/, "");
}
var truncatedCount = truncatedCleanMoreText === "" ? 0 : truncatedCleanMoreText.split(";").length;
if (truncatedCount)
{
countSpan.innerText = "+" + truncatedCount;
span.title = orig;
}
console.log("orig ", orig);
console.log("visible ", vis);
console.log("truncated ", truncatedText);
console.log("visibleCleanLess ", visibleCleanLessText);
console.log("truncatedCleanMore", truncatedCleanMoreText);
console.log("visibleCleanMore ", visibleCleanMoreText);
console.log("truncatedCleanLess", truncatedCleanLessText);
div
{
vertical-align: middle;
}
.truncate
{
width: 300px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
}
.count:empty
{
display: none;
}
.count
{
display: inline-block;
position: relative;
font-family: monospace;
font-size: 90%;
left: -0.5em;
border: 1px solid black;
border-radius: 0.3em;
padding: 0.1em;
}
<div>
<span id="text" class="truncate">email1#example.com;email2#example.com;email3#example.com;email4#example.com</span>
<span id="count" class="count"></span>
</div>
when input yyyyMMdd format in textbox, that will automatically change to yyyy/MM/dd format for example: if your type 20180428, that will change to 2018/04/28
Utilizing built-in JavaScript functions such as parseInt to get the input element from a string to an integer, you are able to apply logic with helper functions to get to the date formatting you desire. e.g. if the day value is greater than 31, default return 1 instead to automatically guide the user from inputting a day more than 31
MDN JavaScript parseInt()
Afterwards, with the use of Regex, you can manipulate the user's initial data input (YYYYmmDD) to a format you want to change it to (YYYY/mm/DD).
Regex
I found an online tutorial outlining this very process below:
Auto-format Date Input by Envato Tuts+
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0)) && num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('input', function(e) {
this.type = 'text';
var input = this.value;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + ' / ' : v;
});
this.value = output.join('').substr(0, 14);
});
date.addEventListener('blur', function(e) {
this.type = 'text';
var input = this.value;
var values = input.split('/').map(function(v, i) {
return v.replace(/\D/g, '')
});
var output = '';
if (values.length == 3) {
var year = values[2].length !== 4 ? parseInt(values[2]) + 2000 : parseInt(values[2]);
var month = parseInt(values[0]) - 1;
var day = parseInt(values[1]);
var d = new Date(year, month, day);
if (!isNaN(d)) {
document.getElementById('result').innerText = d.toString();
var dates = [d.getMonth() + 1, d.getDate(), d.getFullYear()];
output = dates.map(function(v) {
v = v.toString();
return v.length == 1 ? '0' + v : v;
}).join(' / ');
};
};
this.value = output;
});
html {
box-sizing: border-box;
font-family: 'PT Sans', sans-serif;
-webkit-font-smoothing: antialiased;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
background-color: #f3f3f3;
}
form {
width: 100%;
max-width: 400px;
margin: 60px auto;
}
form input {
font-size: 30px;
padding: 0 20px;
border: 2px solid #ccc;
width: 100%;
color: #666;
line-height: 3;
border-radius: 7px;
font-family: 'PT Sans', sans-serif;
font-weight: bold;
}
form input:focus {
outline: 0;
}
form input.error {
border-color: #ff0000;
}
form label.error {
background-color: #ff0000;
color: #fff;
padding: 6px;
font-size: 11px;
}
label {
color: #999;
display: block;
margin-bottom: 10px;
text-transform: uppercase;
font-size: 18px;
font-weight: bold;
letter-spacing: 0.05em
}
form small {
color: #888;
font-size: 1em;
margin-top: 10px;
display: block;
align-self: ;
}
<form id="form" method="post" action="">
<label for="amount">Date</label>
<input type="text" id="date" />
<small>Enter date as Month / Day / Year</small>
</form>
The following code converts text into equal paragraphs, based on the users input character amount.
Is it possible for the input box to calculate the amount of words for each paragraph instead of being based on the character amount?
JSFiddle
If an updated fiddle could please be provided, would be much appreciated, as I am still new to coding.
Thank You!
$(function() {
$('select').on('change', function() {
//Lets target the parent element, instead of P. P will inherit it's font size (css)
var targets = $('#content'),
property = this.dataset.property;
targets.css(property, this.value);
sameheight('#content p');
}).prop('selectedIndex', 0);
});
var btn = document.getElementById('go'),
textarea = document.getElementById('textarea1'),
content = document.getElementById('content');
chunkSize = 100;
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
content.addEventListener('paste', handlePaste);
function initialDistribute() {
custom = parseInt(document.getElementById("custom").value);
chunkSize = (custom>0)?custom:chunkSize;
var text = textarea.value;
while (content.hasChildNodes()) {
content.removeChild(content.lastChild);
}
rearrange(text);
}
function rearrange(text) {
var chunks = splitText(text, false);
chunks.forEach(function(str, idx) {
para = document.createElement('P');
para.classList.add("Paragraph_CSS");
para.setAttribute('contenteditable', true);
para.textContent = str;
content.appendChild(para);
});
sameheight('#content p');
}
function handleKey(e) {
var para = e.target,
position,
key, fragment, overflow, remainingText;
key = e.which || e.keyCode || 0;
if (para.tagName != 'P') {
return;
}
if (key != 13 && key != 8) {
redistributeAuto(para);
return;
}
position = window.getSelection().getRangeAt(0).startOffset;
if (key == 13) {
fragment = para.lastChild;
overflow = fragment.textContent;
fragment.parentNode.removeChild(fragment);
remainingText = overflow + removeSiblings(para, false);
rearrange(remainingText);
}
if (key == 8 && para.previousElementSibling && position == 0) {
fragment = para.previousElementSibling;
remainingText = removeSiblings(fragment, true);
rearrange(remainingText);
}
}
function handlePaste(e) {
if (e.target.tagName != 'P') {
return;
}
overflow = e.target.textContent + removeSiblings(fragment, true);
rearrange(remainingText);
}
function redistributeAuto(para) {
var text = para.textContent,
fullText;
if (text.length > chunkSize) {
fullText = removeSiblings(para, true);
}
rearrange(fullText);
}
function removeSiblings(elem, includeCurrent) {
var text = '',
next;
if (includeCurrent && !elem.previousElementSibling) {
parent = elem.parentNode;
text = parent.textContent;
while (parent.hasChildNodes()) {
parent.removeChild(parent.lastChild);
}
} else {
elem = includeCurrent ? elem.previousElementSibling : elem;
while (next = elem.nextSibling) {
text += next.textContent;
elem.parentNode.removeChild(next);
}
}
return text;
}
function splitText(text, useRegex) {
var chunks = [],
i, textSize, boundary = 0;
if (useRegex) {
var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
chunks = text.match(regex) || [];
} else {
for (i = 0, textSize = text.length; i < textSize; i = boundary) {
boundary = i + chunkSize;
if (boundary <= textSize && text.charAt(boundary) == ' ') {
chunks.push(text.substring(i, boundary));
} else {
while (boundary <= textSize && text.charAt(boundary) != ' ') {
boundary++;
}
chunks.push(text.substring(i, boundary));
}
}
}
return chunks;
}
#text_land {
border: 1px solid #ccc;
padding: 25px;
margin-bottom: 30px;
}
textarea {
width: 95%;
}
label {
display: block;
width: 50%;
clear: both;
margin: 0 0 .5em;
}
label select {
width: 50%;
float: right;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: monospace;
font-size: 1em;
}
h3 {
margin: 1.2em 0;
}
div {
margin: 1.2em;
}
textarea {
width: 100%;
}
button {
padding: .5em;
}
p {
/*Here the sliles for OTHER paragraphs*/
}
#content p {
font-size: inherit;
/*So it gets the font size set on the #content div*/
padding: 1.2em .5em;
margin: 1.4em 0;
border: 1px dashed #aaa;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Import Text below, then press the button</h3>
<textarea id="textarea1" placeholder="Type text here, then press the button below." rows="5">
</textarea>
<input style="width:200px;" id="custom" placeholder="Custom Characters per box">
<br>
<button style="width:200px;" id="go">Divide Text into Paragraphs</button>
</div>
<div>
<h3 align="right">Divided Text Will Appear Below:</h3>
<hr>
<div id="content"></div>
</div>
How about this? It uses jQuery, but as you used the library in your original submission, I hope that won't be an issue:
HTML
<textarea id="input"></textarea>
<br/>
<button id='divide'>Divide</button>
<div id="paras"></div>
CSS
#input {
resize: none;
height: 200px;
width: 100%;
}
JS
$(function() {
$("#divide").click(function() {
var text = $("#input").val();
var wpp = 10 // words per paragraph
var words = text.split(" ");
var paras = [];
for (i = 0; i < words.length; i += wpp) {
paras.push(words.slice(i, i + wpp).join(" "));
}
$.each(paras, function(i, para) {
$("#paras").append("<p>" + para + "</p>");
});
});
})
JSFiddle
The following fiddle converts texts into paragraphs and the problem is the JQuery function attribute chunkSize = 100; currently defines the amount of characters for each divided paragraph to contain.
Is it possible for the user to be able to change this dynamically through the use of an <input> and <button> where the user would be able to type their desired characters for each dynamic paragraph and apply it?
Fiddle
If a new fiddle could please be provided, it would be very much appreciated, as I am still new to coding.
Thank You!
$(function() {
$('select').on('change', function() {
//Lets target the parent element, instead of P. P will inherit it's font size (css)
var targets = $('#content'),
property = this.dataset.property;
targets.css(property, this.value);
sameheight('#content p');
}).prop('selectedIndex', 0);
});
var btn = document.getElementById('go'),
textarea = document.getElementById('textarea1'),
content = document.getElementById('content'),
chunkSize = 100;
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
content.addEventListener('paste', handlePaste);
function initialDistribute() {
var text = textarea.value;
while (content.hasChildNodes()) {
content.removeChild(content.lastChild);
}
rearrange(text);
}
function rearrange(text) {
var chunks = splitText(text, false);
chunks.forEach(function(str, idx) {
para = document.createElement('P');
para.classList.add("Paragraph_CSS");
para.setAttribute('contenteditable', true);
para.textContent = str;
content.appendChild(para);
});
sameheight('#content p');
}
function handleKey(e) {
var para = e.target,
position,
key, fragment, overflow, remainingText;
key = e.which || e.keyCode || 0;
if (para.tagName != 'P') {
return;
}
if (key != 13 && key != 8) {
redistributeAuto(para);
return;
}
position = window.getSelection().getRangeAt(0).startOffset;
if (key == 13) {
fragment = para.lastChild;
overflow = fragment.textContent;
fragment.parentNode.removeChild(fragment);
remainingText = overflow + removeSiblings(para, false);
rearrange(remainingText);
}
if (key == 8 && para.previousElementSibling && position == 0) {
fragment = para.previousElementSibling;
remainingText = removeSiblings(fragment, true);
rearrange(remainingText);
}
}
function handlePaste(e) {
if (e.target.tagName != 'P') {
return;
}
overflow = e.target.textContent + removeSiblings(fragment, true);
rearrange(remainingText);
}
function redistributeAuto(para) {
var text = para.textContent,
fullText;
if (text.length > chunkSize) {
fullText = removeSiblings(para, true);
}
rearrange(fullText);
}
function removeSiblings(elem, includeCurrent) {
var text = '',
next;
if (includeCurrent && !elem.previousElementSibling) {
parent = elem.parentNode;
text = parent.textContent;
while (parent.hasChildNodes()) {
parent.removeChild(parent.lastChild);
}
} else {
elem = includeCurrent ? elem.previousElementSibling : elem;
while (next = elem.nextSibling) {
text += next.textContent;
elem.parentNode.removeChild(next);
}
}
return text;
}
function splitText(text, useRegex) {
var chunks = [],
i, textSize, boundary = 0;
if (useRegex) {
var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
chunks = text.match(regex) || [];
} else {
for (i = 0, textSize = text.length; i < textSize; i = boundary) {
boundary = i + chunkSize;
if (boundary <= textSize && text.charAt(boundary) == ' ') {
chunks.push(text.substring(i, boundary));
} else {
while (boundary <= textSize && text.charAt(boundary) != ' ') {
boundary++;
}
chunks.push(text.substring(i, boundary));
}
}
}
return chunks;
}
#text_land {
border: 1px solid #ccc;
padding: 25px;
margin-bottom: 30px;
}
textarea {
width: 95%;
}
label {
display: block;
width: 50%;
clear: both;
margin: 0 0 .5em;
}
label select {
width: 50%;
float: right;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: monospace;
font-size: 1em;
}
h3 {
margin: 1.2em 0;
}
div {
margin: 1.2em;
}
textarea {
width: 100%;
}
button {
padding: .5em;
}
p {
/*Here the sliles for OTHER paragraphs*/
}
#content p {
font-size: inherit;
/*So it gets the font size set on the #content div*/
padding: 1.2em .5em;
margin: 1.4em 0;
border: 1px dashed #aaa;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Import Text below, then press the button</h3>
<textarea id="textarea1" placeholder="Type text here, then press the button below." rows="5">
</textarea>
<input style="width:200px;" placeholder="Custom Characters per box">
<button>
Go
</button>
<br>
<button style="width:200px;" id="go">Divide Text into Paragraphs</button>
</div>
<div>
<h3 align="right">Divided Text Will Appear Below:</h3>
<hr>
<div id="content"></div>
</div>
Give an id for your input.
<input id="custom" placeholder="Custom Characters per box" style="width:200px;">
Add below code into initialDistribute function.
custom = parseInt(document.getElementById("custom").value); //Get value of the input.
chunkSize = (custom>0)?custom:100; //If Custom value is more than `0`, take that as `chunkSize` value else `100`
See Fiddle
You can use input type="number" element, button element; set chunkSize to input type="number" valueAsNumber property at click of button
html
<label>chunkSize:<input class="chunkSize" type="number" /></label>
<button class="chunkSize">
Set chunkSize
</button>
javascript
$("button.chunkSize").click(function(e) {
var _chunkSize = $("input.chunkSize")[0].valueAsNumber;
chunkSize = _chunkSize;
})
jsfiddle https://jsfiddle.net/csz0ggsw/11/
So, what I am going to do with the input tag is to insert as many as email address inside it.
<input type="text" name="email-tags"/>
To make it more user-friendly, I want to highlight each-email which is typed inside it with blue color, it looks similar like a tag in SO question which also has x button to delete the tag.
Can anybody please help me how to do this with javascript?
Thanks in advance.
This block of code actually does what you need. It's pretty advanced. I hope it suits your needs. document.getElementById("test").value contains the email addresses in an array in this example.
function setInputEmailToExtendedInput()
{
var inputs = document.querySelectorAll("input[data-type='email']");
Array.prototype.slice.call(inputs).forEach(function(element){
var node = new emailInput();
if (element.id)
{
node.container.id = element.id;
}
if (element.className)
{
node.container.className = element.className;
}
element.parentElement.replaceChild(node.container, element);
});
}
function emailInput() {
this.container = document.createElement("div");
this.container.input = document.createElement("input");
this.container.input.type = "text";
this.container.style.overflowY = "auto";
this.container.input.className = "email_input";
this.container.appendChild(this.container.input);
this.container.input.addEventListener("keydown", checkKeyUpOnEmailInputDisable(this), false);
this.evaluateTag = evaluateEmailFunction;
this.deleteTag = deleteEmailFunction;
this.container.input.addEventListener("paste", emailEvaluateOnChange(this), false);
Object.defineProperty(this, "value", {
value: [],
enumerable: false
});
Object.defineProperty(this, "placeholder", {
get: function() {
this.container.input.placeholder;
},
set: function(value) {
this.container.input.placeholder = value;
},
enumerable: false
});
}
function emailEvaluateOnChange(obj, e) {
return function(e) {
obj.evaluateTag(e.target.value);
}
}
function checkKeyUpOnEmailInputDisable(obj, e) {
return function(e) {
if (e.keyCode == 13 || e.keyCode == 32) //either enter or space
{
obj.evaluateTag(e.target.value);
return false;
} else if (e.keyCode == 8) //backspace
{
if (e.target.value.length == 0 && obj.value.length > 0) //length of the input is zero.
{
//delete tag.
obj.deleteTag();
return true;
}
} else if (e.keyCode == 27) //escape
{
//hide the input helper and blur the input.
e.target.blur();
e.preventDefault();
return false;
}
};
}
function deleteEmailFunction(tag) {
if (!tag) {
//delete the last tag
var tag = this.value.length - 1;
}
this.container.removeChild(this.container.querySelectorAll(".email_element")[tag]);
this.value.splice(tag, 1);
if (this.value.length > 0) {
var marginNode = parseInt(getComputedStyle(this.container.children[0]).getPropertyValue("margin-right"));
var width = parseInt(this.container.children[0].offsetLeft) * 2; //default padding
for (var i = 0; i < this.value.length; ++i) {
//calculate the width of all tags.
width += parseInt(this.container.children[i].offsetWidth) + marginNode;
}
this.container.input.style.width = (this.container.offsetWidth - width) - 20 + "px";
} else {
this.container.input.style.width = "100%";
}
this.container.input.focus();
}
function createEmail(value) {
var node = document.createElement("span");
node.className = "email_element";
node.innerHTML = value;
return node;
}
function evaluateEmailFunction(tagValue) {
if (tagValue.match(/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/ig)) {
//email is valid add
var node = createEmail(tagValue.trim());
this.container.insertBefore(node, this.container.input);
this.value.push(tagValue);
var marginNode = parseInt(getComputedStyle(node).getPropertyValue("margin-right"));
var width = parseInt(this.container.children[0].offsetLeft) * 2; //default padding
for (var i = 0; i < this.value.length; ++i) {
//calculate the width of all tags.
width += parseInt(this.container.children[i].offsetWidth) + marginNode;
}
//set the width of the tag input accordingly.
this.container.input.style.width = (this.container.offsetWidth - width) - 20 + "px";
this.container.input.value = "";
this.container.input.focus();
}
}
RegExp.escape = function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
window.addEventListener("load", function(){setInputEmailToExtendedInput()}, false);
div.email_builder {
width: 500px;
height: 36px;
background-color: #ffffff;
border: 1px solid #777777;
box-sizing: border-box;
}
input.email_input {
padding: 8px 8px 8px 8px;
border: 0px solid transparent;
width: 100%;
box-sizing: border-box;
font-size: 11pt;
}
span.email_element {
display: inline-block;
padding: 6px 2px 6px 2px;
margin-right: 4px;
color: #0059B3;
font-size: 10pt;
white-space: nowrap;
cursor: pointer;
box-sizing: border-box;
}
span.email_element > span.email_remove_button {
color: #000000;
font-size: 10pt;
white-space: nowrap;
cursor: pointer;
padding-left: 12px;
font-size: 14px;
font-weight: bold;
}
span.email_element > span.email_remove_button:hover {
color: #660000;
font-size: 10pt;
white-space: nowrap;
cursor: pointer;
padding-left: 12px;
font-size: 14px;
font-weight: bold;
}
<input type="text" class="email_builder" id="test" data-type="email" />
how about this:
<from id="form" action="">
<span id="emailInput">
<input type="text" name="email-tags"/>
</span>
<span id="test"></span>
</form>
function isValidEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
$(function(){
$('input').keydown(function(event){
$input = $(this);
$emailInput = $("#emailInput");
$("#test").html(event.which);
switch(event.which){
//stop for "," ";" and " "
case 188:
case 186:
case 32:
currentEmail = $.trim($input.val());
if(isValidEmail(currentEmail)){
$address = $("<span>");
$address.addClass("emailAddress");
$address.text(currentEmail);
$close=$('<span>');
$close.addClass("close").text("x");
$address.append($close);
$input.val("");
$input.before($address);
}
}
});
$("#emailInput").on("click",".close",function(){
$(this).parent().remove();
});
});
see here:
http://fiddle.jshell.net/wryjde3z/