How does SUSI AI web bot plugin work

   In this blog, we’ll learn how SUSI AI web plugin works. Normally, for any bot like Kik bot, we don’t have to worry about the chat boxes or the way chatbot is rendered on screen because all of that is handled by the service on which we are building our bot. So, for these bots, we simply take the text input from user, send a GET request to SUSI server, receive the response and display it. This is not the case with SUSI AI Web Bot plugin. In this case, there is not Bot platform. Hence, there are a lot of other things that we need to take care of here. Let’s explore the main ones among them. Adding bot to website: The final product that we’re going to provide to the client is going to be just a JavaScript code. Hence the HTML code of bot widget needs to be added to the <body> of the website. This is done usingappend() method of jQuery. The html() method sets or returns the content (innerHTML) of selected elements. Syntax: $(selector).append(content) So we store the HTML code of bot widget in a variable and then returns the content of that variable to the body tag using: $("body").append(mybot); Here “mybot” is the variable containing HTML code of bot widget. The text boxes of user texts and bot texts are added to a HTML element in the same way. Event handling: JavaScript's interaction with HTML is handled through events that occur when the user or the browser manipulates a page. Loading of the page, clicking, pressing a key, closing a window, resizing the window etc are all examples of events. In the SUSI AI web bot, there are two major events. Clicking a button This is required for allowing clicks on send button. Clicking of a button can be done in many ways. There are two major ways that are used in SUSI AI web bot. Some elements already exist on the webpage. For example - the HTML code of web bot. It is added to the body tag as soon as webpage loads. For these elements we use click(). The click() binding is called “direct” binding which can be attached to the elements that already exists. Syntax: $(selector).click(function); Selector - Class, ID or name of HTML element. Function - Specifies the function to run when click event occurs. Some elements are dynamically generated. This means that they are added at a later point of time. For example - the text messages are added when user types in. This happens after loading of page. For this, we have to create “delegated” binding by using on() method. Syntax: $(selector).on(event,childSelector,data,function); Selector - Class, ID or name of HTML element Event - (Required) Specifies one or more event(s) or namespaces to attach to the selected elements. childSelector - (Optional) Specifies that the event handler should only be attached to the specified child elements Data - (Optional) Specifies additional data to pass along to the function Function - Specifies the function to run when click event occurs. Pressing the enter key For identifying which key…

Continue ReadingHow does SUSI AI web bot plugin work

Variable Font Size Badgeyay

Badgeyay is a simple badge generator that aims for promoting an open-source tool for generation of badges in PDF format. The project has options to choose from predefined set of images or upload a background image. User can choose from set of fonts and color of the same. But now Badgeyay also has option to choose custom font-size in generation of badges. To implement font size feature,  first, the component that is determining the font of the label has to be identified. The label that determines the text on the badge is the <text> label and within it, the label that determines the properties of the text is <tspan>. So mainly we need to alter the properties in the tspan. The property that determines the font size for the badge is font-size and its default value is set to 31.25 px. If the property in the labels changed, then we can see the corresponding changes in the PDF generated from the svg. Now the challenges were: To Determine the font value from the frontend. Using the same for the font-config. Changing the built svg accordingly. Procedure Firstly frontend component has to be changed to incorporate a slider to give input for the variable font size. So a range input is inserted with range from 15 px to 45 px and default as 30 px. The size_print label gets changed dynamically to show the value selected from the range slider. <li> <input type="radio" name="fontsize" id="font-size-picker"> Choose font size </li> <section id="font-size-input" style="display:none;"> <label for="inputFile" id="size_print"></label> <div> <input type="range" id="font-size" max=45 min=15 step=5 value=30  class="form-control" name="font_size"> </div> </section> After adding the component, form script is changed to add toggle behaviour to the button. For adding the toggling behaviour in the component, checkbox is used and the value of the label is updated dynamically as the slider value is changed. $("#size_print").text($("#font-size").val() + " px");       $("#font-size-picker").click(function () {           if ($(this).is(":checked")) {               $("#font-size-input").css("display", "block");           } else {               $("#font-size-input").css("display", "none");           }       });       $("#font-size").on('input', function () {           $("#size_print").text($(this).val() + " px");       }); After completing the work on the frontend, it is necessary to modify the backend too. The method for choosing custom font has to be refactored. It now checks whether the custom font is set or font size variable is set, and creates a config file for fonts which after use gets deleted. font_config = {}    # custom font is specified    if custom_font != '':        font_config['font'] = custom_font    if font_size != '':        font_config['font_size'] = font_size    if custom_font != '' or font_size != '':        json_str = json.dumps(font_config)        print(json_str)        f = open(os.path.join(app.config['UPLOAD_FOLDER'], 'fonts.json'), "w+")        f.write(json_str)        f.close() The generator class is modified as well to accommodate the changes, by adding a new class attribute called font_size. We find the keys in the dict object loaded from the file and assign the same to class attribute. if 'font_size' in self.DATA.keys():                self.font_size = self.DATA['font_size'] Make the necessary change in the svg, so that font size change can be represented in the generated PDF. Replace the old font size with the new…

