Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro">
    <link rel="stylesheet" href="https://gist.githack.com/christopherjbaker/58dde856b6e7a9f549db959a6360da7f/raw/f2a8796cd37e920a09089a520e050252b6b9614d/todomvc.css">
    <meta charset="utf-8">
    <title>JS Bin</title>
  </head>
  <body>
    <div class="intro">
      <p>Run the test below to see how DoneJS' view engine is faster than React's when rendering large data sets.</p>
    </div>
    <div class="runTest">
      <button onclick="runTests()">Run Test</button>
      <em>This can take up to a minute to complete</em>
    </div>
    <div style="display: none;" class="spinner">
      <div class="rect1"></div>
      <div class="rect2"></div>
      <div class="rect3"></div>
      <div class="rect4"></div>
    </div>
    <p style="display: none;" class="status">React: Adding 1000 todos</p>
    <div style="display: none;" id="testResults">
      <h2>Results <em>(smaller is faster)</em></h2>
      <p>As more todos are rendered the DOM diff React perform becomes larger and slower while DoneJS' minimal DOM updates remain fast.</p>
      <div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
    </div>
    <h2>React</h2>
    <!--React-->
    <div class="todo-wrapper">
      <section class="todoapp"></section>
      <script src="https://gist.githack.com/christopherjbaker/58dde856b6e7a9f549db959a6360da7f/raw/f2a8796cd37e920a09089a520e050252b6b9614d/react-todomvc.js"></script>
    </div>
    <h2>DoneJS</h2>
    <!--CanJS-->
    <div class="todo-wrapper">
      <section id="todoapp" class="todoapp"></section>
      <script src="https://gist.githack.com/christopherjbaker/58dde856b6e7a9f549db959a6360da7f/raw/da208188041349ca1dcd8b4bc45c7ea58958de44/donejs-todomvc.js"></script>
                <script type="text/stache" id="app-template">
                <todo-app>
                    <header id="header">
                        <h1>todos</h1>
                        <input class="new-todo" placeholder="What needs to be done?" can-enter="createTodo">
                    </header>
                    <section class="main {{^if todos.length}}hidden{{/if}}">
                        <input class="toggle-all" type="checkbox" {{#if todos.allComplete}}checked="checked" {{/if}} can-click="toggleAll">
                        <label for="toggle-all">Mark all as complete</label>
                        <ul class="todo-list">
                            {{#each displayList}}
                                <li class="todo{{#if complete}} completed{{/if}}{{#if editing}} editing{{/if}}">
                                    <div class="view">
                                        <input class="toggle" type="checkbox" can-value="complete">
                                        <label can-dblclick="edit">{{text}}</label>
                                        <button class="destroy" can-click="destroy"></button>
                                    </div>
                                    <input class="edit" type="text" value="{{text}}" can-blur="updateTodo" can-keyup="cancelEditing" can-enter="updateTodo">
                                </li>
                            {{/each}}
                        </ul>
                    </section>
                    <footer class="footer {{^if todos.length}}hidden{{/if}}">
                        <span class="todo-count">
                            <strong>{{todos.remaining}}</strong> {{plural "item" todos.remaining}} left
                        </span>
                        <ul class="filters">
                            <li>{{{link "All" undefined}}}</li>
                            <li>{{{link "Active" "active"}}}</li>
                            <li>{{{link "Completed" "completed"}}}</li>
                        </ul>
                        <button class="clear-completed {{^if todos.completed.length}}hidden{{/if}}" can-click="clearCompleted">
                            Clear completed
                        </button>
                    </footer>
                </todo-app>
            </script>
    </div>
    </div>
  <script src="https://code.highcharts.com/highcharts.js"></script>
  <script src="https://code.highcharts.com/modules/exporting.js"></script>
  </body>
</html>
 
body {
  font-family: "Lato", sans-serif;
  background: #FCFEFD;
  padding: 5px;
}
.intro {
  font-size: 16px;
  line-height: 24px;
  font-weight: 400;
  color: #424a4e;
}
#testResults p {
  font-family: "Lato", sans-serif;
  font-size: 16px;
  color: #424a4e;
  font-weight: 400;
}
.status {
  color: #424a4e;
  font-weight: bold;
  text-align: center;
}
.runTest button {
  cursor: pointer;
  width: 100%;
    color: #fff; 
    height: 35px;
    padding: 5px;
    display: block;
    margin: 0 auto;
      line-height: 1.5em;
  background: #3B83A3;
      font-weight: 700;
  font-size: 14px;
}
.todo-wrapper {
  border:1px solid #eee;
}
/* http://tobiasahlin.com/spinkit/ */
.spinner {
  margin: 10px auto;
  width: 50px;
  height: 40px;
  text-align: center;
  font-size: 10px;
}
.spinner > div {
  background-color: #424a4e;
  height: 100%;
  width: 6px;
  display: inline-block;
  
  -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
  animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
  -webkit-animation-delay: -1.1s;
  animation-delay: -1.1s;
}
.spinner .rect3 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}
.spinner .rect4 {
  -webkit-animation-delay: -0.9s;
  animation-delay: -0.9s;
}
.spinner .rect5 {
  -webkit-animation-delay: -0.8s;
  animation-delay: -0.8s;
}
@-webkit-keyframes sk-stretchdelay {
  0%, 40%, 100% { -webkit-transform: scaleY(0.4) }  
  20% { -webkit-transform: scaleY(1.0) }
}
@keyframes sk-stretchdelay {
  0%, 40%, 100% { 
    transform: scaleY(0.4);
    -webkit-transform: scaleY(0.4);
  }  20% { 
    transform: scaleY(1.0);
    -webkit-transform: scaleY(1.0);
  }
}
 
var todos = [10,20,30,40,50,60,70,80,90,100,120,140,160,180,200,250,300,350,400,450,500,750,1000];
var button = $('.runTest');
var testResults = $('#testResults');
var statusText = $('.status');
var testRunning = $('.spinner');
window.testSetup = function(cb){
  button.hide();
  testResults.hide();
  testRunning.show();
  statusText.text('').show();
  setTimeout(cb, 10);
};
window.testTeardown = function(results){
  window.resetCanTodos();
  window.resetReactTodos();
  button.show();
  testResults.show();
  testRunning.hide();
  statusText.hide();
  $('#container').highcharts({
    title: {
      text: 'Rendering Todo Items'
    },
    xAxis: {
      categories: todos,
      title: {
        text: 'Todos Added'
      }
    },
    yAxis: {
      title: {
        text: 'Render Time (ms)'
      },
      plotLines: [{
        value: 0,
        width: 1,
        color: '#808080'
      }]
    },
    legend: {
      layout: 'vertical',
      align: 'right',
      verticalAlign: 'middle',
      borderWidth: 0
    },
    series: [{
      name: 'CanJS 3.5.1',
      data: results.can
    }, {
      name: 'React v15.4.2',
      data: results.react
    }]
  });
};
window.runTests = function(){
  var results = {
    can: [],
    react: []
  };
  window.testSetup(function(){
    var limit = 2*todos.length;
    var resolved = 0;
    ['can', 'react'].forEach(function(library){
      var ucase = library.charAt(0).toUpperCase() + library.slice(1);
      var i = 0;
      var n;
      function go(){
        n = todos[i];
        window['reset' + ucase + 'Todos']();
        var test = window['add' + ucase + 'Todos'](n);
        test.then(function(r){
          results[library].push(r);
          resolved++;
          i++;
          if(i < todos.length) {
            go();
          }
          if(resolved === limit){
            window.testTeardown(results);
          }
        });
      }
      go();
    });
  });
};
var oldCanAdd = window.addCanTodos;
window.addCanTodos = function(n){
  statusText.text('DoneJS: Adding ' + n + ' todos');
  return new Promise(function(resolve) {
    setTimeout(function(){
      resolve(oldCanAdd(n));
    }, 100);
  });
};
var oldReactAdd = window.addReactTodos;
window.addReactTodos = function(n){
  statusText.text('React: Adding ' + n + ' todos');
  return new Promise(function(resolve) {
    setTimeout(function(){
      resolve(oldReactAdd(n));
    }, 100);
  });
};
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
christopherjbakerpro
0viewers