I am trying to create a dummy progress bar that is initiated when the user clicks the submit button, and then disappears when the data is returned.
I would like it to load a little bit to a certain point to show the user that the data is being returned, and then complete once the data is rendered.
Any advice on how I could achieve this?
Here is my bootstrap progress bar template:
<div id="loadingcontainer">
<div class="progress" style="height: 5px;">
<div id="myprogress" class="progress-bar" style="color:#EB7051;" style="background-color: #ffffff" role="progressbar" style="width: 25%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
Here is my script tag:
function searchIt() {
let form = document.querySelector('form')
console.log(form)
form.addEventListener('submit', async(e) => {
e.preventDefault()
let urlIN = form.url.value
let url = encodeURIComponent(urlIN)
console.log(url)
try {
const data = await fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: url
})
}).then(res => {
document.open()
res.text().then(function(text) {
document.write(text)
});
})
} catch (err) {
console.error(err)
}
})
Related
I am working on file upload with progress bar and cancel button to abort uploading.
I have my upload.html as below,
<div class="row">
<div id="alert-box">{{ msg }}</div>
<div id="image-box"></div>
<div class="col-md-2"><label><b>File :</b></label></div>
<div class="col-md-2"><input type="file" id="fileupload" name="fileupload" required multiple></div>
</div><br>
<div class="container">
<div id="progress-box" class="progress not-visible">
<div class="progress-bar bg-success" role="progessbar" >progress</div>
</div>
</div>
<div id="cancel-box" class="not-visible">
<button id="cancel-btn" class="btn btn-danger">cancel</button>
</div>
and main.js as,
const uploadForm = document.getElementById('upload-form')
const input = document.getElementById('fileupload')
const submitBtn = document.getElementById('submitBtn')
const alertBox = document.getElementById('alert-box')
const progressBox = document.getElementById('progress-box')
const cancelBox = document.getElementById('cancel-box')
const cancelBtn = document.getElementById('cancel-btn')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
$("#upload-form").submit(function(e){
$form = $(this)
var formData = new FormData(this);
const media_data = input.files[0];
if(media_data != null){
console.log(media_data);
progressBox.classList.remove("not-visible");
cancelBox.classList.remove("not-visible");
}
$.ajax({
type: 'POST',
url:'/',
data: formData,
dataType: 'json',
beforeSend: function(){
},
xhr:function(){
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
if(e.lengthComputable){
const percentProgress = (e.loaded/e.total)*100;
console.log(percentProgress);
progressBox.innerHTML = `<div class="progress-bar progress-bar-striped bg-success"
role="progressbar" style="width: ${percentProgress}%" aria-valuenow="${percentProgress}" aria-valuemin="0"
aria-valuemax="100"></div>`
}
})
cancelBtn.addEventListener('click', e=>{
xhr.abort();
console.log("Abort event");
progressBox.innerHTML="";
progressBox.classList.add("not-visible");
cancelBox.classList.add('not-visible');
})
return xhr
},
success: function(response){
console.log(response);
console.log("successfully upload");
progressBox.classList.add("not-visible");
cancelBox.classList.add("not-visible");
uploadForm.reset();
},
error: function(err){
console.log(err);
},
cache: false,
contentType: false,
processData: false,
});
});
I am trying to abort uploading file when some one click on cancel button which appears when file is uploading.
thought it is setting 'not-visible' class to progress bar and cancel button. file still continue to upload.
any thoughts why it is not stop uploading file on xhr.abort() ?
Thanks,
PB.
I have an issue with a progress upload bar in Django when the site is deployed to Heroku, when I click on the upload button the progress bar shows up at 10% then doesn't change or count up to 100%, when the upload is finished, it redirects as instructed in my views.py , the function runs fine locally, but after deploying to heroku it doesn't work. I think it may be something to do with the deployed url using 'https', but not sure and how to fix it? appreciate any help.
custom.js
function progressBar() {
progressBox.classList.remove('not-visible')
cancelBox.classList.remove('not-visible')
const upload_data = input.files[0]
const url = URL.createObjectURL(upload_data)
// console.log(upload_data);
const fd = new FormData()
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('track', upload_data)
$.ajax({
type: 'POST',
enctype: 'multipart/form-data',
data: fd,
beforeSend: function(){
},
xhr: function(){
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
// console.log(e);
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
// console.log(percent);
progressBox.innerHTML = `<h5 style="text-align:center;">${percent.toFixed(1)}%</h5>
<div class="progress" style="height: 30px;">
<div class="progress-bar bg-success" role="progressbar" style="width: ${percent}%"
aria-valuenow="${percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>`
}
})
cancelBtn.addEventListener('click', ()=>{
xhr.abort()
progressBox.innerHTML=""
cancelBox.classList.add('not-visible')
window.location.reload();
})
return xhr;
},
success: function(response){
// console.log(response);
uploadForm.reset()
cancelBox.classList.add('not-visible')
},
error: function(error){
console.log(error);
},
cache: false,
contentType: false,
processData: false,
})
}
I have already made the progress bar and everything. But I have a problem when I choose the file is upload, that's mean the file is uploading twice, once when choosing the file and one once submit the form, and this bad user experience so I want to show the progress bar only when submitting the form, I use Django in backend and ajax recall
my HTML form
<div id="alert-box"></div>
<form id="upload-form" action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
<div id="progress-box" class="d-none">progress</div>
<div class="custom-file">
<input type="file" class="custom-file-input" id="formGroupExampleInput2" required value="{{V_form.video}}">
<label class="custom-file-label" for="formGroupExampleInput2">Choose Video...</label>
</div>
<div class="custom-file mt-5 mb-4">
<input type="file" class="custom-file-input" id="file2" required value="{{V_form.video_poster}}">
<label class="custom-file-label" for="formGroupExampleInput2">Choose Poster For Your Video...</label>
</div>
<div class="d-flex justify-content-center my-3 px-3" > <button class="btn-block btnn-color" id="heel" name="submit_v_form"> Upload</button></div>
</form>
the javascript-Ajax
const file_input_label = document.getElementById('file_input_label')
function input_filename(){
file_input_label.innerHTML = input.files[0].name;
console.log(file_input_label);
}
const uploadForm = document.getElementById('upload-form')
// const input = document.getElementById('formGroupExampleInput2')
const input = document.getElementById('formGroupExampleInput2')
console.log(input)
const alertBox = document.getElementById('alert-box')
const imageBox = document.getElementById('image-box')
const progressBox = document.getElementById('progress-box')
const canceleBox = document.getElementById('cancel-box')
const canceleBtn = document.getElementById('cancel-btn')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
// whenever choose th file something happen
input.addEventListener('change', ()=>{
progressBox.classList.remove('d-none')
canceleBox.classList.remove('d-none')
var filePath = input.value;
var allowedTypes = /(\.mp4|\.mkv|\.avi|\.flv)$/i;
if(!allowedTypes.exec(filePath)){
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">Please Upload the valid file type</div>`
input.value = "";
return false;
}
const img_data = input.files[0]
const url = URL.createObjectURL(img_data)
console.log(img_data)
const fd = new FormData()
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('video', img_data)
$.ajax({
type: 'POST',
url: uploadForm.action,
enctype: 'multipart/form-data',
data: fd,
beforeSend: function() {
console.log('before')
alertBox.innerHTML = ""
// imageBox.innerHTML = ""
},
xhr: function() {
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
// console.log(e)
if (e.lengthComputable){
const percent = e.loaded / e.total * 100
console.log(percent);
progressBox.innerHTML =
`<div class="progress">
<div class="progress-bar" role="progressbar" style="width: ${percent}%" aria-valuenow=" ${percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p>${percent.toFixed(1)}%</p>`
}
})
canceleBtn.addEventListener('click', ()=>{
xhr.abort()
setTimeout(()=>{
uploadForm.reset()
progressBox.innerHTML = ""
alertBox.innerHTML = ""
canceleBox.classList.add('d-none')
}, 1000)
})
return xhr
},
success: function(response) {
console.log(response)
// imageBox.innerHTML = `<img src="${url}" width="300px">`
// imageBox.innerHTML = `<video class="card" controls src="${url}">`
alertBox.innerHTML = `<div class="alert alert-success" role="alert">Successfully uploaded your video. click upload to upload your video</div>`
},
error: function(error){
console.log(error)
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">Ups something went wrong!</div>`
},
cache: false,
contentType: false,
processData: false,
})
})
I think what you are trying to achieve here is to show the progress bar only on Ajax submit. So you can just add/remove the display-none class on each operational methods as below.
input.addEventListener('change', () => {
progressBox.classList.add('d-none') // Though this class is already added in html [seems redundant here].
$.ajax({
type: 'POST',
beforeSend: function() {
progressBox.classList.remove('d-none')
},
success: function(response) {
progressBox.classList.add('d-none')
},
error: function(error) {
progressBox.classList.add('d-none')
})
}
Hope this will be one way to work around but let me know if this solves your problem.
I'm sure it's something simple, but I can't get this to work. I've read the documentation and other sources, but I am just not understanding. I simply want to pass data that I retrieve with ajax to an empty array. I've ensured that the data is indeed successfully coming from the server, but it does not appear to get assigned to UserArticles, and does not update the DOM. What am I missing. Here's my code:
Component:
Vue.component('article-selection', {
props: ['articles'],
template: '<div> <p>{{articles.title}}</p> </div>'
})
Vue:
var Article = {};
var UserArticles = [];
var vm = new Vue({
el: '#createNewArticle',
data: {
Article: Article,
UserArticles: UserArticles
},
computed: {
isNewArticle: function () {
return this.Article.ArticleIdentification.Id.length < 5
}
},
created: function(){
this.getUserArticles();
},
methods: {
setUserId: function (id) {
//code
},
createNewArticle: function (msg) {
//code},
getUserArticles: function () {
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
}).done(function (rData, status, jq) {
UserArticles = rData;
toastr.success('', 'Retrieved User Articles');
}).fail(function (rData, status, error) {
var result = $.parseJSON(rData.responseText);
toastr.warning(result.messages, 'Retrieve User Articles')
});
}
}
})
HTML:
<div class="row" id="createNewArticle" >
<div class="col-sm-12">
<!--Create Initial article-->
<div class="row" v-if="true">
<div class="col-sm-12 text-center">
<div>Passed: {{Article.UserId}}</div>
<div class="form" style="display: inline-block;" id="newArticleForm">
<div class="form-group">
<label for="ArticleName">Article Title</label>
<input type="text" class="form-control" id="ArticleTitle"
name="ArticleTitle" v-model="Article.ArticleIdentification.Title" /><br />
<p>{{Article.ArticleIdentification.Title}}</p>
<button class="btn btn-sm" v-on:click="createNewArticle('hey hey')">
Create New Article
</button>
</div>
</div>
</div>
<div class="col-sm-12">
<!--COMPONENT HERE--!>
<article-selection v-for="(artId, index) in UserArticles"
v-bind:key="artId.id"
v-bind:index="index"
v-bind:articles="artId"></article-selection>
</div>
</div>
</div>
Try writing the method like this
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
success: function (data) {
UserArticles = data;
},
error: function (error) {
alert(JSON.stringify(error));
}
})
}
I had to use an arrow function in my ajax code inside of the done function as well as add the this keyword. Note the difference:
getUserArticles: function () {
$.ajax({
method: "GET",
url: "/api/Article/GetUserArticles"
}).done((rData, status, jq) => {
this.UserArticles = rData;
toastr.success('', 'Retrieved User Articles');
}).fail(function (rData, status, error) {
var result = $.parseJSON(rData.responseText);
toastr.warning(result.messages, 'Retrieve User Articles')
});
}
It is my PartialView:
.......
<div class="form-group">
#Html.LabelFor(model => model.securities, htmlAttributes: new { #class = "control-label col-md-2"})
<div class="col-md-10">
#(Html.Kendo().MultiSelect()
.Name("productMultiSelect")
.DataTextField("label")
.DataValueField("value")Product to be used by the multiselect as a value.
.HtmlAttributes(new { style = "width:350px; height:350px", #id = "prd" })
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetLogin", "IT_Inventory");
})
.ServerFiltering(false);
})
.Value(ViewBag.SelectedItem2)
.ItemTemplate("<span><h3 style=\"font-size: 1.2em;font-weight: normal;margin: 0 0 1px 0;padding: 0;\">#: data.label #</h3><p style=\"margin:0;padding:0;font-size: .8em; \">#: data.desc #</p></span>")
)
</div>
</div>
My button:
<button type="button" id="btnSave" class="btn btn-success btn-lg">Save </button>
My JS:
<script>
$("#btnSave").click(function (e) {
e.preventdefault();
$.ajax({
type: 'POST',
url: '#Url.Action("SignIT", "IT_Inventory")',
data: JSON.stringify({ productMultiSelect: $("#productMultiSelect").data("kendoMultiSelect").value(), id: $("#id").val(), SomeBooleanProperty: false }),
dataType: 'json',
contentType: 'application/json',
success: function (data) {
if (data == true) {
$("#onInsert").data("kendoWindow").close();
}
else {
alert("Error!");
}
},
error: function () {
alert("An error has occured!!!");
}
});
});
</script>
When I try post to controller I am getting Uncaught TypeError: Cannot read property 'value' of undefined. For id and SomeBooleanProperty is ok.
When I use submit form is ok.
I should post data to controller list of productMultiSelect?
Looks like you havn't initialize you kendoMultiSelect, or it's in another div;
Check to see it:
console.log($("#productMultiSelect").length); //should be at least 1, if 0, then you initialized kendo in come other div
and
console.log($("#productMultiSelect").data("kendoMultiSelect")); //should be an object - if undefined, then you have not initialized kendo
console.log($("#productMultiSelect").length); - 0
console.log($("#productMultiSelect").data("kendoMultiSelect")); - undefined
very interesting and strange.
This PartialView is in KendoWindow.