Continue ReadingVariable Font Size Badgeyay

Updating the UI of the generator form in Open Event Webapp

The design of the generator form in Open Event Webapp has been kept very simple and there have been minor modifications to it over time. In keeping up with the changes made to the front page of the other apps, there was a need to modify the UI of the generator and add some new elements to it. This is the related issue for it. The whole work can be seen here. There were three main parts to it: Add a top bar similar to the Open Event Frontend Add a pop-up menu bar similar to the one shown in Google/Susper Add a version deployment link at the bottom of the page like the one shown in staging.loklak.org.   Implementing the top-bar and the pop-up menu bar The first task was to introduce a top-bar and a pop-up menu bar in Generator. The top-bar would contain the text Open Event Webapp Generator and an icon button on the right side of it which would show a pop-up menu. The pop-up menu would contain a number of icons which would link to different pages like FOSSASIA blogs and it’s official website, different projects like loklak, SUSI and Eventyay and also to the Webapp Project Readme and issues page. Creating a top navbar is easy but the pop-up menu is a comparatively tougher. The first step was to gather the gather the small images of the different services. Since this feature had already been implemented in Susper project, we just copied all the icon images from there and copy it into a folder named icons in the open event webapp. Then we create a custom menu div which would hold all the different icons and present it an aesthetic manner. Write the HTML code for the menu and then CSS to decorate and position it! Also, we have to create a click event handler on the pop-up menu button for toggling the menu on and off. Here is an excerpt of the code. The whole file can be seen here <div class="custom-navbar"> <a href='.' class="custom-navtitle"> <strong>Open Event Webapp Generator</strong> <!-- Navbar Title --> </a> <div class="custom-menubutton"> <i class="glyphicon glyphicon-th"></i> <!-- Pop-up Menu button --> </div> <div class="custom-menu"> <!-- Custom pop-up menu containing different links --> <div class="custom-menu-item"> <a class="custom-icon" href="http://github.com/fossasia/open-event-webapp" target="_blank"><img src="./icons/code.png"> <p class="custom-title">Code</p></a> </div> <!-- Code for other links to different projects--> </div> </div> Here is a screenshot of how the top-bar and the pop-up menu looks! Adding version deployment info to the bottom The next task was to add a footer to the page which would contain the version deployment info. The user can click on that link and we can then be taken to the latest version of the code which is currently deployed. To show the version info, we make use of the Github API. We need to get the hash of the latest commit made on the development branch. We send an API request to the Github requesting for the latest hash and then dynamically add the info and the link received to the footer. The user can then click on that…

Continue ReadingUpdating the UI of the generator form in Open Event Webapp

Implementation of Image Viewer in Susper

