css Audio - Active file-generic CSS - Active Generic - Active HTML - Active JS - Active SVG - Active Text - Active file-generic Video - Active header Love html icon-new-collection icon-person icon-team numbered-list123 pop-out spinner split-screen star tv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <div class="container">
    <div class="js-messenger messenger">
        <ul class="js-message-list message-list">
            <li class="message message--help">
                <p class="message__name">Sambego</p>
                <div class="message__inner">
                    <p class="help__text">Try to ask me some of these questions:</p>
                    <ul class="help__topics">
                        <li>Are you there?</li>
                        <li>Who are you?</li>
                        <li>Where do you live?</li>
                        <li>How old are you?</li>
                        <li>Do you have any hobbies?</li>
                        <li>Will you be my friend?</li>
                        <li>Goodbye.</li>
                        <li>...</li>
                    </ul>
                </div>
            </li>
        </ul>
    </div>
    <div class="toolbar">
        <button class="js-listen button button--listen">Start listening</button>
    </div>
</div>
<div class="js-loader loader">Loading</div>
            
          
!
            
              $gray: #F1F5F8;
$gray-dark: #434753;

$green: #62BF6E;
$blue: #7BC4EF;

* {
    box-sizing: border-box;
}

html,
body {
    height: 100%;

    background: $gray;
    
    font-size: 10px;
    font-family: Helvetica, Arial, sans-serif;
}

.container {
    display: flex;
    flex-flow: column;
    
    height: 100%;
}

.messenger {
    height: 100%;
    padding: 1rem 2rem;
    
    overflow-x: auto;
}

.message-list {
    margin: 0 auto;
    max-width: 40rem;
}

.message {
    position: relative;
    display: block;
}

.message__name {
    position: relative;
    
    padding: 0 0 0 1.6rem;
    
    font-size: 1rem;
    color: $gray-dark;
    
    &::before {
        content: "";
        
        position: absolute;
        top: .3rem;
        left: 0;
        
        width: .5rem;
        height: .5rem;
        
        background: $green;
        
        border-radius: 50%;
    }
}

.message__inner {
    position: relative;
    
    display: inline-block;
    margin: 1.2rem 0 1rem 0;
    padding: .6rem 1rem;
    min-width: 3.4rem;
    min-height: 3.4rem;
    
    background: $green;
    
    border-radius: .3rem;
    
    font-size: 1.5rem;
    color: #fff;
    line-height: 150%;
    
    &::before {
        content: "";
        
        position: absolute;
        top: -1.6rem;
        left: 1rem;
        
        width: 0;
        height: 0;
        
        border: .8rem solid transparent;
        border-color: transparent transparent $green transparent;
    }
}

.message--own {
    text-align: right;
    
    .message__inner {
        background: $blue;
        
        &::before {
            left: auto;
            right: 1rem;

            border-bottom-color: $blue;
        }
    }
    
    .message__name {
        padding: 0 1.6rem 0 0;

        &::before {
            left: auto;
            right: 0;
        }
    }
}

.toolbar {
    height: 80px;
    padding: 1rem 2rem;
}

.button {
    display: block;
    width: 100%;
    max-width: 40rem;
    height: 4rem;
    margin: 0 auto;
    
    background: $gray-dark;
    
    border: none;
    border-radius: .3rem;
    outline: none;
    
    font-size: 1.6rem;
    color: #fff;
    
    cursor: pointer;
    
    &[disabled] {
        opacity: .8;
    }
}

.loader {
    animation: loader 1.1s infinite linear;
    transition: opacity .4s ease-in-out;
    
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: 2;
    
    margin: -2.5rem 0 0 -2.5rem;
  
    opacity: 0;
    
    border-top: 1.1em solid rgba($green, 0.2);
    border-right: 1.1em solid rgba($green, 0.2);
    border-bottom: 1.1em solid rgba($green, 0.2);
    border-left: 1.1em solid $green;
 
    font-size: 1rem;
    text-indent: -9999em;
    
    &,
    ::after {
        border-radius: 50%;
        width: 5rem;
        height: 5rem;
    }
    
    &.active {
        opacity: 1;
    }
}

