I have an MVC 5 view with a form and a plupload file uploader section. Upload is triggered by a button on the form. I have no problem uploading file chunks to the server and setting the parameters to the query string and all, but what I do have a problem with is starting the upload only after a custom sanity check has been performed.
Here's what I have tried:
var uploader = new plupload.Uploader({
runtimes: 'html5',
drop_element: 'upload',
browse_button: 'browse',
url: "../UploadFile",
chunk_size: "1024kb",
multipart_params: { "uid": "uid", "chunk": "chunk", "chunks": "chunks", "name": "name" },
init: {
PostInit: function(file) {
document.getElementById("filelist").innerHTML = "";
document.getElementById('submit-all').onclick = function () {
document.getElementById("infoPopup").style.visibility = "visible";
document.getElementById('submit-all').enabled = false;
var uuid = Math.uuidFast();
document.getElementById("uid").value = uuid;
uploader.settings.multipart_params = { uid: uuid, chunk: file.chunk, chunks: file.chunks, name: file.name };
if (checkReq) {
uploader.start();
}
return false;
};
},
The crucial part here is this:
if(checkReq){
uploader.start();
}
"checkReq" is my custom sanity check script that verifies that form values are not nonsensical (e.g. single form entries might be perfectly valid while in combination they are simply wrong, etc.).
So the above does not prevent the upload, the check script is not even fired, Firebug console output shows no error.
Since googling tells me that there is also a "BeforeUpload" event, I tried this:
BeforeUpload: function(up, file) {
if (checkReq) {
up.stop();
return false;
}
return true;
},
Which also does not seem to fire at all.
Edit: Next attempt, I put the call to my checkReq fuction into BeforeUpload in "preinit", which should fire before any chunking etc is done, so before the upload is prepared. This also failed although I have no idea why it does not fire:
var uploader = new plupload.Uploader({
runtimes: 'html5',
drop_element: 'upload',
browse_button: 'browse',
url: "../UploadFile",
chunk_size: "1024kb",
multipart_params: { "uid": "uid", "chunk": "chunk", "chunks": "chunks", "name": "name" },
preinit: {
BeforeUpload: function (up) {
if (checkReq) {
uploader.stop();
uploader.splice(0, uploader.files.length);
return false;
}
return true;
}
},
init: {
PostInit: function(file) {
...
I had used "dropzone.js" before, and my script worked fine with that but I found that I needed chunked uploads so I had to move to plupload and now my script is being ignored.
Could someone please tell me where I am being stupid here? Thanks!
Got it solved.
It's a nasty, ugly hack, but it works:
Made the "actual" submit/upload button hidden
Made a second button that acts as pre-submit button with onclick function
onclick function calls checkReq and if that returns true, the function calls the click() function of the "actual" submit/upload button
Like I said: nasty but it works.
Related
Whenever I upload an image with FS.Collection using FileSystem, the image doesn't renders and I get a 503 error. But if I refresh the page the image will render and I get no error. So I had to to set that images path to a public folder using ostrio:meteor-root, so whenever I upload an image, the page refreshes. I'm fetching the image URL from a Mongo.Collection, not from my FS.Collection.
When I upload an image I store the url on Adverts:
"_id" : "knCMZPK8RrY5Y7GQo",
"reference" : 102020026,
"pics" : {
"pic" : [
{
"url" : "http://localhost:3000/cfs/files/Images/6fHhBT3ky5iAJnQfw"
}
]
},
Images.js:
var imageStore = new FS.Store.FileSystem("Images", {
path: Meteor.absolutePath + '/public/uploads'
})
Images = new FS.Collection("Images", {
stores: [imageStore],
filter: {
allow: {
contentTypes: ['image/*']
},
}
});
if (Meteor.isServer) {
Images.allow({
insert: function(userId, party) {
return true;
},
update: function(userId, party) {
return true;
},
download: function(userId, party) {
return true;
},
remove: function(userId, party) {
return true;
}
});
}
Image not rendering:
ANSWER:
Instead of using FS collection I switched to ostrio:files.
Since I wanted to just upload the images to the document that I was updating (I have a reactive-table with my collection data, each row is clickable and contains a document, when I click a row I use iron:router to navigate to a page with AutoForm that updates that single document) I make a Meteor.call in the client to send the document _id to the server.
Meteor.call('docId', this._id)
It seemed like the image wasn't rendering because it was creating the thumbnail before finishing the upload.
So to fix this I made a afterUpload call back server-side on docId Method:
FSCollection.off('afterUpload')
FSCollection.on('afterUpload', function(fileRef){
Update Mongo.Collection (...)
}
If I don't use .off before .on it keeps incrementing the time that the code inside the callbak is executed. When the first image is uploaded the code executes correctly, when the second one is uploaded the code is executed twice and so on.
I am trying to change an extension I'm working on from a browser action to a page action. Currently, the extension detects a tab change and, if the URL of the tab is on our domains, makes a request for JSON data for status information, so it can make the good icon or the bad icon appear as a status indicator. My browser action code was this:
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.get(activeInfo.tabId, function(tab) {
var url = tab.url,
matches = url.match(/(domain1)|(domain2)\.com/g);
if (url && matches) {
// Query for JSON data and change the icon based on it.
loadReach(url);
} else {
// Change the icon bad
}
});
});
I have the basic listeners in place to insert the declarativeContent listener and show the initial icon, but am unsure where to put my callback that makes the query for the JSON data:
// When the extension is installed or upgraded ...
chrome.runtime.onInstalled.addListener(function() {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostContains: 'domain1.com' },
}),
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostContains: 'domain2.com' },
})
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction() ]
}
]);
});
});
Where in the second codeblock would I be able to run that callback, or is it not supported by this method?
I am using 5.3.2 in basic mode as I need control over the UI.
I have added code to allow the uploads and then created little UI elements that can then trigger a deletion. I need to know the filename when I am deleting. So I used setDeleteFileParams but nothing is attached to the request.
var uploader = new qq.FineUploaderBasic({
button: document.getElementById('btnUploadFiles'),
debug: true,
autoUpload: true,
request: {
paramsInBody: true,
endpoint: '../myendpoint.htm',
params: {
tempID: 'myidwhatever'
}
},
deleteFile: {
enabled: true,
forceConfirm: false,
method: 'POST',
endpoint: '../myendpoint.htm'
},
callbacks: {
onSubmitted: function(id, name){
//do work
},
onDelete: function(id) {
this.setDeleteFileParams({filename: this.getName(id)}, id);
},
onDeleteComplete: function(UID, xhr, isError){
//remove my UI element
},
onComplete: function(UID, name, responseJSON, xhr) {
//create an element and stick it in
}
}
})
//ADD THE DELETE BUTTON ACTIONS
$('uploadedFiles').addEvent("click:relay(.deleteMyFile)", function(event, element) {
event.preventDefault();
arr = element.id.split('_')
uploader.deleteFile(arr[1]);
});
Im using Mootools as my JS framework. Everything triggers ok and the console logs out the filename correctly when I delete a file but when I look at the request there is no 'filename' parameter.
Thanks for any help.
By the time your onDeleteFile callback has been called, the file is already setup to be deleted. If you'd like to influence (or prevent) the underlying request, you'll need to put your logic inside of a onSubmitDelete callback handler instead.
For example:
callbacks: {
onSubmitDelete: function(id) {
console.log(this.getName(id));
this.setDeleteFileParams({filename: this.getName(id)}, id);
}
}
I hate to ask these strange problems but couldn't able to avoid this one.
I have "Option" view with "Option" model passed as a parameter when creating.
var optionView = new OptionView({ model: option });
this.$el.find('div#optionsBoard').append( optionView.render().el );
In this view, when the user clicks on "Vote" button, the "voteCount" attribute of the model will be incremented.
events: { 'click .button-vote': 'processVote' },
processVote: function (e) {
var voteCounted = this.model.get('voteCount');
this.model.set('voteCount', voteCounted++);
console.log(this.model.id); // has a Id value
console.log(this.model.isNew()); // false
this.model.save(); // occurs problem here
e.preventDefault();
},
The problem occurs when I save the model back to the server as following:
PUT http://localhost:13791/api/options/ 404 (Not Found)
Yes, this url actually isn't existed on my REST API server. But I believe the correct path of PUT URL to update the model should be as following:
PUT http://localhost:13791/api/options/id_of_the_entity_to_be_updated
When I test this PUT url (http://localhost:13791/api/options/id_of_the_entity_to_be_updated) with Postman Rest client, it works perfectly.
So I think the problem occurs because Backbone model.save() method does not add the id_of_the_entity_to_be_updated to the PUT url.
Please, suggest me something how should I solve this problem.
As additional description, this is my "option" model setup code.
define([
'backbone'
], function (Backbone) {
var Option = Backbone.Model.extend({
idAttribute: "_id",
defaults: {
name: '',
location: '',
link: '',
voteCount: 0,
expiredDate: Date.now(),
imageName: ''
},
url: '/api/options/',
readFile: function(file) {
var reader = new FileReader();
// closure to capture the file information.
reader.onload = ( function(theFile, that) {
return function(e) {
that.set({filename: theFile.name, data: e.target.result});
that.set({imageUrl: theFile.name});
console.log(e.target.result);
};
})(file, this);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
}
});
return Option;
});
Problem found
My bad. In the "Option" model setup, it should be "urlRoot" instead of "url".
In your model you should use urlRoot instead url:
urlRoot: '/api/options/'
Parse.com with JavaScript SDK - unnecessary duplictions
Every time I create a Parse object of "message", it duplicates that object in my Parse Core. It is so bizarre. The first time I run the code, everything is fine and Parse will create only one object. But when I run the code again, it will duplicate the most recent object twice. If I run it a third time, it will duplicate the most recent object five times. The number of duplications increases based upon how many objects have already been created. Does anyone have any idea how to make sure that it create one object in my Parse Core backend? Thank you so much!!! I wish I could post a picture, but I am a newbie and stackoverflow wont let me
This is where I create the Parse object:
App.Models.Message = Parse.Object.extend({
className: 'Message',
idAttribute: 'objectId',
defaults: {
name : '',
email : '',
subject : '',
message : ''
}
});
This is where I create an instance of the Parse object, and where I save it to Parse:
App.Views.Contact = Parse.View.extend({
el : '#middle',
template : _.template($('#contactTemp').html()),
events: {
'click .submit' : 'submit',
},
initialize : function () {
this.render();
},
render : function () {
this.$el.html(this.template);
},
submit : function (e) {
e.preventDefault();
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function(e) {
alert('There was an error in sending the message');
}
});
}
});
Yes! So I figured out the problem with the help of Hector Ramos from the Parse Developers Google group.
https://groups.google.com/forum/#!topic/parse-developers/2y-mI4TgpLc
It was my client-side code. Instead of creating an event attached to my App.Views.Contact(); a.k.a. - an instance of Parse.View.extend({}), I went ahead and created a 'click' event using jquery within the sendMessage function that I recently defined. If you declare an event in the events object within the Parse view, it will recur over itself if the view wasn't re-initialized or destroyed and recreated properly.
So what happened with me was the submit function that I declared in the events object kept recuring over itself and making duplicate calls to Parse.com. My view was static, it wasn't destroyed properly, re-initialized, or reloaded. You will see what I did below:
Originally I had this:
events: {
'click .submit' : 'submit',
},
& this
submit : function (e) {
e.preventDefault();
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function(e) {
alert('There was an error in sending the message');
}
});
} /*end of submit*/
Now I have I completely removed the events object that I had and declared a sendMessage function:
initialize : function () {
this.render();
},
render : function () {
this.$el.html(this.template);
this.sendMessage();
},
sendMessage : function () {
$('.submit').on('click', function(){
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function() {
alert('There was an error in sending the message');
}
});
}); /*end of jquery submit*/
}/*end of send message function*/,
And now it works perfectly fine. Credit is due Hector Ramos who is a Parse.com Developer and who helped me realize that the problem was the actual event. If you guys have any easy way of stoping an event from making several duplicate calls to the back or from reoccurring several times, then please let me know.