Skip to content

Commit

Permalink
Merge pull request #25 from dmitrizzle/install-textfield
Browse files Browse the repository at this point in the history
Textfield UI (no NLC)
  • Loading branch information
dmitrizzle authored Apr 23, 2017
2 parents 132862e + 3ff5ad5 commit 8ae3c87
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 9 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
57 changes: 50 additions & 7 deletions component/Bubbles.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,52 @@
function Bubbles(container, self, options) {

// options
options = typeof options !== "undefined" ? 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
inputCallbackFn = options.inputCallbackFn || (function(o){ return 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";
}
inputCallbackFn ? this.typeInput(inputCallbackFn) : false;



// init typing bubble
var bubbleTyping = document.createElement("div");
Expand All @@ -25,9 +59,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 +87,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 +112,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 +129,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 +151,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 +175,6 @@ function Bubbles(container, self, options) {
}, wait + animationTime * 2);
}

}


} // close function
39 changes: 38 additions & 1 deletion component/start-here/hello.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<link rel="stylesheet" media="all" href="../styles/says.css">
<link rel="stylesheet" media="all" href="../styles/reply.css">
<link rel="stylesheet" media="all" href="../styles/typing.css">
<link rel="stylesheet" media="all" href="../styles/input.css">
<style>
h1 { text-align: center; }
</style>
Expand Down Expand Up @@ -322,7 +323,43 @@

<!-- initialize bubbles -->
<script>
var givemeBubbles = new Bubbles(document.getElementById("chat"), "givemeBubbles");
var givemeBubbles = new Bubbles(document.getElementById("chat"), "givemeBubbles", {
inputCallbackFn: function(o){

// do this if no answer matched
var miss = function(){
givemeBubbles.talk({
"ice": {
"says":
[
"Sorry, I don't get it 😕. Pls repeat? Or you can just click below 👇",
],
"reply" : o.convo[o.standingAnswer].reply
},
})
}

// do this if answer found
var match = function(key){
givemeBubbles.talk(convo, key); // restart current convo from point found in the answer
}

// sanitize text for search function
var strip = function(text){
return text.toLowerCase().replace(/\ [.,\/#!$%\^&\*;:{}=\-_`~()]/g,"");
}

// search function
var found = false;
o.convo[o.standingAnswer].reply.forEach(function(e, i) {
(strip(e.question).includes(strip(o.input)) && o.input.length > 0) ? found = e.answer : found ? null : found = false;
});
found ? match(found) : miss();



}
});
givemeBubbles.talk(convo);
functionOne = function(){ alert("Function One"); }
functionTwo = function(){ alert("Function Two"); }
Expand Down
38 changes: 38 additions & 0 deletions component/styles/input.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* style user input field */
.bubble-container .input-wrap {
position: absolute;
bottom: 0;
left: 0;
right: 0;
font-family: "Helvetica Neue", Helvetica, sans-serif;
color: #2c2c2c;
background: rgba(255, 255, 255, 0.95);
}
.bubble-container .input-wrap textarea {
width: calc(100% - 20px);
font-family: "Helvetica Neue", Helvetica, sans-serif;
color: #2c2c2c;
background: #fafafa;
font-size: 1em;
letter-spacing: .5px;
font-weight: 400;
margin: 10px;
border-radius: 15px;
border: none;
padding: 10px 15px;
outline: none;
box-shadow: 0 0 0 1px #d0d0d0 inset;
line-height: 1.25em;
}
.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;
}
2 changes: 1 addition & 1 deletion component/styles/reply.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* style usr response reply */
/* style user response reply */
.bubble.reply {
background: transparent;
box-shadow: none;
Expand Down
Binary file added ngrok
Binary file not shown.

0 comments on commit 8ae3c87

Please sign in to comment.