Array in Input text Field using JavaScript - javascript

I am new to JS Community and I am practicing JS. I have Input text field where User will enter the array like 1,2-5,6-9,10,12,13-15 . What I am trying is to expand this array like 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
<input class="inputC" id="inputC" type="text" value="" placeholder="Select Control" required />
JS I tried
var items = $('#inputC').val().split(",");
for (var i in items) {
console.log(items[i]);
}

Note: You should specify the logic of adding 11 in the output based on the given input.
You should split on - as well which you can do inside a map call back function.
Demo:
var items = $('#inputC').val().split(',');
items = items.flatMap(i =>{
var list = [];
i = i.split('-');
if(i.length > 1){
for (var j = i[0]; j <= i[1]; j++) {
list.push(+j);
}
}
else{
list.push(+i[0]);
}
return list;
});
console.log(items);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="inputC" id="inputC" value="1,2-5,6-9,10,12,13-15" type="text" value="" placeholder="Select Control" required />

let str='1,2-5,6-9,10,12,13-15';
str.split(',').map((e)=>{
if(e.includes('-')){
const values = e.split('-');
const end = parseInt(values[1]);
let start = parseInt(values[0]);
while(start < end){
console.log(start);start++;
}
}else{
console.log(parseInt(e))
}
})

This is a great scenario in which you want to create a small derived webcomponent that does just what you need:
<input is="array-input" />
class ArrayInput extends HTMLInputElement {
get value() {
let inter = super.value.split(',').map(el => el.trim());
let ret = [];
for (const el of inter) {
const [ start, end ] = el.split('-').map(Number);
if (isNaN(start)) continue;
if (!end || start > end) {
ret.push(start);
} else if (start === end) {
ret.push(start)
} else if (start < end) {
for (let i = start; i <= end; i++) {
ret.push(i);
}
}
}
return [...new Set(ret)].sort();
}
}
customElements.define('array-input', ArrayInput, {
extends: 'input'
});
<input is="array-input" onchange="console.log(this.value)" />

Related

adding a class and an id to and elements created by loop js

I am trying here to add a class and an id to the elements that will be created (div or section) ,
the problem is when I tried to make a variable that contains the elements that will be created but the code didn't work
let numberOfElements = document.getElementsByTagName("input")[0].value;
document.getElementsByTagName("input")[0].onchange = function () {
numberOfElements = document.getElementsByTagName("input")[0].value;
}
///
let theTextInput = document.getElementsByTagName("input")[1].value;
document.getElementsByTagName("input")[1].onchange = function () {
theTextInput = document.getElementsByTagName("input")[1].value
}
let theSubmit = document.getElementsByName("create")[0];
document.forms[0].onsubmit = function (e) {
// stop submitting
e.preventDefault();
};
theSubmit.onclick = function () {
if (document.getElementsByTagName("select")[0].value === "Div") {
for (let i = 1; i <= numberOfElements; i++) {
return document.body.appendChild(document.createElement("div")).innerHTML = theTextInput;;
}
} else if (document.getElementsByTagName("select")[0].value !== "Div"){
for (let i = 1; i <= numberOfElements; i++) {
return document.body.appendChild(document.createElement("section")).innerHTML = theTextInput;;
}
}
};
<body>
<form action="">
<input type="number" name="elements" class="input" placeholder="Number Of Elements" value="1"/>
<input type="text" name="texts" class="input" placeholder="Elements Text" />
<select name="type" class="input" >
<option value="Div">Div</option>
<option value="Section">Section</option>
</select>
<input type="submit" name="create" value="Create" />
<div class="results"></div>
</form>
<!-- /////////// -->
<script src="DOM.js"></script>
</body>
First of all, you can use variable for created element and update whatever property/attribute required on that variable. At the same time remove the return on creating elements to continue create the rest. The return will stop once first element created:
const divElm = document.createElement('div');
Now, you can modify that element as required then add to the DOM:
divElm.innerHTML = theTextInput;
divElm.classList.add('new-class');
document.body.append(divElm);
Your code can be simplified by getting the required number and text values from inputs only when you need to create the elements. The inputs change events aren't required. Just merge the submit and click events into a single one, then add the get required values inside it:
document.forms[0].onsubmit = function (e) {
// stop submitting
e.preventDefault();
const numberOfElements = document.getElementsByTagName("input")[0].value;
const theTextInput = document.getElementsByTagName("input")[1].value;
if (document.getElementsByTagName("select")[0].value === "Div") {
for (let i = 1; i <= numberOfElements; i++) {
const divElm = document.createElement('div');
divElm.innerHTML = theTextInput;
divElm.classList.add('new');
document.body.append(divElm);
}
} else if (document.getElementsByTagName("select")[0].value !== "Div") {
for (let i = 1; i <= numberOfElements; i++) {
// Same code as above but with section
...
}
}
};
Even with that, there's still room for improvement. So, try to split your statements into multiple lines. First, store queried elements into variables/arrays then use them to manipulate the element. That will also reduce the number of times you query/get those elements from the DOM

