I'm trying to use jQuery to duplicate my file input groups, so that when the user selects a file to upload, it automatially creates another file upload field and description field.
This works fine, except for when I change the file of a file I've already selected an input for. When I do that, it duplicates ALL the file input groups.
Any insight into why this is going on?
JSFiddle: http://jsfiddle.net/czLmbjd6/4/
HTML:
<div id = "add-photos">
<input type="file"></input>
<label>Description:</label>
<input type = "text"></input>
</div>
<div id = "additional-photos">
</div>
JS:
$(document).ready(function(){
bindFileInputs();
});
function bindFileInputs(){
$("input:file").change(function (){
addPhotoField();
});
}
function addPhotoField() {
var id = 1; //standin for now, will dynamically update this number later
createPhotoField(id);
}
function createPhotoField(id){
var p = $("#add-photos");
p.clone().appendTo("#additional-photos").removeAttr("id").children().find('input,select').each(function(){
$(this).val('');
if ($(this).attr('type') == 'file'){
console.log("type is file");
$(this).attr('name', 'data[Image][' + id + '][image]');
}
if ($(this).attr('type') == 'text'){
console.log("type is text");
$(this).attr('name', 'data[Image][' + id + '][description]');
}
});
bindFileInputs();
}
Try
$(document).ready(function() {
bindFileInputs($('#add-photos input[type="file"]'));
});
function bindFileInputs(input) {
//use one() to register a handler which will be fired only once
input.one('change', function() {
addPhotoField();
});
}
function addPhotoField() {
var id = 1; //standin for now, will dynamically update this number later
createPhotoField(id);
}
function createPhotoField(id) {
var p = $("#add-photos");
var $clone = p.clone().appendTo("#additional-photos").removeAttr("id");
$clone.find('input,select').val('');
$clone.find('input:text').attr('name', 'data[Image][' + id + '][description]');
var $file = $clone.find('input:file').attr('name', 'data[Image][' + id + '][image]');
bindFileInputs($file)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Select a file with the file upload control. It should create a new file input group.
<div id="add-photos">
<input type="file" />
<label>Description:</label>
<input type="text" />
</div>
<div id="additional-photos"></div>
Try this Js:
$(document).ready(function(){
bindFileInputs();
});
function bindFileInputs(){
$("input:file").change(function (){
if($('.newF').length ==0 ){
createPhotoField(Number($(this).attr('id'))+1);
}
if($(this).hasClass('newF')){
createPhotoField(Number($(this).attr('id'))+1);
}
});
}
function createPhotoField(id){
$('.newF').removeClass('newF')
id+=1;
var p = $("<div/>");
p.appendTo("#additional-photos");
p.html('<input class="newF" id= "'+id+'" type="file"></input><label>Description:</label><input type = "text"></input>')
p.children().find('input,select').each(function(){
$(this).val('');
if ($(this).attr('type') == 'file'){
console.log("type is file");
$(this).attr('name', 'data[Image][' + id + '][image]');
}
if ($(this).attr('type') == 'text'){
console.log("type is text");
$(this).attr('name', 'data[Image][' + id + '][description]');
}
})
bindFileInputs();
}
UPDATED FIDDLE:
http://jsfiddle.net/czLmbjd6/12/
See your call of bindFileInputs(); in createPhotoField. You are adding another handler to change event of all $("input:file") elements in your page. If you change the file in any of these elements (except the last one), addPhotoField will fire two or more times.
Do:
var newItem = p.clone();
newItem.appendTo("#additional-photos").removeAttr("id").children().find('input,select').each(function(){
...
});
// instead of bindFileInputs();
newItem.find("input:file").change(function (){
addPhotoField();
});
Well try this
<div id = "add-photos">
<input type="file" inuse="false"></input>
<label>Description:</label>
<input type = "text"></input>
</div>
<div id = "additional-photos">
</div>
$(document).ready(function(){
bindFileInputs();
});
function bindFileInputs(){
$("input:file").change(function (){
if($(this).attr('inuse') == "false"){
addPhotoField();
}
$(this).attr('inuse', 'true');
});
}
var id = 0;
function addPhotoField() {
id += 1; //standin for now, will dynamically update this number later
createPhotoField(id);
}
function createPhotoField(id){
$("#add-photos").find('input:file').attr('inuse', 'false');
var p = $("#add-photos");
p.clone().appendTo("#additional-photos").removeAttr("id").children().find('input,select').each(function(){
$(this).val('');
if ($(this).attr('type') == 'file'){
console.log("type is file");
$(this).attr('name', 'data[Image][' + id + '][image]');
$(this).attr('inuse', 'false');
}
if ($(this).attr('type') == 'text'){
console.log("type is text");
$(this).attr('name', 'data[Image][' + id + '][description]');
}
});
$("#add-photos").find('input:file').attr('inuse', 'true');
bindFileInputs();
}
Related
I am using the multiselect jQuery plugin in my ci app
<div class="controls"><select name="delivery_method_' + cloneCntr + '[]" multiple="multiple" class="dm_list_data">' + delivery_method_options + '</select></div>';
$(function () {
$('.dm_list_data').multiselect({
includeSelectAllOption: true,
buttonWidth: '170px',
nonSelectedText: 'Select Delivery Method',
});
});
I have created a function on change. In the function I am not getting unchecked values, it's showing only checked values:
$('.dm_list_data').on('change', function() {
var ischecked= $(this).is(':checked');
if(!ischecked){
alert('uncheckd ' + $(this).val());
} else {
alert("checked");
}
});
Hope this will help you :
see the working example : https://jsfiddle.net/3b4dqhfc/5/
Use jquery's not to get the desired result like this
$(document).ready(function(){
$('.dm_list_data').on('change', function() {
/* use this for unselected value*/
$('.dm_list_data option').not(':selected').each(function(k,v){
console.log(k,v.text, v.value);
});
/* use this for selected value*/
$('.dm_list_data :selected').each(function(k,v){
console.log(k,v.text, v.value);
});
});
});
On every change setup some attribute to unselected and add them in the array.
$('.dm_list_data').on('change', function() {
var $sel = $(this);
val = $(this).val();
$opts = $sel.children();
prevUnselected = $sel.data('unselected');
var currUnselected = $opts.not(':selected').map(function() {
if($("#new-input-"+this.value).length > 0){
$("#new-input-"+this.value).remove();
}
return this.value
}).get();
var currSelected = $('.dm_list_data').val();
$.each(currSelected, function(index, item) {
if($("#new-input-"+item).length == 0){
$("#new-options").append("<input type='text' id='new-input-"+item+"' value='"+item+"'>");
}
});
});
Updated as needed
Add one new div <div id="new-options"></div>
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 5 years ago.
In my AJAX success function, I've written:
rt = JSON.parse(responseText);
for (i = 0; i < rt.length; i++) {
$("#inv").append("<tr><td>" + rt[i][0] +
"</td><td><input type='submit' value='Sync' " +
"class='syncnow' id='sync"+rt[i][6]+"' /></td></tr>");
}
I've tried jQuery code:
$(".syncnow").on("click", function() {
alert("Hi");
});
Tried .click(), $(".tdclass").on("click", ".syncnow", function() {}) etc., but to no avail. Can anyone help me with this?
You can't add an event to a not yet created element. You need to add it to a higher place and catch it when it is bubbling up.
Try this:
$("body").on("click", ".syncnow", function() {
console.log('clicked');
} )
$("#inv").append("<input type='submit' value='Sync' class='syncnow' id='sync' />");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="inv">
</div>
You can attach event to element when created using jQuery()
$.each(rt, function(i, value) {
$("<tr>", {
appendTo: "#inv",
html: $("<td>", {
html: value[0],
append: $("<input>", {
type: "submit",
value: "Sync",
"class": "syncnow",
id: value[6],
on: {
click: function(event) {
console.log("clicked");
}
}
})
})
})
})
Try this one
$(document).on("click", ".syncnow", function() {
alert('clicked');
} )
$("#inv").append("<input type='submit' value='Sync' class='syncnow' id='sync' />");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="inv">
</div>
I've written a jquery function, to append syncbuttons to an invElement
$.fn.appendSyncElements = function(responseText, onComplete) {
var invElement = $(this);
var rt = JSON.parse(responseText);
var base_sync_attrs = [];
base_sync_attrs.push("type=\"submit\"");
base_sync_attrs.push("value=\"Sync\"");
base_sync_attrs.push("class=\"syncnow\"");
var base_sync_attrs_str = base_sync_attrs.join(' ');
for(var i = 0; i < rt.length; i++) {
var crt = rt[i];
var crt_sync_label = crt[0];
var crt_sync_attrs = crt[6];
var sync_attrs = [];
sync_attrs.push(base_sync_attrs_str);
sync_attrs.push("id=\"sync_" + String(i) + "\"");
sync_attrs.push("data-sync_index=\"" + String(i) + "\"");
sync_attrs.push(crt_sync_attrs);
var sync_attrs_str = sync_attrs.join(' ');
var syncElement = $('<input ' + sync_attrs_str + ' />');
syncElement.click(function(e) {
var syncBtn = $(this);
console.log("the syncBtn was clicked at index " + String(syncBtn.data('sync_index'));
var syncEvent = {
'event' : e,
'button' : syncBtn,
'fullresponse': crt,
};
if(typeof(onComplete) === 'function') {
onComplete(syncEvent)
};
});
var tableRowElement = $('<tr><td class="synclabel" ></td><td class="syncinput" ></td></tr>');
tableRowElement.find("td.synclabel").html(crt_sync_label);
tableRowElement.find("td.syncinput").append(syncElement);
invElement.append(tableRowElement);
};
};
Usage
$("#inv").appendSyncElements(responseText);
Or
$("#inv").appendSyncElements(responseText, function(syncResult) {
console.log("This is a custom Complete Method");
});
You can use document on click event:
$(document).on("click",".syncnow",function() {
alert("Working");
});
Also you can check my answer here:
Why is jQuery on-click event handler not working properly for dynamic loaded DOM elements?
Thanks
$("body").on("click",".syncnow", function() {} )
I have a form, and I would like to clear the input field every time I enter the submit (plus) button.
I have tried using this, it does not work. I may be implementing it in the wrong spot.
document.getElementById('add-item').value='';
My Javascript code is below.
window.addEventListener('load', function(){
// Add event listeners
document.getElementById('add-item').addEventListener('click', addItem, false);
document.querySelector('.todo-list').addEventListener('click', toggleCompleted, false);
document.querySelector('.todo-list').addEventListener('click', removeItem, false);
function toggleCompleted(event) {
console.log('=' + event.target.className);
if(event.target.className.indexOf('todo-item') < 0) {
return;
}
console.log(event.target.className.indexOf('completed'));
if(event.target.className.indexOf('completed') > -1) {
console.log(' ' + event.target.className);
event.target.className = event.target.className.replace(' completed', '');
document.getElementById('add-item').value='';
} else {
console.log('-' + event.target.className);
event.target.className += ' completed';
}
}
function addItem() {
var list = document.querySelector('ul.todo-list');
var newItem = document.getElementById('new-item-text').value;
var newListItem = document.createElement('li');
newListItem.className = 'todo-item';
newListItem.innerHTML = newItem + '<span class="remove"></span>';
list.insertBefore(newListItem, document.querySelector('.todo-new'));
}
function removeItem(event) {
if(event.target.className.indexOf('remove') < 0) {
return;
}
var el = event.target.parentNode;
el.parentNode.removeChild(el);
}
});
This is what you need:
document.getElementById('new-item-text').value = "";
regarding your need, you will need to put it at the end of your addItem()
you can refer this simple code:
<html>
<body>
<input type="text" id="test">
<button onclick="func()">remove</button>
<br/>
Value = <span id="val"></span>
<script>
function func(){
alert("clicked");
document.getElementById('val').innerHTML = document.getElementById('test').value;
document.getElementById('test').value = '';
}
</script>
</body>
</html>
Use form reset method to clear inputs in one go.
document.getElementById("myForm").reset();
You can set your textbox value = '' in submit button.
and you can create a ClearFunction and then you can call it everytime you need it.
function cleartextbox() {
$('#name').val("").focus();
$('#selectgender').val("");
$('#telephone').val("");
}
I created a function that creates a HTML chunk of code. Its ids are created dynamically with a tag variable collected from a form. Code:
$(function() {
$("#addTag").click(function() {
var tag = $("#tag").val();
$('section').append('<div id="galleryContainer' + tag + '"><div class=".gallery-header"><h1 >Tag:' + tag + '</h1><div class=".gallery-sort"><p>Sort by:</p><button onclick="sortImagesByPublishedDate()" >Data published</button><button onclick="sortImagesByTakenDate()">Data taken</button><div data-tag="' + tag + '" class="gallery component" id="' + tag + '"></div></div></div></div>');
mainFunction(tag);
});
});
Then I want to use sortImagesByPublishedDate() and sortImagesByTakenDate() by clicking a button, but I want them to sort images only in this particular gallery and not in all galleries. If I have one gallery, it works fine. Problems begin when I add more galleries. How should I select the variable $gallery in the following functions?
function sortImagesByPublishedDate() {
var $gallery = $('div.gallery'),
$galleryA = $gallery.children('a');
$galleryA.sort(function(a, b) {
var an = a.getAttribute('data-published'),
bn = b.getAttribute('data-published');
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
$galleryA.detach().appendTo($gallery);
}
Use the .siblings method to select elements that are siblings of another element. So in your case you can just call
var $gallery = $(buttonElement).siblings(".gallery");
Since you are using inline JS to call the sort functions you need to modify it to pass this to your functions that way you can get a reference to the button that was clicked, ie:
Modified html
<button onclick="sortImagesByPublishedDate(this)">Date published</button>
JS
function sortImagesByPublishedDate(ele){
var $gallery = $(ele).siblings(".gallery"),
Demo
$(function(){
$("#addTag").click(function(){
var tag=$("#tag").val();
$('section').append('<div id="galleryContainer'+tag+'"><div class=".gallery-header"><h1 >Tag:'+tag+'</h1><div class=".gallery-sort"><p>Sort by:</p><button onclick="sortImagesByPublishedDate(this)" >Data published</button><button onclick="sortImagesByTakenDate(this)">Data taken</button><div data-tag="'+tag+'" class="gallery component" id="'+tag+'"></div></div></div></div>');
//mainFunction(tag);
});
});
function sortImagesByPublishedDate(ele){
var $gallery = $(ele).siblings(".gallery"),
$galleryA = $gallery.children('a');
alert($gallery[0].id);
$galleryA.sort(function(a,b){
var an = a.getAttribute('data-published'),
bn = b.getAttribute('data-published');
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
$galleryA.detach().appendTo($gallery);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="tag">
<button id="addTag">Add</button>
<section>
</section>
Instead of inline js you could use delegated event handling to have listeners setup for your buttons:
Modified html
<button class="sortButton" data-sort="date">Data published</button>
<button class="sortButton" data-sort="taken">Data taken</button>
JS
$("section").on("click",".sortButton",function(){
//'this' will be the button clicked
var $gallery = $(this).siblings(".gallery");
var sortBy = $(this).data("sort");
if(sortBy == "date"){
//do date sort
} else if(sortBy == "taken"){
//do taken sort
}
//... rest of code
});
$(function() {
$("#addTag").click(function() {
var tag = $("#tag").val();
$('section').append('<div id="galleryContainer' + tag + '"><div class=".gallery-header"><h1 >Tag:' + tag + '</h1><div class=".gallery-sort"><p>Sort by:</p><button onclick="sortImagesByPublishedDate()" >Data published</button><button onclick="sortImagesByTakenDate()">Data taken</button><div data-tag="' + tag + '" class="gallery component" id="' + tag + '"></div></div></div></div>');
sortImagesByPublishedDate(tag); **// call the function and pass param tag**
mainFunction(tag);
});
});
function sortImagesByPublishedDate(tag) {
**// instead of class select id**
var $gallery = $('div#galleryContainer'+tag),
$galleryA = $gallery.children('a');
$galleryA.sort(function(a, b) {
var an = a.getAttribute('data-published'),
bn = b.getAttribute('data-published');
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
$galleryA.detach().appendTo($gallery);
}
// hope this helps
Not tested but I think this will worl:
HTML:
sortImagesByPublishedDate(this)//pass this
JS:
function sortImagesByPublishedDate() {
var $gallery = $(this).siblings('.gallery'),
$galleryA = $gallery.children('a');
.
.
Pass this to sortImagesByPublishedDate(this) in your html of append
so your code is
function sortImagesByPublishedDate(thisObj) {
and then do
var $gallery = $(thisObj).siblings(".gallery");
I've just created an dynamic HTML form and two of its fields are of type date. Those two fields are posting their data into two arrays. I have 2 issues:
a) The array data are not printed when I press the button.
b) Since I created the arrays to store the data, my dynamic form doesn't seem to be fully functional. It only produces new fields when I press the first "Save entry" button on the form. It also doesn't delete any fields.
My code is:
$(document).ready(function () {
$('#btnAdd').click(function () {
var $address = $('#address');
var num = $('.clonedAddress').length;
var newNum = new Number(num + 1);
var newElem = $address.clone().attr('id', 'address' + newNum).addClass('clonedAddress');
newElem.children('div').each(function (i) {
this.id = 'input' + (newNum * 10 + i);
});
newElem.find('input').each(function () {
this.id = this.id + newNum;
this.name = this.name + newNum;
});
if (num > 0) {
$('.clonedAddress:last').after(newElem);
} else {
$address.after(newElem);
}
$('#btnDel').removeAttr('disabled');
});
$('#btnDel').click(function () {
$('.clonedAddress:last').remove();
$('#btnAdd').removeAttr('disabled');
if ($('.clonedAddress').length == 0) {
$('#btnDel').attr('disabled', 'disabled');
}
});
$('#btnDel').attr('disabled', 'disabled');
});
$(function () {
$("#datepicker1").datepicker({
dateFormat: "yy-mm-dd"
}).datepicker("setDate", "0");
});
var startDateArray = new Array();
var endDateArray = new Array();
function intertDates() {
var inputs = document.getElementsById('datepicker1').value;
var inputsend = document.getElementsById('datepicker2').value;
startDateArray[startDateArray.length] = inputs;
endDateArray[endDateArray.length] = inputsend;
window.alert("Entries added!");
}
function show() {
var content = "<b>Elements of the arrays:</b><br>";
for (var i = 0; i < startDateArray.length; i++) {
content += startDateArray[i] + "<br>";
}
for (var i = 0; i < endDateArray.length; i++) {
content += endDateArray[i] + "<br>";
}
}
JSFIDDLE
Any ideas? Thanks.
On your button you are using element ID's several times, this is so wrong, IDs must be unique for each element, for example:
<button id="btnAdd" onclick="insertDates()">Save entry</button>
</div>
</div>
<button id="btnAdd">Add Address</button>
<button id="btnDel">Delete Address</button>
jQuery will attach the $('#btnAdd') event only on the first #btnAdd it finds.
You need to use classes to attach similar events to multiple elements, and in addition to that simply change all the .click handlers to .on('click', because the on() directive appends the function to present and future elements where as .click() only does on the existing elements when the page is loaded.
For example:
<button id="btnDel">Delete Address</button>
$('#btnDel').click(function () {
[...]
});
Becomes:
<button class="btnDel">Delete Address</button>
$('.btnDel').on('click', function () {
[...]
});
Try this : I know its not answer but it's wrong to get element value using id
Replace
var inputs = document.getElementsById('datepicker1').value;
var inputsend = document.getElementsById('datepicker2').value;
With
var inputs = document.getElementById('datepicker1').value;
var inputsend = document.getElementById('datepicker2').value;
You are using jQuery so i will strongly recommend you to stick with the jQuery selector,
var inputs = $('#datepicker1').val();
var inputsend = $('#datepicker2').val();
where # is used for ID selector.