HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
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.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
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.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
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.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<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>
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% {}
}
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
}
Also see: Tab Triggers