How can i check number of files selected with Fine Uploader? - javascript

I am using manual uploading via Fine Uploader. Now i want to check that file has selected or not.
$(document).ready(function() {
var fineuploader = new qq.FineUploader({
element: $('#fine-uploader')[0],
request: {
endpoint: '<?php echo site_url('pl_items/upload_images');?>'
},
multiple: true,
autoUpload: false,
onLeave: false,
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
sizeLimit: 5120000 // 50 kB = 50 * 1024 bytes
},
text: {
uploadButton: '<i class="icon-plus icon-white"></i> Select Files'
},
template: '<div class="qq-uploader">' +
'<pre class="qq-upload-drop-area"><span>{dragZoneText}</span></pre>' +
'<div class="qq-upload-button btn btn-danger">{uploadButtonText}</div>' +
'<div class="qq-drop-processing span1"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></div>' +
'<div><ul class="qq-upload-list"></ul></div>' +
'</div>',
callbacks: {
onComplete: function(id, name, response) {
$('#frmDetails').append('<input type="hidden" name="pl_item_images[]" value="'+response.file_name+'">');
//$("#frmDetails").submit();
}
},
});
$('#submit_button').click(function() {
fineuploader.uploadStoredFiles();
});
});

Since you haven't responded to my question, I'll just assume that you want to determine if a file has been selected before you call uploadStoredFiles in your click handler.
It's really very simple. Just make use of the getUploads API method. For example, you could change your click handler to look like this:
$('#submit_button').click(function() {
var submittedFileCount = fineuploader.getUploads({status: qq.status.SUBMITTED}).length;
if (submittedFileCouunt > 0) {
fineuploader.uploadStoredFiles();
}
});
A few more things:
There is no onLeave option. You should remove this from your code.
The multiple option defaults to true. You can remove this from your code as well.
You are already using jQuery. Why aren't you using the Fine Uploader jQuery plug-in? See the documentation for instructions.

Related

Add a "Show Less" button to InstafeedJS

Using InstafeedJS, I want to be able to add a button that hides whatever content has been loaded after the initial feed (e.g. the user has clicked Show More one or more times). My initial idea is to add a class or data tag to the additional feed items, then hide them with a custom button. But I'm not sure how to add these references through the script. Any ideas?
Current code:
var loadButton = document.getElementById('instafeed-loadmore');
var feed = new Instafeed({
get: 'user',
type: 'image',
limit: '5',
sortBy: 'most-recent',
resolution: 'standard_resolution',
userId: <?php echo $instagram_id; ?>,
accessToken: '<?php echo $instagram_token; ?>',
template: '<li><span class="instagram-post" data-url="{{link}}" data-modal="instagram-popup" data-caption="{{caption}}" data-image="{{image}}" style="background-image: url({{image}});"></span></li>',
after: function() {
if (!this.hasNext()) {
loadButton.setAttribute('disabled', 'disabled');
}
}
});
loadButton.addEventListener('click', function() {
feed.next();
});
feed.run();
While Dipen's answer is great, as you don't seem to be using jQuery, here it is in standard Js
var limit = 4;
var feed = new Instafeed({
target: 'instafeed',
get: 'user',
type: 'image',
sortBy: 'most-recent',
limit: limit,
resolution: 'standard_resolution',
userId: <?php echo $instagram_id; ?>,
accessToken: '<?php echo $instagram_token; ?>',
template: '<img class="instagram-post" src={{image}} />',
after: function() {
if (!this.hasNext()) {
document.getElementById('btnMore').attr('disabled', 'disabled');
}
}
});
document.getElementById('btnMore').on('click', function(e) {
document.getElementsByClassName("instagram-post:nth-child(n+" + (1 + limit) + ")").show();
feed.next();
});
document.getElementById('btnLess').on('click', function(e) {
document.getElementsByClassName("instagram-post:nth-child(n+" + (1 + limit) + ")").hide();
});
feed.run();
(P.S. As I only de "JQueryified" it for you accept his as the answer, not mine.)
You can add references through the script or add custom data attribute on loaded elements (there are more than one way to achieve what you want) but in my opinion you can use CSS selector to select all elements loaded after initial feed and apply some style (hide) them as shown in the code snippet below.
var limit = 4;
var feed = new Instafeed({
target: 'instafeed',
get: 'user',
type: 'image',
sortBy: 'most-recent',
limit: limit,
resolution: 'standard_resolution',
userId: <?php echo $instagram_id; ?>,
accessToken: '<?php echo $instagram_token; ?>',
template: '<img class="instagram-post" src={{image}} />',
after: function() {
if (!this.hasNext()) {
$('#btnMore').attr('disabled', 'disabled');
}
}
});
$('#btnMore').on('click', function(e) {
$(".instagram-post:nth-child(n+" + (1 + limit) + ")").show();
feed.next();
});
$('#btnLess').on('click', function(e) {
$(".instagram-post:nth-child(n+" + (1 + limit) + ")").hide();
});
feed.run();
.instagram-post {
width: 100px;
height: 100px;
display: inline-block;
margin: 15px;
}
<div id="instafeed"></div>
<button id="btnMore">Load More...</button>
<button id="btnLess">Show Less...</button>
Modify the code as per your need.
Exaplanation:
In the click event handler of $('#btnLess') I'm selecting all images with class .instagram-post from index limit + 1 and hiding them.
In the click event handler of $('#btnMore') I'm making sure all of the available images in the feed are visible so that whenever I press it after pressing $('#btnLess') all previously loaded images in the feed are visible as well.
Hope it helps.

