11/4/2016 - 3:40 PM

Sticky Chatbox - willRender

Sticky Chatbox - willRender

  "version": "0.10.6",
  "ENV": {
    "ember-cli-mirage": {
      "enabled": true
  "EmberENV": {
    "FEATURES": {}
  "options": {
    "use_pods": false,
    "enable-testing": false
  "dependencies": {
    "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
    "ember": "2.9.0",
    "ember-data": "2.9.0",
    "ember-template-compiler": "2.9.0",
    "ember-testing": "2.9.0"
  "addons": {
<p>Is scrolled to bottom: {{isScrolledToBottom}}</p>
<p>Messages: {{messages.length}}</p>
  {{#each messages as |message|}}
<h1>Sticky Chatbox:</h1>

{{chat-box messages=messages}}
body {
  margin: 12px 16px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 12pt;
  width: 500px;
  margin: 0 auto;

h1, h2 {
  margin: 0;
  color: #333;

.chat-box {
  margin: 30px auto;
.chat-box ul {
  width: 400px;
  height: 200px;
  overflow: scroll;
  border: 1px solid #ddd;
  list-style-type: none;
  padding: 0;
  margin: 0;

.chat-box li {
  padding: 4px 15px;
import Model from "ember-data/model";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";

export default Model.extend({
  text: attr()
export default `
Michael: Ok, let's give it for Miss... Holly Flaaaax! [everyone claps]
Holly: Thanks Michael. [Michael groans exhaustingly] Today we're going to have a business ethics seminar because recently, without mentioning any names, there has been some misconduct at corporate and we have a very strict ethics policy and that employee has been fired.
Kevin: Oh come on! He's right there. [points at Ryan] He was hired. [to Jim] Oh check it out, "Hired Guy."
Jim: Nice. [they bump fists]
Ryan: Ok, elephant in the room. Let's talk about it. Do I regret what I did? Of course I do. Even though it was an amazing ride, and I'll give you an example. Anyone see Survivor season six? [Dwight raises his hand] Anyone know Joanna on that show? [Dwight nods] In New York City, I hooked up with a girl who looked exactly like that. Indistinguishable. So...
Michael: [clapping] Ok. Well done. Good speech Ryan, you're a good guy.
Holly: Let's start discussing those questionnaires that you filled in this morning. It is wrong to make personal calls during work hours. Now, some of you marked that you very strongly agree. But ideally you would have selected totally agree.
Phyllis: I thought very strongly agree sounded stronger than totally agree.
Holly: Corporate would like to emphasize that ideally you would all totally agree with that statement.
Michael: Well, I think we can all totally agree that Holly is totally fantastic. [claps]
Holly: Thank you. In fact, spending a half hour at the water cooler during work hours is a form of stealing.
Kelly: What?
Holly: Yes, it's called time theft, and it's the same as taking money from the company. Can anyone think of examples of things that are over the line time wasters?
Stanley: This meeting.
Andy: Hey-oh!
Dwight: Yes.
Michael: [to Holly] Can't set 'em up like that.
Kelly: Why is ok for smokers to take breaks all the time? If I want to go outside and hang out once an hour, then I'll just take up smoking. I'll do it. I don't care.
Meredith: I'll smoke with you. I got a bag of cigars in my purse.
Holly: Stealing office supplies is another big ethical area that there seems to be some confusion about.
Michael: Can we have a moment? [whispering] Can I talk to you for a sec? Lot of good stuff. And you look... you look fantastic.
Dight: Michael.
Michael: Yeah.
Dwight: What should we be working on while you guys are talking?
Michael: Do some... do some work. [whispering to Holly] People expect a lot from these meetings. Laughter, sudden twists. Surprise endings. You need to be Robin Williams and M. Night Shyamalan. You need to be Robin Shyamalan.
Holly: Well, I just have to get through the binder.
Michael: Do you... just... you're kind of losing them.
Holly: I am?
Micheal: Yeah, don't think about the stakes. It'll freak you out. 
Holly: Ok. [to everyone] Michael makes a really good point so, uh, let's just open this up a little bit. Say my name is Lauren and here I am shopping in a supermarket and I steal a pencil. That's not right.
Michael: [coughs to hide his words] Lauren, [coughs] enough with the pencils.
Holly: No, I have to go over pencils and office supplies. It's part of the ethics thing.
Oscar: That isn't ethics. Ethics is a real discussion of the competing conceptions of the good. This is just the corporate anti-shoplifting rules.
Andy: I'll drop an ethics bomb on you. Would you steal bread to feed your family? ... Boom!
Oscar: Exactly, Andy.
Andy: Yeah, I took intro to philosophy, twice. No big deal.
Dwight: It's a trick question. The bread is poisoned. Also, it's not your real family. You've been cuckolded by a stronger, smarter male. 
Andy: No that's... not how it works.
Michael: I would not... steal the bread. And I would not let my family go hungry.
Holly: Ok, but we should get back to business. Have any of you ever faced any ethical dilemmas in the workplace.
Michael: Anybody? This is a chance for you to say something without any repercussions. Stanley? Oscar, come on.
Oscar: Pass.
Michael: I will go first. When I discovered YouTube I didn't work for five days. I did nothing. I viewed Cookie Monster sings Chocolate Rain about a thousand times.
Holly: What was the dilemma?
Michael: To tell you or not. And I'm glad I did. I feel very very good. Cathartic. I promise you that you are not going to get into trouble. You can say anything you want with total and complete immunity.
Holly: Oh--- no no no.
Michael: Yeah, [interrupting gibberish]. Come on, anybody. Let it fly.
Oscar: Ok, once in a while I'll take a long lunch.
Michael: A siesta!
Dwight: Time thief. Time thief! Fire him!
Jim: Dwight, you've really never stolen any company time?
Dwight: Never!
Michael: You are a thief of joy. Anybody else. Yeah?
Kelly: Sometimes I download pirated music onto my work computer.
Michael: Who hasn't? Good. Good! What else?
Holly: No--- I, I'd like to hear more about that.
Michael: Mmm...
Angela: I once reported Oscar to the INS. Turns out he's clean, but I'm glad I did it.
Michael: Well, let's keep this party movin' on.
Meredith: I'll go. Have you guys ever met Bruce Meyers, the Scranton rep for Hammermill?
Michael: Bruuuuuuuuuce.
Meredith: Well for the past six years I have been sleeping with him in exchange for discounts on our supplies and Outback Steakhouse gift certificates.
Jim: Jackpot.
Michael: Ach! Wuh---
Holly: Meredith, that is serious. I mean not only that a conflict of interests, there's also an exchange of goods.
Meredith: Exchange of steak. Have you ever had sirloin steak, honey?
Michael: That's crazy. That's crazy talk! Meredith! The Merenator, sleepin' with suppliers! Hoo-ooh! Wow! What time we got? [checks watch] You know what? That's a good place to end it. Right there. This, I think, was a great ethics seminar. She has given us a lot of wonderful things to think about. Right... what is wrong. Who's to say? Really. In the end. I mean because it is... unknowable. But, let's give her a round of applause. Holly, everybody. Holly! Get back to work. [everyone applauds, then leaves] [to Holly] Great job. I am truly impressed. That, uh, you really pulled that one out. Classic. Classic meeting. We should celebrate.
Holly: Michael, there is some serious issues with Meredith.
Michael: Oh...
Holly: I mean all of you have done things I wouldn't have done myself but Meredith's actions are really over the line.
Micheal: Nnyeah. What ya gonna do?`.split('\n').filter(line => line !== '');
import Ember from 'ember';
import dialog from '../dialog';

export default Ember.Controller.extend({
  appName: 'Ember Twiddle',

  init() {
    this.set('messages', this.store.peekAll('message'));

  fetchNextMessage(i=0) {
    this.store.createRecord('message', {
      text: dialog[i]
    Ember.run.later(() => {
      if (i <= dialog.length) {
    }, (Math.random() * 2000) + 1000);
    //}, 1);

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: 'chat-box',
  willUpdate() {
    let box = this.$('ul')[0];
    let isScrolledToBottom = box.scrollTop + box.clientHeight === box.scrollHeight;
    this.set('isScrolledToBottom', isScrolledToBottom);
  didRender() {
    if (this.get('isScrolledToBottom')) {
      this.$('ul')[0].scrollTop = this.$('ul')[0].scrollHeight;