cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

Quick-add: + add another resource

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.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

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.

            
              <script type="text/x-handlebars" data-template-name="application">
  {{render 'navigation'}}
  <div class="container">
    <h1>This web app is made with Ember.js</h1>
    <h4>Includes bootstrap fontAwesome,  ember.js + ember-data</h4>
    <row>
    
    <p>Welcome to this demo</p>
    
    {{outlet}}
  </div>
  {{outlet 'modal'}}
</script>

<script type="text/x-handlebars" data-template-name="about">
  <div class="container">
    <h1>About This Template</h1>
    <p>made with ember.js bootstrap and handlebars</p>
  </div>
</script>

<script type="text/x-handlebars" data-template-name="navigation">
  <nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      {{#linkTo 'index' class="navbar-brand"}}Home{{/linkTo}}
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
        <li>{{#linkTo 'inview'}}In View{{/linkTo}}</li>
        <li>{{#linkTo 'calendar'}}Calendar{{/linkTo}}</li>
        <li>{{#linkTo 'infinite'}}Infinite Scroll{{/linkTo}}</li>
        <li>{{#linkTo 'scroll'}}Scroll{{/linkTo}}</li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Modals <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li>
              <a href="#" class="navbar-link" {{action 'showModal' 'settings-modal' model}}>Settings</a>
            </li>
            <!--<li class="divider"></li>-->
            <li>
              <a href="#" class="navbar-link" {{action 'showModal' 'logout-modal'}}>Logout</a>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </nav>
</script>

<script type="text/x-handlebars" data-template-name="settings-modal">
  {{#my-modal title='Settings' ok='save' close='removeModal'}}
    <form {{action 'ok' on='submit' target=view}}>
      <div class="form-group">
        <label>Please Leave Your Name</label>
        {{input class="form-control" value=name}}
      </div>
    </form>
  {{/my-modal}}
</script>

<script type="text/x-handlebars" data-template-name="logout-modal">
  {{#my-modal title='Logout' ok='logout' close='removeModal'}}
    Are you sure you want to logout?
  {{/my-modal}}
</script>

<script type="text/x-handlebars" data-template-name="components/my-modal">
  <div class="modal fade">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
          <h4 class="modal-title">{{title}}</h4>
        </div>
        <div class="modal-body">
          {{yield}}
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary" {{action 'ok'}}>OK</button>
        </div>
      </div>
    </div>
  </div>
</script>
  
<script type="text/x-handlebars" data-template-name="inview">
  <div class="container">
    <div class="row">
      {{#each item in model}}
        <div class="col-sm-12">
        
          {{this-is-dog item=item}}
          
        </div>
      {{/each}}
    </div>
  </div>
</script>
  
<script type="text/x-handlebars" data-template-name="components/this-is-dog">
  <header>Header<h2>{{item}} ~ {{enteredViewport}}</h2></header><article><em>blah blah<em>
  <blockquote class="dog-card-description">Lorem ipsum dolor sit amet,  consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
      </blockquote><em>by blah blah<em>
  <div>consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet</div>
  </article>
  {{#if enteredViewport}}
    <article>
      <blockquote class="dog-card-description">Lorem ipsum dolor sit amet,  consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
      </blockquote>
    </article>
  {{/if}}
</script>

  <script type="text/x-handlebars" data-template-name="calendar">

    {{ui-calendar
      selectedDates=emberConfDates
      showNextMonth=false
      showPrevMonth=false
      select="dateSelected"}}

    <ol>
      {{#each day in emberConfDates}}
        <li>{{format-date date=day format="dddd, MMMM Do, YYYY"}}</li>
      {{/each}}
    </ol>
  </script>
  
  <script data-template-name="infinite" type="text/x-handlebars">
<h2>Pretty Boxes (Page {{page}}: {{content.length}} total widgets)</h2>
<ul class=infinite>
  {{#each widget in controller}}
    <li>Pretty Box {{widget.name}}</li>
  {{/each}}
</ul>
{{#if loadingMore}}
  Loading more...
{{else}}
  <a href='#' {{action 'getMore'}}>We can add More...</a>
{{/if}}
</script>
  
    <script type="text/x-handlebars" data-template-name="scroll">
    {{cloaked-collection itemViewClass="item" content=model}}
  </script>
    <script type="text/x-handlebars" data-template-name="item">
      <div {{action "greeting"}}>
      <blockquote>
      <article>
      <blockquote class="dog-card-description"> I am an Ember Route! You gotta LOVE me! 
      <button>Click</button> 
    </article>
        #{{id}} ({{height}}0px)
      </div>
</script>
       
      <div {{action "greeting"}}>
    
      <blockquote class="dog-card-description">
      </blockquote>
   
      </div>
  </script>
            
          
!
            
              @import "compass/css3";
@import "compass";

body { padding-top: 70px; }
.modal-dialog { margin: 90px auto; }


$aqua:  #7FDBFF;
$blue:  #0074D9;
$navy:  #001F3F;
$teal:  #39CCCC;
$green: #2ECC40;
$olive: #3D9970;
$lime:  #01FF70;

// Warm

$yellow:  #FFDC00;
$orange:  #FF851B;
$red:     #FF4136;
$fuchsia: #F012BE;
$purple:  #B10DC9;
$maroon:  #85144B;

// Gray Scale

$white:  #fff;
$silver: #ddd;
$gray:   #aaa;
$black:  #111;

h1.title {
  font-size: 2.5em;
}

.dog-card {
  @include transition(all 0.25s ease-out);
  @include border-radius(5px);
  border: 3px solid $silver;
  min-height: 400px;
  background: darken($white, 3%);
  margin-bottom: 2em;
  padding: 5px 20px;
  header {
    color: $gray;
  }
}

.dog-card-description {
  color: $gray;
  font-size: 1.25em;
}

.entered-viewport {
  background: $white;
  border-color: lighten($green, 20%);
  header {
    @include transition(all 0.1s ease-out);
    color: $black;
  }
  &:hover {
    border-color: $green;
  }
}

.ui-calendar {
  width: 200px;
  font-size: 14px;
  background: #fff; }

.ui-calendar-months:after {
  content: "";
  display: table;
  clear: both; }

.ui-calendar-month-container {
  width: 100%;
  float: left;
  margin: 0;
  padding: 0;
  margin-top: 30px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -o-user-select: none;
  -ms-user-select: none;
  user-select: none; }

.ui-calendar-month {
  margin: 0;
  padding: 3px; }

.ui-calendar-month:last-child {
  padding-right: 0; 
}

.ui-calendar-header {
  position: relative;
  line-height: 22px; }
  .ui-calendar-header h1 {
    font-size: 14px;
    text-align: center; }
  .ui-calendar-header button {
    position: absolute;
    top: 0; }

.ui-calendar-prev {
  left: 0; }

.ui-calendar-next {
  right: 0; }

.ui-calendar-today {
  left: 50%;
margin-left: -28px; }

.ui-calendar-slot {
  float: left;
  list-style: none;
  text-align: center;
  line-height: 30px;
  padding: 0;
  margin: 0;
  width: 14.28%;
  height: 30px;
  border: 1px solid #eee;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box; }
  .ui-calendar-slot.is-today {
    background: #edc; }
  .ui-calendar-slot.is-selected {
    background: #cde; }
  .ui-calendar-slot.is-disabled {
    background: #eee;
    color: #999;
    cursor: default; }

.ui-calendar-day {
  background: #fff;
  cursor: pointer; }

.ui-calendar-empty {
  cursor: default;
  background: #eee; }

    p { width: 50%; }


    ul.infinite { list-style-type: none; padding:0; margin:0; }

    .infinite li {
      background-color: $aqua;
      height: 100px;
      line-height: 100px;
      width: 300px;
      text-align: center;
      margin-bottom: 10px;
      border: 2px solid darkgray;
      border-radius: 2px;
      box-shadow: 1px 1px 2px;
    }

    .ember-view {
      -webkit-animation: debug .5s;
    }
    @-webkit-keyframes debug {
      0% {
        background-color: yellow;
      }
      100% {
        background-color: inherit;
      }

button{
      color:black;  
      }
}       
    
            
          
!
            
              /* App
=============================*/
var App = Ember.Application.create({
  LOG_TRANSITIONS: true
}); 

App.Store = DS.Store.extend({
  adapter: DS.FixtureAdapter.create()
});

/* Router
=============================*/

App.Router.map(function() {
  this.route("about", { path: "/about" });
  this.route("inview", { path: "/inview" });
  this.route("calendar", { path: "/calendar" });
  this.route("infinite", { path: "/infinite" });
  this.route("scroll", { path: "/scroll" });
});

/* Routes
=============================*/
App.IndexRoute = Ember.Route.extend({
  model: function() {
    return Ember.Object.create({ name: 'My name' });
  }
});

App.ApplicationRoute = Ember.Route.extend({
  actions: {
    showModal: function(name, model) {
      this.render(name, {
        into: 'application',
        outlet: 'modal',
        model: model
      });
    },
    removeModal: function() {
      this.disconnectOutlet({
        outlet: 'modal',
        parentView: 'application'
      });
    }
  }
});

App.InviewRoute = Ember.Route.extend({
  model: function() {
    return ['Anything You Want Here'];
  }
});

App.CalendarRoute = Em.Route.extend({
  setupController: function(controller) {
    controller.set('emberConfDates', [
      /*moment('2014-03-25'),
      moment('2014-03-26')*/
    ]);
  },
  actions: {
    dateSelected: function(date) {
/*			console.log(this.get('dates'), 'dateSelected');
      $('input[name="dateSelected]').val('date')*/
    }
  }
});

  App.InfiniteRoute = Ember.Route.extend({
    model: function(){
      var items = Em.A([]);
      for (var i = 0; i < 2; i++) {
        items.pushObject({name: ''+i});
      }
      return items;
    },
    actions: {
      getMore: function() {
        var controller = this.get('controller'),
            nextPage = controller.get('page') + 1,
            perPage = controller.get('perPage'),
            items;

        items = this.send('fetchPage', nextPage, perPage);
        
        console.log(items, 'items')

        // add delay to simulate API latency
        Ember.run.later(function(){
          // alert the controller to the new data
          controller.gotMore(items, nextPage);
        }, 1000);
      },
      // load another page's worth of fake widgets
      fetchPage: function(page, perPage) {
        var items = Em.A([]);
        console.log(items, 'fetchPage')
        var firstIndex = (page-1) * perPage;
        var lastIndex  = page * perPage;
        for (var i = firstIndex; i < lastIndex; i++) {
          items.pushObject({name:''+i});
        }
        return items;
      }
    }
  });


/* Models
=============================*/

/* Views
=============================*/

  App.InfiniteView = Ember.View.extend({
    didInsertElement: function(){
      // we want to make sure 'this' inside `didScroll` refers
      // to the IndexView, so we use jquery's `proxy` method to bind it
      $(window).on('scroll', $.proxy(this.didScroll, this));
    },

    willDestroyElement: function(){
      // have to use the same argument to `off` that we did to `on`
      $(window).off('scroll', $.proxy(this.didScroll, this));
    },

    // this is called every time we scroll
    didScroll: function(){
      if (this.isScrolledToBottom()) {
        this.get('controller').send('getMore');
      }
    },

    // we check if we are at the bottom of the page
    isScrolledToBottom: function(){
      var distanceToViewportTop = (
        $(document).height() - $(window).height());
      var viewPortTop = $(document).scrollTop();

      if (viewPortTop === 0) {
        // if we are at the top of the page, don't do
        // the infinite scroll thing
        return false;
      }

      return (viewPortTop - distanceToViewportTop === 0);
    }
  });

/*rerenderObserver:function(){
    this.rerender();
}.observes('controller.content')*/

/* Controllers =============================*/
App.SettingsModalController = Ember.ObjectController.extend({
  actions: {
    save: function() {
      // save to server
      console.log('settings saved');
    }
  }
});

App.LogoutModalController = Ember.Controller.extend({
  actions: {
    logout: function() {
      // logout
      console.log('logout triggered');
    }
  }
});

  App.InfiniteController = Ember.ArrayController.extend({
    // add properties
    page: 1,
    perPage: 2,

    getMore: function() {
      // don't load new data if we already are
      if (this.get('loadingMore')) return;

      this.set('loadingMore', true);

      // pass this action up the chain to the events hash on the route
      this.get('target').send('getMore');
    },

    // Also add a method `gotMore` that the route can call back to
    // notify the controller that the new data is in and it can stop
    // showing its loading indicator
    gotMore: function(items, page) {
      this.set('loadingMore', false);
      this.set('page', page);

      this.pushObjects(items);
    }
  });


/* Components =============================*/
App.MyModalComponent = Ember.Component.extend({
  actions: {
    ok: function() {
      this.$('.modal').modal('hide');
      this.sendAction('ok');
    }
  },
  show: function() {
    this.$('.modal').modal().on('hidden.bs.modal', function() {
      this.sendAction('close');
    }.bind(this));
  }.on('didInsertElement')
});

App.ThisIsDogComponent = Ember.Component.extend(App.InViewportMixin, {
  classNames: ['dog-card'],
  classNameBindings: ['enteredViewport:entered-viewport']
});

App.FormatDateComponent = Em.Component.extend({
  layout: Em.Handlebars.compile('{{formatted}}'),
  date: null,
  format: null,

  formatted: function() {
    var date = this.get('date');
    var format = this.get('format');

    return date ? date.format(format) : null;
  }.property('date', 'format')
});

/* Mixins =============================*/
App.InViewportMixin = Ember.Mixin.create({
  scrollTimeout: 100,
  boundingClientRect: 0,
  windowHeight: 0,
  windowWidth: 0,
  enteredViewport: Em.computed('boundingClientRect', 'windowHeight', 'windowWidth', function() {
    var rect, windowHeight, windowWidth;
    rect = this.get('boundingClientRect');
    windowHeight = this.get('windowHeight');
    windowWidth = this.get('windowWidth');
    console.log(rect, 'rect')
    return (
      rect.top >= 0 && 
      rect.left >= 0 && 
      rect.bottom <= windowHeight && 
      rect.right <= windowWidth
    );
  }),
  exitedViewport: Em.computed.not('enteredViewport'),
  _updateBoundingClientRect: function() {
    var el;
    el = this.$()[0];
    this.set('boundingClientRect', el.getBoundingClientRect());
  },
  _setup: (function() {
    console.log('setup')
    return Em.run.scheduleOnce('afterRender', this, function() {
      this._updateBoundingClientRect();
      this.set('windowHeight', window.innerHeight || document.documentElement.clientHeight);
      this.set('windowWidth', window.innerWidth || document.documentElement.clientWidth);
    });
  }).on('didInsertElement'),
  _scrollHandler: function() {
    return Em.run.debounce(this, '_updateBoundingClientRect', this.get('scrollTimeout'));
  },
  _bindScroll: (function() {
    console.log('scroll')
    var scrollHandler;
    scrollHandler = this._scrollHandler.bind(this);
    Ember.$(document).on('touchmove.scrollable', scrollHandler);
    Ember.$(window).on('scroll.scrollable', scrollHandler);
  }).on('didInsertElement'),
  _unbindScroll: (function() {
    Ember.$(window).off('.scrollable');
    Ember.$(document).off('.scrollable');
  }).on('willDestroyElement')
});


$(function() {
  // Check to see if the window is running in app mode.
  if (("standalone" in window.navigator) && window.navigator.standalone) {
    		$('.navbar-fixed-top').css({
      paddingTop:'12px'
    });
		  }
})


// Cloaked Collection

random_height = function() {
  return Math.round(Math.random() * 100 + 20);
};

model = (function() {
  var _i, _results;
  _results = [];
  for (i = _i = 0; _i <= 500; i = ++_i) {
    _results.push({
      id: i,
      height: random_height()
    });
  }
  return _results;
})();

App.ScrollRoute = Ember.Route.extend({
  model: function() {
    return model;
  },
  actions: {
    greeting: function() {
      return alert('greeting from route');
    }
  }
});

App.ScrollView = Em.View.extend({
  templateName: 'scroll'
});

App.ItemView = Em.View.extend({
  templateName: 'item',
  didInsertElement: function() {
    return this.$().css('height', this.get('context.height'));
  }
});


  /**
    Display a list of cloaked items
    @class CloakedCollectionView
    @extends Ember.CollectionView
    @namespace Ember
  **/
  Ember.CloakedCollectionView = Ember.CollectionView.extend({
    cloakView: Ember.computed.alias('itemViewClass'),
    topVisible: null,
    bottomVisible: null,
    offsetFixedTopElement: null,
    offsetFixedBottomElement: null,
    loadingHTML: 'Loading...',
    scrollDebounce: 10,

    init: function() {
      var cloakView = this.get('cloakView'),
          idProperty = this.get('idProperty'),
          uncloakDefault = !!this.get('uncloakDefault');

      // Set the slack ratio differently to allow for more or less slack in preloading
      var slackRatio = parseFloat(this.get('slackRatio'));
      if (!slackRatio) { this.set('slackRatio', 1.0); }

      this.set('itemViewClass', Ember.CloakedView.extend({
        classNames: [cloakView + '-cloak'],
        cloaks: cloakView,
        preservesContext: this.get('preservesContext') === 'true',
        cloaksController: this.get('itemController'),
        defaultHeight: this.get('defaultHeight'),

        init: function() {
          this._super();

          if (idProperty) {
            this.set('elementId', cloakView + '-cloak-' + this.get('content.' + idProperty));
          }
          if (uncloakDefault) {
            this.uncloak();
          } else {
            this.cloak();
          }
        }
      }));

      this._super();
      Ember.run.next(this, 'scrolled');
    },


    /**
      If the topmost visible view changed, we will notify the controller if it has an appropriate hook.
      @method _topVisibleChanged
      @observes topVisible
    **/
    _topVisibleChanged: function() {
      var controller = this.get('controller');
      if (controller.topVisibleChanged) { controller.topVisibleChanged(this.get('topVisible')); }
    }.observes('topVisible'),

    /**
      If the bottommost visible view changed, we will notify the controller if it has an appropriate hook.
      @method _bottomVisible
      @observes bottomVisible
    **/
    _bottomVisible: function() {
      var controller = this.get('controller');
      if (controller.bottomVisibleChanged) { controller.bottomVisibleChanged(this.get('bottomVisible')); }
    }.observes('bottomVisible'),

    /**
      Binary search for finding the topmost view on screen.
      @method findTopView
      @param {Array} childViews the childViews to search through
      @param {Number} windowTop The top of the viewport to search against
      @param {Number} min The minimum index to search through of the child views
      @param {Number} max The max index to search through of the child views
      @returns {Number} the index into childViews of the topmost view
    **/
    findTopView: function(childViews, viewportTop, min, max) {
      if (max < min) { return min; }

      var wrapperTop = this.get('wrapperTop')>>0;

      while(max>min){
        var mid = Math.floor((min + max) / 2),
            // in case of not full-window scrolling
            $view = childViews[mid].$(),
            viewBottom = $view.position().top + wrapperTop + $view.height();

        if (viewBottom > viewportTop) {
          max = mid-1;
        } else {
          min = mid+1;
        }
      }

      return min;
    },


    /**
      Determine what views are onscreen and cloak/uncloak them as necessary.
      @method scrolled
    **/
    scrolled: function() {
      if (!this.get('scrollingEnabled')) { return; }

      var childViews = this.get('childViews');
      if ((!childViews) || (childViews.length === 0)) { return; }

      var self = this,
          toUncloak = [],
          onscreen = [],
          onscreenCloaks = [],
          // calculating viewport edges
          $w = Ember.$(window),
          windowHeight = this.get('wrapperHeight') || ( window.innerHeight ? window.innerHeight : $w.height() ),
          windowTop = this.get('wrapperTop') || $w.scrollTop(),
          slack = Math.round(windowHeight * this.get('slackRatio')),
          viewportTop = windowTop - slack,
          windowBottom = windowTop + windowHeight,
          viewportBottom = windowBottom + slack,
          topView = this.findTopView(childViews, viewportTop, 0, childViews.length-1),
          bodyHeight = this.get('wrapperHeight') ? this.$().height() : $('body').height(),
          bottomView = topView,
          offsetFixedTopElement = this.get('offsetFixedTopElement'),
          offsetFixedBottomElement = this.get('offsetFixedBottomElement');

      if (windowBottom > bodyHeight) { windowBottom = bodyHeight; }
      if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; }

      if (offsetFixedTopElement) {
        windowTop += (offsetFixedTopElement.outerHeight(true) || 0);
      }

      if (offsetFixedBottomElement) {
        windowBottom -= (offsetFixedBottomElement.outerHeight(true) || 0);
      }

      // Find the bottom view and what's onscreen
      while (bottomView < childViews.length) {
        var view = childViews[bottomView],
          $view = view.$(),
          // in case of not full-window scrolling
          scrollOffset = this.get('wrapperTop') || 0,
          viewTop = $view.offset().top + scrollOffset,
          viewBottom = viewTop + $view.height();

        if (viewTop > viewportBottom) { break; }
        toUncloak.push(view);

        if (viewBottom > windowTop && viewTop <= windowBottom) {
          onscreen.push(view.get('content'));
          onscreenCloaks.push(view);
        }

        bottomView++;
      }
      if (bottomView >= childViews.length) { bottomView = childViews.length - 1; }

      // If our controller has a `sawObjects` method, pass the on screen objects to it.
      var controller = this.get('controller');
      if (onscreen.length) {
        this.setProperties({topVisible: onscreen[0], bottomVisible: onscreen[onscreen.length-1]});
        if (controller && controller.sawObjects) {
          Em.run.schedule('afterRender', function() {
            controller.sawObjects(onscreen);
          });
        }
      } else {
        this.setProperties({topVisible: null, bottomVisible: null});
      }

      var toCloak = childViews.slice(0, topView).concat(childViews.slice(bottomView+1));

      this._uncloak = toUncloak;
      if(this._nextUncloak){
        Em.run.cancel(this._nextUncloak);
        this._nextUncloak = null;
      }

      Em.run.schedule('afterRender', this, function() {
        onscreenCloaks.forEach(function (v) {
          if(v && v.uncloak) {
            v.uncloak();
          }
        });
        toCloak.forEach(function (v) { v.cloak(); });
        if (self._nextUncloak) { Em.run.cancel(self._nextUncloak); }
        self._nextUncloak = Em.run.later(self, self.uncloakQueue,50);
      });

      for (var j=bottomView; j<childViews.length; j++) {
        var checkView = childViews[j];
        if (!checkView._containedView) {
          if (!checkView.get('loading')) {
            checkView.$().html(this.get('loadingHTML'));
          }
          return;
        }
      }
    },

    uncloakQueue: function(){
      var maxPerRun = 3, delay = 50, processed = 0, self = this;

      if(this._uncloak){
        while(processed < maxPerRun && this._uncloak.length>0){
          var view = this._uncloak.shift();
          if(view && view.uncloak && !view._containedView){
            Em.run.schedule('afterRender', view, view.uncloak);
            processed++;
          }
        }
        if(this._uncloak.length === 0){
          this._uncloak = null;
        } else {
          Em.run.schedule('afterRender', self, function(){
            if(self._nextUncloak){
              Em.run.cancel(self._nextUncloak);
            }
            self._nextUncloak = Em.run.next(self, function(){
              if(self._nextUncloak){
                Em.run.cancel(self._nextUncloak);
              }
              self._nextUncloak = Em.run.later(self,self.uncloakQueue,delay);
            });
          });
        }
      }
    },

    scrollTriggered: function() {
      Em.run.scheduleOnce('afterRender', this, 'scrolled');
    },

    _startEvents: function() {
      if (this.get('offsetFixed')) {
        Em.warn("Cloaked-collection's `offsetFixed` is deprecated. Use `offsetFixedTop` instead.");
      }

      var self = this,
          offsetFixedTop = this.get('offsetFixedTop') || this.get('offsetFixed'),
          offsetFixedBottom = this.get('offsetFixedBottom'),
          scrollDebounce = this.get('scrollDebounce'),
          onScrollMethod = function() {
            Ember.run.debounce(self, 'scrollTriggered', scrollDebounce);
          };

      if (offsetFixedTop) {
        this.set('offsetFixedTopElement', Ember.$(offsetFixedTop));
      }

      if (offsetFixedBottom) {
        this.set('offsetFixedBottomElement', Ember.$(offsetFixedBottom));
      }

      Ember.$(document).bind('touchmove.ember-cloak', onScrollMethod);
      Ember.$(window).bind('scroll.ember-cloak', onScrollMethod);
      this.addObserver('wrapperTop', self, onScrollMethod);
      this.addObserver('wrapperHeight', self, onScrollMethod);
      this.addObserver('content.@each', self, onScrollMethod);
      this.scrollTriggered();

      this.set('scrollingEnabled', true);
    }.on('didInsertElement'),

    cleanUp: function() {
      Ember.$(document).unbind('touchmove.ember-cloak');
      Ember.$(window).unbind('scroll.ember-cloak');
      this.set('scrollingEnabled', false);
    },

    _endEvents: function() {
      this.cleanUp();
    }.on('willDestroyElement')
  });


  /**
    A cloaked view is one that removes its content when scrolled off the screen
    @class CloakedView
    @extends Ember.View
    @namespace Ember
  **/
  Ember.CloakedView = Ember.View.extend({
    attributeBindings: ['style'],
    _containedView: null,
    _scheduled: null,

    init: function() {
      this._super();
      this._scheduled = false;
      this._childViews = [];
    },

    setContainedView: function(cv) {
      if (this._childViews[0]) {
        this._childViews[0].destroy();
        this._childViews[0] = cv;
      }

      if (cv) {
        cv.set('_parentView', this);
        cv.set('templateData', this.get('templateData'));
        this._childViews[0] = cv;
      } else {
        this._childViews.clear();
      }

      if (this._scheduled) return;
      this._scheduled = true;
      this.set('_containedView', cv);
      Ember.run.schedule('render', this, this.updateChildView);
    },

    render: function (buffer) {
      var el = buffer.element();
      this._childViewsMorph = buffer.dom.createMorph(el, null, null, el);
    },

    updateChildView: function () {
      this._scheduled = false;
      if (!this._elementCreated || this.isDestroying || this.isDestroyed) { return; }

      var childView = this._containedView;
      if (childView && !childView._elementCreated) {
        this._renderer.renderTree(childView, this, 0);
      }
    },

    /**
      Triggers the set up for rendering a view that is cloaked.
      @method uncloak
    */
    uncloak: function() {
      var state = this._state || this.state;
      if (state !== 'inDOM' && state !== 'preRender') { return; }

      if (!this._containedView) {
        var model = this.get('content'),
            controller = null,
            container = this.get('container');

        // Wire up the itemController if necessary
        var controllerName = this.get('cloaksController');
        if (controllerName) {
          var controllerFullName = 'controller:' + controllerName,
              factory = container.lookupFactory(controllerFullName),
              parentController = this.get('controller');

          // let ember generate controller if needed
          if (factory === undefined) {
            factory = Ember.generateControllerFactory(container, controllerName, model);

            // inform developer about typo
            Ember.Logger.warn('ember-cloaking: can\'t lookup controller by name "' + controllerFullName + '".');
            Ember.Logger.warn('ember-cloaking: using ' + factory.toString() + '.');
          }

          controller = factory.create({
            model: model,
            parentController: parentController,
            target: parentController
          });
        }

        var createArgs = {},
            target = controller || model;

        if (this.get('preservesContext')) {
          createArgs.content = target;
        } else {
          createArgs.context = target;
        }
        if (controller) { createArgs.controller = controller; }
        this.setProperties({
          style: null,
          loading: false
        });

        this.setContainedView(this.createChildView(this.get('cloaks'), createArgs));
      }
    },

    /**
      Removes the view from the DOM and tears down all observers.
      @method cloak
    */
    cloak: function() {
      var self = this;

      if (this._containedView && (this._state || this.state) === 'inDOM') {
        var style = 'height: ' + this.$().height() + 'px;';
        this.set('style', style);
        this.$().prop('style', style);


        // We need to remove the container after the height of the element has taken
        // effect.
        Ember.run.schedule('afterRender', function() {
          self.setContainedView(null);
        });
      }
    },

    _setHeights: function(){
      if (!this._containedView) {
        // setting default height
        // but do not touch if height already defined
        if(!this.$().height()){
          var defaultHeight = 100;
          if(this.get('defaultHeight')) {
            defaultHeight = this.get('defaultHeight');
          }

          this.$().css('height', defaultHeight);
        }
      }
     }.on('didInsertElement')
  });

  Ember.Handlebars.registerHelper('cloaked-collection', function(options) {
    var hash = options.hash,
        types = options.hashTypes;

    for (var prop in hash) {
      if (types[prop] === 'ID') {
        hash[prop + 'Binding'] = hash[prop];
        delete hash[prop];
      }
    }
    return Ember.Handlebars.helpers.view.call(this, Ember.CloakedCollectionView, options);
  });
            
          
!
999px
Loading ..................

Console