BotUI: Display an animated loading screen prior to performing any actions

When using BotUI (Docs), I want the loading animation to appear before actions (such as buttons) show along with messages.

var botui = new BotUI('hello-world');

botui.message.add({
  content: 'Hello world from bot!'
}).then(function() {
  return botui.message.add({
    delay: 3000,
    human: true,
    content: 'Hello world from human!'
  });
}).then(function() {
  return botui.message.add({
    delay: 3000,
    content: 'Another hello world from bot!'
  });
}).then(function() {
  return botui.message.add({
    delay: 3000,
    human: true,
    content: 'Another hello world from human!'
  });
}).then(function () {
  return botui.action.button({
    delay: 3000,
    action: [{
      text: 'Some button',
      value: 'button1'
    }, {
      text: 'Another button',
      value: 'button2'
    }]
  });
}).then(function (res) {
  if(res.value == 'button1') {
    console.log('Some button was clicked.');
  }
  if(res.value == 'button2') {
    console.log('Another button was clicked.');
  }
});
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
.botui-container {
  font-size: 14px;
  background-color: #fff;
  font-family: "Open Sans", sans-serif;
}

.botui-messages-container {
  padding: 10px 20px;
}

.botui-actions-container {
  padding: 10px 20px;
}

.botui-message {
  min-height: 30px;
}

.botui-message-content {
  padding: 7px 13px 17px 13px;
  border-radius: 15px;
  color: #595a5a;
  background-color: #ebebeb;
}

.botui-message-content.human {
  color: #f7f8f8;
  background-color: #919292;
}

.botui-message-content.text {
  line-height: 1.3;
}

.botui-message-content.loading {
  background-color: rgba(206, 206, 206, 0.5);
  line-height: 1.3;
  text-align: center;
}

.botui-message-content.embed {
  padding: 5px;
  border-radius: 5px;
}

.botui-message-content-link {
  color: #919292;
}

.botui-actions-text-input {
  border: 0;
  outline: 0;
  border-radius: 0;
  padding: 5px 7px;
  font-family: "Open Sans", sans-serif;
  background-color: transparent;
  color: #595a5a;
  border-bottom: 1px solid #919292;
}

.botui-actions-text-submit {
  color: #fff;
  width: 30px;
  padding: 5px;
  height: 30px;
  line-height: 1;
  border-radius: 50%;
  border: 1px solid #919292;
  background: #777979;
}

.botui-actions-buttons-button {
  border: 0;
  color: #fff;
  line-height: 1;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  padding: 7px 15px;
  border-radius: 4px;
  font-family: "Open Sans", sans-serif;
  background: #777979;
  box-shadow: 2px 3px 4px 0 rgba(0, 0, 0, 0.25);
}

.botui-actions-text-select {
  border: 0;
  outline: 0;
  border-radius: 0;
  padding: 5px 7px;
  font-family: "Open Sans", sans-serif;
  background-color: transparent;
  color: #595a5a;
  border-bottom: 1px solid #919292;
}

.botui-actions-text-searchselect {
  border: 0;
  outline: 0;
  border-radius: 0;
  padding: 5px 7px;
  font-family: "Open Sans", sans-serif;
  background-color: transparent;
  color: #595a5a;
  border-bottom: 1px solid #919292;
}

.botui-actions-text-searchselect .dropdown-toggle {
  border: none !important;
}

.botui-actions-text-searchselect .selected-tag {
  background-color: transparent !important;
  border: 0 !important;
}

.slide-fade-enter-active {
  transition: all 0.3s ease;
}

.slide-fade-enter,
.slide-fade-leave-to {
  opacity: 0;
  transform: translateX(-10px);
}

.dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 0.5rem;
  display: inline-block;
  background-color: #919292;
}

.dot:nth-last-child(1) {
  margin-left: 0.3rem;
  animation: loading 0.6s 0.3s linear infinite;
}

.dot:nth-last-child(2) {
  margin-left: 0.3rem;
  animation: loading 0.6s 0.2s linear infinite;
}

.dot:nth-last-child(3) {
  animation: loading 0.6s 0.1s linear infinite;
}