event listener working with getElementByID but not with querySelectorAll

as per the post title, I have these scripts:
let campolim = document.getElementById("province");
campolim.addEventListener("keyup", () => {
if (campolim.value.length > 3) {
campolim.value = campolim.value.slice(0, 3);
}
});
//----------------------------------------------------//
let campilim = document.querySelectorAll("limitme");
for (var i = 0; i < campilim.length; i++) {
campilim[i].addEventListener("keyup", () => {
if (campolim[i].value.length > 3) {
campolim[i].value = campolim[i].value.slice(0, 3);
}
});
}
The scripts should do the same thing (limit the input filds to 3 chars). The first one is working properly, but if I want to capture all fields with limitme class, the script returns that cannot find the length of a unknown element.
Why? What am I missing?
This is the html:
<input type="text" class="limitme form-input" id="province" name="province" value="" placeholder="provincia" required="">
<input type="text" class="limitme form-input" id="cap" name="cap" value="" placeholder="cap" required="">
<input type="submit" >
Thanks.
I think it was just a typo in campilim (campolim)
let campolim = document.getElementById("province");
campolim.addEventListener("keyup", () => {
if (campolim.value.length > 3) {
campolim.value = campolim.value.slice(0, 3);
}
});
//----------------------------------------------------//
let campilim = document.querySelectorAll(".limitme");
console.log(campilim)
for (let i = 0; i < campilim.length; i++) {
campilim[i].addEventListener("keyup", () => {
if (campilim[i].value.length > 3) {
campilim[i].value = campilim[i].value.slice(0, 3);
}
});
}
The code works fine with typo fixed.
u replace second section of your code with
let campilim = document.querySelectorAll(".limitme");
for (var i = 0; i < campilim.length; i++) {
campilim[i].addEventListener("keyup", (e) => {
let element=e.currentTarget;
if (element.value.length > 3) {
element.value = element.value.slice(0, 3);
}
});
}
when use addEventListener in input parameter send e for event and use in function for detect change . for find what is source element u must use e.currentTarget code.

Getting comma separated values into input field