Send value from an input generated by the onSubmit callback

When i add files to the queue i generate a text input for each file.
Is it possible to send this input's value to the server side?
I tried adding the value to the params object like this:
up._options.request.params.description = id;
but it only sends the id of the last image.
var up = new qq.FineUploaderBasic({
button: document.getElementById("addFiles"),
request: {
params: {
action: "upload",
},
endpoint: config.uploadURL,
},
validation: {
allowedExtensions: ["jpg", "jpeg", "png", "gif", "mkv", "mp4"],
},
autoUpload: false,
callbacks: {
onSubmit: function(id, fileName, response) {
var element = document.createElement("li");
element.setAttribute("id", "qImage-"+id);
element.setAttribute("class", "qImage");
$(".imagesList").prepend(element);
var out = "<div class='fileInfo'>";
out += "<span id='qCancel-"+id+"'>Cancel </span>";
out += fileName;
out += "</div>";
out += "<div class='fileData'>";
out += "<label for='fileDescription'>Description</label>";
out += "<input type='text' name='fileDescription' id='fileDescription'>";
out += "</div>";
$("#qImage-"+id).html(out);
$("#qCancel-"+id).on("click", function(){
up.cancel(id);
$("#qImage-"+id).remove();
});
up._options.request.params.description = id;
},
}
});
$('#startUpload').on("click", function(){
up.uploadStoredFiles();
//document.getElementById('queue-list').innerHTML = '';
});
$('#cancelUpload').on("click", function(){
up.cancelAll();
});
To expand on Ray's comment, there are two methods to my knowledge. The first may be exclusive to the S3 implementation, but I use:
uploadSuccess: {
endpoint: "link",
params: {
key: value
}
}
Or utilize setParams if you want it sent along with the file upload request itself.

How can I send data to controller by dialog?

