Retrieving the values from input elements and storing in an array - javascript

I've got a form that takes input from the user
<form id='myForm'>
<div id='x'>
<h2> start </h2>
<ul class="rounded">
<li><input type="text" placeholder="text" id="o" /></li>
</ul>
<h2>dests </h2>
<ul class="rounded">
<li><input type="text" placeholder="text" id="d" /></li>
</ul>
<ul class="rounded">
<li><input type="text" placeholder="text" id="d" /></li>
</ul>
</div>
<li class="arrow"><a href="#page2" onclick='function()'>Run </a></li>
</form>
I need a way of getting the user input from every field in the form, and placing it into an array. I have looked into getElementByTagName('input'), but this returns a HTMLCollection object. Any suggestions? (P.S i'm using a jqtouch if you're wondering what's up with the weird syntax)

You can use Array.prototype.map to create an array from the list of input elements obtained from querySelectorAll.
Try filling the inputs and clicking Run in the demo below:
var elements = document.querySelectorAll('#myForm input');
function callme() {
var result = Array.prototype.map.call(elements, function(e) {
return e.value;
});
console.log(result);
}
<form id='myForm'>
<div id='x'>
<h2> start </h2>
<ul class="rounded">
<li>
<input type="text" placeholder="text" />
</li>
</ul>
<h2>dests </h2>
<ul class="rounded">
<li>
<input type="text" placeholder="text" />
</li>
</ul>
<ul class="rounded">
<li>
<input type="text" placeholder="text" />
</li>
</ul>
</div>
<ul>
<li class="arrow"><a href="#page2" onclick='callme()'>Run </a>
</li>
</ul>
</form>

As others have mentioned be careful to use the html id attribute with a unique id, i.e. each input should have its own.
Using vanilla JavaScript, document.getElementsByTagName() returns a live html collection and you can access its members as properties using [index] to get the element you want. Then use textObject.value to access the inputs' value.
All in all, document.getElementsByTagName('input')[0].value will provide the value of the first input! That is the logic, also check the snippet.
Please also consider the following:
element.querySelectorAll() is generally slower than element.getElementsByTagName(), as the first uses a depth-first pre-order traversal of the document's nodes
element.querySelectorAll() returns a StaticNodeList
I found this article quite interesting for this topic.
function retrieve(){
let list = document.getElementById('inputListContainer');
let input = list.getElementsByTagName('input');
let array = [];
for( let i = 0; i < input.length; i++ ){
//input[i].value is the same as document.getElementsByTagName('input')[i].value
array.push(input[i].value);
}
console.log( array );
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id='inputListContainer'>
<!-- Using a single ul to parent list items. Note that this does not affect the script -->
<ul id='inputList' class='rounded'>
<li><input type="text" placeholder="one"/></li>
<li><input type="text" placeholder="two"/></li>
<li><input type="text" placeholder="three"/></li>
</ul>
<button onclick='retrieve()'>Retrieve</button>
</div>
</body>
</html>

Try this:
function getValues() {
var values = []; // Array of input values
var elements = document.querySelectorAll("#myForm input");
for(var i = 0; i < elements.length; i++) {
values.push(elements[i].value);
//If you need the input ID:
//values.push({name: elements[i].id , value: elements[i].value});
}
}

For this you can use Document.querySelectorAll()
Returns a list of the elements within the document (using depth-first pre-order traversal of the document's nodes) that match the specified group of selectors. The object returned is a NodeList.
Using document.querySelectorAll("#myForm input"); will target all inputs within the form with the ID of myForm.
Then a for() loop is used to iterate through the collection and push the input values into the array .
The for statement creates a loop that consists of three optional expressions, enclosed in parentheses and separated by semicolons, followed by a statement (usually a block statement) to be executed in the loop.
for ([initialization]; [condition]; [final-expression])
statement
function BuildArray() {
var myArray = [];
var input = document.querySelectorAll("#myForm input");
for (var i = 0; i < input.length; i++) {
myArray.push(input[i].value);
}
console.log(myArray);
}
<form id='myForm'>
<div id='x'>
<h2> start </h2>
<ul class="rounded">
<li>
<input type="text" placeholder="text" id="o" value="first" />
</li>
</ul>
<h2>dests </h2>
<ul class="rounded">
<li>
<input type="text" placeholder="text" id="d" value="second" />
</li>
</ul>
<ul class="rounded">
<li>
<input type="text" placeholder="text" id="d" value="third" />
</li>
</ul>
</div>
<li class="arrow"><a href="#page2" onclick='BuildArray()'>Run </a>
</li>
</form>
I would also like to recommend keeping ID's unique if ID's are required but for this task ID's are not used in the selector so no problems if ID's are the same.
If you have any questions about the source code above please leave a comment below and i will get back to you as soon as possible.
I hope this helps. Happy coding!

You just need to iterate through each input and push each value into an array. You would call something like this on click. See jQuery example here.
function click() {
var arr = [];
$.each($('input'), function(k,v) {
arr.push($(v).val());
})
console.log(arr);
}

Related

Easiest way to access unordered list ids as array in PHP

I have an unordered list; I am using DB ids as list-item ids; After the Submit button pressed, I want all ID's of my list-items to be presented as an Array in PHP. I am new to javascript; there are solutions available but can't really figure out proper solution.
Thanks to all in advance.
Assuming you got html like this ...
<ul>
<li id="1">
item 1
</li>
<li id="2">
item 2
</li>
</ul>
... you can rebuild it like this (with hidden-tags) ...
<ul>
<input type="hidden" name="ids[]" value="1" />
<li id="1">
item 1
</li>
<input type="hidden" name="ids[]" value="2" />
<li id="2">
item 2
</li>
</ul>
.. then in PHP you can access it like this ..
$arrIds = $_REQUEST["ids"]; // array(1, 2)
PS:
I first missed you wanted it in PHP so here still as additional info how to do it in JS:
You can use the following code to get an array of ids fetched from the li-ids:
var ids = [];
$("li").each(function() {
ids.push(this.id);
});
... or withouth jquery ...
var ids = []
var lis = document.getElementsByTagName("li");
for(var i = 0; i < lis.length; i++ ){
ids.push(lis[i].id);
}

jQuery Appending Input elements

I am trying to create a simple Do to List which will have Checklists with a list of Tasks under it.
Idea is to create the Complete List and then Submit it to the Server to Save it in the Database.
I am looking to get the Input Boxes in a Clean structure like the following
Array
(
[checklist] => Array
(
[0] => Array
(
[task] => Array
(
[0] =>
[1] =>
)
)
[1] => Array
(
[task] => Array
(
[0] =>
[1] =>
[2] =>
)
)
[2] =>
)
[submit] => Submit
)
As i need to Add the right name to the input box to retain the structure i receive in the database i will need to count the Checklist number and the Task number and then append the same.
One unique case is when a user delete an input box from the middle of the list of tasks how can i retain the number to increment so that i do not over lap an input name and lose the data.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>ToDo</title>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<form action="todo.php" method="post" name="todo">
<ul>
<li>
<input name="checklist[0]" type="text">
<ul>
<li>
<input name="checklist[0][task][0]" type="text">
</li>
<li>
<input name="checklist[0][task][1]" type="text">
</li>
</ul>
<a class="add" href="#">Add one</a> </li>
<li>
<input name="checklist[1]" type="text">
<ul>
<li>
<input name="checklist[1][task][0]" type="text">
</li>
<li>
<input name="checklist[1][task][1]" type="text">
</li>
<li>
<input name="checklist[1][task][2]" type="text">
</li>
</ul>
<a class="add" href="#">Add one</a> </li>
<li>
<input name="checklist[2]" type="text">
<ul>
</ul>
<a class="add" href="#">Add one</a> </li>
</ul>
<input name="submit" type="submit" value="Submit">
</form>
<script language="javascript">
$( ".add" ).click(function() {
// Find the Task Count
var task_count = $(this).siblings('ul').children('li').length;
var count = $(this).siblings('ul').count;
var input = '<li><input name="checklist[][task][]" type="text"></li>';
console.log(task_count);
$(this).siblings('ul').append(input);
});
</script>
<hr/>
<pre>
<?php
print_r($_POST);
?>
</pre>
</body>
</html>
Link: http://play.mink7.com/todo.php
The code (at the page bottom) is:
$( ".add" ).click(function() {
// Find the Task Count
var task_count = $(this).siblings('ul').children('li').length;
var count = $(this).siblings('ul').count;
var input = '<li><input name="checklist[][task][]" type="text"></li>';
console.log(task_count);
$(this).siblings('ul').append(input);
});
When user removes an input you can store the input name probably in an array. And while appending you can check the array for the name. Based on the absence or presence of the name in array you can rename newly appended input. This will prevent the data loss if any.
Another approach will be to don't bother about the names while appending. But before the form is submitted, you can dynamically generate the name of the inputs based on the children count and the task name. This will certainly prevent the data loss.
Here is the demo for the second method: http://jsfiddle.net/lotusgodkk/GCu2D/359/
$(document).ready(function () {
$('input[type="submit"]').on('click', function (e) {
$('form>ul').each(function () {
var ul = $(this);
var name = ul.attr('data-name');
var inputs = $('input', ul);
inputs.each(function () {
var i = $(this);
var index = inputs.index(i);
var n = name + '_' + index; // Generate the name of input
i.attr('name', n);
});
});
return false;
})
});
Sample HTML:
<form action="todo.php" method="post" name="todo">
<ul data-name="listone">
<li>
<input name="checklist[0]" type="text" />
<ul>
<li>
<input name="checklist[0][task][0]" type="text" />
</li>
<li>
<input name="checklist[0][task][1]" type="text" />
</li>
</ul> <a class="add" href="#">Add one</a>
</li>
<li>
<input name="checklist[1]" type="text" />
<ul>
<li>
<input name="checklist[1][task][0]" type="text" />
</li>
<li>
<input name="checklist[1][task][1]" type="text" />
</li>
<li>
<input name="checklist[1][task][2]" type="text" />
</li>
</ul> <a class="add" href="#">Add one</a>
</li>
<li data-name="listthree">
<input name="checklist[2]" type="text" />
<ul></ul> <a class="add" href="#">Add one</a>
</li>
</ul>
<input name="submit" type="submit" value="Submit" />
</form>
Here, for naming I used a data attribute on ul and the index on input inside the list.
Click on the submit button and you'll see the changed name of input.
I think you should count checklists and tasks at submit time. Just ignore the names during "edit time" and set the names all in one block at the end, like this:
http://jsfiddle.net/s3j7ok56/1/
This way if the user deletes, or moves (drag?) items, you just don't care as they will be named correctly at the end.
( example with remove: http://jsfiddle.net/s3j7ok56/2/ )
Note that I also set the val() of inputs for debug, to show the names. And I block the form submit for JsFiddle, all this should be removed to allow correct form posting.
HTML:
<form method="post" id="todo" name="todo" onsubmit="/* for JSFIDDLE */ return false;">
<ul id="all">
</ul>
<a id="addc" href="#">add checklist</a><br />
<input name="submit" type="submit" value="Submit">
</form>
JS:
$(function() {
$("#addc").click(function(e) {
var elem=$('<li class="checklist"><input type="text"><ul class="tasks"></ul></li>');
var link=$('<a class="add" href="#">Add task</a>');
link.appendTo(elem);
elem.appendTo("#all");
link.click(function(e1) {
var task=$('<li class="task"><input type="text"></li>');
$(this).parent().children(".tasks").append(task);
});
});
$("#todo").submit(function() {
var countLists=0;
var countTasks=0;
$("#all>li.checklist>input").each(function() {
$(this).attr("name","checklist["+countLists+"]");
$(this).val("checklist["+countLists+"]");
countTasks=0;
$(this).parent().find("ul.tasks>li.task>input").each(function() {
$(this).attr("name","checklist["+countLists+"]task["+countTasks+"]");
$(this).val("checklist["+countLists+"]task["+countTasks+"]");
countTasks++;
});
countLists++;
})
return true;
});
});

Remove the first 2 <li> content, except what you have inside the tag <label>

How do I remove the content of the first 2 <li>, except what you have inside the tag <label> of the second <li>.
My structure is like this:
<ul>
<li>
Text <label>1#</label> <input type="text" value="" />
</li>
<li>
Text <label>2#</label> <input type="text" value="" />
</li>
<li>
Text <label>3#</label> <input type="text" value="" />
</li>
<li>
Text <label>4#</label> <input type="text" value="" />
</li>
<li>
Text <label>5#</label> <input type="text" value="" />
</li>
<li>
Text <label>6#</label> <input type="text" value="" />
</li>
<li>
Text <label>7#</label> <input type="text" value="" />
</li>
</ul>
And would have to remove the codes and stay that way:
<ul>
<li>
<label>2#</label>
</li>
<li>
Text <label>3#</label> <input type="text" value="" />
</li>
<li>
Text <label>4#</label> <input type="text" value="" />
</li>
<li>
Text <label>5#</label> <input type="text" value="" />
</li>
<li>
Text <label>6#</label> <input type="text" value="" />
</li>
<li>
Text <label>7#</label> <input type="text" value="" />
</li>
</ul>
DEMO CODE
(My English sucks, I hope you understood my question, and it has been clear for everyone.)
This removes the first list item completely, then all nodes except labels from the second list item.
Demo
$('ul li:nth-child(1)').remove();
$('ul li:nth-child(1)').contents().filter(function(){
return !$(this).is('label');
}).remove();
This could be your solution:
$('ul li label').each(function() {
$(this).parent().empty().append($(this));
});
Fiddle:http://jsfiddle.net/FGJLg/
Here's a possibility (just a quick lesson on JQuery here, but I would go for the 3rd option, see below) :
$('ul li:nth-child(1)').remove();
$('ul li:nth-child(1)').remove(); // child(1) ALSO, BECAUSE #2 HAS NOW BECOME #1 !
// OR MODULAR :
for (i=1; i < 3; i++)
{
$('ul li:nth-child('+i+')').remove(); // OBVIOUSLY #3 AND #4 ARE REMOVED AS WELL.
}
// YOU CAN CAPTURE AND STORE THE LABEL CONTENT, ERASE THE CONTENT OF THE LI, AND PUT BACK THE LABEL :
for (i=1; i < 3; i++)
{
var label_content = $('ul li:nth-child('+i+') label').html(); // GETTER
$('ul li:nth-child('+i+')').html(''); // SETTER (set to empty)
$('ul li:nth-child('+i+')').html('<label>'+label_content+'</label>'); // REINJECT THE LABEL
}
Working Fiddle here : http://jsfiddle.net/U5K5q/1/
But it looks like you just want to "hide" (display:none) your inputs... If it is the case, you may as well do :
for (i=1; i < 3; i++)
{
$('ul li:nth-child('+i+') input').css('display':'none');
$('ul li:nth-child('+i+') input').attr('disabled'); // JUST TO MAKE SURE THIS INPUT IS NOT GOING SUBMITTED
}
Or, 3rd option, cleaner :
for (i=1; i < 3; i++)
{
$('ul li:nth-child('+i+') input').remove(); // OBVIOUSLY #3 AND #4 ARE REMOVED AS WELL.
}

How to loop over nested input forms with jquery

I have the following html form, which is generated dynamically:
<ul class="precursorList">
<li>
Precursor Name: <input name="precursorName" type="text">
<ul class="portList">
<li>Portname of precursor: <input name="precursorPort" type="text">
Portname of this: <input name="thisPort" type="text">
</li>
</ul>
</li>
<li>
<li>
Precursor Name: <input name="precursorName" type="text">
<ul class="portList">
<li>Portname of precursor: <input name="precursorPort" type="text">
Portname of this: <input name="thisPort" type="text">
</li>
</ul>
</li>
<li>
</ul>
I want to get the values using jquery, therefore I have defined this loop:
ports = [];
$(".precursorList :input").each(function() {
if(this.name == "precursorName") {
var precursorName_ = this.value
$(".portList :input ").each(function() {
if(this.name == "precursorPort") {
precursorPort_ = this.value;
} else if(this.name == "thisPort") {
ports.push({
filterName : precursorName_,
portNameOfFilter : precursorPort_,
portNameOfThis : this.value
});
}
});
}
});
Unfortunately this function does not work like I want it to work. The following loop $(".portList :input ").each( will always only loop over all elements in portList in the html document. How can I achieve that this loop will only loop over the corresponding portList, for each precursor?
UPDATE: The structure of the html element will stay the same only, the number of inputs will change. But there will only be a portList if a PrecursorElement exist.
id must be a unique field, instead use class to select multiple elements. Also use .live() for dynamically added elements.
EDIT:
If you are using Jquery > 1.7 use .on() instead of .live().
I tried following and it seems that its working
$(".precursorPort").each(function() {
temp = this.name;
$(this).parents(".portList").each(function() {
$(this).parents(".precursorList").each(function() {
alert(temp);
// use temp var and save it in ports
});
});
});
Check this fiddle : http://jsfiddle.net/Ajinkya_Parakh/DR233/
It may not be the best/most efficient but it is one of the working alternative.
An id must be unique in a document. If you want to create a group of similar things, then use a class instead.
I'd do something like this:
<ul id="precursorList">
<li>
Precursor Name1: <input class="precursor" name="precursorName1" id="precursorName1" type="text">
<ul id="portList1">
<li>Portname of precursor1: <input class="precursorPort" name="precursorPort1" id="precursorPort1" type="text">
Portname of this1: <input class="thisPort" name="thisPort1" id="thisPort1" type="text">
</li>
</ul>
</li>
<li>
Precursor Name2: <input class="precursor" name="precursorName2" id="precursorName2" type="text">
<ul id="portList2">
<li>Portname of precursor2 <input class="precursorPort" name="precursorPort2" id="precursorPort2" type="text">
Portname of this2: <input class="thisPort" name="thisPort2" id="thisPort2" type="text">
</li>
</ul>
</li>
</ul>
and then:
ports = [];
$("#precursorList > li").each(function()
{
precursor = $(this).find(".precursor")[0];
precursorPort = $(this).find(".precursorPort")[0];
thisPort = $(this).find(".thisPort")[0];
ports.push({filterName: precursor.value, portNameOfFilter: precursorPort.value, portNameOfThis: thisPort.value});
});
Step back a minute, I think you're overthinking this a bit.
Wrap your dynamic form in <form> tags. Then do a $('form').serialize() No need for crazy loops. Serialize is essentially a built-in, one line version of what you're already trying to do. Of course, serialize works on names so you'll have to have distinct ones (even if it's just name1, name2,etc) ID's must be unique too, so either fix that or drop them.
Simplicity always trumps crazy technical genius.
Fiddle for proof

Undefined variable in array in prototype

I have the following code:
<ul id="litemsd">
<li class="litemd">
<input type="checkbox" id="d1" name="d1" />
<label for="d1">Number One</label>
</li>
<li class="litemd">
<input type="checkbox" id="d2" name="d2" />
<label for="d2">Numer Two</label>
</li>
<li class="litemd">
<input type="checkbox" id="d3" name="d3" />
<label for="d3">Numer Three</label>
</li>
</ul>
And inside the form's submit observe function I try to iterate over the selected checkboxes:
$$('li.litemd').pluck('checked').each(function(s) {
alert(s.next().innerHTML)
});
But whe that code is reached, the following error pops up in firebug:
"s is undefined"
Any hints ?
I think you're confusing the properties which pluck() works on with HTML attributes. It's anyway easier to add the pseudo class of checked as part of the initial selector, like:
$$('li.litemd input:checked').each(function(s) {
alert(s.next().innerHTML);
});
Example
$$('li.litemd').pluck('checked').each(function() {
alert($$(this).next().innerHTML)
});
?
.pluck() returns an array of values (whatever property name you passed in), so it's not filtering your results to the checked ones, it's literally returning a [false, false, false] array.
Instead I think you want this:
$$('li.litemd input').each(function(s) {
if(s.checked) alert(s.next().innerHTML)
});
You can give it a try here, note the addition of input to the selector, since you're cheking on the property of the <input> inside the <li>, not on the <li> itself.

Categories