Validate (custom) before adding file - javascript

I would like to make sure if the user is logged-in or not before anything is added to the uploader area (thumbnails).
it's easy enough checking stuff on the validate event callback, but I can't seem to figure out how to stop the item from being added to the DOM, even if I return false in my validation or submit events...the item just gets a class of qq-upload-fail... but I want to completly do NOTHING if the user isn't logged in...maybe the validation event handler is not the place to put this logic, but where else?
My initialization code (jQuery):
this.holderElm.fineUploader({
template: 'qq-simple-thumbnails-template',
// uploaderType: 'basic',
request: {
endpoint: '/image/upload_image/' + this.settings.uploadID
},
validation: {
allowedExtensions : ['jpeg', 'jpg', 'gif', 'png'],
sizeLimit : this.settings.sizeLimit,
itemLimit : this.settings.itemsLimit
},
retry: {
enableAuto: true
}
})
.on("validate", this.onValidate.bind(this) )
.on('submit', this.onSubmit.bind(this) )
.on('error', this.onError.bind(this) )
.on('upload', this.onUpload.bind(this) )
.on('complete', this.onComplete.bind(this) )
.on('allComplete', this.onAllComplete.bind(this) );

Use the onSubmit event -- which called is before the item has been added to the DOM -- and return false or a qq.Promise that will be rejected to disable the addition of that item to the file list.
var userLoggedIn = true;
// snippet ...
onSubmit: function(id, name){
return userLoggedIn;
},
or with promises:
function isUserLoggedIn(username){
var promise = new qq.Promise();
$.get("/api/user/"+username, function(err, data){
if (err) return promise.failure(err);
return promise.success(data);
});
return promise;
}
// snippet ...
onSubmit: function(id, name){
return isUserLoggedIn(username);
},

Related

How to prevent closing bootbox while using async function?

What I'm trying to get is if an user gets any validation error, then bootbox will show that "this is required". Till now, I've achieved this. But the main problem is that - it closes the window of boot box if the user clicks "Yes" button.
I'm getting this because I had to use g async callback in bootbox. For this reason, even after returning false, the bootbox is closing. But I want users to show the box until they press the cancel button. If they click Yes, then it should show the validation, with the box opened. This is my code:
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: async function (result) {
var isValid = $('#form').valid();
if (result && !isValid) {
return false; //it's not working. It's closing the bootbox
}
if (result && isValid) {
/* for this await function I had to use async callback,
without this bootbox is opend
*/
var data = await self.createData();
$.ajax({
type: "POST",
success: function (result) {
},
}).then(function () {
});
}
}
});
How can I resolve this?
It does not appear to me that bootbox.confirm() has any sort of support for async callbacks like you are trying to use. The bootbox closes when your callback returns which will be at the point you hit your first await unless you explicitly return false, but an async callback function ALWAYS returns a promise which is not explicitly false. You cannot change that.
What you can do is make your callback a regular callback function, not async that can return false if validation fails and then create an embedded async function where you can use await that you call from within that first callback like is shown below. Note that the bootbox will close before your asynchronous code completes so if there are any errors in the bootbox code, you will need to new way to present those errors, perhaps putting up a new bootbox. Here's one way to do this code while still using await.
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var isValid = $('#form').valid();
if (result) {
if (!isValid) {
// keep prompt open until user presses Cancel
return false;
}
async function run() {
const data = await self.createData();
const result = await $.ajax({ ... });
// do something with result
}
// now call async function here (dialog will close)
run().catch(err => {
// do something with an error here
console.log(err);
});
}
return true;
}
});
Alternatively, you could avoid using await and only use .then() and .catch() and then you wouldn't need this extra layer of function:
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var isValid = $('#form').valid();
if (result) {
if (!isValid) {
// keep prompt open until user presses Cancel
return false;
}
self.createData().then(data => {
return $.ajax({ ... }).then(result => {
// do something with result
});
}).catch(err => {
// do something with error here
console.log(err);
});
}
return true;
}
});

How to add a process bar when you waiting for a response from the server