EDIT2: I'm trying to update my code with java, but it's not working (I suppose I miss something in controller):
$(document).ready(function() {
var listGraphic = new Array();
function addPhoto(u, d) {
$.ajax({
url: "aggiungiEpigrafe",
type: "POST",
data: {"graphicUrl": u, "graphicDesc": d},
success: function(data) {
var $url = $("<form:input>").attr({
path: "graphicUrl",
disabled: true
}).html(u);
var $desc = $("<form:input>").attr({
path: "graphicDesc",
disabled: true
}).html(d);
$("#listGraphic").append($url, "<br />", $desc, "<br /><br />");
$(this).dialog("close");
},
error: function(xhr, textStatus, error){
console.log(xhr.statusText);
console.log(textStatus);
console.log(error);
}
});
}
$("button#insertFoto").button().click(function() {
$('#insertPhoto').dialog("open");
return false;
});
$("#newPhoto").submit(function(e) {
e.preventDefault();
var url = $("#graphicUrl").val();
var desc = $("#graphicDesc").val();
listGraphic.push(url);
listGraphic.push(desc);
console.log(listGraphic);
addPhoto(url, desc);
$("#graphicUrl").val("");
$("#graphicDesc").val("");
if ($('#insertPhoto').dialog("isOpen")) {
$('#insertPhoto').dialog("close");
}
});
$('#insertPhoto').dialog({
autoOpen: false,
buttons: {
"Close": function() {
$(this).dialog("close");
},
'Insert': function() {
$("#newPhoto").submit();
}
}
});
});
EDIT1:
Following Twisty suggestion I uptaded the dialog in order to not have any form inside (since this dialog is already in a form): https://jsfiddle.net/e57sj6hp/18/
As Twisty was also commenting, I probably need ajax, but I have to understand how use it; I think I need to use serialize() or seralizeArray(), but I don't understand well how should the controller receive the json and use it.
I have a controller like this:
public String myMethod(#ModelAttribute MyObject object, ModelMap model){...}
The object include a List of photos, and two variables url and description:
List<Photo> photos;
String url;
String description;
each photo in the list is formed by an url and a description.
In my jsp I created a dialog with jquery where a user can put an url and a description, what I want to do is to add each value into a list and send it to the controller, then clean the dialog in order to allow another submission.
I have tried a lot of but can't understand how I should do it. I'm using the spring's form and I have tried many different ways, but I think that the problem is in my javascript code. Here's one example: https://jsfiddle.net/e57sj6hp/12/
In this example the input fields and the textarea inside the dialog aren't surrounded with spring's form tags, since I've append the result inside the div and I supposed that, at the moment of the submitting, the controller should receive the data inside the form:input just created.
Not familiar with Spring, so I may miss an element, but matching what you put in your example, I can offer some potential updates.
Working Example: https://jsfiddle.net/Twisty/e57sj6hp/16/
HTML Updated
<div id="insertPhoto" style="display:none" title="Insert a Photo">
<form id="newPhoto">
<label>Url:</label>
<br/>
<input id="graphicUrl" />
<br/> Description:
<br/>
<textarea rows="4" cols="20" id="graphicDesc"></textarea>
</form>
</div>
You cannot call form.reset() without a form element. I wrapped the the form elements in a form. This has the added benefit of now responding to the form being submitted, for example if the user enters a url and hits enter.
jQuery
$(document).ready(function() {
var listGraphic = new Array();
function addPhoto(u, d) {
var $url = $("<form:input>").attr({
path: "graphicUrl",
disabled: true
}).html(u);
var $desc = $("<form:input>").attr({
path: "graphicDesc",
disabled: true
}).html(d);
$("#listGraphic").append($url, "<br />", $desc);
}
$("button#insertFoto").button().click(function() {
$('#insertPhoto').dialog("open");
return false;
});
$("#newPhoto").submit(function(e) {
e.preventDefault();
var url = $("#graphicUrl").val();
var desc = $("#graphicDesc").val();
listGraphic.push(url);
listGraphic.push(desc);
console.log(listGraphic);
addPhoto(url, desc);
$(this)[0].reset();
if ($('#insertPhoto').dialog("isOpen")) {
$('#insertPhoto').dialog("close");
}
});
$('#insertPhoto').dialog({
autoOpen: false,
buttons: {
"Close": function() {
$(this).dialog("close");
},
'Insert': function() {
$("#newPhoto").submit();
}
}
});
});
Lots of little fixes and improvements here. I moved listGraphic out of the functions, so it can be updated more globally. This allows it to be updated and read from other callbacks.
I created the function to make it a little easier to repeat.
Now regardless of how the form is submitted, the array is updated and so is the page. The dialog is closed and it's form is reset.
UPDATE 1
See new jQuery: https://jsfiddle.net/Twisty/e57sj6hp/21/
jQuery
$(document).ready(function() {
function addPhoto(u, d) {
$.ajax({
url: "aggiungiEpigrafe",
type: "POST",
data: JSON.stringify({
"graphicUrl": u,
"graphicDesc": d
}),
complete: function(data) {
var $url = $("<form:input>").attr({
path: "graphicUrl",
disabled: true
}).html(u);
var $desc = $("<form:input>").attr({
path: "graphicDesc",
disabled: true
}).html(d);
$("#listGraphic").append($url, "<br />", $desc, "<br /><br />");
}
});
}
$("button#insertFoto").button().click(function() {
$('#insertPhoto').dialog("open");
return false;
});
$('#insertPhoto').dialog({
autoOpen: false,
buttons: {
"Close": function() {
$(this).dialog("close");
},
'Insert': function() {
addPhoto($("#graphicUrl").val(), $("#graphicDesc").val());
// Reset values
$("#graphicUrl").val("");
$("#graphicDesc").val("");
// Close Dialog
$(this).dialog("close");
}
}
});
});

jQuery File Upload in Rails 4.x Nested Form

I have a Horse model and a Photo model. I am using jQuery File Upload to resize (client side) images and save on Amazon s3 directly since I am using Heroku.
I have seen other questions similar that use carrierwave, paperclip, or that are very old. I am not sure why you would use carrierwave/paperclip, but I think based on what heroku says, I do not want to have images hitting the server potentially causing time-outs.
Heroku recommends using jQuery File Upload and shows js appending new file input with a value of the image's link (returned from amazon s3). I have this working when saving a photo separately. I now want to make it work in a nested form for Horse but js is not finding input (since it does not exist yet because it's nested I presume).
I am using Cocoon for nested forms (I am open to anything that will work better). I am not too familiar with javascript/jQuery but a far as I can tell, Cocoon 'hides' the nested element until I click to add it via the add_association.
haml view code:
= link_to_add_association 'add photo', f, :photos
html source before clicking 'add photo'
<div class='links'>
<a class="btn btn-default btn-sm add_fields" data-association-insertion-method="after" data-association="photo" data-associations="photos" data-association-insertion-template="<div class='nested-fields'>
<fieldset class="inputs"><ol><input type="file" name="horse[photos_attributes][new_photos][url]" id="horse_photos_attributes_new_photos_url" />
<input type="hidden" name="horse[photos_attributes][new_photos][_destroy]" id="horse_photos_attributes_new_photos__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove photo</a>
</ol></fieldset>
</div>
" href="#">add photo</a>
How do I work with this input and how do I handle multiple file uploads as they are added correctly?
My current upload js:
$(function() {
if ($('#new_horse').length > 0) {
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Pre-uploading done... Please Save or Cancel");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
}, 'json');
}
});
I guess I should have looked at cocoon documentation first:
http://www.rubydoc.info/gems/cocoon#Callbacks__upon_insert_and_remove_of_items_
http://www.rubydoc.info/gems/cocoon/1.2.6
I modified my upload.js file to the following and it worked for multiple files in nested forms perfectly:
// added for file uploading
// https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails
// Get our s3params from our endpoint
$(document).on('ready page:load', function () {
$('.direct-upload')
.on('cocoon:after-insert', function(e, photo) {
console.log('inside cocoon image function');
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
console.log('inside nested-fields photo input form');
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Photo Uploaded");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
}, 'json'); //fileupload
}); //each file
}); //presign call
}); // function cocoon
}); // page ready
I guess Google and a well documented gem can replace knowledge of JS in the short term :-) I am sure it's not at tight as it could be so please offer any improvements.

