Skip to content

Commit

Permalink
Merge pull request #28 from dmitrizzle/v1.2.0
Browse files Browse the repository at this point in the history
V1.2.0
  • Loading branch information
dmitrizzle authored Apr 23, 2017
2 parents 132862e + 5e2b5bb commit 2b7fd1c
Show file tree
Hide file tree
Showing 19 changed files with 798 additions and 366 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore tunneling tool
/ngrok
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
# chat-bubble
### A super-simple, tiny script for creating chat bot interfaces
# 💬 chat-bubble
## A super-simple, tiny script for creating chat bot interfaces

![Screenshot](screenshot.jpg?raw=true)
![Screenshot](screenshot.gif?raw=true)

- Super-easy to use, even if you don't code much! Here's the [tutorial](https://htmlpreview.github.io/?https://github.com/dmitrizzle/chat-bubble/blob/master/component/start-here/hello.html).
- Insanely small footprint, 1.03KB GZipped.
- No dependencies. Written with ES5, vanilla JavaScript.
- Super-easy to install & use! Here's the [tutorial bot](https://htmlpreview.github.io/?https://github.com/dmitrizzle/chat-bubble/blob/master/component/examples/0-tutor.html).
- Insanely small footprint, 1KB GZipped.
- No dependencies. Written with ES5, vanilla JavaScript. Works with modern browsers.

### Usage
```html
<div id="chat"></div>
```

```javascript

// set up the chatbot script
var givemeBubbles = new Bubbles(
document.getElementById('chat'), // attach chatbot to placeholder above ^^
"givemeBubbles" // you need to pass the name of the constructor variable that evokes Bubble function here
);

// pass JSON to your function and you're done!
givemeBubbles.talk({ "ice": { "says": [ "Hi" ] } });
```
Please see examples and the [tutorial bot](https://htmlpreview.github.io/?https://github.com/dmitrizzle/chat-bubble/blob/master/component/examples/0-tutor.html) link to learn more on how to use this thing.

This component comes with styles in CSS files. They are separated in to multiple files. You can turn them into styled components, SASS or whatever for your convenience. For now it's just vanilla CSS so that this tool can work anywhere, regardless of the environment.

Expand Down
66 changes: 55 additions & 11 deletions component/Bubbles.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,53 @@
function Bubbles(container, self, options) {

// options
options = typeof options !== "undefined" ? options : {};
animationTime = options.animationTime || 200; // how long it takes to animate chat bubble, also set in CSS
typeSpeed = options.typeSpeed || 5; // delay per character, to simulate the machine "typing"
widerBy = options.widerBy || 2; // add a little extra width to bubbles to make sure they don't break
sidePadding = options.sidePadding || 6; // padding on both sides of chat bubbles
options = typeof options !== "undefined" ? options : {};
animationTime = options.animationTime || 200; // how long it takes to animate chat bubble, also set in CSS
typeSpeed = options.typeSpeed || 5; // delay per character, to simulate the machine "typing"
widerBy = options.widerBy || 2; // add a little extra width to bubbles to make sure they don't break
sidePadding = options.sidePadding || 6; // padding on both sides of chat bubbles
inputCallbackFn = options.inputCallbackFn || false; // should we display an input field?

var standingAnswer = "ice"; // remember where to restart convo if interrupted



// set up the stage
container.classList.add("bubble-container");
var bubbleWrap = document.createElement("div");
bubbleWrap.className = "bubble-wrap";
container.appendChild(bubbleWrap);

// install user input textfield
this.typeInput = function(callbackFn){
var inputWrap = document.createElement("div");
inputWrap.className = "input-wrap";
var inputText = document.createElement("textarea");
inputText.setAttribute("placeholder", "Type your question...");
inputWrap.appendChild(inputText);
inputText.addEventListener("keypress", function(e){ // register user input
if(e.keyCode == 13){
e.preventDefault();
typeof bubbleQueue !== false ? clearTimeout(bubbleQueue) : false; // allow user to interrupt the bot
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");
// callback
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;



// init typing bubble
var bubbleTyping = document.createElement("div");
Expand All @@ -25,9 +60,10 @@ function Bubbles(container, self, options) {
bubbleWrap.appendChild(bubbleTyping);

// accept JSON & create bubbles
this.talk = function(convo) {
this.talk = function(convo, here) {
this.convo = convo;
this.reply();
this.reply(this.convo[here]);
here ? standingAnswer = here : false;
}
this.reply = function(turn) {
turn = typeof turn !== "undefined" ? turn : this.convo.ice;
Expand All @@ -52,7 +88,7 @@ function Bubbles(container, self, options) {
// navigate "answers"
this.answer = function(key){
var func = function(key){ typeof window[key] === "function" ? window[key]() : false; }
this.convo[key] !== undefined ? this.reply(this.convo[key]) : func(key);
this.convo[key] !== undefined ? (this.reply(this.convo[key]), standingAnswer = key) : func(key);
};

// api for typing bubble
Expand All @@ -77,7 +113,10 @@ function Bubbles(container, self, options) {
start();
}



// create a bubble
var bubbleQueue = false;
var addBubble = function(say, posted, reply){
reply = typeof reply !== "undefined" ? reply : "";
// create bubble element
Expand All @@ -91,7 +130,10 @@ function Bubbles(container, self, options) {
// answer picker styles
if(reply !== ""){
var bubbleButtons = bubbleContent.querySelectorAll(".bubble-button");
bubbleButtons.forEach(function(el){ el.style.width = el.offsetWidth - sidePadding * 2 + widerBy + "px"; });
bubbleButtons.forEach(function(el){
if(!el.parentNode.parentNode.classList.contains("reply-freeform"))
el.style.width = el.offsetWidth - sidePadding * 2 + widerBy + "px";
});
bubble.addEventListener("click", function(){
bubbleButtons.forEach(function(el){
el.style.width = 0 + "px";
Expand All @@ -110,7 +152,7 @@ function Bubbles(container, self, options) {
setTimeout(function() { bubbleTyping.classList.remove("imagine"); }, animationTime );
}
setTimeout(function() { bubbleTyping.classList.add("imagine"); }, wait - animationTime * 2 );
setTimeout(function() {
bubbleQueue = setTimeout(function() {
bubble.classList.remove("imagine");
var bubbleWidthCalc = bubbleContent.offsetWidth + widerBy + "px";
bubble.style.width = reply == "" ? bubbleWidthCalc : "";
Expand All @@ -134,4 +176,6 @@ function Bubbles(container, self, options) {
}, wait + animationTime * 2);
}

}


} // close function
12 changes: 0 additions & 12 deletions component/example-help.html

This file was deleted.

Loading

0 comments on commit 2b7fd1c

Please sign in to comment.