I am struggling already for some time to create script that deletes and adds values to field. The point is that when I click on div - there will be images inside, it will copy part of its class to field, or remove if it's already copied there. All the values in field input_8_3 need to be comma separated without spaces except the last one and in case there is only one value there shouldn't be any comma. The same with field input_8_4, but there I need only erased values.
In addition I need divs to change class on click, one click to add class, another to remove it, but this is how far could I get with my issue.
I need this for deleting images in custom field in Wordpresses frontend. input_8_3 goes to meta and input_8_4 to array in function to delete chosen images.
Thanks in advance!
(function($){
$('.thumbn').click(function() {
var text = $(this).attr("id").replace('img-act-','')+',';
var oldtext = $('#input_8_3').val();
$('#input_8_3').val(text+oldtext);
});
})(jQuery);
(function($){
$('div.thumbn').click(function() {
$(this).removeClass('chosen-img');
});
})(jQuery);
(function($){
$('.thumbn').click(function() {
$(this).addClass('chosen-img');
});
})(jQuery);
.thumbn {
width: 85px;
height: 85px;
background: #7ef369;
float: left;
margin: 10px;
}
.chosen-img.thumbn{background:#727272}
input{width:100%}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text" id="input_8_3" readonly="" value="3014,3015,3016,3017,3018" class="form-control data_lable">
<input type="text" id="input_8_4" readonly="" value="" class="form-control data_lable">
<div class="user-profile-avatar user_seting st_edit">
<div>
<div class="thumbn" id="img-act-3014"></div>
<div class="thumbn" id="img-act-3015"></div>
<div class="thumbn" id="img-act-3016"></div>
<div class="thumbn" id="img-act-3017"></div>
<div class="thumbn" id="img-act-3018"></div>
</div>
</div>
EDIT: I changed value of input_8_3. All the numbers in img-act-**** and values in input_8_3 are the same on load.
I've made a JS of it working.
https://jsfiddle.net/jatwm8sL/6/
I've added these:
var array = [3008,3009,3010,3011,3012];
$("#input_8_3").val(array.join());
and changed your click functions to this
var array = [3008,3009,3010,3011,3012];
var array1 = [];
$("#input_8_3").val(array.join());
(function($){
$('div.thumbn').click(function() {
var text = $(this).attr("id").replace('img-act-','');
var oldtext = $('#input_8_3').val();
if ($(this).hasClass('chosen-img'))
{
$('#input_8_3').val(text+oldtext);
var index = array.indexOf(text);
if (index !== -1)
{
array.splice(index, 1);
}
array1.push(text);
$(this).removeClass('chosen-img');
}
else
{
array.push(text);
var index = array1.indexOf(text);
if (index !== -1)
{
array1.splice(index, 1);
}
$(this).addClass('chosen-img');
}
$("#input_8_3").val(array.join());
$("#input_8_4").val(array1.join());
console.log(array1);
});
})(jQuery);
Basically, you need to check if it has a class and then remove if it has and add it if it doesn't.
Also, it's better to use a javascript array than to play around with html values as you change javascript arrays while HTML should really just display them.
If anything is unclear, let me know and I'll try to explain myself better
var transformNumbers = (function () {
var numerals = {
persian: ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"],
arabic: ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"]
};
function fromEnglish(str, lang) {
var i, len = str.length, result = "";
for (i = 0; i < len; i++)
result += numerals[lang][str[i]];
return result;
}
return {
toNormal: function (str) {
var num, i, len = str.length, result = "";
for (i = 0; i < len; i++) {
num = numerals["persian"].indexOf(str[i]);
num = num != -1 ? num : numerals["arabic"].indexOf(str[i]);
if (num == -1) num = str[i];
result += num;
}
return result;
},
toPersian: function (str, lang) {
return fromEnglish(str, "persian");
},
toArabic: function (str) {
return fromEnglish(str, "arabic");
}
}
})();
document.getElementById('ApproximateValue').addEventListener('input', event =>
event.target.value = TolocalInt(event.target.value)
);
function TolocalInt(value)
{
if ((value.replace(/,/g, '')).length >= 9) {
value = value.replace(/,/g, '').substring(0, 9);
}
var hasZero = false;
var value = transformNumbers.toNormal(value);
var result = (parseInt(value.replace(/[^\d]+/gi, '')) || 0);
if (hasZero) {
result = '0' + (result.toString());
}
return result.toLocaleString('en-US');
}
<input id="ApproximateValue" name="ApproximateValue" type="text" maxlength="12" />

Can I select a multi-dimensional HTML array in JavaScript as a multi-dimensional array?

If I have the following HTML on a page:
<input type="hidden" name=item[0][id]>
<input type="text" name=item[0][title]>
<input type="text" name=item[0][description]>
<input type="hidden" name=item[1][id]>
<input type="text" name=item[1][title]>
<input type="text" name=item[1][description]>
<input type="hidden" name=item[2][id]>
<input type="text" name=item[2][title]>
<input type="text" name=item[2][description]>
I would like to select the items using JavaScript (or JQuery) in such a way that I can loop over the items using the outer array.
Currently I have the following JQuery/JavaScript to handle the items:
var items = ($('[name*="item["]'));
var i = 0;
while (i < items.length) {
if (items[i++].value === '') {
// No ID set.
}
else if (items[i++].value === '') {
// No title set.
}
else if (items[i++].value === '') {
// No description set.
}
}
Is there a way to select the elements so that I can loop over them using notation more like the following (Where items.length is 3)?
for (var i = 0; i < items.length; i++) {
if (items[i][0].value === '') {
// No ID set.
}
else if (items[i][1].value === '') {
// No title set.
}
else if (items[i][2].value === '') {
// No description set.
}
}
Or even more like this?
for (var i = 0; i < items.length; i++) {
if (items[i].id.value === '') {
// No ID set.
}
else if (items[i].title.value === '') {
// No title set.
}
else if (items[i].description.value === '') {
// No description set.
}
}
Or would this require more manipulation and processing to go from selecting from the DOM to creating the data structure to loop over?
I think this is exactly what you are looking for (which is not really related to selectors):
function serialize () {
var serialized = {};
$("[name]").each(function () {
var name = $(this).attr('name');
var value = $(this).val();
var nameBits = name.split('[');
var previousRef = serialized;
for(var i = 0, l = nameBits.length; i < l; i++) {
var nameBit = nameBits[i].replace(']', '');
if(!previousRef[nameBit]) {
previousRef[nameBit] = {};
}
if(i != nameBits.length - 1) {
previousRef = previousRef[nameBit];
} else if(i == nameBits.length - 1) {
previousRef[nameBit] = value;
}
}
});
return serialized;
}
console.log(serialize());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="hidden" name=item[0][id]>
<input type="text" name=item[0][title]>
<input type="text" name=item[0][description]>
<input type="hidden" name=item[1][id]>
<input type="text" name=item[1][title]>
<input type="text" name=item[1][description]>
<input type="hidden" name=item[2][id]>
<input type="text" name=item[2][title]>
<input type="text" name=item[2][description]>
See the related JSFiddle sample.
Here's a way to add a custom function into JQuery to get the data structure you're looking for.
$.fn.getMultiArray = function() {
var $items = [];
var index = 0;
$(this).each(function() {
var $this = $(this);
if ($this.attr('name').indexOf('item[' + index + ']') !== 0)
index++;
if (!$items[index])
$items[index] = {};
var key = $this.attr('name').replace('item[' + index + '][', '').replace(']', '');
$items[index][key] = $this;
});
return $items;
};
var $items = $('input[name^="item["]').getMultiArray();
This allows you to have the references in your "ideal" example.
var $items = $('input[name^="item["]').getMultiArray();
$items[0].id;
JS Fiddle: https://jsfiddle.net/apphffus/

Loop Over Input Fields; Stop After Two Iterations

I have five form fields that will initially NOT be pre-populated with any values.
If a user fills out one of the fields, the next time they visit the form that field will be pre-populated with the value from the previous visit.
Here's what I'm trying: I'd like to create a loop that iterates through the fields. It will always check to see if there are empty fields. After finding 2 empty fields, the loop will stop and only show those 2 empty fields, while the other fields are hidden.
Here's what I have so far...I just can't figure how to stop after iterating through two fields,
HTML:
<form action="">
<input id="first" type="text" value="" />
<input id="second" type="text" value="" />
<input id="third" type="text" value="" />
<input id="fourth" type="text" value="" />
<input id="fifth" type="text" value="" />
</form>
JS:
$(document).ready(function() {
$('input').hide();
var firstValue = $('input[id="first"]').val(),
secondValue = $('input[id="second"]').val(),
thirdValue = $('input[id="third"]').val(),
fourthValue = $('input[id="fourth"]').val(),
fifthValue = $('input[id="fifth"]').val();
var firstField = $('input[id="first"]'),
secondField = $('input[id="second"]'),
thirdField = $('input[id="third"]'),
fourthField = $('input[id="fourth"]'),
fifthField = $('input[id="fifth"]');
var formValues = [firstValue, secondValue, thirdValue, fourthValue, fifthValue];
var fieldIds = [firstField, secondField, thirdField, fourthField, fifthField];
for (var i = 0; i < fieldIds.length; i++) {
for (var i = 0; i < formValues.length; i++) {
if ( formValues[i] === '' ) {
fieldIds[i].show();
return false;
}
}
}
});
Take all input fields, take the first two empty fields and show them; finally, take the complement of that to hide the rest:
var $inputFields = $('form input:text'),
$emptyFields = $inputFields
.filter(function() { return this.value == ''; })
.slice(0, 2)
.show();
$inputFields
.not($emptyFields)
.hide();
Demo
$(document).ready(function() {
$('input').hide().each( function(){
var index=0; //initilialize the counter
if( $(this).val().length ){ //check for input's length
if(index < 2) {
$(this).show();
index=index+1 //or index++ if you like
}
else {
break;
}
}
}
)};
If you want to include select and textarea fields in your eligible input population, use $(':input').hide().each(...). If you have multiple forms on your page, you would want to include that in your selector, too: $('#intended_form').find(':input').hide().each(...).
http://api.jquery.com/each/
I think that Jack provides the best answer, but this should work too. here, i use a second counter j and break the loop when j % 2 == 0, so at this time its found two empty fields. this is known as a modulus or the modulo operator.
$(document).ready(function() {
$('input').hide();
var firstValue = $('input[id="first"]').val(),
secondValue = $('input[id="second"]').val(),
thirdValue = $('input[id="third"]').val(),
fourthValue = $('input[id="fourth"]').val(),
fifthValue = $('input[id="fifth"]').val();
var firstField = $('input[id="first"]'),
secondField = $('input[id="second"]'),
thirdField = $('input[id="third"]'),
fourthField = $('input[id="fourth"]'),
fifthField = $('input[id="fifth"]');
var formValues = [firstValue, secondValue, thirdValue, fourthValue, fifthValue];
var fieldIds = [firstField, secondField, thirdField, fourthField, fifthField];
var j = 0;
for (var i = 1; i < fieldIds.length; i++) {
if ( formValues[i] === '' ) {
fieldIds[i].show();
j++;//we found an empty field
if (j % 2 == 0)
{
break;
}
}
}
});

Categories