FineUploader button text

I have scoured the FineUploader documentation, but when I set my upload button text like below, the change does not seem to propagate. The upload button still displays the default text. What am I missing?
var manualuploader = new qq.FileUploader({
element: document.getElementById('manual-fine-uploader'),
text: {
uploadButton: "Select a File" // <========== Setting text here
},
action: "/file/upload",
autoUpload: false,
multiple: false,
forceMultipart: true,
onComplete: function (id, fileName, json) {
$("#divFileUploadLoading").hide();
$("#buttonUploadFile").show();
if (json.success) {
displaySuccessMessage("Successfully uploaded: " + fileName);
$("#textFileTitle").val("");
$("#textFileDescription").val("");
$("#checkIsDownloadable").prop("checked", true);
$("#checkDisplayDetails").prop("checked", true);
}
else {
displayErrorMessage("Failed to upload: " + fileName + " because '" + json.errorMessage + "'");
}
g_FileCount = 0;
manualuploader.clearStoredFiles();
manualuploader.reset();
},
onSubmit: function (id, fileName) {
g_FileCount++;
},
onCancel: function (id, fileName) {
$("#divFileUploadLoading").hide();
$("#buttonUploadFile").show();
displaySuccessMessage("Canceled upload for: " + fileName);
g_FileCount--;
}
});
Tested and verified. You still need to use the "text" option.
text: {
uploadButton:'<div>Select a file</div>'
}
Another way to do it is to create your own button with the button: option.
JS:
button: document.getElementById('my-button')
HTML:
<div id="my-button" class="qq-upload-button">Select a file</div>
As far as I'm concerned, the provided answers do not work. So what I did was to set the contents of the corresponding division programmatically after having called the FineUploader constructor. My Javascript is as follows (using jQuery):
$('div_ID').fineUploader({... your options here });
$(".qq-upload-button-selector.qq-upload-button div").text("your custom text");
I have tested this and it works for me. Any comments welcome.
Hope this helps.
try using an element:
uploadButton: "<div>Select a File</div>"
good luck !

Categories

Resources