We have implemented image viewer in Susper similar to Google. Before when a user clicks on a thumbnail the images are opened in a separate page, but we want to replace this with an image viewer similar to Google. Implementation Logic: 1. Thumbnails for images in susper are arranged as shown in the above picture. 2. When a user clicks on an image a hidden empty div(image viewer) of the last image in a row is opened. 3. The clicked image is then rendered in the image viewer (hidden div of the last element in a row). 4. Again clicking on the same image closes the opened image viewer. 5. If a second image is clicked then, if an image is in the same row, it is rendered inside the same image viewer. else if the image is in another row, this closes the previous image viewer and renders the image in a new image viewer (hidden div of the last element of the row) 6. Since image viewer is strictly the hidden empty div of the last element in a row when it is expanded it occupies the position of the next row, moving them further down similar to what we want. Implementation Code results.component.html <div *ngFor="let item of items;let i = index"> <div class="item"> <img src="{{item.link}}" height="200px" (click)="expandImage(i)" [ngClass]="'image'+i"> </div> <div class=" item image-viewer" *ngIf="expand && expandedrow === i"> <span class="helper"></span> <img [src]="items[expandedkey].link" height="200px" style="vertical-align: middle;"> </div> </div> Each thumbnail image will have a <div class=" item image-viewer" which is in hidden state initially. Whenever a user clicks on a thumbnail that triggers expandImage(i) results.component.ts expandImage(key) { if (key === this.expandedkey this.expand === false) { this.expand = !this.expand; } this.expandedkey = key; let i = key; let previouselementleft = 0; while ( $('.image' + i) && $('.image' + i).offset().left > previouselementleft) { this.expandedrow = i; previouselementleft = $('.image' + i).offset().left; i = i + 1; The expandImage() function takes the unique key and finds which image is the last element is the last image in the whole row, and on finding the last image, expands the image viewer of the last element and renders the selected image in the image viewer. The source code for the whole implementation of image viewer could be seen at pull: https://github.com/fossasia/susper.com/pull/687/files Resources: Selecting elements in Jquery: https://learn.jquery.com/using-jquery-core/selecting-elements/  

Continue ReadingImplementation of Image Viewer in Susper

Implementing ICS/ICAL to sync calendars with the event schedule in Open Event Webapp

Many people use different calendar apps to mark important events which they want to follow up on later. Other closed source event management systems like sched.org provide users the functionality to export the sessions data of an event into a file which can then be easily imported into other apps like Google Calendar. We wanted to implement the same functionality in the Open Event Webapp. Here is the issue regarding the feature here. ICS/ICAL is the standard format for calendar files (which was discussed above) used by different programs like Google Calendar, Microsoft Outlook etc. They help users to quickly import and export data from their calendars and share it with the outside world. As is the case with any other global format, the contents of the ICS file must follow some specifications for it to be able to be read by the different programs. The official description is quite verbose and detailed and can be read here. As an end result, we want to provide a button to the user which will export the whole data of the event schedule to an ICS file and present it to the user for download after clicking the button. The whole work regarding the feature can be seen here. Instead of implementing the whole specification ourselves which would be much tougher and time-consuming, we looked for some good open source libraries to do a bit of heavy lifting for us. After searching exhaustively for the solution, we came across this library which seemed appropriate for the job. The heart of the library is a function which takes in an object which contains information about the session. It expects information about the start and end time, subject, description and location of the session. Here is an excerpt from the function. The whole file can be seen here var addEvent = function (session) { var calendarEvent = [ 'BEGIN:VEVENT', 'UID:' + session.uid, 'CLASS:PUBLIC', 'DESCRIPTION:' + session.description, 'DTSTART;VALUE=DATETIME:' + session.begin, 'DTEND;VALUE=DATE:' + session.stop, 'LOCATION:' + session.location, 'SUMMARY;LANGUAGE=en-us:' + session.subject, 'TRANSP:TRANSPARENT', 'END:VEVENT' ]; calendarEvents.push(calendarEvent); }; We need to call the above function for every session in the event schedule. In the schedule template file, we have the jsonData object available which contain all the information about the event. It contains a field called timeList which contains the chronological order of the different sessions taking place throughout the events. The structure of that sub-object is something like this. [{'slug': '2017-03-20', 'times': {'caption' : '09:00-09:30', 'sessions': [{'title': 'Welcome', 'description': 'Opening of the event', 'start': '09:00', 'end': '09:30'}]}] So, we define a function for iterating through every session in the above object and adding it to the calendar. We can use most of the attributes directly but have to modify the date and time fields of the session to an appropriate format before adding it. The specification expects time in the ISO 8601 Format. You can read more about the specification here. For eg - If the date is 2017-03-20 and the time is 09:30 then it should be written as 20170320T093000. Here is some part of the function here function exportICS() {…

Continue ReadingImplementing ICS/ICAL to sync calendars with the event schedule in Open Event Webapp

Implementing Logging Functionality in Open Event Webapp

Open Event Webapp allows event organizers to generate an event website by providing JSON data in the form of a zip file or an API endpoint. The generation of event website is a multi step process and takes some time to complete. In order to see the ongoing progress of the process and catch any errors, logging feature is a must. The challenging part was to send the log messages in real time about the tasks being performed in the generator instead of sending it after some time when the task is already finished. To enable real time communication between the web server and the client, we use the Socket IO library. But before using that library for sending log messages from server to client, we have to design the architecture of the logging feature. The log statements can be of several types. It could be about the inception of a task, the successful completion of it or some error which occurred while performing the task. The log message object contains a field named type to show the type of the statements. We define three categories of logs messages:- INFO: Info statements give information about the task currently being performed by the webapp SUCCESS: Success statements give the information of a task being successfully completed ERROR: Error statements give information about a task failing to complete. These statements also contain a detailed error log Along with the type of the statement, the object also contains information about the task. For all types of statements, there is a field called smallMessage containing short information about the task. For the ERROR statements where more information is required to see what went wrong, the message object has an additional field called largeMessage which holds detailed information about the event. We also create a new file called buildlogger.js and define a function for creating log statements about the tasks being performed by generator and export it. The function creates a message object from the arguments received and then return it to the client under the buildLog event via the socket IO. exports.addLog = function(type, smallMessage, socket, largeMessage) { var obj = {'type' : type, 'smallMessage' : smallMessage, 'largeMessage': largeMessage}; var emit = false; if (socket.constructor.name === 'Socket') { emit = true; } if (emit) { socket.emit('buildLog', obj); } }; Most of the steps of the generation process are defined in the generator.js file. So, we include the logging file there and call the addLog function for sending logs messages to the client. All the different steps like cleaning temporary folders, copying assets, fetching JSONs, creating the website directory, resizing images etc have multiple log statements for their inception and successful/erroneous completion. Below is an excerpt from the cleaning step. var logger = require('./buildlogger.js'); async.series([ (done) => { console.log('CLEANING TEMPORARY FOLDERS\n'); logger.addLog('Info', 'Cleaning up the previously existing temporary folders', socket); fs.remove(distHelper.distPath + '/' + appFolder, (err) => { if(err !== null) { // Sending Error Message when the remove process failed logger.addLog('Error', 'Failed to clean up the previously existing temporary folders', socket, err); } // Success message denoting the completion of the…

Continue ReadingImplementing Logging Functionality in Open Event Webapp

Implementing Tracks Filter in Open Event Webapp using the side track name list

Event Websites generated by Open Event Webapp may contain a large number of sessions presented by different speakers. The Sessions are divided into the different group based on their type of track. For example, few sessions may belong to Database Track, few may belong to Machine Learning Track and so on. It is natural that the user may want to filter the visible sessions on the basis of tracks. Before we implemented the tracks filter using the track names list, we had a sub navbar on the tracks page for jumping to the different tracks of the event on a particular day. Below are the screenshots of that feature. On Clicking the Design, Art, Community Track But, it was not an elegant solution. We already had a track names list present on the side of the page which remained unused. A better idea was to use this side track names list to filter the sessions. Other event management sites like http://sched.org follow the same idea. The relevant issue for it is here and the major work can be seen in this Pull Request. Below is the screenshot of the unused side track names list. The end behavior should be something like this, the user clicks on a track and only sessions belonging to the track should be visible and the rest be hidden. There should also be a button for clearing the applied filter and reverting the page back to its default view. Let’s jump to the implementation part. First, we make the side track name list and make the individual tracks clickable. <div class="track-names col-md-3 col-sm-3"> {{#tracknames}} <div class="track-info"> <span style="background-color: {{color}};" class="titlecolor"></span> <span class="track-name" style="cursor: pointer">{{title}} </span> </div> {{/tracknames}} </div> Now we need to write a function for handling the user click event on the track name. Before writing the function, we need to see the basic structure of the tracks page. The divs with the class date-filter contain all the sessions scheduled on a given day. Inside that div, we have another div with class tracks-filter which contains the name of the track and all the sessions of that track are inside the div with class room-filter. Below is a relevant block of code from the tracks.hbs file <div class="date-filter"> // Contains all the sessions present in a single day <div class="track-filter row"> // Contains all the sessions of a single track <div class="row"> // Contains the name of the track <h5 class="text">{{caption}}</h4> </div> <div class="room-filter" id="{{session_id}}"> // Contain the information about the session </div> </div> </div> We iterate over all the date-filter divs and check all the track-filter divs inside it. We extract the name of the track and compare it to the name of the track which the user selected. If both of them are same, then we show that track div and all the sessions inside it. If the names don’t match, then we hide that track div and all the content inside it. We also keep a variable named flag and set it to 0 initially. If the user selected track is present on a given day, we set the flag to 1. Based on it, we decide whether to display that particular day or not. If the flag is set, we display the date-filter div of that…

Continue ReadingImplementing Tracks Filter in Open Event Webapp using the side track name list

Implementing Search Bar Using GitHub API In Yaydoc CI

In Yaydoc’s, documentation will be generated by typing the URL of the git repository to the input box from where user can generate documentation for any public repository, they can see the preview and if they have access, they can push the documentation to the github pages on one click. But In Yaydoc CI user can register the repository only if he has access to the specific repository, so I decided to show the list to the repository where user can select from the list but then it also has one problem that Github won’t give us all the user repository data in one api hit and then I made a search bar in which user can search repository and can register to the Yaydoc CI. var search = function () { var username = $("#orgs").val().split(":")[1]; const searchBarInput = $("#search_bar"); const searchResultDiv = $("#search_result"); searchResultDiv.empty(); if (searchBarInput.val() === "") { searchResultDiv.append('<p class="text-center">Please enter the repository name<p>'); return; } searchResultDiv.append('<p class="text-center">Fetching data<p>'); $.get(`https://api.github.com/search/repositories?q=user:${username}+fork:true+${searchBarInput.val()}`, function (result) { searchResultDiv.empty(); if (result.total_count === 0) { searchResultDiv.append(`<p class="text-center">No results found<p>`); styles.disableButton("btnRegister"); } else { styles.disableButton("btnRegister"); var select = '<label class="control-label" for="repositories">Repositories:</label>'; select += '<select class="form-control" id="repositories" name="repository" required>'; select += `<option value="">Please select</option>`; result.items.forEach(function (x){ select += `<option value="${x.full_name}">${x.full_name}</option>`; }); select += '</select>'; searchResultDiv.append(select); } }); }; $(function() { $("#search").click(function () { search(); }); }); In the above snippet I have defined search function which will get executed when user clicks the search button. The search function will get the search query from input box, if the search query is empty it’ll show the message as “Please enter repository name”, if it is not empty it’ll hit the GitHub API to fetch user repositories. If the GitHub returns empty array it’ll show “No results found”. In between searching time “Fetching data” will be shown. $('#search_bar').on('keyup keypress', function(e) { var keyCode = e.keyCode || e.which; if (keyCode === 13) { search(); } }); $('#ci_register').on('keyup keypress', function(e) { var keyCode = e.keyCode || e.which; if (keyCode === 13) { e.preventDefault(); return false; } }); Still we faced some problem, like on click enter button form is automatically submitting. So I’m registering event listener. In that listener I’m checking whether the key code is 13 or not. Key code 13 represent enter key, so if the key code is 13 then i’ll prevent the form from submitting. You can see the working of the search bar in the Yaydoc CI. Resources: Ajax Search Box in PHP and MySQL GitHub API Documentation jQuery AJAX Autocomplete – Country Example Build an AJAX search bar

Continue ReadingImplementing Search Bar Using GitHub API In Yaydoc CI

Implementing a Collapsible Responsive App Bar of SUSI Web Chat

In the SUSI Web Chat application we wanted to make few static pages such as: Overview, Terms, Support, Docs, Blog, Team, Settings and About. The idea was to show them in app bar. Requirements were  to have the capability to collapse on small viewports and to use Material UI components. In this blog post I’m going to elaborate how we built the responsive app bar Using Material UI components. First we added usual Material UI app bar component  like this. <header className="nav-down" id="headerSection"> <AppBar className="topAppBar" title={<a href={this.state.baseUrl} ><img src="susi-white.svg" alt="susi-logo" className="siteTitle"/></a>} style={{backgroundColor:'#0084ff'}} onLeftIconButtonTouchTap={this.handleDrawer} iconElementRight={<TopMenu />} /> </header> We added SUSI logo instead of the text title using below code snippet and linked it to the home page like this. title={<a href={this.state.baseUrl} ><img src="susi-white.svg" alt="susi-logo" className="siteTitle"/></a>} We have defined "this.state.baseUrl" in constructor and it gets the base url of the web application. this.state = { openDrawer: false, baseUrl: window.location.protocol + '//' + window.location.host + '/' }; We need to open the right drawer when we click on the button on top left corner. So we have to define two methods to open and close drawer as below. handleDrawer = () => this.setState({openDrawer: !this.state.openDrawer}); handleDrawerClose = () => this.setState({openDrawer: false}); Now we have to add components that we need to show on the right side of the app bar. We connect those elements to the app bar like this. "iconElementRight={}" We defined “TopMenu” Items like this. const TopMenu = (props) => ( <div> <div className="top-menu"> <FlatButton label="Overview" href="/overview" style={{color:'#fff'}} className="topMenu-item"/> <FlatButton label="Team" href="/team" style={{color:'#fff'}} className="topMenu-item"/> </div> We added FlatButtons to place links to other static pages. After all we needed a FlatButton that gives IconMenu to show login and signup options. <IconMenu {...props} iconButtonElement={ <IconButton iconStyle={{color:'#fff'}} ><MoreVertIcon /></IconButton> }> <MenuItem primaryText="Chat" containerElement={<Link to="/logout" />} rightIcon={<Chat/>}/> </IconMenu> </div> ); After adding all these correctly you will see this kind of an app bar in your application. Now our app bar is ready. But it does not collapse on small viewports. So we planned to hide flat buttons on small sized screens and show the menu button. For that we used media queries. @media only screen and (max-width: 800px){ .topMenu-item{ display: none !important; } .topAppBar button{ display: block !important; } } This is how we built the responsive app bar using Material UI components. You can check the preview from this url. If you are willing to contribute to SUSI Web Chat here is the GitHub repository. Resources: Material UI Components: http://www.material-ui.com/#/components/ Learn More about media queries: https://www.w3schools.com/css/css_rwd_mediaqueries.asp

Continue ReadingImplementing a Collapsible Responsive App Bar of SUSI Web Chat

Implementing Hiding App Bar of SUSI Web Chat Application

In the SUSI Web Chat application we got a requirement to build a responsive app bar for static pages and there was another requirement to  show and hide the app bar when user scrolls. Basically this is how it should work: The app bar should be hidden after user scrolls down to a certain extent. When user scrolls up, It should appear again. First we tried readymade node packages to do this task. But these packages are hard to customize. So we planned to make this feature from the sketch. We used Jquery for this. This is how we built this. First we installed jQuery package using this command. npm install jquery Next we imported it on top of the application like this. import $ from 'jquery' We have discussed about this app bar and how we made it in previous blog post. Our app bar is like this. <header className="nav-down" id="headerSection"> <AppBar className="topAppBar" title={<img src="susi-white.svg" alt="susi-logo" className="siteTitle"/>} style={{backgroundColor:'#0084ff'}} onLeftIconButtonTouchTap={this.handleDrawer} iconElementRight={<TopMenu />} /> </header> We have to use these HTML elements to write jQuery code. But we can’t refer HTML elements before it renders. So we have to define it soon after the render method executes. We can do it using “React LifeCycle” method. We have to add our code into the “componentDidMount()” method. This is how we used jQuery inside the “componentDidMount()” lifeCycle method. Here we assigned the height of the App Bar using "$('header').outerHeight();" componentDidMount(){ var didScroll; var lastScrollTop = 0; var delta = 5; var navbarHeight = $('header').outerHeight(); Here we assigned the height of the app bar to “navbarHeight” variable. $(window).scroll(function(event){ didScroll = true; }); In this part we checked whether the user has scrolled or not. If user scrolled we set the value of “didScroll” to “true”. Now we have to define what to do if user has scrolled. function hasScrolled() { var st = $(window).scrollTop(); if(Math.abs(lastScrollTop - st) <= delta){ return; } Here we get the absolute scrolled height. If the height is less than the delta value we defined, it does not do anything. It just returns. if (st > lastScrollTop && st > navbarHeight){ $('header').removeClass('nav-down').addClass('nav-up'); } else if(st + $(window).height() < $(document).height()) { $('header').removeClass('nav-up').addClass('nav-down'); } lastScrollTop = st; } Here we hide the app bar after user scrolled down more than the height of the app bar. If we need to change the height which app bar should disappear, we just need to add a value to the condition like this. if (st > lastScrollTop && st > navbarHeight + 200){ If the user scrolled down more than that value we change the class name of the element “nav-down” to “nav-up”. And we change the className “nav-up” to “nav-down” when user is scrolling up. We defined CSS classes in the stylesheet to do these things and the animations of action. header { background: #f5b335; height: 40px; position: fixed; top: 0; transition: top 0.5s ease-in-out; width: 100%; } .nav-up { top: -100px; } We have defined the things which we need to do when…

Continue ReadingImplementing Hiding App Bar of SUSI Web Chat Application