@keyframes loading {
  0% {
    transform: translate(0, 0);
    background-color: #ababab;
  }
  25% {
    transform: translate(0, -3px);
  }
  50% {
    transform: translate(0, 0);
    background-color: #ababab;
  }
  75% {
    transform: translate(0, 3px);
  }
  100% {
    transform: translate(0, 0);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/botui/build/botui.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/botui/build/botui.min.css">
<div class="botui-app-container" id="hello-world">
  <bot-ui></bot-ui>
</div>

I have pinpointed the relevant template section in botui.js.

<div v-if=\"msg.loading\" class=\"botui-message-content loading\"><i class=\"dot\"></i><i class=\"dot\"></i><i class=\"dot\"></i></div>

However, because the content of the botui-actions-container is loaded after a delay, I am unable to show the loading animation before the buttons appear.

Answer №1

Attempting to alter the functionality of a third-party component is generally not recommended. If you find yourself in this situation, the most effective approach may be to create a new request on their Github page. Clearly outline your needs and there's a chance they will incorporate the desired feature into their component.

Answer №2

To achieve the desired outcome without altering the internal workings of BotUI, you can utilize botui.message.add along with botui.message.remove to display loading before executing an action. This method allows the loading feature to appear before the action, even though botui.action does not have a built-in loading parameter.

The following code showcases how I implement this approach using botui.action.button, but any action can be used. By setting delay: 0 for the action, it will replace the loading indicator without displaying a blank message if the initial message is not removed.

// add an empty message to use the "loading" feature not available with action
botui.message.add({
    delay: 2000,
    loading: true,
    content: ''
}).then(function (index) {
    // get the index of the empty message and delete it
    botui.message.remove(index);
    // display action with 0 delay
    botui.action.button({
        delay: 0,
        action: [{
            text: 'Action 1',
            value: 'a1'
        }, {
            text: 'Action 2',
            value: 'a2'
        }]
    }).then(function (res) {
        botui.message.bot({
            delay: 1000,
            content: 'action chosen: ' + res.value
        });
    });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Creating a new object in ThreeJs by deriving from an existing object

After importing an .obj file, I successfully created an object that I now want to clone and assign unique coordinates to. Specifically, I have a wall to which I have attached another object (a window) as a child. Everything functions correctly when movin ...

Performing an HTTP GET Request in Node.js or Express.js

Currently, I am working with express.js and require assistance in making an HTTP GET request to retrieve JSON data. Can anyone recommend some reliable node js/express js modules or libraries that can help me with performing get/post requests? ...

The NextJs router encountered an unknown key passed through the urlObject during the push operation

I have a Next.js/React application where I am utilizing the Next Router to include some queries in my URL. However, when using the following function, the Chrome Dev Console displays numerous warnings: const putTargetsToQueryParams = (targets: IFragrance ...

Reversing the order of input-group-addon and input in bootstrap on mobile devices

I attempted to adjust the layout of a bootstrap input-group-addon on mobile devices by using two input elements and manipulating their display and visibility properties. From a design standpoint, I achieved the desired result as the input is now positione ...

How can I incorporate a custom color into a preset navbar on an HTML webpage?

<div class="navbar-header"> <button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" style="color: blue;" class="navbar-toggle collapsed" type="button"> <i class="fa fa-reo ...

Encountering an Uncaught TypeError occurs when attempting to access properties of undefined, specifically while utilizing an object method with arrays

I was studying how to destructure arrays from objects and expected the order function to return two values, but it did not. const restaurant = { name: 'Classico Italiano', location: 'Via Angelo Tavanti 23, Firenze, Italy', c ...

Adjust the component's onClick property in Next.js

Looking for guidance on how to update a property value of a component in Next.js. I have been using the Material-UI library for styling. Encountering an issue when attempting to modify the 'open' property of a drawer component, as it constantly ...

The Angular/Bootstrap Modal is not functioning properly: TypeError occurs due to v2.deleteModalProject not being recognized as a function and

My main objective is to allow users to call the modal multiple times for content deletion. However, I encountered issues when the modal was triggered a second time without reloading the page. I am currently working with Angular version 1.5.6 After spendi ...

What could be causing the lack of styling in my Express application?

The styles are not rendering correctly on the specified route: 'http://localhost:5000/exams/add-new' However, they are working fine on the following routes: 'http://localhost:5000' 'http://localhost:5000/exams' 'http:// ...

What is the best way to access the validation group in a javascript event?

Recently, I've been grappling with a challenge involving a button that has a validation group. The quirk is that the button click event triggers a jQuery function without using onclientclick. As I navigate through this dilemma, one burning question re ...

Order the AJAX information within a table using tablesorter.js

Having trouble with tablesorter.js and ajax updates on my table. Followed the code from this page, but it's not working as expected. Even noticed issues on the example website where clicking "append new table data" doesn't sort correctly. However ...

Can the combination of a JavaScript frontend and NodeJS backend function effectively together in this scenario?

I have a Domain-A that serves as a static site on Netlify, offering shopping cart functionalities. On the other hand, I have Domain-B hosting a backend server running a Node.JS payment system and utilizing Auth Services through passport.js. Due to its na ...

Ways to extract the maximum value from a dataset formatted in JSON

My current project involves using highcharts to create data series for plotting the chart, which looks something like this: series: [{ data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4] }] I have been considering ...

Can you explain why when using `<button>` within `<input type="file" />` it doesn't activate the native file selector, but it works fine with `<div>`?

Kindly review this simple example .hidden { position: absolute; top: 0; left: 0; width: 1px; height: 1px; visibility: hidden; } <label for="inputFile"> <input id="inputFile" class="hidden" type="file" /> <div>Clic ...

Clicking on navigation does not close Bootstrap dropdown

When I use this code on my HTML page, the dropdown menu appears correctly. However, once I click a link, the menu does not close and remains open. How can I resolve this issue? <div class="col-lg-8 col-md-8 col-xs-2 accordion-menu"> <button t ...

Changing the positioning of divisions based on screen size, transitioning from 1200px width and larger to mobile devices

I'm working on creating a layout with two different displays for larger screens (992-1200) and mobile devices. Here is my rough drawing and demo links: For screen sizes 992 and up: https://i.sstatic.net/mztjL.png For mobile: Display should look like ...

Ways to prevent styles from being overridden by those specified in JavaScript

Some elements on my page have their style dynamically changed by JavaScript. However, I want one of them to maintain its static style without being overridden. Is there a way to specify that the style of this particular element should not be altered? Than ...

Neglecting to utilize a parameter in a function

Here's a question from a beginner: what if I create a function named sendRequest that accepts multiple parameters for an ajax call? I'm not really concerned about the ajax request itself, I just want to understand how the parameters work. funct ...

Having trouble with Grunt and Autoprefixer integration not functioning properly

Joining a non-profit open source project, I wanted to contribute by helping out, but I'm struggling with Grunt configuration. Despite my research, I can't seem to figure out why it's not working. I am trying to integrate a plugin that allow ...

As the object rotates, the camera in Three.js dynamically follows suit, creating a

In my game, I am struggling to make the camera always face the back of a helicopter as it rotates. Despite my efforts, I can't seem to synchronize the camera's movement with that of the helicopter. You can see an image of what I'm aiming for ...