jQuery File Upload not working when file input dynamically created - javascript

i am using this jquery uploader (http://blueimp.github.io/jQuery-File-Upload/basic.html) and it works fine when the file input is put in the raw code of the site, however i am dynamically appending the fields with jquery and it doesnt work. here is the jquery to trigger the upload:
$('.fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
alert(file.name);
//$('<p/>').text(file.name).appendTo(document.body);
});
}
});
and this is what SHOULD trigger the upload:
<input class="fileupload" type="file" name="files[]" data-url="uploads/">
Here is the code that is appended by jquery:
$(document).on('click','.addItem', function(){
$('<!--ROW START-->\
<form class="widget-content item" data-url="uploads/">\
<div class="row">\
<div class="col-md-3"><input type="text" class="form-control" name="itemName[]"></div>\
<div class="col-md-3"><textarea class="auto form-control" name="itemDescription[]" cols="20" rows="1" style="word-wrap: break-word; resize: vertical;"></textarea></div>\
<div class="col-md-3"><textarea class="auto form-control" name="itemCondition[]" cols="20" rows="1" style="word-wrap: break-word; resize: vertical;"></textarea></div>\
<input type="hidden" class="itemId" name="itemId[]" value="">\
<input type="hidden" name="itemInventoryId[]" value="<?=$_GET["inventory_id"]?>">\
<input type="hidden" name="itemParent[]" value="'+$(this).closest('.formHolder').data('parent-room')+'">\
<div class="col-md-2">\
<div class="fileinput-holder input-group">\
<input class="fileupload" type="file" name="files[]">\
</div>\
</div>\
<div class="col-md-1 align-center"><i class="save icon-ok large"> </i> <i class="delete icon-trash large"> </i></div>\
</div>\
</form>\
<!--/ROW END-->').fadeIn(500).appendTo($(this).parents().siblings('.items'));
$(this).parent().parent().siblings('.widget-header, .header-margin, .hide').removeClass('hide').fadeIn();
});
like i say, when i add it into the actual code, not dynamically its fine. Can someone help please?

This is because you bind fileupload event before element is added.
Try moving your code into callback function which will be executed after you create input element. Since appendTo() doesn't support callback, you can use each(callback):
$('code_that_you_append').appendTo('some_element').each(function () {
// here goes $('.fileupload').fileupload({ ... }) function
});
If you need to bind event to .fileupload in multiple places in code, you can create a function to avoid code repetition, like this:
function bindFileUpload() {
$('.fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
alert(file.name);
});
}
});
};
and then call it in the callback, like before:
$('code_that_you_append').appendTo('some_element').each(function () {
bindFileUpload();
});
I've created a little demo. It binds click instead of fileupload to simplify things (fileupload is external plugin...), but the general rule stays the same.

You need to use the jQuery live() function.
This tip I found worked for me.
jQuery fileupload for dynamically added input field

Just bind the upload function with a static identifier at first. Here, 'document' is the static identifier. You can use anything like this that has not been added dynamically. Usually, document is used more often.
$(document).on('click', '.fileupload', function () {
$('.fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
alert(file.name);
//$('<p/>').text(file.name).appendTo(document.body);
});
}
});
});

N.B: Please see accepted answer first.
I think accepted answer has little mistake. I just trying to recover that.
On #Michał Rybak little demo you will see that every time we click add item another click event also will be added to previous added new link( add more then new link and see first new link show alert number of time new item). Because every time it add new link we again add click event to all new link elements.
$('<p>new link</p>').appendTo('body').each(function () {
// bindClickToLink call every 'new link' and add click event on it
bindClickToLink();
});
To solve that issues, instead add click event to all item we just add to newly created item. Here is my solution my demo .

Related

Detect change in an <input> field controlled by a slider