could someone help me with one problem? I want to add a process bar when you waiting for a response from the server (Django 3.x).
Step to reproduce:
On the page 'A' we have the form.
Enter data to form.
Submit POST request by clicking to button on the page 'A'.
Waiting for getting the result on the page 'A'.
Get the result on the page 'A'.
So, I want to add process bar after 4th and before 5th points on the page 'A'. When you will get the result on the page 'A' it should disappear.
Python 3.7
Django 3.x
You can use nprogress, it's a library used for progress bars. Use this inside the interceptor where you can config it for displaying only when request is in progress until finished.
There are lots of ways to do this. I think using jquery would be easier. Basically you just need to prevent submitting the page and do an Ajax request to server. something like
<script type='text/javascript'>
$(document).ready(function () {
$("form").submit(function (e) {
// prevent page loading
e.preventDefault(e);
$('#loadinAnimation').show();
// preapre formdata
$.ajax({
type: "yourRequestType",
url: "yourUrlEndpoint",
data: formdata,
success: function (data) {
$('#loadinAnimation').hide();
// do rest of the work with data
}
});
});
});
</script>
and show appropriate loading animation in your html part
<div id='loadinAnimation' style='display:none'>
<div>loading gif</div>
</div>
You can also do it using UiKit Library in Javascript on your Django Template Page.
Below code is when a file is Uploaded
In your template file (template.html)
<body>
..
<form>
<progress id="js-progressbar" class="uk-progress" value="0" max="100" hidden></progress>
...
<div class="uk-alert-danger uk-margin-top uk-hidden" id="upload_error" uk-alert></div>
...
</form>
</head>
<script type="text/javascript">
$(document).ready(function(){
var bar = document.getElementById('js-progressbar');
UIkit.upload('.js-upload-list', {
url: '',
name : "customer-docs",
params :{
"csrfmiddlewaretoken":"{{csrf_token}}"
},
method : "POST",
concurrent:1,
allow:'*.(csv|xlsx)',
beforeSend: function (environment) {
console.log('beforeSend', arguments);
// The environment object can still be modified here.
// var {data, method, headers, xhr, responseType} = environment;
},
beforeAll: function (args,files) {
console.log('beforeAll', arguments);
},
load: function () {
console.log('load', arguments);
},
error: function (files) {
console.log("---------------")
},
complete: function () {
console.log('complete', arguments);
},
loadStart: function (e) {
console.log('loadStart', arguments);
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
console.log('progress', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
console.log('loadEnd', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function (data) {
console.log('completeAll', arguments);
console.log('completeAll', data);
let redirect_loc = ""
setTimeout(function () {
bar.setAttribute('hidden', 'hidden');
}, 1000);
// This is the response from your POST method of views.py
data.responseText = JSON.parse(data.responseText)
if(data.responseText.status == 201){
// swal is another library to show sweet alert pop ups
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Done: true
},
}).then((value) => {
switch (value) {
case "Done":
window.location.href = ""
break;
}
});
}
else if(data.responseText.status == 500){
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Ok: true
},
}).then((value) => {
switch (value) {
case "Ok":
window.location.href = ""
break;
}
});
}
}
});
// This block of code is to restrict user to upload only specific FILE formats (below example is for CSV & XLSX files)
(function() {
var _old_alert = window.alert;
window.alert = function(e) {
console.log(e)
if(e.includes("csv|xlsx") || e.includes("Invalid file type")) {
$("#upload_error").html("Invalid file format. Valid formats are CSV, XLSX").removeClass('uk-hidden')
}else if(e.includes("Internal Server Error")) {
$("#upload_error").html("Internal Server Error Kindly upload Documents again").removeClass('uk-hidden')
}
else {
_old_alert.apply(window,arguments);
$("#upload_error").addClass('uk-hidden').html("")
}
};
})();
});
</script>
On your views.py you can do your computation and once done, you can return a response like below
resp_json = {
"status" : 201,
"status_icon" : "success",
"url" : "/",
"message": message
}
return HttpResponse(json.dumps(resp_json))
For more info on SWAL (Sweet Alerts), visit https://sweetalert.js.org/guides/

Algolia template if no hits are returned

