How do I continue the numeric sequence of a cloned input? - javascript

$('button').click(function(){
$('#inputs').children().first().clone().appendTo('#inputs');
$('#inputs').children().last().clone().appendTo('#inputs');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='inputs'>
<input type='text' name="input['name'][1]">
<input type='text' name="input['name'][2]">
<input type='text' name="input['name'][3]">
<br>
<input type='text' name="input['age'][1]">
<input type='text' name="input['age'][2]">
<input type='text' name="input['age'][3]">
</div>
<button>Add</button>
The Script works properly, but the only problem is copying the name of the input. I want when I clone it to change the [1] into its sequence number with the ['name'] changes to ['age'] in the second clone. I also want the ['name'] to be appended to the end of the list of ['name'].
I thought about copying the name then removing last two letters and replace it by the '+index+]' But I wonder if that the proper way to do it.

You can just do a normal string operation on it. Since you know the pattern, you just need the number of inputs for the number and to stick in here there. Something like this:
$('#inputs').children().last().attr('name', `input['name'][${$('#inputs').children().length}`);
Since there are now 4 (including the new one), length will give you 4 so you'll end up setting the name to input['name'][4]. Subsequent will give you 5, 6, and so on.
If you need to dynamically grab the name and just need to update the number, you can just find and replace the number part (since you know it'll always be [1]):
const $last = $('#inputs').children().last();
$last.attr('name', $last.attr('name').replace('[1]', `[${$('#inputs').children().length}]`));
With this approach, it'll use the current name, and just replace the [1] bit with the new number, so you'll get [4] in there first (so input['name'][4] and input['age'][4], then [5] and so on.

Yes you can simply change the string. To add the name name to the end of the name list before the <br>, you need to select each group separately and then use after() instead of appendTo():
$('button').click(function(){
var names = $('#inputs').children('[name^="input[\'name"]');
var clone = names.first().clone();
clone.attr("name", "input['name'][" + (names.length + 1) + "]");
names.last().after(clone);
var ages = $('#inputs').children('[name^="input[\'age"]');
clone = ages.first().clone();
clone.attr("name", "input['age'][" + (ages.length + 1) + "]");
ages.last().after(clone);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='inputs'>
<input type='text' name="input['name'][1]">
<input type='text' name="input['name'][2]">
<input type='text' name="input['name'][3]">
<hr>
<input type='text' name="input['age'][1]">
<input type='text' name="input['age'][2]">
<input type='text' name="input['age'][3]">
</div>
<button>Add</button>
Note: I changed your <br> to <hr> only for demo so we can see it.

Related

jinja - how to check if one input value is smaller than the other?

I'm writing a flesk registration form, and I request the user to input two numbers, one of which has to be smaller than the other. I see how I can read the values into the python app and confirm that they are correct, but I would like to have it check as the user type them. Is this possible, or should I brash the dust of my poor JS skills?
I thought that it might look like
<input type='number' name='foo' value='1'></input>
<input type='number' name='bar' value='2' min={{ request.foo.value + 1 }}></input>
but I get an error message jinja2.exceptions.UndefinedError: 'flask.wrappers.Request object' has no attribute 'foo'
Looks like you are trying force "bar" to always be grater than "foo" here is a code example you can use.
// get the input elements
let foo = document.querySelector('[name="foo"]');
let bar = document.querySelector('[name="bar"]')
// set initial min attribute for bar to be grater than foo
bar.setAttribute('min', +foo.value + 1);
// update the min attribute of bar everytime foo changes
foo.addEventListener('change', function(event) {
bar.setAttribute('min', +foo.value + 1)
});
<form>
<input required type="number" name="foo" value="1" />
<input required type="number" name="bar" value="" />
<input type="submit">
</form>

How can I change the index of input element dynamically based on parent and inner parent in jquery

How can I change the index of input element dynamically based on the parent and inner parent count in jQuery.
In the following code how can I change the index of form elements
<div id='parent_container0'>
<div id='parent_inner_container0'>
<label> Name </label>
<input type='text' name='name[]'/>
<div id='child_container0'>
<div id='child_inner_container0'>
<label> Email </label>
<input type='text' name='email[]'/>
<label> Phone </label>
<input type='text' name='phone[]'/>
</div>
</div>
</div>
</div>
<div id='parent_container1'>
<div id='parent_inner_container1'>
<label> Name </label>
<input type='text' name='name[]'/>
<div id='child_container1'>
<div id='child_inner_container1'>
<label> Email </label>
<input type='text' name='email[]'/>
<label> Phone </label>
<input type='text' name='phone[]'/>
</div>
</div>
</div>
</div>
I need the changed name of form element as
name[0]
email[0][0]
phone[0][0]
name[1]
email[1][0]
phone[1][0]
Based on the parent's index of those elements in jQuery.
How can I achieve this?
Any help is appreciated.
Thanks,
Note: The requirement is to use a nested form to add more form of parent and Child with each form has nested form fields I am using the following code for changing index.
$('.parent_container').each(function(i) {
var pindex = $(this).index();
var mainfrm=$(this);
var orgname="";
mainfrm.find('.parent_container_inner').each(function(j) {
$(this).find('input, select, textarea').each(function(k){
orgname = $(this).attr('name');
orgname = orgname.replace(/[[]\d]+/g,"");
$(this).attr('name', orgname+"["+pindex+"]["+j+"]["+k+"]");
});
});
});
First, you should select your parent "containers" with:
$("div[id^=parent_container]").each(function(){
console.log(this);
});
It will print your two parent_container (parent_container0 and parent_container1). Check out here how to use selector attribute with Starts With
Then you will need to find and replace all name[], email[] and phone[].
So, you should use Ends With, to find each input you need to replace the name
$("div[id^=parent_container]").each(function(){
var parentContainerId = this.id.replace('parent_container', '');
$(this).find("input[name$='[]']").each(function(){
var newName = this.name.replace('[]', '[' + parentContainerId + ']');
this.name = newName;
})
});
Here is the Fiddle
Also, concerning your question, you should definitely take a better look into JQuery Selectors

using Javascript HTML Formular

I have mayn different question first and for all there is this pretty normal for who wants to know your firstname and lastname (its German but I hope this deosent matter)
<form name="formular" action="" onsubmit="">
<p>
<label for="vorname">Vorname:</label>
<input value="" type="text" name="vorname" id="vorname" size="25">
</p>
<p>
<label for="nachname">Nachname:</label>
<input type="text" name="nachname" id="nachname" size="25">
</p>
<p><input type="button" value="Absenden" onclick="doFunction();" /></p>
</form>
Then i want to use a function who gets the Name from the form and then shows all Names who ever fill out that form like a Guestbook. Until now i just made it to call an alert whon says "Hallo" but i dont even know how to use The form input as Variables.
I hope u can help me, pls only use JS and HTML.
You can capture the fields and add them to an array, and then print that array onto the page.
Here's a Fiddle containing my code. The existing add button appends to a ul element above the form and saves the name to a global array. I added clear and load buttons as well, so that you can see how to populate the list from the array.
<ul id="guestList">
</ul>
<form name="formular" action="" onsubmit="">
<p>
<label for="vorname">Vorname:</label>
<input value="" type="text" name="vorname" id="vorname" size="25"/>
</p>
<p>
<label for="nachname">Nachname:</label>
<input type="text" name="nachname" id="nachname" size="25"/>
</p>
<p>
<input type="button" value="Absenden" onclick="storeVals();" />
<input type="button" value="Clear List" onclick="clearList();" />
<input type="button" value="Load List" onclick="loadList();" />
</p>
</form>
And javascript:
var names = []; //global scope
function storeVals() //declare function to store the input
{
//document.getElementById finds the element with the
//corresponding ID. In this case I'm getting the objects
//behind each of the input boxes, and retrieving their value properties
//(the text entered in them). I'm also concatenating them together with
//the plus sign (+) operator, and adding a space between them with the ' '
//I'm storing the result of all that in a variable called name.
var name = document.getElementById('vorname').value + ' ' + document.getElementById('nachname').value;
//I'm accessing the names array I declared above. The elements in the
//array are accessed using an index which counts from 0.
//So to get the first element, I would do names[0].
//In this case I'm using names.length instead of a number, as it will return
//the number of elements currently in the array. When there are zero, it will return 0.
//When there is one, it will return 1, which happens to be the index for the second element.
//The means I'm always assigning the name to the element after the last existing one.
names[names.length] = name;
alert(names); //just to help see what's going on. Remove this when you don't need it anymore.
//Uses document.getElementById again, this time to get the object behind my ul list.
//And calls my appendToList function below, passing it my name variable and a
//reference to the list object.
appendToList(name, document.getElementById('guestList'));
}
function appendToList(name,ulist){
//this constructs a <li> object and stores it in a variable.
var li = document.createElement("li");
//this adds the text of the name inside the <li>
//so if name is equal to "john smith", I've built:
//<li>john smith</li>
li.appendChild(document.createTextNode(name));
//adds the li as a child of my existing list object.
//so:
// <ul id="guestList"><li>john smith</li></ul>
ulist.appendChild(li);
}
function clearList(){
//gets my ul list object with the id "guestList"
//sets its innerHTML (all of its contents) to an empty string
//so regardless of what's inside, it becomes <ul id="guestList"></ul>
document.getElementById('guestList').innerHTML = '';
}
function loadList(){
//got my ul list object by id again.
var list = document.getElementById('guestList');
//for loop - essentially this means start the variable i at 0
//keep looping while i < names.length, and increment i by 1
//each time we iterate through the loop.
for(i=0;i < names.length; i++){
//call the appendToList function above, and pass it names[i] and my list object
//so essentially, loop over every name in the array and call that function with
//it to add the name to the list.
appendToList(names[i],list);
}
}
Here are some specific reference materials for some of things I've done.
Arrays
ul DOM object
the document object
document.getElementById
But you need to be aware, if you're just using client-side javascript, this data is not going to survive a page refresh, and it will not be available if the page is accessed from another browser.
What you want to do is implement the JavaScript function to get the name. Here's an example:
function doFunction()
{
var name = document.getElementById('vorname').value;
alert("hallo " + name);
}
<form name="formular" action="" onsubmit="">
<p>
<label for="vorname">Vorname:</label>
<input value="" type="text" name="vorname" id="vorname" size="25">
</p>
<p>
<label for="nachname">Nachname:</label>
<input type="text" name="nachname" id="nachname" size="25">
</p>
<p><input type="button" value="Absenden" onclick="doFunction();" /></p>
</form>
Now you can do something with the name. Maybe you can store it as a global variable like so:
var name = "Guest";
function doFunction()
{
name = document.getElementById('vorname').value;
//do something here
}
And then you change the content of the website on the same page. But you must not navigate from that page; otherwise you may want to use local storage or a server-sided scripting language.

jQuery value attribute selector not returning correct number of elements

I have a programme that generates a count after the key is up.
JQuery Code:
$('.today').keyup(function() {
var Presents = $('input[value="/"]:visible');
$("#counter").html( "Present: " + Presents.length );
});
HTML:
<input type="text" id="1" name="1" class="today" value="/">
<input type="text" id="2" name="2" class="today" value="/">
<input type="text" id="3" name="3" class="today" value="/">
<p id="counter"></p>
The counter tag will display 3 after first key up. When i change the value in the text boxes the value does not change in the counter box.
E.G. when i chance the value of text box 3 to x the tag should now contain the number 2. Currently this does not change.
You are using an attribute selector, but when you change the input value, it won't change the attribute; just the property. You can use filter() to get what you need:
$('.today').keyup(function() {
var Presents = $('input:visible').filter(function(){
return this.value == "/";
});
$("#counter").html( "Present: " + Presents.length );
});
JSFiddle
If you needed to update the attribute itself, you can do simply by adding the following to the top of your event handler:
$(this).attr('value',this.value);
JSFiddle
But that seems pretty messy to me. Also, I believe filter() will be faster than an attribute selector anyway.

How do I replace part of the value of attributes for a set of elements in jQuery?

I am trying to replace a series of 'for' attributes of labels based on their current contents.
The application is using AJAX to add an item to an invoice without refreshing the page. Upon receiving notification of a successful item add, my script should replace all the labels in the form whose 'for' attribute ends with '-new' with the same attribute minus the '-new' and adding ('-' + itemValue), where itemValue is the item Id of the invoice item that was added.
I know how to select all the labels I want to change at once:
jQuery('label[for$=new]')
I know how to get their 'for' attribute:
jQuery('label[for$=new]').attr('for')
I tried the JavaScript replace method:
jQuery('label[for$=new]').attr('for').replace(/-new/,itemValue)
But that appears to select each label's 'for' attribute, replace the text, and pass the replaced text back (to nothing), since I don't know how to identify the labels that have the 'for' attribute I want to replace.
Here's some sample HTML:
<form id="InvoiceItemsForm-1" action="<?=$_SERVER['PHP_SELF'];?>" method="post" name="InvoiceItemsForm-1" onsubmit="return false">
<div id="InvoiceItem-new-1" class="InvoiceItem">
<label for="InvoiceItemNumber-new">New Invoice Item Number: </label>
<input id="InvoiceItemNumber-new" class="InvoiceItemNumber" type="text" value="" name="InvoiceItemNumber-new">
<label for="InvoiceItemDescription-new">Item Description: </label>
<input id="InvoiceItemDescription-new" class="InvoiceItemDescription" type="text" value="" name="InvoiceItemDescription-new">
<label for="InvoiceItemAmount-new">Item Amount: </label>
<input id="InvoiceItemAmount-new" class="InvoiceItemAmount" type="text" value="" name="InvoiceItemAmount-new">
<input id="addInvoiceItem-1" width="25" type="image" height="25" src="/payapp/images/greenplus.th.png" alt="Add New Invoice Item" onclick="addInvoiceItemButtonPushed(this)" value="invoiceItem">
</div>
<button id="CloseInvoice-1" onclick="closeInvoice(this)" type="button">Close Invoice</button>
</form>
Once I get this to work, I'm going to replace all the ids for all the inputs. Same problem. I imagine the solution looks something like this:
jQuery('input[id$=new]').attr('id').replace(/-new/,itemValue)
I just cannot figure out the syntax for this at all.
No need to use .each() ... the .attr() method accepts a function as the second parameter that returns the new value to be used as replacement
jQuery('label[for$=new]').attr('for', function(index, currentValue){
return currentValue.replace(/-new/,'-' + itemValue);
});
If I may, why not just put the input tag inside the label tag? That way, you won't need a for attribute inside the label tag.
Next, a better way to accomplish what you're trying to do would be to use the invoice ID number as the ID for the surrounding div, and add a 'new` class for "new" invoice entries.
So your form would look something like this:
<form id="InvoiceItemsForm-1" action="<?=$_SERVER['PHP_SELF']" method="post" name="InvoiceItemsForm-1" onsubmit="return false">
<div class="InvoiceItem new">
<label>New Invoice Item Number: <input class="InvoiceItemNumber" type="text" value="" name="InvoiceItemNumber"></label>
<label>Item Description: <input class="InvoiceItemDescription" type="text" value="" name="InvoiceItemDescription-new"></label>
<label for="InvoiceItemAmount-new">Item Amount: <input class="InvoiceItemAmount" type="text" value="" name="InvoiceItemAmount-new"></label>
<input id="addInvoiceItem-1" width="25" type="image" height="25" src="/payapp/images/greenplus.th.png" alt="Add New Invoice Item" onclick="addInvoiceItemButtonPushed(this)" value="invoiceItem">
</div>
<button id="CloseInvoice-1" onclick="closeInvoice(this)" type="button">Close Invoice</button>
</form>
You'll still have all the targetability you need to get the new invoice item field data, but now, you only have two things to do to convert from a "new" invoice row to an "existing" invoice item row: add an id attribute to the div and remove the new class, both of which jQuery will let you do quite easily.
Not sure I get the question, but something like:
var oldFor = $('label[for$=new]').attr('for');
var newFor = oldfor.replace(/-new/,itemValue);
$('label[for$=new]').attr('for', newFor);
.attr( attributeName, value )
attributeName = The name of the attribute to set.
value = A value to set for the attribute.
When selecting multiple elements, you will need to iterate:
$('label[for$=new]').each(function(index) {
$(this).attr('for', $(this).attr('for').replace(/-new/, '-' + itemValue));
});

Categories