I have a form with a double-handles slider:
<form id="advancedSearch" action="modules/advanced_search.xq" method="post" onsubmit="advancedSearch(this);">
<div class="slider" id="slider" data-aria-valuemin="1725" data-aria-valuemax="1786" data-slider="data-slider" data-start="1725" data-end="1786" data-initial-start="1725" data-initial-end="1786">
<span id="handle1" class="slider-handle" data-slider-handle="data-slider-handle" role="slider" tabindex="1" aria-controls="dateFrom"/>
<span id="handle2" class="slider-handle" data-slider-handle="data-slider-handle" role="slider" tabindex="1" aria-controls="dateTo"/>
[...]
<input type="number" max="1786" min="1725" id="dateFrom" name="dateFrom"/>
</div>
<div class="cell small-2">
<input type="number" max="1786" min="1725" id="dateTo" name="dateTo"/>
[...]
</form>
It all works well.
Now, I'd like to call the function advancedSearch() when changing the slider's handle, without having to hit 'submit' each time.
Adding a oninput='advancedSearch(this.form); return false;' to the <input> elements does the trick only if I change the numbers inside the <input> field. When using the sliders, although document.getElementById('dateFrom').value does get changed, does not trigger the function. onchange also doesn't work. How can I call the function when changing the number by using the slider itself, other than changing the numbers inside the <input> field manually?
Adding a separate function:
document.getElementById('dateFrom').addEventListener('change', (event) => {
var formData = document.getElementById('advancedSearch')
advancedSearch(formData)
});
yields the same result.
Thanks to Prikesh Savla for pointing me towards the changed.zf.slider event. Unfortunately when implementing that with:
$("#slider").on('change changed.zf.slider', function(){ { var formData = document.getElementById('advancedSearch') advancedSearch(formData); }});
the page calls the function when loading it (either refreshing or landing there). After some troubleshooting I haven't been able to find the reason for that. In the end I'm adding this code:
document.querySelector('.slider').addEventListener("click", function () {
advancedSearch(document.getElementById('advancedSearch'));
});
document.getElementById('dateFrom').addEventListener("input", function () {
advancedSearch(document.getElementById('advancedSearch'));
});
document.getElementById('dateTo').addEventListener("input", function () {
advancedSearch(document.getElementById('advancedSearch'));
});
which does what I want, although I appreciate that it's not the most elegant solution.

Why isn't jQuery append method working when passing parent class to add a child input?

