1

I am installing a search bar, and I want it to appear when the form is submitted, and complete/dissapear when the response is returned. Any idea on how to do so? I am working with the bootstrap progress bar

<div class="progress" style="height: 5px;">
    <div 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>

I know this is HTML, but would I have to do anything with my fetch or POST request? That relevant code is below:

let progress = 0;
        const maxTime = 5000; // 5 seconds
        let interval = null;


    // onclick or the event that start the call
    interval = setInterval(() => {
    progress = progress >= 100 ? 100 : progress + 1
    document.getElementById('myprogress').style.width = `${progress}%`
    
    // end interval and wait at 100%
    if(progress == 100) clearInterval(interval);
        }, maxTime/100)
    document.getElementById('loadingcontainer').style.display = "none"


        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)
                            // Hide the progressbar, stop the timer and reset progress
                        clearInterval(interval);
                        progress = 0;
                        document.getElementById('myprogress').style.width = "0%"
                        document.getElementById('loadingcontainer').style.display = "";
                  
                        });

                    })


                } catch (err) {
                    console.error(err)
                }

            })

            

        }

enter image description here

Progress-bar:

    .progress-bar {
            background-color: rgb(255, 255, 255);
            color: rgb(197, 90, 28);
            -webkit-box-shadow: none;
            box-shadow: none;
        }

    </style>




<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>
KyleUSA
  • 161
  • 1
  • 1
  • 9
  • Are you downloading anything big? How long does it take to download? – Michael Bauer Jan 25 '21 at 01:42
  • @MichaelBauer Not downloading anything. It takes anywhere from 5-10 seconds to return a response from my backend. Just want to be able to show the user that a response is being generated – KyleUSA Jan 25 '21 at 01:49
  • May still recommend a spinner, even though I said that a progress bar is only useful after 5 or so seconds. Only because you'll then need to hook into the progress events, which Fetch doesn't seem to have. I know using Axios will be a solution to this, take a look at this question: https://stackoverflow.com/questions/44936028/progress-bar-with-axios – Michael Bauer Jan 25 '21 at 02:02
  • @MichaelBauer Even if it stops after 5 seconds before completing, that's fine. Just trying to hit a particular UI – KyleUSA Jan 25 '21 at 02:05

1 Answers1

0

I'd recommend using a spinner instead of a loading bar unless if you're downloading something that takes more than say 5 seconds to download. The reason is that getting hooking the progress bar up to the downloaded chunks won't be worth the effort.

The steps are:

  1. Just before as you send out the request (maybe before or asynchronously after) you display the spinner/progressbar.
  2. Then as your download completes, you'll remove the spinner/progressbar

// --- Set somewhere else but within scope
const url = "some url";
let progress = 0;
const maxTime = 5000; // 5 seconds
let interval = null;

// onclick or the event that start the call
interval = setInterval(() => {
    progress = progress >= 100 ? 100 : progress + 1
    document.getElementById('myprogress').style.width = `${progress}%`
    
    // end interval and wait at 100%
    if(progress == 100) clearInterval(interval);
}, maxTime/100)
document.getElementById('loadingcontainer').style.display = "none"

const data = fetch('/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        url: url
    })
 }).then(res => {
    document.open()
    res.text().then(function(text) {
        document.write("done")
        // Hide the progressbar, stop the timer and reset progress
        clearInterval(interval);
        progress = 0;
        document.getElementById('myprogress').style.width = "0%"
        document.getElementById('loadingcontainer').style.display = "";
    });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

<!-- Optional theme -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>


<div id="loadingcontainer" >
  <div class="progress">
     <div id="myprogress" class="progress-bar progress-bar-striped" role="progressbar" style="width: 10%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100"> 
 </div>
</div>
</div>

Naturally the code above doesn't run because of the fetch but it should give you an idea.

Michael Bauer
  • 357
  • 1
  • 7
  • I am not using jQuery. Would it matter? – KyleUSA Jan 25 '21 at 02:05
  • Not too much, I can modify it to help, but effectively replace the lines .hide() and .show() with `document.getElementById('loadingcontainer').style.display = "none" ` to hide it and set it to "block" or nothing to display it. – Michael Bauer Jan 25 '21 at 02:09
  • I suspect you may actually have jQuery because you say you have bootstrap installed, which has a dependency on it. – Michael Bauer Jan 25 '21 at 02:11
  • Thanks for this. But I really need the progress bar. Even if it stops after 5 seconds before completing, that's fine. Just trying to hit a particular UI – let me update the OP with a mockup – KyleUSA Jan 25 '21 at 02:18
  • Updated the original post – KyleUSA Jan 25 '21 at 02:19
  • It also does not need to show accurate progress. Even if it moves a certain pace, and then pauses, until the request completes and the bar disappears, that is a fine approach – KyleUSA Jan 25 '21 at 02:23
  • Ex: moves for 5 seconds, and then stops, waits for request to complete, and then finishes – KyleUSA Jan 25 '21 at 02:24
  • Sorry for the delay. Since you're using the bootstrap progressbar and may just simulate loading, then you can use something like `setInteval` to have a callback that increment the progress. I'll update the answer. – Michael Bauer Jan 25 '21 at 05:18
  • Thanks man. I just gave it a shot and it renders, but only shows up after data is returned. Not while it is waiting for the data. Any advice? I will update my code to show more. Any advice helps. – KyleUSA Jan 25 '21 at 22:52
  • From the looks of your code there are 2 parts that need tweaking. The first is that you're setting 'loadingcontainer' display to 'none' at the start, and showing it at the end, you need to switch those around. The section of code above `function searchIt()` and below the first 3 lines should be within the `form.addEventListener` callback. – Michael Bauer Jan 26 '21 at 22:08
  • Thank you so much !! Really appreciate all the help – KyleUSA Jan 27 '21 at 01:44