I've implemented my own Algolia PoC based of https://www.algolia.com/doc/search/auto-complete and I'm now struggling with a specific use case: how can I handle a search which does not return any hits?
Here is my code:
I've been able to identify and detect when/where no hits are returned, but I can't do anything beside just using a console.log(). I tried to get a custom return_msg but I can't call the function.
I also tried to do some tweak under suggestion: function(suggestion) but this function is never called if no hits are returned.
I also did not found any documentation about this "Templates" section on https://github.com/algolia/autocomplete.js
$('#q').autocomplete({ hint: false }, [
{
source: function(q, cb) {
index.search(q,
{ hitsPerPage: 10 },
function(error, content) {
if (error) {
cb([]);
return;
}
if (content.nbHits == 0)
{ return_msg = '<h5> Sorry, no result </h5>';
// DO something here
console.log(return_msg);
// console.log return "Sorry, no result"
}
cb(content.hits, content);
});
},
displayKey: 'game',
templates: {
suggestion: function(suggestion) {
return_msg = '<h5> '+ suggestion.MY_ATTRIBUTE + '</h5>'
return return_msg;
}
}
}
]).on('autocomplete:selected', function(event, suggestion, dataset) {
window.location = (suggestion.url);
});
Any pointers would be greatly appreciated =)
Using the templates option of your dataset you can specify the template to use when there are no results:
source: autocomplete.sources.hits(indexObj, { hitsPerPage: 2 }),
templates: {
suggestion: // ...
header: // ...
footer: // ...
empty: function(options) {
return '<div>My empty message</div>';
}
}
Full documentation here.

I am unable to execute validation in Backbone.js.

Whenever I set the age attribute to negative value it doesn't return false.
I have also tried executing this code in the console and still nothing happens
<script>
var Human = Backbone.Model.extend({
// If you return a string from the validate function,
// Backbone will throw an error
defaults: {
name: 'Guest user',
age: 23,
occupation: 'worker'
},
validate: function( attributes ){
if( attributes.age < 0){
return "Age must me positive";
}
if( !attributes.name ){
return 'Every person must have a name';
}
},
work: function(){
return this.get('name') + ' is working';
}
});
var human = new Human;
human.set("age", -10);
human.on('error', function(model, error){
console.log(error);
});
</script>
There are a few things wrong with your code:
The event for validation is invalid, error is for ajax requests.
Validation on set doesn't happen by default, you need to pass { validate: true } as an option.
You are listening to the event AFTER setting, so it won't get called for that set.
i.e:
human.on('invalid', function(model, error) {
console.log(error);
});
human.set("age", -10, { validate: true });

Meteor js .allow list not showing

I am trying to implement the .allow part of meteor in an application I'm building. Before introducing it a list was displaying comments a user entered, now the comments just flash up for a second and then disappear. The comments are still being added to the collection though.
Could anyone tell me what I'm doing wrong, I am very new to this.
Main js file:
if (Meteor.isClient) {
Meteor.startup(function () {
Meteor.subscribe("ques");
});
Template.compose.events({
'submit form': function (event) {
var $body = $('#que-body');
var $score = 1;
event.preventDefault();
Questions.insert({
body: $body.val(),
score: $score,
created_at: Date()
});
$body.val('');
}
});
Template.question.selected = function () {
return Session.equals("selected_question", this._id) ? "selected" : '';
};
Template.question.events({
'click': function () {
Session.set("selected_question", this._id);
}
});
Template.question.que = function(){
return Questions.findOne(Session.get("selected"));
};
// Deals with up-vote, down-vote, remove buttons
Template.list.events({
'click .icon-thumbs-up': function(event) {
Questions.update(Session.get("selected_question"), {$inc: {score: 1}});
},
'click .icon-thumbs-down': function(event) {
Questions.update(Session.get("selected_question"), {$inc: {score: -1}});
},
'click .icon-remove': function(event) {
Questions.remove(Session.get("selected_question"));
}
});
Template.list.questions = Questions.find({}, {sort: {score: -1, created_at: -1}});
}
if (Meteor.isServer) {
Meteor.startup(function () {
Meteor.publish("ques", function(){
return Questions.find({}, {
fields:{ }
})
});
});
}
The model.js file:
Questions = new Meteor.Collection("questions");
Questions.allow({
insert: function(userId, que){
return userId && que.owner === userId;
},
update: function(id, ques, fields, modifier){
return true;
},
remove: function(id, que){
return id && que.owner === id;
}
});
Do you mean the questions (you said comments?): Your Meteor.allow rule is basically something that says the question.owner is the current logged in user's _id. You need to insert an owner when you insert your question. This is the only way (que.owner === userId will return true):
Questions.insert({
owner: Meteor.userId(),
body: $body.val(),
score: $score,
created_at: Date()
});
Make sure you ensure that only logged in users have the chance to insert questions. Either by hiding the button or having a check just before everything is inserted too:
if(!Meteor.userId()) {
alert("You need to be logged in to post a question");
return;
}

Categories