How can I retrieve input values from elements added after page load? - javascript

I'm working with Zend Framework 1.12 and I've need to be able to dynamically add and delete fields from a sub-form, in this case we're associating hyperlinks to a parent "promotion".
I haven't found a way to accomplish dynamically adding and removing elements via Zend, and the rare tutorial I've found that claimed to do this are half a decade old and aren't working when I attempt them.
So what I am doing is storing the links I need to work with in a Zend Hidden input field and then dealing with the JSON data after I submit. Not very efficient, but it's the only thing I've gotten to work so far.
Below is the section of the code I'm working with:
Assume a form like:
<form action="/promos/edit/promo_id/15" method="POST" id="form_edit">
<!-- input is Zend_Form_Element_Hidden -->
<input type="hidden" id="link_array" value="{ contains the JSON string }"/>
<button id="add_link">Add Link</button>
</form>
The purpose is that every time the Add Link button is pressed, the form adds fields to allow the user to input new hyperlinks that will be associated with the specific items.
Here's the function:
// add links
$('#add_link').click(
function(e) {
e.preventDefault();
link = '<div class="p_link new_link">' +
'<div class="element_wrap">' +
'<label for="link_name" class="form_label optional">Text: </label>' +
'<input type="text" id="new_link_name" name="link_name"/>' +
'</div>' +
'<div class="element_wrap">' +
'<label for="link_http" class="form_label optional">http://</label>' +
'<input type="text" id="new_link_http" name="link_http"/>' +
'</div>' +
'<div class="element_wrap">' +
'<button class="submit delete_link">Delete</button>' +
'</div>' +
'</div>';
$('#add_link').prev().after(link);
}
);
Now, what I need to do is on submit, for every new_link class element, to take the links name and http reference and place it in a json object. Here's the code as I have it so far (I know I don't have both input fields represented at this point):
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = document.getElementsByClassName('new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).children('#new_link_name').text();
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
My problem is that: var new_links = document.getElementsByClassName('new_link'); will collect all the newly added new_link elements, but it does not pull in any value that has been input into the text fields.
I need to know how I can apparently bind any input I make to the input field's value attribute, because right now anything I type into these new elements are tossed out and the field appears empty when it's anything but.

$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = $('.new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).find('input').val(); // you need input values! This line //is changed...
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
JSFIDDLE: http://jsfiddle.net/DZuLJ/
EDit: You can't have multiple IDS (make class for each input, and target class, if you want link names and http's)

Related

How to make an input field onclick

what I want is to make an input field appear on some kind of popup where the user can input a number between 0-x where x is the current level of a variable. Once the user inputs a number, that number gets added to a different variable. This would be much like transferring money in a videogame. I don't have any code for this but it would be awesome if you could help.
This may help you get started. I created a clickable label that opens a popover with an input field and a button for submission.
I'm using jQuery and Bootstrap.
JSFiddle: https://jsfiddle.net/Ravvy/xjz6ok62/
HTML:
<label>Money: $</label>
<label data-toggle="popover" title="Add Money" data-placement="bottom" id="moneyLabel">0.00</label>
JavaScript:
$(document).ready(function() {
var content = '<input id="moneyInput"></input>' +
'<button id="moneyButton" ' +
'onclick="addMoney()">Add</button>';
$('#moneyLabel').popover({content: content, html: true});
});
function addMoney() {
var currentAmount = parseFloat($('#moneyLabel').text());
var addedAmount = parseFloat($('#moneyInput').val());
var total = currentAmount + addedAmount;
$('#moneyLabel').text(total);
}

Need to create a button that adds input areas, and name the div differently, and can export them using JavaScript

Alright, So basically I got a website that recieves a number of inputs, like lets say name, age, weight...
After all the inputs, the text appears in a text area on the same website.
I need the website to offer the function to add more levels,
for example you click 'add level' and a dynamic new inputs appear that allow you to add more info.
Im facing a problem that when i create a new dynamic div with those inputs, they all have the same id, which wont allow me to print each one individually.
I have this function that prints out the results :
<form id="form" action="#">
<script>
$("#form").submit(function(event) {
event.preventDefault();
$("#template").val()...
</form>
Shortly : I need a way to make a button, that adds a new div with unique id.Inside there will be label inputs, the label will print out on submit.
Hope this is clear enough :)
If I understand your question correctly, this might be a way to do it :
HTML
<button id="addLevelBtn">Add a level</button>
<button id="getResultsBtn">Get results</button>
JS
//on click, add a level
$('#addLevelBtn').on('click',addLevel);
//on click, get results
$('#getResultsBtn').on('click',getResults);
//add the first level on load
addLevel();
function addLevel(){
var nbOfSets = $('.setOfInputs').length;
$('#addLevelBtn').before(
'<div class="setOfInputs" id="set-'+nbOfSets+'">'
+'<p>#set-'+nbOfSets+'</p>'
+'<label for="age">Age: </label>'
+'<input type="text" name="age">'
+'<label for="weight">Weight: </label>'
+'<input type="text" name="weight">'
+'</div>');
}
function getResults(){
var result="";
$.each($('.setOfInputs'),function(){
var id = $(this).attr('id');
var age = $(this).find('[name=age]').val();
var weight = $(this).find('[name=weight]').val();
result += id + ' : age = ' + age + ' , weight = ' + weight + '\n';
});
alert(result);
}
JS Fiddle Demo

clearing input text area with dynamic input id's on button click - jQuery

Although the question title gives an impression that I want to ask one question, but there are two problems I have facing at the moment.
I have gone through few similar questions on how to clear the input text area on button click, but most of them are for fixed input class or id's.
Problem 1: I am generating rows dynamically and and all the fields are being populated using JS thus the input ID's for all text boxes are different. Now if a user enter some number on "Apply to all" input field and click the button the same number should be set to all the rows which are added in the betslip.
Problem 2: After entering individual values in the betslip input boxes and if I click "clear all" button. It should clear all the inputs entered earlier in the bet slip.
Here is the HTML structure
<div id="bets">
<div id="idNo1" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_1" type="text">
</div>
</div>
<div id="idNo2" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_2" type="text">
</div>
</div>
<div id="idNo3" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_3" type="text">
</div>
</div>
</div>
JS for adding element in the individual bets
function createSingleBetDiv(betInfo) {
var id = betInfo.betType + '_' + betInfo.productId + '_' + betInfo.mpid,
div = createDiv(id + '_div', 'singleBet', 'bet gray2'),
a = createA(null, null, null, 'right orange'),
leftDiv = createDiv(null, null, 'left'),
closeDiv = createDiv(null, null, 'icon_shut_bet'),
singleBetNumber = ++document.getElementsByName('singleBet').length;
// Info abt the bet
$(leftDiv).append('<p class="title"><b><span class="bet_no">' + singleBetNumber + '</span>. ' + betInfo['horseName'] + '</b></p>');
var raceInfo = "";
$("#raceInfo").contents().filter(function () {
if (this.nodeType === 3) raceInfo = $(this).text() + ', ' + betInfo['betTypeName'] + ' (' + betInfo['value'].toFixed(2) + ')';
});
$(leftDiv).append('<p class="title">' + raceInfo + '</p>');
// Closing btn
(function(id) {
a.onclick=function() {
removeSingleBet(id + '_div');
};
})(id);
$(a).append(closeDiv);
// Creating input field - This is where I am creating the input fields
$(leftDiv).append('<p class="supermid"><input id="' + id + '_input\" type="text" class="betInput"></p>');
// Creating WIN / PLACE checkbox selection
$(leftDiv).append('<p><input id="' + id + '_checkbox\" type="checkbox"><b>' + winPlace + '</b></p>');
// Append left part
$(div).append(leftDiv);
// Append right part
$(div).append(a);
// Appending div with data
$.data(div, 'mapForBet', betInfo);
return div;
}
HTML for Apply to all and Clear all button
APPLY TO ALL <input type="text">
CLEAR ALL
JS where I need to implement those 2 functions
function applyToAllBetInput() {
$('.apply').change(function() {
$(this).prevAll().find('input[type=text]').val($(this).val());
});
}
function clearAllBetInput() {
$('.clearall').click(function() {
$('div.bet').find('input').val('');
});
}
The best thing to do is remove the inline event handlers from the links, like this...
APPLY TO ALL <input type="text">
CLEAR ALL
Then, assign the event handlers in your script...
$("a.button.apply").on("click", function(e) {
e.preventDefault();
applyToAllBetInput($(this).find("input").val());
});
$("a.button.clearall").on("click", function(e) {
e.preventDefault();
applyToAllBetInput("");
});
And this would apply the value to all inputs...
function applyToAllBetInput(value) {
$("#bets div[name=singleBet] .supermid input:text").val(value);
}
If you pass a parameter into applyToAllBetInput and then set the inputs with that then you only need the one function, as they both do the same thing, but with different values. Best to only have 1 bit of code if it's only doing 1 thing, then you only have to fix it once if things change in the future :)
Please replace the id's i've given with your actual button/textarea ids (give ID's to your elements).
$('#txtApplyToAll').change(function() {
$(this).prevAll().find('input[type=text]').val($(this).val());
});
$('#btnClearAll').click(function() {
$('#txtApplyToAll').prevAll().find('input[type=text].val('');
});
There are several general suggestions I'd make before even starting to write the code. First, Why are you using longhand JavaScript when you have jQuery available? For example:
inputId = divId.document.getElementById('input');
should be simply:
inputId = $(inputId).find('input');
(or something along those lines--I'm not sure what you're after with that.)
Next, you're using inline click handlers. Instead, use event listeners:
<a href="javascript: applyToAllBetInput()" ...
Should be
$('a#my-id').click(function() { ... }
Finally, you can target all your inputs for clearing with a selector like this:
$('div.bet').find('input').val('');

Sorting consistency of dynamically created IDs on DOM Elements

My application successfully creates elements and assigns them different (increasing) IDs.
Now my issue relies when the user deletes these elements (because they have the option to delete as well as create), the consistency of these IDs get broken therefore my application doesn't run well.
This Fiddle represents what I have so far. Just a textbox that appends its value and a few other elements inside a collapsible as many times as the user wants (For some reason my fiddle doesn't increment the alert value, but it works fine on my platform).
SCRIPT (Sorry the txt variable is too long)
$('#Add').click(function () {
if ($("#MedNameStren").val() != "") {
var value = $("#MedNameStren").val();
var noOfMeds = $('#NoOfMedicines').val();
//to check current value
alert(noOfMeds);
var text = '<div data-role="collapsible" data-collapsed="true" data-iconpos="left" data-content-theme="e">' + '<h2>' + desc + '</h2>' + '<div class="ui-grid-a">' + '<div class="ui-block-a" style="width:25%; margin-right:3%;">' + '<input id="quantity' + noOfMeds + '" class="quantity" type="text" placeholder="Quantity" />' + '</div>' + '<div class="ui-block-b" style="width:70%; margin-right:2%;"">' + '<textarea id="directions' + noOfMeds + '" class="directions" cols="40" rows="4" placeholder="Directions given by your GP." ></textarea>' + '</div>' + '</div>' + '<button key="' + vpid + '">Remove</button>' + '</div>';
$("#medListLi").append(text);
$('button').button();
$('#medListLi').find('div[data-role=collapsible]').collapsible();
$('#medListLi li').listview("refresh");
$('#medListLi').trigger("create");
document.getElementById("manuallyName").value = "";
noOfMeds++
$("#NoOfMedicines").val(noOfMeds);
}
else {
alert('Please Provide Medicine Name')
}
});
I am using a counter that neatly increments the ids of quantity and description like:
quantity0
quantity1
quantity2
..and so on, but once the following script is called...
//Deletes colapsible sets (Medicines) from the selected List
$('#medListLi').on('click', 'button', function (el) {
$(this).closest('div[data-role=collapsible]').remove();
var key = $(this).attr('key');
localStorage.removeItem(key);
var noOfMeds = $('#NoOfMedicines').val();
noOfMeds--
$("#NoOfMedicines").val(noOfMeds);
//location.reload();
});
depending on which element (collapsible) is deleted, the IDs stop being consistent. For example if the collapsible with id="quantity1" is deleted then the counter will go back to 1 (currently 2) and on the next addition the respective collapsible will get an id that's already taken, and unfortunately I don't need this to happen.
Maybe I'm making this sound more complicated that it is, but will appreciate any suggestions or ideas to solve this issue (if possible).
If more information is needed, please let me know.
Was brought to my attention that creating and deleting dynamic IDs can be done but keeping up with consistency of these IDs can be very tricky to work around it.
I've solved my own problem by simply creating a function that would keep count of the IDs from the amount of collapsibles inside my list and "renewing" the ID numbers on each Add and Delete.

How can I create dynamic controls and put their data into an object?

I created a div and a button. when the button clicked, there will be a group of element(included 1 select box and 2 text inputs) inserted into the div. User can add as many group as they can, when they finished type in data of all the group they added, he can hit save button, which will take the value from each group one by one into the JSON object array. But I am stuck in the part how to get the value from each group, so please help, thank you.
The code for the div and the add group button function -- AddExtra() are listed below:
<div id="roomextra">
</div>
function AddExtra() {
$('#roomextra').append('<div class=extra>' +
'<select id="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" id="insetLength">' +
'Width(m): <input type="text" id="insetWidth">' +
'Height(m): <input type="text" id="insetHeight">' +
'</div>');
}
function GetInsetOffSetArray (callBack) {
var roomIFSDetail = [{
"IsInset": '' ,
"Length": '' ,
"Width": '' ,
"Height": ''
}];
//should get all the value from each group element and write into the array.
callBack(roomIFSDetail);
}
This should just about do it. However, if you're dynamically creating these groups, you'll need to use something other than id. You may want to add a class to them or a data-* attribute. I used a class, in this case. Add those classes to your controls so we know which is which.
var roomIFSDetail = [];
var obj;
// grab all of the divs (groups) and look for my controls in them
$(.extra).each(function(){
// create object out of select and inputs values
// the 'this' in the selector is the context. It basically says to use the object
// from the .each loop to search in.
obj = {
IsInset: $('.isInset', this).find(':selected').val() ,
Length: $('.insetLength', this).val() ,
Width: $('.insetWidth', this).val() ,
Height: $('.insetHeight', this).val()
};
// add object to array of objects
roomIFSDetail.push(obj);
});
you'd better not to use id attribute to identity the select and input, name attribute instead. for example
$('#roomextra').append('<div class=extra>' +
'<select name="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" name="insetLength">' +
'Width(m): <input type="text" name="insetWidth">' +
'Height(m): <input type="text" name="insetHeight">' +
'</div>');
}
and then, usr foreach to iterate
$(".extra").each(function() {
var $this = $(this);
var isInset = $this.find("select[name='isInset']").val();
var insetLength = $this.find("input[name='insetLength']").val();
// ... and go on
});
A common problem. A couple things:
You can't use IDs in the section you're going to be repeating, because IDs in the DOM are supposed to be unique.
I prefer to use markup where I'm writing a lot of it, and modify it in code rather than generate it there.
http://jsfiddle.net/b9chris/PZ8sf/
HTML:
<div id=form>
... non-repeating elements go here...
<div id=roomextra>
<div class=extra>
<select name=isInset>
<option>Inset</option>
<option>OffSet</option>
</select>
Length(m): <input id=insetLength>
Width(m): <input id=insetWidth>
Height(m): <input id=insetHeight>
</div>
</div>
</div>
JS:
(function() {
// Get the template
var container = $('#roomextra');
var T = $('div.extra', container);
$('#addGroup').click(function() {
container.append(T.clone());
});
$('#submit').click(function() {
var d = {};
// Fill d with data from the rest of the form
d.groups = $.map($('div.extra', container), function(tag) {
var g = {};
$.each(['isInset', 'insetLength', 'insetWidth', 'insetHeight'], function(i, name) {
g[name] = $('[name=' + name + ']', tag).val();
});
return g;
});
// Inspect the data to ensure it's what you wanted
debugger;
});
})();
So the template that keeps repeating is written in plain old HTML rather than a bunch of JS strings appended to each other. Using name attributes instead of ids keeps with the way these elements typically work without violating any DOM constraints.
You might notice I didn't quote my attributes, took the value attributes out of the options, and took the type attributes out of the inputs, to keep the code a bit DRYer. HTML5 specs don't require quoting your attributes, the option tag's value is whatever the text is if you don't specify a value attribute explicitly, and input tags default to type=text if none is specified, all of which adds up to a quicker read and slimmer HTML.
Use $(".extra").each(function() {
//Pull info out of ctrls here
});
That will iterate through all of your extra divs and allow you to add all values to an array.

Categories

Resources