@keyframes loader {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.help {
    margin: 5rem auto 0 auto;
    max-width: 40rem;
    padding: 1rem 2rem;
}

.help__topics {
    padding: 0 0 0 2rem;
    
    font-size: 1.3rem;
    
    list-style: disc;
    line-height: 150%;
}
            
          
!
            
              // Api.ai access_token, I'm using the free version for this demo,
// so there is no need to use or abuse this token.
const apiToken = '3c64a667e77043bebd06ab8556d3e6bf';
const apiUrl = 'https://api.api.ai/v1/';

// Polyfill the SpeechRecognition api
const SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;

// Setup SpeechRecognition variables
let speechRecognition = null;
let speechSynth = null;

// We will save the transcript here when the SpeechRecognition api is listening
let transcript = '';

// Variables where we will store references to DOM elements
let messenger = null;
let messageList = null;
let message = null;
let response = null;
let listenButton = null;
let loader = null;

/**
 * Start listening to user voice input.
 */
const startListening = () => {
    // Create a new SpeechRecognition instance
    speechRecognition = new SpeechRecognition();
    
    // Setup SpeechRecognition
    speechRecognition.continuous = true;
    speechRecognition.interimResults = true;
    
    // Add event handlers
    speechRecognition.onstart = startSpeechRecognition;
    speechRecognition.onresult = processInput;
    speechRecognition.onspeechstart = processAudio;
    
    // Start listening
    speechRecognition.start();
}

/**
 * Voice input has been detected, we'll start with a clean transcript, 
 * and set the ui to listening.
 */
const startSpeechRecognition = () => {
    // Clear the transcript
    transcript = '';
    
    // Set the listen button to a listening state
    listenButton.innerHTML = `I'm listening`;
    listenButton.disabled = true;
}

/**
 * Process the results returned by the SpeechRecognition service.
 */
const processInput = (result) => {
    // Get the message from the result
    const messageText = result.results[0][0].transcript;
    
    // Check if the service is ready interpreting the speech
    const isFinal = result.results[0].isFinal;
    
    if (message) {
        // Show the spoken message
        message.innerHTML = `<p class="message__name">Unknown user</p>
                <div class="message__inner">
                    <p>${messageText.charAt(0).toUpperCase() + messageText.slice(1)}</p>
                </div>`;
        
        // Scroll the chat down so the last message is always in view
        messenger.scrollTop = messenger.scrollHeight;
    }
    
    if (isFinal) {
        // If the SpeechRecognition is done, stop listening.
        speechRecognition.stop();
        
        // Process the input
        processInputText(messageText);
    }
}

/**
 * When the SpeechRecognition api detects speech, we'll setup a new message.
 */
const processAudio = (e) => {
    // Create a new message
    message = document.createElement('li');
    message.classList.add('message', 'message--own');
    
    // Append the message to our list of messages
    messageList.append(message);
}

/**
 * Process the inputted text.
 */
const processInputText = input => {
    // Show a loader
    loader.classList.add('active');
    
    // Create the headers for the request
    var requestHeaders = new Headers();
    requestHeaders.append('Authorization', 'Bearer 3c64a667e77043bebd06ab8556d3e6bf');
    
    // Make a request to api.ai with the inputted text
    return fetch(`${apiUrl}query?v=20150910&query=${encodeURI(input)}&lang=en&sessionId=1234567890&context=weather"`, {
       method: 'GET',
       headers: requestHeaders,
       mode: 'cors',
    }).then(response => {
        return response.json();
    }).then(body => {
        // Show a response
        showResponse(body);  
    });
}

/**
 * Show a response to the user.
 */
const showResponse = response => {
    // Set a default response
    let responseText = `Sorry, can you say that again?`
    
    // If there is a valid response from the api, set it as the response text
    if (responseText && response.result.fulfillment.speech !== '') {
        responseText = response.result.fulfillment.speech;
    }
    
    // Add the response to the list of messages
    response = document.createElement('li');
    response.classList.add('message');
    response.innerHTML = `<p class="message__name">Sambego</p>
                <div class="message__inner">
                    <p>${responseText}</p>
                </div>`;
    
    messageList.append(response);
    
    // Scroll the message in view
    messenger.scrollTop = messenger.scrollHeight;
    
    // Remove the laoder
    loader.classList.remove('active');
    
    // Enable the listen button again
    listenButton.innerHTML = `Start listening`;
    listenButton.disabled = false;
    
    // Let the browser speak the response to the user
    speechSynth.speak(new SpeechSynthesisUtterance(responseText));
}

!function() {
    // Cache DOM elements
    messenger = document.querySelector('.js-messenger');
    messageList = document.querySelector('.js-message-list');
    listenButton = document.querySelector('.js-listen');
    loader = document.querySelector('.js-loader');
    
    // Add eventListener to the listen button
    listenButton.addEventListener('mouseup', startListening);
    
    // Create the speechSynth
    speechSynth = window.speechSynthesis;
}();
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console