The following code populates the second select statement with HTML data. The problem I'm facing is that I clone the two select statements and on submission of the form, I'd like to save all of the selected option values from the two selects into an Array().
What would be the best way to iterate through all of the drop-down values (there's a maximum of 5 that can be added for both Subject Matter and Category)?
Thanks in advance.
$(".SubjectCategory").live("click", function () {
var $this = $(this);
var $elem = $this.closest('div').nextAll('div').first().find('select');
var a = $this.val();
$.get("/userControls/BookSubjectHandler.ashx?category=" + a, {}, function (data) {
$elem.html(data);
});
});
<div class="singleField subjectField">
<label id="Category" class="fieldSml">Subject Matter</label>
<div class="bookDetails ddl"><select id="ddlSubjectMatter" class="fieldSml SubjectCategory"></select></div>
<label id="Subjects" class="fieldSml">Category</label>
<div class="bookDetails ddl" id="subjectMatter"><select id="ddlSubjects" class="fieldSml Subjects"></select></div>
</div>
Using jQuery .map function you can retrieve all values at once:
var arrayOfValues = $(".bookDetails.ddl select").map(function (i, el) { return $(el).val(); }).get();
fiddle: http://jsfiddle.net/e9zxY/
Related
I have a form where users can create recipes. I start them off with one ingredient field (among others) and then use .append() to add as many more as they want to the div container that holds the first ingredient. The first input field has an id of IngredientName1 and dynamically added input fields are IngredientName2, IngredientName3, etc.
When they start typing in the input field, I pop a list of available ingredients filtered by the value they key into IngredientNameX. When they click on an ingredient in the list, it sets the value of the IngredientNameX field to the text from the div - like a search & click to complete thing. This all works very well; however, when you add IngredientName2 (or any beyond the one I started them with initially) clicking on an available ingredient sets the values of every single IngredientNameX field. No matter how many there are.
I hope this is enough context without being overly verbose, here's my code (I've removed a lot that is not relevant for the purpose of posting, hoping I didn't remove too much):
<div id="ingredientsContainer">
<input type="hidden" id="ingredientCounter" value="1">
<div class="ingredientsRowContainer">
<div class="ingredientsInputContainer"><input class="effect-1 ingredientsInput" type="text" name="IngredientName1" placeholder="Ingredient" id="IngredientName1" data-ingID="1"><span class="focus-border"></span></div>
</div>
<input type="hidden" name="Ingredient1ID" id="Ingredient1ID">
</div>
<script>
$(document).ready(function(){
$(document).on('keyup', "[id^=IngredientName]",function () {
var value = $(this).val().toLowerCase();
var searchValue = $(this).val();
var valueLength = value.length;
if(valueLength>1){
var theIngredient = $(this).attr("data-ingID");
$("#Ingredients").removeClass("hidden")
var $results = $('#Ingredients').children().filter(function() {
return $(this).text() === searchValue;
});
//user selected an ingredient from the list
$(".ingredientsValues").click(function(){
console.log("theIngredient: "+theIngredient);//LOGS THE CORRECT NUMBER
var selectedIngredientID = $(this).attr("id");
var selectedIngredientText = $(this).text();
$("#IngredientName"+String(theIngredient)).val(selectedIngredientText);//THIS IS WHAT SETS EVERYTHING WITH AN ID OF IngredientNameX
$("#Ingredient"+String(theIngredient)+"ID").val(selectedIngredientID);
$("#Ingredients").addClass("hidden");
});
$("#Ingredients *").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
} else {
$("#Ingredients").addClass("hidden")
}
});
$("#AddIngredient").click(function(){
var ingredientCounter = $("#ingredientCounter").val();
ingredientCounter++;
$("#ingredientCounter").val(ingredientCounter);
$('#ingredientsContainer').append('\
<div class="ingredientsRowContainer">\
<div class="ingredientsInputContainer"><input class="effect-1 ingredientsInput" type="text" name="IngredientName'+ingredientCounter+'" placeholder="Ingredient" id="IngredientName'+ingredientCounter+'" data-ingID="'+ingredientCounter+'"><span class="focus-border"></span></div>\
</div>\
<input type="hidden" name="Ingredient'+ingredientCounter+'ID" id="Ingredient'+ingredientCounter+'ID">\
');
});
});
</script>
[UPDATE] I realized the problem is happening because the function is running multiple times. I assume this happening because I'm calling a function on keyup of a field whose id starts with IngredientName so when one has a key up event, all existing fields run the function. How do i modify my:
$(document).on('keyup', "[id^=IngredientName]",function () {
to only run on the field with focus?
I have some input in my form,now I want to get the json object from the form without some input named point,What's wrong with my code?I have to remove them.It seems not work for not() function.How to fix my code?
<form id="myform">
<input name='student' value='a'/>
<input name='student' value='b'/> '
...
<input name='point' value='90'/>
<input name='point' value='95'/>
</form>
Now I only want to submit the student data to the server.So I write the code:
var data = $('#myform').not("input[name='point']").serializeArray();
var objParam = {};
$.each(data, function(i, v) {
objParam[v.name] = v.value;
});
but the result still have point data.What's wrong with not() function?
breaking down your code $('#myform') selects your form, in this case, only one object, then you filter that object with .not("input[name='point']") but there is only one object which is the form itself.
You want to filter the form's children instead, so just add .children() like this:
var data = $('#myform').children().not("input[name='point']").serializeArray();
var objParam = {};
$.each(data, function(i, v) {
objParam[v.name] = v.value;
});
Hope this will help you.
$('#myform input[name!=point]').serializeArray()
Your selector is faulty.
$('#myform').not("input[name='point']").serializeArray()
...says, "Serialise the form with ID 'myForm' which is not also an input and has the name 'point'.
Rather, you mean: "Serialise the form with ID 'myForm' but omit its child inputs with name 'point'.
Here's a non-jQuery way, using native FormData.
//get the form as form data
var fd = new FormData(document.querySelector('#myform'));
//delete any elements pertaining to [name=point]
fd.delete('point');
//et voila; this shows we retain only the student fields
for (var key of fd.keys()) alert(key);
I have a drag and drop thing which uses clone. I am having a problem with the date clone though because of datepicker. Therefore, I need to make sure each cloned datepicker has a unique id. A cloned element looks like the following
<div data-type="date" class="form-group">
<label class="control-label col-sm-5" for="dateInput">Date Input:</label>
<div class="col-sm-3">
<input type="text" name="dateInput[]" class="form-control date_picker" id="dateInput">
</div>
</div>
So if I clone two date inputs, I will have two of the above. Now on submit, I clean all of the cloned html, doing things like removing the data-type. At this stage, if there is a cloned date input, I need to give it a unique id. At the moment I am doing this
$("#content").find(".form-group").each(function() {
var html = $(this).attr('class', 'form-group')[0].outerHTML.replace(/ data-(.+)="(.+)"/g, "");
var input = $(this).find('input');
var i = 0;
if(input.attr('id') == 'dateInput') {
alert("TEST");
input.attr("id",'dateInput' + i).datepicker();
i++;
}
console.log(html);
dataArray.push(html);
});
The TEST alert fires twice as it should do if I clone 2 date inputs. However, the id attributes do not seem to change when I output the html to the console. I have set up the following Fiddle to demonstrate that the id of the element is not changing.
Any advice on getting this to change appreciated.
Thanks
Try defining dataArray, i outside out submit event, .each() , using .map() , .get() , .attr(function() {index, attr}) , .outerHTML
$(function() {
// define `i` , `dataArray`
var i = 0, dataArray = [];
$('#content').submit(function(event) {
event.preventDefault();
$("#content").find(".form-group").each(function() {
var html = $(this).attr('class', '.form-group')[0]
.outerHTML.replace(/ data-(.+)="(.+)"/g, "");
dataArray.push($(html).map(function(_, el) {
// adjust `input` `id` here , return `input` as string
return $(el).find("input").attr("id", function(_, id) {
return id + (++i)
})[0].outerHTML
}).get()[0])
});
$("#output")[0].textContent = dataArray.join(" ");
console.log(dataArray)
});
});
jsfiddle https://jsfiddle.net/mLgrfzaL/2/
http://jsfiddle.net/4px4whk0/
I have two question
when first click the checkbox (a), the first console.log should be print the dom with empty data-selected-list attribute, I don't know why it filled what I click already (["a"]) ?
I have to set timeout wrap the container.attr('data-selected-list', selectedList); then it works like what I want.
when click other checkbox (b), I hope it will be ["a","b"] store in attribute. but it only store ["b"] , why?
I hope it can be solve by store data in html attribute not only store in jquery data api
$(document).ready(function() {
$('.container').on('click', 'input[type="checkbox"]', function() {
var container = $(this).closest('.container');
var input = $(this);
console.log(container);
var selectedList = container.data('selected-list');
if (selectedList == '') {
selectedList = [];
}
if (input.is(":checked")) {
selectedList.push(input.val());
}
console.log(selectedList);
selectedList = JSON.stringify(selectedList);
container.attr('data-selected-list', selectedList);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container" data-selected-list="">
<input type="checkbox" value="a">a
<input type="checkbox" value="b">b
<input type="checkbox" value="c">c
</div>
You have several mistakes:
if you want to print the results of your array before you change it, then move the console.log call to before you push to the array
you were using attr and data interchangeably. These do two different things. attr stores the data in the DOM and data is a jquery method that stores the data somewhere within jquery itself.
finally, if you're using attr you need to do JSON.stringify to serialize your array before storing it (which you did do correctly) but when you pull the data out of the DOM you have to convert it back to an array with JSON.parse
jquery's attr returns undefined for an undefined DOM tag, not empty string
the right solution with these problems fixed is:
$(document).ready(function() {
var container = $('.container');
container.on('click', 'input[type="checkbox"]', function() {
var input = $(this);
console.log(container);
var selectedList = container.attr('data-selected-list');
if (!selectedList) {
selectedList = [];
}else{
selectedList = JSON.parse(selectedList);
}
console.log(selectedList);
if (input.is(":checked")) {
selectedList.push(input.val());
}
selectedList = JSON.stringify(selectedList);
container.attr('data-selected-list', selectedList);
});
});
here's a fiddle: http://jsfiddle.net/yLz6uv1q/
I'm using select2() field using select2 library and Drag and Drop Sorting is enabled in the field.
It works well, but once i save it, the ordering break and they are ordered alphabetically.
I was wondering if its possible to anyhow save ordering of elements after drag drop in select2() fields.
Please suggest.
Per Select2 documentation, the new ordered values are saved in a attached hidden field.
http://ivaynberg.github.io/select2/
(right click on the Input field and then inspect element to find the line below just after the div#select2-container)
There are two options that might work for you:
Option 1:Easy one
Check the ordering of how you are feeding the control, specific on:
$("#e15").select2({tags:["red", "green", "blue", "orange", "white", "black", "purple", "cyan", "teal"]});
The control just render the same order that the above line is specified.
If you are not saving those values as comma separated text and instead as row records, maybe your database query is ordering them alphabetically.
Option 2: A little bit further
This code will serve you to save the ordered values in a cookie, so you can have the same order within your whole session.
$(function(){
if ($.cookie('OrderedItemList') != null){
$("#e15").select2({tags: $.cookie('OrderedItemList').split(',')});
}
$("#e15").on("change", function() {
$("#e15_val").html($("#e15").val());
$.cookie('OrderedItemList', $("#e15").val(), { expires: 365 });
});
});
Please note, this code might not work for database bound fields, you might need to add some code if thats what you need.
Well I had your problem. I've overcome it with something like this...
A hidden input to save your order.
the listener on the select2.
$("#reports").on('change', function(){
var data = $(this).select2('data');
var array = [];
$.each(data, function(index, val) {
array[index]=val.id;
});
array.join(',');
$("input[name=reports]").val( array );
});
<form class="form-horizontal form-bordered" action="#something" method="post" accept-charset="utf-8" target="_blank" >
<input type="text" name="reports" >
<select id="reports" class="form-control select2me" multiple >
<? foreach ($Balance::getSeparators() as $key => $value ) { ?>
<option value="<?=( $key )?>"><?=( $value )?></option>
<? } ?>
</select>
</form>
This way the input[name=reports] sends to your page the correct order.
Select2 has progressed to version 4, which is based on <select/> and <option/>-tags, instead of <input/>-tags. I solved it for version 4 as follows:
$(".select2").select2().on('select2:select', function(e){
var $selectedElement = $(e.params.data.element);
var $selectedElementOptgroup = $selectedElement.parent("optgroup");
if ($selectedElementOptgroup.length > 0) {
$selectedElement.data("select2-originaloptgroup", $selectedElementOptgroup);
}
$selectedElement.detach().appendTo($(e.target));
$(e.target).trigger('change');
})
Basically I remove and re-add the selected items to the select-options-list, so that they appear in order of selection.
The hidden field solution was a good solution in my case, but Select2 plugin still keep a numerical/alphabetical(?) order, that is not the user selection's order
I found a solution, that solves all my needs.
In my symfony form declaration will be the hidden field called selectOrder in which to save the current order:
$("#form_people").on('change', function(){
var data = $(this).select2('data');
var array = [];
$.each(data, function(index, val) {
array[index]=val.id;
});
array.join(',');
$("#selectOrder").val( array );
});
and in the javascript part after form declaration there is my Multi Select2:
var sel = $("#form_people").select2({
maximumSelectionSize: 3,
minimumInputLength: 1,
escapeMarkup: function(m) { return m; },
});
then
//After reloading page you must reselect the element with the
//right previous saved order
var order = $("#selectOrder").val().split(",");
var choices = [];
for (i = 0; i < order.length; i++) {
var option = $('#form_people option[value="' +order[i]+ '"]');
choices[i] = {id:order[i], text:option[0].label, element: option};
}
sel.select2('data', choices);
It's what I need, and maybe can help other developers