I'm working on a form where when user clicks "add server" a div block is repeated. I managed to work that out. But if I have only one server block I want the attribute name="servername" and if there are more elements that attribute should be name="servername[]" on all blocks.
I tried and only thing that works is when clicked add server first and second block gets name="servername[]", but when I click one more time first block gets name="servername[][]".
$('#addserver').click(function() {
var num = $('.clone').length; // how many "duplicatable" input fields we currently have
var newNum = new Number(num + 1); // the numeric ID of the new input field being added
// Create the new element via clone(), and manipulate it's ID using newNum value
var newElem = $('#server1').clone().attr('id', 'server' + newNum);
// Insert the new element after the last "duplicatable" input field
$('#server' + num).after(newElem);
// Add [] for PHP array
$('#server' + num + ' input', '#server' + newNum + ' input').attr('name', function() {
return this.name + '[]';
});
// Enable the "remove" button
$('#delserver').attr('disabled','');
// You can only add 5 elements
if (newNum == 5) $('#addserver').attr('disabled','disabled');
});
$('#delserver').click(function() {
var num = $('.clone').length; // how many "duplicatable" input fields we currently have
$('#server' + num).remove(); // remove the last element
// enable the "add" button
$('#addserver').attr('disabled','');
// If only one element remains
if (num-1 == 1) {
// Remove [] because it's not php array anymore
$('#server1 input').attr('name', function() {
s = this.name.substring(0, this.name.length - 2);
return s;
});
// Disable "remove" button
$('#delserver').attr('disabled','disabled');
}
});
$('#delserver').attr('disabled','disabled');
Here's html example:
<div class="clone" id="server1">
<input type="text" name="servername" size="40" />
</div>
I need [] because of php array, but if user is entering one server and there is [] in name it doesn't work.
I think that you should simply have name="servername[]" no matter what.
Since you can get it to work when servername contains more than one element, I don't see what stops you from having it work correctly with only one (or even none at all) element as well.
If you are not completely convinced, consider how much trouble you are having right now, trying to fight against what I suggest.
Add a check
if ($(this).attr('name').substr(-2) != '[]') {
return $(this).attr('name') + "[]";
}
Related
Ive spent several hours trying to resolve an issue with very limited experience with jQuery which is not helping me.
I am wanting to search a database for a list of results using a few input fields and then a submit button, when you click submit the values are passed to a .php script which returns the results and these are displayed in a table within a div container which works perfect.
Each record is then displayed in its own row within the table, with columns for different data.
record number
name
town
What i want is for the record number to be a click link of some kind, which when clicked, it then passes that value and does a different mysql request displaying that unique records data in more detail in a different div container. This is the part i cant get to work as i believe its something to do with BINDING, or the .ON which i dont really know anything or understand how it works, as my experience is very limited.
<script type="text/javascript">
$(document).ready(function() {
$(".click").click(function() {
var name = $("#name").val();
var name = $(this).attr("id");
$('#2').load("mysqlrequest_unique.php?recordid=" +name);
});
$("#get").click(function() {
var sales_record_number = "sales_record_number=" + $("#sales_record_number").val() + "&";
var item_id = "item_id=" + $("#item_id").val() + "&";
var user_id = "user_id=" + $("#user_id").val() + "&";
var buyer_fullname = "buyer_fullname=" + $("#buyer_fullname").val() + "&";
var sale_date = "sale_date=" + $("#sale_date").val() + "&";
var paypal_transaction_id = "paypal_transaction_id=" + $("#paypal_transaction_id").val() + "&";
var ship_to_zip = "ship_to_zip=" + $("#ship_to_zip").val() + "&";
var item_title = "item_title=" + $("#item_title").val() + "&";
$('#1').load("mysqlrequest_all.php?"+sales_record_number+item_id+user_id+buyer_fullname+sale_date+paypal_transaction_id+ship_to_zip+item_title, function(){
var name = $("#name").val();
var name = $(this).attr("id");
$('#2').load("mysqlrequest_unique.php?recordid=" +name);
}
);
});
});
</script>
<div id="1" name='container_display_all'></div>
<div id="2" name='container_display_unique'></div>
This is what each row would have in the table, which doesnt work when its contained in generated html using a jQuery
<a class = 'click' id = '19496'>19496</a>
This isn't working because you are adding html elements dynamically and the event handlers aren't being added to the dynamically added elements.
$(document).ready(...) is only run when the document loads. So if all the elements that have the class click are being added dynamically, this bit of code $(".click") (inside $(document).ready(...) ) will return a jquery object that contains no elements (as there are currently none in the DOM with the class click).
Then later your elements (with class click) are added to the DOM but have no handlers on them. What you need to do is set the handlers for those object when you add them.
So change this line:
$('#1').load("mysqlrequest_all.php?"+sales_record_number+item_id+user_id+buyer_fullname+sale_date+paypal_transaction_id+ship_to_zip+item_title);
to this:
$('#1').load("mysqlrequest_all.php?"+sales_record_number+item_id+user_id+buyer_fullname+sale_date+paypal_transaction_id+ship_to_zip+item_title, function(){
$(".click").click(function() {
var name = $("#name").val();
var name = $(this).attr("id");
$('#2').load("mysqlrequest_unique.php?recordid=" +name);
});
}
);
This code will execute the function that is passed once the new html is loaded into the first div, which will add the needed handlers to the new elements.
I have couple of input field and values in them. This is projected to the user.
The user can modify these values and submit them.
When submitted, I need to check which input field is modified.
I can compare the previous fields and current fields and check. But I am trying to find more optimized way to do this.
I can use javascript, php, jquery and html tricks
<input id="input1" value="someValue" type="text">
<input id="input2" value="someValue" type="text">
Script:
$('input').on('change',function(){
var id = $(this).attr('id');
alert("input field is modified : ID = " + id);
});
You can create 2 different input, 1 hidden with a class like originalVal and 1 visible for every input.
Then on submit you do something like that :
$('input').each(function(){
var currentVal = $(this).val();
var originalVal = $(this).closest('.originalVal').val()
if(currentVal != originalVal){
//This input has changed
}
})
Since no code was given, you could compare what was in the input compared to what is now in it.
HTML Input:
<input type="text" id="testInput" value="DB Value"/>
jQuery
var modifiedInputs = [];
var oldVal = "";
$("#testInput").focus(function() {
oldVal = this.value;
}).blur(function() {
console.log("Old value: " + oldVal + ". New value: " + this.value);
//If different value, add to array:
if (this.value != oldVal) {
modifiedInputs.push(this.id);
}
});
Fiddle: http://jsfiddle.net/tymeJV/tfmVk/1/
Edit: Took it a step further, on modification of an input, if the changed value is different from the original, it pushes the elements ID to the array.
I would say your best bet would be to get the initial values from the input fields, and then compare them later on. Then, just do a comparison once the submit button is clicked. For instance, put this somewhere in your $(document).ready() that way it will retrieve the initial value.
var oldValue=[];
$('input').each(function(){
oldValue.push($(this).val());
});
Then you can compare later on when you hit the submit.
you could compare with default value like this
for(var i in formObj)
if('value' in formObj[i] && formObj[i].value!=formObj[i].defaultValue){
//do what ever here ...
}
I have an admin page where I add and delete table rows on the fly.
The page comes loaded with the existent data in the database (mostly consisting in a sku_code and 5 different prices) but when I add rows on the fly, and fill them with the corresponding skus and prices, I want to save them as well in the database.
The problem is that what I do on the client-side with Javascript (add table rows on the fly) with innerHTML = '<input type="text"> is not accesible via $_POST variables of the main <form>
So basically i add via Javascript 's so i can fill them and save them as well in the database. But the $_POST values are empty.
Javascript code works fine. I have no clue where should i start debugging.
here's some Javascript code i'm using
function insert_record(){
var my_table = document.getElementById('my_table')
var tr = my_table.insertRow(my_table.rows.length-1)
//id-ul curent, numar toate row-urile - 1 (care este butonul OK)
var c_id = my_table.rows.length-2
tr.id = 'row_' + c_id + ''
var tr_td_1 = tr.insertCell(0)
tr_td_1.className = 'text2'
tr_td_1.align = 'center'
tr_td_1.innerHTML = 'SKU'
var tr_td_2 = tr.insertCell(1)
tr_td_2.className = 'text3'
tr_td_2.width = '63'
tr_td_2.innerHTML = '<input name="sku_' + c_id + '" type="text" id="sku_' + c_id + '" size="33" value="">'
....this addes a inside the table just before the last which contains the submit button, after which there's the
You need to assign a label to element. Then you can grab it in next page.
Instead of innerHTML = <input type="text"> try to use
<script>
function addElement(tag_type, target, parameters) {
//Create element
var newElement = document.createElement(tag_type);
//Add parameters
if (typeof parameters != 'undefined') {
for (parameter_name in parameters) {
newElement.setAttribute(parameter_name, parameters[parameter_name]);
}
}
//Append element to target
document.getElementById(target).appendChild(newElement);
}
</script>
You can call this function below either click of even or manually addElement('INPUT','targetTag',{id:'my_input_tag', name:'my_input_tag', type:'text', size:'5'});
you should give the name attribute. if you are worried about the unlimited numbers of fields just go for the array of the input variables,
like this
<input type="text" name="field1[]">
Now you can access them in post like this:
$_POST['field1'] //this is an array of fields
EDIT:
First thing is that you should use some library like jquery which eases the work.
I suggest you make sure your all your fields are inside the form and that you have named all of them instead of trying ajax or functions like #shail suggested.
In my opinion they are not solving the problem, just avoiding it.
I'm cloning input fields on a table that have an autocomplete class. When I clone the fields I have no problem. The problem is that in the cloned fields, the autocomplete doesnt work (on the one that is not cloned it does work). My autocomplete code is this:
$(document).ready(function() {
$('#btnAdd').click(function() {
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
var newNum = new Number(num + 1); // the numeric ID of the new input field being added
// create the new element via clone(), and manipulate it's ID using newNum value
var newElem = $('#input' + num).clone().prop('id', 'input' + newNum);
newElem.find(':input').each(function() {
var name = $(this).attr('name').replace(/\d+$/, '');
$(this).prop({id: name + newNum, name: name + newNum}).val("");
});
// insert the new element after the last "duplicatable" input field
$('#input' + num).after(newElem);
// enable the "remove" button
$('#btnDel').prop('disabled','');
// business rule: you can only add 15 names
if (newNum == 15)
$('#btnAdd').prop('disabled','disabled');
});
$('#btnDel').click(function() {
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
$('#input' + num).remove(); // remove the last element
// enable the "add" button
$('#btnAdd').prop('disabled','');
// if only one element remains, disable the "remove" button
if (num-1 == 1)
$('#btnDel').prop('disabled','disabled');
});
$('#btnDel').prop('disabled','disabled');
});
My Autocomplete code is :
var autoc = {
source: "lib/search.php",
minLength: 1,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.value + " aka " + ui.item.id :
"Nothing selected, input was " + this.value );
}
};
var renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a style='height:75px; text-align:center; font-weight:bold;'>"+ item.label + "</a>" )
.appendTo( ul );
};
$(".member").each(function (i) {
$(this).autocomplete(autoc).data("autocomplete")._renderItem = renderItem;
});
I've been trying to fix it by putting the autocomplete code inside of the clone code, Im not sure what Im doing wrong. It would be great if somebody could help! Thanks!
You have to reinitialize the autocomplete field after it's been cloned. And I think wrapping it within .live() is necessary as well
My solution to this was something like this:
$('#my_clone_button').live('click',function() {
my_clone_script; #this is my function to clone
$('select your new cloned input').each(function() {
$(this).autocomplete('destroy');
enable_autocomplete($(this), json_url); #this is my function to initialize autocomplete
});
});
try $('#input' + num).clone(true) passing true tells the clone to copy the events and data also. This means that it will copy that the input is a autocomplete field.
See this form - http://schnell.dreamhosters.com/form.php
This form has a portion of it where you enter data and can choose to add more of the same data by clicking a button called 'Add A Site' and it will make another of that section to enter another site. This is the jQuery that performs the duplication...
$(function () {
var sites = 1;
var siteform = $("#site1").html();
$(".addsites").live("click", function(e) {
e.preventDefault();
sites++;
$("#events").append("<div id='site" + sites + "'>"
+ "<br /><hr><br />"
+ siteform
+ "<center><button class='removesites' title='site"
+ sites + "'>Remove This Site</button><br />"
+ "<button class='addsites'>Add Another Site</button>"
+ "</center></div>");
});
$(".removesites").live("click", function(e) {
e.preventDefault();
var id = $(this).attr("title");
$("#" + id).remove();
});
});
The duplication works perfectly, but one thing that's bugging me is that when I have to enter data for someone claiming a LOT of sites, it gets very annoying having to repeat same or similar parts of this section of the form (like every site is in the same city, on the same day, by the same person, etc.) So I had the idea that with each duplication, the values of the form elements would also carry over and I just edit what's not the same. The current implementation only duplicates the elements, not the data. I'm not sure how to easily copy the data into new sections, and I can't find any jQuery tools to do that.
PS - This part isn't as important, but I've also considered using this same form to load the data back in for viewing/editing, etc. The only problem with this is that the reprinting of the form means that there will be a form section with the id "Site7" or something, but jQuery starts its numbering at 1, always. I've thought about using selectors to find the highest number site and start off the variable 'sites' at that number, but I'm not sure how. Any advice how to do this, or a better system overall, would be much appreciated.
You want to itterate over the input fields in siteform and store them in an object using their name attribute as a key.
Then after the duplication of the object you made and look for the equivelant fields in the new duplicated form ans set their values.
Somthing like this (not tested, just the idea)
var obj = new Object();
$("#site1 input").each(function(){
obj[this.id] = this.value;
);
// Dupicate form
$.each(obj, function(key, value){
$('#newform input[name="'+key+'"]').value = value;
});
Mind you these two each() functions differ from each other.
http://api.jquery.com/jQuery.each/
http://api.jquery.com/each/
You could consider using cloneNode to truely clone the previous site-div and (by passing true to cloneNode) all of its descendants and their attributes. Just know that the clone will have the same id as the original, so you'll have to manually set its id afterwards
Try this in your click-function
var clone = $("#site" + sites).clone(true, true); // clone the last div
sites++; // increment the number of divs
clone.attr('id', "site" + sites); // give the clone a unique id
$("#events").append(clone); // append it to the container
As Scuzzy points out in a comment jQuery does have its own clone() method (I don't use jQuery much, so I didn't know, and I didn't bother to check before answering). Probably better to use jQuery's method than the built-in cloneNode DOM method, since you're already using jQuery for event listeners. I've updated the code
The query to transfer values is quite simple (please, check the selector for all the right types on the form):
$("#site1").find("input[checked], input:text, input:hidden, input:password, input:submit, option:selected, textarea")
//.filter(":disabled")
.each(function()
{
$('#site2 [name="'+this.name+'"]').val(this.value);
}
Ok I finally figured this out. It's, more or less, an expansion on Alex Pakka's answer.
sites++;
$("#events").append("<div id='site" + sites + "'>"
+ "<hr><br />"
+ siteform
+ "<center><button class='removesites' title='site"
+ sites + "'>Remove This Site</button><br />");
$("#site1").find("input:checked, input:text, textarea, select").each(function() {
var name = $(this).attr("name");
var val = $(this).val();
var checked = $(this).attr("checked");
var selected = $(this).attr("selectedIndex");
$('#site' + sites + ' [name="'+name+'"]').val(val);
$('#site' + sites + ' [name="'+name+'"]').attr("checked", checked);
$('#site' + sites + ' [name="'+name+'"]').attr("selectedIndex", selected);
});
I used extra vars for readability sake, but it should do just as fine if you didn't and used the methods directly.
Dont forget to create a function for registering the event! Its very important because when the DOM is loaded, all new attributes need to be registrated to the DOM.
Small example:
<script>
$(document).ready(function(){
$('#click-me').click(function(){
registerClickEvent();
})
function registerClickEvent(){
$('<input type="text" name="input_field_example[]">').appendTo('#the-div-you-want')
}
registerClickEvent();
})
</script>