Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

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

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

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.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                
   <audio autoplay="true" src="https://od.lk/s/OTdfODE4NjUwMzlf/Disonance-TheLivingThings-.mp3" controls>
</audio>


<head>
  <meta charset="UTF-8" />
  <title>talk to the false poet </title>

  < <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="shortcut icon" href="https://od.lk/d/OTdfODE4NjUxNzFf/LivingThings-Asset-2.png"/>

  <link href="https://fonts.googleapis.com/css?family=Work+Sans:400,600,700&display=swap" rel="stylesheet" />

 
  
  
  <style>
    body {
      background: #000000;
    }

    .bubble-container {
      height: 100vh;
    }

    .bubble-container .input-wrap textarea {
      margin: 0;
    }
  </style>
</head>

<body>
  <div id="chat">
    <div class="header">
      <img src="https://od.lk/s/OTdfODE4NjUyOTJf/LivingThings-Asset-7.png" width="40px;" />
      <div>
<br/>  <br/>
       <h1>Puppiesnkittens_132</h1>
        <p>Online</p>
      </div>
    </div>
  </div>

  <script src="https://codepen.io/tizcreel/pen/YzGRwBd.js">
  </script>
 
  
  <script>
    var chatWindow = new Bubbles(
      document.getElementById("chat"),
      "chatWindow", {
        inputCallbackFn: function(o) {
          var match = function(key) {
            setTimeout(function() {
              chatWindow.talk(convo, key);
            }, 600);
          };
          var strip = function(text) {
            return text
              .toLowerCase()
              .replace(/[\s.,\/#!$%\^&\*;:{}=\-_'"`~()]/g, "");
          };
          var found = false;
          o.convo[o.standingAnswer].reply.forEach(function(e, i) {
            strip(e.human_response).includes(strip(o.input)) &&
              o.input.length > 0 ?
              (found = e.bot_answer) :
              found ?
              null :
              (found = false);
          });
          found ? match(found) : miss();
        }
      }
    );

    
    
    
    
    var convo = {
    

      
      
      
      
      
      
    intro: {
      bot_says: [
        "the usual suspects all lined up",
        "the name of the killer",
        "is about to come up"  
      ],


      human_reply: [{
          human_response: [
            "it can’t be"
          ],
          bot_answer:"shame"
        },
        {
          human_response: [
            "it is faulty"
          ],
          bot_answer: "done"
        }
      ]
    },


   shame: {
        bot_says: [
        "shame",
        "shame",
        "shame, straight to the hole where you belong"  
        ],
  
  
        human_reply: [{
            human_response: [
            "im lying"
            ],
            bot_answer: "art"
          },
          {
            human_response: [
            "Whoever they are, I do what I’m told"
            ],
            bot_answer: "sheep"
          }
        ]
      },

      

      done: {
        bot_says: [
        "what have you done ?"  
        ],
  
  
        human_reply: [{
            human_response: [
              "the solution is or is meant to be impossible"
            ],
            bot_answer: "sheep"
          },
          {
            human_response: [
              "a confession interrupted by a thought"
            ],
            bot_answer: "many"
          }
        ]
      },



      art: {
        bot_says: [
        "you are not an artist"  
        ],
  
  
        human_reply: [{
            human_response: [
              "I believe"
            ],
            bot_answer: "god"
          },
          {
            human_response: [
              "make believe"
            ],
            bot_answer: "sheep"
          }
        ]
      },




      sheep: {
        bot_says: [
        "<img  SRC=https://media.giphy.com/media/wOe1XNgWCNoqY/giphy.gif>"  
        ],
  
  
        human_reply: [{
            human_response: [
              "the light almost blinded me"
            ],
            bot_answer: "mistake"
          },
          {
            human_response: [
              "how did this all went wrong"
            ],
            bot_answer: "nail"
          }
        ]
      },


     
      many: {
        bot_says: [
              "too many opinions", 
              "too many calculations"   
     ],
  
  
        human_reply: [{
            human_response: [
              "we have not managed to figure out, how we will survive"
            ],

            bot_answer: "nail"
          },
          {
            human_response: [
              "but there’s something out there, that’s waiting to be found"
            ],
            bot_answer: "quest"
          }
        ]
      }, 




      god: {
        bot_says: [
              "hold your truths!"   
     ],
  
        human_reply: [{
            human_response: [
              "mistake of god" 
            ],

            bot_answer: "pers"
          },
          {
            human_response: [
              "god makes no mistakes"
            ],
            bot_answer: "mistake"
          }
        ]
      }, 





      nail: {
        bot_says: [
              "If you have a hammer then everything is a nail"   
     ],
  
        human_reply: [{
            human_response: [
              "I am in control" 
            ],

            bot_answer: "control"
          },
          {
            human_response: [
              "never in control"
            ],
            bot_answer: "nocontrol"
          }
        ]
      }, 








      quest: {
        bot_says: [
              "too too too many questions",
              "very few answers"   
     ],
  
        human_reply: [{
            human_response: [
              "if it was up to me, you’ll never know" 
            ],

            bot_answer: "nocontrol"
          },
          {
            human_response: [
              "massive expectation"
            ],
            bot_answer: "wait"
          }
        ]
      }, 



      pers: {
        bot_says: [
          "watch out",
          "looking with other eyes",
          "might change your perspective"   
     ],
  
        human_reply: [{
            human_response: [
              "no matter what we do, this is a dead-end" 
            ],
            bot_answer: "open"
          },
          {
            human_response: [
              "with and beyond what is presented"
            ],
            bot_answer: "coex"
          }
        ]
      }, 




      mistake: {
        bot_says: [
          "accept the bliss is to be normal my dear",
          "to be an average peer",
          "orderly an ordinary",
          "standard mercenary"   
     ],
  
        human_reply: [{
            human_response: [
              "we don’t even look at each other, we don’t even bother" 
            ],
            bot_answer: "coex"
          },
          {
            human_response: [
              "in the name of reason"
            ],
            bot_answer: "control"
          }
        ]
      }, 



      control: {
        bot_says: [
         "is the problem", "solved?"
     ],
  
        human_reply: [{
            human_response: [
              "we might not even know what the problem is" 
            ],
            bot_answer: "luck"
          },
          {
            human_response: [
             "It takes time to change, little by little, slow approach"
            ],
            bot_answer: "problem"
          }
        ]
      }, 



      nocontrol: {
        bot_says: [
         "I rather",
        "stop making sense"
     ],
  
        human_reply: [{
            human_response: [
              "you are asking the wrong question" 
            ],
            bot_answer: "luck"
          },
          {
            human_response: [
                          " how convenient"
            ],
            bot_answer: "seat"
          }
        ]
      }, 



      wait: {
        bot_says: [
        "What are you waiting for?"
     ],
  
        human_reply: [{
            human_response: [
              "im not waiting" 
            ],
            bot_answer: "control"
          },
          {
            human_response: [
                          "cold feet"
            ],
            bot_answer: "problem"
          }
        ]
      }, 


      seat: {
        bot_says: [
              "while resting in our comfortable seat", 
              "indulging in self-defeat",
               "we manage to feel complete"
     ],
  
        human_reply: [{
            human_response: [
               "try not to judge me"
            ],
            bot_answer: "luck"
          }
        ]
      }, 



      luck: {
        bot_says: [
        "Sometimes the solution can be found just by luck"
     ],
  
        human_reply: [{
            human_response: [
              "The crisis is here; the crisis is ahead" 
            ],
            bot_answer: "next"
          },
          {
            human_response: [
                          "false alarm"
            ],
            bot_answer: "last3"
          }
        ]
      }, 


      coex: {
        bot_says: [
        "while we pretend to coexist", 
        "one next to the other"
     ],
  
        human_reply: [{
            human_response: [
              "hold your face " 
            ],
            bot_answer: "open"
          },
          {
            human_response: [
                          "let it rest"
            ],
            bot_answer: "control"
          }
        ]
      }, 





      open: {
        bot_says: [ 
        "Im falling down"
     ],
  
        human_reply: [{
            human_response: [
              "HOLD ME TIGHT" 
            ],
            bot_answer: "next"
          },
          {
            human_response: [
                          "balance, balance"
            ],
            bot_answer: "problem"
          }
        ]
      }, 





      problem: {
        bot_says: [ 
        "I can’t breath", 
        "I can’t stand"
     ],
  
        human_reply: [{
            human_response: [
              "where is the floor?" 
            ],
            bot_answer: "next"
          },
          {
            human_response: [
            "where is the ground?"
            ],
            bot_answer: "next"
          }
        ]
      }, 



      next: {
        bot_says: [ 
        "ground control",
        "no controls",
        "blurred lines",
        "Im so lost"
     ],
  
        human_reply: [{
            human_response: [
              "who is that?" 
            ],
            bot_answer: "last2"
          },
          {
            human_response: [
            "who are you?"
            ],
            bot_answer: "last2"
          },
          {
            human_response: [
           "where am I"
            ],
            bot_answer: "last3"
          }
      
        ]
      }, 
      
      
      
      last1: {
        bot_says: [ 
        "where am I?"
     ],

        human_reply: [{
            human_response: [
              "me?" 
            ],
            bot_answer: "intro"
          }
        ]
      }, 



      last2: {
        bot_says: [ 
        "oh, that is me"
     ],

        human_reply: [{
            human_response: [
              "me?" 
            ],
            bot_answer: "intro"
          }
        ]
      }, 


      last3: {
        bot_says: [ 
        "you will be alright"
     ],

        human_reply: [{
            human_response: [
              "me?" 
            ],
            bot_answer: "intro"
          }
        ]
      }, 



  };
  chatWindow.talk(convo);
    
    
    
    
  </script>
</body>

</html>
              
            
!

CSS

              
                
audio::-webkit-media-controls-panel {
  background-color: #4A4F61;
  
}

audio {
invert(12%);
    width: 230px;
    height: 25px;
}



@font-face {
	font-family: 'cooperhewitt';
	src: url('../fonts/CooperHewitt-Semibold.eot');
	src: url('../fonts/CooperHewitt-Semibold.woff') format('woff'),
	url('../fonts/CooperHewitt-Semibold.otf') format('opentype'),
	url('../fonts/CooperHewitt-Semibold.svg#cooperhewitt') format('svg');
    font-weight: 600;
    font-style: normal;

}
@font-face {
    font-family: 'cooperhewitt';
	src: url('../fonts/CooperHewitt-Medium.eot');
	src: url('../fonts/CooperHewitt-Medium.woff') format('woff'), 
	url('../fonts/CooperHewitt-Medium.otf') format('opentype'),
	url('../fonts/CooperHewitt-Medium.svg#cooperhewitt') format('svg');
    font-weight: 500;
    font-style: normal;

}

.bubble-container .input-wrap {
	position: absolute;
	bottom: -5px;
	left: 0;
	right: 0;
	font-family: "cooperhewitt", sans-serif;
	color: #2c2c2c;
}
.bubble-container .input-wrap textarea {
	width: calc(100% - 20px);
	font-family: "cooperhewitt", Helvetica, sans-serif;
	color: #2c2c2c;
	background: #F0F0F095;
	font-size: 1em;
	letter-spacing: .5px;
	font-weight: 400;
	margin: 10px;
	border-radius: 0;
	border: none;
	padding: 10px 15px;
	outline: none;
	line-height: 1.25em;
	visibility: hidden !important;
}
.bubble.reply-freeform {
	margin: 0;
}
.bubble.reply.reply-freeform.say .bubble-content .bubble-button {
	margin-top: 1px;
	text-align: left;
}
.bubble.reply.say.bubble-hidden {
	margin: 0;
	transform: scale(0);
	height: 0;
}


.bubble.reply {
  background: transparent;
  box-shadow: none;
  float: right;
  position: relative;
  transform-origin: right top;
  margin: 8px 0 10px;
  padding: 0;
  max-width: 90%;
  height: 70px;
}
.bubble.reply.history {
  margin: 0 0 2px 0; 
}
.bubble.reply .bubble-content {
  transition: all 200ms;
}
.bubble.reply .bubble-content .bubble-button {
  background: #070912;
  color: #fff;
  padding: 8px 16px;
  border-radius: 15px 15px 5px 5px;
  margin-left: 2px;
  text-align: center;
  display: inline-block;
  float: right;
  cursor: pointer;
  transition: all 200ms;
  text-decoration: none;
  word-break: normal;
	box-sizing: content-box;
  /* animation-duration: 1s; */
  animation-name: animate-reply;
  animation-play-state: paused;
  animation-fill-mode: forwards;
  /* opacity: 0; */
  transform: translate3d(0px, 0px, 0px);
  animation-delay: -3s;
  -ms-animation-delay: -3;
  -webkit-animation-delay: -3s;
}
@keyframes animate-reply {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.bubble.reply.say .bubble-content .bubble-button {
  animation-play-state: running;
  margin-top: 3px;
  min-height: 24px;
  overflow: hidden;
}

.bubble.reply .bubble-content .bubble-button:first-child {
  border-radius: 15px 15px 15px 5px;
  margin-left: 2px;
}
.bubble.reply .bubble-content .bubble-button:last-child,
.bubble.reply .bubble-content .bubble-button.bubble-pick {
  border-radius: 15px 15px 5px 15px;
}
.bubble.reply.bubble-picked .bubble-content .bubble-button {
  transform: scale(0) translate3d(0px, 0px, 0px);
  padding: 0;
}
.bubble.reply:not(.bubble-picked) .bubble-content .bubble-button:hover,
.bubble.reply .bubble-content .bubble-button.bubble-pick {
  background: #212121;
  border: none;
  color: white;
  transform: scale(1) translate3d(0px, 0px, 0px);
  padding: 8px 16px;
  height: auto;
}

/* interaction recall styles */
.bubble.history .bubble-content .bubble-button,
.bubble.history.reply:not(.bubble-picked) .bubble-content .bubble-button:hover,
.bubble.history.reply .bubble-content .bubble-button.bubble-pick {
  background: rgba(44, 44, 44, 0.67);
  cursor: default;
}

/* input fields for bubbles */
.bubble .bubble-content input {
  background: linear-gradient(193deg, #1faced, #5592dc 100%) !important;
  box-shadow: 0 0px 1px 0px #000, 0 -1px 0 0px rgba(255, 255, 255, 0.38) inset;
  text-shadow: 0 1px rgba(0, 0, 0, 0.35);
  border: 0;
  outline: 0;
}
.bubble .bubble-content input::-webkit-input-placeholder {
  /* Chrome/Opera/Safari */
  color: rgba(255, 255, 255, .5);
  text-shadow: none;
}
.bubble .bubble-content input::-moz-placeholder {
  /* Firefox 19+ */
  color: rgba(255, 255, 255, .5);
  text-shadow: none;
}
.bubble .bubble-content input:read-only {
  background: linear-gradient(166deg, #48121d, #0d4058 100%) !important;
}

/* style bubbles */
.bubble,
.bubble-typing {
  color: white;
  background: #262629;
  padding: 8px 16px;
  border-radius: 15px 15px 15px 5px;
  font-weight: 500;
  text-transform: none;
  text-align: left;
  font-size: 16px;
  letter-spacing: .5px;
  margin: 0 0 4px 0;
  max-width: 65%;
  float: none;
  clear: both;
  line-height: 1.5em;
  word-break: break-word;
  transform-origin: left top;
  transition: all 200ms;
  box-sizing: content-box;
}
.bubble .bubble-content {
  transition: opacity 150ms;
}
.bubble:not(.say) .bubble-content {
  opacity: 0;
}
.bubble-typing.imagine,
.bubble.imagine {
  transform: scale(0);
  transition: all 450ms, height 450ms 1s, padding 450ms 1s;
}
.bubble.imagine {
  margin: 0;
  height: 0;
  padding: 0;
}

/* style media that's inside bubbles */

.bubble .bubble-content img {
  width: calc(80% + 32px);
  margin: -8px -8px;
  overflow: hidden;
  display: inline-block;
  border-radius: 15px 15px 15px 5px;
  background: #262629
}

/* interaction recall styles */
.bubble.history,
.bubble.history .bubble-content,
.bubble.history .bubble-content .bubble-button,
.bubble.history .bubble-content .bubble-button:hover {
  transition: all 0ms !important;
}
.bubble.history {
  opacity: .25;
}


/* setup container styles */

.bubble-container {
	background: #000000;
	height: 520px;
	max-width: 750px;
	width: 100%;
	margin: 0 auto;
	overflow: hidden;
	position: relative;
}
.bubble-wrap {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: -17px;
	padding: 10px calc(17px + 10px) 30px 10px;
	padding-top: 20%;
	overflow-y: scroll;
	-webkit-overflow-scrolling: touch;
	-webkit-transform: translate3d(0, 0, 0);
}
/* optional page styles */
h1 {
	text-align: center;
	font-weight: 300;
	font-size: 4.3em;
	margin: .5em auto 0.15em;
}
body {
    font-family: 'Work Sans', sans-serif;
	margin: 0;
	-webkit-font-smoothing: antialiased;

}
.header {
	position: relative;
	top: 0;
	z-index: 100;
	background: #000000;
	padding: 2%;
	box-shadow: 0 0 4px 0 rgba(0,0,0,0.1);
}

.header img {
	border-radius: 100px;
	margin-top: 3px;
	display: inline-block;
}

.about {
	float: right;
	margin-top: 12px;
	margin-right: 20px;
	color: white;
	background-color: white;
	font-size: 20px;
 	font-family: 'Work Sans', sans-serif;
	font-style: italic;
	font-weight: 400;
	height: 30px;
	width: 30px;
	line-height: 35px;
	text-align: center;
	display: block;
	border-radius: 50%;
	cursor: help;
}
	
.header div {
	display: inline-block;
	margin-left: .4rem;
}

.header div h1 {
	font-size: 1.2rem;
	text-align: left;
	margin: 0px; 
  color: white;
	font-weight: 600;
}

.header div p {
	font-size: 1rem; 
	text-align: left;
	margin: 0px;
	color: white;
	font-weight: 500;
}


/* style "loading" or "typing" stae */

.bubble-typing {
	width: 38px;
	padding: 12px 16px;
	height: 8px;
}
.dot {
	background-color: rgb(255,255,255);
	float: left;
	height: 7px;
	margin-left: 4px;
	width: 7px;
	animation-name: bounce_dot;
	animation-duration: 2.24s;
	animation-iteration-count: infinite;
	animation-direction: normal;
	border-radius: 5px;
}
.dot_1 { animation-delay: 0.45s; }
.dot_2 { animation-delay: 1.05s; }
.dot_3 { animation-delay: 1.35s; }
@keyframes bounce_dot {
	0% {}
	50% { background-color:rgb(0,0,0); }
	100% {}
}

              
            
!

JS

              
                function Bubbles (container, self, options) {

  options = typeof options !== "undefined" ? options : {};
  animationTime = options.animationTime || 250;
  typeSpeed = options.typeSpeed || 5;
  widerBy = options.widerBy || 2 ;
  sidePadding = options.sidePadding || 6;
  recallInteractions = options.recallInteractions || 0; 
  inputCallbackFn = options.inputCallbackFn || false; 

  var standingAnswer = "intro" ;
  var _convo = {} ;

 
  var localStorageCheck = function() {
    var test = "chat-bubble-storage-test";
    try {
      localStorage.setItem(test, test);
      localStorage.removeItem(test);
      return true;
    } catch (error) {
      console.error(
        "Your server does not allow storing data locally. Most likely it's because you've opened this page from your hard-drive. For testing you can disable your browser's security or start a localhost environment."
      );
      return false;
    }
  }
  var localStorageAvailable = localStorageCheck() && recallInteractions > 0
  var interactionsLS = "chat-bubble-interactions"
  var interactionsHistory =
    (localStorageAvailable &&
      JSON.parse(localStorage.getItem(interactionsLS))) ||
    []

  
  interactionsSave = function(say, human_reply) {
    if (!localStorageAvailable) return
    
    if (interactionsHistory.length > recallInteractions)
      interactionsHistory.shift() 

   
    if (
      
      say.includes("bubble-button") &&
      
      human_reply !== "reply reply-freeform" &&
      
      human_reply !== "reply reply-pick"
    )
     
      return

    
    interactionsHistory.push({ say: say, human_reply: human_reply })
  }

  
  interactionsSaveCommit = function() {
    if (!localStorageAvailable) return
    localStorage.setItem(interactionsLS, JSON.stringify(interactionsHistory))
  }

  
  container.classList.add("bubble-container")
  var bubbleWrap = document.createElement("div")
  bubbleWrap.className = "bubble-wrap"
  container.appendChild(bubbleWrap)

  
  this.typeInput = function(callbackFn) {
    var inputWrap = document.createElement("div")
    inputWrap.className = "input-wrap"
    var inputText = document.createElement("textarea")
    inputText.setAttribute("placeholder", "Ask me anything...")
    inputWrap.appendChild(inputText)
    inputText.addEventListener("keypress", function(e) {
     
      if (e.keyCode == 13) {
        e.preventDefault()
        typeof bubbleQueue !== false ? clearTimeout(bubbleQueue) : false 
        var lastBubble = document.querySelectorAll(".bubble.say")
        lastBubble = lastBubble[lastBubble.length - 1]
        lastBubble.classList.contains("reply") &&
        !lastBubble.classList.contains("reply-freeform")
          ? lastBubble.classList.add("bubble-hidden")
          : false
        addBubble(
          '<span class="bubble-button bubble-pick">' + this.value + "</span>",
          function() {},
          "reply reply-freeform"
        )
        
        typeof callbackFn === "function"
          ? callbackFn({
              input: this.value,
              convo: _convo,
              standingAnswer: standingAnswer
            })
          : false
        this.value = ""
      }
    })
    container.appendChild(inputWrap)
    bubbleWrap.style.paddingBottom = "100px"
    inputText.focus()
  }
  inputCallbackFn ? this.typeInput(inputCallbackFn) : false

  
  var bubbleTyping = document.createElement("div")
  bubbleTyping.className = "bubble-typing imagine"
  for (dots = 0; dots < 3; dots++) {
    var dot = document.createElement("div")
    dot.className = "dot_" + dots + " dot"
    bubbleTyping.appendChild(dot)
  }
  bubbleWrap.appendChild(bubbleTyping)

  
  this.talk = function(convo, here) {
    
    _convo = Object.assign(_convo, convo) 

    this.human_reply(_convo[here])
    here ? (standingAnswer = here) : false
  }

  var iceBreaker = false
  this.human_reply = function(turn) {
    iceBreaker = typeof turn === "undefined"
    turn = !iceBreaker ? turn : _convo.intro
    questionsHTML = ""
    if (!turn) return
    if (turn.human_reply !== undefined) {
      turn.human_reply.reverse()
      for (var i = 0; i < turn.human_reply.length; i++) {
        ;(function(el, count) {
          questionsHTML +=
            '<span class="bubble-button" style="animation-delay: ' +
            animationTime / 2 * count +
            'ms" onClick="' +
            self +
            ".bot_answer('" +
            el.bot_answer +
            "', '" +
            el.human_response +
            "');this.classList.add('bubble-pick')\">" +
            el.human_response +
            "</span>"
        })(turn.human_reply[i], i)
      }
    }
    orderBubbles(turn.bot_says, function() {
      bubbleTyping.classList.remove("imagine")
      questionsHTML !== ""
        ? addBubble(questionsHTML, function() {}, "reply")
        : bubbleTyping.classList.add("imagine")
    })
  }
  
  this.bot_answer = function(key, content) {
    var func = function(key) {
      typeof window[key] === "function" ? window[key]() : false
    }
    _convo[key] !== undefined
      ? (this.human_reply(_convo[key]), (standingAnswer = key))
      : func(key)

  
    if (_convo[key] !== undefined && content !== undefined) {
      interactionsSave(
        '<span class="bubble-button reply-pick">' + content + "</span>",
        "reply reply-pick"
      )
    }
  }

  
  this.think = function() {
    bubbleTyping.classList.remove("imagine")
    this.stop = function() {
      bubbleTyping.classList.add("imagine")
    }
  }

  
  var orderBubbles = function(q, callback) {
    var start = function() {
      setTimeout(function() {
        callback()
      }, animationTime)
    }
    var position = 0
    for (
      var nextCallback = position + q.length - 1;
      nextCallback >= position;
      nextCallback--
    ) {
      ;(function(callback, index) {
        start = function() {
          addBubble(q[index], callback)
        }
      })(start, nextCallback)
    }
    start()
  }

 
  var bubbleQueue = false
  var addBubble = function(say, posted, human_reply, live) {
    human_reply = typeof human_reply !== "undefined" ? human_reply : ""
    live = typeof live !== "undefined" ? live : true 
    var animationTime = live ? this.animationTime : 0
    var typeSpeed = live ? this.typeSpeed : 0
   
    var bubble = document.createElement("div")
    var bubbleContent = document.createElement("span")
    bubble.className = "bubble imagine " + (!live ? " history " : "") + human_reply
    bubbleContent.className = "bubble-content"
    bubbleContent.innerHTML = say
    bubble.appendChild(bubbleContent)
    bubbleWrap.insertBefore(bubble, bubbleTyping)
    
    if (human_reply !== "") {
      var bubbleButtons = bubbleContent.querySelectorAll(".bubble-button")
      for (var z = 0; z < bubbleButtons.length; z++) {
        ;(function(el) {
          if (!el.parentNode.parentNode.classList.contains("reply-freeform"))
            el.style.width = el.offsetWidth - sidePadding * 2 + widerBy + "px"
        })(bubbleButtons[z])
      }
      bubble.addEventListener("click", function() {
        for (var i = 0; i < bubbleButtons.length; i++) {
          ;(function(el) {
            el.style.width = 0 + "px"
            el.classList.contains("bubble-pick") ? (el.style.width = "") : false
            el.removeAttribute("onclick")
          })(bubbleButtons[i])
        }
        this.classList.add("bubble-picked")
      })
    }
    
    wait = live ? animationTime * 2 : 0
    minTypingWait = live ? animationTime * 6 : 0
    if (say.length * typeSpeed > animationTime && human_reply == "") {
      wait += typeSpeed * say.length
      wait < minTypingWait ? (wait = minTypingWait) : false
      setTimeout(function() {
        bubbleTyping.classList.remove("imagine")
      }, animationTime)
    }
    live && setTimeout(function() {
      bubbleTyping.classList.add("imagine")
    }, wait - animationTime * 2)
    bubbleQueue = setTimeout(function() {
      bubble.classList.remove("imagine")
      var bubbleWidthCalc = bubbleContent.offsetWidth + widerBy + "px"
      bubble.style.width = human_reply == "" ? bubbleWidthCalc : ""
      bubble.style.width = say.includes("<img src=")
        ? "50%"
        : bubble.style.width
      bubble.classList.add("say")
      posted()

      
      interactionsSave(say, human_reply)
      !iceBreaker && interactionsSaveCommit() 

     
      containerHeight = container.offsetHeight
      scrollDifference = bubbleWrap.scrollHeight - bubbleWrap.scrollTop
      scrollHop = scrollDifference / 200
      var scrollBubbles = function() {
        for (var i = 1; i <= scrollDifference / scrollHop; i++) {
          ;(function() {
            setTimeout(function() {
              bubbleWrap.scrollHeight - bubbleWrap.scrollTop > containerHeight
                ? (bubbleWrap.scrollTop = bubbleWrap.scrollTop + scrollHop)
                : false
            }, i * 5)
          })()
        }
      }
      setTimeout(scrollBubbles, animationTime / 2)
    }, wait + animationTime * 2)
  }

  
  for (var i = 0; i < interactionsHistory.length; i++) {
    addBubble(
      interactionsHistory[i].say,
      function() {},
      interactionsHistory[i].human_reply,
      false
    )
  }
}


function prepHTML(options) {
  
  var options = typeof options !== "undefined" ? options : {}
  var container = options.container || "chat" // id of the container HTML element
  var relative_path = options.relative_path || "./node_modules/chat-bubble/"

  
  window[container] = document.createElement("div")
  window[container].setAttribute("id", container)
  document.body.appendChild(window[container])

  
  var appendCSS = function(file) {
    var link = document.createElement("link")
    link.href = file
    link.type = "text/css"
    link.rel = "stylesheet"
    link.media = "screen,print"
    document.getElementsByTagName("head")[0].appendChild(link)
  }
  appendCSS(relative_path + "component/styles/input.css")
  appendCSS(relative_path + "component/styles/reply.css")
  appendCSS(relative_path + "component/styles/says.css")
  appendCSS(relative_path + "component/styles/setup.css")
  appendCSS(relative_path + "component/styles/typing.css")
}


if (typeof exports !== "undefined") {
  exports.Bubbles = Bubbles
  exports.prepHTML = prepHTML
}

              
            
!
999px

Console