I want to append a duplicate of an input box in a parent box. Here is my HTML structure:
<div class="reading-group input-group">
<input type="text" placeholder="Enter Reading link" id="link">
</div>
+ Add another link
And here is my jQuery code:
function addPlaceholder(parentClass){
var placeHolder = $(parentClass).children().eq(0);
$(parentClass).append(placeHolder);
console.log(placeHolder);
}
$('.add-reading-btn').click(function(){
addPlaceholder('.reading-group');
});
Here is the jsfiddle link: https://jsfiddle.net/abhishekraj007/kexe6gxn/
What am I doing wrong?
Your code is taking the existing <input> element and moving it from the <div> and back into the <div>, so it looks like nothing is happening. If you .clone() the element and then .append() it, a new element will be added.
Here is a working example:
function addPlaceholder(parentClass) {
var placeHolder = $(parentClass).children().eq(0).clone();
$(parentClass).append(placeHolder);
console.log(placeHolder);
}
$('.add-reading-btn').click(function() {
addPlaceholder('.reading-group');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="reading-group input-group">
<input type="text" placeholder="Enter Reading link" id="link">
</div>
+ Add another link
If you want to add focus to your <input> element on load, you can do so by adding this line to the bottom of your code:
$('#link').focus();
If you want to add focus to the new element on creation, as well as give it an empty value rather than copying the prior element's value, add this line to the end of your addPlaceholder() function:
$(placeHolder).val("").focus();
you can just add the .clone() method of jquery to create a clone of the textbox like below . You were only referring to the same element not the cloned html before.
$(document).ready(function(){
function addPlaceholder(parentClass){
var placeHolder = $(parentClass).children().eq(0).clone();
$(parentClass).append(placeHolder);
//console.log(placeHolder);
}
$('.add-reading-btn').click(function(){
addPlaceholder('.reading-group');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="reading-group input-group">
<input type="text" placeholder="Enter Reading link" id="link">
</div>
+ Add another link
Here is a working fiddle
https://jsfiddle.net/kexe6gxn/2/

parsley.js does not work for ckeditor textarea

I wrote code for my form with parsley.js validator, however it works fine except CKEditor textareas. Where can be the problem? Here is screenshot
Here is my code:
<script type="text/javascript">
CKEDITOR.on('instanceReady', function(){
$.each( CKEDITOR.instances, function(instance) {
CKEDITOR.instances[instance].on("change",function(e) {
for ( instance in CKEDITOR.instances)
CKEDITOR.instances[instance].updateElement();
});
});
});
</script>
<h2 class="heading">Description</h2>
<div class="controls">
<textarea name="description" id="description" required="" data-parsley-errors-container="#description-errors" data-parsley-required-message="Это поле необходимо!"></textarea>
</div>
<div style="margin-bottom: 20px;" id="description-errors"></div>
<script>
CKEDITOR.replace('description');
</script>
<h2 class="heading">Purpose</h2>
<div class="controls">
<textarea name="purpose" id="purpose" required="" data-parsley-errors-container="#purpose-errors" data-parsley-required-message="Это поле необходимо!"></textarea>
<div style="margin-bottom: 20px;" id="purpose-errors"></div><br><br>
<button type="submit" name="submit">Submit</button>
</div>
<script>
CKEDITOR.replace('purpose');
</script>
Your issue is related to the required attribute. After, this line:
CKEDITOR.on('instanceReady', function () {
you need to add such an attribute again, for each text area, because lost during CKEDITOR init phase (i.e.: CKEDITOR.replace('purpose');).
For a specific textarea you can write:
$('#description').attr('required', '');
For all the textareas belonging to the form:
$('form textarea').attr('required', '');
From your comment:
When the error shows in other inputs and when I type something it removes automatically. But in textareas it does not leave
In order to solve this part, on CKEDITOR change event, you need to trigger parsley validation. The below line does the trick:
$('form').parsley().validate();
The updated code (jsfiddle here):
CKEDITOR.on('instanceReady', function () {
$('form textarea').attr('required', '');
$.each(CKEDITOR.instances, function (instance) {
CKEDITOR.instances[instance].on("change", function (e) {
for (instance in CKEDITOR.instances) {
CKEDITOR.instances[instance].updateElement();
$('form').parsley().validate();
}
});
});
});
It's always so much easier to answer questions if you provide a minimal working example...
ckeditor hides the <textarea> and fills it in via Javascript.
Maybe the issue is that the error container is in the wrong place.
It's also very possible that ckeditor doesn't trigger the input event (not very well known). If that's the case, the following code should resolve the issue:
$('textarea').on('change', function() { $(this).trigger('input') })
Please update if this works or not.

After click on button in Form append html page by Ajax

I am using Jquery mobile frame work and also new in jquery mobile. I want to append one html page by Ajax. First i am taking one button(check) in form but whenever click on this button then page appended but layout will be damage. I don't know how to append HTML page by ajax in jquery mobile.
SCREEN SHOT FOR HINTS:
This page is before click on check button:
After click on Check button:
HTML CODE:
<form id="checkPinCode1" method="get" data-uri="<c:url value="/pincode-available/${product.productId}/${product.productOfCityId}"/>" data-ajax="false">
<div style="margin-bottom: 20px; width: 80%;">
<input name="pinCode" type="number" class="form-control pinCode" placeholder=" Enter pincode here..">
</div>
<div style="margin-bottom: 20px; width:40%;">
<button class="btn btn-primary" type="submit" value="Check">Check</button>
</div>
</form>
<div id="showPincodeAvailablity">
<%--APPEND PAGE HERE--%>
</div>
AJAX CODE:
$.ajax({
type: 'get',
url: url,
data: {pincode: pincode},
success: function (response) {
if (response.success === "true") {
$("#showPincodeAvailablity").html(response.html);
}
},
error: function (response) {
},
complete: function (response) {
}
});
JAVA CODE:
#RequestMapping(value = "/pincode-available/{productId}/{productOfCityId}", method = {RequestMethod.GET})
#ResponseBody
<%--- CODE LINE 1--%>
<%--- CODE LINE 2--%>
<%--- CODE LINE .....--%>
resp.put("success", "true");
resp.put("html", html);
}
First i am type pin code and click on check button then check button control go to the controller and comes into the ajax then page append by id = showPincodeAvailablity. and page appended but page layout is not comes proper way. Give me some idea for achieving this solution.
Try changing this line
$("#showPincodeAvailablity").html(response.html);
to this
$("#showPincodeAvailablity").html(response.html).enhanceWithin();

Remove element on click with Jquery [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 years ago.
I'm creating new input field with JQuery that include a remove button. The remove button works on the original element but does not work on those that were created using JQuery.
document after two new email fields added
<fieldset>
<legend>Send Email</legend>
<label>Emails(s) to send notice to.</label>
<p>
<input type="email" name="emails[]" style="cursor: auto; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVQ4EaVTO26DQBD1ohQWaS2lg9JybZ+AK7hNwx2oIoVf4UPQ0Lj1FdKktevIpel8AKNUkDcWMxpgSaIEaTVv3sx7uztiTdu2s/98DywOw3Dued4Who/M2aIx5lZV1aEsy0+qiwHELyi+Ytl0PQ69SxAxkWIA4RMRTdNsKE59juMcuZd6xIAFeZ6fGCdJ8kY4y7KAuTRNGd7jyEBXsdOPE3a0QGPsniOnnYMO67LgSQN9T41F2QGrQRRFCwyzoIF2qyBuKKbcOgPXdVeY9rMWgNsjf9ccYesJhk3f5dYT1HX9gR0LLQR30TnjkUEcx2uIuS4RnI+aj6sJR0AM8AaumPaM/rRehyWhXqbFAA9kh3/8/NvHxAYGAsZ/il8IalkCLBfNVAAAAABJRU5ErkJggg==); background-attachment: scroll; background-position: 100% 50%; background-repeat: no-repeat;"><span class="btn_orange">x</span>
</p>
<p><input type="email" name="emails[]"><span class="btn_orange">x</span></p><p><input type="email" name="emails[]"><span class="btn_orange">x</span></p><p>
<span class="btn_orange"><a class="add_email_button" href="#">Add Another Email</a></span>
</p>
<p>
<span class="btn_orange"><a class="ui-button">Send Email</a></span>
</p>
</fieldset>
Script
<script type="text/javascript">
$(document).ready(
function () {
$("#importbutton").click(function () {
$("#ProgressBarImg").show();
$.get('#Url.Action("Import", "Import")', {},
function (data) {
$('body').html(data);
$('#ProgressBarImg').hide();
});
$("#importbutton").removeAttr("href");
}
);
var dialog = $("#emailSection").dialog({
autoOpen: false,
height: 400,
width: 475,
modal: true
});
$('#emailButton').click(function () {
$(dialog).dialog("open");
$('#emailButton').removeAttr('href');
});
$('.add_email_button').closest('p').click(function () {
var html = '<p><input type="email" name="emails[]" /><span class="btn_orange">x</span></p>';
$(html).insertBefore($(this));
});
$('a.remove_field').closest('p').click(function () {
$(this).remove();
});
}
);
</script>
You're setting an event on the element that is on the page initially. After you add new elements, the new elements don't have the handler, you could add it ass you add them, but that's the best way.
Use event delegation: http://jsfiddle.net/mendesjuan/4my1dhw1/
$(document).on('click', 'a.remove_field', function () {
$(this).closest('p').remove();
});
That means you are listening for clicks on the whole document, but filtering for only the ones you're interested in.
The second benefit is that you don't need a separate handler for each element, saving you memory
The code I posted differs in behavior from what you had in that it requires that you click the x. Your code would delete when you click anywhere in the <p>. The reason I changed it is because there is no CSS selector that mimics what closest('p')does, that is CSS selectors do not go up the tree. However, what I have seems to make more sense, and you probably were using closest('p') only because you wanted to delete the entire <p>, but you can do that from inside the handler.
For elements that were added after page load you should use:
$('body').on('click', '.classSelector', function(e) {
});

Categories

Resources